1import numpy as np 2 3from yt.utilities.logger import ytLogger as mylog 4 5 6def parse_unit_dimension(unit_dimension): 7 r"""Transforms an openPMD unitDimension into a string. 8 9 Parameters 10 ---------- 11 unit_dimension : array_like 12 integer array of length 7 with one entry for the dimensional component of every 13 SI unit 14 15 [0] length L, 16 [1] mass M, 17 [2] time T, 18 [3] electric current I, 19 [4] thermodynamic temperature theta, 20 [5] amount of substance N, 21 [6] luminous intensity J 22 23 References 24 ---------- 25 26 https://github.com/openPMD/openPMD-standard/blob/latest/STANDARD.md#unit-systems-and-dimensionality 27 28 29 Returns 30 ------- 31 str 32 33 Examples 34 -------- 35 >>> velocity = [1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0] 36 >>> print(parse_unit_dimension(velocity)) 37 'm**1*s**-1' 38 39 >>> magnetic_field = [0.0, 1.0, -2.0, -1.0, 0.0, 0.0, 0.0] 40 >>> print(parse_unit_dimension(magnetic_field)) 41 'kg**1*s**-2*A**-1' 42 """ 43 if len(unit_dimension) != 7: 44 mylog.error("SI must have 7 base dimensions!") 45 unit_dimension = np.asarray(unit_dimension, dtype="int64") 46 dim = [] 47 si = ["m", "kg", "s", "A", "C", "mol", "cd"] 48 for i in np.arange(7): 49 if unit_dimension[i] != 0: 50 dim.append(f"{si[i]}**{unit_dimension[i]}") 51 return "*".join(dim) 52 53 54def is_const_component(record_component): 55 """Determines whether a group or dataset in the HDF5 file is constant. 56 57 Parameters 58 ---------- 59 record_component : h5py.Group or h5py.Dataset 60 61 Returns 62 ------- 63 bool 64 True if constant, False otherwise 65 66 References 67 ---------- 68 .. https://github.com/openPMD/openPMD-standard/blob/latest/STANDARD.md, 69 section 'Constant Record Components' 70 """ 71 return "value" in record_component.attrs.keys() 72 73 74def get_component(group, component_name, index=0, offset=None): 75 """Grabs a dataset component from a group as a whole or sliced. 76 77 Parameters 78 ---------- 79 group : h5py.Group 80 component_name : str 81 relative path of the component in the group 82 index : int, optional 83 first entry along the first axis to read 84 offset : int, optional 85 number of entries to read 86 if not supplied, every entry after index is returned 87 88 Notes 89 ----- 90 This scales every entry of the component with the respective "unitSI". 91 92 Returns 93 ------- 94 ndarray 95 (N,) 1D in case of particle data 96 (O,P,Q) 1D/2D/3D in case of mesh data 97 """ 98 record_component = group[component_name] 99 unit_si = record_component.attrs["unitSI"] 100 if is_const_component(record_component): 101 shape = np.asarray(record_component.attrs["shape"]) 102 if offset is None: 103 shape[0] -= index 104 else: 105 shape[0] = offset 106 # component is constant, craft an array by hand 107 return np.full(shape, record_component.attrs["value"] * unit_si) 108 else: 109 if offset is not None: 110 offset += index 111 # component is a dataset, return it (possibly masked) 112 return np.multiply(record_component[index:offset], unit_si) 113