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.
- {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/METADATA +5 -33
- {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/RECORD +243 -229
- {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/entry_points.txt +8 -3
- simtools/_version.py +2 -2
- simtools/applications/calculate_trigger_rate.py +10 -10
- simtools/applications/convert_all_model_parameters_from_simtel.py +16 -16
- simtools/applications/convert_model_parameter_from_simtel.py +1 -1
- simtools/applications/derive_ctao_array_layouts.py +5 -5
- simtools/applications/derive_psf_parameters.py +12 -9
- simtools/applications/docs_produce_array_element_report.py +3 -3
- simtools/applications/docs_produce_calibration_reports.py +49 -0
- simtools/applications/docs_produce_simulation_configuration_report.py +50 -0
- simtools/applications/{generate_simtel_array_histograms.py → generate_sim_telarray_histograms.py} +2 -2
- simtools/applications/generate_simtel_event_data.py +36 -46
- simtools/applications/merge_tables.py +104 -0
- simtools/applications/plot_array_layout.py +145 -258
- simtools/applications/production_derive_corsika_limits.py +35 -167
- simtools/applications/production_derive_statistics.py +159 -0
- simtools/applications/production_generate_grid.py +197 -0
- simtools/applications/simulate_light_emission.py +6 -13
- simtools/applications/simulate_prod.py +45 -21
- simtools/applications/simulate_prod_htcondor_generator.py +0 -1
- simtools/applications/submit_array_layouts.py +93 -0
- simtools/applications/validate_cumulative_psf.py +6 -4
- simtools/applications/validate_file_using_schema.py +7 -3
- simtools/applications/validate_optics.py +5 -4
- simtools/applications/verify_simulation_model_production_tables.py +52 -0
- simtools/camera/camera_efficiency.py +17 -42
- simtools/configuration/commandline_parser.py +32 -37
- simtools/configuration/configurator.py +10 -4
- simtools/corsika/corsika_config.py +120 -17
- simtools/corsika/primary_particle.py +46 -13
- simtools/data_model/format_checkers.py +9 -0
- simtools/data_model/metadata_collector.py +7 -3
- simtools/data_model/model_data_writer.py +3 -0
- simtools/data_model/schema.py +27 -16
- simtools/data_model/validate_data.py +27 -7
- simtools/db/db_handler.py +21 -15
- simtools/db/db_model_upload.py +2 -2
- simtools/io_operations/io_handler.py +2 -2
- simtools/io_operations/io_table_handler.py +345 -0
- simtools/job_execution/htcondor_script_generator.py +2 -2
- simtools/job_execution/job_manager.py +7 -121
- simtools/layout/array_layout.py +1 -0
- simtools/layout/array_layout_utils.py +385 -0
- simtools/model/array_model.py +68 -29
- simtools/model/model_parameter.py +76 -51
- simtools/model/model_repository.py +134 -0
- simtools/model/model_utils.py +43 -1
- simtools/model/site_model.py +3 -2
- simtools/model/telescope_model.py +4 -4
- simtools/production_configuration/{calculate_statistical_errors_grid_point.py → calculate_statistical_uncertainties_grid_point.py} +101 -116
- simtools/production_configuration/derive_corsika_limits.py +239 -111
- simtools/production_configuration/derive_corsika_limits_grid.py +189 -0
- simtools/production_configuration/derive_production_statistics.py +155 -0
- simtools/production_configuration/derive_production_statistics_handler.py +152 -0
- simtools/production_configuration/generate_production_grid.py +364 -0
- simtools/production_configuration/interpolation_handler.py +303 -96
- simtools/ray_tracing/mirror_panel_psf.py +16 -20
- simtools/ray_tracing/psf_analysis.py +2 -2
- simtools/ray_tracing/ray_tracing.py +12 -7
- simtools/reporting/docs_read_parameters.py +426 -81
- simtools/runners/corsika_runner.py +11 -1
- simtools/runners/corsika_simtel_runner.py +84 -90
- simtools/runners/runner_services.py +22 -8
- simtools/runners/simtel_runner.py +27 -10
- simtools/schemas/model_parameter.metaschema.yml +4 -0
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +1 -0
- simtools/schemas/model_parameters/adjust_gain.schema.yml +2 -2
- simtools/schemas/model_parameters/array_element_position_ground.schema.yml +2 -2
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +2 -2
- simtools/schemas/model_parameters/array_window.schema.yml +2 -2
- simtools/schemas/model_parameters/asum_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/asum_shaping.schema.yml +2 -2
- simtools/schemas/model_parameters/asum_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/axes_offsets.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_body_diameter.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_body_shape.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_config_file.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_config_rotate.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_degraded_map.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_depth.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_filter.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_pixels.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_transmission.schema.yml +2 -2
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +2 -2
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +2 -2
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +90 -1
- simtools/schemas/model_parameters/default_trigger.schema.yml +2 -2
- simtools/schemas/model_parameters/design_model.schema.yml +2 -2
- simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +2 -2
- simtools/schemas/model_parameters/disc_bins.schema.yml +2 -2
- simtools/schemas/model_parameters/disc_start.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/dish_shape_length.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +44 -3
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +2 -2
- simtools/schemas/model_parameters/effective_focal_length.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_amplitude.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_bins.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_max_signal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_mhz.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_noise.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +2 -2
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/flatfielding.schema.yml +2 -2
- simtools/schemas/model_parameters/focal_length.schema.yml +2 -2
- simtools/schemas/model_parameters/focus_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/gain_variation.schema.yml +2 -2
- simtools/schemas/model_parameters/hg_lg_variation.schema.yml +2 -2
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +2 -2
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +2 -2
- simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +2 -2
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +2 -2
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +2 -2
- simtools/schemas/model_parameters/min_photons.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_class.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_focal_length.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_list.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +2 -2
- simtools/schemas/model_parameters/multiplicity_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +2 -2
- simtools/schemas/model_parameters/nsb_offaxis.schema.yml +2 -2
- simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +2 -2
- simtools/schemas/model_parameters/num_gains.schema.yml +2 -2
- simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +2 -2
- simtools/schemas/model_parameters/optics_properties.schema.yml +2 -2
- simtools/schemas/model_parameters/pedestal_events.schema.yml +7 -3
- simtools/schemas/model_parameters/photon_delay.schema.yml +2 -2
- simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_average_gain.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_gain_index.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_transit_time.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +2 -2
- simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +2 -2
- simtools/schemas/model_parameters/qe_variation.schema.yml +2 -2
- simtools/schemas/model_parameters/quantum_efficiency.schema.yml +2 -2
- simtools/schemas/model_parameters/random_focal_length.schema.yml +2 -2
- simtools/schemas/model_parameters/random_generator.schema.yml +2 -2
- simtools/schemas/model_parameters/random_mono_probability.schema.yml +2 -2
- simtools/schemas/model_parameters/sampled_output.schema.yml +2 -2
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +2 -2
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +2 -2
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +2 -2
- simtools/schemas/model_parameters/telescope_axis_height.schema.yml +2 -2
- simtools/schemas/model_parameters/telescope_random_angle.schema.yml +2 -2
- simtools/schemas/model_parameters/telescope_random_error.schema.yml +2 -2
- simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +2 -2
- simtools/schemas/model_parameters/telescope_transmission.schema.yml +2 -2
- simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +2 -2
- simtools/schemas/model_parameters/teltrig_min_time.schema.yml +2 -2
- simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +2 -2
- simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +2 -2
- simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +2 -2
- simtools/schemas/model_parameters/transit_time_error.schema.yml +2 -2
- simtools/schemas/model_parameters/transit_time_jitter.schema.yml +2 -2
- simtools/schemas/model_parameters/trigger_current_limit.schema.yml +2 -2
- simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +2 -2
- simtools/schemas/model_parameters/trigger_pixels.schema.yml +2 -2
- simtools/schemas/production_configuration_metrics.schema.yml +2 -2
- simtools/simtel/simtel_config_reader.py +21 -17
- simtools/simtel/simtel_config_writer.py +258 -66
- simtools/simtel/simtel_io_event_reader.py +301 -194
- simtools/simtel/simtel_io_event_writer.py +207 -227
- simtools/simtel/simtel_io_file_info.py +62 -0
- simtools/simtel/simtel_io_histogram.py +10 -14
- simtools/simtel/simtel_io_histograms.py +2 -2
- simtools/simtel/simtel_io_metadata.py +106 -0
- simtools/simtel/simulator_array.py +28 -14
- simtools/simtel/simulator_camera_efficiency.py +12 -6
- simtools/simtel/simulator_light_emission.py +85 -45
- simtools/simtel/simulator_ray_tracing.py +16 -6
- simtools/simulator.py +286 -89
- simtools/testing/configuration.py +5 -0
- simtools/testing/helpers.py +18 -0
- simtools/testing/sim_telarray_metadata.py +212 -0
- simtools/testing/validate_output.py +16 -6
- simtools/utils/general.py +18 -27
- simtools/utils/names.py +32 -10
- simtools/visualization/plot_array_layout.py +242 -0
- simtools/visualization/plot_pixels.py +681 -0
- simtools/visualization/visualize.py +5 -221
- simtools/applications/production_generate_simulation_config.py +0 -162
- simtools/applications/production_scale_events.py +0 -185
- simtools/layout/ctao_array_layouts.py +0 -172
- simtools/production_configuration/event_scaler.py +0 -120
- simtools/production_configuration/generate_simulation_config.py +0 -158
- {gammasimtools-0.15.0.dist-info → gammasimtools-0.17.0.dist-info}/licenses/LICENSE +0 -0
- {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__ = ["
|
|
9
|
+
__all__ = ["StatisticalUncertaintyEvaluator"]
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class
|
|
12
|
+
class StatisticalUncertaintyEvaluator:
|
|
13
13
|
"""
|
|
14
|
-
|
|
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
|
-
|
|
21
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
228
|
-
|
|
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,
|
|
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"],
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
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"],
|
|
262
|
+
self.data["event_energies_mc"], self.energy_bin_edges
|
|
278
263
|
)
|
|
279
264
|
simulated_event_histogram = self.data["simulated_event_histogram"]
|
|
280
|
-
_,
|
|
265
|
+
_, relative_uncertainties = self.compute_efficiency_and_uncertainties(
|
|
281
266
|
reconstructed_event_histogram, simulated_event_histogram
|
|
282
267
|
)
|
|
283
|
-
return {"
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
329
|
-
|
|
330
|
-
|
|
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
|
-
|
|
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
|
-
|
|
359
|
-
|
|
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("
|
|
350
|
+
ref_value = self.metrics.get("uncertainty_effective_area", {}).get(
|
|
351
|
+
"target_uncertainty"
|
|
352
|
+
)["value"]
|
|
363
353
|
self._logger.info(
|
|
364
|
-
f"
|
|
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
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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
|
-
|
|
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
|
-
|
|
401
|
-
|
|
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
|
-
|
|
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
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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
|
-
|
|
420
|
-
|
|
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(
|
|
407
|
+
overall_metric = np.mean(all_max_uncertainties)
|
|
423
408
|
elif metric == "maximum":
|
|
424
|
-
overall_metric = np.
|
|
409
|
+
overall_metric = np.nanmax(all_max_uncertainties)
|
|
425
410
|
else:
|
|
426
411
|
raise ValueError(f"Unsupported metric: {metric}")
|
|
427
412
|
|