如何将gro轨迹数据拆分写入HDF5多组并解决盒尺寸写入报错
问题原因
- 页脚行解析格式错误:你定义的
fmtstring1会把最后一行解析出6个字段,其中前3个是无效的空白值,直接将6个字段的数组往目标位置写入时形状不匹配,触发报错。实际上最后一行仅包含3个箱型参数浮点值,无需复杂的struct解析,直接分割字符串转浮点即可。 - 重复创建数据集错误:你在每轮循环中都调用
create_dataset创建同名的box_size数据集,HDF5不允许同组下存在重名数据集,首次循环可正常执行,第二次循环就会触发错误。应该和粒子位置数据集的逻辑一致,首次迭代时创建可扩容的数据集,后续迭代仅追加数据。 - 数据集形状定义错误:你之前注释中的box数据集形状设为
(0, nparticles, 3)完全不符合需求,箱型参数每帧仅3个值,正确形状应为(帧数, 3)。 - 关联逻辑缺失:你提前创建了
edge组下的time、step数据集,但没有写入对应数据,无法和箱型参数关联。
修改后的可运行代码
import struct import numpy as np import h5py import re # gro文件转h5文件逻辑 csv_file = 'com' fmtstring = '7s 8s 5s 7s 7s 7s' fieldstruct = struct.Struct(fmtstring) parse = fieldstruct.unpack_from with open(csv_file, 'r') as f, \ h5py.File('xaa_trial.h5', 'w') as hdf: # 粒子组及属性定义 particles_grp = hdf.require_group('particles/lipids/positions') box_grp = particles_grp.create_group('box') dim_grp = box_grp.create_group('dimension') dim_grp.attrs['dimension'] = 3 bound_grp = box_grp.create_group('boundary') bound_grp.attrs['boundary'] = ['periodic', 'periodic', 'periodic'] edge_grp = box_grp.create_group('edges') edge_ds_time = edge_grp.create_dataset('time', dtype='f', shape=(0,), maxshape=(None,), compression='gzip', shuffle=True) edge_ds_step = edge_grp.create_dataset('step', dtype=np.uint64, shape=(0,), maxshape=(None,), compression='gzip', shuffle=True) edge_ds_value = None # H5MD组及属性定义 h5md_grp = hdf.require_group('h5md/version/author/creator') h5md_grp.attrs['version'] = 1.0 h5md_grp.attrs['author'] = 'rohit' h5md_grp.attrs['creator'] = 'known' # 粒子位置相关数据集定义 ds_time = particles_grp.create_dataset('time', dtype="f", shape=(0,), maxshape=(None,), compression='gzip', shuffle=True) ds_step = particles_grp.create_dataset('step', dtype=np.uint64, shape=(0,), maxshape=(None,), compression='gzip', shuffle=True) ds_value = None step = 0 while True: header = f.readline() m = re.search("t= *(.*)$", header) if m: time = float(m.group(1)) else: print("End Of File") break # 读取粒子数 nparticles = int(f.readline()) # 读取所有粒子位置数据 arr = np.empty(shape=(nparticles, 3), dtype=np.float32) for row in range(nparticles): fields = parse( f.readline().encode('utf-8') ) arr[row] = np.array((float(fields[3]), float(fields[4]), float(fields[5]))) if nparticles > 0: # 首次迭代创建可扩容的粒子位置数据集 if not ds_value: ds_value = particles_grp.create_dataset('value', dtype=np.float32, shape=(0, nparticles, 3), maxshape=(None, nparticles, 3), chunks=(1, nparticles, 3), compression='gzip', shuffle=True) # 追加当前帧粒子数据 ds_time.resize(step + 1, axis=0) ds_step.resize(step + 1, axis=0) ds_value.resize(step + 1, axis=0) ds_time[step] = time ds_step[step] = step ds_value[step] = arr # 处理页脚箱型参数 footer_line = f.readline().strip() box_arr = np.array(list(map(float, footer_line.split())), dtype=np.float32) # 首次迭代创建箱型参数数据集 if not edge_ds_value: edge_ds_value = edge_grp.create_dataset('value', dtype=np.float32, shape=(0, 3), maxshape=(None, 3), chunks=(1, 3), compression='gzip', shuffle=True) # 追加当前帧箱型参数和对应的step、time edge_ds_time.resize(step + 1, axis=0) edge_ds_step.resize(step + 1, axis=0) edge_ds_value.resize(step + 1, axis=0) edge_ds_time[step] = time edge_ds_step[step] = step edge_ds_value[step] = box_arr step += 1
内容的提问来源于stack exchange,提问作者Mahesh
相关产品推荐
相关产品推荐

