【问题标题】:C++: reading a numpy array of complex numbers from an hdf5 fileC ++:从hdf5文件中读取一个numpy复数数组
【发布时间】:2016-02-10 20:10:12
【问题描述】:

正如标题所说,我想从 c++ 中的 hdf5 文件中读取数据集。数据集是用 h5py 编写的。它包含一个 numpy 复数数组。

我可以正确检测出数组的总维数

using namespace H5;
std::string file_name = "/path/to/my/file.hdf5";
std::string dataset_name = "dataset_name";
H5File file(file_name, H5F_ACC_RDONLY);
DataSet dset = file.openDataSet(dataset_name);
DataSpace dspace = dset.getSpace();
int size = dspace.getSimpleExtentNpoints();

我可以准备一个vector

std::vector<std::complex<double>> out_vector(size);

如何读取数据集?

dset.read(out_vector.data(), ???);

【问题讨论】:

  • 很好,你已经陈述了你的要求。下一步究竟是什么?开始设计实现或在 Stack Overflow 上提问? (提示:后者不太可能导致生产就绪的结果)。另外别忘了问一个问题,我找不到。
  • 我试图直截了当,但我认为我的草稿解决方案对知道这个问题的人没有帮助。无论如何,我很高兴发布我的尝试。

标签: c++ hdf5 h5py


【解决方案1】:

HDF5 API 没有复杂的DataType。 python API 也没有。但是,h5py 会自动创建一个包含双精度对的复合类型。 h5dump /path/to/my/file.hdf5 显示它:

DATATYPE  H5T_COMPOUND {
   H5T_IEEE_F64LE "r";
   H5T_IEEE_F64LE "i"  
}

在 c++ 中,必须手动创建兼容的复合数据类型。例如:

CompType complex_data_type(sizeof(out_vector[0]));
complex_data_type.insertMember( "r", 0, PredType::NATIVE_DOUBLE);
complex_data_type.insertMember( "i", sizeof(double), PredType::NATIVE_DOUBLE);

现在可以读取DataSet

dset.read(out_vector.data(), complex_data_type);

