gammasimtools 0.22.0__py3-none-any.whl → 0.23.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 (114) hide show
  1. {gammasimtools-0.22.0.dist-info → gammasimtools-0.23.0.dist-info}/METADATA +2 -1
  2. {gammasimtools-0.22.0.dist-info → gammasimtools-0.23.0.dist-info}/RECORD +114 -112
  3. simtools/_version.py +2 -2
  4. simtools/application_control.py +118 -0
  5. simtools/applications/calculate_incident_angles.py +17 -22
  6. simtools/applications/convert_all_model_parameters_from_simtel.py +28 -43
  7. simtools/applications/convert_geo_coordinates_of_array_elements.py +26 -45
  8. simtools/applications/convert_model_parameter_from_simtel.py +21 -41
  9. simtools/applications/db_add_file_to_db.py +12 -13
  10. simtools/applications/db_add_simulation_model_from_repository_to_db.py +20 -33
  11. simtools/applications/db_add_value_from_json_to_db.py +28 -23
  12. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +19 -34
  13. simtools/applications/db_generate_compound_indexes.py +11 -13
  14. simtools/applications/db_get_array_layouts_from_db.py +19 -39
  15. simtools/applications/db_get_file_from_db.py +15 -17
  16. simtools/applications/db_get_parameter_from_db.py +33 -35
  17. simtools/applications/db_inspect_databases.py +10 -11
  18. simtools/applications/db_upload_model_repository.py +13 -31
  19. simtools/applications/derive_ctao_array_layouts.py +16 -21
  20. simtools/applications/derive_mirror_rnda.py +9 -14
  21. simtools/applications/derive_photon_electron_spectrum.py +7 -10
  22. simtools/applications/derive_psf_parameters.py +13 -20
  23. simtools/applications/derive_trigger_rates.py +6 -9
  24. simtools/applications/docs_produce_array_element_report.py +22 -23
  25. simtools/applications/docs_produce_calibration_reports.py +26 -24
  26. simtools/applications/docs_produce_model_parameter_reports.py +15 -22
  27. simtools/applications/docs_produce_simulation_configuration_report.py +21 -22
  28. simtools/applications/generate_array_config.py +14 -33
  29. simtools/applications/generate_corsika_histograms.py +22 -43
  30. simtools/applications/generate_default_metadata.py +15 -36
  31. simtools/applications/generate_regular_arrays.py +11 -15
  32. simtools/applications/generate_simtel_event_data.py +23 -33
  33. simtools/applications/maintain_simulation_model_add_production.py +12 -19
  34. simtools/applications/maintain_simulation_model_compare_productions.py +10 -12
  35. simtools/applications/maintain_simulation_model_verify_production_tables.py +8 -11
  36. simtools/applications/merge_tables.py +14 -23
  37. simtools/applications/plot_array_layout.py +77 -54
  38. simtools/applications/plot_simtel_events.py +11 -13
  39. simtools/applications/plot_tabular_data.py +17 -38
  40. simtools/applications/plot_tabular_data_for_model_parameter.py +16 -23
  41. simtools/applications/print_version.py +14 -42
  42. simtools/applications/production_derive_corsika_limits.py +5 -9
  43. simtools/applications/production_derive_statistics.py +12 -25
  44. simtools/applications/production_generate_grid.py +20 -48
  45. simtools/applications/production_merge_corsika_limits.py +17 -21
  46. simtools/applications/run_application.py +12 -32
  47. simtools/applications/simulate_flasher.py +21 -25
  48. simtools/applications/simulate_illuminator.py +7 -14
  49. simtools/applications/simulate_pedestals.py +13 -13
  50. simtools/applications/simulate_prod.py +21 -33
  51. simtools/applications/simulate_prod_htcondor_generator.py +11 -25
  52. simtools/applications/submit_array_layouts.py +15 -18
  53. simtools/applications/submit_data_from_external.py +18 -34
  54. simtools/applications/submit_model_parameter_from_external.py +27 -40
  55. simtools/applications/validate_camera_efficiency.py +23 -21
  56. simtools/applications/validate_camera_fov.py +21 -26
  57. simtools/applications/validate_cumulative_psf.py +27 -35
  58. simtools/applications/validate_file_using_schema.py +15 -33
  59. simtools/applications/validate_optics.py +26 -32
  60. simtools/camera/camera_efficiency.py +0 -2
  61. simtools/configuration/commandline_parser.py +32 -4
  62. simtools/configuration/configurator.py +0 -5
  63. simtools/corsika/corsika_config.py +0 -5
  64. simtools/data_model/data_reader.py +0 -2
  65. simtools/data_model/metadata_collector.py +0 -2
  66. simtools/data_model/model_data_writer.py +0 -2
  67. simtools/data_model/validate_data.py +0 -2
  68. simtools/db/db_handler.py +0 -2
  69. simtools/io/hdf5_handler.py +0 -5
  70. simtools/io/legacy_data_handler.py +0 -5
  71. simtools/job_execution/job_manager.py +0 -3
  72. simtools/layout/array_layout.py +0 -2
  73. simtools/layout/telescope_position.py +0 -2
  74. simtools/model/array_model.py +2 -4
  75. simtools/model/calibration_model.py +0 -2
  76. simtools/model/camera.py +0 -2
  77. simtools/model/mirrors.py +0 -2
  78. simtools/model/model_parameter.py +30 -7
  79. simtools/model/model_utils.py +0 -5
  80. simtools/model/site_model.py +0 -2
  81. simtools/model/telescope_model.py +0 -2
  82. simtools/production_configuration/calculate_statistical_uncertainties_grid_point.py +0 -2
  83. simtools/production_configuration/derive_production_statistics.py +0 -2
  84. simtools/production_configuration/interpolation_handler.py +0 -2
  85. simtools/ray_tracing/psf_analysis.py +0 -2
  86. simtools/ray_tracing/ray_tracing.py +0 -2
  87. simtools/reporting/docs_auto_report_generator.py +108 -0
  88. simtools/reporting/docs_read_parameters.py +1 -7
  89. simtools/runners/corsika_runner.py +0 -2
  90. simtools/runners/corsika_simtel_runner.py +0 -2
  91. simtools/runners/simtel_runner.py +0 -2
  92. simtools/schemas/model_parameters/transit_time_random.schema.yml +29 -0
  93. simtools/simtel/simtel_config_reader.py +0 -2
  94. simtools/simtel/simtel_config_writer.py +31 -13
  95. simtools/simtel/simtel_io_metadata.py +3 -3
  96. simtools/simtel/simulator_array.py +9 -21
  97. simtools/simtel/simulator_camera_efficiency.py +0 -2
  98. simtools/simtel/simulator_light_emission.py +1 -3
  99. simtools/simtel/simulator_ray_tracing.py +0 -2
  100. simtools/simulator.py +0 -5
  101. simtools/testing/assertions.py +2 -2
  102. simtools/testing/configuration.py +17 -4
  103. simtools/utils/general.py +5 -13
  104. simtools/utils/geometry.py +0 -5
  105. simtools/utils/names.py +1 -13
  106. simtools/version.py +61 -0
  107. simtools/visualization/plot_array_layout.py +129 -23
  108. simtools/visualization/plot_incident_angles.py +0 -2
  109. simtools/visualization/plot_simtel_events.py +0 -11
  110. simtools/visualization/visualize.py +0 -12
  111. {gammasimtools-0.22.0.dist-info → gammasimtools-0.23.0.dist-info}/WHEEL +0 -0
  112. {gammasimtools-0.22.0.dist-info → gammasimtools-0.23.0.dist-info}/entry_points.txt +0 -0
  113. {gammasimtools-0.22.0.dist-info → gammasimtools-0.23.0.dist-info}/licenses/LICENSE +0 -0
  114. {gammasimtools-0.22.0.dist-info → gammasimtools-0.23.0.dist-info}/top_level.txt +0 -0
