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
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
"""Retrieve, merge, and write layout dictionaries."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import simtools.utils.general as gen
|
|
7
|
+
from simtools.data_model import data_reader
|
|
8
|
+
from simtools.data_model.metadata_collector import MetadataCollector
|
|
9
|
+
from simtools.data_model.model_data_writer import ModelDataWriter
|
|
10
|
+
from simtools.io_operations import io_handler
|
|
11
|
+
from simtools.model.array_model import ArrayModel
|
|
12
|
+
from simtools.model.site_model import SiteModel
|
|
13
|
+
from simtools.utils import names
|
|
14
|
+
|
|
15
|
+
_logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def retrieve_ctao_array_layouts(site, repository_url, branch_name="main"):
|
|
19
|
+
"""
|
|
20
|
+
Retrieve array layouts from CTAO common identifiers repository.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
site : str
|
|
25
|
+
Site identifier.
|
|
26
|
+
repository_url : str
|
|
27
|
+
URL or path to CTAO common identifiers
|
|
28
|
+
branch_name : str
|
|
29
|
+
Repository branch to use for CTAO common identifiers.
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
dict
|
|
34
|
+
Array layouts for all CTAO sites.
|
|
35
|
+
"""
|
|
36
|
+
_logger.info(f"Retrieving array layouts from {repository_url} on branch {branch_name}.")
|
|
37
|
+
|
|
38
|
+
if gen.is_url(repository_url):
|
|
39
|
+
array_element_ids = gen.collect_data_from_http(
|
|
40
|
+
url=f"{repository_url}/{branch_name}/array-element-ids.json"
|
|
41
|
+
)
|
|
42
|
+
sub_arrays = gen.collect_data_from_http(
|
|
43
|
+
url=f"{repository_url}/{branch_name}/subarray-ids.json"
|
|
44
|
+
)
|
|
45
|
+
else:
|
|
46
|
+
array_element_ids = gen.collect_data_from_file(
|
|
47
|
+
Path(repository_url) / "array-element-ids.json"
|
|
48
|
+
)
|
|
49
|
+
sub_arrays = gen.collect_data_from_file(Path(repository_url) / "subarray-ids.json")
|
|
50
|
+
|
|
51
|
+
return _get_ctao_layouts_per_site(site, sub_arrays, array_element_ids)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _get_ctao_layouts_per_site(site, sub_arrays, array_element_ids):
|
|
55
|
+
"""
|
|
56
|
+
Get array layouts for CTAO sites.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
site : str
|
|
61
|
+
Site identifier.
|
|
62
|
+
sub_arrays : dict
|
|
63
|
+
Sub-array definitions.
|
|
64
|
+
array_element_ids : dict
|
|
65
|
+
Array element definitions.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
dict
|
|
70
|
+
Array layouts for CTAO sites.
|
|
71
|
+
"""
|
|
72
|
+
layouts_per_site = []
|
|
73
|
+
|
|
74
|
+
for array in sub_arrays.get("subarrays", []):
|
|
75
|
+
elements = []
|
|
76
|
+
for ids in array.get("array_element_ids", []):
|
|
77
|
+
element_name = _get_ctao_array_element_name(ids, array_element_ids)
|
|
78
|
+
if names.get_site_from_array_element_name(element_name) != site:
|
|
79
|
+
break
|
|
80
|
+
elements.append(element_name)
|
|
81
|
+
if len(elements) > 0:
|
|
82
|
+
array_layout = {
|
|
83
|
+
"name": array.get("name"),
|
|
84
|
+
"elements": elements,
|
|
85
|
+
}
|
|
86
|
+
layouts_per_site.append(array_layout)
|
|
87
|
+
|
|
88
|
+
_logger.info(f"CTAO array layout definition: {layouts_per_site}")
|
|
89
|
+
return layouts_per_site
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _get_ctao_array_element_name(ids, array_element_ids):
|
|
93
|
+
"""Return array element name for common identifier."""
|
|
94
|
+
for element in array_element_ids.get("array_elements", []):
|
|
95
|
+
if element.get("id") == ids:
|
|
96
|
+
return element.get("name")
|
|
97
|
+
return None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def merge_array_layouts(layouts_1, layouts_2):
|
|
101
|
+
"""
|
|
102
|
+
Compare two array layout dictionaries and merge them.
|
|
103
|
+
|
|
104
|
+
Parameters
|
|
105
|
+
----------
|
|
106
|
+
layouts_1 : dict
|
|
107
|
+
Array layout dictionary 1.
|
|
108
|
+
layouts_2 : dict
|
|
109
|
+
Array layout dictionary 2.
|
|
110
|
+
|
|
111
|
+
Returns
|
|
112
|
+
-------
|
|
113
|
+
dict
|
|
114
|
+
Merged array layout dictionary based on layout_1.
|
|
115
|
+
"""
|
|
116
|
+
merged_layout = layouts_1
|
|
117
|
+
for layout_2 in layouts_2:
|
|
118
|
+
layout_found = False
|
|
119
|
+
for layout_1 in layouts_1.get("value", {}):
|
|
120
|
+
if sorted(layout_1["elements"]) == sorted(layout_2["elements"]):
|
|
121
|
+
print(
|
|
122
|
+
f"Equal telescope list: simtools '{layout_1['name']}' "
|
|
123
|
+
f"and CTAO '{layout_2['name']}'"
|
|
124
|
+
)
|
|
125
|
+
layout_1["name"] = layout_2["name"]
|
|
126
|
+
layout_found = True
|
|
127
|
+
if not layout_found:
|
|
128
|
+
merged_layout["value"].append(
|
|
129
|
+
{
|
|
130
|
+
"name": layout_2["name"],
|
|
131
|
+
"elements": layout_2["elements"],
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
_logger.info(f"Adding {layout_2['name']} with {layout_2['elements']}")
|
|
135
|
+
return merged_layout
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def write_array_layouts(array_layouts, args_dict, db_config):
|
|
139
|
+
"""
|
|
140
|
+
Write array layouts as model parameter.
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
args_dict : dict
|
|
145
|
+
Command line arguments.
|
|
146
|
+
array_layouts : dict
|
|
147
|
+
Array layouts to be written.
|
|
148
|
+
db_config : dict
|
|
149
|
+
Database configuration.
|
|
150
|
+
"""
|
|
151
|
+
site = args_dict.get("site") or array_layouts.get("site")
|
|
152
|
+
_logger.info(f"Writing updated array layouts to the database for site {site}.")
|
|
153
|
+
|
|
154
|
+
io_handler_instance = io_handler.IOHandler()
|
|
155
|
+
io_handler_instance.set_paths(
|
|
156
|
+
output_path=args_dict["output_path"],
|
|
157
|
+
use_plain_output_path=args_dict["use_plain_output_path"],
|
|
158
|
+
)
|
|
159
|
+
output_file = io_handler_instance.get_output_file(
|
|
160
|
+
f"array-layouts-{args_dict['updated_parameter_version']}.json"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
ModelDataWriter.dump_model_parameter(
|
|
164
|
+
parameter_name="array_layouts",
|
|
165
|
+
value=array_layouts["value"],
|
|
166
|
+
instrument=site,
|
|
167
|
+
parameter_version=args_dict.get("updated_parameter_version"),
|
|
168
|
+
output_file=output_file,
|
|
169
|
+
use_plain_output_path=args_dict["use_plain_output_path"],
|
|
170
|
+
db_config=db_config,
|
|
171
|
+
)
|
|
172
|
+
MetadataCollector.dump(
|
|
173
|
+
args_dict,
|
|
174
|
+
output_file,
|
|
175
|
+
add_activity_name=True,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def validate_array_layouts_with_db(production_table, array_layouts):
|
|
180
|
+
"""
|
|
181
|
+
Validate array layouts against the production table in the database.
|
|
182
|
+
|
|
183
|
+
Confirm that every telescope defined in the array layouts exist in the
|
|
184
|
+
production table.
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
production_table : dict
|
|
189
|
+
Production table from the database.
|
|
190
|
+
array_layouts : dict
|
|
191
|
+
Array layouts to be validated.
|
|
192
|
+
|
|
193
|
+
Returns
|
|
194
|
+
-------
|
|
195
|
+
dict
|
|
196
|
+
Validated array layouts.
|
|
197
|
+
"""
|
|
198
|
+
db_elements = set(production_table.get("parameters", {}).keys())
|
|
199
|
+
|
|
200
|
+
invalid_array_elements = [
|
|
201
|
+
e
|
|
202
|
+
for layout in array_layouts.get("value", [])
|
|
203
|
+
for e in layout.get("elements", [])
|
|
204
|
+
if e not in db_elements
|
|
205
|
+
]
|
|
206
|
+
|
|
207
|
+
if invalid_array_elements:
|
|
208
|
+
raise ValueError(f"Invalid array elements found: {invalid_array_elements}. ")
|
|
209
|
+
|
|
210
|
+
return array_layouts
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def get_array_layouts_from_parameter_file(
|
|
214
|
+
file_path, model_version, db_config, coordinate_system="ground"
|
|
215
|
+
):
|
|
216
|
+
"""
|
|
217
|
+
Retrieve array layouts from parameter file.
|
|
218
|
+
|
|
219
|
+
Parameters
|
|
220
|
+
----------
|
|
221
|
+
file_path : str or Path
|
|
222
|
+
Path to the array layout parameter file.
|
|
223
|
+
model_version : str
|
|
224
|
+
Model version to retrieve.
|
|
225
|
+
db_config : dict
|
|
226
|
+
Database configuration.
|
|
227
|
+
coordinate_system : str
|
|
228
|
+
Coordinate system to use for the array elements (default is "ground").
|
|
229
|
+
|
|
230
|
+
Returns
|
|
231
|
+
-------
|
|
232
|
+
list
|
|
233
|
+
List of dictionaries containing array layout names and their elements.
|
|
234
|
+
"""
|
|
235
|
+
array_layouts = gen.collect_data_from_file(file_path)
|
|
236
|
+
try:
|
|
237
|
+
value = array_layouts["value"]
|
|
238
|
+
except KeyError as exc:
|
|
239
|
+
raise ValueError("Missing 'value' key in layout file.") from exc
|
|
240
|
+
site = array_layouts.get("site")
|
|
241
|
+
|
|
242
|
+
layouts = []
|
|
243
|
+
for layout in value:
|
|
244
|
+
layouts.append(
|
|
245
|
+
_get_array_layout_dict(
|
|
246
|
+
db_config, model_version, site, None, layout["name"], coordinate_system
|
|
247
|
+
)
|
|
248
|
+
)
|
|
249
|
+
return layouts
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def get_array_layouts_from_db(
|
|
253
|
+
layout_name, site, model_version, db_config, coordinate_system="ground"
|
|
254
|
+
):
|
|
255
|
+
"""
|
|
256
|
+
Retrieve all array layouts from the database and return as list of astropy tables.
|
|
257
|
+
|
|
258
|
+
Parameters
|
|
259
|
+
----------
|
|
260
|
+
layout_name : str
|
|
261
|
+
Name of the array layout to retrieve (for None, all layouts are retrieved).
|
|
262
|
+
site : str
|
|
263
|
+
Site identifier.
|
|
264
|
+
model_version : str
|
|
265
|
+
Model version to retrieve.
|
|
266
|
+
db_config : dict
|
|
267
|
+
Database configuration.
|
|
268
|
+
coordinate_system : str
|
|
269
|
+
Coordinate system to use for the array elements (default is "ground").
|
|
270
|
+
|
|
271
|
+
Returns
|
|
272
|
+
-------
|
|
273
|
+
list
|
|
274
|
+
List of dictionaries containing array layout names and their elements.
|
|
275
|
+
"""
|
|
276
|
+
layout_names = []
|
|
277
|
+
if layout_name:
|
|
278
|
+
layout_names.append(layout_name)
|
|
279
|
+
else:
|
|
280
|
+
site_model = SiteModel(site=site, model_version=model_version, mongo_db_config=db_config)
|
|
281
|
+
layout_names = site_model.get_list_of_array_layouts()
|
|
282
|
+
|
|
283
|
+
layouts = []
|
|
284
|
+
for _layout_name in layout_names:
|
|
285
|
+
layouts.append(
|
|
286
|
+
_get_array_layout_dict(
|
|
287
|
+
db_config, model_version, site, None, _layout_name, coordinate_system
|
|
288
|
+
)
|
|
289
|
+
)
|
|
290
|
+
if len(layouts) == 1:
|
|
291
|
+
return layouts[0]
|
|
292
|
+
return layouts
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def get_array_layouts_using_telescope_lists_from_db(
|
|
296
|
+
telescope_lists, site, model_version, db_config, coordinate_system="ground"
|
|
297
|
+
):
|
|
298
|
+
"""
|
|
299
|
+
Retrieve array layouts from the database using telescope lists.
|
|
300
|
+
|
|
301
|
+
Parameters
|
|
302
|
+
----------
|
|
303
|
+
telescope_lists : list
|
|
304
|
+
List of telescope lists to retrieve array layouts for.
|
|
305
|
+
site : str
|
|
306
|
+
Site identifier.
|
|
307
|
+
model_version : str
|
|
308
|
+
Model version to retrieve.
|
|
309
|
+
db_config : dict
|
|
310
|
+
Database configuration.
|
|
311
|
+
coordinate_system : str
|
|
312
|
+
Coordinate system to use for the array elements (default is "ground").
|
|
313
|
+
|
|
314
|
+
Returns
|
|
315
|
+
-------
|
|
316
|
+
list
|
|
317
|
+
List of dictionaries containing array layout names and their elements.
|
|
318
|
+
|
|
319
|
+
"""
|
|
320
|
+
layouts = []
|
|
321
|
+
for telescope_list in telescope_lists:
|
|
322
|
+
_site = site
|
|
323
|
+
if _site is None:
|
|
324
|
+
sites = {names.get_site_from_array_element_name(t) for t in telescope_list}
|
|
325
|
+
if len(sites) != 1:
|
|
326
|
+
raise ValueError(
|
|
327
|
+
f"Telescope list contains elements from multiple sites: {sites}."
|
|
328
|
+
"Please specify a site."
|
|
329
|
+
)
|
|
330
|
+
_site = sites.pop()
|
|
331
|
+
|
|
332
|
+
layouts.append(
|
|
333
|
+
_get_array_layout_dict(
|
|
334
|
+
db_config, model_version, _site, telescope_list, None, coordinate_system
|
|
335
|
+
)
|
|
336
|
+
)
|
|
337
|
+
return layouts
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def get_array_layouts_from_file(file_path):
|
|
341
|
+
"""
|
|
342
|
+
Retrieve array layout(s) from astropy table file(s).
|
|
343
|
+
|
|
344
|
+
Parameters
|
|
345
|
+
----------
|
|
346
|
+
file_path : str or Path or list of str or list of Path
|
|
347
|
+
Path(s) to array layout files(s).
|
|
348
|
+
|
|
349
|
+
Returns
|
|
350
|
+
-------
|
|
351
|
+
list
|
|
352
|
+
List of dictionaries containing array layout names and their elements.
|
|
353
|
+
"""
|
|
354
|
+
if isinstance(file_path, str | Path):
|
|
355
|
+
file_path = [file_path]
|
|
356
|
+
|
|
357
|
+
layouts = []
|
|
358
|
+
for _file in file_path:
|
|
359
|
+
layouts.append(
|
|
360
|
+
{
|
|
361
|
+
"name": (Path(_file).name).split(".")[0],
|
|
362
|
+
"array_elements": data_reader.read_table_from_file(file_name=_file),
|
|
363
|
+
}
|
|
364
|
+
)
|
|
365
|
+
return layouts
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def _get_array_layout_dict(
|
|
369
|
+
db_config, model_version, site, telescope_list, layout_name, coordinate_system
|
|
370
|
+
):
|
|
371
|
+
"""Return array layout dictionary for a given telescope list."""
|
|
372
|
+
array_model = ArrayModel(
|
|
373
|
+
mongo_db_config=db_config,
|
|
374
|
+
model_version=model_version,
|
|
375
|
+
site=site,
|
|
376
|
+
array_elements=telescope_list,
|
|
377
|
+
layout_name=layout_name,
|
|
378
|
+
)
|
|
379
|
+
return {
|
|
380
|
+
"name": layout_name if layout_name else "list",
|
|
381
|
+
"site": site,
|
|
382
|
+
"array_elements": array_model.export_array_elements_as_table(
|
|
383
|
+
coordinate_system=coordinate_system
|
|
384
|
+
),
|
|
385
|
+
}
|
simtools/model/array_model.py
CHANGED
|
@@ -36,6 +36,10 @@ class ArrayModel:
|
|
|
36
36
|
array_elements: Union[str, Path, List[str]], optional
|
|
37
37
|
Array element definitions (list of array element or path to file with
|
|
38
38
|
the array element positions).
|
|
39
|
+
sim_telarray_seeds : dict, optional
|
|
40
|
+
Dictionary with configuration for sim_telarray random instrument setup.
|
|
41
|
+
simtel_path: str, Path, optional
|
|
42
|
+
Path to the sim_telarray installation directory.
|
|
39
43
|
"""
|
|
40
44
|
|
|
41
45
|
def __init__(
|
|
@@ -46,6 +50,8 @@ class ArrayModel:
|
|
|
46
50
|
site: str | None = None,
|
|
47
51
|
layout_name: str | None = None,
|
|
48
52
|
array_elements: str | Path | list[str] | None = None,
|
|
53
|
+
sim_telarray_seeds: dict | None = None,
|
|
54
|
+
simtel_path: str | Path | None = None,
|
|
49
55
|
):
|
|
50
56
|
"""Initialize ArrayModel."""
|
|
51
57
|
self._logger = logging.getLogger(__name__)
|
|
@@ -65,6 +71,8 @@ class ArrayModel:
|
|
|
65
71
|
|
|
66
72
|
self._telescope_model_files_exported = False
|
|
67
73
|
self._array_model_file_exported = False
|
|
74
|
+
self.sim_telarray_seeds = sim_telarray_seeds
|
|
75
|
+
self.simtel_path = simtel_path
|
|
68
76
|
|
|
69
77
|
def _initialize(self, site: str, array_elements_config: str | Path | list[str]):
|
|
70
78
|
"""
|
|
@@ -116,6 +124,26 @@ class ArrayModel:
|
|
|
116
124
|
telescope_model = self._build_telescope_models(site_model, array_elements)
|
|
117
125
|
return array_elements, site_model, telescope_model
|
|
118
126
|
|
|
127
|
+
@property
|
|
128
|
+
def config_file_path(self) -> Path:
|
|
129
|
+
"""
|
|
130
|
+
Return the path of the array config file for sim_telarray.
|
|
131
|
+
|
|
132
|
+
Returns
|
|
133
|
+
-------
|
|
134
|
+
Path
|
|
135
|
+
Path of the exported config file for sim_telarray.
|
|
136
|
+
"""
|
|
137
|
+
if self._config_file_path is None:
|
|
138
|
+
config_file_name = names.simtel_config_file_name(
|
|
139
|
+
array_name=self.layout_name,
|
|
140
|
+
site=self.site_model.site,
|
|
141
|
+
model_version=self.model_version,
|
|
142
|
+
label=self.label,
|
|
143
|
+
)
|
|
144
|
+
self._config_file_path = self.get_config_directory().joinpath(config_file_name)
|
|
145
|
+
return self._config_file_path
|
|
146
|
+
|
|
119
147
|
@property
|
|
120
148
|
def number_of_telescopes(self) -> int:
|
|
121
149
|
"""
|
|
@@ -140,6 +168,34 @@ class ArrayModel:
|
|
|
140
168
|
"""
|
|
141
169
|
return self.site_model.site
|
|
142
170
|
|
|
171
|
+
@property
|
|
172
|
+
def model_version(self):
|
|
173
|
+
"""Model version."""
|
|
174
|
+
return self._model_version
|
|
175
|
+
|
|
176
|
+
@model_version.setter
|
|
177
|
+
def model_version(self, model_version):
|
|
178
|
+
"""
|
|
179
|
+
Set model version.
|
|
180
|
+
|
|
181
|
+
Parameters
|
|
182
|
+
----------
|
|
183
|
+
_model_version: str or list
|
|
184
|
+
Model version (e.g., "6.0.0").
|
|
185
|
+
If a list is passed, it must contain exactly one element,
|
|
186
|
+
and only that element will be used.
|
|
187
|
+
|
|
188
|
+
Raises
|
|
189
|
+
------
|
|
190
|
+
ValueError
|
|
191
|
+
If more than one model version is passed.
|
|
192
|
+
"""
|
|
193
|
+
if isinstance(model_version, list):
|
|
194
|
+
raise ValueError(
|
|
195
|
+
f"Only one model version can be passed to {self.__class__.__name__}, not a list."
|
|
196
|
+
)
|
|
197
|
+
self._model_version = model_version
|
|
198
|
+
|
|
143
199
|
def _build_telescope_models(self, site_model: SiteModel, array_elements: dict) -> dict:
|
|
144
200
|
"""
|
|
145
201
|
Build the the telescope models for all telescopes of this array.
|
|
@@ -187,7 +243,7 @@ class ArrayModel:
|
|
|
187
243
|
)
|
|
188
244
|
if name not in exported_models:
|
|
189
245
|
self._logger.debug(f"Exporting configuration file for telescope {name}")
|
|
190
|
-
tel_model.
|
|
246
|
+
tel_model.write_sim_telarray_config_file()
|
|
191
247
|
exported_models.append(name)
|
|
192
248
|
else:
|
|
193
249
|
self._logger.debug(
|
|
@@ -196,29 +252,23 @@ class ArrayModel:
|
|
|
196
252
|
|
|
197
253
|
self._telescope_model_files_exported = True
|
|
198
254
|
|
|
199
|
-
def
|
|
255
|
+
def export_sim_telarray_config_file(self):
|
|
200
256
|
"""Export sim_telarray configuration file for the array into the model directory."""
|
|
201
|
-
|
|
202
|
-
config_file_name = names.simtel_config_file_name(
|
|
203
|
-
array_name=self.layout_name,
|
|
204
|
-
site=self.site_model.site,
|
|
205
|
-
model_version=self.model_version,
|
|
206
|
-
label=self.label,
|
|
207
|
-
)
|
|
208
|
-
self._config_file_path = self.get_config_directory().joinpath(config_file_name)
|
|
257
|
+
self.site_model.export_model_files()
|
|
209
258
|
|
|
210
|
-
|
|
211
|
-
self._logger.info(f"Writing array configuration file into {self._config_file_path}")
|
|
259
|
+
self._logger.info(f"Writing array configuration file into {self.config_file_path}")
|
|
212
260
|
simtel_writer = SimtelConfigWriter(
|
|
213
261
|
site=self.site_model.site,
|
|
214
262
|
layout_name=self.layout_name,
|
|
215
263
|
model_version=self.model_version,
|
|
216
264
|
label=self.label,
|
|
265
|
+
simtel_path=self.simtel_path,
|
|
217
266
|
)
|
|
218
267
|
simtel_writer.write_array_config_file(
|
|
219
|
-
config_file_path=self.
|
|
268
|
+
config_file_path=self.config_file_path,
|
|
220
269
|
telescope_model=self.telescope_model,
|
|
221
270
|
site_model=self.site_model,
|
|
271
|
+
sim_telarray_seeds=self.sim_telarray_seeds,
|
|
222
272
|
)
|
|
223
273
|
self._array_model_file_exported = True
|
|
224
274
|
|
|
@@ -231,21 +281,7 @@ class ArrayModel:
|
|
|
231
281
|
if not self._telescope_model_files_exported:
|
|
232
282
|
self.export_simtel_telescope_config_files()
|
|
233
283
|
if not self._array_model_file_exported:
|
|
234
|
-
self.
|
|
235
|
-
|
|
236
|
-
def get_config_file(self) -> Path:
|
|
237
|
-
"""
|
|
238
|
-
Return the path of the array config file for sim_telarray.
|
|
239
|
-
|
|
240
|
-
A new config file is produced if the file is not updated.
|
|
241
|
-
|
|
242
|
-
Returns
|
|
243
|
-
-------
|
|
244
|
-
Path
|
|
245
|
-
Path of the exported config file for sim_telarray.
|
|
246
|
-
"""
|
|
247
|
-
self.export_all_simtel_config_files()
|
|
248
|
-
return self._config_file_path
|
|
284
|
+
self.export_sim_telarray_config_file()
|
|
249
285
|
|
|
250
286
|
def get_config_directory(self) -> Path:
|
|
251
287
|
"""
|
|
@@ -257,7 +293,9 @@ class ArrayModel:
|
|
|
257
293
|
Path of the config directory path for sim_telarray.
|
|
258
294
|
"""
|
|
259
295
|
if self._config_file_directory is None:
|
|
260
|
-
self._config_file_directory = self.io_handler.get_output_directory(
|
|
296
|
+
self._config_file_directory = self.io_handler.get_output_directory(
|
|
297
|
+
self.label, f"model/{self.model_version}"
|
|
298
|
+
)
|
|
261
299
|
return self._config_file_directory
|
|
262
300
|
|
|
263
301
|
def _load_array_element_positions_from_file(
|
|
@@ -331,6 +369,7 @@ class ArrayModel:
|
|
|
331
369
|
"type": "float64",
|
|
332
370
|
"file": False,
|
|
333
371
|
"meta_parameter": False,
|
|
372
|
+
"model_parameter_schema_version": "0.1.0",
|
|
334
373
|
}
|
|
335
374
|
|
|
336
375
|
def _get_array_elements_from_list(self, array_elements_list: list[str]) -> dict:
|