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
|
@@ -7,10 +7,12 @@ import tempfile
|
|
|
7
7
|
from io import BytesIO
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
|
|
10
|
+
import numpy as np
|
|
10
11
|
from astropy.table import Table
|
|
12
|
+
from scipy.optimize import curve_fit
|
|
11
13
|
|
|
12
14
|
import simtools.data_model.model_data_writer as writer
|
|
13
|
-
from simtools.constants import SCHEMA_PATH
|
|
15
|
+
from simtools.constants import MODEL_PARAMETER_SCHEMA_URL, SCHEMA_PATH
|
|
14
16
|
from simtools.data_model import validate_data
|
|
15
17
|
from simtools.data_model.metadata_collector import MetadataCollector
|
|
16
18
|
from simtools.io_operations import io_handler
|
|
@@ -44,12 +46,24 @@ class SinglePhotonElectronSpectrum:
|
|
|
44
46
|
)
|
|
45
47
|
self.io_handler = io_handler.IOHandler()
|
|
46
48
|
self.data = "" # Single photon electron spectrum data (as string)
|
|
49
|
+
self.args_dict["metadata_product_data_name"] = "single_pe_spectrum"
|
|
50
|
+
self.args_dict["metadata_product_data_url"] = (
|
|
51
|
+
MODEL_PARAMETER_SCHEMA_URL + "/pm_photoelectron_spectrum.schema.yml"
|
|
52
|
+
)
|
|
47
53
|
self.metadata = MetadataCollector(args_dict=self.args_dict)
|
|
48
54
|
|
|
49
55
|
def derive_single_pe_spectrum(self):
|
|
50
56
|
"""Derive single photon electron spectrum."""
|
|
57
|
+
afterpulse_fitted_spectrum = (
|
|
58
|
+
self.fit_afterpulse_spectrum() if self.args_dict.get("fit_afterpulse") else None
|
|
59
|
+
)
|
|
60
|
+
|
|
51
61
|
if self.args_dict.get("use_norm_spe"):
|
|
52
|
-
return self._derive_spectrum_norm_spe(
|
|
62
|
+
return self._derive_spectrum_norm_spe(
|
|
63
|
+
input_spectrum=self.args_dict["input_spectrum"],
|
|
64
|
+
afterpulse_spectrum=self.args_dict.get("afterpulse_spectrum"),
|
|
65
|
+
afterpulse_fitted_spectrum=afterpulse_fitted_spectrum,
|
|
66
|
+
)
|
|
53
67
|
|
|
54
68
|
raise NotImplementedError(
|
|
55
69
|
"Derivation of single photon electron spectrum using a simtool is not yet implemented."
|
|
@@ -83,15 +97,27 @@ class SinglePhotonElectronSpectrum:
|
|
|
83
97
|
|
|
84
98
|
writer.ModelDataWriter.dump(
|
|
85
99
|
args_dict=self.args_dict,
|
|
86
|
-
metadata=self.metadata
|
|
100
|
+
metadata=self.metadata,
|
|
87
101
|
product_data=table,
|
|
88
102
|
validate_schema_file=None,
|
|
89
103
|
)
|
|
90
104
|
|
|
91
|
-
def _derive_spectrum_norm_spe(
|
|
105
|
+
def _derive_spectrum_norm_spe(
|
|
106
|
+
self, input_spectrum, afterpulse_spectrum, afterpulse_fitted_spectrum
|
|
107
|
+
):
|
|
92
108
|
"""
|
|
93
109
|
Derive single photon electron spectrum using sim_telarray tool 'norm_spe'.
|
|
94
110
|
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
input_spectrum : str
|
|
114
|
+
Input file with amplitude spectrum
|
|
115
|
+
(prompt spectrum only if afterpulse spectrum is given).
|
|
116
|
+
afterpulse_spectrum : str
|
|
117
|
+
Input file with afterpulse spectrum.
|
|
118
|
+
afterpulse_fitted_spectrum : astro.Table
|
|
119
|
+
Fitted afterpulse spectrum data.
|
|
120
|
+
|
|
95
121
|
Returns
|
|
96
122
|
-------
|
|
97
123
|
int
|
|
@@ -103,11 +129,13 @@ class SinglePhotonElectronSpectrum:
|
|
|
103
129
|
If the command execution fails.
|
|
104
130
|
"""
|
|
105
131
|
tmp_input_file = self._get_input_data(
|
|
106
|
-
input_file=
|
|
132
|
+
input_file=input_spectrum,
|
|
133
|
+
input_table=None,
|
|
107
134
|
frequency_column=self.prompt_column,
|
|
108
135
|
)
|
|
109
136
|
tmp_ap_file = self._get_input_data(
|
|
110
|
-
input_file=
|
|
137
|
+
input_file=afterpulse_spectrum,
|
|
138
|
+
input_table=afterpulse_fitted_spectrum,
|
|
111
139
|
frequency_column=self.afterpulse_column,
|
|
112
140
|
)
|
|
113
141
|
|
|
@@ -115,13 +143,14 @@ class SinglePhotonElectronSpectrum:
|
|
|
115
143
|
f"{self.args_dict['simtel_path']}/sim_telarray/bin/norm_spe",
|
|
116
144
|
"-r",
|
|
117
145
|
f"{self.args_dict['step_size']},{self.args_dict['max_amplitude']}",
|
|
118
|
-
tmp_input_file.name,
|
|
119
146
|
]
|
|
120
147
|
if tmp_ap_file:
|
|
121
|
-
command.
|
|
122
|
-
command.
|
|
148
|
+
command.extend(["-a", f"{tmp_ap_file.name}"])
|
|
149
|
+
command.extend(["-s", f"{self.args_dict['scale_afterpulse_spectrum']}"])
|
|
150
|
+
command.extend(["-t", f"{self.args_dict['afterpulse_amplitude_range'][0]}"])
|
|
151
|
+
command.append(tmp_input_file.name)
|
|
123
152
|
|
|
124
|
-
self._logger.
|
|
153
|
+
self._logger.info(f"Running norm_spe command: {' '.join(command)}")
|
|
125
154
|
try:
|
|
126
155
|
result = subprocess.run(command, capture_output=True, text=True, check=True)
|
|
127
156
|
except subprocess.CalledProcessError as exc:
|
|
@@ -138,24 +167,37 @@ class SinglePhotonElectronSpectrum:
|
|
|
138
167
|
self.data = result.stdout
|
|
139
168
|
return result.returncode
|
|
140
169
|
|
|
141
|
-
def _get_input_data(self, input_file, frequency_column):
|
|
170
|
+
def _get_input_data(self, input_file, input_table, frequency_column):
|
|
142
171
|
"""
|
|
143
|
-
Return input data
|
|
172
|
+
Return input data in the format required by the norm_spe tool as temporary file.
|
|
173
|
+
|
|
174
|
+
The norm_spe tool requires the data to be space separated values of the amplitude spectrum,
|
|
175
|
+
with two columns: amplitude and frequency.
|
|
176
|
+
Input is validated using the single_pe_spectrum schema (legacy input is not validated).
|
|
144
177
|
|
|
145
|
-
|
|
178
|
+
Parameters
|
|
179
|
+
----------
|
|
180
|
+
input_file : str
|
|
181
|
+
Input file with amplitude spectrum.
|
|
182
|
+
input_table : astro.Table
|
|
183
|
+
Input table with amplitude spectrum.
|
|
184
|
+
frequency_column : str
|
|
185
|
+
Column name of the frequency data.
|
|
146
186
|
"""
|
|
147
|
-
input_data = ""
|
|
148
187
|
if not input_file:
|
|
149
188
|
return None
|
|
150
189
|
input_file = Path(input_file)
|
|
151
190
|
|
|
152
|
-
|
|
191
|
+
input_data = ""
|
|
192
|
+
if input_file.suffix == ".ecsv" or input_table:
|
|
153
193
|
data_validator = validate_data.DataValidator(
|
|
154
|
-
schema_file=self.input_schema,
|
|
194
|
+
schema_file=self.input_schema,
|
|
195
|
+
data_table=input_table,
|
|
196
|
+
data_file=input_file if input_table is None else None,
|
|
155
197
|
)
|
|
156
198
|
table = data_validator.validate_and_transform()
|
|
157
199
|
input_data = "\n".join(f"{row['amplitude']} {row[frequency_column]}" for row in table)
|
|
158
|
-
else:
|
|
200
|
+
else: # legacy format
|
|
159
201
|
with open(input_file, encoding="utf-8") as f:
|
|
160
202
|
input_data = (
|
|
161
203
|
f.read().replace(",", " ")
|
|
@@ -166,3 +208,113 @@ class SinglePhotonElectronSpectrum:
|
|
|
166
208
|
with tempfile.NamedTemporaryFile(delete=False, mode="w", encoding="utf-8") as tmpfile:
|
|
167
209
|
tmpfile.write(input_data)
|
|
168
210
|
return tmpfile
|
|
211
|
+
|
|
212
|
+
def fit_afterpulse_spectrum(self):
|
|
213
|
+
"""
|
|
214
|
+
Fit afterpulse spectrum with a exponential decay function.
|
|
215
|
+
|
|
216
|
+
Assume input to be in ecsv format with columns 'amplitude', 'frequency (afterpulsing)',
|
|
217
|
+
and 'frequency stdev (afterpulsing)'.
|
|
218
|
+
|
|
219
|
+
Returns
|
|
220
|
+
-------
|
|
221
|
+
astro.Table
|
|
222
|
+
Table with fitted afterpulse spectrum data.
|
|
223
|
+
"""
|
|
224
|
+
ap_min = self.args_dict["afterpulse_amplitude_range"][0]
|
|
225
|
+
fix_k = self.args_dict.get("afterpulse_decay_factor_fixed_value")
|
|
226
|
+
|
|
227
|
+
x, y, y_err = self._read_afterpulse_spectrum_for_fit(
|
|
228
|
+
self.args_dict.get("afterpulse_spectrum"), ap_min
|
|
229
|
+
)
|
|
230
|
+
fit_func, p0, bounds = self.afterpulse_fit_function(fix_k=fix_k)
|
|
231
|
+
|
|
232
|
+
result = curve_fit(fit_func, x, y, sigma=y_err, p0=p0, bounds=bounds, absolute_sigma=True)
|
|
233
|
+
params, covariance = result[0], result[1]
|
|
234
|
+
param_errors = np.sqrt(np.diag(covariance))
|
|
235
|
+
predicted = fit_func(x, *params)
|
|
236
|
+
self._afterpulse_fit_statistics(x, y, y_err, params, param_errors, predicted, fix_k)
|
|
237
|
+
|
|
238
|
+
# table with fitted afterpulse spectrum
|
|
239
|
+
x_fit = np.arange(
|
|
240
|
+
ap_min, self.args_dict["afterpulse_amplitude_range"][1], self.args_dict["step_size"]
|
|
241
|
+
)
|
|
242
|
+
y_fit = fit_func(x_fit, *params)
|
|
243
|
+
return Table([x_fit, y_fit], names=["amplitude", self.afterpulse_column])
|
|
244
|
+
|
|
245
|
+
def afterpulse_fit_function(self, fix_k):
|
|
246
|
+
"""
|
|
247
|
+
Afterpulse fit function: exponential decay with linear term in the exponent.
|
|
248
|
+
|
|
249
|
+
Starting values and bounds are set for the other parameters using values typical
|
|
250
|
+
for LSTN-design. Allows to fix the K parameter.
|
|
251
|
+
|
|
252
|
+
Parameters
|
|
253
|
+
----------
|
|
254
|
+
fix_K : float
|
|
255
|
+
Fixed value for K parameter.
|
|
256
|
+
|
|
257
|
+
Returns
|
|
258
|
+
-------
|
|
259
|
+
function
|
|
260
|
+
Exponential decay function with linear term in the exponent.
|
|
261
|
+
"""
|
|
262
|
+
|
|
263
|
+
def exp_decay(x, a, b, k):
|
|
264
|
+
return a * np.exp(-1.0 / (b * (k / (x + k))) * x)
|
|
265
|
+
|
|
266
|
+
p0 = [1e-5, 8.0] # Initial guess for [A, B] typical LSTN values
|
|
267
|
+
bounds_lower = [0, 0]
|
|
268
|
+
bounds_upper = [1.0, 20.0]
|
|
269
|
+
|
|
270
|
+
if fix_k is None:
|
|
271
|
+
p0.append(25.0)
|
|
272
|
+
bounds_lower.append(5.0)
|
|
273
|
+
bounds_upper.append(35.0)
|
|
274
|
+
return exp_decay, p0, (bounds_lower, bounds_upper)
|
|
275
|
+
|
|
276
|
+
def exp_decay_fixed_k(x, a, b):
|
|
277
|
+
return exp_decay(x, a, b, k=fix_k)
|
|
278
|
+
|
|
279
|
+
return exp_decay_fixed_k, p0, (bounds_lower, bounds_upper)
|
|
280
|
+
|
|
281
|
+
def _afterpulse_fit_statistics(self, x, y, y_err, params, param_errors, predicted, fix_k):
|
|
282
|
+
"""Print and return afterpulse fit statistics."""
|
|
283
|
+
chi2 = np.sum(((y - predicted) / y_err) ** 2)
|
|
284
|
+
ndf = len(x) - len(params)
|
|
285
|
+
|
|
286
|
+
result = {
|
|
287
|
+
"params": params.tolist(),
|
|
288
|
+
"errors": param_errors.tolist(),
|
|
289
|
+
"chi2_ndf": chi2 / ndf if ndf > 0 else np.nan,
|
|
290
|
+
}
|
|
291
|
+
if fix_k is not None:
|
|
292
|
+
result["params"].append(fix_k)
|
|
293
|
+
result["errors"].append(0.0)
|
|
294
|
+
|
|
295
|
+
self._logger.info(f"Fit results: {result}")
|
|
296
|
+
return result
|
|
297
|
+
|
|
298
|
+
def _read_afterpulse_spectrum_for_fit(self, afterpulse_spectrum, fit_min_pe):
|
|
299
|
+
"""
|
|
300
|
+
Read afterpulse spectrum data for fitting.
|
|
301
|
+
|
|
302
|
+
Parameters
|
|
303
|
+
----------
|
|
304
|
+
afterpulse_spectrum : str
|
|
305
|
+
Afterpulse spectrum data file.
|
|
306
|
+
fit_min_pe : float
|
|
307
|
+
Minimum amplitude for fitting.
|
|
308
|
+
|
|
309
|
+
Returns
|
|
310
|
+
-------
|
|
311
|
+
tuple
|
|
312
|
+
Tuple with x, y, y_err data for fitting.
|
|
313
|
+
"""
|
|
314
|
+
table = Table.read(afterpulse_spectrum, format="ascii.ecsv")
|
|
315
|
+
x = table["amplitude"]
|
|
316
|
+
y = table[self.afterpulse_column]
|
|
317
|
+
y_err = table["frequency stdev (afterpulsing)"]
|
|
318
|
+
mask = (x >= fit_min_pe) & (y > 0)
|
|
319
|
+
x_fit, y_fit, y_err_fit = x[mask], y[mask], y_err[mask]
|
|
320
|
+
return x_fit, y_fit, y_err_fit
|
simtools/constants.py
CHANGED
|
@@ -6,6 +6,8 @@ from importlib.resources import files
|
|
|
6
6
|
SCHEMA_PATH = files("simtools") / "schemas"
|
|
7
7
|
# Path to metadata jsonschema
|
|
8
8
|
METADATA_JSON_SCHEMA = SCHEMA_PATH / "metadata.metaschema.yml"
|
|
9
|
+
# Path to plotting configuration json schema
|
|
10
|
+
PLOT_CONFIG_SCHEMA = SCHEMA_PATH / "plot_configuration.metaschema.yml"
|
|
9
11
|
# Path to model parameter metaschema
|
|
10
12
|
MODEL_PARAMETER_METASCHEMA = SCHEMA_PATH / "model_parameter.metaschema.yml"
|
|
11
13
|
# Path to model parameter description metaschema
|
|
@@ -14,3 +16,8 @@ MODEL_PARAMETER_DESCRIPTION_METASCHEMA = (
|
|
|
14
16
|
)
|
|
15
17
|
# Path to model parameter schema files
|
|
16
18
|
MODEL_PARAMETER_SCHEMA_PATH = SCHEMA_PATH / "model_parameters"
|
|
19
|
+
# URL to model parameter schema files
|
|
20
|
+
MODEL_PARAMETER_SCHEMA_URL = (
|
|
21
|
+
"https://raw.githubusercontent.com/gammasim/simtools/main/src/simtools/schemas/"
|
|
22
|
+
"/model_parameters"
|
|
23
|
+
)
|
|
@@ -11,6 +11,8 @@ import logging
|
|
|
11
11
|
import uuid
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
|
|
14
|
+
import yaml
|
|
15
|
+
|
|
14
16
|
import simtools.constants
|
|
15
17
|
import simtools.utils.general as gen
|
|
16
18
|
import simtools.version
|
|
@@ -68,9 +70,7 @@ class MetadataCollector:
|
|
|
68
70
|
self.top_level_meta = gen.change_dict_keys_case(
|
|
69
71
|
data_dict=metadata_model.get_default_metadata_dict(), lower_case=True
|
|
70
72
|
)
|
|
71
|
-
self.input_metadata = self._read_input_metadata_from_file(
|
|
72
|
-
metadata_file_name=metadata_file_name
|
|
73
|
-
)
|
|
73
|
+
self.input_metadata = self._read_input_metadata_from_file(metadata_file_name)
|
|
74
74
|
self.collect_meta_data()
|
|
75
75
|
if clean_meta:
|
|
76
76
|
self.top_level_meta = self.clean_meta_data(self.top_level_meta)
|
|
@@ -103,6 +103,74 @@ class MetadataCollector:
|
|
|
103
103
|
pass
|
|
104
104
|
return self.top_level_meta
|
|
105
105
|
|
|
106
|
+
@staticmethod
|
|
107
|
+
def dump(args_dict, output_file, add_activity_name=False):
|
|
108
|
+
"""
|
|
109
|
+
Write metadata to file (static method).
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
args_dict: dict
|
|
114
|
+
Command line parameters
|
|
115
|
+
output_file: str or Path
|
|
116
|
+
Name of output file.
|
|
117
|
+
add_activity_name: bool
|
|
118
|
+
Add activity name to file name.
|
|
119
|
+
"""
|
|
120
|
+
collector = MetadataCollector(args_dict)
|
|
121
|
+
collector.write(output_file, add_activity_name=add_activity_name)
|
|
122
|
+
|
|
123
|
+
def write(self, yml_file=None, keys_lower_case=False, add_activity_name=False):
|
|
124
|
+
"""
|
|
125
|
+
Write toplevel metadata to file (yaml file format).
|
|
126
|
+
|
|
127
|
+
Parameters
|
|
128
|
+
----------
|
|
129
|
+
metadata: dict
|
|
130
|
+
Metadata to be stored
|
|
131
|
+
yml_file: str
|
|
132
|
+
Name of output file.
|
|
133
|
+
keys_lower_case: bool
|
|
134
|
+
Write yaml keys in lower case.
|
|
135
|
+
add_activity_name: bool
|
|
136
|
+
Add activity name to file name.
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
str
|
|
141
|
+
Name of output file
|
|
142
|
+
|
|
143
|
+
Raises
|
|
144
|
+
------
|
|
145
|
+
FileNotFoundError
|
|
146
|
+
If yml_file not found.
|
|
147
|
+
TypeError
|
|
148
|
+
If yml_file is not defined.
|
|
149
|
+
"""
|
|
150
|
+
metadata = self.get_top_level_metadata()
|
|
151
|
+
activity_name = metadata.get("cta", {}).get("activity", {}).get("name", "").rstrip(".")
|
|
152
|
+
suffix = f".{activity_name}.meta.yml" if add_activity_name else ".meta.yml"
|
|
153
|
+
|
|
154
|
+
if yml_file is None:
|
|
155
|
+
raise TypeError("No output file for metadata defined")
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
yml_file = names.file_name_with_version(yml_file, suffix)
|
|
159
|
+
with open(yml_file, "w", encoding="UTF-8") as file:
|
|
160
|
+
yaml.safe_dump(
|
|
161
|
+
gen.change_dict_keys_case(
|
|
162
|
+
gen.remove_substring_recursively_from_dict(metadata, substring="\n"),
|
|
163
|
+
keys_lower_case,
|
|
164
|
+
),
|
|
165
|
+
file,
|
|
166
|
+
sort_keys=False,
|
|
167
|
+
explicit_start=True,
|
|
168
|
+
)
|
|
169
|
+
self._logger.info(f"Writing metadata to {yml_file}")
|
|
170
|
+
return yml_file
|
|
171
|
+
except FileNotFoundError as exc:
|
|
172
|
+
raise FileNotFoundError(f"Error writing metadata to {yml_file}") from exc
|
|
173
|
+
|
|
106
174
|
def get_data_model_schema_file_name(self):
|
|
107
175
|
"""
|
|
108
176
|
Return data model schema file name.
|
|
@@ -136,12 +204,12 @@ class MetadataCollector:
|
|
|
136
204
|
self._logger.debug(f"Schema file from data model name: {self.data_model_name}")
|
|
137
205
|
return str(schema.get_model_parameter_schema_file(self.data_model_name))
|
|
138
206
|
|
|
139
|
-
# from input metadata
|
|
207
|
+
# from first entry in input metadata (least preferred)
|
|
140
208
|
try:
|
|
141
|
-
url = self.input_metadata[self.observatory]["product"]["data"]["model"]["url"]
|
|
209
|
+
url = self.input_metadata[0][self.observatory]["product"]["data"]["model"]["url"]
|
|
142
210
|
self._logger.debug(f"Schema file from input metadata: {url}")
|
|
143
211
|
return url
|
|
144
|
-
except KeyError:
|
|
212
|
+
except (KeyError, TypeError):
|
|
145
213
|
pass
|
|
146
214
|
|
|
147
215
|
self._logger.warning("No schema file found.")
|
|
@@ -170,7 +238,7 @@ class MetadataCollector:
|
|
|
170
238
|
Parameters
|
|
171
239
|
----------
|
|
172
240
|
from_input_meta: bool
|
|
173
|
-
Get site from input metadata (default: False)
|
|
241
|
+
Get site from first entry of input metadata (default: False)
|
|
174
242
|
|
|
175
243
|
Returns
|
|
176
244
|
-------
|
|
@@ -182,11 +250,11 @@ class MetadataCollector:
|
|
|
182
250
|
_site = (
|
|
183
251
|
self.top_level_meta[self.observatory]["instrument"]["site"]
|
|
184
252
|
if not from_input_meta
|
|
185
|
-
else self.input_metadata[self.observatory]["instrument"]["site"]
|
|
253
|
+
else self.input_metadata[0][self.observatory]["instrument"]["site"]
|
|
186
254
|
)
|
|
187
255
|
if _site is not None:
|
|
188
256
|
return names.validate_site_name(_site)
|
|
189
|
-
except KeyError:
|
|
257
|
+
except (KeyError, TypeError):
|
|
190
258
|
pass
|
|
191
259
|
return None
|
|
192
260
|
|
|
@@ -202,7 +270,13 @@ class MetadataCollector:
|
|
|
202
270
|
contact_dict["name"] = contact_dict.get("name") or self.args_dict.get("user_name")
|
|
203
271
|
if contact_dict["name"] is None:
|
|
204
272
|
self._logger.warning("No user name provided, take user info from system level.")
|
|
205
|
-
|
|
273
|
+
try:
|
|
274
|
+
contact_dict["name"] = getpass.getuser()
|
|
275
|
+
except Exception as exc: # pylint: disable=broad-except
|
|
276
|
+
contact_dict["name"] = "UNKNOWN_USER"
|
|
277
|
+
self._logger.warning(
|
|
278
|
+
f"Failed to get user name: {exc}, setting it to {contact_dict['name']} "
|
|
279
|
+
)
|
|
206
280
|
meta_dict = {
|
|
207
281
|
"email": "user_mail",
|
|
208
282
|
"orcid": "user_orcid",
|
|
@@ -221,17 +295,28 @@ class MetadataCollector:
|
|
|
221
295
|
Dictionary for context metadata fields.
|
|
222
296
|
|
|
223
297
|
"""
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
for key, value in self.input_metadata[self.observatory]["product"].items()
|
|
228
|
-
if key in {"description", "id", "creation_time", "valid", "format", "filename"}
|
|
229
|
-
}
|
|
230
|
-
self._fill_context_sim_list(context_dict["associated_data"], reduced_product_meta)
|
|
231
|
-
except (KeyError, TypeError):
|
|
232
|
-
self._logger.debug("No input product metadata appended to associated data.")
|
|
298
|
+
input_metadata = (
|
|
299
|
+
self.input_metadata if isinstance(self.input_metadata, list) else [self.input_metadata]
|
|
300
|
+
)
|
|
233
301
|
|
|
234
|
-
|
|
302
|
+
for metadata in input_metadata:
|
|
303
|
+
try: # wide try..except as for some cases we expect that there is no product metadata
|
|
304
|
+
reduced_product_meta = {
|
|
305
|
+
key: value
|
|
306
|
+
for key, value in metadata[self.observatory]["product"].items()
|
|
307
|
+
if key in {"description", "id", "creation_time", "valid", "format", "filename"}
|
|
308
|
+
}
|
|
309
|
+
if metadata[self.observatory].get("activity", {}).get("name"):
|
|
310
|
+
reduced_product_meta["activity_name"] = metadata[self.observatory][
|
|
311
|
+
"activity"
|
|
312
|
+
].get("name")
|
|
313
|
+
context_dict["associated_data"] = self._fill_context_sim_list(
|
|
314
|
+
context_dict["associated_data"], reduced_product_meta
|
|
315
|
+
)
|
|
316
|
+
except (KeyError, TypeError):
|
|
317
|
+
self._logger.debug("No input product metadata appended to associated data.")
|
|
318
|
+
|
|
319
|
+
def _read_input_metadata_from_file(self, metadata_file_name_expression=None):
|
|
235
320
|
"""
|
|
236
321
|
Read and validate input metadata from file.
|
|
237
322
|
|
|
@@ -240,8 +325,8 @@ class MetadataCollector:
|
|
|
240
325
|
|
|
241
326
|
Parameter
|
|
242
327
|
---------
|
|
243
|
-
|
|
244
|
-
Name of metadata file.
|
|
328
|
+
metadata_file_name_expression: str or Path
|
|
329
|
+
Name of metadata file (regular expressions allowed).
|
|
245
330
|
|
|
246
331
|
Returns
|
|
247
332
|
-------
|
|
@@ -256,31 +341,32 @@ class MetadataCollector:
|
|
|
256
341
|
if metadata does not exist
|
|
257
342
|
|
|
258
343
|
"""
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
344
|
+
metadata_file_names = (
|
|
345
|
+
metadata_file_name_expression
|
|
346
|
+
or self.args_dict.get("input_meta")
|
|
347
|
+
or self.args_dict.get("input")
|
|
263
348
|
)
|
|
264
349
|
|
|
265
|
-
|
|
350
|
+
try:
|
|
351
|
+
metadata_files = gen.resolve_file_patterns(metadata_file_names)
|
|
352
|
+
except ValueError:
|
|
266
353
|
self._logger.debug("No input metadata file defined.")
|
|
267
|
-
return
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
354
|
+
return None
|
|
355
|
+
|
|
356
|
+
metadata = []
|
|
357
|
+
for metadata_file in metadata_files:
|
|
358
|
+
self._logger.debug(f"Reading meta data from {metadata_file}")
|
|
359
|
+
if Path(metadata_file).suffix in (".yaml", ".yml", ".json"):
|
|
360
|
+
_input_metadata = self._read_input_metadata_from_yml_or_json(metadata_file)
|
|
361
|
+
elif Path(metadata_file).suffix == ".ecsv":
|
|
362
|
+
_input_metadata = self._read_input_metadata_from_ecsv(metadata_file)
|
|
363
|
+
else:
|
|
364
|
+
raise gen.InvalidConfigDataError(f"Unknown metadata file format: {metadata_file}")
|
|
277
365
|
|
|
278
|
-
|
|
366
|
+
schema.validate_dict_using_schema(_input_metadata, schema_file=METADATA_JSON_SCHEMA)
|
|
367
|
+
metadata.append(gen.change_dict_keys_case(_input_metadata, lower_case=True))
|
|
279
368
|
|
|
280
|
-
return
|
|
281
|
-
self._process_metadata_from_file(_input_metadata),
|
|
282
|
-
lower_case=True,
|
|
283
|
-
)
|
|
369
|
+
return metadata
|
|
284
370
|
|
|
285
371
|
def _read_input_metadata_from_ecsv(self, metadata_file_name):
|
|
286
372
|
"""Read input metadata from ecsv file."""
|
|
@@ -348,13 +434,23 @@ class MetadataCollector:
|
|
|
348
434
|
pass
|
|
349
435
|
|
|
350
436
|
# DATA:MODEL
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
437
|
+
product_dict["data"]["model"]["name"] = (
|
|
438
|
+
self.schema_dict.get("name")
|
|
439
|
+
or self.args_dict.get("metadata_product_data_name")
|
|
440
|
+
or "undefined_model_name"
|
|
441
|
+
)
|
|
442
|
+
product_dict["data"]["model"]["version"] = self.schema_dict.get("version", "0.0.0")
|
|
443
|
+
product_dict["data"]["model"]["type"] = self.schema_dict.get("meta_schema", None)
|
|
444
|
+
product_dict["data"]["model"]["url"] = self.schema_file or self.args_dict.get(
|
|
445
|
+
"metadata_product_data_url"
|
|
446
|
+
)
|
|
355
447
|
|
|
356
|
-
product_dict["
|
|
357
|
-
product_dict["
|
|
448
|
+
product_dict["filename"] = str(self.args_dict.get("output_file", ""))
|
|
449
|
+
product_dict["format"] = (
|
|
450
|
+
self.args_dict.get("output_file_format")
|
|
451
|
+
or Path(product_dict["filename"]).suffix.lstrip(".")
|
|
452
|
+
or None
|
|
453
|
+
)
|
|
358
454
|
|
|
359
455
|
def _fill_instrument_meta(self, instrument_dict):
|
|
360
456
|
"""
|
|
@@ -369,14 +465,17 @@ class MetadataCollector:
|
|
|
369
465
|
Dictionary for instrument metadata fields.
|
|
370
466
|
|
|
371
467
|
"""
|
|
372
|
-
instrument_dict["site"] = self.args_dict.get("site"
|
|
373
|
-
instrument_dict["ID"] = self.args_dict.get("instrument") or self.args_dict.get(
|
|
374
|
-
"telescope", None
|
|
375
|
-
)
|
|
468
|
+
instrument_dict["site"] = self.args_dict.get("site")
|
|
469
|
+
instrument_dict["ID"] = self.args_dict.get("instrument") or self.args_dict.get("telescope")
|
|
376
470
|
if instrument_dict["ID"]:
|
|
377
471
|
instrument_dict["class"] = names.get_collection_name_from_array_element_name(
|
|
378
472
|
instrument_dict["ID"], False
|
|
379
473
|
)
|
|
474
|
+
instrument_dict["type"] = (
|
|
475
|
+
names.get_array_element_type_from_name(instrument_dict["ID"])
|
|
476
|
+
if not instrument_dict.get("type")
|
|
477
|
+
else instrument_dict["type"]
|
|
478
|
+
)
|
|
380
479
|
|
|
381
480
|
def _fill_process_meta(self, process_dict):
|
|
382
481
|
"""
|
|
@@ -460,15 +559,14 @@ class MetadataCollector:
|
|
|
460
559
|
Updated meta list.
|
|
461
560
|
|
|
462
561
|
"""
|
|
463
|
-
if
|
|
562
|
+
if not new_entry_dict:
|
|
464
563
|
return []
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
meta_list = [new_entry_dict]
|
|
564
|
+
if meta_list is None or not meta_list:
|
|
565
|
+
return [new_entry_dict]
|
|
566
|
+
if self._all_values_none(meta_list[0]):
|
|
567
|
+
meta_list[0] = new_entry_dict
|
|
568
|
+
else:
|
|
569
|
+
meta_list.append(new_entry_dict)
|
|
472
570
|
return meta_list
|
|
473
571
|
|
|
474
572
|
def _process_metadata_from_file(self, meta_dict):
|
|
@@ -533,7 +631,7 @@ class MetadataCollector:
|
|
|
533
631
|
"""
|
|
534
632
|
try:
|
|
535
633
|
for document in _input_metadata["context"][key]:
|
|
536
|
-
self._fill_context_sim_list(context_dict[key], document)
|
|
634
|
+
context_dict[key] = self._fill_context_sim_list(context_dict[key], document)
|
|
537
635
|
except KeyError:
|
|
538
636
|
pass
|
|
539
637
|
|