@@ -13,8 +13,6 @@ from simtools.io import ascii_handler, io_handler
13
13
  from simtools.simtel.simtel_config_writer import SimtelConfigWriter
14
14
  from simtools.utils import names
15
15
 
16
- __all__ = ["InvalidModelParameterError", "ModelParameter"]
17
-
18
16
 
19
17
  class InvalidModelParameterError(Exception):
20
18
  """Exception for invalid model parameter."""
@@ -198,6 +196,31 @@ class ModelParameter:
198
196
 
199
197
  return _parameter
200
198
 
199
+ def _create_quantity_for_value(self, value, unit):
200
+ """
201
+ Create an astropy quantity for a single value and unit.
202
+
203
+ Parameters
204
+ ----------
205
+ value: numeric or str
206
+ The value to create a quantity for.
207
+ unit: str or None
208
+ The unit string or None.
209
+
210
+ Returns
211
+ -------
212
+ astropy.Quantity or original value
213
+ Astropy quantity for numeric values with units,
214
+ original value for non-numeric values.
215
+ """
216
+ if not isinstance(value, int | float):
217
+ return value
218
+
219
+ if unit is None or unit == "null":
220
+ return value * u.dimensionless_unscaled
221
+
222
+ return value * u.Unit(unit)
223
+
201
224
  def get_parameter_value_with_unit(self, par_name):
