gammasimtools 0.24.0__py3-none-any.whl → 0.26.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.24.0.dist-info → gammasimtools-0.26.0.dist-info}/METADATA +2 -1
  2. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/RECORD +134 -130
  3. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/entry_points.txt +3 -1
  4. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/licenses/LICENSE +1 -1
  5. simtools/_version.py +2 -2
  6. simtools/application_control.py +78 -0
  7. simtools/applications/calculate_incident_angles.py +0 -2
  8. simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -2
  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 +2 -6
  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/derive_mirror_rnda.py +1 -3
  20. simtools/applications/derive_psf_parameters.py +5 -1
  21. simtools/applications/derive_pulse_shape_parameters.py +194 -0
  22. simtools/applications/derive_trigger_rates.py +1 -1
  23. simtools/applications/docs_produce_array_element_report.py +2 -8
  24. simtools/applications/docs_produce_calibration_reports.py +1 -3
  25. simtools/applications/docs_produce_model_parameter_reports.py +0 -2
  26. simtools/applications/docs_produce_simulation_configuration_report.py +1 -3
  27. simtools/applications/generate_array_config.py +0 -1
  28. simtools/applications/generate_corsika_histograms.py +48 -235
  29. simtools/applications/generate_regular_arrays.py +5 -35
  30. simtools/applications/generate_simtel_event_data.py +2 -2
  31. simtools/applications/maintain_simulation_model_add_production.py +2 -2
  32. simtools/applications/maintain_simulation_model_write_array_element_positions.py +87 -0
  33. simtools/applications/plot_array_layout.py +64 -108
  34. simtools/applications/plot_simulated_event_distributions.py +57 -0
  35. simtools/applications/plot_tabular_data.py +0 -1
  36. simtools/applications/plot_tabular_data_for_model_parameter.py +1 -6
  37. simtools/applications/production_derive_corsika_limits.py +1 -1
  38. simtools/applications/production_generate_grid.py +0 -1
  39. simtools/applications/run_application.py +1 -1
  40. simtools/applications/simulate_flasher.py +3 -4
  41. simtools/applications/simulate_illuminator.py +0 -1
  42. simtools/applications/simulate_pedestals.py +2 -6
  43. simtools/applications/simulate_prod.py +9 -28
  44. simtools/applications/simulate_prod_htcondor_generator.py +8 -1
  45. simtools/applications/submit_array_layouts.py +7 -7
  46. simtools/applications/submit_model_parameter_from_external.py +1 -3
  47. simtools/applications/validate_camera_efficiency.py +0 -1
  48. simtools/applications/validate_camera_fov.py +0 -1
  49. simtools/applications/validate_cumulative_psf.py +0 -2
  50. simtools/applications/validate_file_using_schema.py +49 -123
  51. simtools/applications/validate_optics.py +0 -13
  52. simtools/camera/camera_efficiency.py +1 -6
  53. simtools/camera/single_photon_electron_spectrum.py +2 -1
  54. simtools/configuration/commandline_parser.py +43 -8
  55. simtools/configuration/configurator.py +6 -11
  56. simtools/corsika/corsika_config.py +204 -99
  57. simtools/corsika/corsika_histograms.py +411 -1735
  58. simtools/corsika/primary_particle.py +1 -1
  59. simtools/data_model/metadata_collector.py +5 -2
  60. simtools/data_model/metadata_model.py +0 -4
  61. simtools/data_model/model_data_writer.py +27 -17
  62. simtools/data_model/schema.py +112 -5
  63. simtools/data_model/validate_data.py +80 -48
  64. simtools/db/db_handler.py +19 -8
  65. simtools/db/db_model_upload.py +2 -1
  66. simtools/db/mongo_db.py +133 -42
  67. simtools/dependencies.py +83 -44
  68. simtools/io/ascii_handler.py +4 -2
  69. simtools/io/table_handler.py +1 -1
  70. simtools/job_execution/htcondor_script_generator.py +0 -2
  71. simtools/layout/array_layout.py +4 -12
  72. simtools/layout/array_layout_utils.py +227 -58
  73. simtools/model/array_model.py +37 -18
  74. simtools/model/calibration_model.py +0 -4
  75. simtools/model/legacy_model_parameter.py +134 -0
  76. simtools/model/model_parameter.py +24 -14
  77. simtools/model/model_repository.py +18 -5
  78. simtools/model/model_utils.py +1 -6
  79. simtools/model/site_model.py +0 -4
  80. simtools/model/telescope_model.py +6 -11
  81. simtools/production_configuration/derive_corsika_limits.py +6 -11
  82. simtools/production_configuration/interpolation_handler.py +16 -16
  83. simtools/ray_tracing/incident_angles.py +5 -11
  84. simtools/ray_tracing/mirror_panel_psf.py +3 -7
  85. simtools/ray_tracing/psf_analysis.py +29 -27
  86. simtools/ray_tracing/psf_parameter_optimisation.py +822 -680
  87. simtools/ray_tracing/ray_tracing.py +6 -15
  88. simtools/reporting/docs_auto_report_generator.py +8 -13
  89. simtools/reporting/docs_read_parameters.py +70 -16
  90. simtools/runners/corsika_runner.py +15 -10
  91. simtools/runners/corsika_simtel_runner.py +9 -8
  92. simtools/runners/runner_services.py +17 -7
  93. simtools/runners/simtel_runner.py +11 -58
  94. simtools/runners/simtools_runner.py +2 -4
  95. simtools/schemas/model_parameters/flasher_pulse_exp_decay.schema.yml +2 -0
  96. simtools/schemas/model_parameters/flasher_pulse_shape.schema.yml +50 -0
  97. simtools/schemas/model_parameters/flasher_pulse_width.schema.yml +2 -0
  98. simtools/schemas/simulation_models_info.schema.yml +2 -0
  99. simtools/settings.py +154 -0
  100. simtools/sim_events/file_info.py +128 -0
  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 +273 -0
  105. simtools/simtel/simtel_config_writer.py +146 -22
  106. simtools/simtel/simtel_table_reader.py +6 -4
  107. simtools/simtel/simulator_array.py +62 -23
  108. simtools/simtel/simulator_camera_efficiency.py +4 -6
  109. simtools/simtel/simulator_light_emission.py +101 -19
  110. simtools/simtel/simulator_ray_tracing.py +4 -10
  111. simtools/simulator.py +360 -353
  112. simtools/telescope_trigger_rates.py +3 -4
  113. simtools/testing/assertions.py +115 -8
  114. simtools/testing/configuration.py +2 -3
  115. simtools/testing/helpers.py +2 -3
  116. simtools/testing/log_inspector.py +5 -1
  117. simtools/testing/sim_telarray_metadata.py +1 -1
  118. simtools/testing/validate_output.py +69 -23
  119. simtools/utils/general.py +37 -0
  120. simtools/utils/geometry.py +0 -77
  121. simtools/utils/names.py +7 -9
  122. simtools/version.py +37 -0
  123. simtools/visualization/legend_handlers.py +21 -10
  124. simtools/visualization/plot_array_layout.py +312 -41
  125. simtools/visualization/plot_corsika_histograms.py +143 -605
  126. simtools/visualization/plot_mirrors.py +834 -0
  127. simtools/visualization/plot_pixels.py +2 -4
  128. simtools/visualization/plot_psf.py +0 -1
  129. simtools/visualization/plot_simtel_event_histograms.py +4 -4
  130. simtools/visualization/plot_simtel_events.py +6 -11
  131. simtools/visualization/plot_tables.py +8 -19
  132. simtools/visualization/visualize.py +22 -2
  133. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +0 -160
  134. simtools/applications/print_version.py +0 -53
  135. simtools/io/hdf5_handler.py +0 -139
  136. simtools/simtel/simtel_io_file_info.py +0 -62
  137. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/WHEEL +0 -0
  138. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/top_level.txt +0 -0
