Unify HDF and old-style datatypes
This commit is contained in:
parent
433dca8c69
commit
bdd04a80b7
@ -64,7 +64,7 @@ namespace MatFileHandler
|
||||
{
|
||||
var flags = ConstructArrayFlags(ArrayType.MxCell);
|
||||
var elements = Enumerable.Repeat(MatArray.Empty() as IArray, dimensions.NumberOfElements()).ToList();
|
||||
return new MatCellArray(flags, dimensions, string.Empty, elements);
|
||||
return new MatCellArray(dimensions, elements);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -223,7 +223,7 @@ namespace MatFileHandler
|
||||
elements.Add(element);
|
||||
}
|
||||
|
||||
return new MatCellArray(flags, dimensions, name, elements);
|
||||
return new MatCellArray(dimensions, elements);
|
||||
}
|
||||
|
||||
private DataElementWithArrayFlags ContinueReadingOpaque(BinaryReader reader)
|
||||
|
@ -1,45 +0,0 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
internal class Array : IArray
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Array"/> class.
|
||||
/// </summary>
|
||||
/// <param name="dimensions">Dimensions of the array.</param>
|
||||
protected Array(
|
||||
int[] dimensions)
|
||||
{
|
||||
Dimensions = dimensions;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int[] Dimensions { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Count => Dimensions.NumberOfElements();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new empty array.
|
||||
/// </summary>
|
||||
/// <returns>Empty array.</returns>
|
||||
public static Array Empty()
|
||||
{
|
||||
return new Array(System.Array.Empty<int>());
|
||||
}
|
||||
|
||||
public virtual double[] ConvertToDoubleArray()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual Complex[] ConvertToComplexArray()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEmpty => Dimensions.Length == 0;
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
internal class CellArray : Array, ICellArray
|
||||
{
|
||||
public CellArray(int[] dimensions, IEnumerable<IArray> elements)
|
||||
: base(dimensions)
|
||||
{
|
||||
Data = elements.ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IArray[] Data { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IArray this[params int[] indices]
|
||||
{
|
||||
get => Data[Dimensions.DimFlatten(indices)];
|
||||
set => Data[Dimensions.DimFlatten(indices)] = value;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
internal class CharArray : Array, ICharArray
|
||||
{
|
||||
public CharArray(int[] dimensions, string data)
|
||||
: base(dimensions)
|
||||
{
|
||||
StringData = data;
|
||||
}
|
||||
|
||||
public override double[] ConvertToDoubleArray()
|
||||
{
|
||||
return Data.Select(Convert.ToDouble).ToArray();
|
||||
}
|
||||
|
||||
public override Complex[] ConvertToComplexArray()
|
||||
{
|
||||
return ConvertToDoubleArray().Select(x => new Complex(x, 0.0)).ToArray();
|
||||
}
|
||||
|
||||
public char[] Data => StringData.ToCharArray();
|
||||
|
||||
public char this[params int[] list]
|
||||
{
|
||||
get => StringData[Dimensions.DimFlatten(list)];
|
||||
set {
|
||||
var chars = StringData.ToCharArray();
|
||||
chars[Dimensions.DimFlatten(list)] = value;
|
||||
StringData = chars.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public string String => StringData;
|
||||
|
||||
private string StringData { get; set; }
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
/// <summary>
|
||||
/// A numerical array.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Element type.</typeparam>
|
||||
internal class NumericalArrayOf<T> : Array, IArrayOf<T>
|
||||
where T : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NumericalArrayOf{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="dimensions">Dimensions of the array.</param>
|
||||
/// <param name="name">Array name.</param>
|
||||
/// <param name="data">Array contents.</param>
|
||||
public NumericalArrayOf(int[] dimensions, T[] data)
|
||||
: base(dimensions)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public T[] Data { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public T this[params int[] list]
|
||||
{
|
||||
get => Data[Dimensions.DimFlatten(list)];
|
||||
set => Data[Dimensions.DimFlatten(list)] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to convert the array to an array of Double values.
|
||||
/// </summary>
|
||||
/// <returns>Array of values of the array, converted to Double, or null if the conversion is not possible.</returns>
|
||||
public override double[] ConvertToDoubleArray()
|
||||
{
|
||||
return Data as double[] ?? Data.Select(x => Convert.ToDouble((object)x)).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to convert the array to an array of Complex values.
|
||||
/// </summary>
|
||||
/// <returns>Array of values of the array, converted to Complex, or null if the conversion is not possible.</returns>
|
||||
public override Complex[] ConvertToComplexArray()
|
||||
{
|
||||
if (Data is Complex[])
|
||||
{
|
||||
return Data as Complex[];
|
||||
}
|
||||
if (Data is ComplexOf<sbyte>[])
|
||||
{
|
||||
return ConvertToComplex(Data as ComplexOf<sbyte>[]);
|
||||
}
|
||||
if (Data is ComplexOf<byte>[])
|
||||
{
|
||||
return ConvertToComplex(Data as ComplexOf<byte>[]);
|
||||
}
|
||||
if (Data is ComplexOf<short>[])
|
||||
{
|
||||
return ConvertToComplex(Data as ComplexOf<short>[]);
|
||||
}
|
||||
if (Data is ComplexOf<ushort>[])
|
||||
{
|
||||
return ConvertToComplex(Data as ComplexOf<ushort>[]);
|
||||
}
|
||||
if (Data is ComplexOf<int>[])
|
||||
{
|
||||
return ConvertToComplex(Data as ComplexOf<int>[]);
|
||||
}
|
||||
if (Data is ComplexOf<uint>[])
|
||||
{
|
||||
return ConvertToComplex(Data as ComplexOf<uint>[]);
|
||||
}
|
||||
if (Data is ComplexOf<long>[])
|
||||
{
|
||||
return ConvertToComplex(Data as ComplexOf<long>[]);
|
||||
}
|
||||
if (Data is ComplexOf<ulong>[])
|
||||
{
|
||||
return ConvertToComplex(Data as ComplexOf<ulong>[]);
|
||||
}
|
||||
return ConvertToDoubleArray().Select(x => new Complex(x, 0.0)).ToArray();
|
||||
}
|
||||
|
||||
private static Complex[] ConvertToComplex<TS>(IEnumerable<ComplexOf<TS>> array)
|
||||
where TS : struct
|
||||
{
|
||||
return array.Select(x => new Complex(Convert.ToDouble(x.Real), Convert.ToDouble(x.Imaginary))).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
/// <summary>
|
||||
/// Sparse array.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Element type.</typeparam>
|
||||
/// <remarks>Possible values of T: Double, Complex, Boolean.</remarks>
|
||||
internal class SparseArrayOf<T> : Array, ISparseArrayOf<T>
|
||||
where T : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SparseArrayOf{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="dimensions">Dimensions of the array.</param>
|
||||
/// <param name="data">Array contents.</param>
|
||||
public SparseArrayOf(
|
||||
int[] dimensions,
|
||||
Dictionary<(int, int), T> data)
|
||||
: base(dimensions)
|
||||
{
|
||||
DataDictionary = data;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
T[] IArrayOf<T>.Data =>
|
||||
Enumerable.Range(0, Dimensions[0] * Dimensions[1])
|
||||
.Select(i => this[i])
|
||||
.ToArray();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyDictionary<(int, int), T> Data => DataDictionary;
|
||||
|
||||
private Dictionary<(int, int), T> DataDictionary { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public T this[params int[] list]
|
||||
{
|
||||
get
|
||||
{
|
||||
var rowAndColumn = GetRowAndColumn(list);
|
||||
return DataDictionary.ContainsKey(rowAndColumn) ? DataDictionary[rowAndColumn] : default(T);
|
||||
}
|
||||
set => DataDictionary[GetRowAndColumn(list)] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to convert the array to an array of Double values.
|
||||
/// </summary>
|
||||
/// <returns>Array of values of the array, converted to Double, or null if the conversion is not possible.</returns>
|
||||
public override double[] ConvertToDoubleArray()
|
||||
{
|
||||
var data = ((IArrayOf<T>)this).Data;
|
||||
return data as double[] ?? data.Select(x => Convert.ToDouble(x)).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to convert the array to an array of Complex values.
|
||||
/// </summary>
|
||||
/// <returns>Array of values of the array, converted to Complex, or null if the conversion is not possible.</returns>
|
||||
public override Complex[] ConvertToComplexArray()
|
||||
{
|
||||
var data = ((IArrayOf<T>)this).Data;
|
||||
return data as Complex[] ?? ConvertToDoubleArray().Select(x => new Complex(x, 0.0)).ToArray();
|
||||
}
|
||||
|
||||
private (int row, int column) GetRowAndColumn(int[] indices)
|
||||
{
|
||||
switch (indices.Length)
|
||||
{
|
||||
case 1:
|
||||
return (indices[0] % Dimensions[0], indices[0] / Dimensions[0]);
|
||||
case 2:
|
||||
return (indices[0], indices[1]);
|
||||
default:
|
||||
throw new NotSupportedException("Invalid index for sparse array.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
internal class StructureArray : Array, IStructureArray
|
||||
{
|
||||
public StructureArray(
|
||||
int[] dimensions,
|
||||
Dictionary<string, List<IArray>> fields)
|
||||
: base(dimensions)
|
||||
{
|
||||
Fields = fields;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<string> FieldNames => Fields.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// Gets null: not implemented.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, IArray>[] Data => null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a dictionary that maps field names to lists of values.
|
||||
/// </summary>
|
||||
internal Dictionary<string, List<IArray>> Fields { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IArray this[string field, params int[] list]
|
||||
{
|
||||
get => Fields[field][Dimensions.DimFlatten(list)];
|
||||
set => Fields[field][Dimensions.DimFlatten(list)] = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
IReadOnlyDictionary<string, IArray> IArrayOf<IReadOnlyDictionary<string, IArray>>.this[params int[] list]
|
||||
{
|
||||
get => ExtractStructure(Dimensions.DimFlatten(list));
|
||||
set => throw new NotSupportedException(
|
||||
"Cannot set structure elements via this[params int[]] indexer. Use this[string, int[]] instead.");
|
||||
}
|
||||
|
||||
private IReadOnlyDictionary<string, IArray> ExtractStructure(int i)
|
||||
{
|
||||
return new HdfStructureArrayElement(this, i);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to an element of a structure array by fields.
|
||||
/// </summary>
|
||||
internal class HdfStructureArrayElement : IReadOnlyDictionary<string, IArray>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HdfStructureArrayElement"/> class.
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent structure array.</param>
|
||||
/// <param name="index">Index in the structure array.</param>
|
||||
internal HdfStructureArrayElement(StructureArray parent, int index)
|
||||
{
|
||||
Parent = parent;
|
||||
Index = index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of fields.
|
||||
/// </summary>
|
||||
public int Count => Parent.Fields.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all fields.
|
||||
/// </summary>
|
||||
public IEnumerable<string> Keys => Parent.Fields.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all values.
|
||||
/// </summary>
|
||||
public IEnumerable<IArray> Values => Parent.Fields.Values.Select(array => array[Index]);
|
||||
|
||||
private StructureArray Parent { get; }
|
||||
|
||||
private int Index { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a given field.
|
||||
/// </summary>
|
||||
/// <param name="key">Field name.</param>
|
||||
/// <returns>The corresponding value.</returns>
|
||||
public IArray this[string key] => Parent.Fields[key][Index];
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates fieldstructure/value pairs of the dictionary.
|
||||
/// </summary>
|
||||
/// <returns>All field/value pairs in the structure.</returns>
|
||||
public IEnumerator<KeyValuePair<string, IArray>> GetEnumerator()
|
||||
{
|
||||
foreach (var field in Parent.Fields)
|
||||
{
|
||||
yield return new KeyValuePair<string, IArray>(field.Key, field.Value[Index]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates field/value pairs of the structure.
|
||||
/// </summary>
|
||||
/// <returns>All field/value pairs in the structure.</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the structure has a given field.
|
||||
/// </summary>
|
||||
/// <param name="key">Field name</param>
|
||||
/// <returns>True iff the structure has a given field.</returns>
|
||||
public bool ContainsKey(string key) => Parent.Fields.ContainsKey(key);
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the value of a given field.
|
||||
/// </summary>
|
||||
/// <param name="key">Field name.</param>
|
||||
/// <param name="value">Value (or null if the field is not present).</param>
|
||||
/// <returns>Success status of the query.</returns>
|
||||
public bool TryGetValue(string key, out IArray value)
|
||||
{
|
||||
var success = Parent.Fields.TryGetValue(key, out var array);
|
||||
if (!success)
|
||||
{
|
||||
value = default(IArray);
|
||||
return false;
|
||||
}
|
||||
value = array[Index];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -186,15 +186,17 @@ namespace MatFileHandler
|
||||
}
|
||||
}
|
||||
|
||||
return new CellArray(dims, elements);
|
||||
return new MatCellArray(dims, elements);
|
||||
}
|
||||
|
||||
private static IArray ReadCharArray(Dataset dataset, int[] dims)
|
||||
{
|
||||
var storageSize = dataset.GetStorageSize();
|
||||
var data = ReadDataset(dataset, Hdf.Type.NativeUInt16, storageSize);
|
||||
var uInt16Data = new ushort[data.Length / sizeof(ushort)];
|
||||
Buffer.BlockCopy(data, 0, uInt16Data, 0, data.Length);
|
||||
var str = Encoding.Unicode.GetString(data);
|
||||
return new CharArray(dims, str);
|
||||
return new MatCharArrayOf<ushort>(dims, uInt16Data, str);
|
||||
}
|
||||
|
||||
private static (T[] real, T[] imaginary) ReadComplexData<T>(
|
||||
@ -226,7 +228,7 @@ namespace MatFileHandler
|
||||
switch (arrayType)
|
||||
{
|
||||
case MatlabClass.MEmpty:
|
||||
return Hdf.Array.Empty();
|
||||
return MatArray.Empty();
|
||||
case MatlabClass.MLogical:
|
||||
return ReadNumericalArray<bool>(dataset, dims, arrayType);
|
||||
case MatlabClass.MChar:
|
||||
@ -321,7 +323,7 @@ namespace MatFileHandler
|
||||
switch (arrayType)
|
||||
{
|
||||
case MatlabClass.MEmpty:
|
||||
return Hdf.Array.Empty();
|
||||
return MatArray.Empty();
|
||||
case MatlabClass.MLogical:
|
||||
return ReadSparseArray<bool>(group.Id, arrayType);
|
||||
case MatlabClass.MInt8:
|
||||
@ -390,7 +392,7 @@ namespace MatFileHandler
|
||||
convertedRealData as double[],
|
||||
convertedImaginaryData as double[])
|
||||
.ToArray();
|
||||
return new NumericalArrayOf<Complex>(dims, complexData);
|
||||
return new MatNumericalArrayOf<Complex>(dims, complexData);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -399,7 +401,7 @@ namespace MatFileHandler
|
||||
convertedRealData,
|
||||
convertedImaginaryData)
|
||||
.ToArray();
|
||||
return new NumericalArrayOf<ComplexOf<T>>(dims, complexData);
|
||||
return new MatNumericalArrayOf<ComplexOf<T>>(dims, complexData);
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,7 +412,7 @@ namespace MatFileHandler
|
||||
|
||||
var data = ReadDataset(dataset, H5tTypeFromHdfMatlabClass(arrayType), dataSize);
|
||||
var convertedData = ConvertDataToProperType<T>(data, arrayType);
|
||||
return new NumericalArrayOf<T>(dims, convertedData);
|
||||
return new MatNumericalArrayOf<T>(dims, convertedData);
|
||||
}
|
||||
|
||||
private static IArray ReadSparseArray<T>(long groupId, MatlabClass arrayType)
|
||||
@ -469,7 +471,7 @@ namespace MatFileHandler
|
||||
rowIndex,
|
||||
columnIndex,
|
||||
j => complexData[j]);
|
||||
return new SparseArrayOf<Complex>(dims, complexDataDictionary);
|
||||
return new MatSparseArrayOf<Complex>(dims, complexDataDictionary);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -483,7 +485,7 @@ namespace MatFileHandler
|
||||
rowIndex,
|
||||
columnIndex,
|
||||
j => complexData[j]);
|
||||
return new SparseArrayOf<ComplexOf<T>>(dims, complexDataDictionary);
|
||||
return new MatSparseArrayOf<ComplexOf<T>>(dims, complexDataDictionary);
|
||||
}
|
||||
}
|
||||
|
||||
@ -496,7 +498,7 @@ namespace MatFileHandler
|
||||
var elements = ConvertDataToProperType<T>(d, arrayType);
|
||||
var dataDictionary =
|
||||
DataExtraction.ConvertMatlabSparseToDictionary(rowIndex, columnIndex, j => elements[j]);
|
||||
return new SparseArrayOf<T>(dims, dataDictionary);
|
||||
return new MatSparseArrayOf<T>(dims, dataDictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -547,7 +549,7 @@ namespace MatFileHandler
|
||||
}
|
||||
}
|
||||
|
||||
return new StructureArray(dimensions, dictionary);
|
||||
return new MatStructureArray(dimensions, dictionary);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -13,11 +13,9 @@ namespace MatFileHandler
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MatCellArray"/> class.
|
||||
/// </summary>
|
||||
/// <param name="flags">Array properties.</param>
|
||||
/// <param name="dimensions">Dimensions of the array.</param>
|
||||
/// <param name="name">Array name.</param>
|
||||
/// <param name="elements">Array elements.</param>
|
||||
public MatCellArray(ArrayFlags flags, int[] dimensions, string name, IEnumerable<IArray> elements)
|
||||
public MatCellArray(int[] dimensions, IEnumerable<IArray> elements)
|
||||
: base(dimensions)
|
||||
{
|
||||
Data = elements.ToArray();
|
||||
|
@ -1,7 +1,7 @@
|
||||
using HDF.PInvoke;
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using HDF.PInvoke;
|
||||
|
||||
namespace MatFileHandler
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user