202
225
  """
203
226
  Get the value of an existing parameter of the model as an Astropy Quantity with its unit.
@@ -226,13 +249,12 @@ class ModelParameter:
226
249
  if (isinstance(_value, (int | float))) or (len(_value) > len(_unit)):
227
250
  return _value * u.Unit(_unit[0])
228
251
 
229
- # entries with 'null' units should be returned as dimensionless
230
- _astropy_units = [
231
- u.Unit(item) if item != "null" else u.dimensionless_unscaled for item in _unit
252
+ # Create list of quantities for multiple values with different units
253
+ return [
254
+ self._create_quantity_for_value(_value[i], _unit[i] if i < len(_unit) else None)
255
+ for i in range(len(_value))
232
256
  ]
233
257
 
234
- return [_value[i] * _astropy_units[i] for i in range(len(_value))]
235
-
236
258
  except (KeyError, TypeError, AttributeError) as exc:
237
259
  self._logger.debug(
238
260
  f"{exc} encountered for parameter {par_name}, returning only value without units."
@@ -550,6 +572,7 @@ class ModelParameter:
550
572
  self.simtel_config_writer = SimtelConfigWriter(
551
573
  site=self.site,
552
574
  telescope_model_name=self.name,
575
+ telescope_design_model=self.design_model,
553
576
  model_version=self.model_version,
554
577
  label=self.label,
555
578
  )
@@ -8,11 +8,6 @@ from simtools.model.site_model import SiteModel
8
8
  from simtools.model.telescope_model import TelescopeModel
9
9
  from simtools.utils import names
10
10
 
11
- __all__ = [
12
- "compute_telescope_transmission",
13
- "is_two_mirror_telescope",
14
- ]
15
-
16
11
 
17
12
  def initialize_simulation_models(
18
13
  label, db_config, model_version, site, telescope_name, calibration_device_name=None
@@ -9,8 +9,6 @@ from astropy import units as u
9
9
 
10
10
  from simtools.model.model_parameter import ModelParameter
11
11
 
12
- __all__ = ["SiteModel"]
13
-
14
12
 
15
13
  class SiteModel(ModelParameter):
16
14
  """
@@ -13,8 +13,6 @@ from simtools.model.mirrors import Mirrors
13
13
  from simtools.model.model_parameter import InvalidModelParameterError, ModelParameter
14
14
  from simtools.utils import names
15
15
 
16
- __all__ = ["TelescopeModel"]
17
-
18
16
 
19
17
  class TelescopeModel(ModelParameter):
20
18
  """
@@ -6,8 +6,6 @@ import numpy as np
6
6
  from astropy import units as u
7
7
  from astropy.io import fits
8
8
 
9
- __all__ = ["StatisticalUncertaintyEvaluator"]
10
-
11
9
 
12
10
  class StatisticalUncertaintyEvaluator:
13
11
  """
@@ -10,8 +10,6 @@ metrics and the evaluator's results.
10
10
  import astropy.units as u
11
11
  import numpy as np
12
12
 
13
- __all__ = ["ProductionStatisticsDerivator"]
14
-
15
13
 
16
14
  class ProductionStatisticsDerivator:
17
15
  """
@@ -10,8 +10,6 @@ from simtools.production_configuration.derive_production_statistics import (
10
10
  ProductionStatisticsDerivator,
11
11
  )
12
12
 
13
- __all__ = ["InterpolationHandler"]
14
-
15
13
 
16
14
  class InterpolationHandler:
17
15
  """
@@ -19,8 +19,6 @@ import numpy as np
19
19
 
20
20
  from simtools.utils.general import collect_kwargs, set_default_kwargs
21
21
 
22
- __all__ = ["PSFImage"]
23
-
24
22
 
25
23
  class PSFImage:
26
24
  """
@@ -20,8 +20,6 @@ from simtools.simtel.simulator_ray_tracing import SimulatorRayTracing
20
20
  from simtools.utils import names
21
21
  from simtools.visualization import visualize
22
22
 
23
- __all__ = ["RayTracing"]
24
-
25
23
  INVALID_KEY_TO_PLOT = "Invalid key to plot"
26
24
 
27
25
 
@@ -175,6 +175,10 @@ class ReportGenerator:
175
175
  f"Markdown report generated for {site} Telescope {telescope}: {self.output_path}"
176
176
  )
177
177
 
178
+ # Also generate calibration device parameter comparison reports when using --all_telescopes
179
+ if self.args.get("all_telescopes"):
180
+ self._generate_calibration_device_parameter_reports()
181
+
178
182
  def _generate_observatory_report_combinations(self) -> Generator[tuple[str, str], None, None]:
179
183
  """Generate combinations of sites and model versions for observatory reports.
