diff --git a/simpa/core/simulation.py b/simpa/core/simulation.py index 66170a42..9ced806f 100644 --- a/simpa/core/simulation.py +++ b/simpa/core/simulation.py @@ -16,7 +16,8 @@ import time -def simulate(simulation_pipeline: list, settings: Settings, digital_device_twin: DigitalDeviceTwinBase): +def simulate(simulation_pipeline: list, settings: Settings, digital_device_twin: DigitalDeviceTwinBase, + logging_level: str = Tags.LOGGER_DEBUG): """ This method constitutes the staring point for the simulation pipeline of the SIMPA toolkit. @@ -25,12 +26,13 @@ def simulate(simulation_pipeline: list, settings: Settings, digital_device_twin: :param settings: settings dictionary containing the simulation instructions :param digital_device_twin: a digital device twin of an imaging device as specified by the DigitalDeviceTwinBase class. + :param logging_level: The logging level of the simulation pipeline. :raises TypeError: if one of the given parameters is not of the correct type :raises AssertionError: if the digital device twin is not able to simulate the settings specification :return: list with the save paths of the simulated data within the HDF5 file. """ start_time = time.time() - logger = Logger() + logger = Logger(logging_level=logging_level, force_new_instance=True) if not isinstance(settings, Settings): logger.critical("The second argument was not a settings instance!") raise TypeError("Use a Settings instance from simpa.utils.settings_generator as simulation input.") diff --git a/simpa/io_handling/io_hdf5.py b/simpa/io_handling/io_hdf5.py index eb10ae97..d89e87c8 100644 --- a/simpa/io_handling/io_hdf5.py +++ b/simpa/io_handling/io_hdf5.py @@ -9,8 +9,6 @@ from simpa.log import Logger from simpa.utils.serializer import SerializableSIMPAClass -logger = Logger() - def save_hdf5(save_item, file_path: str, file_dictionary_path: str = "/", file_compression: str = None): """ @@ -32,6 +30,7 @@ def data_grabber(file, path, data_dictionary, compression: str = None): :param data_dictionary: Dictionary to save. :param compression: possible file compression for the corresponding dataset. Values are: gzip, lzf and szip. """ + logger = Logger() for key, item in data_dictionary.items(): key = str(key) diff --git a/simpa/log/file_logger.py b/simpa/log/file_logger.py index 5911bdbc..af2120c7 100644 --- a/simpa/log/file_logger.py +++ b/simpa/log/file_logger.py @@ -6,6 +6,7 @@ from pathlib import Path import sys from simpa.utils.serializer import SerializableSIMPAClass +from simpa.utils import Tags class Logger(SerializableSIMPAClass): @@ -28,22 +29,43 @@ class Logger(SerializableSIMPAClass): _simpa_default_logging_path = str(Path.home())+"/simpa.log" _logger = None - def __new__(cls, path=None, force_new_instance=False, startup_verbose=False): + def __new__(cls, path=None, force_new_instance: bool = False, startup_verbose: bool = False, + logging_level: str = Tags.LOGGER_DEBUG): # This pattern can be used to realise a singleton implementation in Python + """ + Here, we create an instance of the Logger class and set the logging level. + :param path: Where to write the log file. + :param force_new_instance: Whether to create a new instance of the Logger class or not. + :param startup_verbose: Whether to add a verbose for starting up the logger. + :param logging_level: the level of the logging module to use. + """ if cls._instance is None or force_new_instance: cls._instance = super(Logger, cls).__new__(cls) if path is None: path = cls._simpa_default_logging_path + if logging_level == Tags.LOGGER_DEBUG: + _logging_level = logging.DEBUG + elif logging_level == Tags.LOGGER_INFO: + _logging_level = logging.INFO + elif logging_level == Tags.LOGGER_WARNING: + _logging_level = logging.WARNING + elif logging_level == Tags.LOGGER_ERROR: + _logging_level = logging.ERROR + elif logging_level == Tags.LOGGER_CRITICAL: + _logging_level = logging.CRITICAL + else: + raise ValueError('Invalid logging level') + cls._logger = logging.getLogger("SIMPA Logger") - cls._logger.setLevel(logging.DEBUG) + cls._logger.setLevel(_logging_level) console_handler = logging.StreamHandler(stream=sys.stdout) file_handler = logging.FileHandler(path, mode="w") - console_handler.setLevel(logging.DEBUG) - file_handler.setLevel(logging.DEBUG) + console_handler.setLevel(_logging_level) + file_handler.setLevel(_logging_level) console_handler.setFormatter(cls._simpa_logging_formatter) file_handler.setFormatter(cls._simpa_logging_formatter) diff --git a/simpa/utils/tags.py b/simpa/utils/tags.py index c8e29025..d5ca76d6 100644 --- a/simpa/utils/tags.py +++ b/simpa/utils/tags.py @@ -1573,6 +1573,36 @@ class Tags: Identifier for the environment varibale that defines the path the the matlab executable. """ + LOGGER_DEBUG = "debug" + """ + Identifies the logging level to be set to logging.DEBUG. + Usage: log.file_logger + """ + + LOGGER_INFO = "info" + """ + Identifies the logging level to be set to logging.INFO. + Usage: log.file_logger + """ + + LOGGER_WARNING = "warning" + """ + Identifies the logging level to be set to logging.WARNING. + Usage: log.file_logger + """ + + LOGGER_ERROR = "error" + """ + Identifies the logging level to be set to logging.ERROR. + Usage: log.file_logger + """ + + LOGGER_CRITICAL = "critical" + """ + Identifies the logging level to be set to logging.CRITICAL. + Usage: log.file_logger + """ + ADDITIONAL_FLAGS = ("additional_flags", Iterable) """ Defines a sequence of extra flags to be parsed to executables for simulation modules. diff --git a/simpa_examples/optical_and_acoustic_simulation.py b/simpa_examples/optical_and_acoustic_simulation.py index 34887450..fc41fa2c 100644 --- a/simpa_examples/optical_and_acoustic_simulation.py +++ b/simpa_examples/optical_and_acoustic_simulation.py @@ -16,6 +16,10 @@ # point to the correct file in the PathManager(). +# TODO: set the level at which you wish to receive a log for +logger = sp.log.Logger(logging_level=Tags.LOGGER_WARNING) + + @profile def run_optical_and_acoustic_simulation(spacing: float | int = 0.2, path_manager=None, visualise: bool = True): @@ -195,7 +199,7 @@ def create_example_tissue(): sp.FieldOfViewCropping(settings) ] - sp.simulate(SIMULATION_PIPELINE, settings, device) + sp.simulate(SIMULATION_PIPELINE, settings, device, logging_level=Tags.LOGGER_ERROR) if Tags.WAVELENGTH in settings: WAVELENGTH = settings[Tags.WAVELENGTH]