我如何将自定义类型的列表/数组写入HDF5文件
本文关键字:数组 文件 HDF5 列表 自定义 类型 | 更新日期: 2023-09-27 18:13:11
我需要使用c#将一些数据写入HDF5文件。我没有绑定到任何特定的库,但我能找到的唯一可访问的库是HDF5DotNet (http://hdf5.net/)。我有一个简单的类包含一些数据(只是使用默认值初始化测试它很容易,通常数据从传感器读取):
public class mData
{
public double temp = 123.456789;
public double humid = 223.456789;
public int chamberId = 5;
}
我如何将数组或列表写入HDF5文件?HDF5似乎太伟大了,这是一个特殊情况,但我找不到任何合适的文档。以下是我尝试的示例:
List<mData> mdl = new List<mData>();
mdl.Add(new mData()); // create some dummy data
mdl.Add(new mData());
mdl.Add(new mData());
string filename = "test.h5";
const int DATA_ARRAY_LENGTH = 3;
const int RANK = 1; // <- unsure about this one
H5FileId fileId = H5F.create(filename, H5F.CreateMode.ACC_TRUNC);
H5GroupId groupId = H5G.create(fileId, "/myGroup");
long[] dims = new long[RANK]; // <- unsure, extrapolated from example
dims[0] = DATA_ARRAY_LENGTH;
H5DataSpaceId spaceId = H5S.create_simple(RANK, dims);
H5DataTypeId typeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE); // <- NATIVE_DOUBLE is definitely wrong but I dont know which type to use in this case
int typeSize = H5T.getSize(typeId);
H5DataSetId dataSetId = H5D.create(fileId, "/myDataset", typeId, spaceId);
H5D.write(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_DOUBLE),
new H5Array<double>(mdl)); // <- NATIVE_DOUBLE and H5Array<double> are definitely wrong but again unsure which type to use in both cases
H5G.close(groupId);
H5F.close(fileId);
任何帮助或方向,也对其他图书馆的高度赞赏!
用H5T.H5Type.STD_REF_OBJ
代替H5T.H5Type.NATIVE_DOUBLE
就可以了。
测试代码
static void Main(string[] args)
{
SampleH5Modified sh5 = new SampleH5Modified("TestFile01.h5", 5);
sh5.Run();
}
将生成如下输出:
Creating H5 file TestFile01.h5... H5 file TestFile01.h5 created successfully! Reading H5 file TestFile01.h5... chamberId=1 humid=100 temp=80 chamberId=2 humid=101 temp=81 chamberId=3 humid=102 temp=82 chamberId=4 humid=103 temp=83 chamberId=5 humid=104 temp=84 Processing complete!
public class SampleH5Modified
{
private string filename;
private int count;
const string dataSetName = "/SampleDataSet";
public SampleH5Modified(string filename, int count)
{
this.filename = filename;
this.count = count;
}
public void Run()
{
List<mData> data1 = new List<mData>();
for (int i = 0; i < count; i++)
data1.Add(new mData(i + 80, i + 100, i + 1));
WriteData(data1);
mData[] data2 = ReadData();
foreach (mData d in data2)
Console.WriteLine("chamberId={0} humid={1} temp={2}", d.chamberId, d.humid, d.temp);
Console.WriteLine("Processing complete!");
}
private void WriteData(List<mData> data)
{
Console.WriteLine("Creating H5 file {0}...", filename);
const int RANK = 1;
long[] dims = new long[RANK];
dims[0] = count;
H5FileId fileId = H5F.create(filename, H5F.CreateMode.ACC_TRUNC);
H5DataSpaceId spaceId = H5S.create_simple(RANK, dims);
H5DataTypeId typeId = H5T.copy(H5T.H5Type.STD_REF_OBJ);
int typeSize = H5T.getSize(typeId);
H5DataSetId dataSetId = H5D.create(fileId, dataSetName, typeId, spaceId);
H5D.write(dataSetId, new H5DataTypeId(H5T.H5Type.STD_REF_OBJ), new H5Array<mData>(data.ToArray()));
H5D.close(dataSetId);
H5F.close(fileId);
Console.WriteLine("H5 file {0} created successfully!", filename);
}
private mData[] ReadData()
{
Console.WriteLine("Reading H5 file {0}...", filename);
H5FileId fileId = H5F.open(filename, H5F.OpenMode.ACC_RDONLY);
H5DataSetId dataSetId = H5D.open(fileId, dataSetName);
mData[] readDataBack = new mData[count];
H5D.read(dataSetId, new H5DataTypeId(H5T.H5Type.STD_REF_OBJ), new H5Array<mData>(readDataBack));
H5D.close(dataSetId);
H5F.close(fileId);
return readDataBack;
}
}
一种(容易)解决在c#中编写自定义类型(即复合)的列表/数组到HDF5数据集的问题的方法是通过使用HDFql。在HDFql中,这可以通过以下方式解决:
// use HDFql namespace (make sure it can be found by the C# compiler)
using AS.HDFql;
using System;
using System.Runtime.InteropServices;
public class Test
{
[StructLayout(LayoutKind.Sequential, Pack=1)]
struct Sensor
{
public double temp;
public double humid;
public int chamberId;
}
public static void Main(string []args)
{
// declare variable 'data'
Sensor []data = new Sensor[3];
// create an HDF5 file named 'test.h5' and use (i.e. open) it
HDFql.Execute("create and use file test.h5");
// create a dataset named 'myDataset' of data type compound with three members (temp, humid and chamberId)
HDFql.Execute("create dataset myDataset as compound(temp as double, humid as double, chamberId as int)(3)");
// populate variable 'data' with values
data[0].temp = 10;
data[0].humid = 12.1;
data[0].chamberId = 14;
data[1].temp = 20;
data[1].humid = 22.5;
data[1].chamberId = 27;
data[2].temp = 30;
data[2].humid = 32.3;
data[2].chamberId = 39;
// insert (i.e. write) content of variable 'data' into dataset 'myDataset'
HDFql.Execute("insert into myDataset values from memory " + HDFql.VariableRegister(data));
}
}