180
184
 
@@ -215,3 +219,107 @@ class ReportGenerator:
215
219
  """Generate all observatory reports based on which --all_* flags are passed."""
216
220
  for params in self._generate_observatory_report_combinations():
217
221
  self._generate_single_observatory_report(*params)
222
+
223
+ def auto_generate_simulation_configuration_reports(self):
224
+ """Generate simulation configuration reports for one or all model versions.
225
+
226
+ If --all_model_versions is set, produce reports for every model version in
227
+ the DB; otherwise produce reports only for the configured model_version.
228
+ """
229
+ model_versions = (
230
+ self.db.get_model_versions()
231
+ if self.args.get("all_model_versions")
232
+ else [self.args["model_version"]]
233
+ )
234
+
235
+ for version in model_versions:
236
+ # update args and create a per-version output directory
237
+ self.args.update({"model_version": version})
238
+ output_path = Path(self.output_path) / str(version)
239
+
240
+ ReadParameters(
241
+ self.db_config, self.args, output_path
242
+ ).produce_simulation_configuration_report()
243
+
244
+ logger.info(f"Configuration reports for (v{version}) produced: {output_path}")
245
+
246
+ def auto_generate_calibration_reports(self):
247
+ """Generate calibration reports for one or all model versions.
248
+
249
+ Mirrors the pattern used by other auto_generate_* methods: if
250
+ --all_model_versions is set, produce reports for every model version in
251
+ the DB; otherwise produce reports only for the configured model_version.
252
+ """
253
+ model_versions = (
254
+ self.db.get_model_versions()
255
+ if self.args.get("all_model_versions")
256
+ else [self.args["model_version"]]
257
+ )
258
+
259
+ for version in model_versions:
260
+ # update args and create a per-version output directory
261
+ self.args.update({"model_version": version})
262
+ output_path = Path(self.output_path) / str(version)
263
+
264
+ try:
265
+ ReadParameters(self.db_config, self.args, output_path).produce_calibration_reports()
266
+ logger.info(f"Calibration reports for (v{version}) produced: {output_path}")
267
+ except ValueError as err:
268
+ # Some model versions do not have calibration_devices in the DB;
269
+ msg = str(err)
270
+ if "calibration_devices" in msg and "zero results" in msg:
271
+ logger.info(
272
+ f"Skipping model version {version}: no calibration devices defined ({msg})"
273
+ )
274
+ continue
275
+ # re-raise unexpected ValueErrors
276
+ raise
277
+
278
+ def _generate_calibration_device_parameter_reports(self):
279
+ """Generate parameter comparison reports for calibration devices for all model versions."""
280
+ # Get all model versions since no specific version is provided when using --all_telescopes
281
+ model_versions = self.db.get_model_versions()
282
+
283
+ for version in model_versions:
284
+ self._process_calibration_devices_for_version(version)
285
+
286
+ def _process_calibration_devices_for_version(self, version):
287
+ """Process calibration devices for a specific model version."""
288
+ try:
289
+ # Get all calibration devices for this version
290
+ calibration_array_elements = self.db.get_array_elements(
291
+ version, collection="calibration_devices"
292
+ )
293
+ array_elements = calibration_array_elements.copy()
294
+
295
+ # Add design models
296
+ for element in calibration_array_elements:
297
+ design_model = self.db.get_design_model(version, element, "calibration_devices")
298
+ if design_model and design_model not in array_elements:
299
+ array_elements.append(design_model)
300
+
301
+ if array_elements:
302
+ # Create a copy of args with the current version for this iteration
303
+ version_args = self.args.copy()
304
+ version_args["model_version"] = version
305
+
306
+ # Generate parameter comparison reports for calibration devices
307
+ ReadParameters(
308
+ self.db_config, version_args, self.output_path
309
+ ).generate_model_parameter_reports_for_devices(array_elements)
310
+
311
+ logger.info(
312
+ "Calibration device parameter reports generated for"
313
+ f" v{version}: {self.output_path}"
314
+ )
315
+
316
+ except ValueError as err:
317
+ # Some model versions may not have calibration_devices
318
+ msg = str(err)
319
+ if "calibration_devices" in msg and "zero results" in msg:
320
+ logger.info(
321
+ f"Skipping model version {version}: no calibration devices defined ({msg})"
322
+ )
323
+ return
324
+ # re-raise unexpected ValueErrors
325
+ raise
@@ -896,9 +896,6 @@ class ReadParameters:
896
896
  output_filename, calibration_device, data, design_model
