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
@@ -1,205 +1,303 @@
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
- """
1
+ """Read reduced datasets in form of astropy tables from file."""
14
2
 
15
3
  import logging
4
+ from dataclasses import dataclass, field
16
5
 
17
6
  import astropy.units as u
18
7
  import numpy as np
19
- import tables
20
8
  from astropy.coordinates import AltAz, angular_separation
21
9
  from ctapipe.coordinates import GroundFrame, TiltedGroundFrame
22
10
 
23
- from simtools.simtel.simtel_io_event_writer import ShowerEventData, TriggeredEventData
11
+ from simtools.corsika.primary_particle import PrimaryParticle
12
+ from simtools.io_operations import io_table_handler
24
13
 
25
14
 
26
- class SimtelIOEventDataReader:
27
- """
28
- Read reduced MC data set from file.
15
+ @dataclass
16
+ class ShowerEventData:
17
+ """Container for shower event data."""
29
18
 
30
- Calculate some standard derivation like core position in shower coordinates.
19
+ shower_id: list[np.uint32] = field(default_factory=list)
20
+ event_id: list[np.uint32] = field(default_factory=list)
21
+ file_id: list[np.uint32] = field(default_factory=list)
22
+ simulated_energy: list[np.float64] = field(default_factory=list)
23
+ x_core: list[np.float64] = field(default_factory=list)
24
+ y_core: list[np.float64] = field(default_factory=list)
25
+ shower_azimuth: list[np.float64] = field(default_factory=list)
26
+ shower_altitude: list[np.float64] = field(default_factory=list)
27
+ area_weight: list[np.float64] = field(default_factory=list)
28
+ x_core_shower: list[np.float64] = field(default_factory=list)
29
+ y_core_shower: list[np.float64] = field(default_factory=list)
30
+ core_distance_shower: list[np.float64] = field(default_factory=list)
31
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
- """
32
+
33
+ @dataclass
34
+ class TriggeredEventData:
35
+ """Container for triggered event data."""
36
+
37
+ shower_id: list[np.uint32] = field(default_factory=list)
38
+ event_id: list[np.uint32] = field(default_factory=list)
39
+ file_id: list[np.uint32] = field(default_factory=list)
40
+ array_altitude: list[float] = field(default_factory=list)
41
+ array_azimuth: list[float] = field(default_factory=list)
42
+ telescope_list: list[np.ndarray] = field(default_factory=list)
43
+ angular_distance: list[float] = field(default_factory=list)
44
+
45
+
46
+ class SimtelIOEventDataReader:
47
+ """Read reduced MC data set stored in astropy tables."""
39
48
 
40
49
  def __init__(self, event_data_file, telescope_list=None):
41
- """Initialize SimtelIOEventDataReader with the given event data file."""
50
+ """Initialize SimtelIOEventDataReader."""
42
51
  self._logger = logging.getLogger(__name__)
43
52
  self.telescope_list = telescope_list
44
53
 
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()
54
+ self.data_sets = self.read_table_list(event_data_file)
49
55
 
50
- def read_event_data(self, event_data_file):
56
+ def read_table_list(self, event_data_file):
51
57
  """
52
- Read event data from the reduced MC event data file.
58
+ Read available tables from the event data file.
59
+
60
+ Rearrange dictionary with tables names into a list of dictionaries
61
+ under the assumption that the file contains the tables "SHOWERS",
62
+ "TRIGGERS", and "FILE_INFO".
53
63
 
54
64
  Parameters
55
65
  ----------
56
- event_data_file : str, Path
57
- Path to the HDF5 file containing the event data.
66
+ event_data_file : str
67
+ Path to the event data file.
58
68
 
59
69
  Returns
60
70
  -------
