gammasimtools 0.25.0__py3-none-any.whl → 0.27.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/METADATA +6 -1
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/RECORD +135 -130
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/entry_points.txt +3 -2
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +2 -2
- simtools/application_control.py +35 -7
- simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
- simtools/applications/db_add_file_to_db.py +1 -1
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
- simtools/applications/db_add_value_from_json_to_db.py +1 -1
- simtools/applications/db_generate_compound_indexes.py +1 -1
- simtools/applications/db_get_array_layouts_from_db.py +3 -7
- simtools/applications/db_get_file_from_db.py +1 -1
- simtools/applications/db_get_parameter_from_db.py +1 -1
- simtools/applications/db_inspect_databases.py +1 -1
- simtools/applications/db_upload_model_repository.py +1 -1
- simtools/applications/derive_ctao_array_layouts.py +1 -2
- simtools/applications/{calculate_incident_angles.py → derive_incident_angle.py} +16 -18
- simtools/applications/derive_mirror_rnda.py +112 -180
- simtools/applications/derive_psf_parameters.py +0 -1
- simtools/applications/derive_pulse_shape_parameters.py +0 -1
- simtools/applications/derive_trigger_rates.py +1 -1
- simtools/applications/docs_produce_array_element_report.py +2 -8
- simtools/applications/docs_produce_calibration_reports.py +1 -3
- simtools/applications/docs_produce_model_parameter_reports.py +0 -2
- simtools/applications/docs_produce_simulation_configuration_report.py +1 -3
- simtools/applications/generate_array_config.py +0 -1
- simtools/applications/generate_corsika_histograms.py +79 -229
- simtools/applications/generate_regular_arrays.py +76 -69
- simtools/applications/generate_simtel_event_data.py +2 -2
- simtools/applications/maintain_simulation_model_add_production.py +2 -2
- simtools/applications/maintain_simulation_model_write_array_element_positions.py +87 -0
- simtools/applications/plot_array_layout.py +5 -111
- simtools/applications/plot_simulated_event_distributions.py +57 -0
- simtools/applications/plot_tabular_data.py +0 -1
- simtools/applications/plot_tabular_data_for_model_parameter.py +1 -6
- simtools/applications/production_derive_corsika_limits.py +1 -1
- simtools/applications/production_generate_grid.py +0 -1
- simtools/applications/run_application.py +1 -1
- simtools/applications/simulate_flasher.py +3 -15
- simtools/applications/simulate_illuminator.py +2 -11
- simtools/applications/simulate_pedestals.py +1 -5
- simtools/applications/simulate_prod.py +8 -11
- simtools/applications/simulate_prod_htcondor_generator.py +1 -1
- simtools/applications/submit_array_layouts.py +2 -4
- simtools/applications/submit_data_from_external.py +2 -1
- simtools/applications/submit_model_parameter_from_external.py +1 -3
- simtools/applications/validate_camera_efficiency.py +28 -28
- simtools/applications/validate_camera_fov.py +0 -1
- simtools/applications/validate_cumulative_psf.py +1 -5
- simtools/applications/validate_optics.py +2 -14
- simtools/atmosphere.py +83 -0
- simtools/camera/camera_efficiency.py +171 -53
- simtools/camera/single_photon_electron_spectrum.py +8 -7
- simtools/configuration/commandline_parser.py +82 -11
- simtools/configuration/configurator.py +6 -11
- simtools/constants.py +5 -0
- simtools/corsika/corsika_config.py +100 -202
- simtools/corsika/corsika_histograms.py +561 -1708
- simtools/corsika/primary_particle.py +1 -1
- simtools/data_model/metadata_collector.py +5 -2
- simtools/data_model/metadata_model.py +0 -4
- simtools/data_model/model_data_writer.py +59 -64
- simtools/data_model/schema.py +2 -0
- simtools/data_model/validate_data.py +1 -3
- simtools/db/db_handler.py +23 -10
- simtools/db/mongo_db.py +2 -2
- simtools/dependencies.py +81 -38
- simtools/io/ascii_handler.py +55 -5
- simtools/io/io_handler.py +23 -12
- simtools/io/table_handler.py +1 -1
- simtools/job_execution/job_manager.py +154 -79
- simtools/job_execution/process_pool.py +137 -0
- simtools/layout/array_layout.py +4 -13
- simtools/layout/array_layout_utils.py +348 -57
- simtools/model/array_model.py +23 -63
- simtools/model/calibration_model.py +4 -8
- simtools/model/legacy_model_parameter.py +134 -0
- simtools/model/model_parameter.py +147 -86
- simtools/model/model_utils.py +40 -6
- simtools/model/site_model.py +4 -8
- simtools/model/telescope_model.py +10 -16
- simtools/production_configuration/derive_corsika_limits.py +6 -11
- simtools/production_configuration/interpolation_handler.py +16 -16
- simtools/ray_tracing/incident_angles.py +92 -17
- simtools/ray_tracing/mirror_panel_psf.py +338 -222
- simtools/ray_tracing/psf_analysis.py +62 -48
- simtools/ray_tracing/psf_parameter_optimisation.py +3 -3
- simtools/ray_tracing/ray_tracing.py +43 -25
- simtools/reporting/docs_auto_report_generator.py +8 -13
- simtools/reporting/docs_read_parameters.py +2 -8
- simtools/runners/corsika_runner.py +52 -195
- simtools/runners/corsika_simtel_runner.py +77 -108
- simtools/runners/runner_services.py +214 -213
- simtools/runners/simtel_runner.py +27 -160
- simtools/runners/simtools_runner.py +11 -73
- simtools/schemas/application_workflow.metaschema.yml +8 -0
- simtools/settings.py +173 -0
- simtools/{io/eventio_handler.py → sim_events/file_info.py} +3 -3
- simtools/{simtel/simtel_io_event_histograms.py → sim_events/histograms.py} +25 -15
- simtools/{simtel/simtel_io_event_reader.py → sim_events/reader.py} +20 -17
- simtools/{simtel/simtel_io_event_writer.py → sim_events/writer.py} +84 -25
- simtools/simtel/pulse_shapes.py +7 -2
- simtools/simtel/simtel_config_writer.py +79 -91
- simtools/simtel/simtel_seeds.py +184 -0
- simtools/simtel/simtel_table_reader.py +6 -4
- simtools/simtel/simulator_array.py +114 -109
- simtools/simtel/simulator_camera_efficiency.py +68 -46
- simtools/simtel/simulator_light_emission.py +164 -132
- simtools/simtel/simulator_ray_tracing.py +80 -71
- simtools/simulator.py +137 -355
- simtools/telescope_trigger_rates.py +3 -4
- simtools/testing/assertions.py +84 -33
- simtools/testing/configuration.py +1 -2
- simtools/testing/helpers.py +2 -3
- simtools/testing/log_inspector.py +1 -0
- simtools/testing/sim_telarray_metadata.py +14 -12
- simtools/testing/validate_output.py +121 -42
- simtools/utils/general.py +43 -17
- simtools/utils/geometry.py +0 -77
- simtools/utils/names.py +5 -5
- simtools/utils/random.py +36 -0
- simtools/visualization/legend_handlers.py +7 -6
- simtools/visualization/plot_array_layout.py +91 -16
- simtools/visualization/plot_corsika_histograms.py +145 -605
- simtools/visualization/plot_incident_angles.py +48 -1
- simtools/visualization/plot_mirrors.py +1 -4
- simtools/visualization/plot_pixels.py +2 -4
- simtools/visualization/plot_psf.py +160 -19
- simtools/visualization/plot_simtel_event_histograms.py +4 -4
- simtools/visualization/plot_simtel_events.py +6 -11
- simtools/visualization/plot_tables.py +8 -19
- simtools/visualization/visualize.py +22 -2
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +0 -160
- simtools/applications/print_version.py +0 -53
- simtools/io/hdf5_handler.py +0 -139
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/top_level.txt +0 -0
|
@@ -1,37 +1,24 @@
|
|
|
1
1
|
"""Generate run scripts and directories for CORSIKA simulations."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
import stat
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
|
|
7
|
-
from simtools
|
|
6
|
+
from simtools import settings
|
|
8
7
|
from simtools.runners.runner_services import RunnerServices
|
|
9
8
|
|
|
10
9
|
|
|
11
|
-
class MissingRequiredEntryInCorsikaConfigError(Exception):
|
|
12
|
-
"""Exception for missing required entry in corsika config."""
|
|
13
|
-
|
|
14
|
-
|
|
15
10
|
class CorsikaRunner:
|
|
16
11
|
"""
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
CorsikaRunner is responsible for configuring and running CORSIKA, using corsika_autoinputs
|
|
20
|
-
provided by the sim_telarray package. CorsikaRunner generates shell scripts to be run
|
|
21
|
-
externally or by the simulator module simulator.
|
|
12
|
+
Prepare and run CORSIKA simulations.
|
|
22
13
|
|
|
23
|
-
|
|
14
|
+
Generate run scripts and directories for CORSIKA simulations. Run simulations if requested.
|
|
24
15
|
|
|
25
16
|
Parameters
|
|
26
17
|
----------
|
|
27
18
|
corsika_config_data: CorsikaConfig
|
|
28
19
|
CORSIKA configuration.
|
|
29
|
-
simtel_path: str or Path
|
|
30
|
-
Location of source of the sim_telarray/CORSIKA package.
|
|
31
20
|
label: str
|
|
32
21
|
Instance label.
|
|
33
|
-
keep_seeds: bool
|
|
34
|
-
Use seeds based on run number and primary particle. If False, use sim_telarray seeds.
|
|
35
22
|
use_multipipe: bool
|
|
36
23
|
Use multipipe to run CORSIKA and sim_telarray.
|
|
37
24
|
curved_atmosphere_min_zenith_angle: Quantity
|
|
@@ -41,9 +28,7 @@ class CorsikaRunner:
|
|
|
41
28
|
def __init__(
|
|
42
29
|
self,
|
|
43
30
|
corsika_config,
|
|
44
|
-
simtel_path,
|
|
45
31
|
label=None,
|
|
46
|
-
keep_seeds=False,
|
|
47
32
|
use_multipipe=False,
|
|
48
33
|
curved_atmosphere_min_zenith_angle=None,
|
|
49
34
|
):
|
|
@@ -53,74 +38,63 @@ class CorsikaRunner:
|
|
|
53
38
|
self.label = label
|
|
54
39
|
|
|
55
40
|
self.corsika_config = corsika_config
|
|
56
|
-
self._keep_seeds = keep_seeds
|
|
57
41
|
self._use_multipipe = use_multipipe
|
|
58
42
|
self.curved_atmosphere_min_zenith_angle = curved_atmosphere_min_zenith_angle
|
|
59
43
|
|
|
60
|
-
self.
|
|
61
|
-
self.
|
|
62
|
-
|
|
63
|
-
self.runner_service = RunnerServices(corsika_config, label)
|
|
64
|
-
self._directory = self.runner_service.load_data_directories("corsika")
|
|
44
|
+
self.runner_service = RunnerServices(corsika_config, run_type="corsika", label=label)
|
|
45
|
+
self.file_list = None
|
|
65
46
|
|
|
66
|
-
def
|
|
67
|
-
self, run_number=None, extra_commands=None, input_file=None, use_pfp=True
|
|
68
|
-
):
|
|
47
|
+
def prepare_run(self, run_number, sub_script, extra_commands=None, corsika_file=None):
|
|
69
48
|
"""
|
|
70
|
-
Prepare
|
|
49
|
+
Prepare CORSIKA run script and run directory.
|
|
50
|
+
|
|
51
|
+
The CORSIKA run directory includes all input files needed for the simulation.
|
|
71
52
|
|
|
72
53
|
Parameters
|
|
73
54
|
----------
|
|
74
|
-
use_pfp: bool
|
|
75
|
-
Whether to use the preprocessor in preparing the CORSIKA input file
|
|
76
55
|
run_number: int
|
|
77
56
|
Run number.
|
|
57
|
+
sub_script: str or Path
|
|
58
|
+
Path to the CORSIKA run script to be created.
|
|
59
|
+
corsika_file: str or Path
|
|
60
|
+
Path to the multipipe script (used only if use_multipipe is True).
|
|
78
61
|
extra_commands: str
|
|
79
62
|
Additional commands for running simulations.
|
|
80
|
-
|
|
81
|
-
Returns
|
|
82
|
-
-------
|
|
83
|
-
Path:
|
|
84
|
-
Full path of the run script file.
|
|
85
63
|
"""
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)
|
|
95
|
-
corsika_input_file = self.corsika_config.generate_corsika_input_file(
|
|
96
|
-
use_multipipe=self._use_multipipe, use_test_seeds=self._keep_seeds
|
|
64
|
+
self.file_list = self.runner_service.load_files(run_number=run_number)
|
|
65
|
+
|
|
66
|
+
self.corsika_config.generate_corsika_input_file(
|
|
67
|
+
self._use_multipipe,
|
|
68
|
+
self.runner_service.get_file_name("corsika_input", run_number=run_number),
|
|
69
|
+
self.runner_service.get_file_name("corsika_output", run_number=run_number)
|
|
70
|
+
if not self._use_multipipe
|
|
71
|
+
else corsika_file,
|
|
97
72
|
)
|
|
98
73
|
|
|
99
|
-
|
|
100
|
-
corsika_input_tmp_name = self.corsika_config.get_corsika_config_file_name(
|
|
101
|
-
file_type="config_tmp", run_number=self.corsika_config.run_number
|
|
102
|
-
)
|
|
103
|
-
corsika_input_tmp_file = self._directory["inputs"].joinpath(corsika_input_tmp_name)
|
|
104
|
-
# CORSIKA log file naming (temporary and final)
|
|
105
|
-
corsika_log_tmp_file = (
|
|
106
|
-
self._directory["data"]
|
|
107
|
-
.joinpath(f"run{self.corsika_config.run_number:06}")
|
|
108
|
-
.joinpath(f"run{self.corsika_config.run_number}.log")
|
|
109
|
-
)
|
|
110
|
-
corsika_log_file = self.get_file_name(
|
|
111
|
-
file_type="corsika_log", run_number=self.corsika_config.run_number
|
|
112
|
-
)
|
|
74
|
+
self._logger.debug(f"Extra commands to be added to the run script: {extra_commands}")
|
|
113
75
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
self.corsika_config.run_number, corsika_input_tmp_file
|
|
118
|
-
)
|
|
76
|
+
corsika_run_dir = self.runner_service.get_file_name(
|
|
77
|
+
"corsika_output", run_number=run_number
|
|
78
|
+
).parent
|
|
119
79
|
|
|
120
|
-
self.
|
|
121
|
-
self._logger.debug(f"CORSIKA data will be set to {self._directory['data']}")
|
|
80
|
+
self._export_run_script(run_number, sub_script, corsika_run_dir, extra_commands)
|
|
122
81
|
|
|
123
|
-
|
|
82
|
+
def _corsika_executable(self):
|
|
83
|
+
"""Get the CORSIKA executable path."""
|
|
84
|
+
if self.corsika_config.use_curved_atmosphere:
|
|
85
|
+
self._logger.debug("Using curved-atmosphere CORSIKA binary.")
|
|
86
|
+
return Path(settings.config.corsika_exe_curved)
|
|
87
|
+
self._logger.debug("Using flat-atmosphere CORSIKA binary.")
|
|
88
|
+
return Path(settings.config.corsika_exe)
|
|
89
|
+
|
|
90
|
+
def _export_run_script(self, run_number, sub_script, corsika_run_dir, extra_commands):
|
|
91
|
+
"""Export CORSIKA run script."""
|
|
92
|
+
corsika_log_file = self.runner_service.get_file_name(
|
|
93
|
+
"corsika_log", run_number=run_number
|
|
94
|
+
).with_suffix("") # remove .gz from log file
|
|
95
|
+
corsika_input = self.runner_service.get_file_name("corsika_input", run_number=run_number)
|
|
96
|
+
sub_script = Path(sub_script)
|
|
97
|
+
with open(sub_script, "w", encoding="utf-8") as file:
|
|
124
98
|
file.write("#!/usr/bin/env bash\n")
|
|
125
99
|
file.write("set -e\n")
|
|
126
100
|
file.write("set -o pipefail\n")
|
|
@@ -133,136 +107,19 @@ class CorsikaRunner:
|
|
|
133
107
|
file.write(f"{extra_commands}\n")
|
|
134
108
|
file.write("# End of extras\n\n")
|
|
135
109
|
|
|
136
|
-
file.write(f"export CORSIKA_DATA={
|
|
110
|
+
file.write(f"export CORSIKA_DATA={corsika_run_dir}\n")
|
|
137
111
|
file.write('mkdir -p "$CORSIKA_DATA"\n')
|
|
138
112
|
file.write('cd "$CORSIKA_DATA" || exit 2\n')
|
|
139
|
-
if use_pfp:
|
|
140
|
-
file.write("\n# Running pfp\n")
|
|
141
|
-
file.write(pfp_command)
|
|
142
|
-
file.write("\n# Replacing the XXXXXX placeholder with the run number\n")
|
|
143
|
-
file.write(
|
|
144
|
-
f"sed -i 's/XXXXXX/{self.corsika_config.run_number:06}/g' "
|
|
145
|
-
f"{corsika_input_tmp_file}\n"
|
|
146
|
-
)
|
|
147
|
-
else:
|
|
148
|
-
file.write("\n# Copying CORSIKA input file to run location\n")
|
|
149
|
-
file.write(f"cp {corsika_input_file} {corsika_input_tmp_file}")
|
|
150
|
-
file.write("\n# Running corsika_autoinputs\n")
|
|
151
|
-
file.write(autoinputs_command)
|
|
152
|
-
file.write("\n# Moving log files to the corsika log directory\n")
|
|
153
|
-
file.write(f"gzip {corsika_log_tmp_file}\n")
|
|
154
|
-
file.write(f"mv -v {corsika_log_tmp_file}.gz {corsika_log_file}\n")
|
|
155
|
-
|
|
156
|
-
file.write('\necho "RUNTIME: $SECONDS"\n')
|
|
157
|
-
|
|
158
|
-
script_file_path.chmod(script_file_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP)
|
|
159
|
-
return script_file_path
|
|
160
113
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
def _get_pfp_command(self, input_tmp_file, corsika_input_file):
|
|
166
|
-
"""
|
|
167
|
-
Get pfp pre-processor command.
|
|
168
|
-
|
|
169
|
-
pfp is a pre-processor tool and part of sim_telarray.
|
|
170
|
-
|
|
171
|
-
Parameters
|
|
172
|
-
----------
|
|
173
|
-
input_tmp_file: Path
|
|
174
|
-
Temporary input file.
|
|
175
|
-
|
|
176
|
-
Returns
|
|
177
|
-
-------
|
|
178
|
-
str
|
|
179
|
-
pfp command.
|
|
180
|
-
"""
|
|
181
|
-
cmd = self._simtel_path.joinpath("sim_telarray/bin/pfp")
|
|
182
|
-
cmd = str(cmd) + f" -V -DWITHOUT_MULTIPIPE - < {corsika_input_file}"
|
|
183
|
-
cmd += f" > {input_tmp_file} || exit\n"
|
|
184
|
-
return cmd
|
|
185
|
-
|
|
186
|
-
def _get_autoinputs_command(self, run_number, input_tmp_file):
|
|
187
|
-
"""
|
|
188
|
-
Get autoinputs command.
|
|
189
|
-
|
|
190
|
-
corsika_autoinputs is a tool to generate random seeds and user/host dependent
|
|
191
|
-
parameters for CORSIKA configuration.
|
|
192
|
-
|
|
193
|
-
Parameters
|
|
194
|
-
----------
|
|
195
|
-
run_number: int
|
|
196
|
-
Run number.
|
|
197
|
-
input_tmp_file: Path
|
|
198
|
-
Temporary input file.
|
|
199
|
-
|
|
200
|
-
Returns
|
|
201
|
-
-------
|
|
202
|
-
str
|
|
203
|
-
autoinputs command.
|
|
204
|
-
"""
|
|
205
|
-
if self.corsika_config.use_curved_atmosphere:
|
|
206
|
-
corsika_bin_path = self._simtel_path.joinpath("corsika-run/corsika-curved")
|
|
207
|
-
self._logger.debug("Using curved-atmosphere CORSIKA binary.")
|
|
208
|
-
else:
|
|
209
|
-
corsika_bin_path = self._simtel_path.joinpath("corsika-run/corsika")
|
|
210
|
-
self._logger.debug("Using flat-atmosphere CORSIKA binary.")
|
|
211
|
-
|
|
212
|
-
log_file = self.get_file_name(file_type="log", run_number=run_number)
|
|
213
|
-
if self._use_multipipe:
|
|
214
|
-
log_file = log_file.with_name(f"multipipe_{log_file.name}")
|
|
215
|
-
|
|
216
|
-
cmd = self._simtel_path.joinpath("sim_telarray/bin/corsika_autoinputs")
|
|
217
|
-
cmd = str(cmd) + f" --run {corsika_bin_path}"
|
|
218
|
-
cmd += f" -R {run_number}"
|
|
219
|
-
cmd += ' -p "$CORSIKA_DATA"'
|
|
220
|
-
if self._keep_seeds:
|
|
221
|
-
logging.warning(
|
|
222
|
-
"Using --keep-seeds option in corsika_autoinputs is not recommended. "
|
|
223
|
-
"It should only be used for testing purposes."
|
|
114
|
+
file.write("\n# Running corsika\n")
|
|
115
|
+
file.write(
|
|
116
|
+
f"{self._corsika_executable()} < {corsika_input} > {corsika_log_file} 2>&1\n"
|
|
224
117
|
)
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
cmd += " || exit 1\n"
|
|
228
|
-
return cmd
|
|
118
|
+
file.write("\n# Cleanup\n")
|
|
119
|
+
file.write(f"gzip {corsika_log_file}\n")
|
|
229
120
|
|
|
230
|
-
|
|
231
|
-
self,
|
|
232
|
-
simulation_software="corsika",
|
|
233
|
-
file_type=None,
|
|
234
|
-
run_number=None,
|
|
235
|
-
mode="",
|
|
236
|
-
model_version_index=0,
|
|
237
|
-
):
|
|
238
|
-
"""
|
|
239
|
-
Get the full path of a file for a given run number.
|
|
240
|
-
|
|
241
|
-
Parameters
|
|
242
|
-
----------
|
|
243
|
-
simulation_software: str
|
|
244
|
-
Simulation software.
|
|
245
|
-
file_type: str
|
|
246
|
-
File type.
|
|
247
|
-
run_number: int
|
|
248
|
-
Run number.
|
|
249
|
-
model_version_index: int
|
|
250
|
-
Index of the model version.
|
|
251
|
-
This is used to select the correct simulator_array instance in case
|
|
252
|
-
multiple array models are simulated.
|
|
121
|
+
file.write('\necho "RUNTIME: $SECONDS"\n')
|
|
253
122
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
File name with full path.
|
|
258
|
-
"""
|
|
259
|
-
if simulation_software.lower() != "corsika":
|
|
260
|
-
raise ValueError(
|
|
261
|
-
f"simulation_software ({simulation_software}) is not supported in CorsikaRunner"
|
|
262
|
-
)
|
|
263
|
-
return self.runner_service.get_file_name(
|
|
264
|
-
file_type=file_type,
|
|
265
|
-
run_number=run_number,
|
|
266
|
-
mode=mode,
|
|
267
|
-
_model_version_index=model_version_index,
|
|
268
|
-
)
|
|
123
|
+
def get_resources(self, sub_out_file):
|
|
124
|
+
"""Return computing resources used."""
|
|
125
|
+
return self.runner_service.get_resources(sub_out_file)
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import stat
|
|
5
|
-
from pathlib import Path
|
|
6
5
|
|
|
7
6
|
import simtools.utils.general as gen
|
|
8
|
-
from simtools
|
|
7
|
+
from simtools import settings
|
|
8
|
+
from simtools.runners import corsika_runner, runner_services, simtel_runner
|
|
9
9
|
from simtools.simtel.simulator_array import SimulatorArray
|
|
10
10
|
|
|
11
11
|
|
|
@@ -21,49 +21,40 @@ class CorsikaSimtelRunner:
|
|
|
21
21
|
corsika_config : CorsikaConfig or list of CorsikaConfig
|
|
22
22
|
A list of "CorsikaConfig" instances which
|
|
23
23
|
contain the CORSIKA configuration parameters.
|
|
24
|
-
simtel_path : str or Path
|
|
25
|
-
Location of the sim_telarray package.
|
|
26
24
|
label : str
|
|
27
25
|
Label.
|
|
28
|
-
keep_seeds : bool
|
|
29
|
-
Use seeds based on run number and primary particle. If False, use sim_telarray seeds.
|
|
30
26
|
use_multipipe : bool
|
|
31
27
|
Use multipipe to run CORSIKA and sim_telarray.
|
|
32
|
-
sim_telarray_seeds : dict
|
|
33
28
|
Dictionary with configuration for sim_telarray random instrument setup.
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
is_calibration_run : bool
|
|
30
|
+
Flag to indicate if this is a calibration run.
|
|
36
31
|
"""
|
|
37
32
|
|
|
38
33
|
def __init__(
|
|
39
34
|
self,
|
|
40
35
|
corsika_config,
|
|
41
|
-
simtel_path,
|
|
42
36
|
label=None,
|
|
43
|
-
keep_seeds=False,
|
|
44
|
-
use_multipipe=False,
|
|
45
|
-
sim_telarray_seeds=None,
|
|
46
37
|
sequential=False,
|
|
47
|
-
calibration_config=None,
|
|
48
38
|
curved_atmosphere_min_zenith_angle=None,
|
|
39
|
+
is_calibration_run=False,
|
|
49
40
|
):
|
|
50
41
|
self._logger = logging.getLogger(__name__)
|
|
51
42
|
self.corsika_config = gen.ensure_iterable(corsika_config)
|
|
52
43
|
# the base corsika config is the one used to define the CORSIKA specific parameters.
|
|
53
44
|
# The others are used for the array configurations.
|
|
54
45
|
self.base_corsika_config = self.corsika_config[0]
|
|
55
|
-
self._simtel_path = simtel_path
|
|
56
|
-
self.sim_telarray_seeds = sim_telarray_seeds
|
|
57
46
|
self.label = label
|
|
58
47
|
self.sequential = "--sequential" if sequential else ""
|
|
59
48
|
|
|
60
|
-
self.
|
|
61
|
-
|
|
49
|
+
self.runner_service = runner_services.RunnerServices(
|
|
50
|
+
self.base_corsika_config, run_type="multi_pipe", label=label
|
|
51
|
+
)
|
|
52
|
+
self.file_list = None
|
|
53
|
+
|
|
54
|
+
self.corsika_runner = corsika_runner.CorsikaRunner(
|
|
62
55
|
corsika_config=self.base_corsika_config,
|
|
63
|
-
simtel_path=simtel_path,
|
|
64
56
|
label=label,
|
|
65
|
-
|
|
66
|
-
use_multipipe=use_multipipe,
|
|
57
|
+
use_multipipe=True,
|
|
67
58
|
curved_atmosphere_min_zenith_angle=curved_atmosphere_min_zenith_angle,
|
|
68
59
|
)
|
|
69
60
|
# The simulator array should be defined for every CORSIKA configuration
|
|
@@ -73,17 +64,12 @@ class CorsikaSimtelRunner:
|
|
|
73
64
|
self.simulator_array.append(
|
|
74
65
|
SimulatorArray(
|
|
75
66
|
corsika_config=_corsika_config,
|
|
76
|
-
simtel_path=simtel_path,
|
|
77
67
|
label=label,
|
|
78
|
-
|
|
79
|
-
sim_telarray_seeds=sim_telarray_seeds,
|
|
80
|
-
calibration_config=calibration_config,
|
|
68
|
+
is_calibration_run=is_calibration_run,
|
|
81
69
|
)
|
|
82
70
|
)
|
|
83
71
|
|
|
84
|
-
def
|
|
85
|
-
self, run_number=None, input_file=None, extra_commands=None, use_pfp=False
|
|
86
|
-
):
|
|
72
|
+
def prepare_run(self, run_number=None, sub_script=None, corsika_file=None, extra_commands=None):
|
|
87
73
|
"""
|
|
88
74
|
Get the full path of the run script file for a given run number.
|
|
89
75
|
|
|
@@ -91,21 +77,24 @@ class CorsikaSimtelRunner:
|
|
|
91
77
|
----------
|
|
92
78
|
run_number: int
|
|
93
79
|
Run number.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
-------
|
|
99
|
-
Path:
|
|
100
|
-
Full path of the run script file.
|
|
80
|
+
corsika_file: str or Path
|
|
81
|
+
Path to the CORSIKA input file.
|
|
82
|
+
extra_commands: str
|
|
83
|
+
Additional commands for running simulations.
|
|
101
84
|
"""
|
|
85
|
+
self.file_list = self.runner_service.load_files(run_number=run_number)
|
|
102
86
|
self._export_multipipe_script(run_number)
|
|
103
|
-
|
|
87
|
+
self.corsika_runner.prepare_run(
|
|
104
88
|
run_number=run_number,
|
|
105
|
-
|
|
89
|
+
sub_script=sub_script,
|
|
90
|
+
corsika_file=self.runner_service.get_file_name(
|
|
91
|
+
file_type="multi_pipe_script", run_number=run_number
|
|
92
|
+
)
|
|
93
|
+
if not corsika_file
|
|
94
|
+
else corsika_file,
|
|
106
95
|
extra_commands=extra_commands,
|
|
107
|
-
use_pfp=use_pfp,
|
|
108
96
|
)
|
|
97
|
+
self.update_file_list_from_runners()
|
|
109
98
|
|
|
110
99
|
def _export_multipipe_script(self, run_number):
|
|
111
100
|
"""
|
|
@@ -121,44 +110,29 @@ class CorsikaSimtelRunner:
|
|
|
121
110
|
Path:
|
|
122
111
|
Full path of the run script file.
|
|
123
112
|
"""
|
|
124
|
-
multipipe_file =
|
|
125
|
-
|
|
113
|
+
multipipe_file = self.runner_service.get_file_name(
|
|
114
|
+
"multi_pipe_config", run_number=run_number
|
|
126
115
|
)
|
|
127
|
-
|
|
128
116
|
with open(multipipe_file, "w", encoding="utf-8") as file:
|
|
129
117
|
for simulator_array in self.simulator_array:
|
|
118
|
+
log_file = simulator_array.runner_service.get_file_name(
|
|
119
|
+
file_type="sim_telarray_log", run_number=run_number
|
|
120
|
+
)
|
|
130
121
|
run_command = simulator_array.make_run_command(
|
|
131
122
|
run_number=run_number,
|
|
132
|
-
input_file="-", # instruct sim_telarray to take input from
|
|
133
|
-
|
|
123
|
+
input_file="-", # instruct sim_telarray to take input from stdout
|
|
124
|
+
)
|
|
125
|
+
file.write(
|
|
126
|
+
f"{simtel_runner.sim_telarray_env_as_string()} "
|
|
127
|
+
+ " ".join(run_command)
|
|
128
|
+
+ f" | gzip > {log_file} 2>&1\n"
|
|
134
129
|
)
|
|
135
|
-
file.write(f"{run_command}")
|
|
136
130
|
file.write("\n")
|
|
137
|
-
self._logger.info(f"Multipipe script: {multipipe_file}")
|
|
138
|
-
self._write_multipipe_script(multipipe_file)
|
|
139
|
-
|
|
140
|
-
@staticmethod
|
|
141
|
-
def _determine_pointing_option(label):
|
|
142
|
-
"""
|
|
143
|
-
Determine the pointing option for sim_telarray.
|
|
144
131
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
label: str
|
|
148
|
-
Label of the simulation.
|
|
149
|
-
|
|
150
|
-
Returns
|
|
151
|
-
-------
|
|
152
|
-
str:
|
|
153
|
-
Pointing option.
|
|
154
|
-
"""
|
|
155
|
-
try:
|
|
156
|
-
return any(pointing in label for pointing in ["divergent", "convergent"])
|
|
157
|
-
except TypeError: # allow for pointing_option to be None
|
|
158
|
-
pass
|
|
159
|
-
return False
|
|
132
|
+
self._logger.info(f"Multipipe script: {multipipe_file}")
|
|
133
|
+
self._write_multipipe_script(multipipe_file, run_number)
|
|
160
134
|
|
|
161
|
-
def _write_multipipe_script(self, multipipe_file):
|
|
135
|
+
def _write_multipipe_script(self, multipipe_file, run_number):
|
|
162
136
|
"""
|
|
163
137
|
Write script used to call the multipipe_corsika command.
|
|
164
138
|
|
|
@@ -166,61 +140,56 @@ class CorsikaSimtelRunner:
|
|
|
166
140
|
----------
|
|
167
141
|
multipipe_file: str or Path
|
|
168
142
|
The name of the multipipe file which contains all of the multipipe commands.
|
|
143
|
+
run_number: int
|
|
144
|
+
Run number.
|
|
169
145
|
"""
|
|
170
|
-
multipipe_script =
|
|
171
|
-
"
|
|
146
|
+
multipipe_script = self.runner_service.get_file_name(
|
|
147
|
+
"multi_pipe_script", run_number=run_number
|
|
172
148
|
)
|
|
173
149
|
with open(multipipe_script, "w", encoding="utf-8") as file:
|
|
174
|
-
multipipe_command =
|
|
175
|
-
f"
|
|
150
|
+
multipipe_command = settings.config.sim_telarray_path.joinpath(
|
|
151
|
+
f"bin/multipipe_corsika -c {multipipe_file} {self.sequential} "
|
|
176
152
|
"|| echo 'Fan-out failed'"
|
|
177
153
|
)
|
|
178
154
|
file.write(f"{multipipe_command}")
|
|
179
155
|
|
|
180
156
|
multipipe_script.chmod(multipipe_script.stat().st_mode | stat.S_IEXEC)
|
|
181
157
|
|
|
182
|
-
def
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
mode=None,
|
|
188
|
-
model_version_index=0,
|
|
189
|
-
):
|
|
158
|
+
def get_resources(self, run_number=None):
|
|
159
|
+
"""Return computing resources used."""
|
|
160
|
+
return self.corsika_runner.get_resources(run_number)
|
|
161
|
+
|
|
162
|
+
def update_file_list_from_runners(self):
|
|
190
163
|
"""
|
|
191
|
-
Get
|
|
164
|
+
Get list of generated files (independent of type).
|
|
165
|
+
|
|
166
|
+
Includes file lists from all runners.
|
|
192
167
|
|
|
193
168
|
Parameters
|
|
194
169
|
----------
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
file_type: str
|
|
198
|
-
File type.
|
|
199
|
-
run_number: int
|
|
200
|
-
Run number.
|
|
201
|
-
mode: str
|
|
202
|
-
Mode to use for the file name.
|
|
203
|
-
model_version_index: int
|
|
204
|
-
Index of the model version.
|
|
205
|
-
This is used to select the correct simulator_array instance
|
|
206
|
-
in case multiple array models are simulated.
|
|
170
|
+
file_type : str
|
|
171
|
+
File type to be listed.
|
|
207
172
|
|
|
208
173
|
Returns
|
|
209
174
|
-------
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
"""
|
|
213
|
-
if simulation_software is None:
|
|
214
|
-
# preference to sim_telarray output (multipipe)
|
|
215
|
-
simulation_software = "sim_telarray" if self.simulator_array else "corsika"
|
|
216
|
-
|
|
217
|
-
runner = (
|
|
218
|
-
self.corsika_runner
|
|
219
|
-
if simulation_software == "corsika"
|
|
220
|
-
else self.simulator_array[model_version_index]
|
|
221
|
-
)
|
|
222
|
-
return runner.get_file_name(file_type=file_type, run_number=run_number, mode=mode)
|
|
175
|
+
list
|
|
176
|
+
List with the full path of all output files.
|
|
223
177
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
178
|
+
"""
|
|
179
|
+
if self.file_list is None:
|
|
180
|
+
self.file_list = self.corsika_runner.file_list
|
|
181
|
+
else:
|
|
182
|
+
self.file_list.update(self.corsika_runner.file_list)
|
|
183
|
+
|
|
184
|
+
for simulator_array in self.simulator_array:
|
|
185
|
+
_tmp_list = simulator_array.file_list
|
|
186
|
+
for key, data in _tmp_list.items():
|
|
187
|
+
if key in self.file_list:
|
|
188
|
+
# in case of multiple sim_telarray instances, make list of files
|
|
189
|
+
if not isinstance(self.file_list[key], list):
|
|
190
|
+
self.file_list[key] = [self.file_list[key]]
|
|
191
|
+
self.file_list[key].append(data)
|
|
192
|
+
else:
|
|
193
|
+
self.file_list[key] = [data]
|
|
194
|
+
|
|
195
|
+
return self.file_list
|