897
897
  )
898
898
 
899
- # produce parameter comparison reports (site-independent)
900
- self._generate_model_parameter_reports_for_devices(array_elements)
901
-
902
899
  def _collect_calibration_array_elements(self):
903
900
  """Return a list of calibration devices including their design models."""
904
901
  calibration_array_elements = self.db.get_array_elements(
@@ -954,11 +951,8 @@ class ReadParameters:
954
951
 
955
952
  self._write_to_file(display_group, file)
956
953
 
957
- def _generate_model_parameter_reports_for_devices(self, array_elements):
954
+ def generate_model_parameter_reports_for_devices(self, array_elements):
958
955
  """Create model-parameter comparison reports for calibration devices."""
959
- new_output_path = Path(self.output_path).parent.parent / "parameters"
960
- new_output_path.mkdir(parents=True, exist_ok=True)
961
- self.output_path = new_output_path
962
956
  for calibration_device in array_elements:
963
957
  device_sites = names.get_site_from_array_element_name(calibration_device)
964
958
  # parameters are site independent so just take the first site to read from db
@@ -7,8 +7,6 @@ from pathlib import Path
7
7
  from simtools.io import io_handler
8
8
  from simtools.runners.runner_services import RunnerServices
9
9
 
10
- __all__ = ["CorsikaRunner", "MissingRequiredEntryInCorsikaConfigError"]
11
-
12
10
 
13
11
  class MissingRequiredEntryInCorsikaConfigError(Exception):
14
12
  """Exception for missing required entry in corsika config."""
@@ -8,8 +8,6 @@ import simtools.utils.general as gen
8
8
  from simtools.runners.corsika_runner import CorsikaRunner
9
9
  from simtools.simtel.simulator_array import SimulatorArray
10
10
 
11
- __all__ = ["CorsikaSimtelRunner"]
12
-
13
11
 
14
12
  class CorsikaSimtelRunner:
15
13
  """
@@ -8,8 +8,6 @@ from pathlib import Path
8
8
  import simtools.utils.general as gen
9
9
  from simtools.runners.runner_services import RunnerServices
10
10
 
11
- __all__ = ["InvalidOutputFileError", "SimtelExecutionError", "SimtelRunner"]
12
-
13
11
 
14
12
  class SimtelExecutionError(Exception):
15
13
  """Exception for sim_telarray execution error."""
@@ -0,0 +1,29 @@
1
+ %YAML 1.2
2
+ ---
3
+ title: Schema for transit_time_random model parameter
4
+ schema_version: 0.1.0
5
+ meta_schema: simpipe-schema
6
+ meta_schema_url: https://raw.githubusercontent.com/gammasim/simtools/main/src/simtools/schemas/model_parameter_and_data_schema.metaschema.yml
7
+ meta_schema_version: 0.1.0
8
+ name: transit_time_random
9
+ description: Event-wise and pixel-wise random fluctuations in the signal transit time.
10
+ data:
11
+ - type: float64
12
+ unit: ns
13
+ default: 0.
14
+ allowed_range:
15
+ min: 0.0
16
+ instrument:
17
+ class: Camera
18
+ activity:
19
+ setting:
20
+ - SetParameterFromExternal
21
+ validation:
22
+ - ValidateParameterByExpert
23
+ - ValidateCameraTimeResponse
24
+ source:
25
+ - Initial instrument setup
26
+ simulation_software:
27
+ - name: sim_telarray
28
+ - name: simtools
29
+ version: ">=0.22.0"
@@ -10,8 +10,6 @@ import numpy as np
10
10
  from simtools.io import ascii_handler
11
11
  from simtools.utils import names
12
12
 
13
- __all__ = ["SimtelConfigReader"]
14
-
15
13
 
16
14
  def get_list_of_simtel_parameters(simtel_config_file):
17
15
  """
@@ -13,8 +13,6 @@ import simtools.version
13
13
  from simtools.io import ascii_handler
14
14
  from simtools.utils import names
15
15
 
16
- __all__ = ["SimtelConfigWriter"]
17
-
18
16
 
19
17
  def sim_telarray_random_seeds(seed, number):
20
18
  """
@@ -67,6 +65,7 @@ class SimtelConfigWriter:
67
65
  model_version,
68
66
  layout_name=None,
69
67
  telescope_model_name=None,
68
+ telescope_design_model=None,
70
69
  label=None,
71
70
  simtel_path=None,
72
71
  ):
@@ -79,9 +78,12 @@ class SimtelConfigWriter:
79
78
  self._label = label
80
79
  self._layout_name = layout_name
81
80
  self._telescope_model_name = telescope_model_name
81
+ self._telescope_design_model = telescope_design_model
82
82
  self._simtel_path = simtel_path
83
83
 
84
- def write_telescope_config_file(self, config_file_path, parameters, telescope_name=None):
84
+ def write_telescope_config_file(
85
+ self, config_file_path, parameters, telescope_name=None, telescope_design_model=None
86
+ ):
85
87
  """
86
88
  Write the sim_telarray config file for a single telescope.
87
89
 
@@ -93,22 +95,30 @@ class SimtelConfigWriter:
93
95
  Model parameters
94
96
  telescope_name: str
95
97
  Name of the telescope (use self._telescope_model_name if None)
98
+ telescope_design_model: str
99
+ Telescope design model.
96
100
  """
97
101
  self._logger.debug(f"Writing telescope config file {config_file_path}")
98
102
 
99
103
  simtel_par = self._get_parameters_for_sim_telarray(parameters, config_file_path)
104
+ telescope_name = telescope_name or self._telescope_model_name
105
+ _telescope_design_model = telescope_design_model or self._telescope_design_model
100
106
 
101
107
  with open(config_file_path, "w", encoding="utf-8") as file:
102
108
  self._write_header(file, "TELESCOPE CONFIGURATION FILE")
103
109
 
104
- telescope_name = telescope_name or self._telescope_model_name
105
110
  file.write("#ifdef TELESCOPE\n")
106
111
  file.write(f" echo Configuration for {telescope_name} - TELESCOPE $(TELESCOPE)\n")
107
112
  file.write("#endif\n\n")
108
113
 
109
114
  for simtel_name, simtel_value in simtel_par.items():
110
115
  file.write(f"{simtel_name} = {self._get_value_string_for_simtel(simtel_value)}\n")
111
- for meta in self._get_sim_telarray_metadata("telescope", parameters, telescope_name):
116
+ for meta in self._get_sim_telarray_metadata(
117
+ "telescope",
118
+ parameters,
119
+ telescope_name,
120
+ telescope_design_model=_telescope_design_model,
121
+ ):
112
122
  file.write(f"{meta}\n")
113
123
 
114
124
  def _get_parameters_for_sim_telarray(self, parameters, config_file_path):
@@ -211,12 +221,17 @@ class SimtelConfigWriter:
211
221
  value = "none" if value is None else value # simtel requires 'none'
212
222
  if isinstance(value, bool):
213
223
  value = 1 if value else 0
214
- elif isinstance(value, (list, np.ndarray)): # noqa: UP038
224
+ elif isinstance(value, (list, np.ndarray)):
215
225
  value = gen.convert_list_to_string(value, shorten_list=True)
216
226
  return value
217
227
 
218
228
  def _get_sim_telarray_metadata(
219
- self, config_type, model_parameters, telescope_model_name, additional_metadata=None
229
+ self,
230
+ config_type,
231
+ model_parameters,
232
+ telescope_model_name,
233
+ additional_metadata=None,
234
+ telescope_design_model=None,
220
235
  ):
221
236
  """
222
237
  Return sim_telarray metadata.
@@ -231,6 +246,8 @@ class SimtelConfigWriter:
231
246
  Name of the telescope model
232
247
  additional_metadata: dict
233
248
  Dictionary with additional metadata to include using 'set'.
249
+ telescope_design_model: str
250
+ Name of the telescope design model.
234
251
 
235
252
  Returns
236
253
  -------
@@ -241,14 +258,15 @@ class SimtelConfigWriter:
241
258
  f"config_release = {self._model_version} with simtools v{simtools.version.__version__}",
242
259
  f"config_version = {self._model_version}",
243
260
  ]
