Browse Source

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

provider
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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -37,13 +37,12 @@ namespace MathNet.Numerics.Data.Matlab
/// <summary> /// <summary>
/// Represents a MATLAB file /// Represents a MATLAB file
/// </summary> /// </summary>
/// <typeparam name="TDataType">The data type of the matrix to return.</typeparam> internal class MatlabFile
internal class MatlabFile<TDataType> where TDataType : struct, IEquatable<TDataType>, IFormattable
{ {
/// <summary> /// <summary>
/// Matrices in a MATLAB file stored as 1-D arrays /// Matrices in a MATLAB file stored as 1-D arrays
/// </summary> /// </summary>
readonly IDictionary<string, Matrix<TDataType>> _matrices = new SortedList<string, Matrix<TDataType>>(); readonly IDictionary<string, byte[]> _matrices = new SortedList<string, byte[]>();
/// <summary> /// <summary>
/// Gets or sets the header text. /// Gets or sets the header text.
@ -55,32 +54,26 @@ namespace MathNet.Numerics.Data.Matlab
/// Gets or sets the first name of the matrix. /// Gets or sets the first name of the matrix.
/// </summary> /// </summary>
/// <value>The first name of the matrix.</value> /// <value>The first name of the matrix.</value>
internal string FirstMatrixName { get; set; } internal string FirstMatrixName { get; private set; }
/// <summary> internal ICollection<string> MatrixNames
/// Gets the first matrix.
/// </summary>
/// <value>The first matrix.</value>
internal Matrix<TDataType> FirstMatrix
{ {
get get { return _matrices.Keys; }
{ }
if (string.IsNullOrEmpty(FirstMatrixName) || !_matrices.ContainsKey(FirstMatrixName))
{
return null;
}
return _matrices[FirstMatrixName]; internal void Add(string name, byte[] data)
{
if (FirstMatrixName == null)
{
FirstMatrixName = name;
} }
_matrices.Add(name, data);
} }
/// <summary> internal Matrix<TDataType> ReadMatrix<TDataType>(string name) where TDataType : struct, IEquatable<TDataType>, IFormattable
/// Gets the matrices.
/// </summary>
/// <value>The matrices.</value>
internal IDictionary<string, Matrix<TDataType>> Matrices
{ {
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)) 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."); 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> /// <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 parser = new Parser<TDataType>(stream, matrixNames);
var file = parser.Parse(); 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> /// <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. /// Parses the file.
/// </summary> /// </summary>
/// <returns>The parsed MATLAB file as a <see cref="MatlabFile{TDataType}"/> object.</returns> /// <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)) using (var reader = new BinaryReader(_stream))
{ {
@ -245,10 +245,43 @@ namespace MathNet.Numerics.Data.Matlab
/// </summary> /// </summary>
/// <param name="data">The data of the matrix.</param> /// <param name="data">The data of the matrix.</param>
/// <param name="file">The <see cref="MatlabFile{TDataType}"/> instance.</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 ms = new MemoryStream(data))
using (var reader = new BinaryReader(ms)) 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 // skip tag - doesn't tell us anything we don't already know
reader.BaseStream.Seek(8, SeekOrigin.Current); reader.BaseStream.Seek(8, SeekOrigin.Current);
@ -282,12 +315,6 @@ namespace MathNet.Numerics.Data.Matlab
var name = Encoding.ASCII.GetString(reader.ReadBytes(size)); var name = Encoding.ASCII.GetString(reader.ReadBytes(size));
AlignData(reader.BaseStream, size, smallBlock); AlignData(reader.BaseStream, size, smallBlock);
// only grab wanted objects
if (_names.Count != 0 && !_names.Contains(name))
{
return;
}
var type = (DataType)reader.ReadInt16(); var type = (DataType)reader.ReadInt16();
size = reader.ReadInt16(); size = reader.ReadInt16();
if (size == 0) if (size == 0)
@ -313,11 +340,7 @@ namespace MathNet.Numerics.Data.Matlab
break; break;
} }
file.Matrices.Add(name, matrix); return matrix;
if (file.FirstMatrixName == null)
{
file.FirstMatrixName = name;
}
} }
} }
} }

Loading…
Cancel
Save