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
@@ -6,46 +6,38 @@ import numpy as np
6
6
  from astropy import units as u
7
7
  from astropy.io import fits
8
8
 
9
- __all__ = ["StatisticalErrorEvaluator"]
9
+ __all__ = ["StatisticalUncertaintyEvaluator"]
10
10
 
11
11
 
12
- class StatisticalErrorEvaluator:
12
+ class StatisticalUncertaintyEvaluator:
13
13
  """
14
- Evaluates statistical uncertainties from a DL2 MC event file.
14
+ Evaluate statistical uncertainties for a metric at a point in the observational parameter grid.
15
15
 
16
16
  Parameters
17
17
  ----------
18
18
  file_path : str
19
19
  Path to the DL2 MC event file.
20
- file_type : str
21
- Type of the file, either 'point-like' or 'cone'.
22
- metrics : dict, optional
23
- Dictionary of metrics to evaluate. Default is None.
20
+ metrics : dict
21
+ Dictionary of metrics to evaluate.
24
22
  grid_point : tuple, optional
25
- Tuple specifying the grid point (energy, azimuth, zenith, NSB, offset).
23
+ Grid point (energy, azimuth, zenith, NSB, offset).
26
24
  """
27
25
 
28
26
  def __init__(
29
27
  self,
30
28
  file_path: str,
31
- file_type: str,
32
29
  metrics: dict[str, float],
33
30
  grid_point: tuple[float, float, float, float, float] | None = None,
34
31
  ):
35
32
  """Init the evaluator with a DL2 MC event file, its type, and metrics to calculate."""
36
33
  self._logger = logging.getLogger(__name__)
37
- self.file_type = file_type
38
34
  self.metrics = metrics
39
35
  self.grid_point = grid_point
40
36
 
41
37
  self.data = self.load_data_from_file(file_path)
38
+ self.energy_bin_edges = self.create_energy_bin_edges()
42
39
 
43
- self.uncertainty_effective_area = None
44
- self.energy_estimate = None
45
- self.sigma_energy = None
46
- self.delta_energy = None
47
-
48
- self.metric_results = None
40
+ self.metric_results = {}
49
41
  self.energy_threshold = None
50
42
 
51
43
  def _load_event_data(self, hdul, data_type):
@@ -80,21 +72,14 @@ class StatisticalErrorEvaluator:
80
72
  unique_azimuths = np.unique(events_data["PNT_AZ"]) * u.deg
81
73
  unique_zeniths = 90 * u.deg - np.unique(events_data["PNT_ALT"]) * u.deg
82
74
  if len(unique_azimuths) > 1 or len(unique_zeniths) > 1:
83
- msg = (
84
- f"Multiple values found for azimuth ({unique_azimuths}) zenith ({unique_zeniths})."
85
- )
75
+ msg = f"Multiple values found for azimuth ({unique_azimuths}) zenith ({unique_zeniths})"
86
76
  self._logger.error(msg)
87
77
  raise ValueError(msg)
88
- if self.grid_point is not None:
89
- self._logger.warning(
90
- f"Grid point already set to: {self.grid_point}. "
91
- "Overwriting with new values from file."
92
- )
93
78
  self.grid_point = (
94
79
  1 * u.TeV,
95
80
  unique_azimuths[0],
96
81
  unique_zeniths[0],
97
- 0,
82
+ 0, # NSB needs to be read and set here
98
83
  0 * u.deg,
99
84
  )
100
85
  self._logger.info(f"Grid point values: {self.grid_point}")
@@ -131,7 +116,7 @@ class StatisticalErrorEvaluator:
131
116
  raise FileNotFoundError(error_message) from e
132
117
  return data
133
118
 
134
- def create_bin_edges(self):
119
+ def create_energy_bin_edges(self):
135
120
  """
136
121
  Create unique energy bin edges.
137
122
 
@@ -168,7 +153,9 @@ class StatisticalErrorEvaluator:
168
153
  )
169
154
  return reconstructed_event_histogram * u.count
170
155
 
171
- def compute_efficiency_and_errors(self, reconstructed_event_counts, simulated_event_counts):
156
+ def compute_efficiency_and_uncertainties(
157
+ self, reconstructed_event_counts, simulated_event_counts
158
+ ):
172
159
  """
173
160
  Compute reconstructed event efficiency and its uncertainty assuming binomial distribution.
