【问题标题】:How to create datasets within a group in hdf5 file?如何在 hdf5 文件中的组内创建数据集?
【发布时间】:2021-11-09 16:33:45
【问题描述】:

我想创建一个路径为“粒子/脂质/位置”的组,其中包含两个数据集,例如粒子是主要组,脂质是包含脂质名称的数据集,位置将包含每个帧中脂质的位置。我尝试了这个,但在之前的答案code source 的代码的第 40 行中出现以下错误:

 ValueError: Unable to create group (name already exists)

import struct
import numpy as np
import h5py

csv_file = 'com'

fmtstring = '7s 8s 5s 7s 7s 7s'
fieldstruct = struct.Struct(fmtstring)
parse = fieldstruct.unpack_from

#define a np.dtype for gro array/dataset (hard-coded for now)
gro_dt = np.dtype([('col1', 'S7'), ('col2', 'S8'), ('col3', int), 
                   ('col4', float), ('col5', float), ('col6', float)])

with open(csv_file, 'r') as f, \
     h5py.File('xaa.h5', 'w') as hdf:
         
    step = 0
    while True:         
        header = f.readline()
        if not header:
            print("End Of File")
            break
        else:
            print(header)

        # get number of data rows
        no_rows = int(f.readline())
        arr = np.empty(shape=(no_rows,), dtype=gro_dt)
        for row in range(no_rows):
            fields = parse( f.readline().encode('utf-8') )
            arr[row]['col1'] = fields[0].strip()            
            arr[row]['col2'] = fields[1].strip()            
            arr[row]['col3'] = int(fields[2])
            arr[row]['col4'] = float(fields[3])
            arr[row]['col5'] = float(fields[4])
            arr[row]['col6'] = float(fields[5])
        if arr.shape[0] > 0:
            # Create a froup to store positions
            particles_grp = hdf.create_group('particles/lipids/positions')
            # create a dataset for THIS time step
            ds= particles_grp.create_dataset(f'dataset_{step:04}', data=arr,compression='gzip') 
            #ds= hdf.create_dataset(f'dataset_{step:04}', data=arr,compression='gzip') 
            #create attributes for this dataset / time step
            hdr_tokens = header.split()
            particles_grp['ds'] = ds
            ds.attrs['raw_header'] = header
            #ds.attrs['Generated by'] = hdr_tokens[2]
            #ds.attrs['P/L'] = hdr_tokens[4].split('=')[1]
            ds.attrs['Time'] = hdr_tokens[6]
            
        footer = f.readline()
        step += 1

小数据文件链接在这里data file。在本代码中,每一帧都存储在 dataset1、2...中。我希望将这些数据集存储在粒子组中。我不太确定这是否是以后最好的方法,因为我想使用这些框架进行进一步的计算!谢谢!!

【问题讨论】:

  • 这里的脂质是什么?

标签: python hdf5 h5py


【解决方案1】:

如上一个答案所述,您尝试使用此函数在 while 循环内创建相同的组:
particles_grp = hdf.create_group('particles/lipids/positions')
您第二次调用它时会收到错误(b/c 该组已经退出)。

改为使用此函数创建组对象:
particles_grp = hdf.require_group('particles/lipids/positions')

require_group() 很聪明(而且很有用)。如果该组不存在,它将创建它。而且,当组已经存在时,它会简单地返回组对象。

对您的代码进行更改,无需其他更改即可使用。

或者,您可以将create_group() 调用移动到while True: 循环之上(因此它只被调用一次)。

【讨论】:

  • 啊,太好了,我不知道require_group(),我已经有一段时间没有接触HDF5了!
  • 还有一个 require_dataset() :-) 两者都对这些场景很有用。
【解决方案2】:

你正在运行这行代码:

particles_grp = hdf.create_group('particles/lipids/positions')

在你的 while 循环中。这意味着您试图在 hdf5 文件中多次创建组,这是不可能的(因为名称是硬编码的)。试试这样的。

with open(csv_file, 'r') as f, \
     h5py.File('xaa.h5', 'w') as hdf:
    # Create a froup to store positions
    particles_grp = hdf.create_group('particles/lipids/positions')
    step = 0
    while True:         
        header = f.readline()
        if not header:
            print("End Of File")
            break
        else:
            print(header)

        # get number of data rows
        no_rows = int(f.readline())
        arr = np.empty(shape=(no_rows,), dtype=gro_dt)
        for row in range(no_rows):
            fields = parse( f.readline().encode('utf-8') )
            arr[row]['col1'] = fields[0].strip()            
            arr[row]['col2'] = fields[1].strip()            
            arr[row]['col3'] = int(fields[2])
            arr[row]['col4'] = float(fields[3])
            arr[row]['col5'] = float(fields[4])
            arr[row]['col6'] = float(fields[5])
        if arr.shape[0] > 0:
            # create a dataset for THIS time step
            ds= particles_grp.create_dataset(f'dataset_{step:04}', data=arr,compression='gzip') 
            #ds= hdf.create_dataset(f'dataset_{step:04}', data=arr,compression='gzip') 
            #create attributes for this dataset / time step
            hdr_tokens = header.split()
            particles_grp['ds'] = ds
            ds.attrs['raw_header'] = header
            #ds.attrs['Generated by'] = hdr_tokens[2]
            #ds.attrs['P/L'] = hdr_tokens[4].split('=')[1]
            ds.attrs['Time'] = hdr_tokens[6]
            
        footer = f.readline()
        step += 1

我认为这是错误消息中的问题,试一试,让我知道它是否有效。

HDF5 使用类似于您的文件系统的分层文件结构。想象一下,您正在尝试创建两个同名的目录(文件夹)。您只能拥有一个相同的文件夹。所以先创建组或文件夹,然后将文件(数据集)放入组中。

编辑:看起来你会在这里遇到另一个问题

particles_grp['ds'] = ds

您需要为组中的数据集创建自定义名称,因为您不能有 2 个相同的名称。

试试这样的:

particles_grp[f'dataset_{step:04}'] = ds

【讨论】:

  • 您的初始答案有效,但您的编辑答案引发错误 RuntimeError: Unable to create link (name already exists)
  • 初始更改是否会导致任何错误?
猜你喜欢
  • 2019-02-04
  • 2011-03-29
  • 1970-01-01
  • 2015-05-18
  • 2018-11-20
  • 2014-03-04
  • 2020-09-12
  • 2021-12-24
  • 1970-01-01
相关资源
最近更新 更多