gammasimtools 0.12.0__py3-none-any.whl → 0.14.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 (276) hide show
  1. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/METADATA +3 -3
  2. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/RECORD +257 -263
  3. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/WHEEL +1 -1
  4. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/entry_points.txt +4 -1
  5. simtools/_version.py +2 -2
  6. simtools/applications/convert_all_model_parameters_from_simtel.py +77 -88
  7. simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -1
  8. simtools/applications/db_add_file_to_db.py +15 -0
  9. simtools/applications/db_add_value_from_json_to_db.py +18 -1
  10. simtools/applications/db_get_parameter_from_db.py +52 -22
  11. simtools/applications/derive_ctao_array_layouts.py +120 -0
  12. simtools/applications/derive_photon_electron_spectrum.py +30 -2
  13. simtools/applications/docs_produce_array_element_report.py +42 -26
  14. simtools/applications/docs_produce_model_parameter_reports.py +28 -21
  15. simtools/applications/generate_simtel_event_data.py +117 -0
  16. simtools/applications/plot_tabular_data.py +14 -2
  17. simtools/applications/print_version.py +81 -0
  18. simtools/applications/production_derive_corsika_limits.py +240 -0
  19. simtools/applications/production_scale_events.py +59 -36
  20. simtools/applications/run_application.py +47 -18
  21. simtools/applications/simulate_light_emission.py +115 -247
  22. simtools/applications/simulate_prod_htcondor_generator.py +2 -2
  23. simtools/applications/submit_data_from_external.py +1 -1
  24. simtools/applications/submit_model_parameter_from_external.py +2 -1
  25. simtools/camera/single_photon_electron_spectrum.py +169 -17
  26. simtools/constants.py +7 -0
  27. simtools/data_model/metadata_collector.py +159 -61
  28. simtools/data_model/model_data_writer.py +18 -61
  29. simtools/data_model/schema.py +2 -1
  30. simtools/data_model/validate_data.py +5 -3
  31. simtools/db/db_handler.py +123 -33
  32. simtools/dependencies.py +38 -3
  33. simtools/layout/array_layout.py +1 -0
  34. simtools/layout/ctao_array_layouts.py +172 -0
  35. simtools/model/array_model.py +3 -4
  36. simtools/model/model_parameter.py +30 -118
  37. simtools/production_configuration/derive_corsika_limits.py +328 -0
  38. simtools/production_configuration/event_scaler.py +2 -2
  39. simtools/ray_tracing/mirror_panel_psf.py +1 -1
  40. simtools/reporting/docs_auto_report_generator.py +217 -0
  41. simtools/reporting/docs_read_parameters.py +298 -143
  42. simtools/schemas/application_workflow.metaschema.yml +3 -0
  43. simtools/schemas/metadata.metaschema.yml +7 -6
  44. simtools/schemas/model_parameter.metaschema.yml +13 -4
  45. simtools/schemas/model_parameter_and_data_schema.metaschema.yml +19 -5
  46. simtools/schemas/model_parameters/adjust_gain.schema.yml +1 -1
  47. simtools/schemas/model_parameters/altitude.schema.yml +1 -1
  48. simtools/schemas/model_parameters/array_coordinates.schema.yml +1 -1
  49. simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +3 -3
  50. simtools/schemas/model_parameters/array_element_position_ground.schema.yml +3 -3
  51. simtools/schemas/model_parameters/array_element_position_utm.schema.yml +3 -3
  52. simtools/schemas/model_parameters/array_layouts.schema.yml +3 -0
  53. simtools/schemas/model_parameters/array_window.schema.yml +1 -1
  54. simtools/schemas/model_parameters/asum_clipping.schema.yml +1 -1
  55. simtools/schemas/model_parameters/asum_offset.schema.yml +1 -1
  56. simtools/schemas/model_parameters/asum_shaping.schema.yml +1 -1
  57. simtools/schemas/model_parameters/asum_threshold.schema.yml +1 -1
  58. simtools/schemas/model_parameters/atmospheric_profile.schema.yml +1 -1
  59. simtools/schemas/model_parameters/axes_offsets.schema.yml +2 -2
  60. simtools/schemas/model_parameters/camera_body_diameter.schema.yml +1 -1
  61. simtools/schemas/model_parameters/camera_body_shape.schema.yml +1 -1
  62. simtools/schemas/model_parameters/camera_config_file.schema.yml +1 -1
  63. simtools/schemas/model_parameters/camera_config_rotate.schema.yml +1 -1
  64. simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +1 -1
  65. simtools/schemas/model_parameters/camera_degraded_map.schema.yml +1 -1
  66. simtools/schemas/model_parameters/camera_depth.schema.yml +1 -1
  67. simtools/schemas/model_parameters/camera_filter.schema.yml +1 -1
  68. simtools/schemas/model_parameters/camera_pixels.schema.yml +1 -1
  69. simtools/schemas/model_parameters/camera_transmission.schema.yml +1 -1
  70. simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
  71. simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +1 -1
  72. simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +1 -1
  73. simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +1 -1
  74. simtools/schemas/model_parameters/corsika_observation_level.schema.yml +1 -1
  75. simtools/schemas/model_parameters/dark_events.schema.yml +1 -1
  76. simtools/schemas/model_parameters/disc_bins.schema.yml +1 -1
  77. simtools/schemas/model_parameters/disc_start.schema.yml +1 -1
  78. simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +1 -1
  79. simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +1 -1
  80. simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +1 -1
  81. simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +1 -1
  82. simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +1 -1
  83. simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +1 -1
  84. simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +1 -1
  85. simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +1 -1
  86. simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +1 -1
  87. simtools/schemas/model_parameters/discriminator_threshold.schema.yml +1 -1
  88. simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +1 -1
  89. simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +1 -1
  90. simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +1 -1
  91. simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +1 -1
  92. simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +1 -1
  93. simtools/schemas/model_parameters/dish_shape_length.schema.yml +1 -1
  94. simtools/schemas/model_parameters/dsum_clipping.schema.yml +1 -1
  95. simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +1 -1
  96. simtools/schemas/model_parameters/dsum_offset.schema.yml +1 -1
  97. simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +1 -1
  98. simtools/schemas/model_parameters/dsum_prescale.schema.yml +2 -2
  99. simtools/schemas/model_parameters/dsum_presum_max.schema.yml +1 -1
  100. simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +1 -1
  101. simtools/schemas/model_parameters/dsum_shaping.schema.yml +1 -1
  102. simtools/schemas/model_parameters/dsum_threshold.schema.yml +1 -1
  103. simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +1 -1
  104. simtools/schemas/model_parameters/effective_focal_length.schema.yml +5 -5
  105. simtools/schemas/model_parameters/epsg_code.schema.yml +1 -1
  106. simtools/schemas/model_parameters/fadc_amplitude.schema.yml +1 -1
  107. simtools/schemas/model_parameters/fadc_bins.schema.yml +1 -1
  108. simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
  109. simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +2 -2
  110. simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +1 -1
  111. simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +1 -1
  112. simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +1 -1
  113. simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
  114. simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +2 -2
  115. simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +1 -1
  116. simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +1 -1
  117. simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +1 -1
  118. simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +4 -4
  119. simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +1 -1
  120. simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +1 -1
  121. simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +1 -1
  122. simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +1 -1
  123. simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +1 -1
  124. simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +1 -1
  125. simtools/schemas/model_parameters/fadc_max_signal.schema.yml +1 -1
  126. simtools/schemas/model_parameters/fadc_max_sum.schema.yml +4 -4
  127. simtools/schemas/model_parameters/fadc_mhz.schema.yml +1 -1
  128. simtools/schemas/model_parameters/fadc_noise.schema.yml +1 -1
  129. simtools/schemas/model_parameters/fadc_pedestal.schema.yml +1 -1
  130. simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +1 -1
  131. simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +1 -1
  132. simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +1 -1
  133. simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +1 -1
  134. simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +1 -1
  135. simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +1 -1
  136. simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
  137. simtools/schemas/model_parameters/focal_length.schema.yml +1 -1
  138. simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +20 -20
  139. simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +1 -1
  140. simtools/schemas/model_parameters/focus_offset.schema.yml +4 -4
  141. simtools/schemas/model_parameters/gain_variation.schema.yml +1 -1
  142. simtools/schemas/model_parameters/geomag_horizontal.schema.yml +1 -1
  143. simtools/schemas/model_parameters/geomag_rotation.schema.yml +1 -1
  144. simtools/schemas/model_parameters/geomag_vertical.schema.yml +1 -1
  145. simtools/schemas/model_parameters/hg_lg_variation.schema.yml +1 -1
  146. simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
  147. simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
  148. simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
  149. simtools/schemas/model_parameters/laser_external_trigger.schema.yml +1 -1
  150. simtools/schemas/model_parameters/laser_photons.schema.yml +1 -1
  151. simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +1 -1
  152. simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +1 -1
  153. simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +1 -1
  154. simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +1 -1
  155. simtools/schemas/model_parameters/laser_var_photons.schema.yml +1 -1
  156. simtools/schemas/model_parameters/laser_wavelength.schema.yml +1 -1
  157. simtools/schemas/model_parameters/led_events.schema.yml +1 -1
  158. simtools/schemas/model_parameters/led_photons.schema.yml +1 -1
  159. simtools/schemas/model_parameters/led_pulse_offset.schema.yml +1 -1
  160. simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +1 -1
  161. simtools/schemas/model_parameters/led_var_photons.schema.yml +1 -1
  162. simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +1 -1
  163. simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +1 -1
  164. simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
  165. simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
  166. simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +1 -1
  167. simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +4 -4
  168. simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +4 -4
  169. simtools/schemas/model_parameters/mirror_class.schema.yml +1 -1
  170. simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +1 -1
  171. simtools/schemas/model_parameters/mirror_focal_length.schema.yml +1 -1
  172. simtools/schemas/model_parameters/mirror_list.schema.yml +1 -1
  173. simtools/schemas/model_parameters/mirror_offset.schema.yml +1 -1
  174. simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +3 -3
  175. simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +3 -3
  176. simtools/schemas/model_parameters/multiplicity_offset.schema.yml +1 -1
  177. simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +45 -0
  178. simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +2 -2
  179. simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +1 -1
  180. simtools/schemas/model_parameters/nsb_offaxis.schema.yml +5 -5
  181. simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +1 -1
  182. simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +1 -1
  183. simtools/schemas/model_parameters/nsb_reference_value.schema.yml +1 -1
  184. simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +1 -1
  185. simtools/schemas/model_parameters/{nsb_skymap.schema.yml → nsb_sky_map.schema.yml} +1 -1
  186. simtools/schemas/model_parameters/nsb_spectrum.schema.yml +2 -2
  187. simtools/schemas/model_parameters/num_gains.schema.yml +1 -1
  188. simtools/schemas/model_parameters/pedestal_events.schema.yml +1 -1
  189. simtools/schemas/model_parameters/photon_delay.schema.yml +1 -1
  190. simtools/schemas/model_parameters/photons_per_run.schema.yml +1 -1
  191. simtools/schemas/model_parameters/pixel_cells.schema.yml +1 -1
  192. simtools/schemas/model_parameters/pixels_parallel.schema.yml +1 -1
  193. simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +1 -1
  194. simtools/schemas/model_parameters/pm_average_gain.schema.yml +1 -1
  195. simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +1 -1
  196. simtools/schemas/model_parameters/pm_gain_index.schema.yml +1 -1
  197. simtools/schemas/model_parameters/pm_transit_time.schema.yml +4 -4
  198. simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +1 -1
  199. simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +8 -4
  200. simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +1 -1
  201. simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +1 -1
  202. simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +20 -20
  203. simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +1 -1
  204. simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +1 -1
  205. simtools/schemas/model_parameters/qe_variation.schema.yml +1 -1
  206. simtools/schemas/model_parameters/random_focal_length.schema.yml +2 -2
  207. simtools/schemas/model_parameters/random_mono_probability.schema.yml +38 -0
  208. simtools/schemas/model_parameters/reference_point_altitude.schema.yml +1 -1
  209. simtools/schemas/model_parameters/reference_point_latitude.schema.yml +4 -1
  210. simtools/schemas/model_parameters/reference_point_longitude.schema.yml +4 -1
  211. simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +1 -1
  212. simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +1 -1
  213. simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +5 -5
  214. simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +1 -1
  215. simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
  216. simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +1 -1
  217. simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +1 -1
  218. simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +20 -20
  219. simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +1 -1
  220. simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +1 -1
  221. simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +1 -1
  222. simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +1 -1
  223. simtools/schemas/model_parameters/stars.schema.yml +36 -0
  224. simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
  225. simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
  226. simtools/schemas/model_parameters/telescope_axis_height.schema.yml +1 -1
  227. simtools/schemas/model_parameters/telescope_random_angle.schema.yml +1 -1
  228. simtools/schemas/model_parameters/telescope_random_error.schema.yml +1 -1
  229. simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +1 -1
  230. simtools/schemas/model_parameters/telescope_transmission.schema.yml +6 -6
  231. simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +1 -1
  232. simtools/schemas/model_parameters/teltrig_min_time.schema.yml +1 -1
  233. simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +1 -1
  234. simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +1 -1
  235. simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +1 -1
  236. simtools/schemas/model_parameters/transit_time_error.schema.yml +1 -1
  237. simtools/schemas/model_parameters/transit_time_jitter.schema.yml +1 -1
  238. simtools/schemas/model_parameters/trigger_current_limit.schema.yml +1 -1
  239. simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +4 -4
  240. simtools/schemas/model_parameters/trigger_pixels.schema.yml +1 -1
  241. simtools/schemas/plot_configuration.metaschema.yml +162 -0
  242. simtools/schemas/production_tables.schema.yml +1 -1
  243. simtools/simtel/simtel_config_reader.py +85 -34
  244. simtools/simtel/simtel_config_writer.py +70 -38
  245. simtools/simtel/simtel_io_event_reader.py +278 -0
  246. simtools/simtel/simtel_io_event_writer.py +317 -0
  247. simtools/simtel/simtel_table_reader.py +4 -0
  248. simtools/simtel/simulator_light_emission.py +181 -67
  249. simtools/simulator.py +2 -2
  250. simtools/testing/configuration.py +17 -0
  251. simtools/utils/general.py +83 -16
  252. simtools/utils/geometry.py +19 -0
  253. simtools/utils/names.py +14 -3
  254. simtools/visualization/plot_tables.py +25 -20
  255. simtools/visualization/visualize.py +73 -25
  256. simtools/_dev_version/__init__.py +0 -9
  257. simtools/applications/__init__.py +0 -0
  258. simtools/applications/production_derive_limits.py +0 -95
  259. simtools/configuration/__init__.py +0 -0
  260. simtools/corsika/__init__.py +0 -0
  261. simtools/data_model/__init__.py +0 -0
  262. simtools/db/__init__.py +0 -0
  263. simtools/io_operations/__init__.py +0 -0
  264. simtools/job_execution/__init__.py +0 -0
  265. simtools/layout/__init__.py +0 -0
  266. simtools/model/__init__.py +0 -0
  267. simtools/production_configuration/limits_calculation.py +0 -202
  268. simtools/ray_tracing/__init__.py +0 -0
  269. simtools/runners/__init__.py +0 -0
  270. simtools/simtel/__init__.py +0 -0
  271. simtools/simtel/simtel_io_events.py +0 -265
  272. simtools/testing/__init__.py +0 -0
  273. simtools/utils/__init__.py +0 -0
  274. simtools/visualization/__init__.py +0 -0
  275. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info/licenses}/LICENSE +0 -0
  276. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/top_level.txt +0 -0