174
161
 
@@ -183,7 +170,7 @@ class StatisticalErrorEvaluator:
183
170
  -------
184
171
  efficiencies : array
185
172
  Array of calculated efficiencies.
186
- relative_errors : array
173
+ relative_uncertainties : array
187
174
  Array of relative uncertainties.
188
175
  """
189
176
  # Ensure the inputs have compatible units
@@ -224,15 +211,15 @@ class StatisticalErrorEvaluator:
224
211
  )
225
212
  )
226
213
 
227
- # Compute relative errors
228
- relative_errors = np.divide(
229
- uncertainties,
214
+ # Compute relative uncertainties
215
+ relative_uncertainties = np.divide(
216
+ uncertainties.value,
230
217
  np.sqrt(simulated_event_counts.value),
231
- out=np.zeros_like(uncertainties, dtype=float),
232
- where=uncertainties > 0,
218
+ out=np.zeros_like(uncertainties.value, dtype=float),
219
+ where=uncertainties.value > 0,
233
220
  )
234
221
 
235
- return efficiencies, relative_errors
222
+ return efficiencies, relative_uncertainties
236
223
 
237
224
  def calculate_energy_threshold(self, requested_eff_area_fraction=0.1):
238
225
  """
@@ -243,13 +230,12 @@ class StatisticalErrorEvaluator:
243
230
  float
244
231
  Energy threshold value.
245
232
  """
246
- bin_edges = self.create_bin_edges()
247
233
  reconstructed_event_histogram = self.compute_reconstructed_event_histogram(
248
- self.data["event_energies_mc"], bin_edges
234
+ self.data["event_energies_mc"], self.energy_bin_edges
249
235
  )
250
236
  simulated_event_histogram = self.data["simulated_event_histogram"]
251
237
 
252
- efficiencies, _ = self.compute_efficiency_and_errors(
238
+ efficiencies, _ = self.compute_efficiency_and_uncertainties(
253
239
  reconstructed_event_histogram, simulated_event_histogram
254
240
  )
255
241
 
@@ -261,7 +247,7 @@ class StatisticalErrorEvaluator:
261
247
  if threshold_index == 0 and efficiencies[0] < threshold_efficiency:
262
248
  return
263
249
 
264
- self.energy_threshold = bin_edges[threshold_index]
250
+ self.energy_threshold = self.energy_bin_edges[threshold_index]
265
251
 
266
252
  def calculate_uncertainty_effective_area(self):
267
253
  """
@@ -269,18 +255,42 @@ class StatisticalErrorEvaluator:
269
255
 
270
256
  Returns
271
257
  -------
272
- errors : dict
258
+ dict
273
259
  Dictionary with uncertainties for the file.
274
260
  """
275
- bin_edges = self.create_bin_edges()
276
261
  reconstructed_event_histogram = self.compute_reconstructed_event_histogram(
277
- self.data["event_energies_mc"], bin_edges
262
+ self.data["event_energies_mc"], self.energy_bin_edges
278
263
  )
279
264
  simulated_event_histogram = self.data["simulated_event_histogram"]
280
- _, relative_errors = self.compute_efficiency_and_errors(
265
+ _, relative_uncertainties = self.compute_efficiency_and_uncertainties(
281
266
  reconstructed_event_histogram, simulated_event_histogram
282
267
  )
283
- return {"relative_errors": relative_errors}
268
+ return {"relative_uncertainties": relative_uncertainties}
269
+
270
+ def calculate_max_error_for_effective_area(self):
271
+ """
272
+ Calculate the maximum relative uncertainty for effective area within the validity range.
273
+
274
+ Returns
275
+ -------
276
+ max_error : float
277
+ Maximum relative error.
278
+ """
279
+ energy_range = self.metrics.get("uncertainty_effective_area", {}).get("energy_range")
280
+
281
+ min_energy, max_energy = (
282
+ energy_range["value"][0] * u.Unit(energy_range["unit"]),
283
+ energy_range["value"][1] * u.Unit(energy_range["unit"]),
284
+ )
285
+ valid_uncertainties = [
286
+ error
287
+ for energy, error in zip(
288
+ self.data["bin_edges_low"],
289
+ self.metric_results["uncertainty_effective_area"]["relative_uncertainties"],
290
+ )
291
+ if min_energy <= energy <= max_energy
292
+ ]
293
+ return max(valid_uncertainties)
284
294
 
285
295
  def calculate_energy_estimate(self):
286
296
  """
