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
@@ -4,13 +4,38 @@
4
4
  import logging
5
5
  import re
6
6
 
7
+ import astropy.units as u
7
8
  import numpy as np
8
9
 
9
10
  import simtools.utils.general as gen
11
+ from simtools.utils import names
10
12
 
11
13
  __all__ = ["SimtelConfigReader"]
12
14
 
13
15
 
16
+ def get_list_of_simtel_parameters(simtel_config_file):
17
+ """
18
+ Return list of simtel parameters found in simtel configuration file.
19
+
20
+ Parameters
21
+ ----------
22
+ simtel_config_file: str
23
+ File name for sim_telarray configuration
24
+
25
+ Returns
26
+ -------
27
+ list
28
+ List of parameters found in simtel configuration file.
29
+
30
+ """
31
+ simtel_parameter_set = set()
32
+ with open(simtel_config_file, encoding="utf-8") as file:
33
+ for line in file:
34
+ parts_of_lines = re.split(r",\s*|\s+", line.strip())
35
+ simtel_parameter_set.add(parts_of_lines[1].lower())
36
+ return sorted(simtel_parameter_set)
37
+
38
+
14
39
  class SimtelConfigReader:
15
40
  """
16
41
  Reads model parameters from configuration files and converts to the simtools representation.
@@ -26,7 +51,7 @@ class SimtelConfigReader:
26
51
  -C limits=no-internal -C initlist=no-internal -C list=no-internal\
27
52
  -C typelist=no-internal -C maximum_telescopes=30\
28
53
  -DNSB_AUTOSCALE -DNECTARCAM -DHYPER_LAYOUT\
29
- -DNUM_TELESCOPES=30 /dev/null 2>|/dev/null | grep '(@cfg)'
54
+ -DNUM_TELESCOPES=30 /dev/null 2>|/dev/null | grep '(@cfg)' | sed 's/^(@cfg)
30
55
 
31
56
  Parameters
32
57
  ----------
@@ -61,7 +86,12 @@ class SimtelConfigReader:
61
86
  else None
62
87
  )
63
88
  self.parameter_name = self.schema_dict.get("name") if self.schema_dict else parameter_name
64
- self.simtel_parameter_name = self._get_simtel_parameter_name(self.parameter_name)
89
+ try:
90
+ self.simtel_parameter_name = names.get_simulation_software_name_from_parameter_name(
91
+ self.parameter_name
92
+ ).upper()
93
+ except (KeyError, AttributeError):
94
+ self.simtel_parameter_name = self.parameter_name.upper()
65
95
  self.simtel_telescope_name = simtel_telescope_name
66
96
  self.camera_pixels = camera_pixels
67
97
  self.parameter_dict = self.read_simtel_config_file(
@@ -73,7 +103,7 @@ class SimtelConfigReader:
73
103
  return data_type == "limits" and self.parameter_dict.get("type") == "bool"
74
104
 
75
105
  def _get_schema_values(self, data_type):
76
- """Check schema values for limits and defaults."""
106
+ """Check schema values for limits, unit, and default."""
77
107
  try:
78
108
  if data_type == "limits":
79
109
  _from_schema = [
@@ -82,14 +112,25 @@ class SimtelConfigReader:
82
112
  ]
83
113
  return _from_schema[0] if _from_schema[1] is None else _from_schema
84
114
  if len(self.schema_dict["data"]) == 1:
85
- return self.schema_dict["data"][0]["default"]
86
- return [data.get("default") for data in self.schema_dict["data"]]
115
+ return self.schema_dict["data"][0].get(data_type)
116
+ return [data.get(data_type) for data in self.schema_dict["data"]]
87
117
  except (KeyError, IndexError):
88
118
  return None
89
119
 
90
120
  @staticmethod
91
121
  def _values_match(_from_simtel, _from_schema):
92
- """Check if values match (are close for floats)."""
122
+ """
123
+ Check if values match (are close for floats).
124
+
125
+ Convert where necessary astropy.Quantity to float.
126
+
127
+ """
128
+ if isinstance(_from_simtel, u.Quantity):
129
+ _from_simtel = _from_simtel.value
130
+ if isinstance(_from_simtel, np.ndarray) and len(_from_simtel) > 0:
131
+ _from_simtel = np.array(
132
+ [v.value if isinstance(v, u.Quantity) else v for v in _from_simtel]
133
+ )
93
134
  try:
94
135
  if not isinstance(_from_schema, list | np.ndarray) and _from_simtel == _from_schema:
95
136
  return True
@@ -184,6 +225,7 @@ class SimtelConfigReader:
184
225
  dtype=_para_dict.get("type"),
185
226
  n_dim=_para_dict.get("dimension"),
186
227
  default=_para_dict.get("default"),
228
+ is_limit=(key == "limits"),
187
229
  )
188
230
  except KeyError:
189
231
  pass
@@ -232,7 +274,7 @@ class SimtelConfigReader:
232
274
 
233
275
  return column, except_from_all
234
276
 
235
- def _add_value_from_simtel_cfg(self, column, dtype=None, n_dim=1, default=None):
277
+ def _add_value_from_simtel_cfg(self, column, dtype=None, n_dim=1, default=None, is_limit=False):
236
278
  """
