Source code for model.model_utils

#!/usr/bin/python3
"""Helper functions related to model parameters."""

import json
import math

from simtools.context import RunContext
from simtools.io import ascii_handler
from simtools.model.calibration_model import CalibrationModel
from simtools.model.site_model import SiteModel
from simtools.model.telescope_model import TelescopeModel
from simtools.simulation.configuration import export_model_files


[docs] def initialize_simulation_models( label, model_version, site, telescope_name, calibration_device_name=None, calibration_device_type=None, model_reader=None, model_directory=None, context=None, ): """ Initialize simulation models for a single telescope, site, and calibration device model. Parameters ---------- label: str Label for the simulation. model_version: str Version of the simulation model site: str Name of the site. telescope_name: str Name of the telescope. calibration_device_name: str, optional Name of the calibration device. calibration_device_type: str, optional Type of the calibration device. model_directory: pathlib.Path or str, optional Directory for generated model assets and sim_telarray configuration files. Returns ------- Tuple Tuple containing the telescope site, (optional) calibration device model. """ context = context or RunContext.from_environment() overwrite_model_parameter_dict = read_overwrite_model_parameter_dict(context=context) common = { "site": site, "model_version": model_version, "label": label, "overwrite_model_parameter_dict": overwrite_model_parameter_dict, "model_reader": model_reader or context.model_reader, "context": context, } if model_directory is not None: common["model_directory"] = model_directory tel_model = TelescopeModel(telescope_name=telescope_name, **common) site_model = SiteModel(**common) calibration_device_name = calibration_device_name or tel_model.get_calibration_device_name( calibration_device_type ) if calibration_device_name is not None: calibration_model = CalibrationModel( calibration_device_model_name=calibration_device_name, **common ) else: calibration_model = None for model in tel_model, site_model: export_model_files(model) return tel_model, site_model, calibration_model
[docs] def read_overwrite_model_parameter_dict(overwrite_model_parameters=None, context=None): """ Read overwrite model parameters dictionary. Parameters ---------- overwrite_model_parameters: dict or str, optional Either a dictionary with model parameters to overwrite, or a file path. Returns ------- dict Dictionary with model parameters to overwrite. """ if overwrite_model_parameters is None: context = context or RunContext.from_environment() overwrite_model_parameters = context.args.get("overwrite_model_parameters") if overwrite_model_parameters is None: return {} if isinstance(overwrite_model_parameters, dict): return _extract_changes_from_dict(overwrite_model_parameters) if isinstance(overwrite_model_parameters, str): return _extract_changes_from_string(overwrite_model_parameters) return {}
def _extract_changes_from_dict(overwrite_dict): """Extract changes from a dictionary.""" if "changes" in overwrite_dict: return overwrite_dict["changes"] return overwrite_dict def _extract_changes_from_string(overwrite_str): """Extract changes from a string (JSON or file path).""" try: parsed_data = json.loads(overwrite_str) if isinstance(parsed_data, dict): return _extract_changes_from_dict(parsed_data) except json.JSONDecodeError: pass data = ascii_handler.collect_data_from_file(file_name=overwrite_str) if isinstance(data, dict): return _extract_changes_from_dict(data) return {}
[docs] def compute_telescope_transmission(pars: list[float], off_axis: float) -> float: """ Compute telescope transmission (0 < T < 1) for a given off-axis angle. The telescope transmission depends on the MC model used. Parameters ---------- pars: list of float Parameters of the telescope transmission. Len(pars) should be 5 or 6. off_axis: float Off-axis angle in deg. Returns ------- float Telescope transmission. """ _deg_to_rad = math.pi / 180.0 if pars[1] == 0: return pars[0] t = math.sin(off_axis * _deg_to_rad) / (pars[3] * _deg_to_rad) return pars[0] / (1.0 + pars[2] * t ** pars[4])
[docs] def get_array_elements_for_layout( layout_name, site=None, model_version=None, model_reader=None, context=None ): """ Get array elements for a given array layout. Parameters ---------- layout_name: str Name of the array layout. site: str, optional Site name (use central configuration if not provided). model_version: str, optional Model version (use central configuration if not provided). Returns ------- list List of array elements for the given array layout. """ if not layout_name or (isinstance(layout_name, list) and len(layout_name) > 1): raise ValueError("Single array layout name must be provided.") layout_name = layout_name[0] if isinstance(layout_name, list) else layout_name context = context or RunContext.from_environment() site_model = SiteModel( site=site or context.args.get("site"), model_version=model_version or context.args.get("model_version"), label="label", overwrite_model_parameter_dict=read_overwrite_model_parameter_dict(context=context), model_reader=model_reader or context.model_reader, context=context, ) return site_model.get_array_elements_for_layout(layout_name)