61
- ShowerEventData, TriggeredEventData
62
- Event data and triggered event data.
71
+ list
72
+ List of dictionaries containing the data from the tables.
63
73
  """
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
74
+ dataset_dict = io_table_handler.read_table_list(
75
+ event_data_file,
76
+ ["SHOWERS", "TRIGGERS", "FILE_INFO"],
77
+ include_indexed_tables=True,
99
78
  )
100
- return event_data, triggered_shower, triggered_data
101
79
 
102
- def _reduce_to_triggered_events(self, event_data, triggered_data):
80
+ data_sets = []
81
+ for i in range(len(dataset_dict["SHOWERS"])):
82
+ data_sets.append(
83
+ {
84
+ "SHOWERS": dataset_dict["SHOWERS"][i],
85
+ "TRIGGERS": dataset_dict["TRIGGERS"][i],
86
+ "FILE_INFO": dataset_dict["FILE_INFO"][i],
87
+ }
88
+ )
89
+
90
+ return data_sets
91
+
92
+ def _table_to_shower_data(self, table):
103
93
  """
104
- Reduce event data to triggered events only. Apply filter on telescope list if specified.
94
+ Convert tables with shower event data and add derived quantities.
105
95
 
106
96
  Parameters
107
97
  ----------
108
- event_data : ShowerEventData
109
- Event data.
110
- triggered_data : TriggeredEventData
111
- Triggered event data.
98
+ table : astropy.table.Table
99
+ Table "SHOWERS"
112
100
 
113
101
  Returns
114
102
  -------
115
- ShowerEventData, TriggeredEventData
116
- Filtered event data and triggered event data
103
+ ShowerEventData
104
+ An instance of ShowerEventData with the data from the table.
117
105
  """
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,
106
+ shower_data = ShowerEventData()
107
+
108
+ for col in table.colnames:
109
+ setattr(shower_data, col, np.array(table[col].data))
110
+ if table[col].unit:
111
+ setattr(shower_data, f"{col}_unit", table[col].unit)
112
+
113
+ shower_data.x_core_shower, shower_data.y_core_shower = (
114
+ self._transform_to_shower_coordinates(
115
+ shower_data.x_core,
116
+ shower_data.y_core,
117
+ shower_data.shower_azimuth,
118
+ shower_data.shower_altitude,
119
+ )
122
120
  )
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],
121
+ shower_data.core_distance_shower = np.sqrt(
122
+ shower_data.x_core_shower**2 + shower_data.y_core_shower**2
129
123
  )
130
124
 
131
- filtered_telescope_list = [
132
- triggered_data.trigger_telescope_list_list[i] for i in triggered_indices
133
- ]
125
+ return shower_data
134
126
 
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
127
+ def _table_to_triggered_data(self, table):
128
+ """
129
+ Convert table with triggered event data.
130
+
131
+ Converts telescope lists from comma-separated string to numpy array.
132
+
133
+ Parameters
134
+ ----------
135
+ table : astropy.table.Table
136
+ Table "TRIGGERS"
144
137
 
