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
|
@@ -5,38 +5,167 @@ import logging
|
|
|
5
5
|
import astropy.units as u
|
|
6
6
|
import matplotlib.pyplot as plt
|
|
7
7
|
import numpy as np
|
|
8
|
+
from matplotlib.colors import LogNorm
|
|
8
9
|
|
|
9
10
|
from simtools.simtel.simtel_io_event_reader import SimtelIOEventDataReader
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class LimitCalculator:
|
|
13
14
|
"""
|
|
14
|
-
Compute
|
|
15
|
+
Compute limits for CORSIKA configuration for energy, radial distance, and viewcone.
|
|
15
16
|
|
|
16
17
|
Event data is read from the reduced MC event data file.
|
|
17
18
|
|
|
18
19
|
Parameters
|
|
19
20
|
----------
|
|
20
21
|
event_data_file : str
|
|
21
|
-
Path to the
|
|
22
|
+
Path to the event-data file.
|
|
23
|
+
array_name : str, optional
|
|
24
|
+
Name of the telescope array configuration (default is None).
|
|
22
25
|
telescope_list : list, optional
|
|
23
26
|
List of telescope IDs to filter the events (default is None).
|
|
24
27
|
"""
|
|
25
28
|
|
|
26
|
-
def __init__(self, event_data_file, telescope_list=None):
|
|
29
|
+
def __init__(self, event_data_file, array_name=None, telescope_list=None):
|
|
27
30
|
"""Initialize the LimitCalculator with the given event data file."""
|
|
28
31
|
self._logger = logging.getLogger(__name__)
|
|
29
32
|
self.event_data_file = event_data_file
|
|
33
|
+
self.array_name = array_name
|
|
30
34
|
self.telescope_list = telescope_list
|
|
31
35
|
|
|
36
|
+
self.limits = None
|
|
37
|
+
self.histograms = {}
|
|
38
|
+
self.file_info = {}
|
|
39
|
+
|
|
32
40
|
self.reader = SimtelIOEventDataReader(event_data_file, telescope_list=telescope_list)
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
|
|
42
|
+
def _prepare_limit_data(self, file_info_table):
|
|
43
|
+
"""
|
|
44
|
+
Prepare result data structure for limit calculation.
|
|
45
|
+
|
|
46
|
+
Contains both the point in parameter space and the limits derived for that point.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
file_info_table : astropy.table.Table
|
|
51
|
+
Table containing file information.
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
dict
|
|
56
|
+
Dictionary containing limits (not yet calculated) and parameter space information.
|
|
57
|
+
"""
|
|
58
|
+
self.file_info = self.reader.get_reduced_simulation_file_info(file_info_table)
|
|
59
|
+
return {
|
|
60
|
+
"primary_particle": self.file_info["primary_particle"],
|
|
61
|
+
"zenith": self.file_info["zenith"],
|
|
62
|
+
"azimuth": self.file_info["azimuth"],
|
|
63
|
+
"nsb_level": self.file_info["nsb_level"],
|
|
64
|
+
"array_name": self.array_name,
|
|
65
|
+
"telescope_ids": self.telescope_list,
|
|
66
|
+
"lower_energy_limit": None,
|
|
67
|
+
"upper_radius_limit": None,
|
|
68
|
+
"viewcone_radius": None,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
def compute_limits(self, loss_fraction):
|
|
72
|
+
"""
|
|
73
|
+
Compute the limits for energy, radial distance, and viewcone.
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
77
|
+
loss_fraction : float
|
|
78
|
+
Fraction of events to be lost.
|
|
79
|
+
|
|
80
|
+
Returns
|
|
81
|
+
-------
|
|
82
|
+
dict
|
|
83
|
+
Dictionary containing the computed limits.
|
|
84
|
+
"""
|
|
85
|
+
self._fill_histograms()
|
|
86
|
+
|
|
87
|
+
self.limits["lower_energy_limit"] = self.compute_lower_energy_limit(loss_fraction)
|
|
88
|
+
self.limits["upper_radius_limit"] = self.compute_upper_radius_limit(loss_fraction)
|
|
89
|
+
self.limits["viewcone_radius"] = self.compute_viewcone(loss_fraction)
|
|
90
|
+
|
|
91
|
+
return self.limits
|
|
92
|
+
|
|
93
|
+
def _fill_histogram_and_bin_edges(self, name, data, bins, hist1d=True):
|
|
94
|
+
"""
|
|
95
|
+
Fill histogram and bin edges and it both to histogram dictionary.
|
|
96
|
+
|
|
97
|
+
Adds histogram to existing histogram if it exists, otherwise initializes it.
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
if name in self.histograms:
|
|
101
|
+
if hist1d:
|
|
102
|
+
bins = self.histograms[f"{name}_bin_edges"]
|
|
103
|
+
hist, _ = np.histogram(data, bins=bins)
|
|
104
|
+
self.histograms[name] += hist
|
|
105
|
+
else:
|
|
106
|
+
x_bins = self.histograms[f"{name}_bin_x_edges"]
|
|
107
|
+
y_bins = self.histograms[f"{name}_bin_y_edges"]
|
|
108
|
+
hist, _, _ = np.histogram2d(data[0], data[1], bins=[x_bins, y_bins])
|
|
109
|
+
self.histograms[name] += hist
|
|
110
|
+
else:
|
|
111
|
+
if hist1d:
|
|
112
|
+
hist, bin_edges = np.histogram(data, bins=bins)
|
|
113
|
+
self.histograms[name] = hist
|
|
114
|
+
self.histograms[f"{name}_bin_edges"] = bin_edges
|
|
115
|
+
else:
|
|
116
|
+
hist, x_edges, y_edges = np.histogram2d(data[0], data[1], bins=bins)
|
|
117
|
+
self.histograms[name] = hist
|
|
118
|
+
self.histograms[f"{name}_bin_x_edges"] = x_edges
|
|
119
|
+
self.histograms[f"{name}_bin_y_edges"] = y_edges
|
|
120
|
+
|
|
121
|
+
def _fill_histograms(self):
|
|
122
|
+
"""
|
|
123
|
+
Fill histograms with event data.
|
|
124
|
+
|
|
125
|
+
Involves looping over all event data, and therefore is the slowest part of the
|
|
126
|
+
limit calculation. Adds the histograms to the histogram dictionary.
|
|
127
|
+
"""
|
|
128
|
+
for data_set in self.reader.data_sets:
|
|
129
|
+
self._logger.info(f"Reading event data from {self.event_data_file} for {data_set}")
|
|
130
|
+
file_info, _, event_data, triggered_data = self.reader.read_event_data(
|
|
131
|
+
self.event_data_file, table_name_map=data_set
|
|
132
|
+
)
|
|
133
|
+
self.limits = self.limits if self.limits else self._prepare_limit_data(file_info)
|
|
134
|
+
|
|
135
|
+
self._fill_histogram_and_bin_edges(
|
|
136
|
+
"energy", event_data.simulated_energy, self.energy_bins
|
|
137
|
+
)
|
|
138
|
+
self._fill_histogram_and_bin_edges(
|
|
139
|
+
"core_distance", event_data.core_distance_shower, self.core_distance_bins
|
|
140
|
+
)
|
|
141
|
+
self._fill_histogram_and_bin_edges(
|
|
142
|
+
"angular_distance", triggered_data.angular_distance, self.view_cone_bins
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
xy_bins = np.linspace(
|
|
146
|
+
-1.0 * self.core_distance_bins.max(),
|
|
147
|
+
self.core_distance_bins.max(),
|
|
148
|
+
len(self.core_distance_bins),
|
|
149
|
+
)
|
|
150
|
+
self._fill_histogram_and_bin_edges(
|
|
151
|
+
"shower_cores",
|
|
152
|
+
(event_data.x_core_shower, event_data.y_core_shower),
|
|
153
|
+
[xy_bins, xy_bins],
|
|
154
|
+
hist1d=False,
|
|
155
|
+
)
|
|
156
|
+
self._fill_histogram_and_bin_edges(
|
|
157
|
+
"core_vs_energy",
|
|
158
|
+
(event_data.core_distance_shower, event_data.simulated_energy),
|
|
159
|
+
[self.core_distance_bins, self.energy_bins],
|
|
160
|
+
hist1d=False,
|
|
161
|
+
)
|
|
35
162
|
|
|
36
163
|
def _compute_limits(self, hist, bin_edges, loss_fraction, limit_type="lower"):
|
|
37
164
|
"""
|
|
38
165
|
Compute the limits based on the loss fraction.
|
|
39
166
|
|
|
167
|
+
Add or subtract one bin to be on the safe side of the limit.
|
|
168
|
+
|
|
40
169
|
Parameters
|
|
41
170
|
----------
|
|
42
171
|
hist : np.ndarray
|
|
@@ -53,20 +182,25 @@ class LimitCalculator:
|
|
|
53
182
|
float
|
|
54
183
|
Bin edge value corresponding to the threshold.
|
|
55
184
|
"""
|
|
56
|
-
cumulative_sum = np.cumsum(hist) if limit_type == "upper" else np.cumsum(hist[::-1])
|
|
57
185
|
total_events = np.sum(hist)
|
|
58
186
|
threshold = (1 - loss_fraction) * total_events
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
187
|
+
if limit_type == "upper":
|
|
188
|
+
cum = np.cumsum(hist)
|
|
189
|
+
idx = np.searchsorted(cum, threshold) + 1
|
|
190
|
+
return bin_edges[min(idx, len(bin_edges) - 1)]
|
|
191
|
+
if limit_type == "lower":
|
|
192
|
+
cum = np.cumsum(hist[::-1])
|
|
193
|
+
idx = np.searchsorted(cum, threshold) + 1
|
|
194
|
+
return bin_edges[max(len(bin_edges) - 1 - idx, 0)]
|
|
195
|
+
raise ValueError("limit_type must be 'lower' or 'upper'")
|
|
62
196
|
|
|
63
197
|
@property
|
|
64
198
|
def energy_bins(self):
|
|
65
199
|
"""Return bins for the energy histogram."""
|
|
66
200
|
return np.logspace(
|
|
67
|
-
np.log10(self.
|
|
68
|
-
np.log10(self.
|
|
69
|
-
|
|
201
|
+
np.log10(self.file_info.get("energy_min", 1.0e-3 * u.TeV).to("TeV").value),
|
|
202
|
+
np.log10(self.file_info.get("energy_max", 1.0e3 * u.TeV).to("TeV").value),
|
|
203
|
+
100,
|
|
70
204
|
)
|
|
71
205
|
|
|
72
206
|
def compute_lower_energy_limit(self, loss_fraction):
|
|
@@ -83,21 +217,23 @@ class LimitCalculator:
|
|
|
83
217
|
astropy.units.Quantity
|
|
84
218
|
Lower energy limit.
|
|
85
219
|
"""
|
|
86
|
-
hist, _ = np.histogram(self.event_data.simulated_energy, bins=self.energy_bins)
|
|
87
220
|
return (
|
|
88
|
-
self._compute_limits(
|
|
221
|
+
self._compute_limits(
|
|
222
|
+
self.histograms.get("energy"), self.energy_bins, loss_fraction, limit_type="lower"
|
|
223
|
+
)
|
|
224
|
+
* u.TeV
|
|
89
225
|
)
|
|
90
226
|
|
|
91
227
|
@property
|
|
92
228
|
def core_distance_bins(self):
|
|
93
229
|
"""Return bins for the core distance histogram."""
|
|
94
230
|
return np.linspace(
|
|
95
|
-
self.
|
|
96
|
-
self.
|
|
97
|
-
|
|
231
|
+
self.file_info.get("core_scatter_min", 0.0 * u.m).to("m").value,
|
|
232
|
+
self.file_info.get("core_scatter_max", 1.0e5 * u.m).to("m").value,
|
|
233
|
+
100,
|
|
98
234
|
)
|
|
99
235
|
|
|
100
|
-
def
|
|
236
|
+
def compute_upper_radius_limit(self, loss_fraction):
|
|
101
237
|
"""
|
|
102
238
|
Compute the upper radial distance based on the event loss fraction.
|
|
103
239
|
|
|
@@ -111,9 +247,13 @@ class LimitCalculator:
|
|
|
111
247
|
astropy.units.Quantity
|
|
112
248
|
Upper radial distance in m.
|
|
113
249
|
"""
|
|
114
|
-
hist, _ = np.histogram(self.event_data.core_distance_shower, bins=self.core_distance_bins)
|
|
115
250
|
return (
|
|
116
|
-
self._compute_limits(
|
|
251
|
+
self._compute_limits(
|
|
252
|
+
self.histograms.get("core_distance"),
|
|
253
|
+
self.core_distance_bins,
|
|
254
|
+
loss_fraction,
|
|
255
|
+
limit_type="upper",
|
|
256
|
+
)
|
|
117
257
|
* u.m
|
|
118
258
|
)
|
|
119
259
|
|
|
@@ -121,9 +261,9 @@ class LimitCalculator:
|
|
|
121
261
|
def view_cone_bins(self):
|
|
122
262
|
"""Return bins for the viewcone histogram."""
|
|
123
263
|
return np.linspace(
|
|
124
|
-
self.
|
|
125
|
-
self.
|
|
126
|
-
|
|
264
|
+
self.file_info.get("viewcone_min", 0.0 * u.deg).to("deg").value,
|
|
265
|
+
self.file_info.get("viewcone_max", 20.0 * u.deg).to("deg").value,
|
|
266
|
+
100,
|
|
127
267
|
)
|
|
128
268
|
|
|
129
269
|
def compute_viewcone(self, loss_fraction):
|
|
@@ -144,33 +284,34 @@ class LimitCalculator:
|
|
|
144
284
|
astropy.units.Quantity
|
|
145
285
|
Viewcone radius in degrees.
|
|
146
286
|
"""
|
|
147
|
-
hist, _ = np.histogram(self.triggered_data.angular_distance, bins=self.view_cone_bins)
|
|
148
287
|
return (
|
|
149
|
-
self._compute_limits(
|
|
288
|
+
self._compute_limits(
|
|
289
|
+
self.histograms.get("angular_distance"),
|
|
290
|
+
self.view_cone_bins,
|
|
291
|
+
loss_fraction,
|
|
292
|
+
limit_type="upper",
|
|
293
|
+
)
|
|
150
294
|
* u.deg
|
|
151
295
|
)
|
|
152
296
|
|
|
153
|
-
def plot_data(self,
|
|
297
|
+
def plot_data(self, output_path=None):
|
|
154
298
|
"""
|
|
155
|
-
|
|
299
|
+
Histogram plotting.
|
|
156
300
|
|
|
157
301
|
Parameters
|
|
158
302
|
----------
|
|
159
|
-
lower_energy_limit: astropy.units.Quantity
|
|
160
|
-
Lower energy limit to display on plots.
|
|
161
|
-
upper_radial_distance: astropy.units.Quantity
|
|
162
|
-
Upper radial distance limit to display on plots.
|
|
163
|
-
viewcone: astropy.units.Quantity
|
|
164
|
-
Viewcone radius to display on plots.
|
|
165
303
|
output_path: Path or str, optional
|
|
166
304
|
Directory to save plots. If None, plots will be displayed.
|
|
167
305
|
"""
|
|
306
|
+
self._logger.info(f"Plotting histograms written to {output_path}")
|
|
168
307
|
event_counts = "Event Count"
|
|
169
308
|
plots = {
|
|
170
309
|
"core_vs_energy": {
|
|
171
|
-
"
|
|
172
|
-
"
|
|
173
|
-
|
|
310
|
+
"data": self.histograms.get("core_vs_energy"),
|
|
311
|
+
"bins": [
|
|
312
|
+
self.histograms.get("core_vs_energy_bin_x_edges"),
|
|
313
|
+
self.histograms.get("core_vs_energy_bin_y_edges"),
|
|
314
|
+
],
|
|
174
315
|
"plot_type": "histogram2d",
|
|
175
316
|
"plot_params": {"norm": "log", "cmap": "viridis"},
|
|
176
317
|
"labels": {
|
|
@@ -178,76 +319,89 @@ class LimitCalculator:
|
|
|
178
319
|
"y": "Energy [TeV]",
|
|
179
320
|
"title": "Triggered events: core distance vs energy",
|
|
180
321
|
},
|
|
322
|
+
"lines": {
|
|
323
|
+
"x": self.limits["upper_radius_limit"].value,
|
|
324
|
+
"y": self.limits["lower_energy_limit"].value,
|
|
325
|
+
},
|
|
181
326
|
"scales": {"y": "log"},
|
|
182
327
|
"colorbar_label": event_counts,
|
|
183
|
-
"filename": "core_vs_energy_distribution
|
|
328
|
+
"filename": "core_vs_energy_distribution",
|
|
184
329
|
},
|
|
185
330
|
"energy_distribution": {
|
|
186
|
-
"
|
|
187
|
-
"bins":
|
|
331
|
+
"data": self.histograms.get("energy"),
|
|
332
|
+
"bins": self.histograms.get("energy_bin_edges"),
|
|
188
333
|
"plot_type": "histogram",
|
|
189
|
-
"plot_params": {"
|
|
334
|
+
"plot_params": {"color": "g", "edgecolor": "g", "lw": 1},
|
|
190
335
|
"labels": {
|
|
191
336
|
"x": "Energy [TeV]",
|
|
192
337
|
"y": event_counts,
|
|
193
338
|
"title": "Triggered events: energy distribution",
|
|
194
339
|
},
|
|
195
340
|
"scales": {"x": "log", "y": "log"},
|
|
196
|
-
"lines": {"x": lower_energy_limit.value},
|
|
197
|
-
"filename": "energy_distribution
|
|
341
|
+
"lines": {"x": self.limits["lower_energy_limit"].value},
|
|
342
|
+
"filename": "energy_distribution",
|
|
198
343
|
},
|
|
199
344
|
"core_distance": {
|
|
200
|
-
"
|
|
201
|
-
"bins": self.
|
|
345
|
+
"data": self.histograms.get("core_distance"),
|
|
346
|
+
"bins": self.histograms.get("core_distance_bin_edges"),
|
|
202
347
|
"plot_type": "histogram",
|
|
203
|
-
"plot_params": {"
|
|
348
|
+
"plot_params": {"color": "g", "edgecolor": "g", "lw": 1},
|
|
204
349
|
"labels": {
|
|
205
350
|
"x": "Core Distance [m]",
|
|
206
351
|
"y": event_counts,
|
|
207
352
|
"title": "Triggered events: core distance distribution",
|
|
208
353
|
},
|
|
209
|
-
"lines": {"x":
|
|
210
|
-
"filename": "core_distance_distribution
|
|
354
|
+
"lines": {"x": self.limits["upper_radius_limit"].value},
|
|
355
|
+
"filename": "core_distance_distribution",
|
|
211
356
|
},
|
|
212
357
|
"core_xy": {
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
|
|
358
|
+
"data": self.histograms.get("shower_cores"),
|
|
359
|
+
"bins": [
|
|
360
|
+
self.histograms.get("shower_cores_bin_x_edges"),
|
|
361
|
+
self.histograms.get("shower_cores_bin_y_edges"),
|
|
362
|
+
],
|
|
216
363
|
"plot_type": "histogram2d",
|
|
217
|
-
"plot_params": {"norm": "log", "cmap": "viridis"},
|
|
364
|
+
"plot_params": {"norm": "log", "cmap": "viridis", "aspect": "equal"},
|
|
218
365
|
"labels": {
|
|
219
366
|
"x": "Core X [m]",
|
|
220
367
|
"y": "Core Y [m]",
|
|
221
368
|
"title": "Triggered events: core x vs core y",
|
|
222
369
|
},
|
|
223
370
|
"colorbar_label": event_counts,
|
|
224
|
-
"lines": {
|
|
225
|
-
|
|
371
|
+
"lines": {
|
|
372
|
+
"r": self.limits["upper_radius_limit"].value,
|
|
373
|
+
},
|
|
374
|
+
"filename": "core_xy_distribution",
|
|
226
375
|
},
|
|
227
|
-
"
|
|
228
|
-
"
|
|
229
|
-
"bins": self.
|
|
376
|
+
"angular_distance": {
|
|
377
|
+
"data": self.histograms.get("angular_distance"),
|
|
378
|
+
"bins": self.histograms.get("angular_distance_bin_edges"),
|
|
230
379
|
"plot_type": "histogram",
|
|
231
|
-
"plot_params": {"
|
|
380
|
+
"plot_params": {"color": "g", "edgecolor": "g", "lw": 1},
|
|
232
381
|
"labels": {
|
|
233
382
|
"x": "Distance to pointing direction [deg]",
|
|
234
383
|
"y": event_counts,
|
|
235
|
-
"title": "Triggered events:
|
|
384
|
+
"title": "Triggered events: angular distance distribution",
|
|
236
385
|
},
|
|
237
|
-
"lines": {"x":
|
|
238
|
-
"filename": "
|
|
386
|
+
"lines": {"x": self.limits["viewcone_radius"].value},
|
|
387
|
+
"filename": "angular_distance_distribution",
|
|
239
388
|
},
|
|
240
389
|
}
|
|
241
390
|
|
|
242
391
|
for _, plot_args in plots.items():
|
|
243
392
|
filename = plot_args.pop("filename")
|
|
393
|
+
if self.array_name:
|
|
394
|
+
if plot_args.get("labels", {}).get("title"):
|
|
395
|
+
plot_args["labels"]["title"] += f" ({self.array_name} array)"
|
|
396
|
+
filename = f"{filename}_{self.array_name}.png"
|
|
397
|
+
else:
|
|
398
|
+
filename = f"{filename}.png"
|
|
244
399
|
output_file = output_path / filename if output_path else None
|
|
245
400
|
self._create_plot(**plot_args, output_file=output_file)
|
|
246
401
|
|
|
247
402
|
def _create_plot(
|
|
248
403
|
self,
|
|
249
|
-
|
|
250
|
-
y_data=None,
|
|
404
|
+
data,
|
|
251
405
|
bins=None,
|
|
252
406
|
plot_type="histogram",
|
|
253
407
|
plot_params=None,
|
|
@@ -257,65 +411,39 @@ class LimitCalculator:
|
|
|
257
411
|
output_file=None,
|
|
258
412
|
lines=None,
|
|
259
413
|
):
|
|
260
|
-
"""
|
|
261
|
-
Create and save a plot with the given parameters.
|
|
262
|
-
|
|
263
|
-
Parameters
|
|
264
|
-
----------
|
|
265
|
-
x_data : array-like
|
|
266
|
-
Data for the x-axis or primary data for histograms.
|
|
267
|
-
y_data : array-like, optional
|
|
268
|
-
Data for the y-axis in scatter or 2D histograms.
|
|
269
|
-
bins : int, array-like, or list, optional
|
|
270
|
-
Bins specification for histograms.
|
|
271
|
-
plot_type : str, optional
|
|
272
|
-
Type of plot: 'histogram', 'histogram2d', or 'scatter'.
|
|
273
|
-
plot_params : dict, optional
|
|
274
|
-
Additional parameters to pass to the plotting function.
|
|
275
|
-
labels : dict, optional
|
|
276
|
-
Dictionary containing 'x', 'y', and 'title' labels.
|
|
277
|
-
scales : dict, optional
|
|
278
|
-
Dictionary containing 'x' and 'y' scale types ('log' or 'linear').
|
|
279
|
-
colorbar_label : str, optional
|
|
280
|
-
Label for the colorbar in 2D histograms.
|
|
281
|
-
output_file : Path, optional
|
|
282
|
-
File path to save the plot. If not provided, the plot will be displayed.
|
|
283
|
-
lines : dict, optional
|
|
284
|
-
Dictionary containing 'x' and 'y' values for reference lines.
|
|
285
|
-
|
|
286
|
-
Returns
|
|
287
|
-
-------
|
|
288
|
-
matplotlib.figure.Figure
|
|
289
|
-
The created figure object.
|
|
290
|
-
"""
|
|
291
|
-
fig = plt.figure(figsize=(8, 6))
|
|
414
|
+
"""Create and save a plot with the given parameters."""
|
|
292
415
|
plot_params = plot_params or {}
|
|
293
416
|
labels = labels or {}
|
|
294
417
|
scales = scales or {}
|
|
295
418
|
lines = lines or {}
|
|
296
419
|
|
|
420
|
+
fig, ax = plt.subplots(figsize=(8, 6))
|
|
421
|
+
|
|
297
422
|
if plot_type == "histogram":
|
|
298
|
-
plt.
|
|
423
|
+
plt.bar(bins[:-1], data, width=np.diff(bins), **plot_params)
|
|
299
424
|
elif plot_type == "histogram2d":
|
|
300
|
-
plt.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
plt.scatter(x_data, y_data, **plot_params)
|
|
425
|
+
pcm = plt.pcolormesh(
|
|
426
|
+
bins[0], bins[1], data.T, norm=LogNorm(vmin=1, vmax=data.max()), cmap="viridis"
|
|
427
|
+
)
|
|
428
|
+
plt.colorbar(pcm, label=colorbar_label)
|
|
305
429
|
|
|
306
430
|
if "x" in lines:
|
|
307
|
-
plt.axvline(lines["x"], color="r", linestyle="--")
|
|
431
|
+
plt.axvline(lines["x"], color="r", linestyle="--", linewidth=0.5)
|
|
308
432
|
if "y" in lines:
|
|
309
|
-
plt.axhline(lines["y"], color="r", linestyle="--")
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
433
|
+
plt.axhline(lines["y"], color="r", linestyle="--", linewidth=0.5)
|
|
434
|
+
if "r" in lines:
|
|
435
|
+
circle = plt.Circle(
|
|
436
|
+
(0, 0), lines["r"], color="r", fill=False, linestyle="--", linewidth=0.5
|
|
437
|
+
)
|
|
438
|
+
plt.gca().add_artist(circle)
|
|
439
|
+
|
|
440
|
+
ax.set(
|
|
441
|
+
xlabel=labels.get("x", ""),
|
|
442
|
+
ylabel=labels.get("y", ""),
|
|
443
|
+
title=labels.get("title", ""),
|
|
444
|
+
xscale=scales.get("x", "linear"),
|
|
445
|
+
yscale=scales.get("y", "linear"),
|
|
446
|
+
)
|
|
319
447
|
|
|
320
448
|
if output_file:
|
|
321
449
|
self._logger.info(f"Saving plot to {output_file}")
|