Source code for simtel.simtel_io_metadata

#!/usr/bin/python3
"""Read metadata from sim_telarray files."""

import logging
from functools import cache

from eventio import EventIOFile
from eventio.simtel import HistoryMeta

_logger = logging.getLogger(__name__)


[docs] @cache def read_sim_telarray_metadata(file, encoding="utf8"): """ Return global and per-telescope metadata from sim_telarray file. Cached to avoid re-reading the file multiple times. Parameters ---------- file: str Path to the sim_telarray file. encoding: str Encoding to use for decoding metadata. Default is 'utf8'. Returns ------- global_meta: dict Global metadata dictionary. telescope_meta: dict Dictionary of telescope metadata, keyed by telescope ID. """ global_meta = None telescope_meta = {} with EventIOFile(file) as f: found_meta = False for o in f: if isinstance(o, HistoryMeta): found_meta = True else: if found_meta: break continue meta = _decode_dictionary(o.parse(), encoding=encoding) if o.header.id == -1: global_meta = meta else: telescope_meta[o.header.id] = meta def clean_meta(meta): """Clean metadata dictionary.""" meta = {k.lower().lstrip("*"): v for k, v in meta.items()} return {k: v.strip() if isinstance(v, str) else v for k, v in meta.items()} # keys to lower case and strip leading '*', trailing spaces return clean_meta(global_meta), { tel_id: clean_meta(meta) for tel_id, meta in telescope_meta.items() }
def _decode_dictionary(meta, encoding="utf8"): """Decode metadata dictionary.""" def safe_decode(byte_str, encoding, errors="ignore"): return byte_str.decode(encoding, errors=errors) try: return {k.decode(encoding, errors="ignore"): v.decode(encoding) for k, v in meta.items()} except UnicodeDecodeError as e: _logger.warning( f"Failed to decode metadata with encoding {encoding}: {e}. " "Falling back to 'utf-8' with errors='ignore'." ) return {safe_decode(k, encoding): safe_decode(v, encoding) for k, v in meta.items()}
[docs] def get_sim_telarray_telescope_id(telescope_name, file): """ Return the telescope ID for a given telescope name in a sim_telarray file. Translates e.g. 'LSTN-01' to the corresponding telescope ID. Parameters ---------- telescope_name: str Name of the telescope. file: str Path to the sim_telarray file. Returns ------- int, None Telescope ID. Returns None if not found. """ _, telescope_meta = read_sim_telarray_metadata(file) telescope_name_to_sim_telarray_id = {} for tel_id in telescope_meta.keys(): _optics_name = telescope_meta[tel_id].get("optics_config_name", None) _camera_name = telescope_meta[tel_id].get("camera_config_name", None) if _optics_name == _camera_name and _optics_name == telescope_name: telescope_name_to_sim_telarray_id[telescope_name] = tel_id return telescope_name_to_sim_telarray_id.get(telescope_name, None)