Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changes/1981.maintenance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve file management for light emission simulations (flasher/illuminators). Change of output file naming and directory tree.
11 changes: 2 additions & 9 deletions src/simtools/applications/simulate_flasher.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@
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)
Expand Down Expand Up @@ -89,13 +87,6 @@ def _parse():
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"],
Expand Down Expand Up @@ -128,6 +119,8 @@ def main():
raise ValueError(f"Unsupported run_mode: {app_context.args['run_mode']}")

light_source.simulate()
light_source.verify_simulations()

app_context.logger.info("Flasher simulation completed.")


Expand Down
12 changes: 2 additions & 10 deletions src/simtools/applications/simulate_illuminator.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@
m. If not set, the position from the simulation model is used.
light_source_pointing (float, float, float, optional)
Light source pointing direction. If not set, the pointing from the simulation model is used.
output_prefix (str, optional)
Prefix for output files (default: empty).
"""

from simtools.application_control import get_application_label, startup_application
Expand Down Expand Up @@ -100,13 +98,6 @@ def _parse():
default=1,
required=False,
)
config.parser.add_argument(
"--output_prefix",
help="Prefix for output files (default: empty)",
type=str,
default=None,
required=False,
)
return config.initialize(
db_config=True,
simulation_model=["telescope", "model_version"],
Expand All @@ -119,10 +110,11 @@ def main():
app_context = startup_application(_parse)

light_source = SimulatorLightEmission(
light_emission_config=app_context.args,
light_emission_config={**app_context.args, "run_mode": "illuminator"},
label=app_context.args.get("label"),
)
light_source.simulate()
light_source.verify_simulations()


if __name__ == "__main__":
Expand Down
24 changes: 15 additions & 9 deletions src/simtools/runners/corsika_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def __init__(
self._use_multipipe = use_multipipe
self.curved_atmosphere_min_zenith_angle = curved_atmosphere_min_zenith_angle

self.runner_service = RunnerServices(corsika_config, "corsika", label)
self.runner_service = RunnerServices(corsika_config, run_type="corsika", label=label)
self.file_list = None

def prepare_run(self, run_number, sub_script, extra_commands=None, corsika_file=None):
Expand All @@ -70,15 +70,19 @@ def prepare_run(self, run_number, sub_script, extra_commands=None, corsika_file=
self.corsika_config.generate_corsika_input_file(
self._use_multipipe,
self._corsika_seeds,
self.file_list["corsika_input"],
self.file_list["corsika_output"] if not self._use_multipipe else corsika_file,
self.runner_service.get_file_name("corsika_input", run_number=run_number),
self.runner_service.get_file_name("corsika_output", run_number=run_number)
if not self._use_multipipe
else corsika_file,
)

self._logger.debug(f"Extra commands to be added to the run script: {extra_commands}")

corsika_run_dir = self.file_list["corsika_output"].parent
corsika_run_dir = self.runner_service.get_file_name(
"corsika_output", run_number=run_number
).parent

self._export_run_script(sub_script, corsika_run_dir, extra_commands)
self._export_run_script(run_number, sub_script, corsika_run_dir, extra_commands)

def _corsika_executable(self):
"""Get the CORSIKA executable path."""
Expand All @@ -88,9 +92,12 @@ def _corsika_executable(self):
self._logger.debug("Using flat-atmosphere CORSIKA binary.")
return Path(settings.config.corsika_exe)

def _export_run_script(self, sub_script, corsika_run_dir, extra_commands):
def _export_run_script(self, run_number, sub_script, corsika_run_dir, extra_commands):
"""Export CORSIKA run script."""
corsika_log_file = self.file_list["corsika_log"].with_suffix("")
corsika_log_file = self.runner_service.get_file_name(
"corsika_log", run_number=run_number
).with_suffix("") # remove .gz from log file
corsika_input = self.runner_service.get_file_name("corsika_input", run_number=run_number)
sub_script = Path(sub_script)
with open(sub_script, "w", encoding="utf-8") as file:
file.write("#!/usr/bin/env bash\n")
Expand All @@ -111,8 +118,7 @@ def _export_run_script(self, sub_script, corsika_run_dir, extra_commands):

file.write("\n# Running corsika\n")
file.write(
f"{self._corsika_executable()} < {self.file_list['corsika_input']} "
f"> {corsika_log_file} 2>&1\n"
f"{self._corsika_executable()} < {corsika_input} > {corsika_log_file} 2>&1\n"
)
file.write("\n# Cleanup\n")
file.write(f"gzip {corsika_log_file}\n")
Expand Down
2 changes: 1 addition & 1 deletion src/simtools/runners/corsika_simtel_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def __init__(
self.sequential = "--sequential" if sequential else ""

self.runner_service = runner_services.RunnerServices(
self.base_corsika_config, "multi_pipe", label
self.base_corsika_config, run_type="multi_pipe", label=label
)
self.file_list = None

Expand Down
74 changes: 56 additions & 18 deletions src/simtools/runners/runner_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import logging

from simtools.corsika.corsika_config import CorsikaConfig
from simtools.io import io_handler

_logger = logging.getLogger(__name__)
Expand All @@ -21,6 +22,11 @@
"suffix": ".corsika.log.gz",
"sub_dir_type": "run_number",
},
# Generic iact output
"iact_output": {
"suffix": ".iact.gz",
"sub_dir_type": "run_number",
},
# sim_telarray
"sim_telarray_output": {
"suffix": ".simtel.zst",
Expand Down Expand Up @@ -101,19 +107,19 @@ class RunnerServices:

Parameters
----------
corsika_config : CorsikaConfig, list of CorsikaConfig
Configuration parameters for CORSIKA.
config: CorsikaConfig, dict
Configuration parameters.
run_type : str
Type of simulation runner.
label : str
Label.
"""

