Browse Source

Data: Matlab: delayed deserialization, allow matrix file to contain matrices of multiple types

pull/248/head
Christoph Ruegg 12 years ago
parent
commit
07cd162e57
  1. 39
      src/Data/Matlab/MatlabFile.cs
  2. 8
      src/Data/Matlab/MatlabReader.cs
  3. 51
      src/Data/Matlab/Parser.cs

39
src/Data/Matlab/MatlabFile.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -37,13 +37,12 @@ namespace MathNet.Numerics.Data.Matlab
/// <summary>
/// Represents a MATLAB file
/// </summary>
/// <typeparam name="TDataType">The data type of the matrix to return.</typeparam>
internal class MatlabFile<TDataType> where TDataType : struct, IEquatable<TDataType>, IFormattable
internal class MatlabFile
{
/// <summary>
/// Matrices in a MATLAB file stored as 1-D arrays
/// </summary>
readonly IDictionary<string, Matrix<TDataType>> _matrices = new SortedList<string, Matrix<TDataType>>();
readonly IDictionary<string, byte[]> _matrices = new SortedList<string, byte[]>();
/// <summary>
/// Gets or sets the header text.
@ -55,32 +54,26 @@ namespace MathNet.Numerics.Data.Matlab
/// Gets or sets the first name of the matrix.
/// </summary>
/// <value>The first name of the matrix.</value>
internal string FirstMatrixName { get; set; }
internal string FirstMatrixName { get; private set; }
/// <summary>
/// Gets the first matrix.
/// </summary>
/// <value>The first matrix.</value>
internal Matrix<TDataType> FirstMatrix
internal ICollection<string> MatrixNames
{
get
{
if (string.IsNullOrEmpty(FirstMatrixName) || !_matrices.ContainsKey(FirstMatrixName))
{
return null;
}
get { return _matrices.Keys; }
}
return _matrices[FirstMatrixName];
internal void Add(string name, byte[] data)
{
if (FirstMatrixName == null)
{
FirstMatrixName = name;
}
_matrices.Add(name, data);
}
/// <summary>
/// Gets the matrices.
/// </summary>
/// <value>The matrices.</value>
internal IDictionary<string, Matrix<TDataType>> Matrices
internal Matrix<TDataType> ReadMatrix<TDataType>(string name) where TDataType : struct, IEquatable<TDataType>, IFormattable
{
get { return _matrices; }
return Parser<TDataType>.ReadMatrix(_matrices[name]);
}
}
}

8
src/Data/Matlab/MatlabReader.cs

@ -51,15 +51,15 @@ namespace MathNet.Numerics.Data.Matlab
if (string.IsNullOrEmpty(matrixName))
{
return file.FirstMatrix;
return file.ReadMatrix<TDataType>(file.FirstMatrixName);
}
if (!file.Matrices.ContainsKey(matrixName))
if (!file.MatrixNames.Contains(matrixName))
{
throw new KeyNotFoundException("Matrix with the provided name was not found.");
}
return file.Matrices[matrixName];
return file.ReadMatrix<TDataType>(matrixName);
}
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: double, float, Complex, or Complex32.</typeparam>
@ -78,7 +78,7 @@ namespace MathNet.Numerics.Data.Matlab
{
var parser = new Parser<TDataType>(stream, matrixNames);
var file = parser.Parse();
return file.Matrices.ToDictionary(matrix => matrix.Key, matrix => matrix.Value);
return file.MatrixNames.ToDictionary(name => name, file.ReadMatrix<TDataType>);
}
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: double, float, Complex, or Complex32.</typeparam>

51
src/Data/Matlab/Parser.cs

@ -136,9 +136,9 @@ namespace MathNet.Numerics.Data.Matlab
/// Parses the file.
/// </summary>
/// <returns>The parsed MATLAB file as a <see cref="MatlabFile{TDataType}"/> object.</returns>
internal MatlabFile<TDataType> Parse()
internal MatlabFile Parse()
{
var file = new MatlabFile<TDataType>();
var file = new MatlabFile();
using (var reader = new BinaryReader(_stream))
{
@ -245,10 +245,43 @@ namespace MathNet.Numerics.Data.Matlab
/// </summary>
/// <param name="data">The data of the matrix.</param>
/// <param name="file">The <see cref="MatlabFile{TDataType}"/> instance.</param>
void AddMatrix(byte[] data, MatlabFile<TDataType> file)
void AddMatrix(byte[] data, MatlabFile file)
{
using (var ms = new MemoryStream(data))
using (var reader = new BinaryReader(ms))
{
// skip unneeded bytes
reader.BaseStream.Seek(20, SeekOrigin.Current);
var numDimensions = reader.ReadInt32()/8;
if (numDimensions > 2)
{
throw new NotSupportedException(Resources.MoreThan2D);
}
// skip unneeded bytes
reader.BaseStream.Seek(10, SeekOrigin.Current);
int size = reader.ReadInt16();
if (size == 0)
{
size = reader.ReadInt32();
}
var name = Encoding.ASCII.GetString(reader.ReadBytes(size));
// only grab wanted objects
if (_names.Count == 0 || _names.Contains(name))
{
file.Add(name, data);
}
}
}
internal static Matrix<TDataType> ReadMatrix(byte[] data)
{
using (var stream = new MemoryStream(data))
using (var reader = new BinaryReader(stream))
{
// skip tag - doesn't tell us anything we don't already know
reader.BaseStream.Seek(8, SeekOrigin.Current);
@ -282,12 +315,6 @@ namespace MathNet.Numerics.Data.Matlab
var name = Encoding.ASCII.GetString(reader.ReadBytes(size));
AlignData(reader.BaseStream, size, smallBlock);
// only grab wanted objects
if (_names.Count != 0 && !_names.Contains(name))
{
return;
}
var type = (DataType)reader.ReadInt16();
size = reader.ReadInt16();
if (size == 0)
@ -313,11 +340,7 @@ namespace MathNet.Numerics.Data.Matlab
break;
}
file.Matrices.Add(name, matrix);
if (file.FirstMatrixName == null)
{
file.FirstMatrixName = name;
}
return matrix;
}
}
}

Loading…
Cancel
Save