237
279
  Extract value(s) from simtel configuration file columns.
238
280
 
@@ -276,7 +318,42 @@ class SimtelConfigReader:
276
318
  if dtype == "bool":
277
319
  column = np.array([bool(int(item)) for item in column])
278
320
 
279
- return self._process_column(column, dtype)
321
+ column, ndim = self._process_column(column, dtype)
322
+ if not is_limit:
323
+ column = self._add_units(column)
324
+ return column, ndim
325
+
326
+ def _add_units(self, column):
327
+ """
328
+ Add units as given in schema file to column.
329
+
330
+ Take into account array types and dimensionless units.
331
+ Ensure that integer values are returned as integers (astropy converts
332
+ values to floats when multiplying them with units).
333
+
334
+ """
335
+ try:
336
+ unit = self._get_schema_values("unit")
337
+ except TypeError: # no schema defined
338
+ return column
339
+ if unit is None or unit == "dimensionless":
340
+ return column
341
+
342
+ if isinstance(column, np.ndarray) and len(column) == len(unit):
343
+ return np.array(
344
+ [
345
+ col * u.Unit(un) if un != "dimensionless" else col
346
+ for col, un in zip(column, unit)
347
+ ],
348
+ dtype=object,
349
+ )
350
+ if isinstance(unit, str):
351
+ column_with_unit = column * u.Unit(unit)
352
+ if isinstance(column, int | np.integer):
353
+ return u.Quantity(int(column_with_unit.value), unit, dtype=type(column))
354
+ return column_with_unit
355
+
356
+ return None
280
357
 
281
358
  def _process_column(self, column, dtype):
282
359
  """
@@ -324,29 +401,3 @@ class SimtelConfigReader:
324
401
  if self.camera_pixels is not None and self.simtel_parameter_name in ["NIGHTSKY_BACKGROUND"]:
325
402
  return str(np.dtype(column[0].lower())), self.camera_pixels
326
403
  return str(np.dtype(column[0].lower())), int(column[1])
327
-
328
- def _get_simtel_parameter_name(self, parameter_name):
329
- """
330
- Return parameter name as used in sim_telarray.
331
-
332
- This is documented in the schema file.
333
-
334
- Parameters
335
- ----------
336
- parameter_name: str
337
- Model parameter name (as used in simtools)
338
-
339
- Returns
340
- -------
341
- str
342
- Parameter name as used in sim_telarray.
343
-
344
- """
345
- try:
346
- for sim_soft in self.schema_dict["simulation_software"]:
347
- if sim_soft["name"] == "sim_telarray":
348
- return sim_soft["internal_parameter_name"].upper()
349
- except (KeyError, TypeError):
350
- pass
351
-
352
- return parameter_name.upper()
@@ -76,16 +76,24 @@ class SimtelConfigWriter:
76
76
  )
77
77
  file.write("#endif\n\n")
78
78
 
79
- for _simtel_name, value in parameters.items():
79
+ for par, value in parameters.items():
80
+ _simtel_name = names.get_simulation_software_name_from_parameter_name(
81
+ par, simulation_software="sim_telarray"
82
+ )
80
83
  # array trigger is a site parameter, not a telescope parameter
81
84
  # fake_mirror_list is not a sim_telarray parameter (used for testeff only)
82
- if _simtel_name.startswith("array_trigger") or _simtel_name == "fake_mirror_list":
85
+ if (
86
+ not _simtel_name
87
+ or _simtel_name.startswith("array_trigger")
88
+ or _simtel_name == "fake_mirror_list"
89
+ ):
83
90
  continue
84
- if _simtel_name:
85
- file.write(f"{_simtel_name} = {self._get_value_string_for_simtel(value)}\n")
86
- _config_meta = self._get_simtel_metadata("telescope")
87
- for _simtel_name, value in _config_meta.items():
88
- file.write(f"{_simtel_name} = {value}\n")
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")
89
97
 
90
98
  def _get_value_string_for_simtel(self, value):
91
99
  """