261
+ telescope_design_model = telescope_design_model or "design_model_not_set"
244
262
  if config_type == "telescope":
245
263
  meta_parameters.extend(
246
264
  [
247
- f"camera_config_name = {telescope_model_name}",
248
- "camera_config_variant = ",
265
+ f"camera_config_name = {telescope_design_model}",
266
+ f"camera_config_variant = {telescope_model_name}",
249
267
  f"camera_config_version = {self._model_version}",
250
- f"optics_config_name = {telescope_model_name}",
251
- "optics_config_variant = ",
268
+ f"optics_config_name = {telescope_design_model}",
269
+ f"optics_config_variant = {telescope_model_name}",
252
270
  f"optics_config_version = {self._model_version}",
253
271
  ]
254
272
  )
@@ -521,7 +539,7 @@ class SimtelConfigWriter:
521
539
  if simtel_name is not None:
522
540
  file.write(f"{self.TAB}{simtel_name} = {value}\n")
523
541
  for meta in self._get_sim_telarray_metadata(
524
- "site", site_parameters, self._telescope_model_name, additional_metadata
542
+ "site", site_parameters, None, additional_metadata
525
543
  ):
526
544
  file.write(f"{self.TAB}{meta}\n")
527
545
  file.write("\n")
@@ -588,7 +606,7 @@ class SimtelConfigWriter:
588
606
  trigger_lines[tel_type] += ", ".join(map(str, tel_list))