@@ -12,7 +12,7 @@ from simtools.io_operations import io_handler
12
12
  from simtools.model.site_model import SiteModel
13
13
  from simtools.model.telescope_model import TelescopeModel
14
14
  from simtools.simtel.simtel_config_writer import SimtelConfigWriter
15
- from simtools.utils import general, names
15
+ from simtools.utils import names
16
16
 
17
17
  __all__ = ["ArrayModel"]
18
18
 
@@ -326,12 +326,11 @@ class ArrayModel:
326
326
  "site": site,
327
327
  "parameter_version": parameter_version,
328
328
  "unique_id": None,
329
- "value": general.convert_list_to_string(
330
- [x.to("m").value, y.to("m").value, z.to("m").value]
331
- ),
329
+ "value": [x.to("m").value, y.to("m").value, z.to("m").value],
332
330
  "unit": "m",
333
331
  "type": "float64",
334
332
  "file": False,
333
+ "meta_parameter": False,
335
334
  }
336
335
 
337
336
  def _get_array_elements_from_list(self, array_elements_list: list[str]) -> dict:
@@ -6,12 +6,10 @@ import shutil
6
6
  from copy import copy
7
7
 
8
8
  import astropy.units as u
9
- from astropy.table import Table
10
9
 
11
10
  import simtools.utils.general as gen