145
- def _get_mask_triggered_telescopes(
146
- self, telescope_list, triggered_id, trigger_telescope_list_list
138
+ Returns
139
+ -------
140
+ TriggeredEventData
141
+ An instance of TriggeredEventData with the data from the table.
142
+ """
143
+ triggered_data = TriggeredEventData()
144
+ for col in table.colnames:
145
+ if col == "telescope_list":
146
+ arrays = [
147
+ np.array(list(map(int, tel_list.split(","))), dtype=np.int16)
148
+ for tel_list in table[col]
149
+ ]
150
+ triggered_data.telescope_list = arrays
151
+ else:
152
+ data = np.array(table[col].data)
153
+ setattr(triggered_data, col, data)
154
+ if table[col].unit:
155
+ setattr(triggered_data, f"{col}_unit", table[col].unit)
156
+ return triggered_data
157
+
158
+ def _get_triggered_shower_data(
159
+ self, shower_data, triggered_file_id, triggered_event_id, triggered_shower_id
147
160
  ):
148
161
  """
149
- Return indices of events that triggered the specified telescopes.
162
+ Get shower data corresponding to triggered events.
163
+
164
+ Matches triggered events with showers based on shower_id, event_id, and file_id.
150
165
 
151
166
  Parameters
152
167
  ----------
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.
168
+ shower_data : ShowerEventData
169
+ The shower data containing all showers.
170
+ triggered_file_id : list
171
+ List of file IDs for triggered events.
172
+ triggered_event_id : list
173
+ List of event IDs for triggered events.
174
+ triggered_shower_id : list
175
+ List of shower IDs for triggered events.
159
176
 
160
177
  Returns
161
178
  -------
162
- tuple
163
- Filtered triggered IDs and indices.
179
+ ShowerEventData
180
+ An instance of ShowerEventData containing only the triggered showers.
181
+
164
182
  """
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
- ]
183
+ triggered_shower = ShowerEventData()
184
+
185
+ matched_indices = []
186
+ for tr_shower_id, tr_event_id, tr_file_id in zip(
187
+ triggered_shower_id, triggered_event_id, triggered_file_id
188
+ ):
189
+ mask = (
190
+ (shower_data.shower_id == tr_shower_id)
191
+ & (shower_data.event_id == tr_event_id)
192
+ & (shower_data.file_id == tr_file_id)
172
193
  )
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,
194
+ matched_idx = np.where(mask)[0]
195
+ if len(matched_idx) == 1:
196
+ matched_indices.append(matched_idx[0])
197
+ else:
198
+ self._logger.warning(
199
+ f"Found {len(matched_idx)} matches for shower {tr_shower_id}"
200
+ f" event {tr_event_id} file {tr_file_id}"
186
201
  )
187
- )
188
- event_data.core_distance_shower = np.sqrt(
189
- event_data.x_core_shower**2 + event_data.y_core_shower**2
190
- )
191
202
 
192
- self.triggered_data.angular_distance = (
203
+ for attr in vars(shower_data):
204
+ if not attr.endswith("_unit"):
205
+ value = getattr(shower_data, attr)
206
+ if isinstance(value, list | np.ndarray):
207
+ setattr(triggered_shower, attr, np.array(value)[matched_indices])
208
+
209
+ return triggered_shower
210
+
211
+ def read_event_data(self, event_data_file, table_name_map=None):
212
+ """
213
+ Read event data and file info tables from file and apply transformations.
214
+
215
+ Allows to map tables names to their actual names in the file
216
+ (e.g., "SHOWER" to "SHOWER_1").
217
+
218
+ Parameters
219
+ ----------
220
+ event_data_file : str
221
+ Path to the event data file.
222
+ table_name_map : dict, optional
223
+ Mapping of table names to their actual names in the file.
224
+ Defaults to using the standard names "SHOWERS", "TRIGGERS", and "FILE_INFO".
225
+
226
+ Returns
227
+ -------
228
+ tuple
229
+ A tuple with file info table, shower, triggered shower, and triggered event data.
230
+ """
231
+ table_name_map = table_name_map or {}
232
+
233
+ def get_name(key):
234
+ return table_name_map.get(key, key)
235
+
236
+ tables = io_table_handler.read_tables(
237
+ event_data_file,
238
+ table_names=[get_name(k) for k in ("SHOWERS", "TRIGGERS", "FILE_INFO")],
239
+ )
240
+
241
+ shower_data = self._table_to_shower_data(tables[get_name("SHOWERS")])
242
+ triggered_data = self._table_to_triggered_data(tables[get_name("TRIGGERS")])
243
+ triggered_shower = self._get_triggered_shower_data(
244
+ shower_data,
245
+ tables[get_name("TRIGGERS")]["file_id"],
246
+ tables[get_name("TRIGGERS")]["event_id"],
247
+ tables[get_name("TRIGGERS")]["shower_id"],
248
+ )
249
+
250
+ triggered_data.angular_distance = (
193
251
  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,
252
+ triggered_shower.shower_azimuth * u.rad,
253
+ triggered_shower.shower_altitude * u.rad,
254
+ triggered_data.array_azimuth * u.rad,
255
+ triggered_data.array_altitude * u.rad,
256
+ )
257
+ .to(u.deg)
258
+ .value
259
+ )
260
+
261
+ if self.telescope_list:
262
+ triggered_data, triggered_shower = self._filter_by_telescopes(
263
+ triggered_data, triggered_shower
198
264
  )
199
- * 180
200
- / np.pi
265
+
266
+ self._logger.info(f"Number of triggered events: {len(triggered_data.array_altitude)}")
267
+
268
+ return (
269
+ tables[get_name("FILE_INFO")],
270
+ shower_data,
271
+ triggered_shower,
272
+ triggered_data,
201
273
  )
202
274
 
275
+ def _filter_by_telescopes(self, triggered_data, triggered_shower):
276
+ """Filter trigger data and triggered shower data by the specified telescope list."""
277
+ mask = np.array(
278
+ [
279
+ any(tel in event for tel in self.telescope_list)
280
+ for event in triggered_data.telescope_list
281
+ ]
282
+ )
283
+ filtered_triggered_data = TriggeredEventData(
284
+ shower_id=triggered_data.shower_id[mask],
285
+ event_id=triggered_data.event_id[mask],
286
+ file_id=triggered_data.file_id[mask],
287
+ array_altitude=triggered_data.array_altitude[mask],
288
+ array_azimuth=triggered_data.array_azimuth[mask],
289
+ telescope_list=[triggered_data.telescope_list[i] for i in np.arange(len(mask))[mask]],
290
+ angular_distance=triggered_data.angular_distance[mask],
291
+ )
292
+ filtered_triggered_shower_data = self._get_triggered_shower_data(
293
+ triggered_shower,
294
+ filtered_triggered_data.file_id,
295
+ filtered_triggered_data.event_id,
296
+ filtered_triggered_data.shower_id,
297
+ )
298
+
299
+ return filtered_triggered_data, filtered_triggered_shower_data
300
+
203
301
  def _transform_to_shower_coordinates(self, x_core, y_core, shower_azimuth, shower_altitude):
204
302
  """
205
303
  Transform core positions from ground coordinates to shower coordinates.
@@ -220,59 +318,68 @@ class SimtelIOEventDataReader:
220
318
  tuple
221
319
  Core positions in shower coordinates (x, y).
222
320
  """
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
-
321
+ ground = GroundFrame(x=x_core * u.m, y=y_core * u.m, z=np.zeros_like(x_core) * u.m)
322
+ shower_frame = ground.transform_to(
323
+ TiltedGroundFrame(
324
+ pointing_direction=AltAz(az=shower_azimuth * u.rad, alt=shower_altitude * u.rad)
325
+ )
326
+ )
227
327
  return shower_frame.x.value, shower_frame.y.value
228
328
 
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("")
329
+ def get_reduced_simulation_file_info(self, simulation_file_info):
330
+ """
331
+ Return reduced simulation file info assuming single-valued parameters.
253
332
 
254
- def print_event_table(self, lines_per_page=20):
255
- """Print event table with pagination.
333
+ Applies rounding and uniqueness functions extract representative values
334
+ for zenith, azimuth, and NSB level. Assumes all files share identical
335
+ simulation parameters except for file names. Returns particle name instead
336
+ of ID.
337
+
338
+ Logs a warning if multiple unique values are found.
256
339
 
257
340
  Parameters
258
341
  ----------
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
- )
342
+ simulation_file_info : astropy.table.Table
343
+ Dictionary containing simulation file info.
266
344
 
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("")
345
+ Returns
346
+ -------
347
+ dict
348
+ Dictionary containing the reduced simulation file info.
349
+ """
350
+ particle_id = np.unique(simulation_file_info["particle_id"].data)
351
+ keys = [
352
+ "zenith",
353
+ "azimuth",
354
+ "nsb_level",
355
+ "energy_min",
356
+ "energy_max",
357
+ "viewcone_min",
358
+ "viewcone_max",
359
+ "core_scatter_min",
360
+ "core_scatter_max",
361
+ ]
362
+ float_arrays = {}
363
+ for key in keys:
364
+ if key == "energy_min":
365
+ float_arrays[key] = np.unique(np.round(simulation_file_info[key].data, decimals=3))
366
+ else:
367
+ float_arrays[key] = np.unique(np.round(simulation_file_info[key].data, decimals=2))
368
+
369
+ if any(len(arr) > 1 for arr in (particle_id, *(float_arrays[key] for key in keys))):
370
+ self._logger.warning("Simulation file info has non-unique values.")
371
+
372
+ reduced_info = {
373
+ "primary_particle": PrimaryParticle(
374
+ particle_id_type="corsika7_id",
375
+ particle_id=int(particle_id[0]),
376
+ ).name,
377
+ }
378
+
379
+ for key in keys:
380
+ value = float(float_arrays[key][0])
381
+ if simulation_file_info[key].unit is not None:
382
+ value = value * simulation_file_info[key].unit
383
+ reduced_info[key] = value
384
+
385
+ return reduced_info