from pathlib import Path
from typing import Union
import h5py
import numpy
[docs]
def assert_hdf5_content(path: Union[str, Path], data: Union[str, dict], nspectra: int):
if isinstance(data, str):
if data == "full_larch":
data = _FULL_LARCH_RESULT
elif data == "full_pymca":
data = _FULL_PYMCA_RESULT
elif data == "full_larch_noise":
data = _FULL_LARCH_NOISE_RESULT
else:
raise ValueError(f"{data!r} is not a known expected HDF5 structure")
expected = _generate_expected(data, nspectra)
with h5py.File(path, "r") as f:
actual = _extract_hdf5_tree("", f)
assert actual == expected
def _generate_expected(data: dict, nspectra: int) -> dict:
expected = {"@NX_class": "NXroot"}
for i in range(nspectra):
j = i + 1
expected[f"1.{j}"] = {
f"1.{j}@NX_class": "NXentry",
f"1.{j}@default": "data",
**data,
}
return expected
def _extract_hdf5_tree(name: str, obj: Union[h5py.Group, h5py.Dataset]):
result = {}
for attr_name, attr_value in obj.attrs.items():
if isinstance(attr_value, numpy.ndarray):
attr_value = attr_value.tolist()
result[f"{name}@{attr_name}"] = attr_value
if isinstance(obj, h5py.Dataset):
return result
for name, child in obj.items():
result[name] = _extract_hdf5_tree(name, child)
return result
_FULL_LARCH_RESULT = {
"data": {
"data@NX_class": "NXdata",
"data@auxiliary_signals": ["pre_edge", "post_edge"],
"data@axes": ["energy"],
"data@signal": "mu",
"energy": {
"energy@long_name": "Energy (eV)",
"energy@units": "eV",
},
"mu": {"mu@long_name": "μ"},
"post_edge": {},
"pre_edge": {},
},
"results": {
"results@NX_class": "NXprocess",
"date": {},
"program": {},
"exafs": {
"chi": {"chi@long_name": "χ"},
"chi_weighted_k": {
"chi_weighted_k@long_name": "k^0 χ (Å^-0)",
"chi_weighted_k@units": "Å^-0",
},
"exafs@NX_class": "NXdata",
"exafs@auxiliary_signals": ["chi_weighted_k"],
"exafs@axes": ["k"],
"exafs@signal": "chi",
"k": {
"k@long_name": "Wavenumber (Å^-1)",
"k@units": "Å^-1",
},
},
"ft": {
"ft@NX_class": "NXdata",
"ft@auxiliary_signals": ["real", "imaginary"],
"ft@axes": ["radius"],
"ft@signal": "intensity",
"imaginary": {
"imaginary@long_name": "Im[FT(R)] (Å^-1)",
"imaginary@units": "Å^-1",
},
"intensity": {
"intensity@long_name": "|FT(R)| (Å^-1)",
"intensity@units": "Å^-1",
},
"radius": {
"radius@long_name": "Radius (Å)",
"radius@units": "Å",
},
"real": {
"real@long_name": "Re[FT(R)] (Å^-1)",
"real@units": "Å^-1",
},
},
"larch": {
"bkg": {"bkg@long_name": "Background μ(E)"},
"larch@NX_class": "NXparameters",
"xftf_k_max": {},
"xftf_k_min": {},
"xftf_k_weight": {},
},
"normalized": {
"energy": {
"energy@long_name": "Energy (eV)",
"energy@units": "eV",
},
"flatten_mu": {"flatten_mu@long_name": "Flat(μ)"},
"normalized@NX_class": "NXdata",
"normalized@auxiliary_signals": ["normalized_mu"],
"normalized@axes": ["energy"],
"normalized@signal": "flatten_mu",
"normalized_mu": {"normalized_mu@long_name": "Norm(μ)"},
},
"statistics": {
"statistics@NX_class": "NXparameters",
"e0": {
"e0@long_name": "Edge Energy (eV)",
"e0@units": "eV",
},
"edge_step": {},
},
},
}
_FULL_LARCH_NOISE_RESULT = {
"data": {
"data@NX_class": "NXdata",
"data@auxiliary_signals": ["pre_edge", "post_edge"],
"data@axes": ["energy"],
"data@signal": "mu",
"energy": {
"energy@long_name": "Energy (eV)",
"energy@units": "eV",
},
"mu": {"mu@long_name": "μ"},
"post_edge": {},
"pre_edge": {},
},
"results": {
"results@NX_class": "NXprocess",
"date": {},
"program": {},
"exafs": {
"chi": {"chi@long_name": "χ"},
"chi_weighted_k": {
"chi_weighted_k@long_name": "k^0 χ (Å^-0)",
"chi_weighted_k@units": "Å^-0",
},
"exafs@NX_class": "NXdata",
"exafs@auxiliary_signals": ["chi_weighted_k"],
"exafs@axes": ["k"],
"exafs@signal": "chi",
"k": {
"k@long_name": "Wavenumber (Å^-1)",
"k@units": "Å^-1",
},
},
"ft": {
"ft@NX_class": "NXdata",
"ft@auxiliary_signals": ["real", "imaginary"],
"ft@axes": ["radius"],
"ft@signal": "intensity",
"imaginary": {
"imaginary@long_name": "Im[FT(R)] (Å^-1)",
"imaginary@units": "Å^-1",
},
"intensity": {
"intensity@long_name": "|FT(R)| (Å^-1)",
"intensity@units": "Å^-1",
},
"radius": {
"radius@long_name": "Radius (Å)",
"radius@units": "Å",
},
"real": {
"real@long_name": "Re[FT(R)] (Å^-1)",
"real@units": "Å^-1",
},
},
"larch": {
"bkg": {"bkg@long_name": "Background μ(E)"},
"larch@NX_class": "NXparameters",
"xftf_k_max": {},
"xftf_k_min": {},
"xftf_k_weight": {},
},
"noise": {
"energy": {
"energy@long_name": "Energy (eV)",
"energy@units": "eV",
},
"noise@NX_class": "NXdata",
"noise@axes": ["energy"],
"noise@signal": "noise_savgol",
"noise_savgol": {
"noise_savgol@long_name": "Noise(μ)",
},
},
"normalized": {
"energy": {
"energy@long_name": "Energy (eV)",
"energy@units": "eV",
},
"flatten_mu": {"flatten_mu@long_name": "Flat(μ)"},
"normalized@NX_class": "NXdata",
"normalized@auxiliary_signals": ["normalized_mu"],
"normalized@axes": ["energy"],
"normalized@signal": "flatten_mu",
"normalized_mu": {"normalized_mu@long_name": "Norm(μ)"},
},
"statistics": {
"statistics@NX_class": "NXparameters",
"e0": {
"e0@long_name": "Edge Energy (eV)",
"e0@units": "eV",
},
"edge_step": {},
"noise_e_max": {},
"noise_e_min": {},
"norm_noise_savgol": {},
"raw_noise_savgol": {},
},
},
}
_FULL_PYMCA_RESULT = {
"data": {
"data@NX_class": "NXdata",
"data@auxiliary_signals": ["pre_edge", "post_edge"],
"data@axes": ["energy"],
"data@signal": "mu",
"energy": {
"energy@long_name": "Energy (eV)",
"energy@units": "eV",
},
"mu": {"mu@long_name": "μ"},
"post_edge": {},
"pre_edge": {},
},
"results": {
"results@NX_class": "NXprocess",
"date": {},
"program": {},
"exafs": {
"chi": {"chi@long_name": "χ"},
"exafs@NX_class": "NXdata",
"exafs@axes": ["k"],
"exafs@signal": "chi",
"k": {
"k@long_name": "Wavenumber (Å^-1)",
"k@units": "Å^-1",
},
},
"ft": {
"ft@NX_class": "NXdata",
"ft@auxiliary_signals": ["real", "imaginary"],
"ft@axes": ["radius"],
"ft@signal": "intensity",
"imaginary": {
"imaginary@long_name": "Im[FT(R)] (Å^-(n+1))",
"imaginary@units": "Å^-(n+1)",
},
"intensity": {
"intensity@long_name": "|FT(R)| (Å^-(n+1))",
"intensity@units": "Å^-(n+1)",
},
"radius": {
"radius@long_name": "Radius (Å)",
"radius@units": "Å",
},
"real": {
"real@long_name": "Re[FT(R)] (Å^-(n+1))",
"real@units": "Å^-(n+1)",
},
},
"normalized_enorm": {
"normalized_energy": {
"normalized_energy@long_name": "Normalized energy (eV)",
"normalized_energy@units": "eV",
},
"normalized_enorm@NX_class": "NXdata",
"normalized_enorm@axes": ["normalized_energy"],
"normalized_enorm@signal": "normalized_mu",
"normalized_mu": {
"normalized_mu@long_name": "Norm(μ)",
},
},
"pymca": {
"EXAFSNormalized": {"EXAFSNormalized@long_name": "χ(k)"},
"KMax": {},
"KMin": {},
"KWeight": {},
"KnotsX": {"KnotsX@long_name": "Knots X"},
"KnotsY": {"KnotsY@long_name": "Knots Y"},
"PostEdgeB": {"PostEdgeB@long_name": "Post-edge background"},
"PostEdgeK": {
"PostEdgeK@long_name": "Wavenumber (Å^-1)",
"PostEdgeK@units": "Å^-1",
},
"pymca@NX_class": "NXparameters",
},
"raw_enorm": {
"mu": {"mu@long_name": "μ"},
"normalized_energy": {
"normalized_energy@long_name": "Normalized energy (eV)",
"normalized_energy@units": "eV",
},
"post_edge": {},
"pre_edge": {},
"raw_enorm@NX_class": "NXdata",
"raw_enorm@auxiliary_signals": ["pre_edge", "post_edge"],
"raw_enorm@axes": ["normalized_energy"],
"raw_enorm@signal": "mu",
},
"statistics": {
"statistics@NX_class": "NXparameters",
"e0": {
"e0@long_name": "Edge Energy (eV)",
"e0@units": "eV",
},
},
},
}