@@ -10,9 +10,12 @@ import numpy as np
10
10
 
11
11
  import simtools.utils.general as gen
12
12
  import simtools.version
13
- from simtools.io import ascii_handler
13
+ from simtools import dependencies, settings
14
+ from simtools.simtel.pulse_shapes import generate_pulse_from_rise_fall_times
14
15
  from simtools.utils import names
15
16
 
17
+ logger = logging.getLogger(__name__)
18
+
16
19
 
17
20
  def sim_telarray_random_seeds(seed, number):
18
21
  """
@@ -53,8 +56,6 @@ class SimtelConfigWriter:
53
56
  Layout name.
54
57
  label: str
55
58
  Instance label. Important for output file naming.
56
- simtel_path: str or Path
57
- Path to the sim_telarray installation directory.
58
59
  """
59
60
 
60
61
  TAB = " " * 3
@@ -67,7 +68,6 @@ class SimtelConfigWriter:
67
68
  telescope_model_name=None,
68
69
  telescope_design_model=None,
69
70
  label=None,
70
- simtel_path=None,
71
71
  ):
72
72
  """Initialize SimtelConfigWriter."""
73
73
  self._logger = logging.getLogger(__name__)
@@ -79,7 +79,6 @@ class SimtelConfigWriter:
79
79
  self._layout_name = layout_name
