com.meliorbis.numerics.io.matlab.MatlabReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Numerics Show documentation
Show all versions of Numerics Show documentation
A library for working with large multi-dimensional arrays and the functions they represent
package com.meliorbis.numerics.io.matlab;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.jmatio.io.MatFileReader;
import com.jmatio.types.MLArray;
import com.jmatio.types.MLNumericArray;
import com.jmatio.types.MLStructure;
import com.meliorbis.numerics.DoubleArrayFactories;
import com.meliorbis.numerics.IntArrayFactories;
import com.meliorbis.numerics.generic.MultiDimensionalArray;
import com.meliorbis.numerics.generic.SettableIndexedIterator;
import com.meliorbis.numerics.generic.primitives.DoubleSettableIndexedIterator;
import com.meliorbis.utils.Utils;
/**
* This class provides an API for reading from MATLAB files and returning Numerics arrays
*
* @author Tobias Grasl
*/
public class MatlabReader implements com.meliorbis.numerics.io.NumericsReader
{
private final File _file;
private Map _arrays;
/**
* @param file_ The file to read from
*/
public MatlabReader(File file_)
{
_file = file_;
}
/**
* @param path_ The path to the file to read from
*/
public MatlabReader(String path_)
{
this(new File(path_));
}
/**
* Returns the named array
*
* @param name_ The name of the array to return
*
* @param The type of the array to return. Note this must coincide with the actual type in MatLab, therefore
* the type must be known in advance
*
* @return The array requested, or null if no such array has been read
*/
@SuppressWarnings("unchecked")
@Override
public MultiDimensionalArray getArray(String name_) throws IOException
{
// Throw an exception if no data has been read
checkRead();
final MLArray mlArray = _arrays.get(name_);
if(mlArray == null)
{
return null;
}
return toNumericsArray((MLNumericArray) mlArray);
}
private void checkRead() throws IOException
{
if(_arrays == null)
{
final MatFileReader matFileReader = new MatFileReader();
_arrays = matFileReader.read(_file);
}
}
/**
* @return all arrays in the matlab file that was read, mapped by name
*/
@SuppressWarnings("unchecked")
@Override
public Map> getArrays() throws IOException
{
// Throw an exception if no data has been read
checkRead();
Map> results =
new HashMap>();
// Convert each array and set it in the result map
for(Map.Entry entry : _arrays.entrySet())
{
results.put(entry.getKey(),toNumericsArray((MLNumericArray extends Number>) entry.getValue()));
}
return results;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private MultiDimensionalArray toNumericsArray(MLNumericArray mlArray_)
{
MultiDimensionalArray result;
final int[] dimensions = mlArray_.getDimensions();
if(mlArray_.isDouble())
{
result = (MultiDimensionalArray) DoubleArrayFactories.createArrayOfSize(dimensions);
// Need to rearrange dimensions to account for different linear indexing in ML and numerics
final DoubleSettableIndexedIterator targetIter =
(DoubleSettableIndexedIterator) result.arrangeDimensions(Utils.sequence(dimensions.length - 1, -1)).iterator();
int index = 0;
// Iterate over the target array, incrementing the ML array counter as we go along, and copy each value
while(targetIter.hasNext())
{
targetIter.nextDouble();
targetIter.set(((Double)mlArray_.get(index++)).doubleValue());
}
}
// Note the 64-bitness might bite us
else if(mlArray_.isInt64()||mlArray_.isInt32()||mlArray_.isInt16())
{
result = (MultiDimensionalArray) IntArrayFactories.createIntArrayOfSize(dimensions);
// Need to rearrange dimensions to account for different linear indexing in ML and numerics
final SettableIndexedIterator targetIter =
result.arrangeDimensions(Utils.sequence(dimensions.length - 1, -1)).iterator();
int index = 0;
// Iterate over the target array, incrementing the ML array counter as we go along, and copy each value
while(targetIter.hasNext())
{
targetIter.next();
targetIter.set(mlArray_.get(index++));
}
}
else
{
throw new UnsupportedOperationException("Only double and int supported");
}
return result;
}
@SuppressWarnings("unchecked")
@Override
public Map> getStruct(String name_) throws IOException
{
checkRead();
final MLArray structure = _arrays.get(name_);
if(!(structure instanceof MLStructure))
{
throw new IllegalStateException("The named array is not a structure");
}
Map> results =
new HashMap>();
// Convert each array and set it in the result map
for(String fieldName : ((MLStructure) structure).getFieldNames())
{
results.put(fieldName,toNumericsArray((MLNumericArray extends Number>) ((MLStructure) structure).getField(fieldName)));
}
return results;
}
}