def __init__(self, corsika_config, run_type, label=None):
def __init__(self, config, run_type, label=None):
"""Initialize RunnerServices."""
self._logger = logging.getLogger(__name__)
self.label = label
self.corsika_config = corsika_config
self.config = config
self.run_type = run_type
self.directory = self.load_data_directory()

Expand All @@ -129,6 +135,7 @@ def load_data_directory(self):
ioh = io_handler.IOHandler()
directory = ioh.get_output_directory(self.run_type)
self._logger.debug(f"Data directories for {self.run_type}: {directory}")

return directory

def load_files(self, run_number=None):
Expand Down Expand Up @@ -171,13 +178,39 @@ def _get_file_basename(self, run_number, is_multi_pipe=False):
str
Base name for the simulation files.
"""
vc_high = self.corsika_config.get_config_parameter("VIEWCONE")[1]
zenith = self.corsika_config.get_config_parameter("THETAP")[0]

if self.corsika_config.run_mode is not None and self.corsika_config.run_mode != "":
primary_name = self.corsika_config.run_mode
if isinstance(self.config, CorsikaConfig):
return self._get_file_base_name_from_corsika_config(run_number, is_multi_pipe)
if isinstance(self.config, dict):
return self._get_file_base_name_from_core_config()
raise ValueError(f"Invalid configuration type: {type(self.config)}")

def _get_file_base_name_from_core_config(self):
"""Get file base name from core configuration."""
cfg = self.config
zenith_angle = cfg.get("zenith_angle")
azimuth_angle = cfg.get("azimuth_angle")

parts = [
f"{cfg['run_mode']}_" if cfg.get("run_mode") else "",
f"{self._get_run_number_string(cfg.get('run_number'))}_" if "run_number" in cfg else "",
f"za{round(zenith_angle):02}deg_" if isinstance(zenith_angle, (int, float)) else "",
f"azm{round(azimuth_angle):03}deg_" if isinstance(azimuth_angle, (int, float)) else "",
f"{cfg['site']}_" if cfg.get("site") else "",
f"{cfg['layout']}_" if cfg.get("layout") else "",
cfg.get("model_version", ""),
f"_{self.label}" if self.label else "",
]
return "".join(parts)

def _get_file_base_name_from_corsika_config(self, run_number, is_multi_pipe=False):
"""Get file base name from CORSIKA configuration."""
zenith = self.config.get_config_parameter("THETAP")[0]
vc_high = self.config.get_config_parameter("VIEWCONE")[1]

if self.config.run_mode is not None and self.config.run_mode != "":
primary_name = self.config.run_mode
else:
primary_name = self.corsika_config.primary_particle.name
primary_name = self.config.primary_particle.name
if primary_name == "gamma" and vc_high > 0:
primary_name = "gamma_diffuse"

Expand All @@ -188,10 +221,10 @@ def _get_file_basename(self, run_number, is_multi_pipe=False):
return (
prefix
+ f"za{round(zenith):02}deg_"
+ f"azm{self.corsika_config.azimuth_angle:03}deg_"
+ f"{self.corsika_config.array_model.site}_"
+ f"{self.corsika_config.array_model.layout_name}_"
+ (self.corsika_config.array_model.model_version if not is_multi_pipe else "")
+ f"azm{self.config.azimuth_angle:03}deg_"
+ f"{self.config.array_model.site}_"
+ f"{self.config.array_model.layout_name}_"
+ (self.config.array_model.model_version if not is_multi_pipe else "")
+ file_label
)

Expand Down Expand Up @@ -264,6 +297,8 @@ def _get_run_number_string(run_number):
str
Run number string.
"""
if run_number is None:
return ""
return f"run{validate_corsika_run_number(run_number):06d}"

