gammasimtools 0.14.0__py3-none-any.whl → 0.16.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.14.0.dist-info → gammasimtools-0.16.0.dist-info}/METADATA +2 -32
- {gammasimtools-0.14.0.dist-info → gammasimtools-0.16.0.dist-info}/RECORD +222 -214
- {gammasimtools-0.14.0.dist-info → gammasimtools-0.16.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.14.0.dist-info → gammasimtools-0.16.0.dist-info}/entry_points.txt +5 -2
- simtools/_version.py +2 -2
- simtools/applications/calculate_trigger_rate.py +10 -10
- simtools/applications/convert_all_model_parameters_from_simtel.py +16 -16
- simtools/applications/convert_model_parameter_from_simtel.py +1 -1
- simtools/applications/derive_psf_parameters.py +12 -9
- simtools/applications/docs_produce_array_element_report.py +3 -3
- simtools/applications/docs_produce_calibration_reports.py +49 -0
- simtools/applications/docs_produce_simulation_configuration_report.py +50 -0
- simtools/applications/{generate_simtel_array_histograms.py → generate_sim_telarray_histograms.py} +2 -2
- simtools/applications/production_derive_corsika_limits.py +63 -10
- simtools/applications/production_derive_statistics.py +125 -0
- simtools/applications/production_generate_grid.py +197 -0
- simtools/applications/production_generate_simulation_config.py +0 -10
- simtools/applications/simulate_light_emission.py +5 -13
- simtools/applications/simulate_prod.py +16 -4
- simtools/applications/validate_cumulative_psf.py +6 -4
- simtools/applications/validate_file_using_schema.py +7 -3
- simtools/applications/validate_optics.py +5 -4
- simtools/camera/camera_efficiency.py +14 -39
- simtools/configuration/commandline_parser.py +4 -3
- simtools/configuration/configurator.py +10 -0
- simtools/corsika/corsika_config.py +103 -5
- simtools/data_model/format_checkers.py +9 -0
- simtools/data_model/model_data_writer.py +3 -0
- simtools/data_model/schema.py +27 -16
- simtools/data_model/validate_data.py +27 -7
- simtools/db/db_handler.py +10 -4
- simtools/layout/array_layout.py +1 -0
- simtools/model/array_model.py +63 -29
- simtools/model/model_parameter.py +76 -51
- simtools/model/model_utils.py +43 -1
- simtools/model/site_model.py +3 -2
- simtools/model/telescope_model.py +4 -4
- simtools/production_configuration/calculate_statistical_errors_grid_point.py +0 -4
- simtools/production_configuration/{event_scaler.py → derive_production_statistics.py} +24 -20
- simtools/production_configuration/derive_production_statistics_handler.py +119 -0
- simtools/production_configuration/generate_production_grid.py +364 -0
- simtools/production_configuration/generate_simulation_config.py +9 -9
- simtools/production_configuration/interpolation_handler.py +16 -11
- simtools/ray_tracing/mirror_panel_psf.py +16 -20
- simtools/ray_tracing/psf_analysis.py +2 -2
- simtools/ray_tracing/ray_tracing.py +5 -1
- simtools/reporting/docs_read_parameters.py +361 -58
- simtools/runners/corsika_runner.py +11 -1
- simtools/runners/corsika_simtel_runner.py +80 -89
- simtools/runners/runner_services.py +17 -4
- simtools/runners/simtel_runner.py +27 -10
- simtools/schemas/model_parameter.metaschema.yml +4 -0
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +1 -0
- simtools/schemas/model_parameters/adjust_gain.schema.yml +2 -2
- simtools/schemas/model_parameters/array_element_position_ground.schema.yml +2 -2
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +2 -2
- simtools/schemas/model_parameters/array_window.schema.yml +2 -2
- simtools/schemas/model_parameters/asum_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/asum_shaping.schema.yml +2 -2
- simtools/schemas/model_parameters/asum_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/axes_offsets.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_body_diameter.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_body_shape.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_config_file.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_config_rotate.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_degraded_map.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_depth.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_filter.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_pixels.schema.yml +2 -2
- simtools/schemas/model_parameters/camera_transmission.schema.yml +2 -2
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +2 -2
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +2 -2
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +90 -1
- simtools/schemas/model_parameters/default_trigger.schema.yml +2 -2
- simtools/schemas/model_parameters/design_model.schema.yml +2 -2
- simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +2 -2
- simtools/schemas/model_parameters/disc_bins.schema.yml +2 -2
- simtools/schemas/model_parameters/disc_start.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/dish_shape_length.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +3 -3
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +2 -2
- simtools/schemas/model_parameters/effective_focal_length.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_amplitude.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_bins.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_max_signal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_mhz.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_noise.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +2 -2
- simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +2 -2
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/flatfielding.schema.yml +2 -2
- simtools/schemas/model_parameters/focal_length.schema.yml +2 -2
- simtools/schemas/model_parameters/focus_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/gain_variation.schema.yml +2 -2
- simtools/schemas/model_parameters/hg_lg_variation.schema.yml +2 -2
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +2 -2
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +2 -2
- simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +2 -2
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +2 -2
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +2 -2
- simtools/schemas/model_parameters/min_photons.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_class.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_focal_length.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_list.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +2 -2
- simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +2 -2
- simtools/schemas/model_parameters/multiplicity_offset.schema.yml +2 -2
- simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +2 -2
- simtools/schemas/model_parameters/nsb_offaxis.schema.yml +2 -2
- simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +2 -2
- simtools/schemas/model_parameters/num_gains.schema.yml +2 -2
- simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +2 -2
- simtools/schemas/model_parameters/optics_properties.schema.yml +2 -2
- simtools/schemas/model_parameters/pedestal_events.schema.yml +7 -3
- simtools/schemas/model_parameters/photon_delay.schema.yml +2 -2
- simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_average_gain.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_gain_index.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_transit_time.schema.yml +2 -2
- simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +2 -2
- simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +2 -2
- simtools/schemas/model_parameters/qe_variation.schema.yml +2 -2
- simtools/schemas/model_parameters/quantum_efficiency.schema.yml +2 -2
- simtools/schemas/model_parameters/random_focal_length.schema.yml +2 -2
- simtools/schemas/model_parameters/random_generator.schema.yml +2 -2
- simtools/schemas/model_parameters/random_mono_probability.schema.yml +2 -2
- simtools/schemas/model_parameters/sampled_output.schema.yml +2 -2
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +2 -2
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +2 -2
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +2 -2
- simtools/schemas/model_parameters/telescope_axis_height.schema.yml +2 -2
- simtools/schemas/model_parameters/telescope_random_angle.schema.yml +2 -2
- simtools/schemas/model_parameters/telescope_random_error.schema.yml +2 -2
- simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +2 -2
- simtools/schemas/model_parameters/telescope_transmission.schema.yml +2 -2
- simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +2 -2
- simtools/schemas/model_parameters/teltrig_min_time.schema.yml +2 -2
- simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +2 -2
- simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +2 -2
- simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +2 -2
- simtools/schemas/model_parameters/transit_time_error.schema.yml +2 -2
- simtools/schemas/model_parameters/transit_time_jitter.schema.yml +2 -2
- simtools/schemas/model_parameters/trigger_current_limit.schema.yml +2 -2
- simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +2 -2
- simtools/schemas/model_parameters/trigger_pixels.schema.yml +2 -2
- simtools/simtel/simtel_config_reader.py +21 -17
- simtools/simtel/simtel_config_writer.py +237 -65
- simtools/simtel/simtel_io_file_info.py +57 -0
- simtools/simtel/simtel_io_histogram.py +10 -14
- simtools/simtel/simtel_io_histograms.py +2 -2
- simtools/simtel/simtel_io_metadata.py +91 -0
- simtools/simtel/simulator_array.py +26 -12
- simtools/simtel/simulator_camera_efficiency.py +12 -6
- simtools/simtel/simulator_light_emission.py +6 -11
- simtools/simtel/simulator_ray_tracing.py +14 -4
- simtools/simulator.py +230 -66
- simtools/testing/configuration.py +12 -6
- simtools/testing/helpers.py +18 -0
- simtools/testing/sim_telarray_metadata.py +212 -0
- simtools/testing/validate_output.py +12 -5
- simtools/utils/general.py +18 -27
- simtools/utils/names.py +27 -5
- simtools/visualization/visualize.py +2 -2
- simtools/applications/production_scale_events.py +0 -185
- {gammasimtools-0.14.0.dist-info → gammasimtools-0.16.0.dist-info}/licenses/LICENSE +0 -0
- {gammasimtools-0.14.0.dist-info → gammasimtools-0.16.0.dist-info}/top_level.txt +0 -0
|
@@ -163,6 +163,7 @@ class Configurator:
|
|
|
163
163
|
self.config["activity_id"] = str(uuid.uuid4())
|
|
164
164
|
if self.config["label"] is None:
|
|
165
165
|
self.config["label"] = self.label
|
|
166
|
+
self._initialize_model_versions()
|
|
166
167
|
|
|
167
168
|
self._initialize_io_handler()
|
|
168
169
|
if output:
|
|
@@ -329,6 +330,15 @@ class Configurator:
|
|
|
329
330
|
|
|
330
331
|
self._fill_from_config_dict(_env_dict)
|
|
331
332
|
|
|
333
|
+
def _initialize_model_versions(self):
|
|
334
|
+
"""Initialize model versions."""
|
|
335
|
+
if (
|
|
336
|
+
self.config.get("model_version", None)
|
|
337
|
+
and isinstance(self.config["model_version"], list)
|
|
338
|
+
and len(self.config["model_version"]) == 1
|
|
339
|
+
):
|
|
340
|
+
self.config["model_version"] = self.config["model_version"][0]
|
|
341
|
+
|
|
332
342
|
def _initialize_io_handler(self):
|
|
333
343
|
"""Initialize IOHandler with input and output paths."""
|
|
334
344
|
_io_handler = io_handler.IOHandler()
|
|
@@ -124,9 +124,15 @@ class CorsikaConfig:
|
|
|
124
124
|
if db_config is None: # all following parameter require DB
|
|
125
125
|
return config
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
)
|
|
127
|
+
# If the user provided multiple model versions, we take the first one
|
|
128
|
+
# because for CORSIKA config we need only one and it doesn't matter which
|
|
129
|
+
model_versions = args_dict.get("model_version", None)
|
|
130
|
+
if not isinstance(model_versions, list):
|
|
131
|
+
model_versions = [model_versions]
|
|
132
|
+
self.assert_corsika_configurations_match(model_versions, db_config=db_config)
|
|
133
|
+
model_version = model_versions[0]
|
|
134
|
+
self._logger.debug(f"Using model version {model_version} for CORSIKA parameters")
|
|
135
|
+
db_model_parameters = ModelParameter(mongo_db_config=db_config, model_version=model_version)
|
|
130
136
|
parameters_from_db = db_model_parameters.get_simulation_software_parameters("corsika")
|
|
131
137
|
|
|
132
138
|
config["INTERACTION_FLAGS"] = self._corsika_configuration_interaction_flags(
|
|
@@ -140,6 +146,60 @@ class CorsikaConfig:
|
|
|
140
146
|
|
|
141
147
|
return config
|
|
142
148
|
|
|
149
|
+
def assert_corsika_configurations_match(self, model_versions, db_config=None):
|
|
150
|
+
"""
|
|
151
|
+
Assert that CORSIKA configurations match across all model versions.
|
|
152
|
+
|
|
153
|
+
Parameters
|
|
154
|
+
----------
|
|
155
|
+
model_versions : list
|
|
156
|
+
List of model versions to check.
|
|
157
|
+
db_config : dict, optional
|
|
158
|
+
Database configuration.
|
|
159
|
+
|
|
160
|
+
Raises
|
|
161
|
+
------
|
|
162
|
+
InvalidCorsikaInputError
|
|
163
|
+
If CORSIKA parameters are not identical across all model versions.
|
|
164
|
+
"""
|
|
165
|
+
if len(model_versions) < 2:
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
parameters_from_db_list = []
|
|
169
|
+
|
|
170
|
+
# Get parameters for all model versions
|
|
171
|
+
for model_version in model_versions:
|
|
172
|
+
db_model_parameters = ModelParameter(
|
|
173
|
+
mongo_db_config=db_config, model_version=model_version
|
|
174
|
+
)
|
|
175
|
+
parameters_from_db_list.append(
|
|
176
|
+
db_model_parameters.get_simulation_software_parameters("corsika")
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Parameters that can differ between model versions (e.g., i/o buffer size)
|
|
180
|
+
skip_parameters = ["corsika_iact_io_buffer", "corsika_iact_split_auto"]
|
|
181
|
+
|
|
182
|
+
# Check if all parameters match
|
|
183
|
+
for i in range(len(parameters_from_db_list) - 1):
|
|
184
|
+
for key in parameters_from_db_list[i]:
|
|
185
|
+
if key in skip_parameters:
|
|
186
|
+
continue
|
|
187
|
+
|
|
188
|
+
current_value = parameters_from_db_list[i][key]["value"]
|
|
189
|
+
next_value = parameters_from_db_list[i + 1][key]["value"]
|
|
190
|
+
|
|
191
|
+
if current_value != next_value:
|
|
192
|
+
self._logger.warning(
|
|
193
|
+
f"Parameter '{key}' mismatch between model versions:\n"
|
|
194
|
+
f" {model_versions[i]}: {current_value}\n"
|
|
195
|
+
f" {model_versions[i + 1]}: {next_value}"
|
|
196
|
+
)
|
|
197
|
+
raise InvalidCorsikaInputError(
|
|
198
|
+
f"CORSIKA parameter '{key}' differs between model versions "
|
|
199
|
+
f"{model_versions[i]} and {model_versions[i + 1]}. "
|
|
200
|
+
f"Values are {current_value} and {next_value} respectively."
|
|
201
|
+
)
|
|
202
|
+
|
|
143
203
|
def _corsika_configuration_from_user_input(self, args_dict):
|
|
144
204
|
"""
|
|
145
205
|
Get CORSIKA configuration from user input.
|
|
@@ -236,7 +296,45 @@ class CorsikaConfig:
|
|
|
236
296
|
|
|
237
297
|
def _input_config_corsika_starting_grammage(self, entry):
|
|
238
298
|
"""Return FIXCHI parameter CORSIKA format."""
|
|
239
|
-
|
|
299
|
+
value = self._get_starting_grammage_value(entry["value"])
|
|
300
|
+
return f"{value * u.Unit(entry['unit']).to('g/cm2')}"
|
|
301
|
+
|
|
302
|
+
def _get_starting_grammage_value(self, value_entry):
|
|
303
|
+
"""
|
|
304
|
+
Get appropriate starting grammage value from entry values.
|
|
305
|
+
|
|
306
|
+
Parameters
|
|
307
|
+
----------
|
|
308
|
+
value_entry : float or list
|
|
309
|
+
Value or list of grammage configurations
|
|
310
|
+
|
|
311
|
+
Returns
|
|
312
|
+
-------
|
|
313
|
+
float
|
|
314
|
+
Selected grammage value
|
|
315
|
+
"""
|
|
316
|
+
if not isinstance(value_entry, list):
|
|
317
|
+
return value_entry
|
|
318
|
+
|
|
319
|
+
tel_types = {tel.design_model for tel in self.array_model.telescope_model.values()}
|
|
320
|
+
particle = self.primary_particle.name
|
|
321
|
+
matched_values = self._get_matching_grammage_values(value_entry, tel_types, particle)
|
|
322
|
+
|
|
323
|
+
return min(matched_values) if matched_values else 0
|
|
324
|
+
|
|
325
|
+
def _get_matching_grammage_values(self, configs, tel_types, particle):
|
|
326
|
+
"""Get list of matching grammage values for particle and telescope types."""
|
|
327
|
+
matched = []
|
|
328
|
+
defaults = []
|
|
329
|
+
|
|
330
|
+
for config in configs:
|
|
331
|
+
if config.get("instrument") is None or config.get("instrument") in tel_types:
|
|
332
|
+
if config["primary_particle"] == particle:
|
|
333
|
+
matched.append(config["value"])
|
|
334
|
+
elif config["primary_particle"] == "default":
|
|
335
|
+
defaults.append(config["value"])
|
|
336
|
+
|
|
337
|
+
return matched if matched else defaults
|
|
240
338
|
|
|
241
339
|
def _input_config_corsika_particle_kinetic_energy_cutoff(self, entry):
|
|
242
340
|
"""Return ECUTS parameter CORSIKA format."""
|
|
@@ -587,7 +685,7 @@ class CorsikaConfig:
|
|
|
587
685
|
str
|
|
588
686
|
Output file name.
|
|
589
687
|
"""
|
|
590
|
-
sub_dir = "
|
|
688
|
+
sub_dir = "corsika_sim_telarray" if use_multipipe else "corsika"
|
|
591
689
|
config_file_name = self.get_corsika_config_file_name(file_type="config")
|
|
592
690
|
file_directory = self.io_handler.get_output_directory(label=self.label, sub_dir=sub_dir)
|
|
593
691
|
self._logger.debug(f"Creating directory {file_directory}")
|
|
@@ -5,6 +5,7 @@ import re
|
|
|
5
5
|
import astropy.units as u
|
|
6
6
|
import jsonschema
|
|
7
7
|
|
|
8
|
+
from simtools.corsika.primary_particle import PrimaryParticle
|
|
8
9
|
from simtools.utils import names
|
|
9
10
|
|
|
10
11
|
format_checker = jsonschema.FormatChecker()
|
|
@@ -50,3 +51,11 @@ def check_array_triggers_name(name):
|
|
|
50
51
|
raise ValueError(f"Array trigger name '{name}' does not match pattern '{pattern}'")
|
|
51
52
|
names.validate_array_element_type(re.match(pattern, name).group(1))
|
|
52
53
|
return True
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@format_checker.checks("common_particle_name")
|
|
57
|
+
def check_common_particle_name(name):
|
|
58
|
+
"""Validate common particle names for jsonschema."""
|
|
59
|
+
if name in PrimaryParticle.particle_names() or name == "default":
|
|
60
|
+
return True
|
|
61
|
+
raise ValueError(f"Invalid common particle name: '{name}'")
|
|
@@ -270,6 +270,9 @@ class ModelDataWriter:
|
|
|
270
270
|
"type": self._get_parameter_type(),
|
|
271
271
|
"file": self._parameter_is_a_file(),
|
|
272
272
|
"meta_parameter": False,
|
|
273
|
+
"model_parameter_schema_version": self.schema_dict.get(
|
|
274
|
+
"model_parameter_schema_version", "0.1.0"
|
|
275
|
+
),
|
|
273
276
|
}
|
|
274
277
|
return self.validate_and_transform(
|
|
275
278
|
product_data_dict=data_dict,
|
simtools/data_model/schema.py
CHANGED
|
@@ -18,7 +18,7 @@ from simtools.utils import names
|
|
|
18
18
|
_logger = logging.getLogger(__name__)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
def
|
|
21
|
+
def get_model_parameter_schema_files(schema_directory=MODEL_PARAMETER_SCHEMA_PATH):
|
|
22
22
|
"""
|
|
23
23
|
Return list of parameters and schema files located in schema file directory.
|
|
24
24
|
|
|
@@ -35,7 +35,8 @@ def get_get_model_parameter_schema_files(schema_directory=MODEL_PARAMETER_SCHEMA
|
|
|
35
35
|
raise FileNotFoundError(f"No schema files found in {schema_directory}")
|
|
36
36
|
parameters = []
|
|
37
37
|
for schema_file in schema_files:
|
|
38
|
-
|
|
38
|
+
# reading parameter 'name' only - first document in schema file should be ok
|
|
39
|
+
schema_dict = gen.collect_data_from_file(file_name=schema_file, yaml_document=0)
|
|
39
40
|
parameters.append(schema_dict.get("name"))
|
|
40
41
|
return parameters, schema_files
|
|
41
42
|
|
|
@@ -182,6 +183,15 @@ def load_schema(schema_file=None, schema_version=None):
|
|
|
182
183
|
return schema
|
|
183
184
|
|
|
184
185
|
|
|
186
|
+
def _get_array_element_list():
|
|
187
|
+
"""Build complete list of array elements including design types."""
|
|
188
|
+
elements = set(names.array_elements().keys())
|
|
189
|
+
for array_element in names.array_elements():
|
|
190
|
+
for design_type in names.array_element_design_types(array_element):
|
|
191
|
+
elements.add(f"{array_element}-{design_type}")
|
|
192
|
+
return sorted(elements)
|
|
193
|
+
|
|
194
|
+
|
|
185
195
|
def _add_array_elements(key, schema):
|
|
186
196
|
"""
|
|
187
197
|
Add list of array elements to schema.
|
|
@@ -200,22 +210,23 @@ def _add_array_elements(key, schema):
|
|
|
200
210
|
-------
|
|
201
211
|
dict
|
|
202
212
|
Schema dictionary with added array elements.
|
|
203
|
-
|
|
204
213
|
"""
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
def
|
|
208
|
-
if
|
|
209
|
-
|
|
210
|
-
sub_schema[key]["enum"] = list(
|
|
211
|
-
set(sub_schema[key]["enum"] + _list_of_array_elements)
|
|
212
|
-
)
|
|
213
|
-
else:
|
|
214
|
-
sub_schema[key]["enum"] = _list_of_array_elements
|
|
214
|
+
array_elements = _get_array_element_list()
|
|
215
|
+
|
|
216
|
+
def update_enum(sub_schema):
|
|
217
|
+
if "enum" in sub_schema and isinstance(sub_schema["enum"], list):
|
|
218
|
+
sub_schema["enum"] = list(set(sub_schema["enum"] + array_elements))
|
|
215
219
|
else:
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
220
|
+
sub_schema["enum"] = array_elements
|
|
221
|
+
|
|
222
|
+
def recursive_search(sub_schema, target_key):
|
|
223
|
+
if target_key in sub_schema:
|
|
224
|
+
update_enum(sub_schema[target_key])
|
|
225
|
+
return
|
|
226
|
+
|
|
227
|
+
for v in sub_schema.values():
|
|
228
|
+
if isinstance(v, dict):
|
|
229
|
+
recursive_search(v, target_key)
|
|
219
230
|
|
|
220
231
|
recursive_search(schema, key)
|
|
221
232
|
return schema
|
|
@@ -177,7 +177,11 @@ class DataValidator:
|
|
|
177
177
|
if is_model_parameter:
|
|
178
178
|
self._prepare_model_parameter()
|
|
179
179
|
|
|
180
|
-
self._data_description = self._read_validation_schema(
|
|
180
|
+
self._data_description = self._read_validation_schema(
|
|
181
|
+
self.schema_file_name,
|
|
182
|
+
# use 0.1.0 as default; this corresponds to the first definition of the schema
|
|
183
|
+
self.data_dict.get("model_parameter_schema_version", "0.1.0"),
|
|
184
|
+
)
|
|
181
185
|
|
|
182
186
|
value_as_list, unit_as_list = self._get_value_and_units_as_lists()
|
|
183
187
|
|
|
@@ -701,14 +705,20 @@ class DataValidator:
|
|
|
701
705
|
|
|
702
706
|
return False
|
|
703
707
|
|
|
704
|
-
def _read_validation_schema(self, schema_file):
|
|
708
|
+
def _read_validation_schema(self, schema_file, schema_version=None):
|
|
705
709
|
"""
|
|
706
710
|
Read validation schema from file.
|
|
707
711
|
|
|
712
|
+
The schema file can be a yaml file with several documents, each document
|
|
713
|
+
describing a different schema version. Returns first document if no
|
|
714
|
+
schema version is requested.
|
|
715
|
+
|
|
708
716
|
Parameters
|
|
709
717
|
----------
|
|
710
718
|
schema_file: Path
|
|
711
719
|
Schema file describing input data.
|
|
720
|
+
schema_version: str
|
|
721
|
+
Version of the schema to be used.
|
|
712
722
|
|
|
713
723
|
Returns
|
|
714
724
|
-------
|
|
@@ -719,11 +729,21 @@ class DataValidator:
|
|
|
719
729
|
------
|
|
720
730
|
KeyError
|
|
721
731
|
if 'data' can not be read from dict in schema file
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
732
|
+
ValueError
|
|
733
|
+
if schema version is not found in schema file
|
|
734
|
+
"""
|
|
735
|
+
schema_data = gen.collect_data_from_file(file_name=schema_file)
|
|
736
|
+
entries = schema_data if isinstance(schema_data, list) else [schema_data]
|
|
737
|
+
|
|
738
|
+
for entry in entries:
|
|
739
|
+
if not schema_version or entry.get("version") == schema_version:
|
|
740
|
+
try:
|
|
741
|
+
return entry["data"]
|
|
742
|
+
except KeyError as exc:
|
|
743
|
+
raise KeyError(f"Error reading validation schema from {schema_file}") from exc
|
|
744
|
+
raise ValueError(
|
|
745
|
+
f"Schema version {schema_version} not found in schema file {schema_file}. "
|
|
746
|
+
)
|
|
727
747
|
|
|
728
748
|
def _get_data_description(self, column_name=None, status_test=False):
|
|
729
749
|
"""
|
simtools/db/db_handler.py
CHANGED
|
@@ -122,9 +122,11 @@ class DatabaseHandler:
|
|
|
122
122
|
port=self.mongo_db_config["db_api_port"],
|
|
123
123
|
username=self.mongo_db_config["db_api_user"],
|
|
124
124
|
password=self.mongo_db_config["db_api_pw"],
|
|
125
|
-
authSource=
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
authSource=(
|
|
126
|
+
self.mongo_db_config.get("db_api_authentication_database")
|
|
127
|
+
if self.mongo_db_config.get("db_api_authentication_database")
|
|
128
|
+
else "admin"
|
|
129
|
+
),
|
|
128
130
|
directConnection=direct_connection,
|
|
129
131
|
ssl=not direct_connection,
|
|
130
132
|
tlsallowinvalidhostnames=True,
|
|
@@ -211,6 +213,10 @@ class DatabaseHandler:
|
|
|
211
213
|
"""
|
|
212
214
|
collection_name = names.get_collection_name_from_parameter_name(parameter)
|
|
213
215
|
if model_version:
|
|
216
|
+
if isinstance(model_version, list):
|
|
217
|
+
raise ValueError(
|
|
218
|
+
"Only one model version can be passed to get_model_parameter, not a list."
|
|
219
|
+
)
|
|
214
220
|
production_table = self._read_production_table_from_mongo_db(
|
|
215
221
|
collection_name, model_version
|
|
216
222
|
)
|
|
@@ -678,7 +684,7 @@ class DatabaseHandler:
|
|
|
678
684
|
model_version=model_version,
|
|
679
685
|
collection="configuration_corsika",
|
|
680
686
|
)
|
|
681
|
-
if simulation_software == "
|
|
687
|
+
if simulation_software == "sim_telarray":
|
|
682
688
|
return (
|
|
683
689
|
self.get_model_parameters(
|
|
684
690
|
site,
|
simtools/layout/array_layout.py
CHANGED
simtools/model/array_model.py
CHANGED
|
@@ -36,6 +36,8 @@ class ArrayModel:
|
|
|
36
36
|
array_elements: Union[str, Path, List[str]], optional
|
|
37
37
|
Array element definitions (list of array element or path to file with
|
|
38
38
|
the array element positions).
|
|
39
|
+
sim_telarray_seeds : dict, optional
|
|
40
|
+
Dictionary with configuration for sim_telarray random instrument setup.
|
|
39
41
|
"""
|
|
40
42
|
|
|
41
43
|
def __init__(
|
|
@@ -46,6 +48,7 @@ class ArrayModel:
|
|
|
46
48
|
site: str | None = None,
|
|
47
49
|
layout_name: str | None = None,
|
|
48
50
|
array_elements: str | Path | list[str] | None = None,
|
|
51
|
+
sim_telarray_seeds: dict | None = None,
|
|
49
52
|
):
|
|
50
53
|
"""Initialize ArrayModel."""
|
|
51
54
|
self._logger = logging.getLogger(__name__)
|
|
@@ -65,6 +68,7 @@ class ArrayModel:
|
|
|
65
68
|
|
|
66
69
|
self._telescope_model_files_exported = False
|
|
67
70
|
self._array_model_file_exported = False
|
|
71
|
+
self.sim_telarray_seeds = sim_telarray_seeds
|
|
68
72
|
|
|
69
73
|
def _initialize(self, site: str, array_elements_config: str | Path | list[str]):
|
|
70
74
|
"""
|
|
@@ -116,6 +120,26 @@ class ArrayModel:
|
|
|
116
120
|
telescope_model = self._build_telescope_models(site_model, array_elements)
|
|
117
121
|
return array_elements, site_model, telescope_model
|
|
118
122
|
|
|
123
|
+
@property
|
|
124
|
+
def config_file_path(self) -> Path:
|
|
125
|
+
"""
|
|
126
|
+
Return the path of the array config file for sim_telarray.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
Path
|
|
131
|
+
Path of the exported config file for sim_telarray.
|
|
132
|
+
"""
|
|
133
|
+
if self._config_file_path is None:
|
|
134
|
+
config_file_name = names.simtel_config_file_name(
|
|
135
|
+
array_name=self.layout_name,
|
|
136
|
+
site=self.site_model.site,
|
|
137
|
+
model_version=self.model_version,
|
|
138
|
+
label=self.label,
|
|
139
|
+
)
|
|
140
|
+
self._config_file_path = self.get_config_directory().joinpath(config_file_name)
|
|
141
|
+
return self._config_file_path
|
|
142
|
+
|
|
119
143
|
@property
|
|
120
144
|
def number_of_telescopes(self) -> int:
|
|
121
145
|
"""
|
|
@@ -140,6 +164,34 @@ class ArrayModel:
|
|
|
140
164
|
"""
|
|
141
165
|
return self.site_model.site
|
|
142
166
|
|
|
167
|
+
@property
|
|
168
|
+
def model_version(self):
|
|
169
|
+
"""Model version."""
|
|
170
|
+
return self._model_version
|
|
171
|
+
|
|
172
|
+
@model_version.setter
|
|
173
|
+
def model_version(self, model_version):
|
|
174
|
+
"""
|
|
175
|
+
Set model version.
|
|
176
|
+
|
|
177
|
+
Parameters
|
|
178
|
+
----------
|
|
179
|
+
_model_version: str or list
|
|
180
|
+
Model version (e.g., "6.0.0").
|
|
181
|
+
If a list is passed, it must contain exactly one element,
|
|
182
|
+
and only that element will be used.
|
|
183
|
+
|
|
184
|
+
Raises
|
|
185
|
+
------
|
|
186
|
+
ValueError
|
|
187
|
+
If more than one model version is passed.
|
|
188
|
+
"""
|
|
189
|
+
if isinstance(model_version, list):
|
|
190
|
+
raise ValueError(
|
|
191
|
+
f"Only one model version can be passed to {self.__class__.__name__}, not a list."
|
|
192
|
+
)
|
|
193
|
+
self._model_version = model_version
|
|
194
|
+
|
|
143
195
|
def _build_telescope_models(self, site_model: SiteModel, array_elements: dict) -> dict:
|
|
144
196
|
"""
|
|
145
197
|
Build the the telescope models for all telescopes of this array.
|
|
@@ -187,7 +239,7 @@ class ArrayModel:
|
|
|
187
239
|
)
|
|
188
240
|
if name not in exported_models:
|
|
189
241
|
self._logger.debug(f"Exporting configuration file for telescope {name}")
|
|
190
|
-
tel_model.
|
|
242
|
+
tel_model.write_sim_telarray_config_file()
|
|
191
243
|
exported_models.append(name)
|
|
192
244
|
else:
|
|
193
245
|
self._logger.debug(
|
|
@@ -196,19 +248,11 @@ class ArrayModel:
|
|
|
196
248
|
|
|
197
249
|
self._telescope_model_files_exported = True
|
|
198
250
|
|
|
199
|
-
def
|
|
251
|
+
def export_sim_telarray_config_file(self):
|
|
200
252
|
"""Export sim_telarray configuration file for the array into the model directory."""
|
|
201
|
-
|
|
202
|
-
config_file_name = names.simtel_config_file_name(
|
|
203
|
-
array_name=self.layout_name,
|
|
204
|
-
site=self.site_model.site,
|
|
205
|
-
model_version=self.model_version,
|
|
206
|
-
label=self.label,
|
|
207
|
-
)
|
|
208
|
-
self._config_file_path = self.get_config_directory().joinpath(config_file_name)
|
|
253
|
+
self.site_model.export_model_files()
|
|
209
254
|
|
|
210
|
-
|
|
211
|
-
self._logger.info(f"Writing array configuration file into {self._config_file_path}")
|
|
255
|
+
self._logger.info(f"Writing array configuration file into {self.config_file_path}")
|
|
212
256
|
simtel_writer = SimtelConfigWriter(
|
|
213
257
|
site=self.site_model.site,
|
|
214
258
|
layout_name=self.layout_name,
|
|
@@ -216,9 +260,10 @@ class ArrayModel:
|
|
|
216
260
|
label=self.label,
|
|
217
261
|
)
|
|
218
262
|
simtel_writer.write_array_config_file(
|
|
219
|
-
config_file_path=self.
|
|
263
|
+
config_file_path=self.config_file_path,
|
|
220
264
|
telescope_model=self.telescope_model,
|
|
221
265
|
site_model=self.site_model,
|
|
266
|
+
sim_telarray_seeds=self.sim_telarray_seeds,
|
|
222
267
|
)
|
|
223
268
|
self._array_model_file_exported = True
|
|
224
269
|
|
|
@@ -231,21 +276,7 @@ class ArrayModel:
|
|
|
231
276
|
if not self._telescope_model_files_exported:
|
|
232
277
|
self.export_simtel_telescope_config_files()
|
|
233
278
|
if not self._array_model_file_exported:
|
|
234
|
-
self.
|
|
235
|
-
|
|
236
|
-
def get_config_file(self) -> Path:
|
|
237
|
-
"""
|
|
238
|
-
Return the path of the array config file for sim_telarray.
|
|
239
|
-
|
|
240
|
-
A new config file is produced if the file is not updated.
|
|
241
|
-
|
|
242
|
-
Returns
|
|
243
|
-
-------
|
|
244
|
-
Path
|
|
245
|
-
Path of the exported config file for sim_telarray.
|
|
246
|
-
"""
|
|
247
|
-
self.export_all_simtel_config_files()
|
|
248
|
-
return self._config_file_path
|
|
279
|
+
self.export_sim_telarray_config_file()
|
|
249
280
|
|
|
250
281
|
def get_config_directory(self) -> Path:
|
|
251
282
|
"""
|
|
@@ -257,7 +288,9 @@ class ArrayModel:
|
|
|
257
288
|
Path of the config directory path for sim_telarray.
|
|
258
289
|
"""
|
|
259
290
|
if self._config_file_directory is None:
|
|
260
|
-
self._config_file_directory = self.io_handler.get_output_directory(
|
|
291
|
+
self._config_file_directory = self.io_handler.get_output_directory(
|
|
292
|
+
self.label, f"model/{self.model_version}"
|
|
293
|
+
)
|
|
261
294
|
return self._config_file_directory
|
|
262
295
|
|
|
263
296
|
def _load_array_element_positions_from_file(
|
|
@@ -331,6 +364,7 @@ class ArrayModel:
|
|
|
331
364
|
"type": "float64",
|
|
332
365
|
"file": False,
|
|
333
366
|
"meta_parameter": False,
|
|
367
|
+
"model_parameter_schema_version": "0.1.0",
|
|
334
368
|
}
|
|
335
369
|
|
|
336
370
|
def _get_array_elements_from_list(self, array_elements_list: list[str]) -> dict:
|