gammasimtools 0.9.0__py3-none-any.whl → 0.11.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.9.0.dist-info → gammasimtools-0.11.0.dist-info}/METADATA +4 -2
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/RECORD +133 -117
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/entry_points.txt +6 -1
- simtools/_version.py +9 -4
- simtools/applications/calculate_trigger_rate.py +15 -38
- simtools/applications/convert_all_model_parameters_from_simtel.py +9 -29
- simtools/applications/convert_geo_coordinates_of_array_elements.py +47 -45
- simtools/applications/convert_model_parameter_from_simtel.py +2 -3
- simtools/applications/db_add_file_to_db.py +1 -3
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +110 -0
- simtools/applications/db_add_value_from_json_to_db.py +1 -2
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +6 -6
- simtools/applications/db_get_file_from_db.py +11 -12
- simtools/applications/db_get_parameter_from_db.py +26 -35
- simtools/applications/derive_mirror_rnda.py +1 -2
- simtools/applications/derive_photon_electron_spectrum.py +99 -0
- simtools/applications/derive_psf_parameters.py +1 -0
- simtools/applications/docs_produce_array_element_report.py +71 -0
- simtools/applications/docs_produce_model_parameter_reports.py +63 -0
- simtools/applications/generate_array_config.py +17 -17
- simtools/applications/generate_corsika_histograms.py +2 -2
- simtools/applications/generate_regular_arrays.py +19 -17
- simtools/applications/generate_simtel_array_histograms.py +11 -48
- simtools/applications/production_derive_limits.py +95 -0
- simtools/applications/production_generate_simulation_config.py +37 -33
- simtools/applications/production_scale_events.py +4 -9
- simtools/applications/run_application.py +165 -0
- simtools/applications/simulate_light_emission.py +0 -4
- simtools/applications/simulate_prod.py +1 -1
- simtools/applications/simulate_prod_htcondor_generator.py +26 -26
- simtools/applications/submit_data_from_external.py +12 -4
- simtools/applications/submit_model_parameter_from_external.py +18 -11
- simtools/applications/validate_camera_efficiency.py +2 -2
- simtools/applications/validate_file_using_schema.py +26 -22
- simtools/camera/single_photon_electron_spectrum.py +168 -0
- simtools/configuration/commandline_parser.py +37 -1
- simtools/configuration/configurator.py +8 -10
- simtools/constants.py +10 -3
- simtools/corsika/corsika_config.py +19 -17
- simtools/corsika/corsika_histograms.py +5 -7
- simtools/corsika/corsika_histograms_visualize.py +2 -4
- simtools/data_model/data_reader.py +0 -3
- simtools/data_model/metadata_collector.py +20 -12
- simtools/data_model/metadata_model.py +8 -124
- simtools/data_model/model_data_writer.py +81 -75
- simtools/data_model/schema.py +220 -0
- simtools/data_model/validate_data.py +79 -68
- simtools/db/db_handler.py +350 -492
- simtools/db/db_model_upload.py +139 -0
- simtools/dependencies.py +112 -0
- simtools/io_operations/hdf5_handler.py +54 -24
- simtools/layout/array_layout.py +38 -32
- simtools/model/array_model.py +13 -7
- simtools/model/model_parameter.py +55 -54
- simtools/model/site_model.py +2 -2
- simtools/production_configuration/calculate_statistical_errors_grid_point.py +119 -145
- simtools/production_configuration/event_scaler.py +9 -35
- simtools/production_configuration/generate_simulation_config.py +9 -44
- simtools/production_configuration/interpolation_handler.py +9 -15
- simtools/production_configuration/limits_calculation.py +202 -0
- simtools/reporting/docs_read_parameters.py +310 -0
- simtools/runners/corsika_simtel_runner.py +4 -4
- simtools/schemas/{integration_tests_config.metaschema.yml → application_workflow.metaschema.yml} +61 -27
- simtools/schemas/array_elements.yml +8 -0
- simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +39 -0
- simtools/schemas/input/single_pe_spectrum.schema.yml +38 -0
- simtools/schemas/model_parameter.metaschema.yml +103 -2
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +4 -1
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +1 -1
- simtools/schemas/model_parameters/array_window.schema.yml +37 -0
- simtools/schemas/model_parameters/asum_clipping.schema.yml +0 -4
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +4 -2
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +2 -0
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_offset.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +0 -2
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_noise.schema.yml +3 -3
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +33 -0
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_photons.schema.yml +2 -2
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/random_generator.schema.yml +1 -1
- simtools/schemas/model_parameters/sampled_output.schema.yml +1 -1
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
- simtools/schemas/production_configuration_metrics.schema.yml +68 -0
- simtools/schemas/production_tables.schema.yml +41 -0
- simtools/simtel/simtel_config_reader.py +1 -2
- simtools/simtel/simtel_config_writer.py +6 -8
- simtools/simtel/simtel_io_histogram.py +32 -68
- simtools/simtel/simtel_io_histograms.py +17 -34
- simtools/simtel/simulator_array.py +2 -1
- simtools/simtel/simulator_camera_efficiency.py +6 -3
- simtools/simtel/simulator_light_emission.py +5 -6
- simtools/simtel/simulator_ray_tracing.py +3 -4
- simtools/testing/configuration.py +2 -1
- simtools/testing/helpers.py +6 -13
- simtools/testing/validate_output.py +141 -47
- simtools/utils/general.py +114 -14
- simtools/utils/names.py +299 -157
- simtools/utils/value_conversion.py +17 -13
- simtools/version.py +2 -2
- simtools/visualization/legend_handlers.py +2 -0
- simtools/applications/db_add_model_parameters_from_repository_to_db.py +0 -176
- simtools/db/db_array_elements.py +0 -130
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/LICENSE +0 -0
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/top_level.txt +0 -0
- /simtools/{camera_efficiency.py → camera/camera_efficiency.py} +0 -0
|
@@ -6,16 +6,10 @@ which scales the number of events for both the entire dataset and specific grid
|
|
|
6
6
|
Scaling factors are calculated using error metrics and the evaluator's results.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
import logging
|
|
10
|
-
|
|
11
9
|
import astropy.units as u
|
|
12
10
|
import numpy as np
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
StatisticalErrorEvaluator,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
_logger = logging.getLogger(__name__)
|
|
12
|
+
__all__ = ["EventScaler"]
|
|
19
13
|
|
|
20
14
|
|
|
21
15
|
class EventScaler:
|
|
@@ -25,43 +19,36 @@ class EventScaler:
|
|
|
25
19
|
Supports scaling both the entire dataset and specific grid points like energy values.
|
|
26
20
|
"""
|
|
27
21
|
|
|
28
|
-
def __init__(self, evaluator
|
|
22
|
+
def __init__(self, evaluator, metrics: dict):
|
|
29
23
|
"""
|
|
30
|
-
Initialize the EventScaler with the evaluator
|
|
24
|
+
Initialize the EventScaler with the evaluator and metrics.
|
|
31
25
|
|
|
32
26
|
Parameters
|
|
33
27
|
----------
|
|
34
28
|
evaluator : StatisticalErrorEvaluator
|
|
35
29
|
The evaluator responsible for calculating metrics and handling event data.
|
|
36
|
-
science_case : str
|
|
37
|
-
The science case used to adjust the uncertainty factor.
|
|
38
30
|
metrics : dict
|
|
39
31
|
Dictionary containing metrics, including target error for effective area.
|
|
40
32
|
"""
|
|
41
33
|
self.evaluator = evaluator
|
|
42
|
-
self.science_case = science_case
|
|
43
34
|
self.metrics = metrics
|
|
44
35
|
|
|
45
36
|
def scale_events(self, return_sum: bool = True) -> u.Quantity:
|
|
46
37
|
"""
|
|
47
38
|
Calculate the scaled number of events based on statistical error metrics.
|
|
48
39
|
|
|
49
|
-
If `return_sum` is `True`, the method returns the sum of scaled events for the entire
|
|
50
|
-
dataset. If `return_sum` is `False`, it returns the scaled number of events for each
|
|
51
|
-
grid point (e.g., along the energy axis).
|
|
52
|
-
|
|
53
40
|
Parameters
|
|
54
41
|
----------
|
|
55
42
|
return_sum : bool, optional
|
|
56
|
-
If
|
|
57
|
-
returns the scaled events for each grid point along the energy axis. Default is
|
|
43
|
+
If True, returns the sum of scaled events for the entire set of MC events. If False,
|
|
44
|
+
returns the scaled events for each grid point along the energy axis. Default is True.
|
|
58
45
|
|
|
59
46
|
Returns
|
|
60
47
|
-------
|
|
61
48
|
u.Quantity
|
|
62
|
-
If
|
|
63
|
-
If
|
|
64
|
-
a
|
|
49
|
+
If 'return_sum' is True, returns the total scaled number of events as a u.Quantity.
|
|
50
|
+
If 'return_sum' is False, returns an array of scaled events along the energy axis as
|
|
51
|
+
a u.Quantity.
|
|
65
52
|
"""
|
|
66
53
|
scaling_factor = self._compute_scaling_factor()
|
|
67
54
|
|
|
@@ -87,20 +74,7 @@ class EventScaler:
|
|
|
87
74
|
"value"
|
|
88
75
|
]
|
|
89
76
|
|
|
90
|
-
return (
|
|
91
|
-
current_max_error / target_max_error
|
|
92
|
-
) ** 2 * self._apply_science_case_scaling_factor()
|
|
93
|
-
|
|
94
|
-
def _apply_science_case_scaling_factor(self) -> float:
|
|
95
|
-
"""
|
|
96
|
-
Apply the uncertainty factor based on the science case.
|
|
97
|
-
|
|
98
|
-
Returns
|
|
99
|
-
-------
|
|
100
|
-
float
|
|
101
|
-
The final scaling factor after applying uncertainty.
|
|
102
|
-
"""
|
|
103
|
-
return 1 if self.science_case == "science case 1" else 1.0
|
|
77
|
+
return (current_max_error / target_max_error) ** 2
|
|
104
78
|
|
|
105
79
|
def _number_of_simulated_events(self) -> u.Quantity:
|
|
106
80
|
"""
|
|
@@ -1,33 +1,11 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Configures and generates simulation parameters for a specific grid point.
|
|
3
|
-
|
|
4
|
-
Used to configure and generate simulation parameters for a specific grid point
|
|
5
|
-
based on statistical uncertainties.
|
|
6
|
-
The class considers parameters, such as azimuth, elevation, and night sky background,
|
|
7
|
-
to compute core scatter area, viewcone, and the required number of simulated events.
|
|
8
|
-
|
|
9
|
-
Key Components:
|
|
10
|
-
---------------
|
|
11
|
-
- `SimulationConfig`: Main class to handle simulation configuration for a grid point.
|
|
12
|
-
- Attributes:
|
|
13
|
-
- `grid_point` (dict): Contains azimuth, elevation, and night sky background.
|
|
14
|
-
- `ctao_data_level` (str): The data level for the simulation (e.g., 'A', 'B', 'C').
|
|
15
|
-
- `science_case` (str): The science case for the simulation.
|
|
16
|
-
- `file_path` (str): Path to the DL2 MC event file
|
|
17
|
-
used for statistical error evaluation.
|
|
18
|
-
- `file_type` (str): Type of the DL2 MC event file ('point-like' or 'cone').
|
|
19
|
-
- `metrics` (dict, optional): Dictionary of metrics to evaluate.
|
|
20
|
-
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
import logging
|
|
1
|
+
"""Derives simulation configuration parameters for a grid point based on several metrics."""
|
|
24
2
|
|
|
25
3
|
from simtools.production_configuration.calculate_statistical_errors_grid_point import (
|
|
26
4
|
StatisticalErrorEvaluator,
|
|
27
5
|
)
|
|
28
6
|
from simtools.production_configuration.event_scaler import EventScaler
|
|
29
7
|
|
|
30
|
-
|
|
8
|
+
__all__ = ["SimulationConfig"]
|
|
31
9
|
|
|
32
10
|
|
|
33
11
|
class SimulationConfig:
|
|
@@ -38,10 +16,6 @@ class SimulationConfig:
|
|
|
38
16
|
----------
|
|
39
17
|
grid_point : dict
|
|
40
18
|
Dictionary representing a grid point with azimuth, elevation, and night sky background.
|
|
41
|
-
ctao_data_level : str
|
|
42
|
-
The data level (e.g., 'A', 'B', 'C') for the simulation configuration.
|
|
43
|
-
science_case : str
|
|
44
|
-
The science case for the simulation configuration.
|
|
45
19
|
file_path : str
|
|
46
20
|
Path to the DL2 MC event file for statistical uncertainty evaluation.
|
|
47
21
|
file_type : str
|
|
@@ -53,26 +27,22 @@ class SimulationConfig:
|
|
|
53
27
|
def __init__(
|
|
54
28
|
self,
|
|
55
29
|
grid_point: dict[str, float],
|
|
56
|
-
ctao_data_level: str,
|
|
57
|
-
science_case: str,
|
|
58
30
|
file_path: str,
|
|
59
31
|
file_type: str,
|
|
60
32
|
metrics: dict[str, float] | None = None,
|
|
61
33
|
):
|
|
62
34
|
"""Initialize the simulation configuration for a grid point."""
|
|
63
35
|
self.grid_point = grid_point
|
|
64
|
-
self.ctao_data_level = ctao_data_level
|
|
65
|
-
self.science_case = science_case
|
|
66
36
|
self.file_path = file_path
|
|
67
37
|
self.file_type = file_type
|
|
68
38
|
self.metrics = metrics or {}
|
|
69
39
|
self.evaluator = StatisticalErrorEvaluator(file_path, file_type, metrics)
|
|
70
|
-
self.event_scaler = EventScaler(self.evaluator,
|
|
40
|
+
self.event_scaler = EventScaler(self.evaluator, self.metrics)
|
|
71
41
|
self.simulation_params = {}
|
|
72
42
|
|
|
73
43
|
def configure_simulation(self) -> dict[str, float]:
|
|
74
44
|
"""
|
|
75
|
-
Configure the simulation parameters for the grid point
|
|
45
|
+
Configure the simulation parameters for the grid point.
|
|
76
46
|
|
|
77
47
|
Returns
|
|
78
48
|
-------
|
|
@@ -80,16 +50,11 @@ class SimulationConfig:
|
|
|
80
50
|
A dictionary with simulation parameters such as core scatter area,
|
|
81
51
|
viewcone, and number of simulated events.
|
|
82
52
|
"""
|
|
83
|
-
core_scatter_area = self._calculate_core_scatter_area()
|
|
84
|
-
viewcone = self._calculate_viewcone()
|
|
85
|
-
number_of_events = self.calculate_required_events()
|
|
86
|
-
|
|
87
53
|
self.simulation_params = {
|
|
88
|
-
"core_scatter_area":
|
|
89
|
-
"viewcone":
|
|
90
|
-
"number_of_events":
|
|
54
|
+
"core_scatter_area": self._calculate_core_scatter_area(),
|
|
55
|
+
"viewcone": self._calculate_viewcone(),
|
|
56
|
+
"number_of_events": self.calculate_required_events(),
|
|
91
57
|
}
|
|
92
|
-
|
|
93
58
|
return self.simulation_params
|
|
94
59
|
|
|
95
60
|
def calculate_required_events(self) -> int:
|
|
@@ -107,7 +72,7 @@ class SimulationConfig:
|
|
|
107
72
|
|
|
108
73
|
def _calculate_core_scatter_area(self) -> float:
|
|
109
74
|
"""
|
|
110
|
-
Calculate the core scatter area based on the grid point
|
|
75
|
+
Calculate the core scatter area based on the grid point.
|
|
111
76
|
|
|
112
77
|
Returns
|
|
113
78
|
-------
|
|
@@ -120,7 +85,7 @@ class SimulationConfig:
|
|
|
120
85
|
|
|
121
86
|
def _calculate_viewcone(self) -> float:
|
|
122
87
|
"""
|
|
123
|
-
Calculate the viewcone based on the grid point conditions
|
|
88
|
+
Calculate the viewcone based on the grid point conditions.
|
|
124
89
|
|
|
125
90
|
Returns
|
|
126
91
|
-------
|
|
@@ -4,24 +4,18 @@ import astropy.units as u
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
from scipy.interpolate import griddata
|
|
6
6
|
|
|
7
|
-
from simtools.production_configuration.calculate_statistical_errors_grid_point import (
|
|
8
|
-
StatisticalErrorEvaluator,
|
|
9
|
-
)
|
|
10
7
|
from simtools.production_configuration.event_scaler import EventScaler
|
|
11
8
|
|
|
9
|
+
__all__ = ["InterpolationHandler"]
|
|
10
|
+
|
|
12
11
|
|
|
13
12
|
class InterpolationHandler:
|
|
14
13
|
"""Handle interpolation between multiple StatisticalErrorEvaluator instances."""
|
|
15
14
|
|
|
16
|
-
def __init__(
|
|
17
|
-
self, evaluators: list["StatisticalErrorEvaluator"], science_case: str, metrics: dict
|
|
18
|
-
):
|
|
15
|
+
def __init__(self, evaluators, metrics: dict):
|
|
19
16
|
self.evaluators = evaluators
|
|
20
|
-
self.science_case = science_case
|
|
21
17
|
self.metrics = metrics
|
|
22
|
-
self.event_scalers = [
|
|
23
|
-
EventScaler(e, self.science_case, self.metrics) for e in self.evaluators
|
|
24
|
-
]
|
|
18
|
+
self.event_scalers = [EventScaler(e, self.metrics) for e in self.evaluators]
|
|
25
19
|
|
|
26
20
|
self.azimuths = [e.grid_point[1].to(u.deg).value for e in self.evaluators]
|
|
27
21
|
self.zeniths = [e.grid_point[2].to(u.deg).value for e in self.evaluators]
|
|
@@ -157,9 +151,9 @@ class InterpolationHandler:
|
|
|
157
151
|
|
|
158
152
|
return interpolated_threshold.item()
|
|
159
153
|
|
|
160
|
-
def plot_comparison(self, evaluator
|
|
154
|
+
def plot_comparison(self, evaluator):
|
|
161
155
|
"""
|
|
162
|
-
Plot a comparison between the simulated, scaled, and
|
|
156
|
+
Plot a comparison between the simulated, scaled, and reconstructed events.
|
|
163
157
|
|
|
164
158
|
Parameters
|
|
165
159
|
----------
|
|
@@ -184,14 +178,14 @@ class InterpolationHandler:
|
|
|
184
178
|
|
|
185
179
|
plt.plot(midpoints, evaluator.scaled_events, label="Scaled")
|
|
186
180
|
|
|
187
|
-
|
|
181
|
+
reconstructed_event_histogram, _ = np.histogram(
|
|
188
182
|
evaluator.data["event_energies_reco"], bins=evaluator.data["bin_edges_low"]
|
|
189
183
|
)
|
|
190
|
-
plt.plot(midpoints[:-1],
|
|
184
|
+
plt.plot(midpoints[:-1], reconstructed_event_histogram, label="Reconstructed")
|
|
191
185
|
|
|
192
186
|
plt.legend()
|
|
193
187
|
plt.xscale("log")
|
|
194
188
|
plt.xlabel("Energy (Midpoint of Bin Edges)")
|
|
195
189
|
plt.ylabel("Event Count")
|
|
196
|
-
plt.title("Comparison of Simulated,
|
|
190
|
+
plt.title("Comparison of Simulated, scaled, and reconstructed events")
|
|
197
191
|
plt.show()
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""Calculate the thresholds for energy, radial distance, and viewcone."""
|
|
2
|
+
|
|
3
|
+
import astropy.units as u
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LimitCalculator:
|
|
8
|
+
"""
|
|
9
|
+
Compute thresholds/limits for energy, radial distance, and viewcone.
|
|
10
|
+
|
|
11
|
+
Histograms are generated with simtools-generate-simtel-array-histograms with --hdf5 flag.
|
|
12
|
+
|
|
13
|
+
Event data is read from the generated HDF5 file from the following tables:
|
|
14
|
+
- angle_to_observing_position__triggered_showers_ for the viewcone limit.
|
|
15
|
+
- event_weight__ra3d__log10_e__ for the energy and radial distance limit.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
event_data_file : list of astropy.table.Table
|
|
21
|
+
The list of tables containing the event data.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, event_data_file_tables):
|
|
25
|
+
"""
|
|
26
|
+
Initialize the LimitCalculator with the given event data file.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
event_data_file : list of astropy.table.Table
|
|
31
|
+
The list of tables containing the event data.
|
|
32
|
+
"""
|
|
33
|
+
self.angle_to_observing_position__triggered_showers_ = None
|
|
34
|
+
self.event_weight__ra3d__log10_e__ = None
|
|
35
|
+
|
|
36
|
+
for table in event_data_file_tables:
|
|
37
|
+
if (
|
|
38
|
+
"Title" in table.meta
|
|
39
|
+
and table.meta["Title"] == "angle_to_observing_position__triggered_showers_"
|
|
40
|
+
):
|
|
41
|
+
self.angle_to_observing_position__triggered_showers_ = table
|
|
42
|
+
elif "Title" in table.meta and table.meta["Title"] == "event_weight__ra3d__log10_e__":
|
|
43
|
+
self.event_weight__ra3d__log10_e__ = table
|
|
44
|
+
|
|
45
|
+
def _compute_limits(
|
|
46
|
+
self, event_weight_array, bin_edges, loss_fraction, axis=0, limit_type="lower"
|
|
47
|
+
):
|
|
48
|
+
"""
|
|
49
|
+
Compute the limits based on the loss fraction.
|
|
50
|
+
|
|
51
|
+
Parameters
|
|
52
|
+
----------
|
|
53
|
+
event_weight_array : np.ndarray
|
|
54
|
+
Array of event weights.
|
|
55
|
+
bin_edges : np.ndarray
|
|
56
|
+
Array of bin edges.
|
|
57
|
+
loss_fraction : float
|
|
58
|
+
Fraction of events to be lost.
|
|
59
|
+
axis : int, optional
|
|
60
|
+
Axis along which to sum the event weights. Default is 0.
|
|
61
|
+
limit_type : str, optional
|
|
62
|
+
Type of limit ('lower' or 'upper'). Default is 'lower'.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
int
|
|
67
|
+
Bin index where the threshold is reached.
|
|
68
|
+
float
|
|
69
|
+
Bin edge value corresponding to the threshold.
|
|
70
|
+
"""
|
|
71
|
+
projection = np.sum(event_weight_array, axis=axis)
|
|
72
|
+
bin_edge_value = None
|
|
73
|
+
cumulative_sum = None
|
|
74
|
+
if limit_type == "upper":
|
|
75
|
+
cumulative_sum = np.cumsum(projection)
|
|
76
|
+
|
|
77
|
+
elif limit_type == "lower":
|
|
78
|
+
cumulative_sum = np.cumsum(projection[::-1])
|
|
79
|
+
|
|
80
|
+
total_events = np.sum(projection)
|
|
81
|
+
threshold = (1 - loss_fraction) * total_events
|
|
82
|
+
bin_index = np.searchsorted(cumulative_sum, threshold)
|
|
83
|
+
if limit_type == "upper":
|
|
84
|
+
bin_edge_value = bin_edges[bin_index]
|
|
85
|
+
elif limit_type == "lower":
|
|
86
|
+
bin_edge_value = bin_edges[-bin_index]
|
|
87
|
+
return bin_index, bin_edge_value
|
|
88
|
+
|
|
89
|
+
def get_bin_edges_and_units(self, table, axis="x"):
|
|
90
|
+
"""
|
|
91
|
+
Extract bin edges and units from the table metadata.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
table : astropy.table.Table
|
|
96
|
+
Table containing the event data.
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
tuple
|
|
101
|
+
Tuple containing the bin edges and their units.
|
|
102
|
+
"""
|
|
103
|
+
bin_edges = table.meta[f"{axis}_bin_edges"]
|
|
104
|
+
try:
|
|
105
|
+
bin_edges_unit = table.meta[f"{axis}_bin_edges_unit"]
|
|
106
|
+
except KeyError:
|
|
107
|
+
bin_edges_unit = ""
|
|
108
|
+
return bin_edges, bin_edges_unit
|
|
109
|
+
|
|
110
|
+
def compute_lower_energy_limit(self, loss_fraction):
|
|
111
|
+
"""
|
|
112
|
+
Compute the lower energy limit in TeV based on the event loss fraction.
|
|
113
|
+
|
|
114
|
+
Parameters
|
|
115
|
+
----------
|
|
116
|
+
loss_fraction : float
|
|
117
|
+
Fraction of events to be lost.
|
|
118
|
+
|
|
119
|
+
Returns
|
|
120
|
+
-------
|
|
121
|
+
astropy.units.Quantity
|
|
122
|
+
Lower energy limit.
|
|
123
|
+
"""
|
|
124
|
+
event_weight_array = np.column_stack(
|
|
125
|
+
[
|
|
126
|
+
self.event_weight__ra3d__log10_e__[name]
|
|
127
|
+
for name in self.event_weight__ra3d__log10_e__.dtype.names
|
|
128
|
+
]
|
|
129
|
+
)
|
|
130
|
+
bin_edges, bin_edges_unit = self.get_bin_edges_and_units(
|
|
131
|
+
self.event_weight__ra3d__log10_e__, axis="y"
|
|
132
|
+
)
|
|
133
|
+
if bin_edges_unit == "":
|
|
134
|
+
bin_edges_unit = "TeV"
|
|
135
|
+
_, lower_bin_edge_value = self._compute_limits(
|
|
136
|
+
event_weight_array, bin_edges, loss_fraction, axis=0, limit_type="lower"
|
|
137
|
+
)
|
|
138
|
+
return (10**lower_bin_edge_value) * u.Unit(bin_edges_unit)
|
|
139
|
+
|
|
140
|
+
def compute_upper_radial_distance(self, loss_fraction):
|
|
141
|
+
"""
|
|
142
|
+
Compute the upper radial distance based on the event loss fraction.
|
|
143
|
+
|
|
144
|
+
Parameters
|
|
145
|
+
----------
|
|
146
|
+
loss_fraction : float
|
|
147
|
+
Fraction of events to be lost.
|
|
148
|
+
|
|
149
|
+
Returns
|
|
150
|
+
-------
|
|
151
|
+
astropy.units.Quantity
|
|
152
|
+
Upper radial distance in m.
|
|
153
|
+
"""
|
|
154
|
+
event_weight_array = np.column_stack(
|
|
155
|
+
[
|
|
156
|
+
self.event_weight__ra3d__log10_e__[name]
|
|
157
|
+
for name in self.event_weight__ra3d__log10_e__.dtype.names
|
|
158
|
+
]
|
|
159
|
+
)
|
|
160
|
+
bin_edges, bin_edges_unit = self.get_bin_edges_and_units(
|
|
161
|
+
self.event_weight__ra3d__log10_e__, axis="x"
|
|
162
|
+
)
|
|
163
|
+
if bin_edges_unit == "":
|
|
164
|
+
bin_edges_unit = "m"
|
|
165
|
+
_, upper_bin_edge_value = self._compute_limits(
|
|
166
|
+
event_weight_array, bin_edges, loss_fraction, axis=1, limit_type="upper"
|
|
167
|
+
)
|
|
168
|
+
return upper_bin_edge_value * u.Unit(bin_edges_unit)
|
|
169
|
+
|
|
170
|
+
def compute_viewcone(self, loss_fraction):
|
|
171
|
+
"""
|
|
172
|
+
Compute the viewcone based on the event loss fraction.
|
|
173
|
+
|
|
174
|
+
Parameters
|
|
175
|
+
----------
|
|
176
|
+
loss_fraction : float
|
|
177
|
+
Fraction of events to be lost.
|
|
178
|
+
|
|
179
|
+
Returns
|
|
180
|
+
-------
|
|
181
|
+
astropy.units.Quantity
|
|
182
|
+
Viewcone radius in degrees.
|
|
183
|
+
"""
|
|
184
|
+
angle_to_observing_position__triggered_showers = np.column_stack(
|
|
185
|
+
[
|
|
186
|
+
self.angle_to_observing_position__triggered_showers_[name]
|
|
187
|
+
for name in self.angle_to_observing_position__triggered_showers_.dtype.names
|
|
188
|
+
]
|
|
189
|
+
)
|
|
190
|
+
bin_edges, bin_edges_unit = self.get_bin_edges_and_units(
|
|
191
|
+
self.angle_to_observing_position__triggered_showers_, axis="x"
|
|
192
|
+
)
|
|
193
|
+
if bin_edges_unit == "":
|
|
194
|
+
bin_edges_unit = "deg"
|
|
195
|
+
_, upper_bin_edge_value = self._compute_limits(
|
|
196
|
+
angle_to_observing_position__triggered_showers,
|
|
197
|
+
bin_edges,
|
|
198
|
+
loss_fraction,
|
|
199
|
+
axis=0,
|
|
200
|
+
limit_type="upper",
|
|
201
|
+
)
|
|
202
|
+
return upper_bin_edge_value * u.Unit(bin_edges_unit)
|