80
80
  self._telescope_model_name = telescope_model_name
81
81
  self._telescope_design_model = telescope_design_model
82
- self._simtel_path = simtel_path
83
82
 
84
83
  def write_telescope_config_file(
85
84
  self, config_file_path, parameters, telescope_name=None, telescope_design_model=None
@@ -121,6 +120,128 @@ class SimtelConfigWriter:
121
120
  ):
122
121
  file.write(f"{meta}\n")
123
122
 
123
+ @staticmethod
124
+ def write_light_pulse_table_gauss_exp_conv(
125
+ file_path,
126
+ width_ns,
127
+ exp_decay_ns,
128
+ fadc_sum_bins,
129
+ dt_ns=0.1,
130
+ rise_range=(0.1, 0.9),
131
+ fall_range=(0.9, 0.1),
132
+ time_margin_ns=10.0,
133
+ ):
134
+ """Write a pulse table for a Gaussian convolved with a causal exponential.
135
+
136
+ Parameters
137
+ ----------
138
+ file_path : str or pathlib.Path
139
+ Destination path of the ASCII pulse table to write. Parent directory must exist.
140
+ width_ns : float
141
+ Target rise time in ns between the fractional levels defined by ``rise_range``.
142
+ exp_decay_ns : float
143
+ Target fall time in ns between the fractional levels defined by ``fall_range``.
144
+ fadc_sum_bins : int
145
+ Length of the FADC integration window (treated as ns here) used to derive
146
+ the internal time sampling window of the solver as [-(margin), bins + margin].
147
+ dt_ns : float, optional
148
+ Time sampling step in ns for the generated pulse table.
149
+ rise_range : tuple[float, float], optional
150
+ Fractional amplitude bounds (low, high) for rise-time definition.
151
+ fall_range : tuple[float, float], optional
152
+ Fractional amplitude bounds (high, low) for fall-time definition.
153
+ time_margin_ns : float, optional
154
+ Margin in ns to add to both ends of the FADC window when ``fadc_sum_bins`` is given.
155
+
156
+ Returns
157
+ -------
158
+ pathlib.Path
159
+ The path to the created pulse table file.
160
+
161
+ Notes
162
+ -----
163
+ The underlying model is a Gaussian convolved with a causal exponential. The model
164
+ parameters (sigma, tau) are solved such that the normalized pulse matches the requested
165
+ rise and fall times. The pulse is normalized to a peak amplitude of 1.
166
+ """
167
+ if width_ns is None or exp_decay_ns is None:
168
+ raise ValueError("width_ns (rise 10-90) and exp_decay_ns (fall 90-10) are required")
169
+ logger.info(
170
+ "Generating pulse-shape table with "
171
+ f"rise{int(rise_range[0] * 100)}-{int(rise_range[1] * 100)}={width_ns} ns, "
172
+ f"fall{int(fall_range[0] * 100)}-{int(fall_range[1] * 100)}={exp_decay_ns} ns, "
173
+ f"dt={dt_ns} ns"
174
+ )
175
+ width = float(fadc_sum_bins)
176
+ t_start_ns = -abs(time_margin_ns + width)
177
+ t_stop_ns = +abs(time_margin_ns + width)
178
+ t, y = generate_pulse_from_rise_fall_times(
179
+ width_ns,
180
+ exp_decay_ns,
181
+ dt_ns=dt_ns,
182
+ rise_range=rise_range,
183
+ fall_range=fall_range,
184
+ t_start_ns=t_start_ns,
185
+ t_stop_ns=t_stop_ns,
186
+ center_on_peak=True,
187
+ )
188
+
189
+ return SimtelConfigWriter._write_ascii_pulse_table(file_path, t, y)
190
+
191
+ @staticmethod
192
+ def write_angular_distribution_table_lambertian(
193
+ file_path,
194
+ max_angle_deg,
195
+ n_samples=100,
196
+ ):
197
+ """Write a Lambertian angular distribution table (I(t) ~ cos(t)).
198
+
199
+ Parameters
200
+ ----------
201
+ file_path : str or pathlib.Path
202
+ Destination path of the ASCII table to write. Parent directory must exist.
203
+ max_angle_deg : float
204
+ Maximum angle (deg) for the distribution sampling range [0, max_angle_deg].
205
+ n_samples : int, optional
206
+ Number of samples (including end point) from 0 to max_angle_deg. Default 100.
207
+
208
+ Returns
209
+ -------
210
+ pathlib.Path
211
+ Path to created angular distribution table.
212
+ """
213
+ logger.info(
214
+ f"Generating Lambertian angular distribution table up to {max_angle_deg} deg "
215
+ f"with {n_samples} samples"
216
+ )
217
+ angles = np.linspace(0.0, float(max_angle_deg), int(n_samples), dtype=float)
218
+ intensities = np.cos(np.deg2rad(angles))
219
+ intensities[intensities < 0] = 0.0
220
+ if intensities.max() > 0:
221
+ intensities /= intensities.max()
222
+
223
+ return SimtelConfigWriter._write_ascii_angle_distribution_table(
224
+ file_path, angles, intensities
225
+ )
226
+
227
+ @staticmethod
228
+ def _write_ascii_pulse_table(file_path, t, y):
229
+ """Write two-column ASCII pulse table."""
230
+ with open(file_path, "w", encoding="utf-8") as fh:
231
+ fh.write("# time[ns] amplitude\n")
232
+ for ti, yi in zip(t, y):
233
+ fh.write(f"{ti:.6f} {yi:.8f}\n")
234
+ return Path(file_path)
235
+
236
+ @staticmethod
237
+ def _write_ascii_angle_distribution_table(file_path, angles, intensities):
238
+ """Write two-column ASCII angular distribution table."""
239
+ with open(file_path, "w", encoding="utf-8") as fh:
240
+ fh.write("# angle[deg] relative_intensity\n")
241
+ for a, i in zip(angles, intensities):
242
+ fh.write(f"{a:.6f} {i:.8f}\n")
243
+ return Path(file_path)
244
+
124
245
  def _get_parameters_for_sim_telarray(self, parameters, config_file_path):
