Browse Source

Data: Matlab: static parser design, refactoring

provider
Christoph Ruegg 12 years ago
parent
commit
7be849100f
  1. 1
      src/Data/Matlab/Matlab.csproj
  2. 79
      src/Data/Matlab/MatlabFile.cs
  3. 2
      src/Data/Matlab/MatlabMatrix.cs
  4. 15
      src/Data/Matlab/MatlabReader.cs
  5. 85
      src/Data/Matlab/Parser.cs
  6. 4
      src/Data/Matlab/SparseArrayReader.cs

1
src/Data/Matlab/Matlab.csproj

@ -55,7 +55,6 @@
<Compile Include="SparseArrayReader.cs" /> <Compile Include="SparseArrayReader.cs" />
<Compile Include="NumericArrayReader.cs" /> <Compile Include="NumericArrayReader.cs" />
<Compile Include="DataType.cs" /> <Compile Include="DataType.cs" />
<Compile Include="MatlabFile.cs" />
<Compile Include="Parser.cs" /> <Compile Include="Parser.cs" />
<Compile Include="MatlabReader.cs" /> <Compile Include="MatlabReader.cs" />
<Compile Include="MatlabWriter.cs" /> <Compile Include="MatlabWriter.cs" />

79
src/Data/Matlab/MatlabFile.cs

@ -1,79 +0,0 @@
// <copyright file="MatlabFile.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 System.Collections.Generic;
using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Data.Matlab
{
/// <summary>
/// Represents a MATLAB file
/// </summary>
internal class MatlabFile
{
/// <summary>
/// Matrices in a MATLAB file stored as 1-D arrays
/// </summary>
readonly IDictionary<string, MatlabMatrix> _matrices = new SortedList<string, MatlabMatrix>();
/// <summary>
/// Gets or sets the header text.
/// </summary>
/// <value>The header text.</value>
internal string HeaderText { get; set; }
/// <summary>
/// Gets or sets the first name of the matrix.
/// </summary>
/// <value>The first name of the matrix.</value>
internal string FirstMatrixName { get; private set; }
internal ICollection<string> MatrixNames
{
get { return _matrices.Keys; }
}
internal void Add(string name, MatlabMatrix data)
{
if (FirstMatrixName == null)
{
FirstMatrixName = name;
}
_matrices.Add(name, data);
}
internal Matrix<TDataType> ReadMatrix<TDataType>(string name) where TDataType : struct, IEquatable<TDataType>, IFormattable
{
return _matrices[name].Read<TDataType>();
}
}
}

2
src/Data/Matlab/MatlabMatrix.cs

@ -53,7 +53,7 @@ namespace MathNet.Numerics.Data.Matlab
internal Matrix<TDataType> Read<TDataType>() internal Matrix<TDataType> Read<TDataType>()
where TDataType : struct, IEquatable<TDataType>, IFormattable where TDataType : struct, IEquatable<TDataType>, IFormattable
{ {
return Parser<TDataType>.ReadMatrixBlock(_data); return Parser.ReadMatrixBlock<TDataType>(_data);
} }
} }
} }

15
src/Data/Matlab/MatlabReader.cs

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

85
src/Data/Matlab/Parser.cs

