Browse Source

Data: Matlab: introduce MatlabMatrix type, refactoring

provider
Christoph Ruegg 12 years ago
parent
commit
d33397d25c
  1. 1
      src/Data/Matlab/Matlab.csproj
  2. 6
      src/Data/Matlab/MatlabFile.cs
  3. 59
      src/Data/Matlab/MatlabMatrix.cs
  4. 14
      src/Data/Matlab/MatlabReader.cs
  5. 84
      src/Data/Matlab/Parser.cs

1
src/Data/Matlab/Matlab.csproj

@ -51,6 +51,7 @@
<Compile Include="Adler32.cs" />
<Compile Include="ArrayClass.cs" />
<Compile Include="ArrayFlags.cs" />
<Compile Include="MatlabMatrix.cs" />
<Compile Include="SparseArrayReader.cs" />
<Compile Include="NumericArrayReader.cs" />
<Compile Include="DataType.cs" />

6
src/Data/Matlab/MatlabFile.cs

@ -42,7 +42,7 @@ namespace MathNet.Numerics.Data.Matlab
/// <summary>
/// Matrices in a MATLAB file stored as 1-D arrays
/// </summary>
readonly IDictionary<string, byte[]> _matrices = new SortedList<string, byte[]>();
readonly IDictionary<string, MatlabMatrix> _matrices = new SortedList<string, MatlabMatrix>();
/// <summary>
/// Gets or sets the header text.
@ -61,7 +61,7 @@ namespace MathNet.Numerics.Data.Matlab
get { return _matrices.Keys; }
}
internal void Add(string name, byte[] data)
internal void Add(string name, MatlabMatrix data)
{
if (FirstMatrixName == null)
{
@ -73,7 +73,7 @@ namespace MathNet.Numerics.Data.Matlab
internal Matrix<TDataType> ReadMatrix<TDataType>(string name) where TDataType : struct, IEquatable<TDataType>, IFormattable
{
return Parser<TDataType>.ReadMatrix(_matrices[name]);
return _matrices[name].Read<TDataType>();
}
}
}

59
src/Data/Matlab/MatlabMatrix.cs

@ -0,0 +1,59 @@
// <copyright file="MatlabMatrix.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// 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
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Data.Matlab
{
public class MatlabMatrix
{
byte[] _data;
public string Name { get; private set; }
public int Size { get; private set; }
public int Dimensions { get; private set; }
internal MatlabMatrix(string name, int size, int dimensions, byte[] data)
{
_data = data;
Name = name;
Size = size;
Dimensions = dimensions;
}
internal Matrix<TDataType> Read<TDataType>()
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
return Parser<TDataType>.ReadMatrixBlock(_data);
}
}
}

14
src/Data/Matlab/MatlabReader.cs

@ -47,19 +47,20 @@ namespace MathNet.Numerics.Data.Matlab
{
var names = string.IsNullOrEmpty(matrixName) ? new string[] { } : new[] { matrixName };
var parser = new Parser<TDataType>(stream, names);
var file = parser.Parse();
var file = parser.ParseAll();
if (string.IsNullOrEmpty(matrixName))
{
return file.ReadMatrix<TDataType>(file.FirstMatrixName);
return file.First().Read<TDataType>();
}
if (!file.MatrixNames.Contains(matrixName))
var matrix = file.Find(m => m.Name == matrixName);
if (matrix == null)
{
throw new KeyNotFoundException("Matrix with the provided name was not found.");
}
return file.ReadMatrix<TDataType>(matrixName);
return matrix.Read<TDataType>();
}
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: double, float, Complex, or Complex32.</typeparam>
@ -76,9 +77,10 @@ namespace MathNet.Numerics.Data.Matlab
public static Dictionary<string, Matrix<TDataType>> ReadMatrices<TDataType>(Stream stream, params string[] matrixNames)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
var names = new HashSet<string>(matrixNames);
var parser = new Parser<TDataType>(stream, matrixNames);
var file = parser.Parse();
return file.MatrixNames.ToDictionary(name => name, file.ReadMatrix<TDataType>);
var file = parser.ParseAll();
return file.Where(m => names.Count == 0 || names.Contains(m.Name)).ToDictionary(m => m.Name, m => m.Read<TDataType>());
}
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: double, float, Complex, or Complex32.</typeparam>

84
src/Data/Matlab/Parser.cs

@ -133,20 +133,15 @@ namespace MathNet.Numerics.Data.Matlab
}
/// <summary>
/// Parses the file.
/// Extracts all matrix blocks in a format we support.
/// </summary>
/// <returns>The parsed MATLAB file as a <see cref="MatlabFile{TDataType}"/> object.</returns>
internal MatlabFile Parse()
internal List<MatlabMatrix> ParseAll()
{
var file = new MatlabFile();
var matrices = new List<MatlabMatrix>();
using (var reader = new BinaryReader(_stream))
{
file.HeaderText = Encoding.ASCII.GetString(reader.ReadBytes(116));
// skipping subsystem offsets
reader.BaseStream.Position = 126;
if (reader.ReadByte() != LittleEndianIndicator)
{
throw new NotSupportedException(Resources.BigEndianNotSupported);
@ -182,16 +177,32 @@ namespace MathNet.Numerics.Data.Matlab
if (type == DataType.Matrix)
{
AddMatrix(data, file);
}
else
{
throw new NotSupportedException(string.Format(Resources.NotSupportedType, type));
using (var matrixStream = new MemoryStream(data))
using (var matrixReader = new BinaryReader(matrixStream))
{
matrixReader.BaseStream.Seek(20, SeekOrigin.Current);
var matrixDim = matrixReader.ReadInt32()/8;
if (matrixDim > 2)
{
continue;
}
matrixReader.BaseStream.Seek(10, SeekOrigin.Current);
int matrixSize = matrixReader.ReadInt16();
if (matrixSize == 0)
{
matrixSize = matrixReader.ReadInt32();
}
var matrixName = Encoding.ASCII.GetString(matrixReader.ReadBytes(matrixSize));
matrices.Add(new MatlabMatrix(matrixName, matrixSize, matrixDim, data));
}
}
}
}
return file;
return matrices;
}
/// <summary>
@ -240,45 +251,7 @@ namespace MathNet.Numerics.Data.Matlab
return data;
}
/// <summary>
/// Adds a matrix from the actual file into our presentation of a MATLAB file.
/// </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 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)
internal static Matrix<TDataType> ReadMatrixBlock(byte[] data)
{
using (var stream = new MemoryStream(data))
using (var reader = new BinaryReader(stream))
@ -302,7 +275,7 @@ namespace MathNet.Numerics.Data.Matlab
var rows = reader.ReadInt32();
var columns = reader.ReadInt32();
// skip unneeded bytes
// skip name and unneeded bytes
reader.BaseStream.Seek(2, SeekOrigin.Current);
int size = reader.ReadInt16();
var smallBlock = true;
@ -311,8 +284,7 @@ namespace MathNet.Numerics.Data.Matlab
size = reader.ReadInt32();
smallBlock = false;
}
var name = Encoding.ASCII.GetString(reader.ReadBytes(size));
reader.BaseStream.Seek(size, SeekOrigin.Current);
AlignData(reader.BaseStream, size, smallBlock);
var type = (DataType)reader.ReadInt16();

Loading…
Cancel
Save