HDF5 示例代码

Posted

技术标签:

【中文标题】HDF5 示例代码【英文标题】:HDF5 Example code 【发布时间】:2011-12-17 21:23:15 【问题描述】:

使用HDF5DotNet,谁能指出示例代码,它将打开一个hdf5文件,提取数据集的内容,并将内容打印到标准输出?

到目前为止,我有以下内容:

        H5.Open();
        var h5 = H5F.open("example.h5", H5F.OpenMode.ACC_RDONLY);
        var dataset = H5D.open(h5, "/Timings/aaPCBTimes");
        var space = H5D.getSpace(dataset);
        var size = H5S.getSimpleExtentDims(space);

然后就有点混乱了。

我实际上想对数据集的内容进行一些处理,但我认为一旦我将转储到标准输出,我就可以从那里解决它。

更新:我已经解决了这个问题,足以解决我自己的问题。我没有意识到数据集是一个多数组 - 我认为它更像是一个 db 表。万一有人感兴趣,

double[,] dataArray = new double[size[0], 6];
var wrapArray = new H5Array<double>(dataArray);
var dataType = H5D.getType(d);
H5D.read(dataset, dataType, wrapArray);
Console.WriteLine(dataArray[0, 0]);

【问题讨论】:

我想指出,将H5h5H5FH5SH5D 作为变量名是不好的形式。前两个仅因情况而异。其他的只有一个字母。 是的。 H5、H5F、H5S 和 H5D 均由 API - HDF5DotNet - C++/CLI Wrapper of the HDF5 Library 提供。如果您点击链接,您还可以享受 H5A、H5E、H5G、H5I、H5L、H5O、H5P 和 H5R。我正在寻找代码示例,因为我不想花太多时间研究这个界面。 你为什么不添加你的破解/解决方案作为答案并接受它? @Sebastian,我刚刚找到了用于 HDF5 的 this(商业许可)高级 API。它看起来不错,但它是一个大而昂贵的项目的一部分。 请注意,HDF5 项目 now recommends 使用他们的 P/Invoke 包装器 here,并且 HDF5DotNet 在 2012 年没有维护和冻结。 【参考方案1】:

试试这个:

using System;
using HDF5DotNet;

