gammasimtools 0.12.0__py3-none-any.whl → 0.14.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.12.0.dist-info → gammasimtools-0.14.0.dist-info}/METADATA +3 -3
- {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/RECORD +257 -263
- {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/entry_points.txt +4 -1
- simtools/_version.py +2 -2
- simtools/applications/convert_all_model_parameters_from_simtel.py +77 -88
- simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -1
- simtools/applications/db_add_file_to_db.py +15 -0
- simtools/applications/db_add_value_from_json_to_db.py +18 -1
- simtools/applications/db_get_parameter_from_db.py +52 -22
- simtools/applications/derive_ctao_array_layouts.py +120 -0
- simtools/applications/derive_photon_electron_spectrum.py +30 -2
- simtools/applications/docs_produce_array_element_report.py +42 -26
- simtools/applications/docs_produce_model_parameter_reports.py +28 -21
- simtools/applications/generate_simtel_event_data.py +117 -0
- simtools/applications/plot_tabular_data.py +14 -2
- simtools/applications/print_version.py +81 -0
- simtools/applications/production_derive_corsika_limits.py +240 -0
- simtools/applications/production_scale_events.py +59 -36
- simtools/applications/run_application.py +47 -18
- simtools/applications/simulate_light_emission.py +115 -247
- simtools/applications/simulate_prod_htcondor_generator.py +2 -2
- simtools/applications/submit_data_from_external.py +1 -1
- simtools/applications/submit_model_parameter_from_external.py +2 -1
- simtools/camera/single_photon_electron_spectrum.py +169 -17
- simtools/constants.py +7 -0
- simtools/data_model/metadata_collector.py +159 -61
- simtools/data_model/model_data_writer.py +18 -61
- simtools/data_model/schema.py +2 -1
- simtools/data_model/validate_data.py +5 -3
- simtools/db/db_handler.py +123 -33
- simtools/dependencies.py +38 -3
- simtools/layout/array_layout.py +1 -0
- simtools/layout/ctao_array_layouts.py +172 -0
- simtools/model/array_model.py +3 -4
- simtools/model/model_parameter.py +30 -118
- simtools/production_configuration/derive_corsika_limits.py +328 -0
- simtools/production_configuration/event_scaler.py +2 -2
- simtools/ray_tracing/mirror_panel_psf.py +1 -1
- simtools/reporting/docs_auto_report_generator.py +217 -0
- simtools/reporting/docs_read_parameters.py +298 -143
- simtools/schemas/application_workflow.metaschema.yml +3 -0
- simtools/schemas/metadata.metaschema.yml +7 -6
- simtools/schemas/model_parameter.metaschema.yml +13 -4
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +19 -5
- simtools/schemas/model_parameters/adjust_gain.schema.yml +1 -1
- simtools/schemas/model_parameters/altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/array_coordinates.schema.yml +1 -1
- simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +3 -3
- simtools/schemas/model_parameters/array_element_position_ground.schema.yml +3 -3
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +3 -3
- simtools/schemas/model_parameters/array_layouts.schema.yml +3 -0
- simtools/schemas/model_parameters/array_window.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/atmospheric_profile.schema.yml +1 -1
- simtools/schemas/model_parameters/axes_offsets.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_body_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_body_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_file.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_rotate.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_depth.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_filter.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_pixels.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_observation_level.schema.yml +1 -1
- simtools/schemas/model_parameters/dark_events.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_start.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/dish_shape_length.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +1 -1
- simtools/schemas/model_parameters/effective_focal_length.schema.yml +5 -5
- simtools/schemas/model_parameters/epsg_code.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +4 -4
- simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_max_signal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_max_sum.schema.yml +4 -4
- simtools/schemas/model_parameters/fadc_mhz.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_noise.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +20 -20
- simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/focus_offset.schema.yml +4 -4
- simtools/schemas/model_parameters/gain_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_horizontal.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_rotation.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_vertical.schema.yml +1 -1
- simtools/schemas/model_parameters/hg_lg_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_external_trigger.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_var_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_wavelength.schema.yml +1 -1
- simtools/schemas/model_parameters/led_events.schema.yml +1 -1
- simtools/schemas/model_parameters/led_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/led_pulse_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +1 -1
- simtools/schemas/model_parameters/led_var_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +4 -4
- simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +4 -4
- simtools/schemas/model_parameters/mirror_class.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +3 -3
- simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +3 -3
- simtools/schemas/model_parameters/multiplicity_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +45 -0
- simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +2 -2
- simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_offaxis.schema.yml +5 -5
- simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_reference_value.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +1 -1
- simtools/schemas/model_parameters/{nsb_skymap.schema.yml → nsb_sky_map.schema.yml} +1 -1
- simtools/schemas/model_parameters/nsb_spectrum.schema.yml +2 -2
- simtools/schemas/model_parameters/num_gains.schema.yml +1 -1
- simtools/schemas/model_parameters/pedestal_events.schema.yml +1 -1
- simtools/schemas/model_parameters/photon_delay.schema.yml +1 -1
- simtools/schemas/model_parameters/photons_per_run.schema.yml +1 -1
- simtools/schemas/model_parameters/pixel_cells.schema.yml +1 -1
- simtools/schemas/model_parameters/pixels_parallel.schema.yml +1 -1
- simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_average_gain.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_gain_index.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_transit_time.schema.yml +4 -4
- simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +8 -4
- simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +20 -20
- simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/qe_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/random_focal_length.schema.yml +2 -2
- simtools/schemas/model_parameters/random_mono_probability.schema.yml +38 -0
- simtools/schemas/model_parameters/reference_point_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_latitude.schema.yml +4 -1
- simtools/schemas/model_parameters/reference_point_longitude.schema.yml +4 -1
- simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +5 -5
- simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +20 -20
- simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/stars.schema.yml +36 -0
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_axis_height.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_random_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_random_error.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_transmission.schema.yml +6 -6
- simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +1 -1
- simtools/schemas/model_parameters/teltrig_min_time.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_jitter.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_current_limit.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +4 -4
- simtools/schemas/model_parameters/trigger_pixels.schema.yml +1 -1
- simtools/schemas/plot_configuration.metaschema.yml +162 -0
- simtools/schemas/production_tables.schema.yml +1 -1
- simtools/simtel/simtel_config_reader.py +85 -34
- simtools/simtel/simtel_config_writer.py +70 -38
- simtools/simtel/simtel_io_event_reader.py +278 -0
- simtools/simtel/simtel_io_event_writer.py +317 -0
- simtools/simtel/simtel_table_reader.py +4 -0
- simtools/simtel/simulator_light_emission.py +181 -67
- simtools/simulator.py +2 -2
- simtools/testing/configuration.py +17 -0
- simtools/utils/general.py +83 -16
- simtools/utils/geometry.py +19 -0
- simtools/utils/names.py +14 -3
- simtools/visualization/plot_tables.py +25 -20
- simtools/visualization/visualize.py +73 -25
- simtools/_dev_version/__init__.py +0 -9
- simtools/applications/__init__.py +0 -0
- simtools/applications/production_derive_limits.py +0 -95
- simtools/configuration/__init__.py +0 -0
- simtools/corsika/__init__.py +0 -0
- simtools/data_model/__init__.py +0 -0
- simtools/db/__init__.py +0 -0
- simtools/io_operations/__init__.py +0 -0
- simtools/job_execution/__init__.py +0 -0
- simtools/layout/__init__.py +0 -0
- simtools/model/__init__.py +0 -0
- simtools/production_configuration/limits_calculation.py +0 -202
- simtools/ray_tracing/__init__.py +0 -0
- simtools/runners/__init__.py +0 -0
- simtools/simtel/__init__.py +0 -0
- simtools/simtel/simtel_io_events.py +0 -265
- simtools/testing/__init__.py +0 -0
- simtools/utils/__init__.py +0 -0
- simtools/visualization/__init__.py +0 -0
- {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info/licenses}/LICENSE +0 -0
- {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/top_level.txt +0 -0
|
@@ -6,7 +6,6 @@ from pathlib import Path
|
|
|
6
6
|
|
|
7
7
|
import astropy.units as u
|
|
8
8
|
import numpy as np
|
|
9
|
-
import yaml
|
|
10
9
|
from astropy.io.registry.base import IORegistryError
|
|
11
10
|
|
|
12
11
|
import simtools.utils.general as gen
|
|
@@ -95,7 +94,7 @@ class ModelDataWriter:
|
|
|
95
94
|
Dictionary with configuration parameters (including output file name and path).
|
|
96
95
|
output_file: string or Path
|
|
97
96
|
Name of output file (args["output_file"] is used if this parameter is not set).
|
|
98
|
-
metadata:
|
|
97
|
+
metadata: MetadataCollector object
|
|
99
98
|
Metadata to be written.
|
|
100
99
|
product_data: astropy Table
|
|
101
100
|
Model data to be written
|
|
@@ -174,11 +173,11 @@ class ModelDataWriter:
|
|
|
174
173
|
if metadata_input_dict is not None:
|
|
175
174
|
metadata_input_dict["output_file"] = output_file
|
|
176
175
|
metadata_input_dict["output_file_format"] = Path(output_file).suffix.lstrip(".")
|
|
177
|
-
metadata = MetadataCollector(args_dict=metadata_input_dict)
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
metadata = MetadataCollector(args_dict=metadata_input_dict)
|
|
177
|
+
metadata.write(output_path / Path(output_file))
|
|
178
|
+
unique_id = (
|
|
179
|
+
metadata.get_top_level_metadata().get("cta", {}).get("product", {}).get("id")
|
|
180
180
|
)
|
|
181
|
-
unique_id = metadata.get("cta", {}).get("product", {}).get("id")
|
|
182
181
|
|
|
183
182
|
_json_dict = writer.get_validated_parameter_dict(
|
|
184
183
|
parameter_name, value, instrument, parameter_version, unique_id
|
|
@@ -270,6 +269,7 @@ class ModelDataWriter:
|
|
|
270
269
|
"unit": unit,
|
|
271
270
|
"type": self._get_parameter_type(),
|
|
272
271
|
"file": self._parameter_is_a_file(),
|
|
272
|
+
"meta_parameter": False,
|
|
273
273
|
}
|
|
274
274
|
return self.validate_and_transform(
|
|
275
275
|
product_data_dict=data_dict,
|
|
@@ -364,7 +364,7 @@ class ModelDataWriter:
|
|
|
364
364
|
----------
|
|
365
365
|
product_data: astropy Table
|
|
366
366
|
Model data to be written
|
|
367
|
-
metadata:
|
|
367
|
+
metadata: MetadataCollector object
|
|
368
368
|
Metadata to be written.
|
|
369
369
|
|
|
370
370
|
Raises
|
|
@@ -377,7 +377,9 @@ class ModelDataWriter:
|
|
|
377
377
|
return
|
|
378
378
|
|
|
379
379
|
if metadata is not None:
|
|
380
|
-
product_data.meta.update(
|
|
380
|
+
product_data.meta.update(
|
|
381
|
+
gen.change_dict_keys_case(metadata.get_top_level_metadata(), False)
|
|
382
|
+
)
|
|
381
383
|
|
|
382
384
|
self._logger.info(f"Writing data to {self.product_data_file}")
|
|
383
385
|
if isinstance(product_data, dict) and Path(self.product_data_file).suffix == ".json":
|
|
@@ -390,6 +392,8 @@ class ModelDataWriter:
|
|
|
390
392
|
except IORegistryError:
|
|
391
393
|
self._logger.error(f"Error writing model data to {self.product_data_file}.")
|
|
392
394
|
raise
|
|
395
|
+
if metadata is not None:
|
|
396
|
+
metadata.write(self.product_data_file, add_activity_name=True)
|
|
393
397
|
|
|
394
398
|
def write_dict_to_model_parameter_json(self, file_name, data_dict):
|
|
395
399
|
"""
|
|
@@ -423,7 +427,7 @@ class ModelDataWriter:
|
|
|
423
427
|
"""
|
|
424
428
|
Prepare data dictionary for writing to json file.
|
|
425
429
|
|
|
426
|
-
Ensure sim_telarray style lists as strings.
|
|
430
|
+
Ensure sim_telarray style lists as strings 'type' and 'unit' entries.
|
|
427
431
|
Replace "None" with "null" for unit field.
|
|
428
432
|
|
|
429
433
|
Parameters
|
|
@@ -438,64 +442,17 @@ class ModelDataWriter:
|
|
|
438
442
|
|
|
439
443
|
"""
|
|
440
444
|
try:
|
|
441
|
-
data_dict["value"] = gen.convert_list_to_string(data_dict["value"])
|
|
442
|
-
data_dict["unit"] = gen.convert_list_to_string(data_dict["unit"], comma_separated=True)
|
|
443
|
-
data_dict["type"] = gen.convert_list_to_string(
|
|
444
|
-
data_dict["type"], comma_separated=True, collapse_list=True
|
|
445
|
-
)
|
|
446
445
|
if isinstance(data_dict["unit"], str):
|
|
447
446
|
data_dict["unit"] = data_dict["unit"].replace("None", "null")
|
|
447
|
+
elif isinstance(data_dict["unit"], list):
|
|
448
|
+
data_dict["unit"] = [
|
|
449
|
+
unit.replace("None", "null") if isinstance(unit, str) else unit
|
|
450
|
+
for unit in data_dict["unit"]
|
|
451
|
+
]
|
|
448
452
|
except KeyError:
|
|
449
453
|
pass
|
|
450
454
|
return data_dict
|
|
451
455
|
|
|
452
|
-
def write_metadata_to_yml(self, metadata, yml_file=None, keys_lower_case=False):
|
|
453
|
-
"""
|
|
454
|
-
Write model metadata file (yaml file format).
|
|
455
|
-
|
|
456
|
-
Parameters
|
|
457
|
-
----------
|
|
458
|
-
metadata: dict
|
|
459
|
-
Metadata to be stored
|
|
460
|
-
yml_file: str
|
|
461
|
-
Name of output file.
|
|
462
|
-
keys_lower_case: bool
|
|
463
|
-
Write yaml keys in lower case.
|
|
464
|
-
|
|
465
|
-
Returns
|
|
466
|
-
-------
|
|
467
|
-
str
|
|
468
|
-
Name of output file
|
|
469
|
-
|
|
470
|
-
Raises
|
|
471
|
-
------
|
|
472
|
-
FileNotFoundError
|
|
473
|
-
If yml_file not found.
|
|
474
|
-
TypeError
|
|
475
|
-
If yml_file is not defined.
|
|
476
|
-
"""
|
|
477
|
-
try:
|
|
478
|
-
yml_file = names.file_name_with_version(
|
|
479
|
-
yml_file or self.product_data_file, ".metadata.yml"
|
|
480
|
-
)
|
|
481
|
-
with open(yml_file, "w", encoding="UTF-8") as file:
|
|
482
|
-
yaml.safe_dump(
|
|
483
|
-
gen.change_dict_keys_case(metadata, keys_lower_case),
|
|
484
|
-
file,
|
|
485
|
-
sort_keys=False,
|
|
486
|
-
)
|
|
487
|
-
self._logger.info(f"Writing metadata to {yml_file}")
|
|
488
|
-
return yml_file
|
|
489
|
-
except FileNotFoundError:
|
|
490
|
-
self._logger.error(f"Error writing model data to {yml_file}")
|
|
491
|
-
raise
|
|
492
|
-
except AttributeError:
|
|
493
|
-
self._logger.error("No metadata defined for writing")
|
|
494
|
-
raise
|
|
495
|
-
except TypeError:
|
|
496
|
-
self._logger.error("No output file for metadata defined")
|
|
497
|
-
raise
|
|
498
|
-
|
|
499
456
|
@staticmethod
|
|
500
457
|
def _astropy_data_format(product_data_format):
|
|
501
458
|
"""
|
simtools/data_model/schema.py
CHANGED
|
@@ -108,7 +108,7 @@ def validate_dict_using_schema(data, schema_file=None, json_schema=None):
|
|
|
108
108
|
"""
|
|
109
109
|
if json_schema is None and schema_file is None:
|
|
110
110
|
_logger.warning(f"No schema provided for validation of {data}")
|
|
111
|
-
return
|
|
111
|
+
return None
|
|
112
112
|
if json_schema is None:
|
|
113
113
|
json_schema = load_schema(
|
|
114
114
|
schema_file,
|
|
@@ -131,6 +131,7 @@ def validate_dict_using_schema(data, schema_file=None, json_schema=None):
|
|
|
131
131
|
raise FileNotFoundError(f"Meta schema URL does not exist: {data['meta_schema_url']}")
|
|
132
132
|
|
|
133
133
|
_logger.debug(f"Successful validation of data using schema ({json_schema.get('name')})")
|
|
134
|
+
return data
|
|
134
135
|
|
|
135
136
|
|
|
136
137
|
def load_schema(schema_file=None, schema_version=None):
|
|
@@ -220,7 +220,7 @@ class DataValidator:
|
|
|
220
220
|
json_schema=self._get_data_description(index).get("json_schema"),
|
|
221
221
|
)
|
|
222
222
|
else:
|
|
223
|
-
self._check_data_type(np.array(value).dtype, index)
|
|
223
|
+
self._check_data_type(np.array(value).dtype, index, value)
|
|
224
224
|
|
|
225
225
|
if self.data_dict.get("type") not in ("string", "dict", "file"):
|
|
226
226
|
self._check_for_not_a_number(value, index)
|
|
@@ -436,7 +436,7 @@ class DataValidator:
|
|
|
436
436
|
|
|
437
437
|
return u.Unit(reference_unit)
|
|
438
438
|
|
|
439
|
-
def _check_data_type(self, dtype, column_name):
|
|
439
|
+
def _check_data_type(self, dtype, column_name, value=None):
|
|
440
440
|
"""
|
|
441
441
|
Check column data type.
|
|
442
442
|
|
|
@@ -446,6 +446,8 @@ class DataValidator:
|
|
|
446
446
|
data type
|
|
447
447
|
column_name: str
|
|
448
448
|
column name
|
|
449
|
+
value: value
|
|
450
|
+
value to be tested (optional)
|
|
449
451
|
|
|
450
452
|
Raises
|
|
451
453
|
------
|
|
@@ -456,7 +458,7 @@ class DataValidator:
|
|
|
456
458
|
reference_dtype = self._get_data_description(column_name).get("type", None)
|
|
457
459
|
if not gen.validate_data_type(
|
|
458
460
|
reference_dtype=reference_dtype,
|
|
459
|
-
value=
|
|
461
|
+
value=value,
|
|
460
462
|
dtype=dtype,
|
|
461
463
|
allow_subtypes=(not self.check_exact_data_type),
|
|
462
464
|
):
|
simtools/db/db_handler.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
5
|
+
from collections import defaultdict
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from threading import Lock
|
|
7
8
|
|
|
@@ -13,7 +14,8 @@ from pymongo import MongoClient
|
|
|
13
14
|
|
|
14
15
|
from simtools.data_model import validate_data
|
|
15
16
|
from simtools.io_operations import io_handler
|
|
16
|
-
from simtools.
|
|
17
|
+
from simtools.simtel import simtel_table_reader
|
|
18
|
+
from simtools.utils import general, names, value_conversion
|
|
17
19
|
|
|
18
20
|
__all__ = ["DatabaseHandler"]
|
|
19
21
|
|
|
@@ -113,6 +115,7 @@ class DatabaseHandler:
|
|
|
113
115
|
direct_connection = self.mongo_db_config["db_server"] in (
|
|
114
116
|
"localhost",
|
|
115
117
|
"simtools-mongodb",
|
|
118
|
+
"mongodb",
|
|
116
119
|
)
|
|
117
120
|
return MongoClient(
|
|
118
121
|
self.mongo_db_config["db_server"],
|
|
@@ -177,48 +180,62 @@ class DatabaseHandler:
|
|
|
177
180
|
def get_model_parameter(
|
|
178
181
|
self,
|
|
179
182
|
parameter,
|
|
180
|
-
parameter_version,
|
|
181
183
|
site,
|
|
182
184
|
array_element_name,
|
|
185
|
+
parameter_version=None,
|
|
186
|
+
model_version=None,
|
|
183
187
|
):
|
|
184
188
|
"""
|
|
185
|
-
Get a model parameter using
|
|
189
|
+
Get a single model parameter using model or parameter version.
|
|
190
|
+
|
|
191
|
+
Note that this function should not be called in a loop for many parameters,
|
|
192
|
+
as it each call queries the database.
|
|
186
193
|
|
|
187
194
|
Parameters
|
|
188
195
|
----------
|
|
189
196
|
parameter: str
|
|
190
197
|
Name of the parameter.
|
|
191
|
-
parameter_version: str
|
|
192
|
-
Version of the parameter.
|
|
193
198
|
site: str
|
|
194
199
|
Site name.
|
|
195
200
|
array_element_name: str
|
|
196
|
-
Name of the array element model
|
|
201
|
+
Name of the array element model.
|
|
202
|
+
parameter_version: str
|
|
203
|
+
Version of the parameter.
|
|
204
|
+
model_version: str
|
|
205
|
+
Version of the model.
|
|
197
206
|
|
|
198
207
|
Returns
|
|
199
208
|
-------
|
|
200
209
|
dict containing the parameter
|
|
201
210
|
|
|
202
211
|
"""
|
|
212
|
+
collection_name = names.get_collection_name_from_parameter_name(parameter)
|
|
213
|
+
if model_version:
|
|
214
|
+
production_table = self._read_production_table_from_mongo_db(
|
|
215
|
+
collection_name, model_version
|
|
216
|
+
)
|
|
217
|
+
array_element_list = self._get_array_element_list(
|
|
218
|
+
array_element_name, site, production_table, collection_name
|
|
219
|
+
)
|
|
220
|
+
for array_element in reversed(array_element_list):
|
|
221
|
+
parameter_version = (
|
|
222
|
+
production_table["parameters"].get(array_element, {}).get(parameter)
|
|
223
|
+
)
|
|
224
|
+
if parameter_version:
|
|
225
|
+
array_element_name = array_element
|
|
226
|
+
break
|
|
227
|
+
|
|
203
228
|
query = {
|
|
204
229
|
"parameter_version": parameter_version,
|
|
205
230
|
"parameter": parameter,
|
|
206
231
|
}
|
|
207
|
-
if array_element_name
|
|
232
|
+
if array_element_name:
|
|
208
233
|
query["instrument"] = array_element_name
|
|
209
|
-
if site
|
|
234
|
+
if site:
|
|
210
235
|
query["site"] = site
|
|
211
|
-
return self._read_mongo_db(
|
|
212
|
-
query=query, collection_name=names.get_collection_name_from_parameter_name(parameter)
|
|
213
|
-
)
|
|
236
|
+
return self._read_mongo_db(query=query, collection_name=collection_name)
|
|
214
237
|
|
|
215
|
-
def get_model_parameters(
|
|
216
|
-
self,
|
|
217
|
-
site,
|
|
218
|
-
array_element_name,
|
|
219
|
-
collection,
|
|
220
|
-
model_version=None,
|
|
221
|
-
):
|
|
238
|
+
def get_model_parameters(self, site, array_element_name, collection, model_version):
|
|
222
239
|
"""
|
|
223
240
|
Get model parameters using the model version.
|
|
224
241
|
|
|
@@ -239,22 +256,48 @@ class DatabaseHandler:
|
|
|
239
256
|
-------
|
|
240
257
|
dict containing the parameters
|
|
241
258
|
"""
|
|
242
|
-
model_versions = (
|
|
243
|
-
self.get_model_versions(collection) if model_version is None else [model_version]
|
|
244
|
-
)
|
|
245
|
-
|
|
246
259
|
pars = {}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
260
|
+
production_table = self._read_production_table_from_mongo_db(collection, model_version)
|
|
261
|
+
array_element_list = self._get_array_element_list(
|
|
262
|
+
array_element_name, site, production_table, collection
|
|
263
|
+
)
|
|
264
|
+
for array_element in array_element_list:
|
|
265
|
+
pars.update(
|
|
266
|
+
self._get_parameter_for_model_version(
|
|
267
|
+
array_element, model_version, site, collection, production_table
|
|
268
|
+
)
|
|
251
269
|
)
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
270
|
+
return pars
|
|
271
|
+
|
|
272
|
+
def get_model_parameters_for_all_model_versions(self, site, array_element_name, collection):
|
|
273
|
+
"""
|
|
274
|
+
Get model parameters for all model versions.
|
|
275
|
+
|
|
276
|
+
Parameters
|
|
277
|
+
----------
|
|
278
|
+
site: str
|
|
279
|
+
Site name.
|
|
280
|
+
array_element_name: str
|
|
281
|
+
Name of the array element model (e.g. LSTN-01, MSTx-FlashCam, ILLN-01).
|
|
282
|
+
collection: str
|
|
283
|
+
Collection of array element (e.g. telescopes, calibration_devices).
|
|
284
|
+
|
|
285
|
+
Returns
|
|
286
|
+
-------
|
|
287
|
+
dict containing the parameters with model version as first key
|
|
288
|
+
"""
|
|
289
|
+
pars = defaultdict(dict)
|
|
290
|
+
for _model_version in self.get_model_versions(collection):
|
|
291
|
+
try:
|
|
292
|
+
parameter_data = self.get_model_parameters(
|
|
293
|
+
site, array_element_name, collection, _model_version
|
|
257
294
|
)
|
|
295
|
+
pars[_model_version].update(parameter_data)
|
|
296
|
+
except KeyError:
|
|
297
|
+
self._logger.debug(
|
|
298
|
+
f"Skipping model version {_model_version} - {array_element_name} not found"
|
|
299
|
+
)
|
|
300
|
+
continue
|
|
258
301
|
return pars
|
|
259
302
|
|
|
260
303
|
def _get_parameter_for_model_version(
|
|
@@ -331,9 +374,54 @@ class DatabaseHandler:
|
|
|
331
374
|
return [collection for collection in collections if not collection.startswith("fs.")]
|
|
332
375
|
return collections
|
|
333
376
|
|
|
377
|
+
def export_model_file(
|
|
378
|
+
self,
|
|
379
|
+
parameter,
|
|
380
|
+
site,
|
|
381
|
+
array_element_name,
|
|
382
|
+
model_version=None,
|
|
383
|
+
parameter_version=None,
|
|
384
|
+
export_file_as_table=False,
|
|
385
|
+
):
|
|
386
|
+
"""
|
|
387
|
+
Export single model file from the DB identified by the parameter name.
|
|
388
|
+
|
|
389
|
+
The parameter can be identified by model or parameter version.
|
|
390
|
+
Files can be exported as astropy tables (ecsv format).
|
|
391
|
+
|
|
392
|
+
Parameters
|
|
393
|
+
----------
|
|
394
|
+
parameter: str
|
|
395
|
+
Name of the parameter.
|
|
396
|
+
site: str
|
|
397
|
+
Site name.
|
|
398
|
+
array_element_name: str
|
|
399
|
+
Name of the array element model (e.g. MSTN, SSTS).
|
|
400
|
+
parameter_version: str
|
|
401
|
+
Version of the parameter.
|
|
402
|
+
model_version: str
|
|
403
|
+
Version of the model.
|
|
404
|
+
export_file_as_table: bool
|
|
405
|
+
If True, export the file as an astropy table (ecsv format).
|
|
406
|
+
"""
|
|
407
|
+
parameters = self.get_model_parameter(
|
|
408
|
+
parameter,
|
|
409
|
+
site,
|
|
410
|
+
array_element_name,
|
|
411
|
+
parameter_version=parameter_version,
|
|
412
|
+
model_version=model_version,
|
|
413
|
+
)
|
|
414
|
+
self.export_model_files(parameters=parameters, dest=self.io_handler.get_output_directory())
|
|
415
|
+
if export_file_as_table:
|
|
416
|
+
return simtel_table_reader.read_simtel_table(
|
|
417
|
+
parameter,
|
|
418
|
+
self.io_handler.get_output_directory().joinpath(parameters[parameter]["value"]),
|
|
419
|
+
)
|
|
420
|
+
return None
|
|
421
|
+
|
|
334
422
|
def export_model_files(self, parameters=None, file_names=None, dest=None, db_name=None):
|
|
335
423
|
"""
|
|
336
|
-
Export files from the DB to
|
|
424
|
+
Export models files from the DB to given directory.
|
|
337
425
|
|
|
338
426
|
The files to be exported can be specified by file_name or retrieved from the database
|
|
339
427
|
using the parameters dictionary.
|
|
@@ -711,10 +799,12 @@ class DatabaseHandler:
|
|
|
711
799
|
f"corresponding to the {par_dict['parameter']} parameter, must be provided."
|
|
712
800
|
)
|
|
713
801
|
file_path = Path(file_prefix).joinpath(par_dict["value"])
|
|
802
|
+
if not general.is_utf8_file(file_path):
|
|
803
|
+
raise ValueError(f"File is not UTF-8 encoded: {file_path}")
|
|
714
804
|
files_to_add_to_db.add(f"{file_path}")
|
|
715
805
|
|
|
716
806
|
self._logger.info(
|
|
717
|
-
f"Adding a new entry to DB {db_name} and collection {
|
|
807
|
+
f"Adding a new entry to DB {db_name} and collection {collection_name}:\n{par_dict}"
|
|
718
808
|
)
|
|
719
809
|
collection.insert_one(par_dict)
|
|
720
810
|
|
simtools/dependencies.py
CHANGED
|
@@ -81,18 +81,53 @@ def get_sim_telarray_version():
|
|
|
81
81
|
|
|
82
82
|
def get_corsika_version():
|
|
83
83
|
"""
|
|
84
|
-
Get the version of the
|
|
84
|
+
Get the version of the CORSIKA package.
|
|
85
85
|
|
|
86
86
|
Returns
|
|
87
87
|
-------
|
|
88
88
|
str
|
|
89
|
-
Version of the
|
|
89
|
+
Version of the CORSIKA package.
|
|
90
90
|
"""
|
|
91
|
+
version = None
|
|
92
|
+
sim_telarray_path = os.getenv("SIMTOOLS_SIMTEL_PATH")
|
|
93
|
+
if sim_telarray_path is None:
|
|
94
|
+
_logger.warning("Environment variable SIMTOOLS_SIMTEL_PATH is not set.")
|
|
95
|
+
return None
|
|
96
|
+
corsika_command = Path(sim_telarray_path) / "corsika-run" / "corsika"
|
|
97
|
+
|
|
98
|
+
# Below I do not use the standard context manager because
|
|
99
|
+
# it makes mocking in the tests significantly more difficult
|
|
100
|
+
process = subprocess.Popen( # pylint: disable=consider-using-with
|
|
101
|
+
corsika_command,
|
|
102
|
+
stdout=subprocess.PIPE,
|
|
103
|
+
stderr=subprocess.PIPE,
|
|
104
|
+
stdin=subprocess.PIPE,
|
|
105
|
+
text=True,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Capture output until it waits for input
|
|
109
|
+
while True:
|
|
110
|
+
line = process.stdout.readline()
|
|
111
|
+
if not line:
|
|
112
|
+
break
|
|
113
|
+
# Extract the version from the line "NUMBER OF VERSION : 7.7550"
|
|
114
|
+
if "NUMBER OF VERSION" in line:
|
|
115
|
+
version = line.split(":")[1].strip()
|
|
116
|
+
break
|
|
117
|
+
# Check for a specific prompt or indication that the program is waiting for input
|
|
118
|
+
if "DATA CARDS FOR RUN STEERING ARE EXPECTED FROM STANDARD INPUT" in line:
|
|
119
|
+
break
|
|
120
|
+
|
|
121
|
+
process.terminate()
|
|
122
|
+
# Check it's a valid version string
|
|
123
|
+
if version and re.match(r"\d+\.\d+", version):
|
|
124
|
+
return version
|
|
91
125
|
try:
|
|
92
126
|
build_opts = get_build_options()
|
|
93
127
|
except (FileNotFoundError, TypeError):
|
|
94
|
-
_logger.warning("
|
|
128
|
+
_logger.warning("Could not get CORSIKA version.")
|
|
95
129
|
return None
|
|
130
|
+
_logger.debug("Getting the CORSIKA version from the build options.")
|
|
96
131
|
return build_opts.get("corsika_version")
|
|
97
132
|
|
|
98
133
|
|
simtools/layout/array_layout.py
CHANGED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""Retrieve, merge, and write layouts from CTAO common identifiers repository."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import simtools.utils.general as gen
|
|
7
|
+
from simtools.data_model.metadata_collector import MetadataCollector
|
|
8
|
+
from simtools.data_model.model_data_writer import ModelDataWriter
|
|
9
|
+
from simtools.io_operations import io_handler
|
|
10
|
+
from simtools.utils import names
|
|
11
|
+
|
|
12
|
+
_logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def retrieve_array_layouts(site, repository_url, branch_name="main"):
|
|
16
|
+
"""
|
|
17
|
+
Retrieve array layouts from CTAO common identifiers repository.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
site : str
|
|
22
|
+
Site identifier.
|
|
23
|
+
repository_url : str
|
|
24
|
+
URL or path to CTAO common identifiers
|
|
25
|
+
branch_name : str
|
|
26
|
+
Repository branch to use for CTAO common identifiers.
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
dict
|
|
31
|
+
Array layouts for all CTAO sites.
|
|
32
|
+
"""
|
|
33
|
+
_logger.info(f"Retrieving array layouts from {repository_url} on branch {branch_name}.")
|
|
34
|
+
|
|
35
|
+
if gen.is_url(repository_url):
|
|
36
|
+
array_element_ids = gen.collect_data_from_http(
|
|
37
|
+
url=f"{repository_url}/{branch_name}/array-element-ids.json"
|
|
38
|
+
)
|
|
39
|
+
sub_arrays = gen.collect_data_from_http(
|
|
40
|
+
url=f"{repository_url}/{branch_name}/subarray-ids.json"
|
|
41
|
+
)
|
|
42
|
+
else:
|
|
43
|
+
array_element_ids = gen.collect_data_from_file(
|
|
44
|
+
Path(repository_url) / "array-element-ids.json"
|
|
45
|
+
)
|
|
46
|
+
sub_arrays = gen.collect_data_from_file(Path(repository_url) / "subarray-ids.json")
|
|
47
|
+
|
|
48
|
+
return _get_layouts_per_site(site, sub_arrays, array_element_ids)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _get_layouts_per_site(site, sub_arrays, array_element_ids):
|
|
52
|
+
"""
|
|
53
|
+
Get array layouts for CTAO sites.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
site : str
|
|
58
|
+
Site identifier.
|
|
59
|
+
sub_arrays : dict
|
|
60
|
+
Sub-array definitions.
|
|
61
|
+
array_element_ids : dict
|
|
62
|
+
Array element definitions.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
dict
|
|
67
|
+
Array layouts for CTAO sites.
|
|
68
|
+
"""
|
|
69
|
+
layouts_per_site = []
|
|
70
|
+
|
|
71
|
+
for array in sub_arrays.get("subarrays", []):
|
|
72
|
+
elements = []
|
|
73
|
+
for ids in array.get("array_element_ids", []):
|
|
74
|
+
element_name = _get_array_element_name(ids, array_element_ids)
|
|
75
|
+
if names.get_site_from_array_element_name(element_name) != site:
|
|
76
|
+
break
|
|
77
|
+
elements.append(element_name)
|
|
78
|
+
if len(elements) > 0:
|
|
79
|
+
array_layout = {
|
|
80
|
+
"name": array.get("name"),
|
|
81
|
+
"elements": elements,
|
|
82
|
+
}
|
|
83
|
+
layouts_per_site.append(array_layout)
|
|
84
|
+
|
|
85
|
+
_logger.info(f"CTAO array layout definition: {layouts_per_site}")
|
|
86
|
+
return layouts_per_site
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _get_array_element_name(ids, array_element_ids):
|
|
90
|
+
"""Return array element name for common identifier."""
|
|
91
|
+
for element in array_element_ids.get("array_elements", []):
|
|
92
|
+
if element.get("id") == ids:
|
|
93
|
+
return element.get("name")
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def merge_array_layouts(layouts_1, layouts_2):
|
|
98
|
+
"""
|
|
99
|
+
Compare array layout dictionaries and merge them.
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
layouts_1 : dict
|
|
104
|
+
Array layout dictionary 1.
|
|
105
|
+
layouts_2 : dict
|
|
106
|
+
Array layout dictionary 2.
|
|
107
|
+
|
|
108
|
+
Returns
|
|
109
|
+
-------
|
|
110
|
+
dict
|
|
111
|
+
Merged array layout dictionary based on layout_1.
|
|
112
|
+
"""
|
|
113
|
+
merged_layout = layouts_1
|
|
114
|
+
for layout_2 in layouts_2:
|
|
115
|
+
layout_found = False
|
|
116
|
+
for layout_1 in layouts_1.get("value", {}):
|
|
117
|
+
if sorted(layout_1["elements"]) == sorted(layout_2["elements"]):
|
|
118
|
+
print(
|
|
119
|
+
f"Equal telescope list: simtools '{layout_1['name']}' "
|
|
120
|
+
f"and CTAO '{layout_2['name']}'"
|
|
121
|
+
)
|
|
122
|
+
layout_1["name"] = layout_2["name"]
|
|
123
|
+
layout_found = True
|
|
124
|
+
if not layout_found:
|
|
125
|
+
merged_layout["value"].append(
|
|
126
|
+
{
|
|
127
|
+
"name": layout_2["name"],
|
|
128
|
+
"elements": layout_2["elements"],
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
_logger.info(f"Adding {layout_2['name']} with {layout_2['elements']}")
|
|
132
|
+
return merged_layout
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def write_array_layouts(array_layouts, args_dict, db_config):
|
|
136
|
+
"""
|
|
137
|
+
Write array layouts as model parameter.
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
args_dict : dict
|
|
142
|
+
Command line arguments.
|
|
143
|
+
array_layouts : dict
|
|
144
|
+
Array layouts to be written.
|
|
145
|
+
db_config : dict
|
|
146
|
+
Database configuration.
|
|
147
|
+
"""
|
|
148
|
+
_logger.info(f"Writing updated array layouts to the database for site {args_dict['site']}.")
|
|
149
|
+
|
|
150
|
+
io_handler_instance = io_handler.IOHandler()
|
|
151
|
+
io_handler_instance.set_paths(
|
|
152
|
+
output_path=args_dict["output_path"],
|
|
153
|
+
use_plain_output_path=args_dict["use_plain_output_path"],
|
|
154
|
+
)
|
|
155
|
+
output_file = io_handler_instance.get_output_file(
|
|
156
|
+
f"array-layouts-{args_dict['updated_parameter_version']}.json"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
ModelDataWriter.dump_model_parameter(
|
|
160
|
+
parameter_name="array_layouts",
|
|
161
|
+
value=array_layouts["value"],
|
|
162
|
+
instrument=args_dict["site"],
|
|
163
|
+
parameter_version=args_dict.get("updated_parameter_version"),
|
|
164
|
+
output_file=output_file,
|
|
165
|
+
use_plain_output_path=args_dict["use_plain_output_path"],
|
|
166
|
+
db_config=db_config,
|
|
167
|
+
)
|
|
168
|
+
MetadataCollector.dump(
|
|
169
|
+
args_dict,
|
|
170
|
+
output_file,
|
|
171
|
+
add_activity_name=True,
|
|
172
|
+
)
|