The code below illustrates how to use the HDF5DotNet library to traverse the group/dataset structure of a file, and then how to read data from a dataset. The code presented assumes only a two-level scheme of groups and associated datasets. It also assumes 16-bit integer data. I am studying how to get the exact numeric data type from a file but like most of the things commonly needed, this does not seem to be easy to do with the HDF5 libraries at this time.
// HDF5 Generic File Access in C#
// Copyright (C) 2011 Morris Maynard
// All rights reserved
// Please give credit to the author when using this code.
using HDF5DotNet;
namespace HDF5
{
public class H5Dataset
{
public H5GroupId id;
public String Name;
public ulong lIndex;
public long[] dims;
public H5Dataset(H5GroupId _idg, String strN, ulong _idx)
{ id = _idg; Name = strN; lIndex = _idx; dims = null; }
}
public class H5Group
{
public H5GroupId id;
public H5FileId idFile;
public String Name;
public ulong lIndex;
public List<H5Dataset> datasets;
public H5Group(H5GroupId _id, String strN, ulong _idx) { id = _id; Name = strN; lIndex = _idx; datasets = null; }
}
// HDF File Reader
// Usage example:
//String fileName = textBox1.Text;
//H5Group[] groups = HDF5.H5Reader.GetGroups(fileName);
//long[] dims = HDF5.H5Reader.GetDims(H5Group group, HDF5.H5Dataset set);
//Array arr = HDF5.H5Reader.ReadFrame(groups[0], nFrame: 0);
//Console.Write((Int16[,])arr)[0,1]);
public class H5Reader
{
public static H5Group[] GetGroups(String fileName)
{
H5FileId idFile = H5F.open(fileName, H5F.OpenMode.ACC_RDONLY);
H5GroupId idGroup = H5G.open(idFile, "/");
List<H5Group> groups = new List<H5Group>();
ulong lIndex = 0;
H5L.iterate(idGroup, H5IndexType.NAME, H5IterationOrder.INCREASING, ref lIndex, (H5GroupId iGroup, string gName, H5LinkInfo info, object objData) =>
{
H5Group newGroup = new H5Group(iGroup, gName, lIndex);
groups.Add(newGroup);
return H5IterationResult.SUCCESS;
}, null);
foreach (H5Group g in groups)
GetDatasets(g, idFile);
return groups.ToArray();
}
public static void GetDatasets(H5Group group, H5LocId idFileOrGroup)
{
H5GroupId idGroup = null;
idGroup = H5G.open(idFileOrGroup, group.Name);
ulong lIndex = 0;
// Going to get all of the subgroups of this group (no recursion - 1 level)
// Assuming here that subgroups are the same as datasets
List<H5Dataset> datasets = new List<H5Dataset>();
H5L.iterate(idGroup, H5IndexType.NAME, H5IterationOrder.INCREASING, ref lIndex, (H5GroupId iGroup, string gName, H5LinkInfo info, object objData) =>
{
H5Dataset newDataset = new H5Dataset(iGroup, gName, lIndex);
newDataset.dims = GetDims(group, newDataset);
datasets.Add(newDataset);
return H5IterationResult.SUCCESS;
}, null);
group.datasets = datasets;
return; // all but intial call only accessible via linked-list
}
public static long[] GetDims(H5Group group, HDF5.H5Dataset set)
{
H5DataSetId idDataSet =
H5D.open(group.id, group.Name + "/" + set.Name);
// Open Data Set in group
H5DataSpaceId idFileSpace = H5D.getSpace(idDataSet);
// Get Data Space Id for Data Set in file.
int nRank = H5S.getSimpleExtentNDims(idFileSpace);
// Get rank of data from data space
long[] dims = H5S.getSimpleExtentDims(idFileSpace);
return dims;
}
// don't use this one before the group is all set up
public static long[] GetDims(H5Group group, int idxDataset)
{
H5Dataset set = group.datasets[idxDataset];
return GetDims(group, group.datasets[idxDataset]);
}
public static Array ReadFrame(H5Group group, int dataset = 0, int nFrame = 0)
{
H5DataSetId idDataSet =
H5D.open(group.id, group.Name + "/" + group.datasets[dataset].Name);
// Open Data Set in group
H5DataSpaceId idFileSpace = H5D.getSpace(idDataSet);
// Get Data Space Id for Data Set in file.
int nRank = H5S.getSimpleExtentNDims(idFileSpace);
// Get rank of data from data space
long[] dims = H5S.getSimpleExtentDims(idFileSpace);
long[] start, stride, count;
long nFrames, nx, ny;
if (nRank > 2) // dims are z y x here
{
nFrames = dims[0]; nx = dims[1]; ny = dims[2];
start = new long[] { nFrame, 0, 0 };
stride = new long[] { 1, 1, 1 };
count = new long[] { 1, nx, ny };
}
else // assume nRank == 2 !!
{
nFrames = 1; nx = dims[0]; ny = dims[1];
start = new long[] { nFrame };
stride = new long[] { 1 };
count = new long[] { 1 };
}
// setup counts and offsets to just read 1st "slice" of data
H5DataSpaceId idMemSpace = H5S.create_simple(nRank, count);
H5S.selectHyperslab(idMemSpace, H5S.SelectOperator.SET, new long[] { 0, 0, 0}, count);
idFileSpace = H5D.getSpace(idDataSet);
// select hyperslab in filespace
H5S.selectHyperslab(idFileSpace, H5S.SelectOperator.SET, start, count);
// ************* Assuming data is 16-bit integer here!!! **********
// Set up memory to read into
Int16[,] rdata = new Int16[nx, ny];
H5Array<Int16> udata = new H5Array<Int16>(rdata);
H5D.read(idDataSet, new H5DataTypeId(H5T.H5Type.NATIVE_SHORT), idMemSpace, idFileSpace,
new H5PropertyListId(new H5P.Template()), new H5Array<short>(rdata));
return rdata;
}
}
}