gammasimtools 0.9.0__py3-none-any.whl → 0.11.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.9.0.dist-info → gammasimtools-0.11.0.dist-info}/METADATA +4 -2
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/RECORD +133 -117
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/entry_points.txt +6 -1
- simtools/_version.py +9 -4
- simtools/applications/calculate_trigger_rate.py +15 -38
- simtools/applications/convert_all_model_parameters_from_simtel.py +9 -29
- simtools/applications/convert_geo_coordinates_of_array_elements.py +47 -45
- simtools/applications/convert_model_parameter_from_simtel.py +2 -3
- simtools/applications/db_add_file_to_db.py +1 -3
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +110 -0
- simtools/applications/db_add_value_from_json_to_db.py +1 -2
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +6 -6
- simtools/applications/db_get_file_from_db.py +11 -12
- simtools/applications/db_get_parameter_from_db.py +26 -35
- simtools/applications/derive_mirror_rnda.py +1 -2
- simtools/applications/derive_photon_electron_spectrum.py +99 -0
- simtools/applications/derive_psf_parameters.py +1 -0
- simtools/applications/docs_produce_array_element_report.py +71 -0
- simtools/applications/docs_produce_model_parameter_reports.py +63 -0
- simtools/applications/generate_array_config.py +17 -17
- simtools/applications/generate_corsika_histograms.py +2 -2
- simtools/applications/generate_regular_arrays.py +19 -17
- simtools/applications/generate_simtel_array_histograms.py +11 -48
- simtools/applications/production_derive_limits.py +95 -0
- simtools/applications/production_generate_simulation_config.py +37 -33
- simtools/applications/production_scale_events.py +4 -9
- simtools/applications/run_application.py +165 -0
- simtools/applications/simulate_light_emission.py +0 -4
- simtools/applications/simulate_prod.py +1 -1
- simtools/applications/simulate_prod_htcondor_generator.py +26 -26
- simtools/applications/submit_data_from_external.py +12 -4
- simtools/applications/submit_model_parameter_from_external.py +18 -11
- simtools/applications/validate_camera_efficiency.py +2 -2
- simtools/applications/validate_file_using_schema.py +26 -22
- simtools/camera/single_photon_electron_spectrum.py +168 -0
- simtools/configuration/commandline_parser.py +37 -1
- simtools/configuration/configurator.py +8 -10
- simtools/constants.py +10 -3
- simtools/corsika/corsika_config.py +19 -17
- simtools/corsika/corsika_histograms.py +5 -7
- simtools/corsika/corsika_histograms_visualize.py +2 -4
- simtools/data_model/data_reader.py +0 -3
- simtools/data_model/metadata_collector.py +20 -12
- simtools/data_model/metadata_model.py +8 -124
- simtools/data_model/model_data_writer.py +81 -75
- simtools/data_model/schema.py +220 -0
- simtools/data_model/validate_data.py +79 -68
- simtools/db/db_handler.py +350 -492
- simtools/db/db_model_upload.py +139 -0
- simtools/dependencies.py +112 -0
- simtools/io_operations/hdf5_handler.py +54 -24
- simtools/layout/array_layout.py +38 -32
- simtools/model/array_model.py +13 -7
- simtools/model/model_parameter.py +55 -54
- simtools/model/site_model.py +2 -2
- simtools/production_configuration/calculate_statistical_errors_grid_point.py +119 -145
- simtools/production_configuration/event_scaler.py +9 -35
- simtools/production_configuration/generate_simulation_config.py +9 -44
- simtools/production_configuration/interpolation_handler.py +9 -15
- simtools/production_configuration/limits_calculation.py +202 -0
- simtools/reporting/docs_read_parameters.py +310 -0
- simtools/runners/corsika_simtel_runner.py +4 -4
- simtools/schemas/{integration_tests_config.metaschema.yml → application_workflow.metaschema.yml} +61 -27
- simtools/schemas/array_elements.yml +8 -0
- simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +39 -0
- simtools/schemas/input/single_pe_spectrum.schema.yml +38 -0
- simtools/schemas/model_parameter.metaschema.yml +103 -2
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +4 -1
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +1 -1
- simtools/schemas/model_parameters/array_window.schema.yml +37 -0
- simtools/schemas/model_parameters/asum_clipping.schema.yml +0 -4
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +4 -2
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +2 -0
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_offset.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +0 -2
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_noise.schema.yml +3 -3
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +33 -0
- 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_photons.schema.yml +2 -2
- 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/random_generator.schema.yml +1 -1
- simtools/schemas/model_parameters/sampled_output.schema.yml +1 -1
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
- simtools/schemas/production_configuration_metrics.schema.yml +68 -0
- simtools/schemas/production_tables.schema.yml +41 -0
- simtools/simtel/simtel_config_reader.py +1 -2
- simtools/simtel/simtel_config_writer.py +6 -8
- simtools/simtel/simtel_io_histogram.py +32 -68
- simtools/simtel/simtel_io_histograms.py +17 -34
- simtools/simtel/simulator_array.py +2 -1
- simtools/simtel/simulator_camera_efficiency.py +6 -3
- simtools/simtel/simulator_light_emission.py +5 -6
- simtools/simtel/simulator_ray_tracing.py +3 -4
- simtools/testing/configuration.py +2 -1
- simtools/testing/helpers.py +6 -13
- simtools/testing/validate_output.py +141 -47
- simtools/utils/general.py +114 -14
- simtools/utils/names.py +299 -157
- simtools/utils/value_conversion.py +17 -13
- simtools/version.py +2 -2
- simtools/visualization/legend_handlers.py +2 -0
- simtools/applications/db_add_model_parameters_from_repository_to_db.py +0 -176
- simtools/db/db_array_elements.py +0 -130
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/LICENSE +0 -0
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/top_level.txt +0 -0
- /simtools/{camera_efficiency.py → camera/camera_efficiency.py} +0 -0
|
@@ -5,16 +5,14 @@ import os
|
|
|
5
5
|
import re
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
|
-
import jsonschema
|
|
9
8
|
import numpy as np
|
|
10
9
|
from astropy import units as u
|
|
11
10
|
from astropy.table import Column, Table, unique
|
|
12
11
|
from astropy.utils.diff import report_diff_values
|
|
13
12
|
|
|
14
13
|
import simtools.utils.general as gen
|
|
15
|
-
from simtools.
|
|
16
|
-
from simtools.
|
|
17
|
-
from simtools.utils import value_conversion
|
|
14
|
+
from simtools.data_model import schema
|
|
15
|
+
from simtools.utils import names, value_conversion
|
|
18
16
|
|
|
19
17
|
__all__ = ["DataValidator"]
|
|
20
18
|
|
|
@@ -81,7 +79,7 @@ class DataValidator:
|
|
|
81
79
|
|
|
82
80
|
"""
|
|
83
81
|
if self.data_file_name:
|
|
84
|
-
self.validate_data_file()
|
|
82
|
+
self.validate_data_file(is_model_parameter)
|
|
85
83
|
if isinstance(self.data_dict, dict):
|
|
86
84
|
return self._validate_data_dict(is_model_parameter, lists_as_strings)
|
|
87
85
|
if isinstance(self.data_table, Table):
|
|
@@ -89,11 +87,16 @@ class DataValidator:
|
|
|
89
87
|
self._logger.error("No data or data table to validate")
|
|
90
88
|
raise TypeError
|
|
91
89
|
|
|
92
|
-
def validate_data_file(self):
|
|
90
|
+
def validate_data_file(self, is_model_parameter=None):
|
|
93
91
|
"""
|
|
94
92
|
Open data file and read data from file.
|
|
95
93
|
|
|
96
94
|
Doing this successfully is understood as file validation.
|
|
95
|
+
|
|
96
|
+
Parameters
|
|
97
|
+
----------
|
|
98
|
+
is_model_parameter: bool
|
|
99
|
+
This is a model parameter file.
|
|
97
100
|
"""
|
|
98
101
|
try:
|
|
99
102
|
if Path(self.data_file_name).suffix in (".yml", ".yaml", ".json"):
|
|
@@ -104,14 +107,30 @@ class DataValidator:
|
|
|
104
107
|
self._logger.info(f"Validating tabled data from: {self.data_file_name}")
|
|
105
108
|
except (AttributeError, TypeError):
|
|
106
109
|
pass
|
|
110
|
+
if is_model_parameter:
|
|
111
|
+
self.validate_parameter_and_file_name()
|
|
107
112
|
|
|
108
113
|
def validate_parameter_and_file_name(self):
|
|
109
|
-
"""
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
"""
|
|
115
|
+
Validate model parameter file name.
|
|
116
|
+
|
|
117
|
+
Expect that the following convention is used:
|
|
118
|
+
|
|
119
|
+
- file name starts with the parameter name
|
|
120
|
+
- file name ends with parameter version string
|
|
121
|
+
|
|
122
|
+
"""
|
|
123
|
+
file_stem = Path(self.data_file_name).stem
|
|
124
|
+
param = self.data_dict.get("parameter")
|
|
125
|
+
param_version = self.data_dict.get("parameter_version")
|
|
126
|
+
if not file_stem.startswith(param):
|
|
127
|
+
raise ValueError(f"Mismatch: parameter '{param}' vs. file '{file_stem}'.")
|
|
128
|
+
|
|
129
|
+
if param_version and not file_stem.endswith(param_version):
|
|
130
|
+
raise ValueError(f"Mismatch: version '{param_version}' vs. file '{file_stem}'.")
|
|
131
|
+
|
|
132
|
+
if param_version is None:
|
|
133
|
+
self._logger.warning(f"File '{file_stem}' has no parameter version defined.")
|
|
115
134
|
|
|
116
135
|
@staticmethod
|
|
117
136
|
def validate_model_parameter(par_dict):
|
|
@@ -129,7 +148,7 @@ class DataValidator:
|
|
|
129
148
|
Validated data dictionary
|
|
130
149
|
"""
|
|
131
150
|
data_validator = DataValidator(
|
|
132
|
-
schema_file=
|
|
151
|
+
schema_file=schema.get_model_parameter_schema_file(f"{par_dict['parameter']}"),
|
|
133
152
|
data_dict=par_dict,
|
|
134
153
|
check_exact_data_type=False,
|
|
135
154
|
)
|
|
@@ -158,9 +177,7 @@ class DataValidator:
|
|
|
158
177
|
if is_model_parameter:
|
|
159
178
|
self._prepare_model_parameter()
|
|
160
179
|
|
|
161
|
-
|
|
162
|
-
raise KeyError("Data dict does not contain a 'name' or 'parameter' key.")
|
|
163
|
-
self._data_description = self._read_validation_schema(self.schema_file_name, _name)
|
|
180
|
+
self._data_description = self._read_validation_schema(self.schema_file_name)
|
|
164
181
|
|
|
165
182
|
value_as_list, unit_as_list = self._get_value_and_units_as_lists()
|
|
166
183
|
|
|
@@ -174,7 +191,17 @@ class DataValidator:
|
|
|
174
191
|
else:
|
|
175
192
|
self.data_dict["value"], self.data_dict["unit"] = value_as_list, unit_as_list
|
|
176
193
|
|
|
177
|
-
self.
|
|
194
|
+
if self.data_dict.get("instrument"):
|
|
195
|
+
if self.data_dict["instrument"] == self.data_dict["site"]: # site parameters
|
|
196
|
+
names.validate_site_name(self.data_dict["site"])
|
|
197
|
+
else:
|
|
198
|
+
names.validate_array_element_name(self.data_dict["instrument"])
|
|
199
|
+
self._check_site_and_array_element_consistency(
|
|
200
|
+
self.data_dict.get("instrument"), self.data_dict.get("site")
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
for version_string in ("version", "parameter_version", "model_version"):
|
|
204
|
+
self._check_version_string(self.data_dict.get(version_string))
|
|
178
205
|
|
|
179
206
|
if lists_as_strings:
|
|
180
207
|
self._convert_results_to_model_format()
|
|
@@ -188,8 +215,9 @@ class DataValidator:
|
|
|
188
215
|
Take into account different data types and allow to use json_schema for testing.
|
|
189
216
|
"""
|
|
190
217
|
if self._get_data_description(index).get("type", None) == "dict":
|
|
191
|
-
|
|
192
|
-
self.data_dict["value"],
|
|
218
|
+
schema.validate_dict_using_schema(
|
|
219
|
+
data=self.data_dict["value"],
|
|
220
|
+
json_schema=self._get_data_description(index).get("json_schema"),
|
|
193
221
|
)
|
|
194
222
|
else:
|
|
195
223
|
self._check_data_type(np.array(value).dtype, index)
|
|
@@ -235,27 +263,6 @@ class DataValidator:
|
|
|
235
263
|
except TypeError:
|
|
236
264
|
return [None], target_unit
|
|
237
265
|
|
|
238
|
-
def _validate_data_dict_using_json_schema(self, data, json_schema):
|
|
239
|
-
"""
|
|
240
|
-
Validate a dictionary using a json schema.
|
|
241
|
-
|
|
242
|
-
Parameters
|
|
243
|
-
----------
|
|
244
|
-
data: dict
|
|
245
|
-
Data dictionary
|
|
246
|
-
json_schema: dict
|
|
247
|
-
JSON schema
|
|
248
|
-
"""
|
|
249
|
-
if json_schema is None:
|
|
250
|
-
self._logger.debug("Skipping validation of dict type")
|
|
251
|
-
return
|
|
252
|
-
self._logger.debug("Validation of dict type using JSON schema")
|
|
253
|
-
try:
|
|
254
|
-
jsonschema.validate(data, json_schema, format_checker=format_checkers.format_checker)
|
|
255
|
-
except jsonschema.exceptions.ValidationError as exc:
|
|
256
|
-
self._logger.error(f"Validation error: {exc}")
|
|
257
|
-
raise exc
|
|
258
|
-
|
|
259
266
|
def _validate_data_table(self):
|
|
260
267
|
"""Validate tabulated data."""
|
|
261
268
|
try:
|
|
@@ -692,7 +699,7 @@ class DataValidator:
|
|
|
692
699
|
|
|
693
700
|
return False
|
|
694
701
|
|
|
695
|
-
def _read_validation_schema(self, schema_file
|
|
702
|
+
def _read_validation_schema(self, schema_file):
|
|
696
703
|
"""
|
|
697
704
|
Read validation schema from file.
|
|
698
705
|
|
|
@@ -700,11 +707,6 @@ class DataValidator:
|
|
|
700
707
|
----------
|
|
701
708
|
schema_file: Path
|
|
702
709
|
Schema file describing input data.
|
|
703
|
-
If this is a directory, a filename of
|
|
704
|
-
'<par>.schema.yml' is assumed.
|
|
705
|
-
parameter: str
|
|
706
|
-
Parameter name of required schema
|
|
707
|
-
(if None, return first schema in file)
|
|
708
710
|
|
|
709
711
|
Returns
|
|
710
712
|
-------
|
|
@@ -715,17 +717,11 @@ class DataValidator:
|
|
|
715
717
|
------
|
|
716
718
|
KeyError
|
|
717
719
|
if 'data' can not be read from dict in schema file
|
|
718
|
-
|
|
719
720
|
"""
|
|
720
721
|
try:
|
|
721
|
-
if Path(schema_file).is_dir():
|
|
722
|
-
return gen.collect_data_from_file(
|
|
723
|
-
file_name=Path(schema_file) / (parameter + ".schema.yml"),
|
|
724
|
-
)["data"]
|
|
725
722
|
return gen.collect_data_from_file(file_name=schema_file)["data"]
|
|
726
|
-
except KeyError:
|
|
727
|
-
|
|
728
|
-
raise
|
|
723
|
+
except KeyError as exc:
|
|
724
|
+
raise KeyError(f"Error reading validation schema from {schema_file}") from exc
|
|
729
725
|
|
|
730
726
|
def _get_data_description(self, column_name=None, status_test=False):
|
|
731
727
|
"""
|
|
@@ -801,20 +797,14 @@ class DataValidator:
|
|
|
801
797
|
Converts strings to numerical values or lists of values, if required.
|
|
802
798
|
|
|
803
799
|
"""
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
self.data_dict["value"] = float(value) if _is_float else int(value)
|
|
813
|
-
else:
|
|
814
|
-
self.data_dict["value"] = gen.convert_string_to_list(value, is_float=_is_float)
|
|
815
|
-
|
|
816
|
-
if self.data_dict["unit"] is not None:
|
|
817
|
-
self.data_dict["unit"] = gen.convert_string_to_list(self.data_dict["unit"])
|
|
800
|
+
self.data_dict["value"], _ = value_conversion.split_value_and_unit(
|
|
801
|
+
self.data_dict["value"],
|
|
802
|
+
"int" in self.data_dict.get("type", "float"),
|
|
803
|
+
)
|
|
804
|
+
if isinstance(self.data_dict["unit"], str):
|
|
805
|
+
self.data_dict["unit"] = gen.convert_string_to_list(
|
|
806
|
+
self.data_dict["unit"], force_comma_separation=True
|
|
807
|
+
)
|
|
818
808
|
|
|
819
809
|
def _convert_results_to_model_format(self):
|
|
820
810
|
"""
|
|
@@ -849,3 +839,24 @@ class DataValidator:
|
|
|
849
839
|
if not re.match(semver_regex, version):
|
|
850
840
|
raise ValueError(f"Invalid version string '{version}'")
|
|
851
841
|
self._logger.debug(f"Valid version string '{version}'")
|
|
842
|
+
|
|
843
|
+
def _check_site_and_array_element_consistency(self, instrument, site):
|
|
844
|
+
"""
|
|
845
|
+
Check that site and array element names are consistent.
|
|
846
|
+
|
|
847
|
+
An example for an inconsistency is 'LSTN' at site 'South'
|
|
848
|
+
"""
|
|
849
|
+
if not all([instrument, site]) or "OBS" in instrument:
|
|
850
|
+
return
|
|
851
|
+
|
|
852
|
+
def to_sorted_list(value):
|
|
853
|
+
"""Return value as sorted list."""
|
|
854
|
+
return [value] if isinstance(value, str) else sorted(value)
|
|
855
|
+
|
|
856
|
+
instrument_site = to_sorted_list(names.get_site_from_array_element_name(instrument))
|
|
857
|
+
site = to_sorted_list(site)
|
|
858
|
+
|
|
859
|
+
if instrument_site != site:
|
|
860
|
+
raise ValueError(
|
|
861
|
+
f"Site '{site}' and instrument site '{instrument_site}' are inconsistent."
|
|
862
|
+
)
|