@@ -108,7 +116,7 @@ class SimtelConfigWriter:
108
116
  value = gen.convert_list_to_string(value, shorten_list=True)
109
117
  return value
110
118
 
111
- def _get_simtel_metadata(self, config_type):
119
+ def _get_simtel_metadata(self, config_type, model_parameters):
112
120
  """
113
121
  Return simtel metadata.
114
122
 
@@ -116,35 +124,60 @@ class SimtelConfigWriter:
116
124
  ----------
117
125
  type: str
118
126
  Type of the configuration file (telescope, site)
127
+ model_parameters: dict
128
+ Model parameters dictionary.
119
129
 
120
130
  Returns
121
131
  -------
122
- dict
123
- Dictionary with simtel metadata.
132
+ list
133
+ List with simtel metadata.
124
134
 
125
135
  """
126
- parameters = {}
127
- parameters["config_release"] = (
128
- f"{self._model_version} written by simtools v{simtools.version.__version__}"
129
- )
130
- parameters["config_version"] = self._model_version
136
+ meta_parameters = [
137
+ f"config_release = {self._model_version} with simtools v{simtools.version.__version__}",
138
+ f"config_version = {self._model_version}",
139
+ ]
131
140
  if config_type == "telescope":
132
- parameters["camera_config_name"] = self._telescope_model_name
133
- parameters["camera_config_variant"] = ""
134
- parameters["camera_config_version"] = self._model_version
135
- parameters["optics_config_name"] = self._telescope_model_name
136
- parameters["optics_config_variant"] = ""
137
- parameters["optics_config_version"] = self._model_version
141
+ meta_parameters.extend(
142
+ [
143
+ f"camera_config_name = {self._telescope_model_name}",
144
+ "camera_config_variant = ",
145
+ f"camera_config_version = {self._model_version}",
146
+ f"optics_config_name = {self._telescope_model_name}",
147
+ "optics_config_variant = ",
148
+ f"optics_config_version = {self._model_version}",
149
+ ]
150
+ )
151
+ prefix = "metaparam telescope"
138
152
  elif config_type == "site":
139
- parameters["site_config_name"] = self._site
140
- parameters["site_config_variant"] = ""
141
- parameters["site_config_version"] = self._model_version
142
- parameters["array_config_name"] = self._layout_name
143
- parameters["array_config_variant"] = ""
144
- parameters["array_config_version"] = self._model_version
153
+ meta_parameters.extend(
154
+ [
155
+ f"site_config_name = {self._site}",
156
+ "site_config_variant = ",
157
+ f"site_config_version = {self._model_version}",
158
+ f"array_config_name = {self._layout_name}",
159
+ "array_config_variant = ",
160
+ f"array_config_version = {self._model_version}",
161
+ ]
162
+ )
163
+ prefix = "metaparam global"
145
164
  else:
146
165
  raise ValueError(f"Unknown metadata type {config_type}")
147
- return parameters
166
+
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']}")
179
+
180
+ return meta_parameters
148
181
 
149
182
  def write_array_config_file(self, config_file_path, telescope_model, site_model):
150
183
  """
@@ -177,7 +210,7 @@ class SimtelConfigWriter:
177
210
 
178
211
  # Writing site parameters
179
212
  self._write_site_parameters(
180
- file, site_model, Path(config_file_path).parent, telescope_model
213
+ file, site_model.parameters, Path(config_file_path).parent, telescope_model
181
214
  )
182
215
 
183
216
  # Maximum telescopes
@@ -276,7 +309,7 @@ class SimtelConfigWriter:
276
309
  header += f"{comment_char}\n"
277
310
  file.write(header)
278
311
 
279
- def _write_site_parameters(self, file, site_model, model_path, telescope_model):
312
+ def _write_site_parameters(self, file, site_parameters, model_path, telescope_model):
280
313
  """
281
314
  Write site parameters.
282
315
 
@@ -284,27 +317,26 @@ class SimtelConfigWriter:
284
317
  ----------
285
318
  file: file
