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
simtools/utils/names.py
CHANGED
|
@@ -1,20 +1,32 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Name utilities for array elements, sites, and model parameters.
|
|
2
|
+
|
|
3
|
+
Naming in simtools:
|
|
4
|
+
|
|
5
|
+
* 'site': South or North
|
|
6
|
+
* 'array element': e.g., LSTN-01, MSTN-01, ...
|
|
7
|
+
* 'array element type': e.g., LSTN, MSTN, ...
|
|
8
|
+
* 'array element ID': e.g., 01, 02, ...
|
|
9
|
+
* 'array element design type': e.g., design, test
|
|
10
|
+
* 'instrument class key': e.g., telescope, camera, structure
|
|
11
|
+
* 'db collection': e.g., telescopes, sites, calibration_devices
|
|
12
|
+
|
|
13
|
+
"""
|
|
2
14
|
|
|
3
15
|
import logging
|
|
4
16
|
import re
|
|
5
17
|
from functools import cache
|
|
6
|
-
from importlib.resources import files
|
|
7
18
|
from pathlib import Path
|
|
8
19
|
|
|
9
20
|
import yaml
|
|
10
21
|
|
|
22
|
+
from simtools.constants import MODEL_PARAMETER_SCHEMA_PATH, SCHEMA_PATH
|
|
23
|
+
|
|
11
24
|
_logger = logging.getLogger(__name__)
|
|
12
25
|
|
|
13
26
|
__all__ = [
|
|
14
27
|
"generate_file_name",
|
|
15
28
|
"get_array_element_type_from_name",
|
|
16
29
|
"get_site_from_array_element_name",
|
|
17
|
-
"layout_telescope_list_file_name",
|
|
18
30
|
"sanitize_name",
|
|
19
31
|
"simtel_config_file_name",
|
|
20
32
|
"simtel_single_mirror_list_file_name",
|
|
@@ -23,68 +35,170 @@ __all__ = [
|
|
|
23
35
|
"validate_site_name",
|
|
24
36
|
]
|
|
25
37
|
|
|
38
|
+
# Mapping of db collection names to class keys
|
|
39
|
+
db_collections_to_class_keys = {
|
|
40
|
+
"sites": ["Site"],
|
|
41
|
+
"telescopes": ["Structure", "Camera", "Telescope"],
|
|
42
|
+
"calibration_devices": ["Calibration"],
|
|
43
|
+
"configuration_sim_telarray": ["configuration_sim_telarray"],
|
|
44
|
+
"configuration_corsika": ["configuration_corsika"],
|
|
45
|
+
}
|
|
46
|
+
|
|
26
47
|
|
|
27
48
|
@cache
|
|
28
49
|
def array_elements():
|
|
29
50
|
"""
|
|
30
|
-
|
|
51
|
+
Get array elements and their properties.
|
|
31
52
|
|
|
32
53
|
Returns
|
|
33
54
|
-------
|
|
34
55
|
dict
|
|
35
56
|
Array elements.
|
|
36
57
|
"""
|
|
37
|
-
with open(
|
|
58
|
+
with open(Path(SCHEMA_PATH) / "array_elements.yml", encoding="utf-8") as file:
|
|
38
59
|
return yaml.safe_load(file)["data"]
|
|
39
60
|
|
|
40
61
|
|
|
41
62
|
@cache
|
|
42
63
|
def site_names():
|
|
43
64
|
"""
|
|
44
|
-
|
|
65
|
+
Get site names.
|
|
45
66
|
|
|
46
|
-
The list of sites is derived from the sites listed in
|
|
47
|
-
|
|
67
|
+
The list of sites is derived from the sites listed in array element definition file.
|
|
68
|
+
Return a dictionary for compatibility with the validation '_validate_name' routine.
|
|
48
69
|
|
|
49
70
|
Returns
|
|
50
71
|
-------
|
|
51
72
|
dict
|
|
52
73
|
Site names.
|
|
53
74
|
"""
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
75
|
+
return {
|
|
76
|
+
site: [site.lower()]
|
|
77
|
+
for entry in array_elements().values()
|
|
78
|
+
for site in (entry["site"] if isinstance(entry["site"], list) else [entry["site"]])
|
|
79
|
+
}
|
|
57
80
|
|
|
58
81
|
|
|
59
82
|
@cache
|
|
60
|
-
def
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
83
|
+
def array_element_design_types(array_element_type):
|
|
84
|
+
"""
|
|
85
|
+
Get array element site types (e.g., 'design' or 'flashcam').
|
|
86
|
+
|
|
87
|
+
Default values are ['design', 'test'].
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
array_element_type
|
|
92
|
+
Array element type
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
list
|
|
97
|
+
Array element design types.
|
|
98
|
+
"""
|
|
99
|
+
default_types = ["design", "test"]
|
|
100
|
+
if array_element_type is None:
|
|
101
|
+
return default_types
|
|
102
|
+
try:
|
|
103
|
+
return array_elements()[array_element_type].get("design_types", default_types)
|
|
104
|
+
except KeyError as exc:
|
|
105
|
+
raise ValueError(f"Invalid name {array_element_type}") from exc
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def is_design_type(array_element_name):
|
|
109
|
+
"""
|
|
110
|
+
Check if array element is a design type (e.g., "MSTS-FlashCam" or "LSTN-design").
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
array_element_name: str
|
|
115
|
+
Array element name.
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
bool
|
|
120
|
+
True if array element is a design type.
|
|
121
|
+
"""
|
|
122
|
+
return get_array_element_id_from_name(array_element_name) in array_element_design_types(
|
|
123
|
+
get_array_element_type_from_name(array_element_name)
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@cache
|
|
128
|
+
def _load_model_parameters():
|
|
129
|
+
"""
|
|
130
|
+
Get model parameters properties from schema files.
|
|
131
|
+
|
|
132
|
+
Returns
|
|
133
|
+
-------
|
|
134
|
+
dict
|
|
135
|
+
Model parameters definitions for all model parameters.
|
|
136
|
+
"""
|
|
137
|
+
_parameters = {}
|
|
138
|
+
for schema_file in list(Path(MODEL_PARAMETER_SCHEMA_PATH).rglob("*.yml")):
|
|
64
139
|
with open(schema_file, encoding="utf-8") as f:
|
|
65
140
|
data = yaml.safe_load(f)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
141
|
+
_parameters[data["name"]] = data
|
|
142
|
+
return _parameters
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def model_parameters(class_key_list=None):
|
|
146
|
+
"""
|
|
147
|
+
Get model parameters and their properties for a given instrument class key.
|
|
148
|
+
|
|
149
|
+
Returns all model parameters if class_key is None.
|
|
150
|
+
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
class_key: str, None
|
|
154
|
+
Class key (e.g., "telescope", "camera", structure").
|
|
155
|
+
|
|
156
|
+
Returns
|
|
157
|
+
-------
|
|
158
|
+
dict
|
|
159
|
+
Model parameters definitions.
|
|
160
|
+
"""
|
|
161
|
+
_parameters = {}
|
|
162
|
+
if class_key_list is None:
|
|
163
|
+
return _load_model_parameters()
|
|
164
|
+
for key, value in _load_model_parameters().items():
|
|
165
|
+
if value.get("instrument", {}).get("class", "") in class_key_list:
|
|
166
|
+
_parameters[key] = value
|
|
167
|
+
return _parameters
|
|
72
168
|
|
|
73
169
|
|
|
74
170
|
def site_parameters():
|
|
75
|
-
|
|
171
|
+
"""Return site model parameters."""
|
|
172
|
+
return model_parameters(class_key_list=tuple(db_collections_to_class_keys["sites"]))
|
|
76
173
|
|
|
77
174
|
|
|
78
175
|
def telescope_parameters():
|
|
79
|
-
|
|
176
|
+
"""Return telescope model parameters."""
|
|
177
|
+
return model_parameters(class_key_list=tuple(db_collections_to_class_keys["telescopes"]))
|
|
178
|
+
|
|
80
179
|
|
|
180
|
+
def instrument_class_key_to_db_collection(class_name):
|
|
181
|
+
"""Convert instrument class key to collection name."""
|
|
182
|
+
for collection, classes in db_collections_to_class_keys.items():
|
|
183
|
+
if class_name in classes:
|
|
184
|
+
return collection
|
|
185
|
+
raise ValueError(f"Class {class_name} not found")
|
|
81
186
|
|
|
82
|
-
|
|
187
|
+
|
|
188
|
+
def db_collection_to_instrument_class_key(collection_name="telescopes"):
|
|
189
|
+
"""Return list of instrument classes for a given collection."""
|
|
190
|
+
try:
|
|
191
|
+
return db_collections_to_class_keys[collection_name]
|
|
192
|
+
except KeyError as exc:
|
|
193
|
+
raise KeyError(f"Invalid collection name {collection_name}") from exc
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def validate_array_element_id_name(array_element_id, array_element_type=None):
|
|
83
197
|
"""
|
|
84
198
|
Validate array element ID.
|
|
85
199
|
|
|
86
200
|
Allowed IDs are
|
|
87
|
-
- design (for design array elements or testing)
|
|
201
|
+
- design types (for design array elements or testing)
|
|
88
202
|
- array element ID (e.g., 1, 5, 15)
|
|
89
203
|
- test (for testing)
|
|
90
204
|
|
|
@@ -92,6 +206,8 @@ def validate_array_element_id_name(name):
|
|
|
92
206
|
----------
|
|
93
207
|
name: str or int
|
|
94
208
|
Array element ID name.
|
|
209
|
+
array_element_type: str
|
|
210
|
+
Array element type (e.g., LSTN, MSTN).
|
|
95
211
|
|
|
96
212
|
Returns
|
|
97
213
|
-------
|
|
@@ -103,23 +219,20 @@ def validate_array_element_id_name(name):
|
|
|
103
219
|
ValueError
|
|
104
220
|
If name is not valid.
|
|
105
221
|
"""
|
|
106
|
-
if isinstance(
|
|
107
|
-
return f"{int(
|
|
108
|
-
if
|
|
109
|
-
return str(
|
|
222
|
+
if isinstance(array_element_id, int) or array_element_id.isdigit():
|
|
223
|
+
return f"{int(array_element_id):02d}"
|
|
224
|
+
if array_element_id in array_element_design_types(array_element_type):
|
|
225
|
+
return str(array_element_id)
|
|
226
|
+
raise ValueError(f"Invalid array element ID name {array_element_id}")
|
|
110
227
|
|
|
111
|
-
msg = f"Invalid array element ID name {name}"
|
|
112
|
-
_logger.error(msg)
|
|
113
|
-
raise ValueError(msg)
|
|
114
228
|
|
|
115
|
-
|
|
116
|
-
def validate_site_name(name):
|
|
229
|
+
def validate_site_name(site_name):
|
|
117
230
|
"""
|
|
118
231
|
Validate site name.
|
|
119
232
|
|
|
120
233
|
Parameters
|
|
121
234
|
----------
|
|
122
|
-
|
|
235
|
+
site_name: str
|
|
123
236
|
Site name.
|
|
124
237
|
|
|
125
238
|
Returns
|
|
@@ -127,7 +240,7 @@ def validate_site_name(name):
|
|
|
127
240
|
str
|
|
128
241
|
Validated name.
|
|
129
242
|
"""
|
|
130
|
-
return _validate_name(
|
|
243
|
+
return _validate_name(site_name, site_names())
|
|
131
244
|
|
|
132
245
|
|
|
133
246
|
def _validate_name(name, all_names):
|
|
@@ -166,13 +279,13 @@ def _validate_name(name, all_names):
|
|
|
166
279
|
raise ValueError(msg)
|
|
167
280
|
|
|
168
281
|
|
|
169
|
-
def validate_array_element_type(
|
|
282
|
+
def validate_array_element_type(array_element_type):
|
|
170
283
|
"""
|
|
171
284
|
Validate array element type (e.g., LSTN, MSTN).
|
|
172
285
|
|
|
173
286
|
Parameters
|
|
174
287
|
----------
|
|
175
|
-
|
|
288
|
+
array_element_type: str
|
|
176
289
|
Array element type.
|
|
177
290
|
|
|
178
291
|
Returns
|
|
@@ -180,16 +293,18 @@ def validate_array_element_type(name):
|
|
|
180
293
|
str
|
|
181
294
|
Validated name.
|
|
182
295
|
"""
|
|
183
|
-
return _validate_name(
|
|
296
|
+
return _validate_name(array_element_type, array_elements())
|
|
184
297
|
|
|
185
298
|
|
|
186
|
-
def validate_array_element_name(
|
|
299
|
+
def validate_array_element_name(array_element_name):
|
|
187
300
|
"""
|
|
188
|
-
Validate array element name (e.g.,
|
|
301
|
+
Validate array element name (e.g., MSTx-NectarCam, MSTN-01).
|
|
302
|
+
|
|
303
|
+
Forgiving validation, is it allows also to give a site name (e.g., OBS-North).
|
|
189
304
|
|
|
190
305
|
Parameters
|
|
191
306
|
----------
|
|
192
|
-
|
|
307
|
+
array_element_name: str
|
|
193
308
|
Array element name.
|
|
194
309
|
|
|
195
310
|
Returns
|
|
@@ -198,20 +313,22 @@ def validate_array_element_name(name):
|
|
|
198
313
|
Validated name.
|
|
199
314
|
"""
|
|
200
315
|
try:
|
|
201
|
-
_array_element_type, _array_element_id =
|
|
316
|
+
_array_element_type, _array_element_id = array_element_name.split("-")
|
|
202
317
|
except ValueError as exc:
|
|
203
|
-
msg = f"Invalid name {
|
|
318
|
+
msg = f"Invalid name {array_element_name}"
|
|
204
319
|
raise ValueError(msg) from exc
|
|
320
|
+
if _array_element_type == "OBS":
|
|
321
|
+
return validate_site_name(_array_element_id)
|
|
205
322
|
return (
|
|
206
323
|
_validate_name(_array_element_type, array_elements())
|
|
207
324
|
+ "-"
|
|
208
|
-
+ validate_array_element_id_name(_array_element_id)
|
|
325
|
+
+ validate_array_element_id_name(_array_element_id, _array_element_type)
|
|
209
326
|
)
|
|
210
327
|
|
|
211
328
|
|
|
212
|
-
def
|
|
329
|
+
def generate_array_element_name_from_type_site_id(array_element_type, site, array_element_id):
|
|
213
330
|
"""
|
|
214
|
-
|
|
331
|
+
Generate a new array element name from array element type, site, and array element ID.
|
|
215
332
|
|
|
216
333
|
Parameters
|
|
217
334
|
----------
|
|
@@ -228,17 +345,17 @@ def get_array_element_name_from_type_site_id(array_element_type, site, array_ele
|
|
|
228
345
|
Array element name.
|
|
229
346
|
"""
|
|
230
347
|
_short_site = validate_site_name(site)[0]
|
|
231
|
-
_val_id = validate_array_element_id_name(array_element_id)
|
|
348
|
+
_val_id = validate_array_element_id_name(array_element_id, array_element_type)
|
|
232
349
|
return f"{array_element_type}{_short_site}-{_val_id}"
|
|
233
350
|
|
|
234
351
|
|
|
235
|
-
def get_array_element_type_from_name(
|
|
352
|
+
def get_array_element_type_from_name(array_element_name):
|
|
236
353
|
"""
|
|
237
|
-
Get array element type from name
|
|
354
|
+
Get array element type from array element name (e.g "MSTN" from "MSTN-01").
|
|
238
355
|
|
|
239
356
|
Parameters
|
|
240
357
|
----------
|
|
241
|
-
|
|
358
|
+
array_element_name: str
|
|
242
359
|
Array element name
|
|
243
360
|
|
|
244
361
|
Returns
|
|
@@ -246,14 +363,36 @@ def get_array_element_type_from_name(name):
|
|
|
246
363
|
str
|
|
247
364
|
Array element type.
|
|
248
365
|
"""
|
|
249
|
-
return _validate_name(
|
|
366
|
+
return _validate_name(array_element_name.split("-")[0], array_elements())
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def get_array_element_id_from_name(array_element_name):
|
|
370
|
+
"""
|
|
371
|
+
Get array element ID from array element name, (e.g. "01" from "MSTN-01").
|
|
372
|
+
|
|
373
|
+
Parameters
|
|
374
|
+
----------
|
|
375
|
+
array_element_name: str
|
|
376
|
+
Array element name
|
|
377
|
+
|
|
378
|
+
Returns
|
|
379
|
+
-------
|
|
380
|
+
str
|
|
381
|
+
Array element ID.
|
|
382
|
+
"""
|
|
383
|
+
try:
|
|
384
|
+
return validate_array_element_id_name(
|
|
385
|
+
array_element_name.split("-")[1], array_element_name.split("-")[0]
|
|
386
|
+
)
|
|
387
|
+
except IndexError as exc:
|
|
388
|
+
raise ValueError(f"Invalid name {array_element_name}") from exc
|
|
250
389
|
|
|
251
390
|
|
|
252
391
|
def get_list_of_array_element_types(
|
|
253
392
|
array_element_class="telescopes", site=None, observatory="CTAO"
|
|
254
393
|
):
|
|
255
394
|
"""
|
|
256
|
-
Get list of array element types.
|
|
395
|
+
Get list of array element types (e.g., ["LSTN", "MSTN"] for the Northern site).
|
|
257
396
|
|
|
258
397
|
Parameters
|
|
259
398
|
----------
|
|
@@ -267,135 +406,136 @@ def get_list_of_array_element_types(
|
|
|
267
406
|
list
|
|
268
407
|
List of array element types.
|
|
269
408
|
"""
|
|
270
|
-
return
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
409
|
+
return sorted(
|
|
410
|
+
[
|
|
411
|
+
key
|
|
412
|
+
for key, value in array_elements().items()
|
|
413
|
+
if value["collection"] == array_element_class
|
|
414
|
+
and (site is None or value["site"] == site)
|
|
415
|
+
and (observatory is None or value["observatory"] == observatory)
|
|
416
|
+
]
|
|
417
|
+
)
|
|
277
418
|
|
|
278
419
|
|
|
279
|
-
def get_site_from_array_element_name(
|
|
420
|
+
def get_site_from_array_element_name(array_element_name):
|
|
280
421
|
"""
|
|
281
|
-
Get site name from array element name.
|
|
422
|
+
Get site name from array element name (e.g., "South" from "MSTS-01").
|
|
282
423
|
|
|
283
424
|
Parameters
|
|
284
425
|
----------
|
|
285
|
-
|
|
426
|
+
array_element_name: str
|
|
286
427
|
Array element name.
|
|
287
428
|
|
|
288
429
|
Returns
|
|
289
430
|
-------
|
|
290
|
-
str
|
|
291
|
-
Site name
|
|
431
|
+
str, list
|
|
432
|
+
Site name(s).
|
|
292
433
|
"""
|
|
293
|
-
|
|
434
|
+
try: # e.g. instrument is 'North' as given for the site parameters
|
|
435
|
+
return validate_site_name(array_element_name)
|
|
436
|
+
except ValueError: # e.g. instrument is 'LSTN' as given for the array element types
|
|
437
|
+
return array_elements()[get_array_element_type_from_name(array_element_name)]["site"]
|
|
294
438
|
|
|
295
439
|
|
|
296
|
-
def get_collection_name_from_array_element_name(
|
|
440
|
+
def get_collection_name_from_array_element_name(array_element_name, array_elements_only=True):
|
|
297
441
|
"""
|
|
298
|
-
Get collection name (e.g., telescopes, calibration_devices
|
|
442
|
+
Get collection name (e.g., telescopes, calibration_devices) of an array element from its name.
|
|
299
443
|
|
|
300
444
|
Parameters
|
|
301
445
|
----------
|
|
302
|
-
|
|
303
|
-
Array element name.
|
|
446
|
+
array_element_name: str
|
|
447
|
+
Array element name (e.g. LSTN-01)
|
|
448
|
+
array_elements_only: bool
|
|
449
|
+
If True, only array elements are considered (e.g. "OBS-North" will raise a ValueError).
|
|
304
450
|
|
|
305
451
|
Returns
|
|
306
452
|
-------
|
|
307
453
|
str
|
|
308
454
|
Collection name .
|
|
455
|
+
|
|
456
|
+
Raises
|
|
457
|
+
------
|
|
458
|
+
ValueError
|
|
459
|
+
If name is not a valid array element name.
|
|
309
460
|
"""
|
|
310
461
|
try:
|
|
311
|
-
return array_elements()[get_array_element_type_from_name(
|
|
462
|
+
return array_elements()[get_array_element_type_from_name(array_element_name)]["collection"]
|
|
463
|
+
except ValueError as exc:
|
|
464
|
+
if array_elements_only:
|
|
465
|
+
raise ValueError(f"Invalid array element name {array_element_name}") from exc
|
|
466
|
+
try:
|
|
467
|
+
if array_element_name.startswith("OBS") or validate_site_name(array_element_name):
|
|
468
|
+
return "sites"
|
|
312
469
|
except ValueError:
|
|
313
470
|
pass
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
471
|
+
if array_element_name in {
|
|
472
|
+
"configuration_sim_telarray",
|
|
473
|
+
"configuration_corsika",
|
|
474
|
+
"Files",
|
|
475
|
+
"Dummy-Telescope",
|
|
476
|
+
}:
|
|
477
|
+
return array_element_name
|
|
478
|
+
raise ValueError(f"Invalid array element name {array_element_name}")
|
|
319
479
|
|
|
320
480
|
|
|
321
|
-
def
|
|
322
|
-
par_name,
|
|
323
|
-
simulation_software="sim_telarray",
|
|
324
|
-
search_telescope_parameters=True,
|
|
325
|
-
search_site_parameters=True,
|
|
326
|
-
):
|
|
481
|
+
def get_collection_name_from_parameter_name(parameter_name):
|
|
327
482
|
"""
|
|
328
|
-
Get the
|
|
329
|
-
|
|
330
|
-
Name convention is expected to be defined in the schema.
|
|
331
|
-
Returns the parameter name if no simulation software name is found.
|
|
483
|
+
Get the db collection name for a given parameter.
|
|
332
484
|
|
|
333
485
|
Parameters
|
|
334
486
|
----------
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
simulation_software: str
|
|
338
|
-
Simulation software name.
|
|
339
|
-
search_telescope_parameters: bool
|
|
340
|
-
If True, telescope model parameters are included.
|
|
341
|
-
search_site_parameters: bool
|
|
342
|
-
If True, site model parameters are included.
|
|
487
|
+
parameter_name: str
|
|
488
|
+
Name of the parameter.
|
|
343
489
|
|
|
344
490
|
Returns
|
|
345
491
|
-------
|
|
346
492
|
str
|
|
347
|
-
|
|
348
|
-
"""
|
|
349
|
-
_parameter_names = {}
|
|
350
|
-
if search_telescope_parameters:
|
|
351
|
-
_parameter_names.update(telescope_parameters())
|
|
352
|
-
if search_site_parameters:
|
|
353
|
-
_parameter_names.update(site_parameters())
|
|
354
|
-
|
|
355
|
-
try:
|
|
356
|
-
_parameter = _parameter_names[par_name]
|
|
357
|
-
except KeyError as err:
|
|
358
|
-
_logger.error(f"Parameter {par_name} without schema definition")
|
|
359
|
-
raise err
|
|
493
|
+
Collection name.
|
|
360
494
|
|
|
495
|
+
Raises
|
|
496
|
+
------
|
|
497
|
+
KeyError
|
|
498
|
+
If the parameter name is not found in the list of model parameters
|
|
499
|
+
"""
|
|
500
|
+
_parameter_names = model_parameters()
|
|
361
501
|
try:
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
pass
|
|
367
|
-
return None
|
|
502
|
+
class_key = _parameter_names[parameter_name].get("instrument", {}).get("class")
|
|
503
|
+
except KeyError as exc:
|
|
504
|
+
raise KeyError(f"Parameter {parameter_name} without schema definition") from exc
|
|
505
|
+
return instrument_class_key_to_db_collection(class_key)
|
|
368
506
|
|
|
369
507
|
|
|
370
|
-
def
|
|
508
|
+
def get_simulation_software_name_from_parameter_name(
|
|
509
|
+
parameter_name,
|
|
510
|
+
simulation_software="sim_telarray",
|
|
511
|
+
):
|
|
371
512
|
"""
|
|
372
|
-
Get the
|
|
513
|
+
Get the name used in the given simulation software from the model parameter name.
|
|
373
514
|
|
|
374
|
-
|
|
515
|
+
Name convention is expected to be defined in the model parameter schema.
|
|
516
|
+
Returns the parameter name if no simulation software name is found.
|
|
375
517
|
|
|
376
518
|
Parameters
|
|
377
519
|
----------
|
|
378
|
-
|
|
379
|
-
|
|
520
|
+
parameter_name: str
|
|
521
|
+
Model parameter name.
|
|
522
|
+
simulation_software: str
|
|
523
|
+
Simulation software name.
|
|
380
524
|
|
|
381
525
|
Returns
|
|
382
526
|
-------
|
|
383
527
|
str
|
|
384
|
-
|
|
528
|
+
Simtel parameter name.
|
|
385
529
|
"""
|
|
386
|
-
|
|
530
|
+
_parameter = model_parameters().get(parameter_name)
|
|
531
|
+
if not _parameter:
|
|
532
|
+
raise KeyError(f"Parameter {parameter_name} without schema definition")
|
|
533
|
+
|
|
534
|
+
for software in _parameter.get("simulation_software", []):
|
|
535
|
+
if software.get("name") == simulation_software:
|
|
536
|
+
return software.get("internal_parameter_name", parameter_name)
|
|
387
537
|
|
|
388
|
-
|
|
389
|
-
try:
|
|
390
|
-
for software in par_info["simulation_software"]:
|
|
391
|
-
if (
|
|
392
|
-
software["name"] == "sim_telarray"
|
|
393
|
-
and software["internal_parameter_name"] == simtel_name
|
|
394
|
-
):
|
|
395
|
-
return par_name
|
|
396
|
-
except (KeyError, TypeError): # catches cases for which 'simulation_software' is None
|
|
397
|
-
pass
|
|
398
|
-
return simtel_name
|
|
538
|
+
return None
|
|
399
539
|
|
|
400
540
|
|
|
401
541
|
def simtel_config_file_name(
|
|
@@ -469,28 +609,6 @@ def simtel_single_mirror_list_file_name(
|
|
|
469
609
|
return name
|
|
470
610
|
|
|
471
611
|
|
|
472
|
-
def layout_telescope_list_file_name(name, label):
|
|
473
|
-
"""
|
|
474
|
-
File name for files required at the RayTracing class.
|
|
475
|
-
|
|
476
|
-
Parameters
|
|
477
|
-
----------
|
|
478
|
-
name: str
|
|
479
|
-
Name of the array.
|
|
480
|
-
label: str
|
|
481
|
-
Instance label.
|
|
482
|
-
|
|
483
|
-
Returns
|
|
484
|
-
-------
|
|
485
|
-
str
|
|
486
|
-
File name.
|
|
487
|
-
"""
|
|
488
|
-
file_name = f"telescope_positions-{name}"
|
|
489
|
-
file_name += f"_{label}" if label is not None else ""
|
|
490
|
-
file_name += ".ecsv"
|
|
491
|
-
return file_name
|
|
492
|
-
|
|
493
|
-
|
|
494
612
|
def generate_file_name(
|
|
495
613
|
file_type,
|
|
496
614
|
suffix,
|
|
@@ -575,12 +693,10 @@ def sanitize_name(name):
|
|
|
575
693
|
ValueError:
|
|
576
694
|
if the string name can not be sanitized.
|
|
577
695
|
"""
|
|
578
|
-
|
|
696
|
+
if name is None:
|
|
697
|
+
return None
|
|
579
698
|
sanitized = name.lower()
|
|
580
|
-
|
|
581
|
-
# Replace spaces with underscores
|
|
582
699
|
sanitized = sanitized.replace(" ", "_")
|
|
583
|
-
|
|
584
700
|
# Remove characters that are not alphanumerics or underscores
|
|
585
701
|
sanitized = re.sub(r"\W|^(?=\d)", "_", sanitized)
|
|
586
702
|
if not sanitized.isidentifier():
|
|
@@ -588,3 +704,29 @@ def sanitize_name(name):
|
|
|
588
704
|
_logger.error(msg)
|
|
589
705
|
raise ValueError(msg)
|
|
590
706
|
return sanitized
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
def file_name_with_version(file_name, suffix):
|
|
710
|
+
"""
|
|
711
|
+
Return a file name including a semantic version with the correct suffix.
|
|
712
|
+
|
|
713
|
+
Replaces 'Path.suffix()', which removes trailing numbers (and therefore version numbers).
|
|
714
|
+
|
|
715
|
+
Parameters
|
|
716
|
+
----------
|
|
717
|
+
file_name: str
|
|
718
|
+
File name.
|
|
719
|
+
suffix: str
|
|
720
|
+
File suffix.
|
|
721
|
+
|
|
722
|
+
Returns
|
|
723
|
+
-------
|
|
724
|
+
Path
|
|
725
|
+
File name with version number.
|
|
726
|
+
"""
|
|
727
|
+
if file_name is None or suffix is None:
|
|
728
|
+
return None
|
|
729
|
+
file_name = str(file_name)
|
|
730
|
+
if bool(re.search(r"\d+\.\d+\.\d+$", file_name)):
|
|
731
|
+
return Path(file_name + suffix)
|
|
732
|
+
return Path(file_name).with_suffix(suffix)
|