125
246
  """
126
247
  Convert parameter dictionary to sim_telarray configuration file format.
@@ -176,28 +297,24 @@ class SimtelConfigWriter:
176
297
  Model parameters in sim_telarray format including flasher parameters.
177
298
 
178
299
  """
179
- if "flasher_pulse_shape" not in parameters and "flasher_pulse_width" not in parameters:
300
+ if "flasher_pulse_shape" not in parameters:
180
301
  return simtel_par
181
302
 
182
303
  mapping = {
183
304
  "gauss": "laser_pulse_sigtime",
184
305
  "tophat": "laser_pulse_twidth",
306
+ "gauss-exponential": "laser_pulse_sigtime",
185
307
  }
186
308
 
187
- shape = parameters.get("flasher_pulse_shape", {}).get("value", "").lower()
188
- if "exponential" in shape:
189
- simtel_par["laser_pulse_exptime"] = parameters.get("flasher_pulse_exp_decay", {}).get(
190
- "value", 0.0
191
- )
192
- else:
193
- simtel_par["laser_pulse_exptime"] = 0.0
309
+ shape_value = parameters.get("flasher_pulse_shape", {}).get("value")
310
+ shape = shape_value[0].lower()
311
+ width = shape_value[1]
312
+ exp_decay = shape_value[2]
194
313
 