12
11
  from simtools.db import db_handler
13
12
  from simtools.io_operations import io_handler
14
- from simtools.simtel import simtel_table_reader
15
13
  from simtools.simtel.simtel_config_writer import SimtelConfigWriter
16
14
  from simtools.utils import names
17
15
 
@@ -88,6 +86,18 @@ class ModelParameter:
88
86
  self._is_config_file_up_to_date = False
89
87
  self._is_exported_model_files_up_to_date = False
90
88
 
89
+ @property
90
+ def parameters(self):
91
+ """
92
+ Model parameters dictionary.
93
+
94
+ Returns
95
+ -------
96
+ dict
97
+ Dictionary containing all model parameters
98
+ """
99
+ return self._parameters
100
+
91
101
  def _get_parameter_dict(self, par_name):
92
102
  """
93
103
  Get model parameter dictionary as stored in the DB.
@@ -112,11 +122,11 @@ class ModelParameter:
112
122
  If par_name does not match any parameter in this model.
113
123
  """
114
124
  try:
115
- return self._parameters[par_name]
125
+ return self.parameters[par_name]
116
126
  except (KeyError, ValueError) as e:
117
- msg = f"Parameter {par_name} was not found in the model {self.name}, {self.site}."
118
- self._logger.error(msg)
119
- raise InvalidModelParameterError(msg) from e
127
+ raise InvalidModelParameterError(
128
+ f"Parameter {par_name} was not found in the model {self.name}, {self.site}."
129
+ ) from e
120
130
 
