gammasimtools 0.15.0__py3-none-any.whl → 0.17.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 (248) hide show
  1. {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/METADATA +5 -33
  2. {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/RECORD +243 -229
  3. {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/WHEEL +1 -1
  4. {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/entry_points.txt +8 -3
  5. simtools/_version.py +2 -2
  6. simtools/applications/calculate_trigger_rate.py +10 -10
  7. simtools/applications/convert_all_model_parameters_from_simtel.py +16 -16
  8. simtools/applications/convert_model_parameter_from_simtel.py +1 -1
  9. simtools/applications/derive_ctao_array_layouts.py +5 -5
  10. simtools/applications/derive_psf_parameters.py +12 -9
  11. simtools/applications/docs_produce_array_element_report.py +3 -3
  12. simtools/applications/docs_produce_calibration_reports.py +49 -0
  13. simtools/applications/docs_produce_simulation_configuration_report.py +50 -0
  14. simtools/applications/{generate_simtel_array_histograms.py → generate_sim_telarray_histograms.py} +2 -2
  15. simtools/applications/generate_simtel_event_data.py +36 -46
  16. simtools/applications/merge_tables.py +104 -0
  17. simtools/applications/plot_array_layout.py +145 -258
  18. simtools/applications/production_derive_corsika_limits.py +35 -167
  19. simtools/applications/production_derive_statistics.py +159 -0
  20. simtools/applications/production_generate_grid.py +197 -0
  21. simtools/applications/simulate_light_emission.py +6 -13
  22. simtools/applications/simulate_prod.py +45 -21
  23. simtools/applications/simulate_prod_htcondor_generator.py +0 -1
  24. simtools/applications/submit_array_layouts.py +93 -0
  25. simtools/applications/validate_cumulative_psf.py +6 -4
  26. simtools/applications/validate_file_using_schema.py +7 -3
  27. simtools/applications/validate_optics.py +5 -4
  28. simtools/applications/verify_simulation_model_production_tables.py +52 -0
  29. simtools/camera/camera_efficiency.py +17 -42
  30. simtools/configuration/commandline_parser.py +32 -37
  31. simtools/configuration/configurator.py +10 -4
  32. simtools/corsika/corsika_config.py +120 -17
  33. simtools/corsika/primary_particle.py +46 -13
  34. simtools/data_model/format_checkers.py +9 -0
  35. simtools/data_model/metadata_collector.py +7 -3
  36. simtools/data_model/model_data_writer.py +3 -0
  37. simtools/data_model/schema.py +27 -16
  38. simtools/data_model/validate_data.py +27 -7
  39. simtools/db/db_handler.py +21 -15
  40. simtools/db/db_model_upload.py +2 -2
  41. simtools/io_operations/io_handler.py +2 -2
  42. simtools/io_operations/io_table_handler.py +345 -0
  43. simtools/job_execution/htcondor_script_generator.py +2 -2
  44. simtools/job_execution/job_manager.py +7 -121
  45. simtools/layout/array_layout.py +1 -0
  46. simtools/layout/array_layout_utils.py +385 -0
  47. simtools/model/array_model.py +68 -29
  48. simtools/model/model_parameter.py +76 -51
  49. simtools/model/model_repository.py +134 -0
  50. simtools/model/model_utils.py +43 -1
  51. simtools/model/site_model.py +3 -2
  52. simtools/model/telescope_model.py +4 -4
  53. simtools/production_configuration/{calculate_statistical_errors_grid_point.py → calculate_statistical_uncertainties_grid_point.py} +101 -116
  54. simtools/production_configuration/derive_corsika_limits.py +239 -111
  55. simtools/production_configuration/derive_corsika_limits_grid.py +189 -0
  56. simtools/production_configuration/derive_production_statistics.py +155 -0
  57. simtools/production_configuration/derive_production_statistics_handler.py +152 -0
  58. simtools/production_configuration/generate_production_grid.py +364 -0
  59. simtools/production_configuration/interpolation_handler.py +303 -96
  60. simtools/ray_tracing/mirror_panel_psf.py +16 -20
  61. simtools/ray_tracing/psf_analysis.py +2 -2
  62. simtools/ray_tracing/ray_tracing.py +12 -7
  63. simtools/reporting/docs_read_parameters.py +426 -81
  64. simtools/runners/corsika_runner.py +11 -1
  65. simtools/runners/corsika_simtel_runner.py +84 -90
  66. simtools/runners/runner_services.py +22 -8
  67. simtools/runners/simtel_runner.py +27 -10
  68. simtools/schemas/model_parameter.metaschema.yml +4 -0
  69. simtools/schemas/model_parameter_and_data_schema.metaschema.yml +1 -0
  70. simtools/schemas/model_parameters/adjust_gain.schema.yml +2 -2
  71. simtools/schemas/model_parameters/array_element_position_ground.schema.yml +2 -2
  72. simtools/schemas/model_parameters/array_element_position_utm.schema.yml +2 -2
  73. simtools/schemas/model_parameters/array_window.schema.yml +2 -2
  74. simtools/schemas/model_parameters/asum_offset.schema.yml +2 -2
  75. simtools/schemas/model_parameters/asum_shaping.schema.yml +2 -2
  76. simtools/schemas/model_parameters/asum_threshold.schema.yml +2 -2
  77. simtools/schemas/model_parameters/axes_offsets.schema.yml +2 -2
  78. simtools/schemas/model_parameters/camera_body_diameter.schema.yml +2 -2
  79. simtools/schemas/model_parameters/camera_body_shape.schema.yml +2 -2
  80. simtools/schemas/model_parameters/camera_config_file.schema.yml +2 -2
  81. simtools/schemas/model_parameters/camera_config_rotate.schema.yml +2 -2
  82. simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +2 -2
  83. simtools/schemas/model_parameters/camera_degraded_map.schema.yml +2 -2
  84. simtools/schemas/model_parameters/camera_depth.schema.yml +2 -2
  85. simtools/schemas/model_parameters/camera_filter.schema.yml +2 -2
  86. simtools/schemas/model_parameters/camera_pixels.schema.yml +2 -2
  87. simtools/schemas/model_parameters/camera_transmission.schema.yml +2 -2
  88. simtools/schemas/model_parameters/channels_per_chip.schema.yml +2 -2
  89. simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +2 -2
  90. simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +90 -1
  91. simtools/schemas/model_parameters/default_trigger.schema.yml +2 -2
  92. simtools/schemas/model_parameters/design_model.schema.yml +2 -2
  93. simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +2 -2
  94. simtools/schemas/model_parameters/disc_bins.schema.yml +2 -2
  95. simtools/schemas/model_parameters/disc_start.schema.yml +2 -2
  96. simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +2 -2
  97. simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +2 -2
  98. simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +2 -2
  99. simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +2 -2
  100. simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +2 -2
  101. simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +2 -2
  102. simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +2 -2
  103. simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +2 -2
  104. simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +2 -2
  105. simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +2 -2
  106. simtools/schemas/model_parameters/discriminator_threshold.schema.yml +2 -2
  107. simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +2 -2
  108. simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +2 -2
  109. simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +2 -2
  110. simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +2 -2
  111. simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +2 -2
  112. simtools/schemas/model_parameters/dish_shape_length.schema.yml +2 -2
  113. simtools/schemas/model_parameters/dsum_clipping.schema.yml +2 -2
  114. simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +2 -2
  115. simtools/schemas/model_parameters/dsum_offset.schema.yml +2 -2
  116. simtools/schemas/model_parameters/dsum_pedsub.schema.yml +2 -2
  117. simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +2 -2
  118. simtools/schemas/model_parameters/dsum_prescale.schema.yml +2 -2
  119. simtools/schemas/model_parameters/dsum_presum_max.schema.yml +2 -2
  120. simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +2 -2
  121. simtools/schemas/model_parameters/dsum_shaping.schema.yml +2 -2
  122. simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +2 -2
  123. simtools/schemas/model_parameters/dsum_threshold.schema.yml +44 -3
  124. simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +2 -2
  125. simtools/schemas/model_parameters/effective_focal_length.schema.yml +2 -2
  126. simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +2 -2
  127. simtools/schemas/model_parameters/fadc_amplitude.schema.yml +2 -2
  128. simtools/schemas/model_parameters/fadc_bins.schema.yml +2 -2
  129. simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +2 -2
  130. simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +2 -2
  131. simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +2 -2
  132. simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +2 -2
  133. simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +2 -2
  134. simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +2 -2
  135. simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +2 -2
  136. simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +2 -2
  137. simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +2 -2
  138. simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +2 -2
  139. simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +2 -2
  140. simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +2 -2
  141. simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +2 -2
  142. simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +2 -2
  143. simtools/schemas/model_parameters/fadc_max_signal.schema.yml +2 -2
  144. simtools/schemas/model_parameters/fadc_mhz.schema.yml +2 -2
  145. simtools/schemas/model_parameters/fadc_noise.schema.yml +2 -2
  146. simtools/schemas/model_parameters/fadc_pedestal.schema.yml +2 -2
  147. simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +2 -2
  148. simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +2 -2
  149. simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +2 -2
  150. simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +2 -2
  151. simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +2 -2
  152. simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +2 -2
  153. simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +2 -2
  154. simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
  155. simtools/schemas/model_parameters/flatfielding.schema.yml +2 -2
  156. simtools/schemas/model_parameters/focal_length.schema.yml +2 -2
  157. simtools/schemas/model_parameters/focus_offset.schema.yml +2 -2
  158. simtools/schemas/model_parameters/gain_variation.schema.yml +2 -2
  159. simtools/schemas/model_parameters/hg_lg_variation.schema.yml +2 -2
  160. simtools/schemas/model_parameters/iobuf_maximum.schema.yml +2 -2
  161. simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +2 -2
  162. simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
  163. simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +2 -2
  164. simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +2 -2
  165. simtools/schemas/model_parameters/min_photoelectrons.schema.yml +2 -2
  166. simtools/schemas/model_parameters/min_photons.schema.yml +2 -2
  167. simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +2 -2
  168. simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +2 -2
  169. simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +2 -2
  170. simtools/schemas/model_parameters/mirror_class.schema.yml +2 -2
  171. simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +2 -2
  172. simtools/schemas/model_parameters/mirror_focal_length.schema.yml +2 -2
  173. simtools/schemas/model_parameters/mirror_list.schema.yml +2 -2
  174. simtools/schemas/model_parameters/mirror_offset.schema.yml +2 -2
  175. simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +2 -2
  176. simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +2 -2
  177. simtools/schemas/model_parameters/multiplicity_offset.schema.yml +2 -2
  178. simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +2 -2
  179. simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +2 -2
  180. simtools/schemas/model_parameters/nsb_offaxis.schema.yml +2 -2
  181. simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +2 -2
  182. simtools/schemas/model_parameters/num_gains.schema.yml +2 -2
  183. simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +2 -2
  184. simtools/schemas/model_parameters/optics_properties.schema.yml +2 -2
  185. simtools/schemas/model_parameters/pedestal_events.schema.yml +7 -3
  186. simtools/schemas/model_parameters/photon_delay.schema.yml +2 -2
  187. simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +2 -2
  188. simtools/schemas/model_parameters/pm_average_gain.schema.yml +2 -2
  189. simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +2 -2
  190. simtools/schemas/model_parameters/pm_gain_index.schema.yml +2 -2
  191. simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +2 -2
  192. simtools/schemas/model_parameters/pm_transit_time.schema.yml +2 -2
  193. simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +2 -2
  194. simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +2 -2
  195. simtools/schemas/model_parameters/qe_variation.schema.yml +2 -2
  196. simtools/schemas/model_parameters/quantum_efficiency.schema.yml +2 -2
  197. simtools/schemas/model_parameters/random_focal_length.schema.yml +2 -2
  198. simtools/schemas/model_parameters/random_generator.schema.yml +2 -2
  199. simtools/schemas/model_parameters/random_mono_probability.schema.yml +2 -2
  200. simtools/schemas/model_parameters/sampled_output.schema.yml +2 -2
  201. simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +2 -2
  202. simtools/schemas/model_parameters/store_photoelectrons.schema.yml +2 -2
  203. simtools/schemas/model_parameters/tailcut_scale.schema.yml +2 -2
  204. simtools/schemas/model_parameters/telescope_axis_height.schema.yml +2 -2
  205. simtools/schemas/model_parameters/telescope_random_angle.schema.yml +2 -2
  206. simtools/schemas/model_parameters/telescope_random_error.schema.yml +2 -2
  207. simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +2 -2
  208. simtools/schemas/model_parameters/telescope_transmission.schema.yml +2 -2
  209. simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +2 -2
  210. simtools/schemas/model_parameters/teltrig_min_time.schema.yml +2 -2
  211. simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +2 -2
  212. simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +2 -2
  213. simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +2 -2
  214. simtools/schemas/model_parameters/transit_time_error.schema.yml +2 -2
  215. simtools/schemas/model_parameters/transit_time_jitter.schema.yml +2 -2
  216. simtools/schemas/model_parameters/trigger_current_limit.schema.yml +2 -2
  217. simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +2 -2
  218. simtools/schemas/model_parameters/trigger_pixels.schema.yml +2 -2
  219. simtools/schemas/production_configuration_metrics.schema.yml +2 -2
  220. simtools/simtel/simtel_config_reader.py +21 -17
  221. simtools/simtel/simtel_config_writer.py +258 -66
  222. simtools/simtel/simtel_io_event_reader.py +301 -194
  223. simtools/simtel/simtel_io_event_writer.py +207 -227
  224. simtools/simtel/simtel_io_file_info.py +62 -0
  225. simtools/simtel/simtel_io_histogram.py +10 -14
  226. simtools/simtel/simtel_io_histograms.py +2 -2
  227. simtools/simtel/simtel_io_metadata.py +106 -0
  228. simtools/simtel/simulator_array.py +28 -14
  229. simtools/simtel/simulator_camera_efficiency.py +12 -6
  230. simtools/simtel/simulator_light_emission.py +85 -45
  231. simtools/simtel/simulator_ray_tracing.py +16 -6
  232. simtools/simulator.py +286 -89
  233. simtools/testing/configuration.py +5 -0
  234. simtools/testing/helpers.py +18 -0
  235. simtools/testing/sim_telarray_metadata.py +212 -0
  236. simtools/testing/validate_output.py +16 -6
  237. simtools/utils/general.py +18 -27
  238. simtools/utils/names.py +32 -10
  239. simtools/visualization/plot_array_layout.py +242 -0
  240. simtools/visualization/plot_pixels.py +681 -0
  241. simtools/visualization/visualize.py +5 -221
  242. simtools/applications/production_generate_simulation_config.py +0 -162
  243. simtools/applications/production_scale_events.py +0 -185
  244. simtools/layout/ctao_array_layouts.py +0 -172
  245. simtools/production_configuration/event_scaler.py +0 -120
  246. simtools/production_configuration/generate_simulation_config.py +0 -158
  247. {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/licenses/LICENSE +0 -0
  248. {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@
2
2
  """Configuration file writer for sim_telarray."""
3
3
 
4
4
  import logging
5
+ from copy import deepcopy
5
6
  from pathlib import Path
6
7
 
7
8
  import astropy.units as u
@@ -14,6 +15,27 @@ from simtools.utils import names
14
15
  __all__ = ["SimtelConfigWriter"]
15
16
 
16
17
 
18
+ def sim_telarray_random_seeds(seed, number):
19
+ """
20
+ Generate random seeds to be used in sim_telarray.
21
+
22
+ Parameters
23
+ ----------
24
+ seed: int
25
+ Seed for the random number generator.
26
+ number: int
27
+ Number of random seeds to generate.
28
+
29
+ Returns
30
+ -------
31
+ list
32
+ List of random seeds.
33
+ """
34
+ rng = np.random.default_rng(seed)
35
+ max_int32 = np.iinfo(np.int32).max # sim_telarray requires 32 bit integers
36
+ return list(rng.integers(low=1, high=max_int32, size=number, dtype=np.int32))
37
+
38
+
17
39
  class SimtelConfigWriter:
18
40
  """
19
41
  SimtelConfigWriter writes sim_telarray configuration files.
@@ -32,12 +54,20 @@ class SimtelConfigWriter:
32
54
  Layout name.
33
55
  label: str
34
56
  Instance label. Important for output file naming.
57
+ simtel_path: str or Path
58
+ Path to the sim_telarray installation directory.
35
59
  """
36
60
 
37
61
  TAB = " " * 3
38
62
 
39
63
  def __init__(
40
- self, site, model_version, layout_name=None, telescope_model_name=None, label=None
64
+ self,
65
+ site,
66
+ model_version,
67
+ layout_name=None,
68
+ telescope_model_name=None,
69
+ label=None,
70
+ simtel_path=None,
41
71
  ):
42
72
  """Initialize SimtelConfigWriter."""
43
73
  self._logger = logging.getLogger(__name__)
@@ -48,8 +78,9 @@ class SimtelConfigWriter:
48
78
  self._label = label
49
79
  self._layout_name = layout_name
50
80
  self._telescope_model_name = telescope_model_name
81
+ self._simtel_path = simtel_path
51
82
 
52
- def write_telescope_config_file(self, config_file_path, parameters, config_parameters=None):
83
+ def write_telescope_config_file(self, config_file_path, parameters, telescope_name=None):
53
84
  """
54
85
  Write the sim_telarray config file for a single telescope.
55
86
 
@@ -59,41 +90,34 @@ class SimtelConfigWriter:
59
90
  Path of the file to write on.
60
91
  parameters: dict
61
92
  Model parameters
62
- config_parameters: dict
63
- Simulation software configuration parameters
93
+ telescope_name: str
94
+ Name of the telescope (use self._telescope_model_name if None)
64
95
  """
65
96
  self._logger.debug(f"Writing telescope config file {config_file_path}")
66
97
 
67
- if config_parameters:
68
- parameters.update(config_parameters)
69
-
70
98
  with open(config_file_path, "w", encoding="utf-8") as file:
71
99
  self._write_header(file, "TELESCOPE CONFIGURATION FILE")
72
100
 
101
+ telescope_name = telescope_name or self._telescope_model_name
73
102
  file.write("#ifdef TELESCOPE\n")
74
- file.write(
75
- f" echo Configuration for {self._telescope_model_name} - TELESCOPE $(TELESCOPE)\n"
76
- )
103
+ file.write(f" echo Configuration for {telescope_name} - TELESCOPE $(TELESCOPE)\n")
77
104
  file.write("#endif\n\n")
78
105
 
79
106
  for par, value in parameters.items():
80
- _simtel_name = names.get_simulation_software_name_from_parameter_name(
81
- par, simulation_software="sim_telarray"
107
+ simtel_name, value = self._convert_model_parameters_to_simtel_format(
108
+ names.get_simulation_software_name_from_parameter_name(
109
+ par, software_name="sim_telarray"
110
+ ),
111
+ value["value"],
112
+ config_file_path,
113
+ None,
82
114
  )
83
- # array trigger is a site parameter, not a telescope parameter
84
- # fake_mirror_list is not a sim_telarray parameter (used for testeff only)
85
- if (
86
- not _simtel_name
87
- or _simtel_name.startswith("array_trigger")
88
- or _simtel_name == "fake_mirror_list"
89
- ):
90
- continue
91
- file.write(
92
- f"{_simtel_name} = {self._get_value_string_for_simtel(value['value'])}\n"
93
- )
94
- _config_meta = self._get_simtel_metadata("telescope", parameters)
95
- for value in _config_meta:
96
- file.write(f"{value}\n")
115
+ if simtel_name:
116
+ file.write(f"{simtel_name} = {self._get_value_string_for_simtel(value)}\n")
117
+ if "stars" not in parameters: # sim_telarray requires 'stars' to be set
118
+ file.write("stars = none\n")
119
+ for meta in self._get_sim_telarray_metadata("telescope", parameters, telescope_name):
120
+ file.write(f"{meta}\n")
97
121
 
98
122
  def _get_value_string_for_simtel(self, value):
99
123
  """
@@ -116,9 +140,11 @@ class SimtelConfigWriter:
116
140
  value = gen.convert_list_to_string(value, shorten_list=True)
117
141
  return value
118
142
 
119
- def _get_simtel_metadata(self, config_type, model_parameters):
143
+ def _get_sim_telarray_metadata(
144
+ self, config_type, model_parameters, telescope_model_name, sim_telarray_seeds=None
145
+ ):
120
146
  """
121
- Return simtel metadata.
147
+ Return sim_telarray metadata.
122
148
 
123
149
  Parameters
124
150
  ----------
@@ -126,12 +152,15 @@ class SimtelConfigWriter:
126
152
  Type of the configuration file (telescope, site)
127
153
  model_parameters: dict
128
154
  Model parameters dictionary.
155
+ telescope_model_name: str
156
+ Name of the telescope model
157
+ sim_telarray_seeds: dict
158
+ Dictionary with configuration for sim_telarray random instrument setup.
129
159
 
130
160
  Returns
131
161
  -------
132
162
  list
133
- List with simtel metadata.
134
-
163
+ List with sim_telarray metadata.
135
164
  """
136
165
  meta_parameters = [
137
166
  f"config_release = {self._model_version} with simtools v{simtools.version.__version__}",
@@ -140,10 +169,10 @@ class SimtelConfigWriter:
140
169
  if config_type == "telescope":
141
170
  meta_parameters.extend(
142
171
  [
143
- f"camera_config_name = {self._telescope_model_name}",
172
+ f"camera_config_name = {telescope_model_name}",
144
173
  "camera_config_variant = ",
145
174
  f"camera_config_version = {self._model_version}",
146
- f"optics_config_name = {self._telescope_model_name}",
175
+ f"optics_config_name = {telescope_model_name}",
147
176
  "optics_config_variant = ",
148
177
  f"optics_config_version = {self._model_version}",
149
178
  ]
@@ -161,25 +190,41 @@ class SimtelConfigWriter:
161
190
  ]
162
191
  )
163
192
  prefix = "metaparam global"
193
+ meta_parameters.append("metaparam global add random_seed")
164
194
  else:
165
195
  raise ValueError(f"Unknown metadata type {config_type}")
166
196
 
167
- if model_parameters:
168
- for key, value in model_parameters.items():
169
- simtel_name = names.get_simulation_software_name_from_parameter_name(
170
- key, simulation_software="sim_telarray", set_meta_parameter=False
171
- )
172
- if simtel_name and value.get("meta_parameter"):
173
- meta_parameters.append(f"{prefix} add {simtel_name}")
174
- simtel_name = names.get_simulation_software_name_from_parameter_name(
175
- key, simulation_software="sim_telarray", set_meta_parameter=True
176
- )
177
- if simtel_name and value.get("meta_parameter"):
178
- meta_parameters.append(f"{prefix} set {simtel_name}={value['value']}")
197
+ self._add_model_parameters_to_metadata(model_parameters, meta_parameters, prefix)
198
+
199
+ if sim_telarray_seeds and sim_telarray_seeds.get("random_instrument_instances"):
200
+ meta_parameters.append(f"{prefix} set instrument_seed={sim_telarray_seeds['seed']}")
201
+ meta_parameters.append(
202
+ f"{prefix} set instrument_instances="
203
+ f"{sim_telarray_seeds['random_instrument_instances']}"
204
+ )
179
205
 
180
206
  return meta_parameters
181
207
 
182
- def write_array_config_file(self, config_file_path, telescope_model, site_model):
208
+ def _add_model_parameters_to_metadata(self, model_parameters, meta_parameters, prefix):
209
+ """Add model parameters to metadata."""
210
+ if not model_parameters:
211
+ return
212
+
213
+ for key, value in model_parameters.items():
214
+ simtel_name = names.get_simulation_software_name_from_parameter_name(
215
+ key, software_name="sim_telarray", set_meta_parameter=False
216
+ )
217
+ if simtel_name and value.get("meta_parameter"):
218
+ meta_parameters.append(f"{prefix} add {simtel_name}")
219
+ simtel_name = names.get_simulation_software_name_from_parameter_name(
220
+ key, software_name="sim_telarray", set_meta_parameter=True
221
+ )
222
+ if simtel_name and value.get("meta_parameter"):
223
+ meta_parameters.append(f"{prefix} set {simtel_name}={value['value']}")
224
+
225
+ def write_array_config_file(
226
+ self, config_file_path, telescope_model, site_model, sim_telarray_seeds=None
227
+ ):
183
228
  """
184
229
  Write the sim_telarray config file for an array of telescopes.
185
230
 
@@ -191,11 +236,13 @@ class SimtelConfigWriter:
191
236
  Dictionary of TelescopeModel's instances as used by the ArrayModel instance.
192
237
  site_model: Site model
193
238
  Site model.
239
+ sim_telarray_seeds: dict
240
+ Dictionary with configuration for sim_telarray random instrument setup.
194
241
  """
242
+ config_file_directory = Path(config_file_path).parent
195
243
  with open(config_file_path, "w", encoding="utf-8") as file:
196
244
  self._write_header(file, "ARRAY CONFIGURATION FILE")
197
245
 
198
- # Be careful with the formatting - simtel is sensitive
199
246
  file.write("#ifndef TELESCOPE\n")
200
247
  file.write("# define TELESCOPE 0\n")
201
248
  file.write("#endif\n\n")
@@ -208,27 +255,68 @@ class SimtelConfigWriter:
208
255
  file.write(self.TAB + f"echo ModelVersion: {self._model_version}\n")
209
256
  file.write(self.TAB + "echo *****************************\n\n")
210
257
 
211
- # Writing site parameters
258
+ self._write_simtools_parameters(file)
259
+
212
260
  self._write_site_parameters(
213
- file, site_model.parameters, Path(config_file_path).parent, telescope_model
261
+ file,
262
+ site_model.parameters,
263
+ config_file_directory,
264
+ telescope_model,
265
+ sim_telarray_seeds,
214
266
  )
215
267
 
216
- # Maximum telescopes
217
268
  file.write(self.TAB + f"maximum_telescopes = {len(telescope_model)}\n\n")
218
269
 
219
270
  # Default telescope in sim_telarray - 0th tel in telescope list
220
271
  _, first_telescope = next(iter(telescope_model.items()))
221
- tel_config_file = first_telescope.get_config_file(no_export=True).name
222
- file.write(f"# include <{tel_config_file}>\n\n")
272
+ invalid_telescope_name = "InvalidTelescope"
273
+ file.write(f"# include <{invalid_telescope_name}.cfg>\n\n")
274
+ self.write_dummy_telescope_configuration_file(
275
+ deepcopy(first_telescope.parameters),
276
+ config_file_directory / f"{invalid_telescope_name}.cfg",
277
+ invalid_telescope_name,
278
+ )
223
279
 
224
- # Looping over telescopes
225
280
  for count, (tel_name, tel_model) in enumerate(telescope_model.items()):
226
- tel_config_file = tel_model.get_config_file(no_export=True).name
227
- file.write(f"%{tel_name}\n")
281
+ tel_config_file = tel_model.config_file_path.name
282
+ file.write(f"% {tel_name}\n")
228
283
  file.write(f"#elif TELESCOPE == {count + 1}\n\n")
229
284
  file.write(f"# include <{tel_config_file}>\n\n")
230
285
  file.write("#endif \n\n") # configuration files need to end with \n\n
231
286
 
287
+ if sim_telarray_seeds and sim_telarray_seeds.get("random_instrument_instances"):
288
+ self._write_random_seeds_file(sim_telarray_seeds, config_file_directory)
289
+
290
+ def _write_random_seeds_file(self, sim_telarray_seeds, config_file_directory):
291
+ """
292
+ Write list of random number used to generate random instances of instrument.
293
+
294
+ Parameters
295
+ ----------
296
+ random_instrument_instances: int
297
+ Number of random instances of the instrument.
298
+ """
299
+ self._logger.info(
300
+ "Writing random seed file "
301
+ f"{config_file_directory}/{sim_telarray_seeds['seed_file_name']}"
302
+ f" (global seed {sim_telarray_seeds['seed']})"
303
+ )
304
+ if sim_telarray_seeds["random_instrument_instances"] > 1024:
305
+ raise ValueError("Number of random instances of instrument must be less than 1024")
306
+ random_integers = sim_telarray_random_seeds(
307
+ sim_telarray_seeds["seed"], sim_telarray_seeds["random_instrument_instances"]
308
+ )
309
+ with open(
310
+ config_file_directory / sim_telarray_seeds["seed_file_name"], "w", encoding="utf-8"
311
+ ) as file:
312
+ file.write(
313
+ "# Random seeds for instrument configuration generated with seed "
314
+ f"{sim_telarray_seeds['seed']}"
315
+ f" (model version {self._model_version}, site {self._site})\n"
316
+ )
317
+ for number in random_integers:
318
+ file.write(f"{number}\n")
319
+
232
320
  def write_single_mirror_list_file(
233
321
  self, mirror_number, mirrors, single_mirror_list_file, set_focal_length_to_zero=False
234
322
  ):
@@ -288,7 +376,7 @@ class SimtelConfigWriter:
288
376
  title: str
289
377
  Title of the header.
290
378
  comment_char: str
291
- Character to be used for comments, which differs among ctypes of config files.
379
+ Character to be used for comments, which differs among types of config files.
292
380
  """
293
381
  header = f"{comment_char}{50 * '='}\n"
294
382
  header += f"{comment_char} {title}\n"
@@ -309,7 +397,26 @@ class SimtelConfigWriter:
309
397
  header += f"{comment_char}\n"
310
398
  file.write(header)
311
399
 
312
- def _write_site_parameters(self, file, site_parameters, model_path, telescope_model):
400
+ def _write_simtools_parameters(self, file):
401
+ """Write simtools-specific parameters."""
402
+ meta_items = {
403
+ "simtools_version": simtools.version.__version__,
404
+ "simtools_model_production_version": self._model_version,
405
+ }
406
+ try:
407
+ build_opts = gen.collect_data_from_file(Path(self._simtel_path) / "build_opts.yml")
408
+ for key, value in build_opts.items():
409
+ meta_items[f"simtools_{key}"] = value
410
+ except (FileNotFoundError, TypeError):
411
+ pass # don't expect build_opts.yml to be present on all systems
412
+
413
+ file.write(f"{self.TAB}% Simtools parameters\n")
414
+ for key, value in meta_items.items():
415
+ file.write(f"{self.TAB}metaparam global set {key} = {value}\n")
416
+
417
+ def _write_site_parameters(
418
+ self, file, site_parameters, model_path, telescope_model, sim_telarray_seeds=None
419
+ ):
313
420
  """
314
421
  Write site parameters.
315
422
 
@@ -323,20 +430,25 @@ class SimtelConfigWriter:
323
430
  Path to the model for writing of additional files.
324
431
  telescope_model: dict of TelescopeModel
325
432
  Telescope models.
433
+ sim_telarray_seeds: dict
434
+ Dictionary with configuration for sim_telarray random instrument setup.
326
435
  """
327
436
  file.write(self.TAB + "% Site parameters\n")
328
437
  for par, value in site_parameters.items():
329
- _simtel_name = names.get_simulation_software_name_from_parameter_name(
330
- par, simulation_software="sim_telarray"
331
- )
332
- _simtel_name, value = self._convert_model_parameters_to_simtel_format(
333
- _simtel_name, value["value"], model_path, telescope_model
438
+ simtel_name, value = self._convert_model_parameters_to_simtel_format(
439
+ names.get_simulation_software_name_from_parameter_name(
440
+ par, software_name="sim_telarray"
441
+ ),
442
+ value["value"],
443
+ model_path,
444
+ telescope_model,
334
445
  )
335
- if _simtel_name is not None:
336
- file.write(f"{self.TAB}{_simtel_name} = {value}\n")
337
- _simtel_meta = self._get_simtel_metadata("site", site_parameters)
338
- for value in _simtel_meta:
339
- file.write(f"{self.TAB}{value}\n")
446
+ if simtel_name is not None:
447
+ file.write(f"{self.TAB}{simtel_name} = {value}\n")
448
+ for meta in self._get_sim_telarray_metadata(
449
+ "site", site_parameters, self._telescope_model_name, sim_telarray_seeds
450
+ ):
451
+ file.write(f"{self.TAB}{meta}\n")
340
452
  file.write("\n")
341
453
 
342
454
  def _convert_model_parameters_to_simtel_format(
@@ -370,6 +482,8 @@ class SimtelConfigWriter:
370
482
  value = conversion_dict[simtel_name](value, model_path, telescope_model)
371
483
  except KeyError:
372
484
  pass
485
+ except AttributeError: # covers cases where telescope_model is None
486
+ return None, None
373
487
  return simtel_name, value
374
488
 
375
489
  def _write_array_triggers_file(self, array_triggers, model_path, telescope_model):
@@ -432,3 +546,81 @@ class SimtelConfigWriter:
432
546
  if trigger_dict["name"] == telescope_type + "_array":
433
547
  return trigger_dict
434
548
  return None
549
+
550
+ def write_dummy_telescope_configuration_file(
551
+ self, parameters, config_file_path, telescope_name
552
+ ):
553
+ """
554
+ Write 'dummy' telescope configuration file used as zeroth telescope in sim_telarray.
555
+
556
+ Replaces key telescope configuration values with dummy values.
557
+
558
+ Parameters
559
+ ----------
560
+ parameters: dict
561
+ Telescope parameters used as template.
562
+ config_file_path: str or Path
563
+ Path of the dummy configuration file to write on.
564
+ telescope_name: str
565
+ Name of the telescope.
566
+ """
567
+ self._logger.debug(f"Writing {telescope_name} telescope config file {config_file_path}")
568
+ dummy_defaults = {
569
+ "camera_config_file": f"{telescope_name}_single_pixel_camera.dat",
570
+ "discriminator_pulse_shape": f"{telescope_name}_pulse.dat",
571
+ "fadc_pulse_shape": f"{telescope_name}_pulse.dat",
572
+ "mirror_list": f"{telescope_name}_single_12m_mirror.dat",
573
+ "mirror_reflectivity": f"{telescope_name}_reflectivity.dat",
574
+ "camera_pixels": 1,
575
+ "trigger_pixels": 1,
576
+ "num_gains": 1,
577
+ "fadc_bins": 10,
578
+ "disc_bins": 10,
579
+ "fadc_sum_bins": 10,
580
+ "fadc_sum_offset": 0,
581
+ "asum_threshold": 9999,
582
+ "dsum_threshold": 9999,
583
+ "discriminator_threshold": 9999,
584
+ "fadc_amplitude": 1.0,
585
+ "discriminator_amplitude": 1.0,
586
+ }
587
+
588
+ for key, val in dummy_defaults.items():
589
+ if key in parameters:
590
+ parameters[key]["value"] = val
591
+
592
+ self.write_telescope_config_file(config_file_path, parameters, telescope_name)
593
+
594
+ config_file_directory = Path(config_file_path).parent
595
+ self._write_dummy_mirror_list_files(config_file_directory, telescope_name)
596
+ self._write_dummy_camera_files(config_file_directory, telescope_name)
597
+
598
+ def _write_dummy_mirror_list_files(self, config_directory, telescope_name):
599
+ """Write dummy mirror list with single mirror and reflectivity file."""
600
+ with open(
601
+ config_directory / f"{telescope_name}_single_12m_mirror.dat", "w", encoding="utf-8"
602
+ ) as file:
603
+ file.write("0 0 1200 0.0 0\n")
604
+ with open(
605
+ config_directory / f"{telescope_name}_reflectivity.dat", "w", encoding="utf-8"
606
+ ) as file:
607
+ file.writelines(f"{w} 0.8\n" for w in range(200, 801, 50))
608
+
609
+ def _write_dummy_camera_files(self, config_directory, telescope_name):
610
+ """Write dummy camera, pulse shape, and funnels file with a single pixel."""
611
+ with open(
612
+ config_directory / f"{telescope_name}_single_pixel_camera.dat", "w", encoding="utf-8"
613
+ ) as file:
614
+ file.write(f'PixType 1 0 0 300 1 300 0.00 "{telescope_name}_funnels.dat"\n')
615
+ file.write("Pixel 0 1 0. 0. 0 0 0 0x00 1\n")
616
+ file.write("Trigger 1 of 0\n")
617
+
618
+ with open(config_directory / f"{telescope_name}_funnel.dat", "w", encoding="utf-8") as file:
619
+ file.writelines(f"{a} 0.78 1.5\n" for a in range(36))
620
+
621
+ with open(config_directory / f"{telescope_name}_pulse.dat", "w", encoding="utf-8") as file:
622
+ file.write("0 0 0\n")
623
+ file.write("1 1 1\n")
624
+ file.write("2 2 2\n")
625
+ file.write("3 3 3\n")
626
+ file.write("4 0 0\n")