195
- width = parameters.get("flasher_pulse_width", {}).get("value", 0.0)
314
+ simtel_par["laser_pulse_exptime"] = exp_decay if ("exponential" in shape) else 0.0
196
315
 
197
316
  simtel_par.update(dict.fromkeys(mapping.values(), 0.0))
198
- if shape == "gauss-exponential":
199
- simtel_par["laser_pulse_sigtime"] = width
200
- elif shape in mapping:
317
+ if shape in mapping:
201
318
  simtel_par[mapping[shape]] = width
202
319
  else:
203
320
  self._logger.warning(f"Flasher pulse shape '{shape}' without width definition")
@@ -221,7 +338,7 @@ class SimtelConfigWriter:
221
338
  value = "none" if value is None else value # simtel requires 'none'
222
339
  if isinstance(value, bool):
223
340
  value = 1 if value else 0
224
- elif isinstance(value, (list, np.ndarray)):
341
+ elif isinstance(value, list | np.ndarray):
225
342
  value = gen.convert_list_to_string(value, shorten_list=True)
226
343
  return value
227
344
 
@@ -495,17 +612,24 @@ class SimtelConfigWriter:
495
612
  "simtools_model_production_version": self._model_version,
496
613
  }
497
614
  try:
498
- build_opts = ascii_handler.collect_data_from_file(
499
- Path(self._simtel_path) / "build_opts.yml"
500
- )
615
+ build_opts = dependencies.get_build_options()
501
616
  for key, value in build_opts.items():
502
617
  meta_items[f"simtools_{key}"] = value
503
618
  except (FileNotFoundError, TypeError):
504
619
  pass # don't expect build_opts.yml to be present on all systems
505
620
 
621
+ # CORSIKA executable without _flat/_curved suffix (do not know here if curved or flat)
622
+ try:
623
+ meta_items["simtools_corsika_exec"] = settings.config.corsika_exe.name.removesuffix(
624
+ "_flat"
625
+ )
626
+ except AttributeError as exc:
627
+ raise AttributeError("CORSIKA executable path is not set in settings.") from exc
628
+
506
629
  file.write(f"{self.TAB}% Simtools parameters\n")
507
630
  for key, value in meta_items.items():
508
- file.write(f"{self.TAB}metaparam global set {key} = {value}\n")
631
+ if not isinstance(value, list):
632
+ file.write(f"{self.TAB}metaparam global set {key} = {value}\n")
509
633
 
510
634
  def _write_site_parameters(
511
635
  self, file, site_parameters, model_path, telescope_model, additional_metadata=None
@@ -154,14 +154,16 @@ def _data_columns_mirror_reflectivity(n_columns, n_dim):
154
154
  {"name": "wavelength", "description": "Wavelength", "unit": "nm"},
155
155
  ]
