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.
Files changed (138) hide show
  1. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/METADATA +6 -1
  2. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/RECORD +135 -130
  3. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/WHEEL +1 -1
  4. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/entry_points.txt +3 -2
  5. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/licenses/LICENSE +1 -1
  6. simtools/_version.py +2 -2
  7. simtools/application_control.py +35 -7
  8. simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
  9. simtools/applications/db_add_file_to_db.py +1 -1
  10. simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
  11. simtools/applications/db_add_value_from_json_to_db.py +1 -1
  12. simtools/applications/db_generate_compound_indexes.py +1 -1
  13. simtools/applications/db_get_array_layouts_from_db.py +3 -7
  14. simtools/applications/db_get_file_from_db.py +1 -1
  15. simtools/applications/db_get_parameter_from_db.py +1 -1
  16. simtools/applications/db_inspect_databases.py +1 -1
  17. simtools/applications/db_upload_model_repository.py +1 -1
  18. simtools/applications/derive_ctao_array_layouts.py +1 -2
  19. simtools/applications/{calculate_incident_angles.py → derive_incident_angle.py} +16 -18
  20. simtools/applications/derive_mirror_rnda.py +112 -180
  21. simtools/applications/derive_psf_parameters.py +0 -1
  22. simtools/applications/derive_pulse_shape_parameters.py +0 -1
  23. simtools/applications/derive_trigger_rates.py +1 -1
  24. simtools/applications/docs_produce_array_element_report.py +2 -8
  25. simtools/applications/docs_produce_calibration_reports.py +1 -3
  26. simtools/applications/docs_produce_model_parameter_reports.py +0 -2
  27. simtools/applications/docs_produce_simulation_configuration_report.py +1 -3
  28. simtools/applications/generate_array_config.py +0 -1
  29. simtools/applications/generate_corsika_histograms.py +79 -229
  30. simtools/applications/generate_regular_arrays.py +76 -69
  31. simtools/applications/generate_simtel_event_data.py +2 -2
  32. simtools/applications/maintain_simulation_model_add_production.py +2 -2
  33. simtools/applications/maintain_simulation_model_write_array_element_positions.py +87 -0
  34. simtools/applications/plot_array_layout.py +5 -111
  35. simtools/applications/plot_simulated_event_distributions.py +57 -0
  36. simtools/applications/plot_tabular_data.py +0 -1
  37. simtools/applications/plot_tabular_data_for_model_parameter.py +1 -6
  38. simtools/applications/production_derive_corsika_limits.py +1 -1
  39. simtools/applications/production_generate_grid.py +0 -1
  40. simtools/applications/run_application.py +1 -1
  41. simtools/applications/simulate_flasher.py +3 -15
  42. simtools/applications/simulate_illuminator.py +2 -11
  43. simtools/applications/simulate_pedestals.py +1 -5
  44. simtools/applications/simulate_prod.py +8 -11
  45. simtools/applications/simulate_prod_htcondor_generator.py +1 -1
  46. simtools/applications/submit_array_layouts.py +2 -4
  47. simtools/applications/submit_data_from_external.py +2 -1
  48. simtools/applications/submit_model_parameter_from_external.py +1 -3
  49. simtools/applications/validate_camera_efficiency.py +28 -28
  50. simtools/applications/validate_camera_fov.py +0 -1
  51. simtools/applications/validate_cumulative_psf.py +1 -5
  52. simtools/applications/validate_optics.py +2 -14
  53. simtools/atmosphere.py +83 -0
  54. simtools/camera/camera_efficiency.py +171 -53
  55. simtools/camera/single_photon_electron_spectrum.py +8 -7
  56. simtools/configuration/commandline_parser.py +82 -11
  57. simtools/configuration/configurator.py +6 -11
  58. simtools/constants.py +5 -0
  59. simtools/corsika/corsika_config.py +100 -202
  60. simtools/corsika/corsika_histograms.py +561 -1708
  61. simtools/corsika/primary_particle.py +1 -1
  62. simtools/data_model/metadata_collector.py +5 -2
  63. simtools/data_model/metadata_model.py +0 -4
  64. simtools/data_model/model_data_writer.py +59 -64
  65. simtools/data_model/schema.py +2 -0
  66. simtools/data_model/validate_data.py +1 -3
  67. simtools/db/db_handler.py +23 -10
  68. simtools/db/mongo_db.py +2 -2
  69. simtools/dependencies.py +81 -38
  70. simtools/io/ascii_handler.py +55 -5
  71. simtools/io/io_handler.py +23 -12
  72. simtools/io/table_handler.py +1 -1
  73. simtools/job_execution/job_manager.py +154 -79
  74. simtools/job_execution/process_pool.py +137 -0
  75. simtools/layout/array_layout.py +4 -13
  76. simtools/layout/array_layout_utils.py +348 -57
  77. simtools/model/array_model.py +23 -63
  78. simtools/model/calibration_model.py +4 -8
  79. simtools/model/legacy_model_parameter.py +134 -0
  80. simtools/model/model_parameter.py +147 -86
  81. simtools/model/model_utils.py +40 -6
  82. simtools/model/site_model.py +4 -8
  83. simtools/model/telescope_model.py +10 -16
  84. simtools/production_configuration/derive_corsika_limits.py +6 -11
  85. simtools/production_configuration/interpolation_handler.py +16 -16
  86. simtools/ray_tracing/incident_angles.py +92 -17
  87. simtools/ray_tracing/mirror_panel_psf.py +338 -222
  88. simtools/ray_tracing/psf_analysis.py +62 -48
  89. simtools/ray_tracing/psf_parameter_optimisation.py +3 -3
  90. simtools/ray_tracing/ray_tracing.py +43 -25
  91. simtools/reporting/docs_auto_report_generator.py +8 -13
  92. simtools/reporting/docs_read_parameters.py +2 -8
  93. simtools/runners/corsika_runner.py +52 -195
  94. simtools/runners/corsika_simtel_runner.py +77 -108
  95. simtools/runners/runner_services.py +214 -213
  96. simtools/runners/simtel_runner.py +27 -160
  97. simtools/runners/simtools_runner.py +11 -73
  98. simtools/schemas/application_workflow.metaschema.yml +8 -0
  99. simtools/settings.py +173 -0
  100. simtools/{io/eventio_handler.py → sim_events/file_info.py} +3 -3
  101. simtools/{simtel/simtel_io_event_histograms.py → sim_events/histograms.py} +25 -15
  102. simtools/{simtel/simtel_io_event_reader.py → sim_events/reader.py} +20 -17
  103. simtools/{simtel/simtel_io_event_writer.py → sim_events/writer.py} +84 -25
  104. simtools/simtel/pulse_shapes.py +7 -2
  105. simtools/simtel/simtel_config_writer.py +79 -91
  106. simtools/simtel/simtel_seeds.py +184 -0
  107. simtools/simtel/simtel_table_reader.py +6 -4
  108. simtools/simtel/simulator_array.py +114 -109
  109. simtools/simtel/simulator_camera_efficiency.py +68 -46
  110. simtools/simtel/simulator_light_emission.py +164 -132
  111. simtools/simtel/simulator_ray_tracing.py +80 -71
  112. simtools/simulator.py +137 -355
  113. simtools/telescope_trigger_rates.py +3 -4
  114. simtools/testing/assertions.py +84 -33
  115. simtools/testing/configuration.py +1 -2
  116. simtools/testing/helpers.py +2 -3
  117. simtools/testing/log_inspector.py +1 -0
  118. simtools/testing/sim_telarray_metadata.py +14 -12
  119. simtools/testing/validate_output.py +121 -42
  120. simtools/utils/general.py +43 -17
  121. simtools/utils/geometry.py +0 -77
  122. simtools/utils/names.py +5 -5
  123. simtools/utils/random.py +36 -0
  124. simtools/visualization/legend_handlers.py +7 -6
  125. simtools/visualization/plot_array_layout.py +91 -16
  126. simtools/visualization/plot_corsika_histograms.py +145 -605
  127. simtools/visualization/plot_incident_angles.py +48 -1
  128. simtools/visualization/plot_mirrors.py +1 -4
  129. simtools/visualization/plot_pixels.py +2 -4
  130. simtools/visualization/plot_psf.py +160 -19
  131. simtools/visualization/plot_simtel_event_histograms.py +4 -4
  132. simtools/visualization/plot_simtel_events.py +6 -11
  133. simtools/visualization/plot_tables.py +8 -19
  134. simtools/visualization/visualize.py +22 -2
  135. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +0 -160
  136. simtools/applications/print_version.py +0 -53
  137. simtools/io/hdf5_handler.py +0 -139
  138. {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.io import io_handler
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
- Generate run scripts and directories for CORSIKA simulations. Run simulations if requested.
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
- CorsikaRunner is configured through a CorsikaConfig instance.
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._simtel_path = Path(simtel_path)
61
- self.io_handler = io_handler.IOHandler()
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 prepare_run_script(
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 and write CORSIKA run script.
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
- if input_file is not None:
87
- self._logger.warning(
88
- "input_file parameter is not used in CorsikaRunner.prepare_run_script"
89
- )
90
- self.corsika_config.run_number = run_number
91
-
92
- script_file_path = self.get_file_name(
93
- file_type="sub_script", run_number=self.corsika_config.run_number
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
- # CORSIKA input file for a specific run, created by the preprocessor pfp
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
- if use_pfp:
115
- pfp_command = self._get_pfp_command(corsika_input_tmp_file, corsika_input_file)
116
- autoinputs_command = self._get_autoinputs_command(
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._logger.debug(f"Extra commands to be added to the run script: {extra_commands}")
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
- with open(script_file_path, "w", encoding="utf-8") as file:
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={self._directory['data']}\n")
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
- def get_resources(self, run_number=None):
162
- """Return computing resources used."""
163
- return self.runner_service.get_resources(run_number)
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
- cmd += " --keep-seeds"
226
- cmd += f" {input_tmp_file} | gzip > {log_file} 2>&1"
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
- def get_file_name(
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
- Returns
255
- -------
256
- str
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.runners.corsika_runner import CorsikaRunner
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
- calibration_config : dict
35
- Configuration for the calibration of the sim_telarray data.
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.base_corsika_config.set_output_file_and_directory(use_multipipe)
61
- self.corsika_runner = CorsikaRunner(
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
- keep_seeds=keep_seeds,
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
- use_multipipe=use_multipipe,
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 prepare_run_script(
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
- use_pfp: bool
95
- Whether to use the preprocessor in preparing the CORSIKA input file
96
-
97
- Returns
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
- return self.corsika_runner.prepare_run_script(
87
+ self.corsika_runner.prepare_run(
104
88
  run_number=run_number,
105
- input_file=input_file,
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 = Path(self.base_corsika_config.config_file_path.parent).joinpath(
125
- self.base_corsika_config.get_corsika_config_file_name("multipipe")
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 standard output
133
- weak_pointing=self._determine_pointing_option(self.label),
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
- Parameters
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 = Path(self.base_corsika_config.config_file_path.parent).joinpath(
171
- "run_cta_multipipe"
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 = Path(self._simtel_path).joinpath(
175
- f"sim_telarray/bin/multipipe_corsika -c {multipipe_file} {self.sequential} "
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 get_file_name(
183
- self,
184
- simulation_software=None,
185
- file_type=None,
186
- run_number=None,
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 the full path of a file for a given run number.
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
- simulation_software: str
196
- Simulation software.
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
- str
211
- File name with full path.
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
- def get_resources(self, run_number=None):
225
- """Return computing resources used."""
226
- return self.corsika_runner.get_resources(run_number)
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