589
607
  width = trigger_dict["width"]["value"] * u.Unit(trigger_dict["width"]["unit"]).to("ns")
590
608
  trigger_lines[tel_type] += f" width {width}"
591
- if trigger_dict.get("hard_stereo"):
609
+ if trigger_dict.get("hard_stereo", {}).get("value"):
592
610
  trigger_lines[tel_type] += " hardstereo"
593
611
  if all(trigger_dict["min_separation"][key] is not None for key in ["value", "unit"]):
594
612
  min_sep = trigger_dict["min_separation"]["value"] * u.Unit(
@@ -105,8 +105,8 @@ def get_sim_telarray_telescope_id(telescope_name, file):
105
105
  _, telescope_meta = read_sim_telarray_metadata(file)
106
106
  telescope_name_to_sim_telarray_id = {}
107
107
  for tel_id in telescope_meta.keys():
108
- _optics_name = telescope_meta[tel_id].get("optics_config_name", None)
109
- _camera_name = telescope_meta[tel_id].get("camera_config_name", None)
108
+ _optics_name = telescope_meta[tel_id].get("optics_config_variant", None)
109
+ _camera_name = telescope_meta[tel_id].get("camera_config_variant", None)
110
110
  if _optics_name == _camera_name and _optics_name == telescope_name:
111
111
  telescope_name_to_sim_telarray_id[telescope_name] = tel_id
112
112
 
@@ -132,7 +132,7 @@ def get_sim_telarray_telescope_id_to_telescope_name_mapping(file):
132
132
  for i, (tel_id, meta) in enumerate(telescope_meta.items()):
133
133
  try:
134
134
  telescope_name = names.validate_array_element_name(
135
- meta.get("optics_config_name", f"Unknown-{tel_id}")
135
+ meta.get("optics_config_variant", f"Unknown-{tel_id}")
136
136
  )
137
137
  except ValueError:
138
138
  telescope_name = _guess_telescope_name_for_legacy_files(i, file)
@@ -6,8 +6,6 @@ from simtools.io import io_handler
6
6
  from simtools.runners.simtel_runner import InvalidOutputFileError, SimtelRunner
7
7
  from simtools.utils.general import clear_default_sim_telarray_cfg_directories
8
8
 
9
- __all__ = ["SimulatorArray"]
10
-
11
9
 
12
10
  class SimulatorArray(SimtelRunner):
13
11
  """
@@ -73,41 +71,33 @@ class SimulatorArray(SimtelRunner):
73
71
  command = self._common_run_command(run_number, weak_pointing)
74
72
 
75
73
  if self.calibration_config:
76
- command += self._make_run_command_for_calibration_simulations(input_file)
74
+ command += self._make_run_command_for_calibration_simulations()
77
75
  else:
78
- command += self._make_run_command_for_shower_simulations(input_file)
76
+ command += self._make_run_command_for_shower_simulations()
77
+
78
+ # "-C show=all" should be the last option
79
+ command += super().get_config_option("show", "all")
80
+ command += f" {input_file} | gzip > {self._log_file} 2>&1 || exit"
79
81
 
80
82
  return clear_default_sim_telarray_cfg_directories(command)
81
83
 
82
- def _make_run_command_for_shower_simulations(self, input_file=None):
84
+ def _make_run_command_for_shower_simulations(self):
83
85
  """
84
86
  Build and return the command to run sim_telarray shower simulations.
85
87
 
86
- Parameters
87
- ----------
88
- input_file: str
89
- Full path of the input CORSIKA file
90
- run_number: int (optional)
91
- run number
92
- weak_pointing: bool (optional)
93
- Specify weak pointing option for sim_telarray.
94
-
95
88
  Returns
96
89
  -------
97
90
  str
98
91
  Command to run sim_telarray.
99
92
  """
100
- command = f" {input_file}"
101
- command += f" | gzip > {self._log_file} 2>&1 || exit"
102
- command += super().get_config_option(
93
+ return super().get_config_option(
103
94
  "power_law",
104
95
  SimulatorArray.get_power_law_for_sim_telarray_histograms(
105
96
  self.corsika_config.primary_particle
106
97
  ),
107
98
  )
108
- return command
109
99
 
110
- def _make_run_command_for_calibration_simulations(self, input_file=None):
100
+ def _make_run_command_for_calibration_simulations(self):
111
101
  """Build sim_telarray command for calibration simulations."""
112
102
  cfg = self.calibration_config
113
103
  altitude = self.corsika_config.array_model.site_model.get_parameter_value_with_unit(
@@ -133,7 +123,6 @@ class SimulatorArray(SimtelRunner):
133
123
  n_events = cfg.get("number_of_flasher_events", cfg["number_of_events"])
134
124
  command += super().get_config_option("laser_events", n_events)
135
125
 
136
- command += f" {input_file} | gzip > {self._log_file} 2>&1 || exit"
137
126
  return command
138
127
 
139
128
  def _common_run_command(self, run_number, weak_pointing=None):
@@ -162,7 +151,6 @@ class SimulatorArray(SimtelRunner):
162
151
  )
163
152
  elif self.sim_telarray_seeds and self.sim_telarray_seeds.get("seed"):
164
153
  command += super().get_config_option("random_seed", self.sim_telarray_seeds["seed"])
165
- command += super().get_config_option("show", "all")
166
154
  command += super().get_config_option("output_file", output_file)
167
155
 
168
156
  return command
@@ -7,8 +7,6 @@ from simtools.io import ascii_handler
7
7
  from simtools.runners.simtel_runner import SimtelRunner
8
8
  from simtools.utils import general
9
9
 
10
- __all__ = ["SimulatorCameraEfficiency"]
11
-
12
10
 
13
11
  class SimulatorCameraEfficiency(SimtelRunner):
14
12
  """
@@ -15,8 +15,6 @@ from simtools.runners.simtel_runner import SimtelRunner
15
15
  from simtools.utils.general import clear_default_sim_telarray_cfg_directories
16
16
  from simtools.utils.geometry import fiducial_radius_from_shape
17
17
 
18
- __all__ = ["SimulatorLightEmission"]
19
-
20
18
 
21
19
  class SimulatorLightEmission(SimtelRunner):
22
20
  """
@@ -41,7 +39,7 @@ class SimulatorLightEmission(SimtelRunner):
41
39
  simtel_path=light_emission_config.get("simtel_path"), label=label, corsika_config=None
42
40
  )
43
41
 
44
- self.output_directory = self.io_handler.get_output_directory(label)
42
+ self.output_directory = self.io_handler.get_output_directory()
45
43
 
46
44
  self.telescope_model, self.site_model, self.calibration_model = (
47
45
  initialize_simulation_models(
@@ -10,8 +10,6 @@ from simtools.runners.simtel_runner import SimtelRunner
10
10
  from simtools.utils import names
11
11
  from simtools.utils.general import clear_default_sim_telarray_cfg_directories
12
12
 
13
- __all__ = ["SimulatorRayTracing"]
14
-
15
13
  # pylint: disable=no-member
16
14
  # The line above is needed because there are members which are created
17
15
  # by adding them to the __dict__ of the class rather than directly.
simtools/simulator.py CHANGED
@@ -22,11 +22,6 @@ from simtools.simtel.simulator_array import SimulatorArray
22
22
  from simtools.testing.sim_telarray_metadata import assert_sim_telarray_metadata
23
23
  from simtools.version import semver_to_int
24
24
 
25
- __all__ = [
26
- "InvalidRunsToSimulateError",
27
- "Simulator",
28
- ]
29
-
30
25
 
31
26
  class InvalidRunsToSimulateError(Exception):
32
27
  """Exception for invalid runs to simulate."""
@@ -62,9 +62,9 @@ def assert_n_showers_and_energy_range(file):
62
62
 
63
63
  simulated_energies = []
64
64
  simulation_config = {}
65
- with SimTelFile(file) as f:
65
+ with SimTelFile(file, skip_non_triggered=False) as f:
66
66
  simulation_config = f.mc_run_headers[0]
67
- for event in f.iter_mc_events():
67
+ for event in f:
68
68
  simulated_energies.append(event["mc_shower"]["energy"])
69
69
 
70
70
  # The relative tolerance is set to 1% because ~0.5% shower simulations do not