@@ -291,7 +301,7 @@ class StatisticalErrorEvaluator:
291
301
  float
292
302
  The calculated uncertainty for energy estimation.
293
303
  """
294
- logging.info("Calculating Energy Resolution Error")
304
+ logging.info("Calculating Energy Resolution Uncertainty")
295
305
 
296
306
  event_energies_reco = self.data["event_energies_reco"]
297
307
  event_energies_mc = self.data["event_energies_mc"]
@@ -304,87 +314,59 @@ class StatisticalErrorEvaluator:
304
314
 
305
315
  energy_deviation = (event_energies_reco - event_energies_mc) / event_energies_mc
306
316
 
307
- bin_edges = self.create_bin_edges()
308
- bin_indices = np.digitize(event_energies_reco, bin_edges) - 1
317
+ bin_indices = np.digitize(event_energies_reco, self.energy_bin_edges) - 1
309
318
 
310
319
  energy_deviation_by_bin = [
311
- energy_deviation[bin_indices == i] for i in range(len(bin_edges) - 1)
320
+ energy_deviation[bin_indices == i] for i in range(len(self.energy_bin_edges) - 1)
312
321
  ]
313
322
 
314
323
  # Calculate sigma for each bin
315
- sigma_energy = [np.std(d) if len(d) > 0 else np.nan for d in energy_deviation_by_bin]
324
+ sigma_energy = [np.std(d.value) if len(d) > 0 else np.nan for d in energy_deviation_by_bin]
316
325
 
317
326
  # Calculate delta_energy as the mean deviation for each bin
318
- delta_energy = [np.mean(d) if len(d) > 0 else np.nan for d in energy_deviation_by_bin]
327
+ delta_energy = [np.mean(d.value) if len(d) > 0 else np.nan for d in energy_deviation_by_bin]
319
328
 
320
329
  # Combine sigma into a single measure
321
330
  overall_uncertainty = np.nanmean(sigma_energy)
322
331
 
323
- return overall_uncertainty, sigma_energy, delta_energy
332
+ self.metric_results["energy_estimate"] = {
333
+ "overall_uncertainty": overall_uncertainty,
334
+ "sigma_energy": sigma_energy,
335
+ "delta_energy": delta_energy,
336
+ }
324
337
 
325
338
  def calculate_metrics(self):
326
339
  """Calculate all defined metrics as specified in self.metrics and store results."""
327
340
  if "uncertainty_effective_area" in self.metrics:
328
- self.uncertainty_effective_area = self.calculate_uncertainty_effective_area()
329
- if self.uncertainty_effective_area:
330
- energy_range = self.metrics.get("uncertainty_effective_area", {}).get(
331
- "energy_range"
332
- )
333
- min_energy, max_energy = (
334
- energy_range["value"][0] * u.Unit(energy_range["unit"]),
335
- energy_range["value"][1] * u.Unit(energy_range["unit"]),
336
- )
337
-
338
- valid_errors = [
339
- error
340
- for energy, error in zip(
341
- self.data["bin_edges_low"],
342
- self.uncertainty_effective_area["relative_errors"],
343
- )
344
- if min_energy <= energy <= max_energy
341
+ self.metric_results["uncertainty_effective_area"] = {
342
+ "relative_uncertainties": self.calculate_uncertainty_effective_area()[
343
+ "relative_uncertainties"
345
344
  ]
346
- self.uncertainty_effective_area["max_error"] = (
347
- max(valid_errors) if valid_errors else 0.0
348
- )
349
- ref_value = self.metrics.get("uncertainty_effective_area", {}).get("target_error")[
350
- "value"
351
- ]
352
- self._logger.info(
353
- f"Effective Area Error (max in validity range): "
354
- f"{self.uncertainty_effective_area['max_error'].value:.6f}, "
355
- f"Reference: {ref_value:.3f}"
356
- )
345
+ }
357
346
 
358
- if "energy_estimate" in self.metrics:
359
- self.energy_estimate, self.sigma_energy, self.delta_energy = (
360
- self.calculate_energy_estimate()
347
+ self.metric_results["uncertainty_effective_area"]["max_error"] = (
348
+ self.calculate_max_error_for_effective_area()
361
349
  )
362
- ref_value = self.metrics.get("energy_estimate", {}).get("target_error")["value"]
350
+ ref_value = self.metrics.get("uncertainty_effective_area", {}).get(
351
+ "target_uncertainty"
352
+ )["value"]
363
353
  self._logger.info(
364
- f"Energy Estimate Error: {self.energy_estimate:.3f}, Reference: {ref_value:.3f}"
354
+ f"Effective Area Uncertainty (max in validity range): "
355
+ f"{self.metric_results['uncertainty_effective_area']['max_error']:.6f}, "
356
+ f"Reference: {ref_value:.3f}"
365
357
  )
366
- else:
367
- raise ValueError("Invalid metric specified.")
368
- self.metric_results = {
369
- "uncertainty_effective_area": self.uncertainty_effective_area,
370
- "energy_estimate": self.energy_estimate,
371
- }
372
- return self.metric_results
373
358
 
374
- def calculate_max_error_for_effective_area(self):
375
- """
376
- Calculate the maximum relative error for effective area.
359
+ if "energy_estimate" in self.metrics:
360
+ self.calculate_energy_estimate()
361
+ ref_value = self.metrics.get("energy_estimate", {}).get("target_uncertainty")["value"]
362
+ self._logger.info(
363
+ f"Energy Estimate Uncertainty: "
364
+ f"{self.metric_results['energy_estimate']['overall_uncertainty']:.6f}, "
365
+ f"Reference: {ref_value:.3f}"
366
+ )
377
367
 