121
131
  def get_parameter_value(self, par_name, parameter_dict=None):
122
132
  """
@@ -260,7 +270,7 @@ class ModelParameter:
260
270
 
261
271
  def print_parameters(self):
262
272
  """Print parameters and their values for debugging purposes."""
263
- for par in self._parameters:
273
+ for par in self.parameters:
264
274
  print(f"{par} = {self.get_parameter_value(par)}")
265
275
 
266
276
  def _set_config_file_directory_and_name(self):
@@ -300,21 +310,6 @@ class ModelParameter:
300
310
  """
301
311
  return self._simulation_config_parameters.get(simulation_software)
302
312
 
303
- def has_parameter(self, par_name):
304
- """Check if a parameter exists in the model.
305
-
306
- Parameters
307
- ----------
308
- par_name : str
309
- Name of the parameter.
310
-
311
- Returns
312
- -------
313
- bool
314
- True if parameter exists in the model.
315
- """
316
- return par_name in self._parameters
317
-
318
313
  def _load_simulation_software_parameter(self):
319
314
  """Read simulation software parameters from DB."""
320
315
  for simulation_software in self._simulation_config_parameters:
@@ -339,12 +334,12 @@ class ModelParameter:
339
334
  if self.db is None:
340
335
  return
341
336
 
342
- if self.name is not None:
337
+ if self.name:
343
338
  self._parameters = self.db.get_model_parameters(
344
339
  self.site, self.name, self.collection, self.model_version
345
340
  )