def get_resources(self, sub_out_file):
Expand Down Expand Up @@ -292,7 +327,10 @@ def get_resources(self, sub_out_file):
if runtime is None:
_logger.debug("RUNTIME was not found in run log file")

return {
"runtime": runtime,
"n_events": int(self.corsika_config.get_config_parameter("NSHOW")),
}
if isinstance(self.config, CorsikaConfig):
return {
"runtime": runtime,
"n_events": int(self.config.get_config_parameter("NSHOW")),
}
self._logger.warning("Number of events cannot be determined from non-CORSIKA config.")
return {"runtime": runtime, "n_events": None}
8 changes: 4 additions & 4 deletions src/simtools/runners/simtel_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ class SimtelRunner:
----------
label: str
Instance label. Important for output file naming.
corsika_config: CorsikaConfig
CORSIKA configuration.
config: CorsikaConfig or dict
Configuration parameters.
is_calibration_run: bool
Flag to indicate if this is a calibration run.
"""

def __init__(self, label=None, corsika_config=None, is_calibration_run=False):
def __init__(self, label=None, config=None, is_calibration_run=False):
"""Initialize SimtelRunner."""
self._logger = logging.getLogger(__name__)

Expand All @@ -42,7 +42,7 @@ def __init__(self, label=None, corsika_config=None, is_calibration_run=False):

self.runs_per_set = 1

self.runner_service = RunnerServices(corsika_config, "sim_telarray", label)
self.runner_service = RunnerServices(config, run_type="sim_telarray", label=label)
self.file_list = None

def run(self, test=False, input_file=None, run_number=None):
Expand Down
6 changes: 1 addition & 5 deletions src/simtools/simtel/simulator_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ def __init__(
is_calibration_run=False,
):
"""Initialize SimulatorArray."""
super().__init__(
label=label,
corsika_config=corsika_config,
is_calibration_run=is_calibration_run,
)
super().__init__(label=label, config=corsika_config, is_calibration_run=is_calibration_run)

self.sim_telarray_seeds = sim_telarray_seeds
self.corsika_config = corsika_config
Expand Down
Loading