namespace CSharpExample1

    class Program
    
    // Function used with 
    static int myFunction(H5GroupId id, string objectName, Object param)
    
        Console.WriteLine("The object name is 0", objectName);
        Console.WriteLine("The object parameter is 0", param);
        return 0;
    

    static void Main(string[] args)
    
        try
        
            // We will write and read an int array of this length.
            const int DATA_ARRAY_LENGTH = 12;

            // Rank is the number of dimensions of the data array.
            const int RANK = 1;

            // Create an HDF5 file.
            // The enumeration type H5F.CreateMode provides only the legal 
            // creation modes.  Missing H5Fcreate parameters are provided
            // with default values.
            H5FileId fileId = H5F.create("myCSharp.h5", 
                                         H5F.CreateMode.ACC_TRUNC);

            // Create a HDF5 group.  
            H5GroupId groupId = H5G.create(fileId, "/cSharpGroup", 0);
            H5GroupId subGroup = H5G.create(groupId, "mySubGroup", 0);   

            // Demonstrate getObjectInfo
            ObjectInfo info = H5G.getObjectInfo(fileId, "/cSharpGroup", true);
            Console.WriteLine("cSharpGroup header size is 0", info.headerSize);
            Console.WriteLine("cSharpGroup nlinks is 0", info.nHardLinks);
            Console.WriteLine("cSharpGroup fileno is 0 1", 
                 info.fileNumber[0], info.fileNumber[1]);
            Console.WriteLine("cSharpGroup objno is 0 1", 
                 info.objectNumber[0], info.objectNumber[1]);
            Console.WriteLine("cSharpGroup type is 0", info.objectType);


            H5G.close(subGroup);

            // Prepare to create a data space for writing a 1-dimensional 
            // signed integer array.
            ulong[] dims = new ulong[RANK];
            dims[0] = DATA_ARRAY_LENGTH;

            // Put descending ramp data in an array so that we can
            // write it to the file.
            int[] dset_data = new int[DATA_ARRAY_LENGTH];
            for (int i = 0; i < DATA_ARRAY_LENGTH; i++)
                dset_data[i] = DATA_ARRAY_LENGTH - i;

            // Create a data space to accommodate our 1-dimensional array.
            // The resulting H5DataSpaceId will be used to create the 
            // data set.
            H5DataSpaceId spaceId = H5S.create_simple(RANK, dims);

            // Create a copy of a standard data type.  We will use the 
            // resulting H5DataTypeId to create the data set.  We could
            // have  used the HST.H5Type data directly in the call to 
            // H5D.create, but this demonstrates the use of H5T.copy 
            // and the use of a H5DataTypeId in H5D.create.
            H5DataTypeId typeId = H5T.copy(H5T.H5Type.NATIVE_INT);

            // Find the size of the type
            uint typeSize = H5T.getSize(typeId);
            Console.WriteLine("typeSize is 0", typeSize);

            // Set the order to big endian
            H5T.setOrder(typeId, H5T.Order.BE);

            // Set the order to little endian
            H5T.setOrder(typeId, H5T.Order.LE);

            // Create the data set.
            H5DataSetId dataSetId = H5D.create(fileId, "/csharpExample", 
                                               typeId, spaceId);

            // Write the integer data to the data set.

            H5D.write(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_INT),
                              new H5Array<int>(dset_data));

            // If we were writing a single value it might look like this.
            //  int singleValue = 100;
            //  H5D.writeScalar(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_INT),
            //     ref singleValue);

            // Create an integer array to receive the read data.
            int[] readDataBack = new int[DATA_ARRAY_LENGTH];

            // Read the integer data back from the data set
            H5D.read(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_INT), 
                new H5Array<int>(readDataBack));

            // Echo the data
            for(int i=0;i<DATA_ARRAY_LENGTH;i++)
            
               Console.WriteLine(readDataBack[i]);
              

            // Close all the open resources.
            H5D.close(dataSetId);

            // Reopen and close the data sets to show that we can.
            dataSetId = H5D.open(fileId, "/csharpExample");
            H5D.close(dataSetId);
            dataSetId = H5D.open(groupId, "/csharpExample");
            H5D.close(dataSetId);

            H5S.close(spaceId);
            H5T.close(typeId);
            H5G.close(groupId);

            //int x = 10;
            //H5T.enumInsert<int>(typeId, "myString", ref x);
            //H5G.close(groupId);
            H5GIterateDelegate myDelegate;
            myDelegate = myFunction;
            int x = 9;
            int index = H5G.iterate(fileId, "/cSharpGroup",
                myDelegate, x, 0);

            // Reopen the group id to show that we can.
            groupId = H5G.open(fileId, "/cSharpGroup");
            H5G.close(groupId);

            H5F.close(fileId);

            // Reopen and reclose the file.
            H5FileId openId = H5F.open("myCSharp.h5", 
                                       H5F.OpenMode.ACC_RDONLY);
            H5F.close(openId);
        
        // This catches all the HDF exception classes.  Because each call
        // generates unique exception, different exception can be handled
        // separately.  For example, to catch open errors we could have used
        // catch (H5FopenException openException).
        catch (HDFException e)
        
            Console.WriteLine(e.Message);
        

        Console.WriteLine("Processing complete!");
        Console.ReadLine();
    


【讨论】:

我编辑了这个例子,因为它没有编译:H5G.create -> 跳过第三个参数,H5S.create_simple 必须得到 long[] 而不是 ulong[] 作为第二个参数,H5T.getSize 返回 int而不是 uint【参考方案2】:

所以,你的开始很棒。我创建了一些可以帮助你的扩展。在您的代码中使用它,您应该能够在面向对象的语言中更有意义的事情,例如(在您的情况下):

H5.Open();
var h5FileId= H5F.open("example.h5");
double[,] dataArray = h5FileId.Read2DArray<double>("/Timings/aaPCBTimes");
// or more generically...
T[,] dataArray = h5FileId.Read2DArray<T>("/Timings/aaPCBTimes");