346
341
 
347
- if self.site is not None:
342
+ if self.site:
348
343
  self._parameters.update(
349
344
  self.db.get_model_parameters(
350
345
  self.site,
@@ -355,56 +350,11 @@ class ModelParameter:
355
350
  )
356
351
  self._load_simulation_software_parameter()
357
352
 
358
- def set_extra_label(self, extra_label):
359
- """
360
- Set an extra label for the name of the config file.
361
-
362
- Notes
363
- -----
364
- The config file directory name is not affected by the extra label. Only the file name is \
365
- changed. This is important for the ArrayModel class to export multiple config files in the\
366
- same directory.
367
-
368
- Parameters
369
- ----------
370
- extra_label: str
371
- Extra label to be appended to the original label.
372
- """
373
- self._extra_label = extra_label
374
- self._set_config_file_directory_and_name()
375
-
376
353
  @property
377
354
  def extra_label(self):
378
355
  """Return the extra label if defined, if not return ''."""
379
356
  return self._extra_label if self._extra_label is not None else ""
380
357
 
381
- def get_simtel_parameters(self, parameters=None):
382
- """
383
- Get simtel parameters as name and value pairs.
384
-
385
- Parameters
386
- ----------
387
- parameters: dict
388
- Parameters (simtools) to be renamed (if necessary)
389
-
390
- Returns
391
- -------
392
- dict
393
- simtel parameters as dict (sorted by parameter names)
394
-
395
- """
396
- if parameters is None:
397
- parameters = self._parameters
398
-
399
- _simtel_parameter_value = {}
400
- for key in parameters:
401
- _par_name = names.get_simulation_software_name_from_parameter_name(
402
- key, simulation_software="sim_telarray"
403
- )
404
- if _par_name is not None:
405
- _simtel_parameter_value[_par_name] = parameters[key].get("value")
406
- return dict(sorted(_simtel_parameter_value.items()))
407
-
408
358
  def change_parameter(self, par_name, value):
409
359
  """
410
360
  Change the value of an existing parameter.
@@ -423,29 +373,24 @@ class ModelParameter:
423
373
  InvalidModelParameterError
424
374
  If the parameter to be changed does not exist in this model.
425
375
  """
426
- if par_name not in self._parameters:
427
- msg = f"Parameter {par_name} not in the model"
428
- self._logger.error(msg)
429
- raise InvalidModelParameterError(msg)
376
+ if par_name not in self.parameters:
377
+ raise InvalidModelParameterError(f"Parameter {par_name} not in the model")
430
378
 
431
- if isinstance(value, str):
432
- value = gen.convert_string_to_list(value)
379
+ value = gen.convert_string_to_list(value) if isinstance(value, str) else value
433
380
 
381
+ par_type = self.get_parameter_type(par_name)
434
382
  if not gen.validate_data_type(
435
- reference_dtype=self.get_parameter_type(par_name),
383
+ reference_dtype=par_type,
436
384
  value=value,
437
385
  dtype=None,
438
386
  allow_subtypes=True,
439
387
  ):
440
- raise ValueError(
441
- f"Could not cast {value} of type {type(value)} "
442
- f"to {self.get_parameter_type(par_name)}."
443
- )
388
+ raise ValueError(f"Could not cast {value} of type {type(value)} to {par_type}.")
444
389
 
445
390
  self._logger.debug(
446
391
  f"Changing parameter {par_name} from {self.get_parameter_value(par_name)} to {value}"
447
392
  )
448
- self._parameters[par_name]["value"] = value
393
+ self.parameters[par_name]["value"] = value
449
394
 
450
395
  # In case parameter is a file, the model files will be outdated
451
396
  if self.get_parameter_file_flag(par_name):
@@ -485,7 +430,7 @@ class ModelParameter:
485
430
 
486
431
  """
487
432
  for par, value in kwargs.items():
488
- if par in self._parameters:
433
+ if par in self.parameters:
489
434
  self.change_parameter(par, value)
490
435
 
491
436
  self._is_config_file_up_to_date = False
@@ -509,7 +454,7 @@ class ModelParameter:
509
454
  def export_model_files(self):
510
455
  """Export the model files into the config file directory."""
511
456
  # Removing parameter files added manually (which are not in DB)
512
- pars_from_db = copy(self._parameters)
457
+ pars_from_db = copy(self.parameters)
513
458
  if self._added_parameter_files is not None:
514
459
  for par in self._added_parameter_files:
515
460
  pars_from_db.pop(par)
@@ -517,49 +462,16 @@ class ModelParameter:
517
462
  self.db.export_model_files(parameters=pars_from_db, dest=self.config_file_directory)
518
463
  self._is_exported_model_files_up_to_date = True
519
464
 
520
- def get_model_file_as_table(self, par_name):
521
- """
522
- Return tabular data from file as astropy table.
523
-
524
- Parameters
525
- ----------
526
- par_name: str
527
- Name of the parameter.
528
-
529
- Returns
530
- -------
531
- Table
532
- Astropy table.
533
- """
534
- _par_entry = {}
535
- try:
536
- _par_entry[par_name] = self._parameters[par_name]
537
- except KeyError as exc:
538
- raise ValueError(f"Parameter {par_name} not found in the model.") from exc
539
- self.db.export_model_files(parameters=_par_entry, dest=self.config_file_directory)
540
- if _par_entry[par_name]["value"].endswith("ecsv"):
541
- return Table.read(
542
- self.config_file_directory.joinpath(_par_entry[par_name]["value"]),
543
- format="ascii.ecsv",
544
- )
545
- return simtel_table_reader.read_simtel_table(
546
- par_name, self.config_file_directory.joinpath(_par_entry[par_name]["value"])
547
- )
548
-
549
465
  def export_config_file(self):
550
466
  """Export the config file used by sim_telarray."""
551
- # Exporting model file
552
467
  if not self._is_exported_model_files_up_to_date:
553
468
  self.export_model_files()
554
469
 
555
- # Using SimtelConfigWriter to write the config file.
556
470
  self._load_simtel_config_writer()
557
471
  self.simtel_config_writer.write_telescope_config_file(
558
472
  config_file_path=self.config_file_path,
559
- parameters=self.get_simtel_parameters(parameters=self._parameters),
560
- config_parameters=self.get_simtel_parameters(
561
- parameters=self._simulation_config_parameters["simtel"]
562
- ),
473
+ parameters=self.parameters,
474
+ config_parameters=self._simulation_config_parameters["simtel"],
563
475
  )
564
476
 
565
477
  @property
@@ -0,0 +1,328 @@
1
+ """Calculate CORSIKA thresholds for energy, radial distance, and viewcone."""
2
+
3
+ import logging
4
+
5
+ import astropy.units as u
6
+ import matplotlib.pyplot as plt
7
+ import numpy as np
8
+
9
+ from simtools.simtel.simtel_io_event_reader import SimtelIOEventDataReader
10
+
11
+
12
+ class LimitCalculator:
13
+ """
14
+ Compute thresholds for CORSIKA configuration for energy, radial distance, and viewcone.
15
+
16
+ Event data is read from the reduced MC event data file.
17
+
18
+ Parameters
19
+ ----------
20
+ event_data_file : str
21
+ Path to the HDF5 file containing the event data.
22
+ telescope_list : list, optional
23
+ List of telescope IDs to filter the events (default is None).
24
+ """
25
+
26
+ def __init__(self, event_data_file, telescope_list=None):
27
+ """Initialize the LimitCalculator with the given event data file."""
28
+ self._logger = logging.getLogger(__name__)
29
+ self.event_data_file = event_data_file
30
+ self.telescope_list = telescope_list
31
+
32
+ self.reader = SimtelIOEventDataReader(event_data_file, telescope_list=telescope_list)
33
+ self.event_data = self.reader.triggered_shower_data
34
+ self.triggered_data = self.reader.triggered_data
35
+
36
+ def _compute_limits(self, hist, bin_edges, loss_fraction, limit_type="lower"):
37
+ """
38
+ Compute the limits based on the loss fraction.
39
+
40
+ Parameters
41
+ ----------
42
+ hist : np.ndarray
43
+ 1D histogram array.
44
+ bin_edges : np.ndarray
45
+ Array of bin edges.
46
+ loss_fraction : float
47
+ Fraction of events to be lost.
48
+ limit_type : str, optional
49
+ Type of limit ('lower' or 'upper'). Default is 'lower'.
50
+
51
+ Returns
52
+ -------
53
+ float
54
+ Bin edge value corresponding to the threshold.
55
+ """
56
+ cumulative_sum = np.cumsum(hist) if limit_type == "upper" else np.cumsum(hist[::-1])
57
+ total_events = np.sum(hist)
58
+ threshold = (1 - loss_fraction) * total_events
59
+ bin_index = np.searchsorted(cumulative_sum, threshold)
60
+
61
+ return bin_edges[bin_index] if limit_type == "upper" else bin_edges[-bin_index]
62
+
63
+ @property
64
+ def energy_bins(self):
65
+ """Return bins for the energy histogram."""
66
+ return np.logspace(
67
+ np.log10(self.event_data.simulated_energy.min()),
68
+ np.log10(self.event_data.simulated_energy.max()),
69
+ 1000,
70
+ )
71
+
72
+ def compute_lower_energy_limit(self, loss_fraction):
73
+ """
74
+ Compute the lower energy limit in TeV based on the event loss fraction.
75
+
76
+ Parameters
77
+ ----------
78
+ loss_fraction : float
79
+ Fraction of events to be lost.
80
+
81
+ Returns
82
+ -------
83
+ astropy.units.Quantity
84
+ Lower energy limit.
85
+ """
86
+ hist, _ = np.histogram(self.event_data.simulated_energy, bins=self.energy_bins)
87
+ return (
88
+ self._compute_limits(hist, self.energy_bins, loss_fraction, limit_type="lower") * u.TeV
89
+ )
90
+
91
+ @property
92
+ def core_distance_bins(self):
93
+ """Return bins for the core distance histogram."""
94
+ return np.linspace(
95
+ self.event_data.core_distance_shower.min(),
96
+ self.event_data.core_distance_shower.max(),
97
+ 1000,
98
+ )
99
+
100
+ def compute_upper_radial_distance(self, loss_fraction):
101
+ """
102
+ Compute the upper radial distance based on the event loss fraction.
103
+
104
+ Parameters
105
+ ----------
106
+ loss_fraction : float
107
+ Fraction of events to be lost.
108
+
109
+ Returns
110
+ -------
111
+ astropy.units.Quantity
112
+ Upper radial distance in m.
113
+ """
114
+ hist, _ = np.histogram(self.event_data.core_distance_shower, bins=self.core_distance_bins)
115
+ return (
116
+ self._compute_limits(hist, self.core_distance_bins, loss_fraction, limit_type="upper")
117
+ * u.m
118
+ )
119
+
120
+ @property
121
+ def view_cone_bins(self):
122
+ """Return bins for the viewcone histogram."""
123
+ return np.linspace(
124
+ self.triggered_data.angular_distance.min(),
125
+ self.triggered_data.angular_distance.max(),
126
+ 1000,
127
+ )
128
+
129
+ def compute_viewcone(self, loss_fraction):
130
+ """
131
+ Compute the viewcone based on the event loss fraction.
132
+
133
+ The shower IDs of triggered events are used to create a mask for the
134
+ azimuth and altitude of the triggered events. A mapping is created
135
+ between the triggered events and the simulated events using the shower IDs.
136
+
137
+ Parameters
138
+ ----------
139
+ loss_fraction : float
140
+ Fraction of events to be lost.
141
+
142
+ Returns
143
+ -------
144
+ astropy.units.Quantity
145
+ Viewcone radius in degrees.
146
+ """
147
+ hist, _ = np.histogram(self.triggered_data.angular_distance, bins=self.view_cone_bins)
148
+ return (
149
+ self._compute_limits(hist, self.view_cone_bins, loss_fraction, limit_type="upper")
150
+ * u.deg
151
+ )
152
+
153
+ def plot_data(self, lower_energy_limit, upper_radial_distance, viewcone, output_path=None):
154
+ """
155
+ Plot the core distances and energies of triggered events.
156
+
157
+ Parameters
158
+ ----------
159
+ lower_energy_limit: astropy.units.Quantity
160
+ Lower energy limit to display on plots.
161
+ upper_radial_distance: astropy.units.Quantity
162
+ Upper radial distance limit to display on plots.
163
+ viewcone: astropy.units.Quantity
164
+ Viewcone radius to display on plots.
165
+ output_path: Path or str, optional
166
+ Directory to save plots. If None, plots will be displayed.
167
+ """
168
+ event_counts = "Event Count"
169
+ plots = {
170
+ "core_vs_energy": {
171
+ "x_data": self.event_data.core_distance_shower,
172
+ "y_data": self.event_data.simulated_energy,
173
+ "bins": [self.core_distance_bins, self.energy_bins],
174
+ "plot_type": "histogram2d",
175
+ "plot_params": {"norm": "log", "cmap": "viridis"},
176
+ "labels": {
177
+ "x": "Core Distance [m]",
178
+ "y": "Energy [TeV]",
179
+ "title": "Triggered events: core distance vs energy",
180
+ },
181
+ "scales": {"y": "log"},
182
+ "colorbar_label": event_counts,
183
+ "filename": "core_vs_energy_distribution.png",
184
+ },
185
+ "energy_distribution": {
186
+ "x_data": self.event_data.simulated_energy,
187
+ "bins": np.logspace(-3, 0.0, 100),
188
+ "plot_type": "histogram",
189
+ "plot_params": {"histtype": "step", "color": "k", "lw": 2},
190
+ "labels": {
191
+ "x": "Energy [TeV]",
192
+ "y": event_counts,
193
+ "title": "Triggered events: energy distribution",
194
+ },
195
+ "scales": {"x": "log", "y": "log"},
196
+ "lines": {"x": lower_energy_limit.value},
197
+ "filename": "energy_distribution.png",
198
+ },
199
+ "core_distance": {
200
+ "x_data": self.event_data.core_distance_shower,
201
+ "bins": self.core_distance_bins,
202
+ "plot_type": "histogram",
203
+ "plot_params": {"histtype": "step", "color": "k", "lw": 2},
204
+ "labels": {
205
+ "x": "Core Distance [m]",
206
+ "y": event_counts,
207
+ "title": "Triggered events: core distance distribution",
208
+ },
209
+ "lines": {"x": upper_radial_distance.value},
210
+ "filename": "core_distance_distribution.png",
211
+ },
212
+ "core_xy": {
213
+ "x_data": self.event_data.x_core_shower,
214
+ "y_data": self.event_data.y_core_shower,
215
+ "bins": 100,
216
+ "plot_type": "histogram2d",
217
+ "plot_params": {"norm": "log", "cmap": "viridis"},
218
+ "labels": {
219
+ "x": "Core X [m]",
220
+ "y": "Core Y [m]",
221
+ "title": "Triggered events: core x vs core y",
222
+ },
223
+ "colorbar_label": event_counts,
224
+ "lines": {"x": upper_radial_distance.value, "y": upper_radial_distance.value},
225
+ "filename": "core_xy_distribution.png",
226
+ },
227
+ "view-cone": {
228
+ "x_data": self.triggered_data.angular_distance,
229
+ "bins": self.view_cone_bins,
230
+ "plot_type": "histogram",
231
+ "plot_params": {"histtype": "step", "color": "k", "lw": 2},
232
+ "labels": {
233
+ "x": "Distance to pointing direction [deg]",
234
+ "y": event_counts,
235
+ "title": "Triggered events: viewcone distribution",
236
+ },
237
+ "lines": {"x": viewcone.value},
238
+ "filename": "viewcone_distribution.png",
239
+ },
240
+ }
241
+
242
+ for _, plot_args in plots.items():
243
+ filename = plot_args.pop("filename")
244
+ output_file = output_path / filename if output_path else None
245
+ self._create_plot(**plot_args, output_file=output_file)
246
+
247
+ def _create_plot(
248
+ self,
249
+ x_data,
250
+ y_data=None,
251
+ bins=None,
252
+ plot_type="histogram",
253
+ plot_params=None,
254
+ labels=None,
255
+ scales=None,
256
+ colorbar_label=None,
257
+ output_file=None,
258
+ lines=None,
259
+ ):
260
+ """
261
+ Create and save a plot with the given parameters.
262
+
263
+ Parameters
264
+ ----------
265
+ x_data : array-like
266
+ Data for the x-axis or primary data for histograms.
267
+ y_data : array-like, optional
268
+ Data for the y-axis in scatter or 2D histograms.
269
+ bins : int, array-like, or list, optional
270
+ Bins specification for histograms.
271
+ plot_type : str, optional
272
+ Type of plot: 'histogram', 'histogram2d', or 'scatter'.
273
+ plot_params : dict, optional
274
+ Additional parameters to pass to the plotting function.
275
+ labels : dict, optional
276
+ Dictionary containing 'x', 'y', and 'title' labels.
277
+ scales : dict, optional
278
+ Dictionary containing 'x' and 'y' scale types ('log' or 'linear').
279
+ colorbar_label : str, optional
280
+ Label for the colorbar in 2D histograms.
281
+ output_file : Path, optional
282
+ File path to save the plot. If not provided, the plot will be displayed.
283
+ lines : dict, optional
284
+ Dictionary containing 'x' and 'y' values for reference lines.
285
+
286
+ Returns
287
+ -------
288
+ matplotlib.figure.Figure
289
+ The created figure object.
290
+ """
291
+ fig = plt.figure(figsize=(8, 6))
292
+ plot_params = plot_params or {}
293
+ labels = labels or {}
294
+ scales = scales or {}
295
+ lines = lines or {}
296
+
297
+ if plot_type == "histogram":
298
+ plt.hist(x_data, bins=bins, **plot_params)
299
+ elif plot_type == "histogram2d":
300
+ plt.hist2d(x_data, y_data, bins=bins, **plot_params)
301
+ if colorbar_label:
302
+ plt.colorbar(label=colorbar_label)
303
+ elif plot_type == "scatter":
304
+ plt.scatter(x_data, y_data, **plot_params)
305
+
306
+ if "x" in lines:
307
+ plt.axvline(lines["x"], color="r", linestyle="--")
308
+ if "y" in lines:
309
+ plt.axhline(lines["y"], color="r", linestyle="--")
310
+
311
+ plt.xlabel(labels.get("x", ""))
312
+ plt.ylabel(labels.get("y", ""))
313
+ plt.title(labels.get("title", ""))
314
+
315
+ if "x" in scales:
316
+ plt.xscale(scales["x"])
317
+ if "y" in scales:
318
+ plt.yscale(scales["y"])
319
+
320
+ if output_file:
321
+ self._logger.info(f"Saving plot to {output_file}")
322
+ plt.savefig(output_file, dpi=300, bbox_inches="tight")
323
+ plt.close()
324
+ else:
325
+ plt.tight_layout()
326
+ plt.show()
327
+
328
+ return fig
@@ -68,9 +68,9 @@ class EventScaler:
68
68
  The scaling factor.
69
69
  """
70
70
  metric_results = self.evaluator.calculate_metrics()
71
- uncertainty_effective_area = metric_results.get("uncertainty_effective_area", {})
71
+ uncertainty_effective_area = metric_results.get("uncertainty_effective_area")
72
72
  current_max_error = uncertainty_effective_area.get("max_error")
73
- target_max_error = self.metrics.get("uncertainty_effective_area", {}).get("target_error")[
73
+ target_max_error = self.metrics.get("uncertainty_effective_area").get("target_error")[
74
74
  "value"
75
75
  ]
76
76
 
@@ -295,6 +295,6 @@ class MirrorPanelPSF:
295
295
  )
296
296
  writer.ModelDataWriter.dump(
297
297
  args_dict=self.args_dict,
298
- metadata=MetadataCollector(args_dict=self.args_dict).get_top_level_metadata(),
298
+ metadata=MetadataCollector(args_dict=self.args_dict),
299
299
  product_data=result_table,
300
300
  )