【讨论】:

    【解决方案2】:

    https://support.hdfgroup.org/ 上有一个示例,解释了如何处理 HDF5 C++ API 1.10.1 的复合数据类型(不仅是复杂的):

    https://support.hdfgroup.org/HDF5/doc/cpplus_RM/compound_8cpp-example.html

    需要为 complex 定义复合类型:

    typedef struct complex_type{
                    double r;
                    double i;
                } complex_type;
    
    H5::CompType complex_compound( sizeof(complex_type) );
    complex_compound.insertMember("r", HOFFSET(complex_type, r), H5::PredType::NATIVE_DOUBLE);
    complex_compound.insertMember("i", HOFFSET(complex_type, i), H5::PredType::NATIVE_DOUBLE);
    

    这是完整的代码:

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * Copyright by The HDF Group.                                               *
     * Copyright by the Board of Trustees of the University of Illinois.         *
     * All rights reserved.                                                      *
     *                                                                           *
     * This file is part of HDF5.  The full HDF5 copyright notice, including     *
     * terms governing use, modification, and redistribution, is contained in    *
     * the COPYING file, which can be found at the root of the source code       *
     * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
     * If you do not have access to either file, you may request a copy from     *
     * help@hdfgroup.org.                                                        *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    /*
     * This example shows how to create a compound datatype,
     * write an array which has the compound datatype to the file,
     * and read back fields' subsets.
     */
    #ifdef OLD_HEADER_FILENAME
    #include <iostream.h>
    #else
    #include <iostream>
    #endif
    using std::cout;
    using std::endl;
    #include <string>
    #include "H5Cpp.h"
    using namespace H5;
    const H5std_string FILE_NAME( "SDScompound.h5" );
    const H5std_string DATASET_NAME( "ArrayOfStructures" );
    const H5std_string MEMBER1( "a_name" );
    const H5std_string MEMBER2( "b_name" );
    const H5std_string MEMBER3( "c_name" );
    const int   LENGTH = 10;
    const int   RANK = 1;
    int main(void)
    {
       /* First structure  and dataset*/
       typedef struct s1_t {
        int    a;
        float  b;
        double c;
       } s1_t;
       /* Second structure (subset of s1_t)  and dataset*/
       typedef struct s2_t {
        double c;
        int    a;
       } s2_t;
       // Try block to detect exceptions raised by any of the calls inside it
       try
       {
          /*
           * Initialize the data
           */
          int  i;
          s1_t s1[LENGTH];
          for (i = 0; i< LENGTH; i++)
          {
             s1[i].a = i;
             s1[i].b = i*i;
             s1[i].c = 1./(i+1);
          }
          /*
           * Turn off the auto-printing when failure occurs so that we can
           * handle the errors appropriately
           */
          Exception::dontPrint();
          /*
           * Create the data space.
           */
          hsize_t dim[] = {LENGTH};   /* Dataspace dimensions */
          DataSpace space( RANK, dim );
          /*
           * Create the file.
           */
          H5File* file = new H5File( FILE_NAME, H5F_ACC_TRUNC );
          /*
           * Create the memory datatype.
           */
          CompType mtype1( sizeof(s1_t) );
          mtype1.insertMember( MEMBER1, HOFFSET(s1_t, a), PredType::NATIVE_INT);
          mtype1.insertMember( MEMBER3, HOFFSET(s1_t, c), PredType::NATIVE_DOUBLE);
          mtype1.insertMember( MEMBER2, HOFFSET(s1_t, b), PredType::NATIVE_FLOAT);
          /*
           * Create the dataset.
           */
          DataSet* dataset;
          dataset = new DataSet(file->createDataSet(DATASET_NAME, mtype1, space));
          /*
           * Write data to the dataset;
           */
          dataset->write( s1, mtype1 );
          /*
           * Release resources
           */
          delete dataset;
          delete file;
          /*
           * Open the file and the dataset.
           */
          file = new H5File( FILE_NAME, H5F_ACC_RDONLY );
          dataset = new DataSet (file->openDataSet( DATASET_NAME ));
          /*
           * Create a datatype for s2
           */
          CompType mtype2( sizeof(s2_t) );
          mtype2.insertMember( MEMBER3, HOFFSET(s2_t, c), PredType::NATIVE_DOUBLE);
          mtype2.insertMember( MEMBER1, HOFFSET(s2_t, a), PredType::NATIVE_INT);
          /*
           * Read two fields c and a from s1 dataset. Fields in the file
           * are found by their names "c_name" and "a_name".
           */
          s2_t s2[LENGTH];
          dataset->read( s2, mtype2 );
          /*
           * Display the fields
           */
          cout << endl << "Field c : " << endl;
          for( i = 0; i < LENGTH; i++)
         cout << s2[i].c << " ";
          cout << endl;
          cout << endl << "Field a : " << endl;
          for( i = 0; i < LENGTH; i++)
         cout << s2[i].a << " ";
          cout << endl;
          /*
           * Create a datatype for s3.
           */
          CompType mtype3( sizeof(float) );
          mtype3.insertMember( MEMBER2, 0, PredType::NATIVE_FLOAT);
          /*
           * Read field b from s1 dataset. Field in the file is found by its name.
           */
          float s3[LENGTH];  // Third "structure" - used to read float field of s1
          dataset->read( s3, mtype3 );
          /*
           * Display the field
           */
          cout << endl << "Field b : " << endl;
          for( i = 0; i < LENGTH; i++)
         cout << s3[i] << " ";
          cout << endl;
          /*
           * Release resources
           */
          delete dataset;
          delete file;
       }  // end of try block
       // catch failure caused by the H5File operations
       catch( FileIException error )
       {
          error.printError();
          return -1;
       }
       // catch failure caused by the DataSet operations
       catch( DataSetIException error )
       {
          error.printError();
          return -1;
       }
       // catch failure caused by the DataSpace operations
       catch( DataSpaceIException error )
       {
          error.printError();
          return -1;
       }
       // catch failure caused by the DataSpace operations
       catch( DataTypeIException error )
       {
          error.printError();
          return -1;
       }
       return 0;
    }
    

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    • 我用相应的代码编辑了我的答案。我采用了整个代码,因为我认为所有包含的信息对于在 HDF5 中读取/写入复杂数据集都很重要。
    猜你喜欢
    • 2017-09-23
    • 2018-03-25
    • 2021-03-23
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 2017-09-24
    • 2015-11-02
    相关资源
    最近更新 更多