这是不完整的扩展,我会考虑将它们添加到 HDF5Net...

public static class HdfExtensions

    // thank you http://***.com/questions/4133377/splitting-a-string-number-every-nth-character-number
    public static IEnumerable<String> SplitInParts(this String s, Int32 partLength)
    
        if (s == null)
            throw new ArgumentNullException("s");
        if (partLength <= 0)
            throw new ArgumentException("Part length has to be positive.", "partLength");

        for (var i = 0; i < s.Length; i += partLength)
            yield return s.Substring(i, Math.Min(partLength, s.Length - i));
    

    public static T[] Read1DArray<T>(this H5FileId fileId, string dataSetName)
    
        var dataset = H5D.open(fileId, dataSetName);
        var space = H5D.getSpace(dataset);
        var dims = H5S.getSimpleExtentDims(space);
        var dataType = H5D.getType(dataset);
        if (typeof(T) == typeof(string))
        
            int stringLength = H5T.getSize(dataType);
            byte[] buffer = new byte[dims[0] * stringLength];
            H5D.read(dataset, dataType, new H5Array<byte>(buffer));
            string stuff = System.Text.ASCIIEncoding.ASCII.GetString(buffer);
            return stuff.SplitInParts(stringLength).Select(ss => (T)(object)ss).ToArray();
        
        T[] dataArray = new T[dims[0]];
        var wrapArray = new H5Array<T>(dataArray);
        H5D.read(dataset, dataType, wrapArray);
        return dataArray;
    

    public static T[,] Read2DArray<T>(this H5FileId fileId, string dataSetName)
    
        var dataset = H5D.open(fileId, dataSetName);
        var space = H5D.getSpace(dataset);
        var dims = H5S.getSimpleExtentDims(space);
        var dataType = H5D.getType(dataset);
        if (typeof(T) == typeof(string))
        
             // this will also need a string hack...
        
        T[,] dataArray = new T[dims[0], dims[1]];
        var wrapArray = new H5Array<T>(dataArray);
        H5D.read(dataset, dataType, wrapArray);
        return dataArray;
    

【讨论】:

这比公认的答案更有帮助。【参考方案3】:

这是一个工作示例:

