Source code for io_operations.io_handler

"""Handle input and output paths."""

import datetime
import logging
from pathlib import Path

__all__ = ["IOHandlerSingleton", "IOHandler"]


class IncompleteIOHandlerInitError(Exception):
    """Exception raised when IOHandler is not initialized."""


[docs] class IOHandlerSingleton(type): """Singleton base class.""" _instances = {} def __call__(cls, *args, **kwargs): """ Ensure a single instance of the IOHandlerSingleton class. Creates a new instance if it doesn't exist, otherwise returns the existing instance. """ if cls not in cls._instances: cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls]
[docs] class IOHandler(metaclass=IOHandlerSingleton): """Handle input and output paths.""" def __init__(self): """Initialize IOHandler.""" self._logger = logging.getLogger(__name__) self._logger.debug("Init IOHandler") self.output_path = None self.use_plain_output_path = False self.data_path = None self.model_path = None
[docs] def set_paths( self, output_path=None, data_path=None, model_path=None, use_plain_output_path=False ): """ Set paths for input and output. Parameters ---------- output_path: str or Path Path pointing to the output directory. data_path: str or Path Path pointing to the data files (e.g., CORSIKA or sim_telarray output). model_path: str or Path Path pointing to the model file directory. use_plain_output_path: bool Use plain output path without adding tool name and date """ self.output_path = output_path self.use_plain_output_path = use_plain_output_path self.data_path = data_path self.model_path = model_path
[docs] def get_output_directory(self, label=None, sub_dir=None): """ Return path to output directory. Parameters ---------- label: str Instance label. sub_dir: str Name of the subdirectory (ray-tracing, model etc) Returns ------- Path Raises ------ FileNotFoundError if error creating directory TypeError raised for errors while creating directory name """ path = Path(self.output_path) if not self.use_plain_output_path: path = ( path if str(self.output_path).endswith("-output") else path.joinpath("simtools-output") ) label_dir = label if label is not None else "d-" + str(datetime.date.today()) path = ( path.joinpath(label_dir) if sub_dir is None else path.joinpath(label_dir, sub_dir) ) try: path.mkdir(parents=True, exist_ok=True) except FileNotFoundError: self._logger.error(f"Error creating directory {path!s}") raise return path.absolute()
[docs] def get_output_file(self, file_name, label=None, sub_dir=None): """ Get path of an output file. Parameters ---------- files_name: str File name. label: str Instance label. sub_dir: str Name of the subdirectory (ray-tracing, model etc) Returns ------- Path """ return ( self.get_output_directory(label=label, sub_dir=sub_dir).joinpath(file_name).absolute() )
[docs] def get_input_data_file(self, parent_dir=None, file_name=None, test=False): """ Get path of a data file, using data_path. Parameters ---------- parent_dir: str Parent directory of the file. files_name: str File name. test: bool If true, return test resources location Returns ------- Path Raises ------ IncompleteIOHandlerInitError if data_path is not set """ if test: file_prefix = Path("tests/resources/") elif self.data_path is not None: file_prefix = Path(self.data_path).joinpath(parent_dir) else: raise IncompleteIOHandlerInitError return file_prefix.joinpath(file_name).absolute()