286
319
  File to write on.
287
- site_model: SiteModel
288
- Site model.
320
+ site_parameters: site parameters
321
+ Site parameters.
289
322
  model_path: Path
290
323
  Path to the model for writing of additional files.
291
324
  telescope_model: dict of TelescopeModel
292
325
  Telescope models.
293
326
  """
294
327
  file.write(self.TAB + "% Site parameters\n")
295
- _site_parameters = site_model.get_simtel_parameters()
296
- for par, value in _site_parameters.items():
328
+ for par, value in site_parameters.items():
297
329
  _simtel_name = names.get_simulation_software_name_from_parameter_name(
298
330
  par, simulation_software="sim_telarray"
299
331
  )
300
332
  _simtel_name, value = self._convert_model_parameters_to_simtel_format(
301
- _simtel_name, value, model_path, telescope_model
333
+ _simtel_name, value["value"], model_path, telescope_model
302
334
  )
303
335
  if _simtel_name is not None:
304
336
  file.write(f"{self.TAB}{_simtel_name} = {value}\n")
305
- _simtel_meta = self._get_simtel_metadata("site")
306
- for _simtel_name, value in _simtel_meta.items():
307
- 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")
308
340
  file.write("\n")
309
341
 
310
342
  def _convert_model_parameters_to_simtel_format(
@@ -0,0 +1,278 @@
1
+ """
2
+ Read a reduced dataset from file.
3
+
4
+ Allow to filter the events based on the triggered telescopes.
5
+ Provide functionality to list events, e.g. through
6
+
7
+ .. code-block:: console
8
+
9
+ from simtools.simtel.simtel_io_event_reader import SimtelIOEventDataReader
10
+ reader = SimtelIOEventDataReader("gamma_diffuse_60deg.hdf5", [1,2,3,4])
11
+ reader.print_event_table()
12
+
13
+ """
14
+
15
+ import logging
16
+
17
+ import astropy.units as u
18
+ import numpy as np
19
+ import tables
20
+ from astropy.coordinates import AltAz, angular_separation
21
+ from ctapipe.coordinates import GroundFrame, TiltedGroundFrame
22
+
23
+ from simtools.simtel.simtel_io_event_writer import ShowerEventData, TriggeredEventData
24
+
25
+
26
+ class SimtelIOEventDataReader:
27
+ """
28
+ Read reduced MC data set from file.
29
+
30
+ Calculate some standard derivation like core position in shower coordinates.
31
+
32
+ Parameters
33
+ ----------
34
+ event_data_file : str
35
+ Path to the HDF5 file containing the event data.
36
+ telescope_list : list, optional
37
+ List of telescope IDs to filter the events (default is None).
38
+ """
39
+
40
+ def __init__(self, event_data_file, telescope_list=None):
41
+ """Initialize SimtelIOEventDataReader with the given event data file."""
42
+ self._logger = logging.getLogger(__name__)
43
+ self.telescope_list = telescope_list
44
+
45
+ self.shower_data, self.triggered_shower_data, self.triggered_data = self.read_event_data(
46
+ event_data_file
47
+ )
48
+ self._derived_event_data()
49
+
50
+ def read_event_data(self, event_data_file):
51
+ """
52
+ Read event data from the reduced MC event data file.
53
+
54
+ Parameters
55
+ ----------
56
+ event_data_file : str, Path
57
+ Path to the HDF5 file containing the event data.
58
+
59
+ Returns
60
+ -------
61
+ ShowerEventData, TriggeredEventData
62
+ Event data and triggered event data.
63
+ """
64
+ event_data = ShowerEventData()
65
+ triggered_event_data = TriggeredEventData()
66
+
67
+ with tables.open_file(event_data_file, mode="r") as f:
68
+ reduced_data = f.root.data.reduced_data
69
+ event_data.simulated_energy = reduced_data.col("simulated_energy")
70
+ event_data.x_core = reduced_data.col("x_core")
71
+ event_data.y_core = reduced_data.col("y_core")
72
+ event_data.shower_azimuth = reduced_data.col("shower_azimuth")
73
+ event_data.shower_altitude = reduced_data.col("shower_altitude")
74
+ event_data.shower_id = reduced_data.col("shower_id")
75
+ event_data.area_weight = reduced_data.col("area_weight")
76
+
77
+ triggered_data = f.root.data.triggered_data
78
+ triggered_event_data.triggered_id = triggered_data.col("triggered_id")
79
+ triggered_event_data.array_altitudes = triggered_data.col("array_altitudes")
80
+ triggered_event_data.array_azimuths = triggered_data.col("array_azimuths")
81
+
82
+ telescope_indices = triggered_data.col("telescope_list_index")
83
+ telescope_list_array = f.root.data.trigger_telescope_list_list
84
+
85
+ triggered_event_data.trigger_telescope_list_list = []
86
+ for index in telescope_indices:
87
+ if index < telescope_list_array.nrows:
88
+ triggered_event_data.trigger_telescope_list_list.append(
89
+ telescope_list_array[index]
90
+ )
91
+ else:
92
+ self._logger.warning(f"Invalid telescope list index: {index}")
93
+ triggered_event_data.trigger_telescope_list_list.append(
94
+ np.array([], dtype=np.int16)
95
+ )
96
+
97
+ triggered_shower, triggered_data = self._reduce_to_triggered_events(
98
+ event_data, triggered_event_data
99
+ )
100
+ return event_data, triggered_shower, triggered_data
101
+
102
+ def _reduce_to_triggered_events(self, event_data, triggered_data):
103
+ """
104
+ Reduce event data to triggered events only. Apply filter on telescope list if specified.
105
+
106
+ Parameters
107
+ ----------
108
+ event_data : ShowerEventData
109
+ Event data.
110
+ triggered_data : TriggeredEventData
111
+ Triggered event data.
112
+
113
+ Returns
114
+ -------
115
+ ShowerEventData, TriggeredEventData
116
+ Filtered event data and triggered event data
117
+ """
118
+ filtered_shower_ids, triggered_indices = self._get_mask_triggered_telescopes(
119
+ self.telescope_list,
120
+ triggered_data.triggered_id,
121
+ triggered_data.trigger_telescope_list_list,
122
+ )
123
+ filtered_event_data = ShowerEventData(
124
+ x_core=event_data.x_core[filtered_shower_ids],
125
+ y_core=event_data.y_core[filtered_shower_ids],
126
+ simulated_energy=event_data.simulated_energy[filtered_shower_ids],
127
+ shower_azimuth=event_data.shower_azimuth[filtered_shower_ids],
128
+ shower_altitude=event_data.shower_altitude[filtered_shower_ids],
129
+ )
130
+
131
+ filtered_telescope_list = [
132
+ triggered_data.trigger_telescope_list_list[i] for i in triggered_indices
133
+ ]
134
+
135
+ filtered_triggered_data = TriggeredEventData(
136
+ array_azimuths=triggered_data.array_azimuths[triggered_indices],
137
+ array_altitudes=triggered_data.array_altitudes[triggered_indices],
138
+ trigger_telescope_list_list=filtered_telescope_list,
139
+ )
140
+ self._logger.info(
141
+ f"Events reduced to triggered events: {len(filtered_event_data.simulated_energy)}"
142
+ )
143
+ return filtered_event_data, filtered_triggered_data
144
+
145
+ def _get_mask_triggered_telescopes(
146
+ self, telescope_list, triggered_id, trigger_telescope_list_list
147
+ ):
148
+ """
149
+ Return indices of events that triggered the specified telescopes.
150
+
151
+ Parameters
152
+ ----------
153
+ telescope_list : list
154
+ List of telescope IDs to filter the events
155
+ triggered_id : np.ndarray
156
+ Array of event IDs that triggered.
157
+ trigger_telescope_list_list : list
158
+ List of triggered telescopes for each event.
159
+
160
+ Returns
161
+ -------
162
+ tuple
163
+ Filtered triggered IDs and indices.
164
+ """
165
+ triggered_indices = np.arange(len(triggered_id))
166
+ if telescope_list:
167
+ mask = np.array(
168
+ [
169
+ any(tel in event for tel in telescope_list)
170
+ for event in trigger_telescope_list_list
171
+ ]
172
+ )
173
+ triggered_indices = triggered_indices[mask]
174
+ return triggered_id[mask], triggered_indices
175
+ return triggered_id, triggered_indices
176
+
177
+ def _derived_event_data(self):
178
+ """Calculate core positions in shower coordinates and angular distances."""
179
+ for event_data in (self.shower_data, self.triggered_shower_data):
180
+ event_data.x_core_shower, event_data.y_core_shower = (
181
+ self._transform_to_shower_coordinates(
182
+ event_data.x_core,
183
+ event_data.y_core,
184
+ event_data.shower_azimuth,
185
+ event_data.shower_altitude,
186
+ )
187
+ )
188
+ event_data.core_distance_shower = np.sqrt(
189
+ event_data.x_core_shower**2 + event_data.y_core_shower**2
190
+ )
191
+
192
+ self.triggered_data.angular_distance = (
193
+ angular_separation(
194
+ self.triggered_shower_data.shower_azimuth,
195
+ self.triggered_shower_data.shower_altitude,
196
+ self.triggered_data.array_azimuths,
197
+ self.triggered_data.array_altitudes,
198
+ )
199
+ * 180
200
+ / np.pi
201
+ )
202
+
203
+ def _transform_to_shower_coordinates(self, x_core, y_core, shower_azimuth, shower_altitude):
204
+ """
205
+ Transform core positions from ground coordinates to shower coordinates.
206
+
207
+ Parameters
208
+ ----------
209
+ x_core : np.ndarray
210
+ Core x positions in ground coordinates.
211
+ y_core : np.ndarray
212
+ Core y positions in ground coordinates.
213
+ shower_azimuth : np.ndarray
214
+ Shower azimuth angles.
215
+ shower_altitude : np.ndarray
216
+ Shower altitude angles.
217
+
218
+ Returns
219
+ -------
220
+ tuple
221
+ Core positions in shower coordinates (x, y).
222
+ """
223
+ pointing = AltAz(az=shower_azimuth * u.rad, alt=shower_altitude * u.rad)
224
+ ground = GroundFrame(x=x_core * u.m, y=y_core * u.m, z=0 * u.m)
225
+ shower_frame = ground.transform_to(TiltedGroundFrame(pointing_direction=pointing))
226
+
227
+ return shower_frame.x.value, shower_frame.y.value
228
+
229
+ def print_dataset_information(self, n_events=1):
230
+ """Print information about the datasets."""
231
+
232
+ def print_event_data(data, name):
233
+ """Print event data."""
234
+ print(f"{name}: {data[:n_events]}")
235
+
236
+ print_event_data(self.triggered_shower_data.simulated_energy, "Simulated energy (TeV)")
237
+ print_event_data(self.triggered_shower_data.x_core, "Core x (m)")
238
+ print_event_data(self.triggered_shower_data.y_core, "Core y (m)")
239
+ print_event_data(self.triggered_shower_data.shower_azimuth, "Shower azimuth (rad)")
240
+ print_event_data(self.triggered_shower_data.shower_altitude, "Shower altitude (rad)")
241
+ print_event_data(self.triggered_shower_data.x_core_shower, "Core x shower (m)")
242
+ print_event_data(self.triggered_shower_data.y_core_shower, "Core y shower (m)")
243
+ print_event_data(
244
+ self.triggered_shower_data.core_distance_shower, "Core distance shower (m)"
245
+ )
246
+ print_event_data(self.triggered_data.array_azimuths, "Array azimuth (rad)")
247
+ print_event_data(self.triggered_data.array_altitudes, "Array altitude (rad)")
248
+ print_event_data(self.triggered_data.trigger_telescope_list_list, "Triggered telescopes")
249
+ print_event_data(
250
+ self.triggered_data.angular_distance, "Angular distance to pointing direction (deg)"
251
+ )
252
+ print("")
253
+
254
+ def print_event_table(self, lines_per_page=20):
255
+ """Print event table with pagination.
256
+
257
+ Parameters
258
+ ----------
259
+ lines_per_page : int
260
+ Number of lines to display before pausing (default: 20)
261
+ """
262
+ print(
263
+ f"{'Counter':<10} {'Simulated Energy (TeV)':<20} {'Triggered Telescopes':<20} "
264
+ f"{'Core distance shower (m)':<20}"
265
+ )
266
+
267
+ for i, telescope_list in enumerate(self.triggered_data.trigger_telescope_list_list):
268
+ if i > 0 and i % lines_per_page == 0:
269
+ response = input("Press Enter to continue or 'q' to quit...")
270
+ if response.lower() == "q":
271
+ break
272
+
273
+ print(
274
+ f"{i:<10} {self.triggered_shower_data.simulated_energy[i]:<20.3f}"
275
+ f"{telescope_list} "
276
+ f"{self.triggered_shower_data.core_distance_shower[i]:<20.3f}"
277
+ )
278
+ print("")