@ -41,9 +41,7 @@ namespace MathNet.Numerics.Data.Matlab
/// <summary> /// <summary>
/// Parse a MATLAB file /// Parse a MATLAB file
/// </summary> /// </summary>
/// <typeparam name="TDataType">The data type of the matrix.</typeparam> internal static class Parser
internal class Parser<TDataType>
where TDataType : struct, IEquatable<TDataType>, IFormattable
{ {
/// <summary> /// <summary>
/// Large Block Size /// Large Block Size
@ -60,86 +58,14 @@ namespace MathNet.Numerics.Data.Matlab
/// </summary> /// </summary>
const int SmallBlockSize = 4; const int SmallBlockSize = 4;
/// <summary>
/// Holds the names of the matrices in the file.
/// </summary>
readonly IList<string> _names = new List<string>();
/// <summary>
/// The stream to read the MATLAB file from.
/// </summary>
readonly Stream _stream;
/// <summary>
/// Initializes a new instance of the <see cref="Parser{TDataType}"/> class.
/// </summary>
/// <param name="fileName">Name of the file.</param>
internal Parser(string fileName)
: this(fileName, new string[0])
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Parser{TDataType}"/> class.
/// </summary>
/// <param name="stream">The stream to read from.</param>
internal Parser(Stream stream)
: this(stream, new string[0])
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Parser{TDataType}"/> class.
/// </summary>
/// <param name="stream">The stream to read from.</param>
/// <param name="objectNames">The name of the objects to retrieve.</param>
internal Parser(Stream stream, IEnumerable<string> objectNames)
{
if (stream == null)
{
throw new ArgumentNullException("stream");
}
_stream = stream;
SetNames(objectNames);
}
/// <summary>
/// Initializes a new instance of the <see cref="Parser{TDataType}"/> class.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="objectNames">The name of the objects to retrieve.</param>
Parser(string fileName, IEnumerable<string> objectNames)
{
if (string.IsNullOrEmpty(fileName))
{
throw new ArgumentException(Resources.StringNullOrEmpty, "fileName");
}
_stream = File.OpenRead(fileName);
SetNames(objectNames);
}
/// <summary>
/// Copies the names of the objects to retrieve to a local field.
/// </summary>
/// <param name="objectNames">The name of the objects to retrieve.</param>
void SetNames(IEnumerable<string> objectNames)
{
foreach (var name in objectNames)
{
_names.Add(name);
}
}
/// <summary> /// <summary>
/// Extracts all matrix blocks in a format we support. /// Extracts all matrix blocks in a format we support.
/// </summary> /// </summary>
internal List<MatlabMatrix> ParseAll() internal static List<MatlabMatrix> ParseAll(Stream stream)
{ {
var matrices = new List<MatlabMatrix>(); var matrices = new List<MatlabMatrix>();
using (var reader = new BinaryReader(_stream)) using (var reader = new BinaryReader(stream))
{ {
reader.BaseStream.Position = 126; reader.BaseStream.Position = 126;
if (reader.ReadByte() != LittleEndianIndicator) if (reader.ReadByte() != LittleEndianIndicator)
@ -149,7 +75,7 @@ namespace MathNet.Numerics.Data.Matlab
// skip version since it is always 0x0100. // skip version since it is always 0x0100.
reader.BaseStream.Position = 128; reader.BaseStream.Position = 128;
var length = _stream.Length; var length = stream.Length;
// for each data block add a MATLAB object to the file. // for each data block add a MATLAB object to the file.
while (reader.BaseStream.Position < length) while (reader.BaseStream.Position < length)
@ -251,7 +177,8 @@ namespace MathNet.Numerics.Data.Matlab
return data; return data;
} }
internal static Matrix<TDataType> ReadMatrixBlock(byte[] data) internal static Matrix<TDataType> ReadMatrixBlock<TDataType>(byte[] data)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{ {
using (var stream = new MemoryStream(data)) using (var stream = new MemoryStream(data))
using (var reader = new BinaryReader(stream)) using (var reader = new BinaryReader(stream))

4
src/Data/Matlab/SparseArrayReader.cs

@ -63,7 +63,7 @@ namespace MathNet.Numerics.Data.Matlab
ir[i] = reader.ReadInt32(); ir[i] = reader.ReadInt32();
} }
Parser<TDataType>.AlignData(reader.BaseStream, size, false); Parser.AlignData(reader.BaseStream, size, false);
// skip data type since it will always be int32 // skip data type since it will always be int32
reader.BaseStream.Seek(4, SeekOrigin.Current); reader.BaseStream.Seek(4, SeekOrigin.Current);
@ -81,7 +81,7 @@ namespace MathNet.Numerics.Data.Matlab
jc[j] = reader.ReadInt32(); jc[j] = reader.ReadInt32();
} }
Parser<TDataType>.AlignData(reader.BaseStream, jcsize, false); Parser.AlignData(reader.BaseStream, jcsize, false);
var type = (DataType)reader.ReadInt32(); var type = (DataType)reader.ReadInt32();
var dataSize = reader.ReadInt32(); var dataSize = reader.ReadInt32();

Loading…
Cancel
Save