Source code for simulate_flasher

#!/usr/bin/python3

r"""
Simulate flasher devices used e.g. for camera flat fielding.

The flasher simulation allows for two different run modes:

1. Direct injection of light into the camera (bypassing the telescope optics).
2. Simulation of the full light path (using the light-emission package from sim_telarray).

The direct injection mode uses a simplified model for the flasher light source. Both run modes
provide events in sim_telarray format that can be processed by standard analysis steps or
visualized using e.g. the 'simtools-plot-simtel-events' application.

Example Usage
-------------

1. Simulate flashers for a telescope (direct injection):

    .. code-block:: console

        simtools-simulate-flasher --run_mode direct_injection \
        --light_source MSFx-FlashCam --model_version 6.0.0 \
        --array_layout_name subsystem_msts --site South \
        --run_number 3

2. Simulate flashers for a telescope (detailed simulation):

    .. code-block:: console

        simtools-simulate-flasher --run_mode full_simulation \
        --light_source MSFx-FlashCam --model_version 6.0.0 \
        --telescope MSTS-04 --site South

Command Line Arguments
----------------------
run_mode (str, required)
    Run mode, either "direct_injection" or "full_simulation".
telescope (str, required)
    Telescope model name (e.g. LSTN-01, MSTN-04, SSTS-04, ...)
site (str, required)
    Site name (North or South).
light_source (str, required)
    Calibration light source, e.g., MSFx-FlashCam
number_of_events (int, optional):
    Number of events to simulate (default: 1).
output_prefix (str, optional):
    Prefix for output files (default: empty).
model_version (str, optional)
    Version of the simulation model.
array_layout_name (str, optional)
    Name of the array layout to use (required for direct injection mode).
run_number (int, optional)
    Run number to use (default: 1, required for direct injection mode).
telescope (str, optional)
    Telescope name (required for full simulation mode).
"""

from simtools.application_control import get_application_label, startup_application
from simtools.configuration import configurator
from simtools.simtel.simulator_light_emission import SimulatorLightEmission
from simtools.simulator import Simulator


def _parse():
    """Parse command line configuration."""
    config = configurator.Configurator(
        label=get_application_label(__file__), description="Simulate flasher devices."
    )
    config.parser.add_argument(
        "--run_mode",
        help="Flasher simulation run mode",
        type=str,
        choices=["direct_injection", "full_simulation"],
        required=True,
        default="direct_injection",
    )
    config.parser.add_argument(
        "--light_source",
        help="Flasher device associated with a specific telescope, i.e. MSFx-FlashCam",
        type=str,
        required=True,
    )
    config.parser.add_argument(
        "--number_of_events",
        help="Number of flasher events to simulate",
        type=int,
        default=1,
        required=False,
    )
    config.parser.add_argument(
        "--output_prefix",
        help="Prefix for output files",
        type=str,
        default=None,
        required=False,
    )
    return config.initialize(
        db_config=True,
        simulation_model=["site", "layout", "telescope", "model_version"],
        simulation_configuration={
            "corsika_configuration": ["run_number"],
            "sim_telarray_configuration": ["all"],
        },
    )


[docs] def main(): """Simulate flasher devices.""" app_context = startup_application(_parse) app_context.logger.info( f"Flasher simulation for telescope {app_context.args['telescope']} " f" with light source {app_context.args['light_source']} " f" ({app_context.args['number_of_events']} events, " f"run mode: {app_context.args['run_mode']})" ) if app_context.args["run_mode"] == "full_simulation": light_source = SimulatorLightEmission( light_emission_config=app_context.args, db_config=app_context.db_config, label=app_context.args.get("label"), ) elif app_context.args["run_mode"] == "direct_injection": light_source = Simulator( args_dict=app_context.args, db_config=app_context.db_config, label=app_context.args.get("label"), ) else: raise ValueError(f"Unsupported run_mode: {app_context.args['run_mode']}") light_source.simulate() app_context.logger.info("Flasher simulation completed.")
if __name__ == "__main__": main()