156
156
  if n_dim:
157
- for angle in n_dim:
158
- _columns.append(
157
+ _columns.extend(
158
+ [
159
159
  {
160
160
  "name": f"reflectivity_{angle}deg",
161
161
  "description": f"Mirror reflectivity at {angle} deg",
162
162
  "unit": None,
163
- },
164
- )
163
+ }
164
+ for angle in n_dim
165
+ ]
166
+ )
165
167
  else:
166
168
  _columns.append(
167
169
  {
@@ -1,7 +1,9 @@
1
1
  """Simulation runner for array simulations."""
2
2
 
3
3
  import logging
4
+ import stat
4
5
 
6
+ from simtools import settings
5
7
  from simtools.io import io_handler
6
8
  from simtools.runners.simtel_runner import InvalidOutputFileError, SimtelRunner
7
9
  from simtools.utils.general import clear_default_sim_telarray_cfg_directories
@@ -15,8 +17,6 @@ class SimulatorArray(SimtelRunner):
15
17
  ----------
16
18
  corsika_config_data: CorsikaConfig
17
19
  CORSIKA configuration.
18
- simtel_path: str or Path
19
- Location of source of the sim_telarray/CORSIKA package.
20
20
  label: str
21
21
  Instance label.
22
22
  use_multipipe: bool
@@ -28,7 +28,6 @@ class SimulatorArray(SimtelRunner):
28
28
  def __init__(
29
29
  self,
30
30
  corsika_config,
31
- simtel_path,
32
31
  label=None,
33
32
  use_multipipe=False,
34
33
  sim_telarray_seeds=None,
@@ -39,9 +38,9 @@ class SimulatorArray(SimtelRunner):
39
38
  self._logger.debug("Init SimulatorArray")
40
39
  super().__init__(
41
40
  label=label,
42
- simtel_path=simtel_path,
43
41
  corsika_config=corsika_config,
44
42
  use_multipipe=use_multipipe,
43
+ calibration_run_mode=calibration_config.get("run_mode") if calibration_config else None,
45
44
  )
46
45
 
47
46
  self.sim_telarray_seeds = sim_telarray_seeds
@@ -50,6 +49,52 @@ class SimulatorArray(SimtelRunner):
50
49
  self.io_handler = io_handler.IOHandler()
51
50
  self._log_file = None
52
51
 
52
+ def prepare_run_script(self, test=False, input_file=None, run_number=None, extra_commands=None):
53
+ """
54
+ Build and return the full path of the bash run script containing the sim_telarray command.
55
+
56
+ Parameters
57
+ ----------
58
+ test: bool
59
+ Test flag for faster execution.
60
+ input_file: str or Path
61
+ Full path of the input CORSIKA file.
62
+ run_number: int
63
+ Run number.
64
+ extra_commands: list[str]
65
+ Additional commands for running simulations given in config.yml.
66
+
67
+ Returns
68
+ -------
69
+ Path
70
+ Full path of the run script.
71
+ """
72
+ script_file_path = self.get_file_name(file_type="sub_script", run_number=run_number)
73
+ self._logger.debug(f"Run bash script - {script_file_path}")
74
+ self._logger.debug(f"Extra commands to be added to the run script {extra_commands}")
75
+
76
+ command = self.make_run_command(run_number=run_number, input_file=input_file)
77
+ with script_file_path.open("w", encoding="utf-8") as file:
78
+ file.write("#!/usr/bin/env bash\n\n")
79
+ file.write("set -e\n")
80
+ file.write("set -o pipefail\n")
81
+ file.write("\nSECONDS=0\n")
82
+
83
+ if extra_commands:
84
+ file.write("# Writing extras\n")
85
+ for line in extra_commands:
86
+ file.write(f"{line}\n")
87
+ file.write("# End of extras\n\n")
88
+
89
+ n = 1 if test else self.runs_per_set
90
+ for _ in range(n):
91
+ file.write(f"{command}\n\n")
92
+
93
+ file.write('\necho "RUNTIME: $SECONDS"\n')
94
+
95
+ script_file_path.chmod(script_file_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP)
96
+ return script_file_path
97
+
53
98
  def make_run_command(self, run_number=None, input_file=None, weak_pointing=None):
54
99
  """
55
100
  Build and return the command to run sim_telarray.
@@ -111,12 +156,12 @@ class SimulatorArray(SimtelRunner):
111
156
  command += super().get_config_option(key, cfg[key])
112
157
 
113
158
  run_mode = cfg.get("run_mode")
114
- if run_mode in ("pedestals", "nsb_only_pedestals"):
159
+ if run_mode in ("pedestals", "pedestals_nsb_only"):
115
160
  n_events = cfg.get("number_of_pedestal_events", cfg["number_of_events"])
116
161
  command += super().get_config_option("pedestal_events", n_events)
117
- if run_mode == "nsb_only_pedestals":
118
- command += self._nsb_only_pedestals_command()
119
- if run_mode == "dark_pedestals":
162
+ if run_mode == "pedestals_nsb_only":
163
+ command += self._pedestals_nsb_only_command()
164
+ if run_mode == "pedestals_dark":
120
165
  n_events = cfg.get("number_of_dark_events", cfg["number_of_events"])
121
166
  command += super().get_config_option("dark_events", n_events)
122
167
  if run_mode == "direct_injection":
@@ -133,7 +178,7 @@ class SimulatorArray(SimtelRunner):
133
178
  output_file = self.get_file_name(file_type="simtel_output", run_number=run_number)
134
179
  self.corsika_config.array_model.export_all_simtel_config_files()
135
180
 
136
- command = str(self._simtel_path.joinpath("sim_telarray/bin/sim_telarray"))
181
+ command = str(settings.config.sim_telarray_exe)
137
182
  command += f" -c {self.corsika_config.array_model.config_file_path}"
138
183
  command += f" -I{config_dir}"
139
184
  command += super().get_config_option(
@@ -155,7 +200,7 @@ class SimulatorArray(SimtelRunner):
155
200
 
156
201
  return command
157
202
 
158
- def _nsb_only_pedestals_command(self):
203
+ def _pedestals_nsb_only_command(self):
159
204
  """
160
205
  Generate the command to run sim_telarray for nsb-only pedestal simulations.
161
206
 
@@ -174,9 +219,7 @@ class SimulatorArray(SimtelRunner):
174
219
  "fadc_sysvar_pedestal",
175
220
  "fadc_dev_pedestal",
176
221
  ]
177
- null_command_parts = []
178
- for param in null_values:
179
- null_command_parts.append(super().get_config_option(param, 0.0))
222
+ null_command_parts = [super().get_config_option(param, 0.0) for param in null_values]
180
223
  command = " ".join(null_command_parts)
181
224
 
182
225
  one_values = [
@@ -185,15 +228,13 @@ class SimulatorArray(SimtelRunner):
185
228
  "fadc_lg_dev_pedestal",
186
229
  "fadc_lg_sysvar_pedestal",
187
230
  ]
188
- one_command_parts = []
189
- for param in one_values:
190
- one_command_parts.append(super().get_config_option(param, -1.0))
231
+ one_command_parts = [super().get_config_option(param, -1.0) for param in one_values]
191
232
  command += " " + " ".join(one_command_parts)
192
233
  return command
193
234
 
194
235
  def _check_run_result(self, run_number=None):
195
236
  """
196
- Check if simtel output file exists.
237
+ Check if sim_telarray output file exists.
197
238
 
198
239
  Parameters
199
240
  ----------
@@ -203,18 +244,16 @@ class SimulatorArray(SimtelRunner):
203
244
  Returns
204
245
  -------
205
246
  bool
206
- True if simtel output file exists.
247
+ True if sim_telarray output file exists.
207
248
 
208
249
  Raises
209
250
  ------
210
251
  InvalidOutputFileError
211
- If simtel output file does not exist.
252
+ If sim_telarray output file does not exist.
212
253
  """
213
254
  output_file = self.get_file_name(file_type="simtel_output", run_number=run_number)
214
255
  if not output_file.exists():
215
- msg = f"sim_telarray output file {output_file} does not exist."
216
- self._logger.error(msg)
217
- raise InvalidOutputFileError(msg)
256
+ raise InvalidOutputFileError(f"sim_telarray output file {output_file} does not exist.")
218
257
  self._logger.debug(f"sim_telarray output file {output_file} exists.")
219
258
  return True
220
259
 
@@ -223,7 +262,7 @@ class SimulatorArray(SimtelRunner):
223
262
  """
224
263
  Get the power law index for sim_telarray.
225
264
 
226
- Events will be histogrammed in sim_telarray with a weight according to
265
+ Events will be filled in histograms in sim_telarray with a weight according to
227
266
  the difference between this exponent and the one used for the shower simulations.
228
267
 
229
268
  Parameters
@@ -3,6 +3,7 @@
3
3
  import logging
4
4
  from pathlib import Path
5
5
 
6
+ from simtools import settings
6
7
  from simtools.io import ascii_handler
7
8
  from simtools.runners.simtel_runner import SimtelRunner
8
9
  from simtools.utils import general
@@ -20,8 +21,6 @@ class SimulatorCameraEfficiency(SimtelRunner):
20
21
  Instance of SiteModel class.
21
22
  label: str
22
23
  Instance label. Important for output file naming.
23
- simtel_path: str or Path
24
- Location of sim_telarray installation.
25
24
  file_simtel: str or Path
26
25
  Location of the sim_telarray testeff tool output file.
27
26
  zenith_angle: float
@@ -37,7 +36,6 @@ class SimulatorCameraEfficiency(SimtelRunner):
37
36
  telescope_model,
38
37
  site_model,
39
38
  label=None,
40
- simtel_path=None,
41
39
  file_simtel=None,
42
40
  file_log=None,
43
41
  zenith_angle=None,
@@ -48,7 +46,7 @@ class SimulatorCameraEfficiency(SimtelRunner):
48
46
  self._logger = logging.getLogger(__name__)
49
47
  self._logger.debug("Init SimulatorCameraEfficiency")
50
48
 
51
- super().__init__(label=label, simtel_path=simtel_path)
49
+ super().__init__(label=label)
52
50
 
53
51
  self._telescope_model = telescope_model
54
52
  self._site_model = site_model
@@ -109,7 +107,7 @@ class SimulatorCameraEfficiency(SimtelRunner):
109
107
  "mirror_reflectivity", "secondary_mirror_incidence_angle"
110
108
  )
111
109
 
112
- command = str(self._simtel_path.joinpath("sim_telarray/testeff"))
110
+ command = str(settings.config.sim_telarray_path / "bin/testeff")
113
111
  if self.skip_correction_to_nsb_spectrum:
114
112
  command += " -nc" # Do not apply correction to original altitude where B&E was derived
115
113
  command += " -I" # Clear the fall-back configuration directories
@@ -150,7 +148,7 @@ class SimulatorCameraEfficiency(SimtelRunner):
150
148
  command = general.clear_default_sim_telarray_cfg_directories(command)
151
149
 
152
150
  return (
153
- f"cd {self._simtel_path.joinpath('sim_telarray')} && {command}",
151
+ f"cd {settings.config.sim_telarray_path} && {command}",
154
152
  self._file_simtel,
155
153
  self._file_log,
156
154
  )