378
- Returns
379
- -------
380
- max_error : float
381
- Maximum relative error.
382
- """
383
- if "relative_errors" in self.metric_results["uncertainty_effective_area"]:
384
- return np.max(self.metric_results["uncertainty_effective_area"]["relative_errors"])
385
- if self.uncertainty_effective_area:
386
- return np.max(self.uncertainty_effective_area["relative_errors"])
387
- return None
368
+ if not ("uncertainty_effective_area" in self.metrics or "energy_estimate" in self.metrics):
369
+ raise ValueError("Invalid metric specified.")
388
370
 
389
371
  def calculate_overall_metric(self, metric="average"):
390
372
  """
@@ -397,31 +379,34 @@ class StatisticalErrorEvaluator:
397
379
 
398
380
  Returns
399
381
  -------
400
- dict
401
- Dictionary with overall maximum errors for each metric.
382
+ float
383
+ The overall metric value.
402
384
  """
403
385
  # Decide how to combine the metrics
404
386
  if self.metric_results is None:
405
387
  raise ValueError("Metrics have not been computed yet.")
406
388
 
407
- overall_max_errors = {}
389
+ overall_max_uncertainties = {}
408
390
 
409
391
  for metric_name, result in self.metric_results.items():
410
392
  if metric_name == "uncertainty_effective_area":
411
- max_errors = self.calculate_max_error_for_effective_area()
412
- overall_max_errors[metric_name] = max_errors if max_errors else 0
413
- elif metric_name in [
414
- "error_gamma_ray_psf",
415
- ]:
416
- overall_max_errors[metric_name] = result
393
+ max_uncertainties = self.calculate_max_error_for_effective_area()
394
+ overall_max_uncertainties[metric_name] = (
395
+ max_uncertainties if max_uncertainties else 0
396
+ )
397
+ elif metric_name == "energy_estimate":
398
+ # Use the "overall_uncertainty"
399
+ overall_max_uncertainties[metric_name] = result["overall_uncertainty"]
417
400
  else:
418
401
  raise ValueError(f"Unsupported result type for {metric_name}: {type(result)}")
419
- self._logger.info(f"overall_max_errors {overall_max_errors}")
420
- all_max_errors = list(overall_max_errors.values())
402
+
403
+ self._logger.info(f"overall_max_uncertainties {overall_max_uncertainties}")
404
+ all_max_uncertainties = list(overall_max_uncertainties.values())
405
+
421
406
  if metric == "average":
422
- overall_metric = np.mean(all_max_errors)
407
+ overall_metric = np.mean(all_max_uncertainties)
423
408
  elif metric == "maximum":
424
- overall_metric = np.max(all_max_errors)
409
+ overall_metric = np.nanmax(all_max_uncertainties)
425
410
  else:
426
411
  raise ValueError(f"Unsupported metric: {metric}")
427
412