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
|
@@ -1,37 +1,88 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Handle interpolation between multiple StatisticalUncertaintyEvaluator instances."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
2
4
|
|
|
3
5
|
import astropy.units as u
|
|
4
6
|
import numpy as np
|
|
5
7
|
from scipy.interpolate import griddata
|
|
6
8
|
|
|
7
|
-
from simtools.production_configuration.
|
|
9
|
+
from simtools.production_configuration.derive_production_statistics import (
|
|
10
|
+
ProductionStatisticsDerivator,
|
|
11
|
+
)
|
|
8
12
|
|
|
9
13
|
__all__ = ["InterpolationHandler"]
|
|
10
14
|
|
|
11
15
|
|
|
12
16
|
class InterpolationHandler:
|
|
13
|
-
"""
|
|
17
|
+
"""
|
|
18
|
+
Calculate the required events for production via interpolation from a grid.
|
|
19
|
+
|
|
20
|
+
This class provides methods to interpolate production statistics across a grid of
|
|
21
|
+
parameter values (azimuth, zenith, NSB, offset) and energy.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, evaluators, metrics: dict, grid_points_production: list):
|
|
25
|
+
"""
|
|
26
|
+
Initialize the InterpolationHandler.
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
evaluators : list
|
|
31
|
+
List of StatisticalUncertaintyEvaluator instances.
|
|
32
|
+
metrics : dict
|
|
33
|
+
Dictionary of metrics to use for production statistics.
|
|
34
|
+
grid_points_production : list
|
|
35
|
+
List of grid points for interpolation, each being a dictionary with keys
|
|
36
|
+
'azimuth', 'zenith_angle', 'nsb', 'offset' etc.
|
|
37
|
+
"""
|
|
38
|
+
self._logger = logging.getLogger(__name__)
|
|
16
39
|
self.evaluators = evaluators
|
|
17
40
|
self.metrics = metrics
|
|
18
|
-
self.
|
|
41
|
+
self.grid_points_production = grid_points_production
|
|
19
42
|
|
|
43
|
+
self._initialize_derivators()
|
|
44
|
+
self._extract_grid_properties()
|
|
45
|
+
|
|
46
|
+
self.data, self.grid_points = self._build_data_array()
|
|
47
|
+
self.interpolated_production_statistics = None
|
|
48
|
+
self.interpolated_production_statistics_with_energy = None
|
|
49
|
+
self._non_flat_mask = None
|
|
50
|
+
|
|
51
|
+
def _initialize_derivators(self):
|
|
52
|
+
"""Initialize production statistics derivators for all evaluators."""
|
|
53
|
+
self.derive_production_statistics = [
|
|
54
|
+
ProductionStatisticsDerivator(e, self.metrics) for e in self.evaluators
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
self.production_statistics = [
|
|
58
|
+
derivator.derive_statistics(return_sum=False)
|
|
59
|
+
for derivator in self.derive_production_statistics
|
|
60
|
+
]
|
|
61
|
+
self.production_statistics_sum = [
|
|
62
|
+
derivator.derive_statistics(return_sum=True)
|
|
63
|
+
for derivator in self.derive_production_statistics
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
def _extract_grid_properties(self):
|
|
67
|
+
"""Extract grid properties from evaluators."""
|
|
20
68
|
self.azimuths = [e.grid_point[1].to(u.deg).value for e in self.evaluators]
|
|
21
69
|
self.zeniths = [e.grid_point[2].to(u.deg).value for e in self.evaluators]
|
|
22
70
|
self.nsbs = [e.grid_point[3] for e in self.evaluators]
|
|
23
71
|
self.offsets = [e.grid_point[4].to(u.deg).value for e in self.evaluators]
|
|
24
|
-
|
|
25
72
|
self.energy_grids = [
|
|
26
73
|
(e.data["bin_edges_low"][:-1] + e.data["bin_edges_high"][:-1]) / 2
|
|
27
74
|
for e in self.evaluators
|
|
28
75
|
]
|
|
29
|
-
self.scaled_events = [
|
|
30
|
-
scaler.scale_events(return_sum=False) for scaler in self.event_scalers
|
|
31
|
-
]
|
|
32
76
|
self.energy_thresholds = np.array([e.energy_threshold for e in self.evaluators])
|
|
33
77
|
|
|
34
|
-
|
|
78
|
+
# Check if energy grids are consistent
|
|
79
|
+
if self.energy_grids and not all(
|
|
80
|
+
np.array_equal(self.energy_grids[0], grid) for grid in self.energy_grids
|
|
81
|
+
):
|
|
82
|
+
self._logger.warning(
|
|
83
|
+
"Energy grids are not identical across evaluators. "
|
|
84
|
+
"Using the first evaluator's energy grid for interpolation."
|
|
85
|
+
)
|
|
35
86
|
|
|
36
87
|
def _build_data_array(self):
|
|
37
88
|
"""
|
|
@@ -44,148 +95,304 @@ class InterpolationHandler:
|
|
|
44
95
|
np.ndarray
|
|
45
96
|
The corresponding grid points.
|
|
46
97
|
"""
|
|
47
|
-
|
|
98
|
+
if not self.evaluators:
|
|
99
|
+
return np.array([]), np.array([])
|
|
100
|
+
|
|
48
101
|
flat_data_list = []
|
|
49
102
|
flat_grid_points = []
|
|
50
103
|
|
|
51
|
-
for
|
|
52
|
-
self.
|
|
104
|
+
for i, (energy_grid, production_statistics) in enumerate(
|
|
105
|
+
zip(self.energy_grids, self.production_statistics)
|
|
53
106
|
):
|
|
54
|
-
az =
|
|
55
|
-
zen =
|
|
56
|
-
nsb =
|
|
57
|
-
offset =
|
|
107
|
+
az = self.azimuths[i]
|
|
108
|
+
zen = self.zeniths[i]
|
|
109
|
+
nsb = self.nsbs[i]
|
|
110
|
+
offset = self.offsets[i]
|
|
111
|
+
|
|
112
|
+
az_array = np.full(len(energy_grid), az)
|
|
113
|
+
zen_array = np.full(len(energy_grid), zen)
|
|
114
|
+
nsb_array = np.full(len(energy_grid), nsb)
|
|
115
|
+
offset_array = np.full(len(energy_grid), offset)
|
|
116
|
+
|
|
117
|
+
grid_points = np.column_stack(
|
|
118
|
+
[energy_grid.to(u.TeV).value, az_array, zen_array, nsb_array, offset_array]
|
|
119
|
+
)
|
|
58
120
|
|
|
59
|
-
# Combine grid points and data
|
|
60
|
-
grid_points = np.column_stack([energy_grid.to(u.TeV).value, az, zen, nsb, offset])
|
|
61
121
|
flat_grid_points.append(grid_points)
|
|
62
|
-
flat_data_list.append(
|
|
122
|
+
flat_data_list.append(production_statistics)
|
|
63
123
|
|
|
64
|
-
# Flatten the list and convert to numpy arrays
|
|
65
124
|
flat_grid_points = np.vstack(flat_grid_points)
|
|
66
125
|
flat_data = np.hstack(flat_data_list)
|
|
67
126
|
|
|
68
|
-
# Sort the grid points and corresponding data by energy
|
|
69
127
|
sorted_indices = np.argsort(flat_grid_points[:, 0])
|
|
70
128
|
sorted_grid_points = flat_grid_points[sorted_indices]
|
|
71
129
|
sorted_data = flat_data[sorted_indices]
|
|
72
130
|
|
|
73
131
|
return sorted_data, sorted_grid_points
|
|
74
132
|
|
|
75
|
-
def _remove_flat_dimensions(self, grid_points):
|
|
76
|
-
"""
|
|
133
|
+
def _remove_flat_dimensions(self, grid_points, threshold=1e-6):
|
|
134
|
+
"""
|
|
135
|
+
Identify and remove flat dimensions (dimensions with no variance).
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
grid_points : np.ndarray
|
|
140
|
+
Grid points to analyze.
|
|
141
|
+
threshold : float, optional
|
|
142
|
+
Threshold for determining flatness, by default 1e-6
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
tuple
|
|
147
|
+
(reduced_grid_points, non_flat_mask)
|
|
148
|
+
"""
|
|
149
|
+
if grid_points.size == 0:
|
|
150
|
+
return grid_points, np.array([], dtype=bool)
|
|
151
|
+
|
|
77
152
|
variance = np.var(grid_points, axis=0)
|
|
78
|
-
non_flat_mask = variance >
|
|
153
|
+
non_flat_mask = variance > threshold
|
|
154
|
+
|
|
155
|
+
if not np.any(non_flat_mask):
|
|
156
|
+
self._logger.warning(
|
|
157
|
+
"All dimensions are flat. Keeping all dimensions for interpolation."
|
|
158
|
+
)
|
|
159
|
+
return grid_points, np.ones_like(variance, dtype=bool)
|
|
160
|
+
|
|
79
161
|
reduced_grid_points = grid_points[:, non_flat_mask]
|
|
80
162
|
return reduced_grid_points, non_flat_mask
|
|
81
163
|
|
|
82
|
-
def
|
|
164
|
+
def build_grid_points_no_energy(self):
|
|
165
|
+
"""
|
|
166
|
+
Build grid points without energy dimension.
|
|
167
|
+
|
|
168
|
+
Returns
|
|
169
|
+
-------
|
|
170
|
+
tuple
|
|
171
|
+
(production_statistics, grid_points_no_energy)
|
|
172
|
+
"""
|
|
173
|
+
if not self.evaluators:
|
|
174
|
+
self._logger.error("No evaluators available for grid point building.")
|
|
175
|
+
return np.array([]), np.array([])
|
|
176
|
+
|
|
177
|
+
flat_data_list = []
|
|
178
|
+
flat_grid_points = []
|
|
179
|
+
|
|
180
|
+
for i, production_statistics_sum in enumerate(self.production_statistics_sum):
|
|
181
|
+
az = self.azimuths[i]
|
|
182
|
+
zen = self.zeniths[i]
|
|
183
|
+
nsb = self.nsbs[i]
|
|
184
|
+
offset = self.offsets[i]
|
|
185
|
+
|
|
186
|
+
flat_data_list.append(float(production_statistics_sum.value))
|
|
187
|
+
|
|
188
|
+
grid_point = np.array([[az, zen, nsb, offset]])
|
|
189
|
+
flat_grid_points.append(grid_point)
|
|
190
|
+
|
|
191
|
+
flat_grid_points = np.vstack(flat_grid_points)
|
|
192
|
+
return flat_data_list, flat_grid_points
|
|
193
|
+
|
|
194
|
+
def _prepare_energy_independent_data(self):
|
|
195
|
+
"""
|
|
196
|
+
Prepare data for energy-independent interpolation.
|
|
197
|
+
|
|
198
|
+
Returns
|
|
199
|
+
-------
|
|
200
|
+
tuple
|
|
201
|
+
(production_statistic, grid_points_no_energy)
|
|
83
202
|
"""
|
|
84
|
-
|
|
203
|
+
production_statistic, grid_points_no_energy = self.build_grid_points_no_energy()
|
|
204
|
+
production_statistic = np.array(production_statistic, dtype=float)
|
|
205
|
+
grid_points_no_energy, non_flat_mask = self._remove_flat_dimensions(grid_points_no_energy)
|
|
206
|
+
|
|
207
|
+
self._non_flat_mask = non_flat_mask # Store for later use
|
|
208
|
+
return production_statistic, grid_points_no_energy
|
|
209
|
+
|
|
210
|
+
def _prepare_production_grid_points(self):
|
|
211
|
+
"""
|
|
212
|
+
Convert grid_points_production to a format suitable for interpolation.
|
|
213
|
+
|
|
214
|
+
Returns
|
|
215
|
+
-------
|
|
216
|
+
np.ndarray
|
|
217
|
+
Reduced production grid points.
|
|
218
|
+
"""
|
|
219
|
+
production_grid_points = []
|
|
220
|
+
|
|
221
|
+
for point in self.grid_points_production:
|
|
222
|
+
production_grid_points.append(
|
|
223
|
+
[
|
|
224
|
+
point["azimuth"]["value"],
|
|
225
|
+
point["zenith_angle"]["value"],
|
|
226
|
+
point["nsb"]["value"],
|
|
227
|
+
point["offset"]["value"],
|
|
228
|
+
]
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
production_grid_points = np.array(production_grid_points)
|
|
232
|
+
|
|
233
|
+
return production_grid_points[:, self._non_flat_mask]
|
|
234
|
+
|
|
235
|
+
def _perform_interpolation(self, grid_points, values, query_points, method="linear"):
|
|
236
|
+
"""
|
|
237
|
+
Perform interpolation using griddata.
|
|
85
238
|
|
|
86
239
|
Parameters
|
|
87
240
|
----------
|
|
241
|
+
grid_points : np.ndarray
|
|
242
|
+
Grid points for interpolation.
|
|
243
|
+
values : np.ndarray
|
|
244
|
+
Values at the grid points.
|
|
88
245
|
query_points : np.ndarray
|
|
89
|
-
|
|
90
|
-
|
|
246
|
+
Query points for interpolation.
|
|
247
|
+
method : str, optional
|
|
248
|
+
Interpolation method, by default "linear".
|
|
91
249
|
|
|
92
250
|
Returns
|
|
93
251
|
-------
|
|
94
252
|
np.ndarray
|
|
95
|
-
Interpolated values
|
|
253
|
+
Interpolated values.
|
|
96
254
|
"""
|
|
97
|
-
|
|
98
|
-
|
|
255
|
+
self._logger.debug(f"Grid points shape: {grid_points.shape}")
|
|
256
|
+
self._logger.debug(f"Values shape: {values.shape}")
|
|
257
|
+
self._logger.debug(f"Query points shape: {query_points.shape}")
|
|
99
258
|
|
|
100
|
-
# Interpolate using the reduced dimensions
|
|
101
259
|
return griddata(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
method=
|
|
260
|
+
grid_points,
|
|
261
|
+
values,
|
|
262
|
+
query_points,
|
|
263
|
+
method=method,
|
|
106
264
|
fill_value=np.nan,
|
|
107
265
|
rescale=True,
|
|
108
266
|
)
|
|
109
267
|
|
|
110
|
-
def
|
|
268
|
+
def _perform_interpolation_with_energy(self):
|
|
111
269
|
"""
|
|
112
|
-
|
|
270
|
+
Perform energy-dependent interpolation.
|
|
113
271
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
272
|
+
Returns
|
|
273
|
+
-------
|
|
274
|
+
np.ndarray
|
|
275
|
+
Energy-dependent interpolated values.
|
|
276
|
+
"""
|
|
277
|
+
# Get grid points with energy dimension
|
|
278
|
+
grid_points_energy = self.grid_points
|
|
279
|
+
grid_points_energy, _ = self._remove_flat_dimensions(grid_points_energy)
|
|
280
|
+
|
|
281
|
+
# Build energy query grid
|
|
282
|
+
reduced_production_grid_points = self._prepare_production_grid_points()
|
|
283
|
+
energy_grid = self.energy_grids[0] if self.energy_grids else []
|
|
284
|
+
|
|
285
|
+
energy_query_grid = []
|
|
286
|
+
for energy in energy_grid:
|
|
287
|
+
for grid_point in reduced_production_grid_points:
|
|
288
|
+
energy_query_grid.append(np.hstack([energy.to(u.TeV).value, grid_point]))
|
|
289
|
+
|
|
290
|
+
energy_query_grid = np.array(energy_query_grid)
|
|
291
|
+
|
|
292
|
+
self._logger.debug(f"Grid points with energy shape: {grid_points_energy.shape}")
|
|
293
|
+
self._logger.debug(f"Data shape: {self.data.shape}")
|
|
294
|
+
self._logger.debug(f"Energy query grid shape: {energy_query_grid.shape}")
|
|
295
|
+
|
|
296
|
+
interpolated_values = self._perform_interpolation(
|
|
297
|
+
grid_points_energy, self.data, energy_query_grid
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
reshaped = interpolated_values.reshape(
|
|
301
|
+
len(reduced_production_grid_points), len(energy_grid)
|
|
302
|
+
)
|
|
303
|
+
return np.array([reshaped])
|
|
304
|
+
|
|
305
|
+
def interpolate(self) -> np.ndarray:
|
|
306
|
+
"""
|
|
307
|
+
Interpolate production statistics at the grid points specified in grid_points_production.
|
|
308
|
+
|
|
309
|
+
This method performs two types of interpolation:
|
|
310
|
+
1. Energy-independent interpolation using the sum of production statistics
|
|
311
|
+
2. Energy-dependent interpolation for each energy bin
|
|
118
312
|
|
|
119
313
|
Returns
|
|
120
314
|
-------
|
|
121
|
-
|
|
122
|
-
Interpolated
|
|
315
|
+
np.ndarray
|
|
316
|
+
Interpolated values at the query points.
|
|
123
317
|
"""
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
for e in self.evaluators:
|
|
128
|
-
az = e.grid_point[1].to(u.deg).value
|
|
129
|
-
zen = e.grid_point[2].to(u.deg).value
|
|
130
|
-
nsb = e.grid_point[3]
|
|
131
|
-
offset = e.grid_point[4].to(u.deg).value
|
|
132
|
-
grid_point = np.array([az, zen, nsb, offset])
|
|
133
|
-
flat_grid_points.append(grid_point)
|
|
134
|
-
flat_energy_thresholds.append(e.energy_threshold)
|
|
318
|
+
if not self.evaluators:
|
|
319
|
+
self._logger.error("No evaluators available for interpolation.")
|
|
320
|
+
return np.array([])
|
|
135
321
|
|
|
136
|
-
|
|
137
|
-
|
|
322
|
+
# Energy-independent interpolation
|
|
323
|
+
production_statistic, grid_points_no_energy = self._prepare_energy_independent_data()
|
|
324
|
+
reduced_production_grid_points = self._prepare_production_grid_points()
|
|
138
325
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
326
|
+
self.interpolated_production_statistics = self._perform_interpolation(
|
|
327
|
+
grid_points_no_energy, production_statistic, reduced_production_grid_points
|
|
328
|
+
)
|
|
142
329
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
reduced_query_point,
|
|
147
|
-
method="linear",
|
|
148
|
-
fill_value=np.nan,
|
|
149
|
-
rescale=False,
|
|
330
|
+
# Energy-dependent interpolation
|
|
331
|
+
self.interpolated_production_statistics_with_energy = (
|
|
332
|
+
self._perform_interpolation_with_energy()
|
|
150
333
|
)
|
|
151
334
|
|
|
152
|
-
return
|
|
335
|
+
return self.interpolated_production_statistics
|
|
153
336
|
|
|
154
|
-
def plot_comparison(self,
|
|
337
|
+
def plot_comparison(self, grid_point_index=0):
|
|
155
338
|
"""
|
|
156
|
-
Plot a comparison between
|
|
339
|
+
Plot a comparison between interpolated production statistics and reconstructed events.
|
|
157
340
|
|
|
158
341
|
Parameters
|
|
159
342
|
----------
|
|
160
|
-
|
|
161
|
-
|
|
343
|
+
grid_point_index : int, optional
|
|
344
|
+
Index of the grid point to plot, by default 0
|
|
345
|
+
|
|
346
|
+
Returns
|
|
347
|
+
-------
|
|
348
|
+
matplotlib.axes.Axes
|
|
349
|
+
The Axes object containing the plot.
|
|
162
350
|
"""
|
|
163
|
-
import matplotlib.pyplot as plt # pylint: disable=
|
|
351
|
+
import matplotlib.pyplot as plt # pylint: disable=C0415
|
|
352
|
+
|
|
353
|
+
if not self.evaluators:
|
|
354
|
+
self._logger.error("No evaluators available for plotting.")
|
|
355
|
+
_, ax = plt.subplots()
|
|
356
|
+
ax.text(0.5, 0.5, "No data available", ha="center", va="center")
|
|
357
|
+
return ax
|
|
358
|
+
|
|
359
|
+
# Use first evaluator for energy bins
|
|
360
|
+
bin_edges_low = self.evaluators[0].data["bin_edges_low"][:-1]
|
|
361
|
+
bin_edges_high = self.evaluators[0].data["bin_edges_high"][:-1]
|
|
362
|
+
midpoints = (bin_edges_low + bin_edges_high) / 2
|
|
363
|
+
|
|
364
|
+
if (
|
|
365
|
+
self.interpolated_production_statistics_with_energy is None
|
|
366
|
+
or len(self.interpolated_production_statistics_with_energy) == 0
|
|
367
|
+
or len(self.interpolated_production_statistics_with_energy[0]) <= grid_point_index
|
|
368
|
+
):
|
|
369
|
+
self._logger.warning(
|
|
370
|
+
f"Invalid grid point index {grid_point_index}. Using index 0 instead."
|
|
371
|
+
)
|
|
372
|
+
grid_point_index = 0
|
|
164
373
|
|
|
165
|
-
|
|
374
|
+
_, ax = plt.subplots()
|
|
166
375
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
np.full_like(midpoints, evaluator.grid_point[4]),
|
|
376
|
+
if (
|
|
377
|
+
self.interpolated_production_statistics_with_energy is not None
|
|
378
|
+
and len(self.interpolated_production_statistics_with_energy) > 0
|
|
379
|
+
):
|
|
380
|
+
interpolated_stats = self.interpolated_production_statistics_with_energy[0][
|
|
381
|
+
grid_point_index
|
|
174
382
|
]
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
self.interpolate(self.grid_points)
|
|
178
|
-
|
|
179
|
-
plt.plot(midpoints, evaluator.scaled_events, label="Scaled")
|
|
383
|
+
ax.plot(midpoints, interpolated_stats, label="Interpolated Production Statistics")
|
|
180
384
|
|
|
181
385
|
reconstructed_event_histogram, _ = np.histogram(
|
|
182
|
-
|
|
386
|
+
self.evaluators[0].data["event_energies_reco"],
|
|
387
|
+
bins=self.evaluators[0].data["bin_edges_low"],
|
|
183
388
|
)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
389
|
+
ax.plot(midpoints, reconstructed_event_histogram, label="Reconstructed Events")
|
|
390
|
+
|
|
391
|
+
ax.legend()
|
|
392
|
+
ax.set_xscale("log")
|
|
393
|
+
ax.set_yscale("log")
|
|
394
|
+
ax.set_xlabel("Energy (TeV)")
|
|
395
|
+
ax.set_ylabel("Event Count")
|
|
396
|
+
ax.set_title("Comparison of Interpolated and Reconstructed Events")
|
|
397
|
+
|
|
398
|
+
return ax
|
|
@@ -9,7 +9,7 @@ from astropy.table import QTable, Table
|
|
|
9
9
|
import simtools.data_model.model_data_writer as writer
|
|
10
10
|
import simtools.utils.general as gen
|
|
11
11
|
from simtools.data_model.metadata_collector import MetadataCollector
|
|
12
|
-
from simtools.model.
|
|
12
|
+
from simtools.model.model_utils import initialize_simulation_models
|
|
13
13
|
from simtools.ray_tracing.ray_tracing import RayTracing
|
|
14
14
|
|
|
15
15
|
|
|
@@ -38,7 +38,7 @@ class MirrorPanelPSF:
|
|
|
38
38
|
self._logger.debug("Initializing MirrorPanelPSF")
|
|
39
39
|
|
|
40
40
|
self.args_dict = args_dict
|
|
41
|
-
self.telescope_model = self._define_telescope_model(label, db_config)
|
|
41
|
+
self.telescope_model, self.site_model = self._define_telescope_model(label, db_config)
|
|
42
42
|
|
|
43
43
|
if self.args_dict["test"]:
|
|
44
44
|
self.args_dict["number_of_mirrors_to_test"] = 2
|
|
@@ -63,37 +63,32 @@ class MirrorPanelPSF:
|
|
|
63
63
|
This includes updating the configuration with mirror list and/or random focal length given
|
|
64
64
|
as input.
|
|
65
65
|
|
|
66
|
-
Attributes
|
|
67
|
-
----------
|
|
68
|
-
label: str
|
|
69
|
-
Application label.
|
|
70
|
-
db_config:
|
|
71
|
-
Dictionary with database configuration.
|
|
72
|
-
|
|
73
66
|
Returns
|
|
74
67
|
-------
|
|
75
|
-
tel TelescopeModel
|
|
76
|
-
telescope model
|
|
77
|
-
|
|
68
|
+
tel : TelescopeModel
|
|
69
|
+
The telescope model.
|
|
70
|
+
site_model : SiteModel
|
|
71
|
+
The site model.
|
|
78
72
|
"""
|
|
79
|
-
|
|
73
|
+
tel_model, site_model = initialize_simulation_models(
|
|
74
|
+
label=label,
|
|
75
|
+
db_config=db_config,
|
|
80
76
|
site=self.args_dict["site"],
|
|
81
77
|
telescope_name=self.args_dict["telescope"],
|
|
82
78
|
model_version=self.args_dict["model_version"],
|
|
83
|
-
mongo_db_config=db_config,
|
|
84
|
-
label=label,
|
|
85
79
|
)
|
|
86
80
|
if self.args_dict["mirror_list"] is not None:
|
|
87
81
|
mirror_list_file = gen.find_file(
|
|
88
82
|
name=self.args_dict["mirror_list"], loc=self.args_dict["model_path"]
|
|
89
83
|
)
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
tel_model.change_parameter("mirror_list", self.args_dict["mirror_list"])
|
|
85
|
+
tel_model.export_parameter_file("mirror_list", mirror_list_file)
|
|
92
86
|
if self.args_dict["random_focal_length"] is not None:
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
tel_model.change_parameter(
|
|
88
|
+
"random_focal_length", str(self.args_dict["random_focal_length"])
|
|
89
|
+
)
|
|
95
90
|
|
|
96
|
-
return
|
|
91
|
+
return tel_model, site_model
|
|
97
92
|
|
|
98
93
|
def _get_psf_containment(self):
|
|
99
94
|
"""Read measured single-mirror point-spread function from file and return mean and sigma."""
|
|
@@ -229,6 +224,7 @@ class MirrorPanelPSF:
|
|
|
229
224
|
self.telescope_model.change_parameter("mirror_reflection_random_angle", rnda)
|
|
230
225
|
ray = RayTracing(
|
|
231
226
|
telescope_model=self.telescope_model,
|
|
227
|
+
site_model=self.site_model,
|
|
232
228
|
simtel_path=self.args_dict.get("simtel_path", None),
|
|
233
229
|
single_mirror_mode=True,
|
|
234
230
|
mirror_numbers=(
|
|
@@ -91,7 +91,7 @@ class PSFImage:
|
|
|
91
91
|
|
|
92
92
|
def _process_simtel_file_using_rx(self, photon_file):
|
|
93
93
|
"""
|
|
94
|
-
Process a
|
|
94
|
+
Process a sim_telarray file with photon lists using the RX method.
|
|
95
95
|
|
|
96
96
|
Parameters
|
|
97
97
|
----------
|
|
@@ -152,7 +152,7 @@ class PSFImage:
|
|
|
152
152
|
self._process_simtel_line(line)
|
|
153
153
|
|
|
154
154
|
if not self._is_photon_positions_ok():
|
|
155
|
-
msg = "Problems reading
|
|
155
|
+
msg = "Problems reading sim_telarray file - invalid data"
|
|
156
156
|
self._logger.error(msg)
|
|
157
157
|
raise RuntimeError(msg)
|
|
158
158
|
|
|
@@ -33,6 +33,8 @@ class RayTracing:
|
|
|
33
33
|
----------
|
|
34
34
|
telescope_model: TelescopeModel
|
|
35
35
|
telescope model
|
|
36
|
+
site_model: SiteModel
|
|
37
|
+
site model
|
|
36
38
|
simtel_path: str (or Path)
|
|
37
39
|
Location of sim_telarray installation.
|
|
38
40
|
label: str
|
|
@@ -61,6 +63,7 @@ class RayTracing:
|
|
|
61
63
|
def __init__(
|
|
62
64
|
self,
|
|
63
65
|
telescope_model,
|
|
66
|
+
site_model,
|
|
64
67
|
simtel_path,
|
|
65
68
|
label=None,
|
|
66
69
|
zenith_angle=20.0 * u.deg,
|
|
@@ -77,7 +80,7 @@ class RayTracing:
|
|
|
77
80
|
self.simtel_path = Path(simtel_path)
|
|
78
81
|
self._io_handler = io_handler.IOHandler()
|
|
79
82
|
|
|
80
|
-
self.telescope_model = telescope_model
|
|
83
|
+
self.telescope_model, self.site_model = telescope_model, site_model
|
|
81
84
|
self.label = label if label is not None else self.telescope_model.label
|
|
82
85
|
|
|
83
86
|
self.zenith_angle = zenith_angle.to("deg").value
|
|
@@ -86,11 +89,11 @@ class RayTracing:
|
|
|
86
89
|
self.use_random_focal_length = use_random_focal_length
|
|
87
90
|
self.mirrors = self._initialize_mirror_configuration(source_distance, mirror_numbers)
|
|
88
91
|
self.output_directory = self._io_handler.get_output_directory(
|
|
89
|
-
label=self.label, sub_dir="
|
|
92
|
+
label=self.label, sub_dir="ray_tracing"
|
|
90
93
|
)
|
|
91
94
|
self.output_directory.joinpath("results").mkdir(parents=True, exist_ok=True)
|
|
92
95
|
self._file_results = self.output_directory.joinpath("results").joinpath(
|
|
93
|
-
self._generate_file_name(file_type="
|
|
96
|
+
self._generate_file_name(file_type="ray_tracing", suffix=".ecsv")
|
|
94
97
|
)
|
|
95
98
|
self._psf_images = {}
|
|
96
99
|
self._results = None
|
|
@@ -211,6 +214,7 @@ class RayTracing:
|
|
|
211
214
|
simtel = SimulatorRayTracing(
|
|
212
215
|
simtel_path=self.simtel_path,
|
|
213
216
|
telescope_model=self.telescope_model,
|
|
217
|
+
site_model=self.site_model,
|
|
214
218
|
test=test,
|
|
215
219
|
config_data={
|
|
216
220
|
"zenith_angle": self.zenith_angle,
|
|
@@ -509,7 +513,7 @@ class RayTracing:
|
|
|
509
513
|
|
|
510
514
|
if save:
|
|
511
515
|
plot_file_name = self._generate_file_name(
|
|
512
|
-
file_type="
|
|
516
|
+
file_type="ray_tracing",
|
|
513
517
|
suffix=".pdf",
|
|
514
518
|
extra_label=key,
|
|
515
519
|
)
|
|
@@ -520,7 +524,7 @@ class RayTracing:
|
|
|
520
524
|
|
|
521
525
|
for off_axis_key, image in self._psf_images.items():
|
|
522
526
|
image_file_name = self._generate_file_name(
|
|
523
|
-
file_type="
|
|
527
|
+
file_type="ray_tracing",
|
|
524
528
|
off_axis_angle=off_axis_key,
|
|
525
529
|
suffix=".pdf",
|
|
526
530
|
extra_label=f"image_{key}",
|
|
@@ -530,7 +534,7 @@ class RayTracing:
|
|
|
530
534
|
image.plot_image(file_name=image_file)
|
|
531
535
|
|
|
532
536
|
image_cumulative_file_name = self._generate_file_name(
|
|
533
|
-
file_type="
|
|
537
|
+
file_type="ray_tracing",
|
|
534
538
|
off_axis_angle=off_axis_key,
|
|
535
539
|
suffix=".pdf",
|
|
536
540
|
extra_label=f"cumulative_psf_{key}",
|
|
@@ -632,8 +636,9 @@ class RayTracing:
|
|
|
632
636
|
self, file_type, suffix, off_axis_angle=None, mirror_number=None, extra_label=None
|
|
633
637
|
):
|
|
634
638
|
"""Generate file name for output files."""
|
|
639
|
+
file_type_prefix = file_type if file_type == "ray_tracing" else f"ray_tracing_{file_type}"
|
|
635
640
|
return names.generate_file_name(
|
|
636
|
-
file_type=
|
|
641
|
+
file_type=file_type_prefix,
|
|
637
642
|
suffix=suffix,
|
|
638
643
|
site=self.telescope_model.site,
|
|
639
644
|
telescope_model_name=self.telescope_model.name,
|