using System.Collections.Generic;
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HDF5DotNet;
namespace HDF5Test

    public class HDFTester
    
        static int myFunction(H5GroupId id, string objectName, Object param)
        
            Console.WriteLine("The object name is 0", objectName);
            Console.WriteLine("The object parameter is 0", param);
            return 0;
        

        public static void runTest()
        
            try
            
                // We will write and read an int array of this length.
                const int DATA_ARRAY_LENGTH = 12;

                // Rank is the number of dimensions of the data array.
                const int RANK = 1;

                // Create an HDF5 file.
                // The enumeration type H5F.CreateMode provides only the legal 
                // creation modes.  Missing H5Fcreate parameters are provided
                // with default values.
                H5FileId fileId = H5F.create("myCSharp.h5",
                    H5F.CreateMode.ACC_TRUNC);

                // Create a HDF5 group.  
                H5GroupId groupId = H5G.create(fileId, "/cSharpGroup");
                H5GroupId subGroup = H5G.create(groupId, "mySubGroup");

                // Demonstrate getObjectInfo
                ObjectInfo info = H5G.getObjectInfo(fileId, "/cSharpGroup", true);
                Console.WriteLine("cSharpGroup header size is 0", info.headerSize);
                Console.WriteLine("cSharpGroup nlinks is 0", info.nHardLinks);
                Console.WriteLine("cSharpGroup fileno is 0 1",
                    info.fileNumber[0], info.fileNumber[1]);
                Console.WriteLine("cSharpGroup objno is 0 1",
                    info.objectNumber[0], info.objectNumber[1]);
                Console.WriteLine("cSharpGroup type is 0", info.objectType);


                H5G.close(subGroup);

                // Prepare to create a data space for writing a 1-dimensional 
                // signed integer array.
                long[] dims = new long[RANK];
                dims[0] = DATA_ARRAY_LENGTH;

                // Put descending ramp data in an array so that we can
                // write it to the file.
                int[] dset_data = new int[DATA_ARRAY_LENGTH];
                for (int i = 0; i < DATA_ARRAY_LENGTH; i++)
                    dset_data[i] = DATA_ARRAY_LENGTH - i;

                // Create a data space to accommodate our 1-dimensional array.
                // The resulting H5DataSpaceId will be used to create the 
                // data set.
                H5DataSpaceId spaceId = H5S.create_simple(RANK, dims);

                // Create a copy of a standard data type.  We will use the 
                // resulting H5DataTypeId to create the data set.  We could
                // have  used the HST.H5Type data directly in the call to 
                // H5D.create, but this demonstrates the use of H5T.copy 
                // and the use of a H5DataTypeId in H5D.create.
                H5DataTypeId typeId = H5T.copy(H5T.H5Type.NATIVE_INT);

                // Find the size of the type
                int typeSize = H5T.getSize(typeId);
                Console.WriteLine("typeSize is 0", typeSize);

                // Set the order to big endian
                H5T.setOrder(typeId, H5T.Order.BE);

                // Set the order to little endian
                H5T.setOrder(typeId, H5T.Order.LE);

                // Create the data set.
                H5DataSetId dataSetId = H5D.create(fileId, "/csharpExample",
                    typeId, spaceId);

                // Write the integer data to the data set.

                H5D.write(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_INT),
                    new H5Array<int>(dset_data));

                // If we were writing a single value it might look like this.
                //  int singleValue = 100;
                //  H5D.writeScalar(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_INT),
                //     ref singleValue);

                // Create an integer array to receive the read data.
                int[] readDataBack = new int[DATA_ARRAY_LENGTH];

                // Read the integer data back from the data set
                H5D.read(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_INT),
                    new H5Array<int>(readDataBack));

                // Echo the data
                for (int i = 0; i < DATA_ARRAY_LENGTH; i++)
                
                    Console.WriteLine(readDataBack[i]);
                

                // Close all the open resources.
                H5D.close(dataSetId);

                // Reopen and close the data sets to show that we can.
                dataSetId = H5D.open(fileId, "/csharpExample");
                H5D.close(dataSetId);
                dataSetId = H5D.open(groupId, "/csharpExample");
                H5D.close(dataSetId);

                H5S.close(spaceId);
                H5T.close(typeId);
                H5G.close(groupId);

                //int x = 10;
                //H5T.enumInsert<int>(typeId, "myString", ref x);
                //H5G.close(groupId);
                H5GIterateCallback myDelegate;
                myDelegate = myFunction;
                int x = 9;
                int start = 0;
                int index = H5G.iterate(fileId, "/cSharpGroup",myDelegate, x, ref start);

                // Reopen the group id to show that we can.
                groupId = H5G.open(fileId, "/cSharpGroup");
                H5G.close(groupId);

                H5F.close(fileId);

                // Reopen and reclose the file.
                H5FileId openId = H5F.open("myCSharp.h5",
                    H5F.OpenMode.ACC_RDONLY);
                H5F.close(openId);
            
                // This catches all the HDF exception classes.  Because each call
                // generates unique exception, different exception can be handled
                // separately.  For example, to catch open errors we could have used
                // catch (H5FopenException openException).
            catch (HDFException e)
            
                Console.WriteLine(e.Message);
            

            Console.WriteLine("Processing complete!");
            Console.ReadLine();

        
    

【讨论】:

【参考方案4】:

我知道这已经过时了,但对于仍然需要处理 HDF5 文件的任何人,我都有一个 C# 包装器,它封装了 github 的大部分操作(基于其他人的原创作品)。

unit tes 项目中有很多例子。

【讨论】:

以上是关于HDF5 示例代码的主要内容,如果未能解决你的问题,请参考以下文章

使用 Java Native Library 在 HDF5 中编写交错数组

在 hdf5save 中保存会创建一个不可读的文件

MATLAB中无限hdf5文件的效率

KeyError:“无法打开对象(对象'示例'不存在)”

如何检查文件是不是为有效的 HDF5 文件?

HDF5没有将所有数据写入文件