Source code for io_operations.hdf5_handler
"""Helper module for reading and writing in hd5 format."""
import logging
from pathlib import PosixPath
import astropy.units as u
import tables
from astropy.table import Table
from ctapipe.io import read_table
from simtools.utils.names import sanitize_name
__all__ = [
"fill_hdf5_table",
"read_hdf5",
]
_logger = logging.getLogger(__name__)
[docs]
def fill_hdf5_table(hist, x_bin_edges, y_bin_edges, x_label, y_label, meta_data):
"""
Create and fill an hdf5 table with the histogram information.
It works for both 1D and 2D distributions.
Parameters
----------
hist: numpy.ndarray
The counts of the histograms.
x_bin_edges: numpy.array
The x bin edges of the histograms.
y_bin_edges: numpy.array
The y bin edges of the histograms.
Use None for 1D histograms.
x_label: str
X bin edges label.
y_label: str
Y bin edges label.
Use None for 1D histograms.
meta_data: dict
Dictionary with the histogram metadata.
"""
# Complement metadata
if x_label is not None:
meta_data["x_bin_edges"] = sanitize_name(x_label)
meta_data["x_bin_edges_unit"] = (
x_bin_edges.unit if isinstance(x_bin_edges, u.Quantity) else u.dimensionless_unscaled
)
if y_bin_edges is not None:
if y_label is not None:
meta_data["y_bin_edges"] = sanitize_name(y_label)
names = [
f"{meta_data['y_bin_edges'].split('__')[0]}_{i}"
for i in range(len(y_bin_edges[:-1]))
]
else:
names = [
f"{meta_data['Title'].split('__')[0]}_{i}" for i in range(len(y_bin_edges[:-1]))
]
meta_data["y_bin_edges_unit"] = (
y_bin_edges.unit if isinstance(y_bin_edges, u.Quantity) else u.dimensionless_unscaled
)
table = Table(
[hist[i, :] for i in range(len(y_bin_edges[:-1]))],
names=names,
meta=meta_data,
)
else:
if x_label is not None:
meta_data["x_bin_edges"] = sanitize_name(x_label)
names = meta_data["x_bin_edges"]
else:
names = meta_data["Title"]
table = Table(
[
x_bin_edges[:-1],
hist,
],
names=(names, sanitize_name("Values")),
meta=meta_data,
)
return table
[docs]
def read_hdf5(hdf5_file_name):
"""
Read a hdf5 output file.
Parameters
----------
hdf5_file_name: str or Path
Name or Path of the hdf5 file to read from.
Returns
-------
list
The list with the astropy.Table instances for the various 1D and 2D histograms saved
in the hdf5 file.
"""
if isinstance(hdf5_file_name, PosixPath):
hdf5_file_name = hdf5_file_name.absolute().as_posix()
tables_list = []
with tables.open_file(hdf5_file_name, mode="r") as file:
for node in file.walk_nodes("/", "Table"):
table_path = node._v_pathname # pylint: disable=protected-access
table = read_table(hdf5_file_name, table_path)
tables_list.append(table)
return tables_list