Note
Go to the end to download the full example code.
Annotating and Converting the Radial Magnetic Field#
Read the radial magnetic field dataset from HDF4, attach physically meaningful metadata, and produce a PSI-convention HDF5 file.
This example walks through a realistic data-preparation workflow:
Read the radial magnetic field (Br) data and its coordinate scales from the example HDF4 file.
Attach attributes that describe the physical quantity, coordinate system, and units using types compatible with both HDF4 and HDF5.
Write an annotated HDF4 file.
Convert that file to HDF5 using
convert_psih4_to_psih5(), which preserves the attached attributes in the output.
Note
This example can be amended to include additional or domain-specific metadata once the basic pipeline is confirmed to work end-to-end.
import tempfile
from pathlib import Path
import numpy as np
from psi_io import read_hdf_data, write_hdf_data, read_hdf_meta, convert_psih4_to_psih5, data
Step 1 – Read the source HDF4 file
Fetch the example radial magnetic field file and load the primary dataset together with its (r, θ, φ) coordinate scales:
br_filepath = data.get_3d_data(hdf=".hdf")
print(f"Source file : {Path(br_filepath).name}")
br_data, r, t, p = read_hdf_data(br_filepath)
print(f"\nData shape : {br_data.shape} (nφ × nθ × nr, Fortran-ordered)")
print(f"r scale : {r.shape}, range = [{r[0]:.4f}, {r[-1]:.4f}] R☉")
print(f"θ scale : {t.shape}, range = [{t[0]:.4f}, {t[-1]:.4f}] rad")
print(f"φ scale : {p.shape}, range = [{p[0]:.4f}, {p[-1]:.4f}] rad")
Source file : br.hdf
Data shape : (181, 100, 151) (nφ × nθ × nr, Fortran-ordered)
r scale : (151,), range = [0.9996, 30.5116] R☉
θ scale : (100,), range = [0.0000, 3.1416] rad
φ scale : (181,), range = [0.0000, 6.2832] rad
Step 2 – Define the attributes
All attribute values are chosen to be compatible with HDF4’s SDC type system:
float32 and int32 scalars for numeric quantities, and plain Python
strings for descriptive fields. float16, int64, and uint64 are
not supported by HDF4 and must be avoided (see the
Writing Datasets with Attributes
example for a full discussion of type restrictions):
br_attrs = dict(
variable="br",
long_name="Radial Magnetic Field",
coord_system="Carrington",
r_units="R_sun",
angle_units="radians",
b_scale=np.float32(2.2047), # reference field scale [Gauss]
cr_number=np.int32(2190), # Carrington rotation number
)
Step 3 – Write an annotated HDF4 file
Pass the attributes as keyword arguments to write_hdf_data().
The dataset identifier is omitted so the PSI-standard name 'Data-Set-2' is
used, which is required by convert_psih4_to_psih5() in
the next step:
_tmp = tempfile.TemporaryDirectory()
tmpdir = Path(_tmp.name)
annotated_hdf = tmpdir / "br_annotated.hdf"
write_hdf_data(annotated_hdf, br_data, r, t, p, **br_attrs)
print(f"Annotated HDF4 written : {annotated_hdf.name}")
Annotated HDF4 written : br_annotated.hdf
Step 4 – Convert to PSI-convention HDF5
convert_psih4_to_psih5() reads 'Data-Set-2' from the
HDF4 file, remaps it to 'Data', and carries over the attached attributes:
annotated_h5 = tmpdir / "br_annotated.h5"
convert_psih4_to_psih5(annotated_hdf, annotated_h5)
print(f"Converted to HDF5 : {annotated_h5.name}")
Converted to HDF5 : br_annotated.h5
Step 5 – Verify the round-trip
Confirm that the dataset, scales, and all attributes survived the write-and-convert pipeline intact:
meta = read_hdf_meta(annotated_h5)
print(f"\nDataset : {meta[0].name!r} shape={meta[0].shape} dtype={meta[0].type}")
print("\nAttributes:")
for key, val in meta[0].attr.items():
print(f" {key:<16}: {val!r}")
print("\nScales:")
for s in meta[0].scales:
print(f" {s.name!r:<8} shape={s.shape} "
f"range=[{s.imin:.4f}, {s.imax:.4f}]")
_tmp.cleanup()
Dataset : 'Data' shape=(181, 100, 151) dtype=float32
Attributes:
DIMENSION_LABELS: array(['dim1', 'dim2', 'dim3'], dtype=object)
DIMENSION_LIST : array([array([<HDF5 object reference>], dtype=object),
array([<HDF5 object reference>], dtype=object),
array([<HDF5 object reference>], dtype=object)], dtype=object)
angle_units : 'radians'
b_scale : np.float64(2.204699993133545)
coord_system : 'Carrington'
cr_number : np.int64(2190)
long_name : 'Radial Magnetic Field'
r_units : 'R_sun'
variable : 'br'
Scales:
'dim1' shape=(151,) range=[0.9996, 30.5116]
'dim2' shape=(100,) range=[0.0000, 3.1416]
'dim3' shape=(181,) range=[0.0000, 6.2832]
Total running time of the script: (0 minutes 0.049 seconds)