gammasimtools 0.10.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.10.0.dist-info → gammasimtools-0.11.0.dist-info}/METADATA +3 -1
- {gammasimtools-0.10.0.dist-info → gammasimtools-0.11.0.dist-info}/RECORD +84 -77
- {gammasimtools-0.10.0.dist-info → gammasimtools-0.11.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.10.0.dist-info → gammasimtools-0.11.0.dist-info}/entry_points.txt +4 -0
- simtools/_version.py +9 -4
- simtools/applications/convert_all_model_parameters_from_simtel.py +0 -1
- simtools/applications/convert_model_parameter_from_simtel.py +0 -1
- simtools/applications/db_add_file_to_db.py +0 -1
- simtools/applications/db_get_parameter_from_db.py +7 -28
- simtools/applications/derive_mirror_rnda.py +1 -2
- 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_corsika_histograms.py +2 -2
- simtools/applications/generate_regular_arrays.py +4 -2
- simtools/applications/production_derive_limits.py +95 -0
- simtools/applications/production_generate_simulation_config.py +15 -29
- simtools/applications/production_scale_events.py +2 -7
- simtools/applications/run_application.py +165 -0
- simtools/applications/simulate_light_emission.py +0 -4
- simtools/applications/submit_model_parameter_from_external.py +11 -6
- simtools/applications/validate_file_using_schema.py +3 -3
- simtools/configuration/commandline_parser.py +29 -0
- simtools/configuration/configurator.py +8 -10
- simtools/corsika/corsika_config.py +11 -10
- simtools/corsika/corsika_histograms.py +4 -6
- simtools/corsika/corsika_histograms_visualize.py +2 -4
- simtools/data_model/metadata_collector.py +18 -9
- simtools/data_model/model_data_writer.py +67 -15
- simtools/data_model/schema.py +10 -3
- simtools/data_model/validate_data.py +70 -24
- simtools/db/db_handler.py +42 -12
- simtools/dependencies.py +112 -0
- simtools/layout/array_layout.py +5 -4
- simtools/model/model_parameter.py +35 -2
- simtools/production_configuration/calculate_statistical_errors_grid_point.py +5 -6
- simtools/production_configuration/event_scaler.py +3 -19
- simtools/production_configuration/generate_simulation_config.py +4 -12
- simtools/production_configuration/interpolation_handler.py +2 -5
- simtools/production_configuration/limits_calculation.py +202 -0
- simtools/reporting/docs_read_parameters.py +310 -0
- simtools/runners/corsika_simtel_runner.py +1 -3
- simtools/schemas/{integration_tests_config.metaschema.yml → application_workflow.metaschema.yml} +51 -27
- simtools/schemas/array_elements.yml +8 -0
- simtools/schemas/model_parameter.metaschema.yml +96 -0
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +2 -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 +2 -0
- 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/iobuf_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_output_maximum.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/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/store_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
- simtools/schemas/production_tables.schema.yml +1 -1
- simtools/simtel/simtel_config_reader.py +1 -2
- simtools/simtel/simtel_config_writer.py +1 -2
- simtools/simtel/simtel_io_histogram.py +0 -1
- simtools/simtel/simtel_io_histograms.py +2 -4
- simtools/simtel/simulator_camera_efficiency.py +1 -3
- simtools/simtel/simulator_light_emission.py +2 -5
- simtools/simtel/simulator_ray_tracing.py +1 -3
- simtools/testing/configuration.py +2 -1
- simtools/testing/validate_output.py +23 -13
- simtools/utils/general.py +12 -2
- simtools/utils/names.py +290 -152
- simtools/utils/value_conversion.py +17 -13
- simtools/version.py +2 -2
- simtools/visualization/legend_handlers.py +2 -0
- {gammasimtools-0.10.0.dist-info → gammasimtools-0.11.0.dist-info}/LICENSE +0 -0
- {gammasimtools-0.10.0.dist-info → gammasimtools-0.11.0.dist-info}/top_level.txt +0 -0
simtools/utils/names.py
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
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
|
|
@@ -15,7 +27,6 @@ __all__ = [
|
|
|
15
27
|
"generate_file_name",
|
|
16
28
|
"get_array_element_type_from_name",
|
|
17
29
|
"get_site_from_array_element_name",
|
|
18
|
-
"layout_telescope_list_file_name",
|
|
19
30
|
"sanitize_name",
|
|
20
31
|
"simtel_config_file_name",
|
|
21
32
|
"simtel_single_mirror_list_file_name",
|
|
@@ -24,11 +35,20 @@ __all__ = [
|
|
|
24
35
|
"validate_site_name",
|
|
25
36
|
]
|
|
26
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
|
+
|
|
27
47
|
|
|
28
48
|
@cache
|
|
29
49
|
def array_elements():
|
|
30
50
|
"""
|
|
31
|
-
|
|
51
|
+
Get array elements and their properties.
|
|
32
52
|
|
|
33
53
|
Returns
|
|
34
54
|
-------
|
|
@@ -42,50 +62,143 @@ def array_elements():
|
|
|
42
62
|
@cache
|
|
43
63
|
def site_names():
|
|
44
64
|
"""
|
|
45
|
-
|
|
65
|
+
Get site names.
|
|
46
66
|
|
|
47
|
-
The list of sites is derived from the sites listed in
|
|
48
|
-
|
|
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.
|
|
49
69
|
|
|
50
70
|
Returns
|
|
51
71
|
-------
|
|
52
72
|
dict
|
|
53
73
|
Site names.
|
|
54
74
|
"""
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
+
}
|
|
58
80
|
|
|
59
81
|
|
|
60
82
|
@cache
|
|
61
|
-
def
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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")):
|
|
65
139
|
with open(schema_file, encoding="utf-8") as f:
|
|
66
140
|
data = yaml.safe_load(f)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
73
168
|
|
|
74
169
|
|
|
75
170
|
def site_parameters():
|
|
76
|
-
|
|
171
|
+
"""Return site model parameters."""
|
|
172
|
+
return model_parameters(class_key_list=tuple(db_collections_to_class_keys["sites"]))
|
|
77
173
|
|
|
78
174
|
|
|
79
175
|
def telescope_parameters():
|
|
80
|
-
|
|
176
|
+
"""Return telescope model parameters."""
|
|
177
|
+
return model_parameters(class_key_list=tuple(db_collections_to_class_keys["telescopes"]))
|
|
178
|
+
|
|
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
|
|
|
83
|
-
def
|
|
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):
|
|
84
197
|
"""
|
|
85
198
|
Validate array element ID.
|
|
86
199
|
|
|
87
200
|
Allowed IDs are
|
|
88
|
-
- design (for design array elements or testing)
|
|
201
|
+
- design types (for design array elements or testing)
|
|
89
202
|
- array element ID (e.g., 1, 5, 15)
|
|
90
203
|
- test (for testing)
|
|
91
204
|
|
|
@@ -93,6 +206,8 @@ def validate_array_element_id_name(name):
|
|
|
93
206
|
----------
|
|
94
207
|
name: str or int
|
|
95
208
|
Array element ID name.
|
|
209
|
+
array_element_type: str
|
|
210
|
+
Array element type (e.g., LSTN, MSTN).
|
|
96
211
|
|
|
97
212
|
Returns
|
|
98
213
|
-------
|
|
@@ -104,23 +219,20 @@ def validate_array_element_id_name(name):
|
|
|
104
219
|
ValueError
|
|
105
220
|
If name is not valid.
|
|
106
221
|
"""
|
|
107
|
-
if isinstance(
|
|
108
|
-
return f"{int(
|
|
109
|
-
if
|
|
110
|
-
return str(
|
|
111
|
-
|
|
112
|
-
msg = f"Invalid array element ID name {name}"
|
|
113
|
-
_logger.error(msg)
|
|
114
|
-
raise ValueError(msg)
|
|
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}")
|
|
115
227
|
|
|
116
228
|
|
|
117
|
-
def validate_site_name(
|
|
229
|
+
def validate_site_name(site_name):
|
|
118
230
|
"""
|
|
119
231
|
Validate site name.
|
|
120
232
|
|
|
121
233
|
Parameters
|
|
122
234
|
----------
|
|
123
|
-
|
|
235
|
+
site_name: str
|
|
124
236
|
Site name.
|
|
125
237
|
|
|
126
238
|
Returns
|
|
@@ -128,7 +240,7 @@ def validate_site_name(name):
|
|
|
128
240
|
str
|
|
129
241
|
Validated name.
|
|
130
242
|
"""
|
|
131
|
-
return _validate_name(
|
|
243
|
+
return _validate_name(site_name, site_names())
|
|
132
244
|
|
|
133
245
|
|
|
134
246
|
def _validate_name(name, all_names):
|
|
@@ -167,13 +279,13 @@ def _validate_name(name, all_names):
|
|
|
167
279
|
raise ValueError(msg)
|
|
168
280
|
|
|
169
281
|
|
|
170
|
-
def validate_array_element_type(
|
|
282
|
+
def validate_array_element_type(array_element_type):
|
|
171
283
|
"""
|
|
172
284
|
Validate array element type (e.g., LSTN, MSTN).
|
|
173
285
|
|
|
174
286
|
Parameters
|
|
175
287
|
----------
|
|
176
|
-
|
|
288
|
+
array_element_type: str
|
|
177
289
|
Array element type.
|
|
178
290
|
|
|
179
291
|
Returns
|
|
@@ -181,16 +293,18 @@ def validate_array_element_type(name):
|
|
|
181
293
|
str
|
|
182
294
|
Validated name.
|
|
183
295
|
"""
|
|
184
|
-
return _validate_name(
|
|
296
|
+
return _validate_name(array_element_type, array_elements())
|
|
185
297
|
|
|
186
298
|
|
|
187
|
-
def validate_array_element_name(
|
|
299
|
+
def validate_array_element_name(array_element_name):
|
|
188
300
|
"""
|
|
189
|
-
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).
|
|
190
304
|
|
|
191
305
|
Parameters
|
|
192
306
|
----------
|
|
193
|
-
|
|
307
|
+
array_element_name: str
|
|
194
308
|
Array element name.
|
|
195
309
|
|
|
196
310
|
Returns
|
|
@@ -199,20 +313,22 @@ def validate_array_element_name(name):
|
|
|
199
313
|
Validated name.
|
|
200
314
|
"""
|
|
201
315
|
try:
|
|
202
|
-
_array_element_type, _array_element_id =
|
|
316
|
+
_array_element_type, _array_element_id = array_element_name.split("-")
|
|
203
317
|
except ValueError as exc:
|
|
204
|
-
msg = f"Invalid name {
|
|
318
|
+
msg = f"Invalid name {array_element_name}"
|
|
205
319
|
raise ValueError(msg) from exc
|
|
320
|
+
if _array_element_type == "OBS":
|
|
321
|
+
return validate_site_name(_array_element_id)
|
|
206
322
|
return (
|
|
207
323
|
_validate_name(_array_element_type, array_elements())
|
|
208
324
|
+ "-"
|
|
209
|
-
+ validate_array_element_id_name(_array_element_id)
|
|
325
|
+
+ validate_array_element_id_name(_array_element_id, _array_element_type)
|
|
210
326
|
)
|
|
211
327
|
|
|
212
328
|
|
|
213
|
-
def
|
|
329
|
+
def generate_array_element_name_from_type_site_id(array_element_type, site, array_element_id):
|
|
214
330
|
"""
|
|
215
|
-
|
|
331
|
+
Generate a new array element name from array element type, site, and array element ID.
|
|
216
332
|
|
|
217
333
|
Parameters
|
|
218
334
|
----------
|
|
@@ -229,17 +345,17 @@ def get_array_element_name_from_type_site_id(array_element_type, site, array_ele
|
|
|
229
345
|
Array element name.
|
|
230
346
|
"""
|
|
231
347
|
_short_site = validate_site_name(site)[0]
|
|
232
|
-
_val_id = validate_array_element_id_name(array_element_id)
|
|
348
|
+
_val_id = validate_array_element_id_name(array_element_id, array_element_type)
|
|
233
349
|
return f"{array_element_type}{_short_site}-{_val_id}"
|
|
234
350
|
|
|
235
351
|
|
|
236
|
-
def get_array_element_type_from_name(
|
|
352
|
+
def get_array_element_type_from_name(array_element_name):
|
|
237
353
|
"""
|
|
238
|
-
Get array element type from name
|
|
354
|
+
Get array element type from array element name (e.g "MSTN" from "MSTN-01").
|
|
239
355
|
|
|
240
356
|
Parameters
|
|
241
357
|
----------
|
|
242
|
-
|
|
358
|
+
array_element_name: str
|
|
243
359
|
Array element name
|
|
244
360
|
|
|
245
361
|
Returns
|
|
@@ -247,14 +363,36 @@ def get_array_element_type_from_name(name):
|
|
|
247
363
|
str
|
|
248
364
|
Array element type.
|
|
249
365
|
"""
|
|
250
|
-
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
|
|
251
389
|
|
|
252
390
|
|
|
253
391
|
def get_list_of_array_element_types(
|
|
254
392
|
array_element_class="telescopes", site=None, observatory="CTAO"
|
|
255
393
|
):
|
|
256
394
|
"""
|
|
257
|
-
Get list of array element types.
|
|
395
|
+
Get list of array element types (e.g., ["LSTN", "MSTN"] for the Northern site).
|
|
258
396
|
|
|
259
397
|
Parameters
|
|
260
398
|
----------
|
|
@@ -268,139 +406,136 @@ def get_list_of_array_element_types(
|
|
|
268
406
|
list
|
|
269
407
|
List of array element types.
|
|
270
408
|
"""
|
|
271
|
-
return
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
+
)
|
|
278
418
|
|
|
279
419
|
|
|
280
|
-
def get_site_from_array_element_name(
|
|
420
|
+
def get_site_from_array_element_name(array_element_name):
|
|
281
421
|
"""
|
|
282
|
-
Get site name from array element name.
|
|
422
|
+
Get site name from array element name (e.g., "South" from "MSTS-01").
|
|
283
423
|
|
|
284
424
|
Parameters
|
|
285
425
|
----------
|
|
286
|
-
|
|
426
|
+
array_element_name: str
|
|
287
427
|
Array element name.
|
|
288
428
|
|
|
289
429
|
Returns
|
|
290
430
|
-------
|
|
291
|
-
str
|
|
292
|
-
Site name
|
|
431
|
+
str, list
|
|
432
|
+
Site name(s).
|
|
293
433
|
"""
|
|
294
|
-
|
|
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"]
|
|
295
438
|
|
|
296
439
|
|
|
297
|
-
def get_collection_name_from_array_element_name(
|
|
440
|
+
def get_collection_name_from_array_element_name(array_element_name, array_elements_only=True):
|
|
298
441
|
"""
|
|
299
|
-
Get collection name (e.g., telescopes, calibration_devices
|
|
442
|
+
Get collection name (e.g., telescopes, calibration_devices) of an array element from its name.
|
|
300
443
|
|
|
301
444
|
Parameters
|
|
302
445
|
----------
|
|
303
|
-
|
|
304
|
-
Array element name.
|
|
446
|
+
array_element_name: str
|
|
447
|
+
Array element name (e.g. LSTN-01)
|
|
305
448
|
array_elements_only: bool
|
|
306
|
-
If True, only array elements are considered.
|
|
449
|
+
If True, only array elements are considered (e.g. "OBS-North" will raise a ValueError).
|
|
307
450
|
|
|
308
451
|
Returns
|
|
309
452
|
-------
|
|
310
453
|
str
|
|
311
454
|
Collection name .
|
|
455
|
+
|
|
456
|
+
Raises
|
|
457
|
+
------
|
|
458
|
+
ValueError
|
|
459
|
+
If name is not a valid array element name.
|
|
312
460
|
"""
|
|
313
461
|
try:
|
|
314
|
-
return array_elements()[get_array_element_type_from_name(
|
|
315
|
-
except ValueError:
|
|
316
|
-
pass
|
|
317
|
-
if name.startswith("OBS"):
|
|
318
|
-
return "sites"
|
|
319
|
-
try:
|
|
320
|
-
validate_site_name(name)
|
|
321
|
-
return "sites"
|
|
462
|
+
return array_elements()[get_array_element_type_from_name(array_element_name)]["collection"]
|
|
322
463
|
except ValueError as exc:
|
|
323
464
|
if array_elements_only:
|
|
324
|
-
raise ValueError(f"Invalid array element name {
|
|
325
|
-
|
|
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"
|
|
469
|
+
except ValueError:
|
|
470
|
+
pass
|
|
471
|
+
if array_element_name in {
|
|
326
472
|
"configuration_sim_telarray",
|
|
327
473
|
"configuration_corsika",
|
|
328
474
|
"Files",
|
|
329
475
|
"Dummy-Telescope",
|
|
330
|
-
|
|
331
|
-
return
|
|
476
|
+
}:
|
|
477
|
+
return array_element_name
|
|
478
|
+
raise ValueError(f"Invalid array element name {array_element_name}")
|
|
332
479
|
|
|
333
|
-
raise ValueError(f"Invalid array element name {name}")
|
|
334
480
|
|
|
335
|
-
|
|
336
|
-
def get_simulation_software_name_from_parameter_name(
|
|
337
|
-
par_name,
|
|
338
|
-
simulation_software="sim_telarray",
|
|
339
|
-
):
|
|
481
|
+
def get_collection_name_from_parameter_name(parameter_name):
|
|
340
482
|
"""
|
|
341
|
-
Get the
|
|
342
|
-
|
|
343
|
-
Name convention is expected to be defined in the schema.
|
|
344
|
-
Returns the parameter name if no simulation software name is found.
|
|
483
|
+
Get the db collection name for a given parameter.
|
|
345
484
|
|
|
346
485
|
Parameters
|
|
347
486
|
----------
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
simulation_software: str
|
|
351
|
-
Simulation software name.
|
|
487
|
+
parameter_name: str
|
|
488
|
+
Name of the parameter.
|
|
352
489
|
|
|
353
490
|
Returns
|
|
354
491
|
-------
|
|
355
492
|
str
|
|
356
|
-
|
|
357
|
-
"""
|
|
358
|
-
_parameter_names = {**telescope_parameters(), **site_parameters()}
|
|
493
|
+
Collection name.
|
|
359
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()
|
|
360
501
|
try:
|
|
361
|
-
|
|
362
|
-
except KeyError as
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
try:
|
|
367
|
-
for software in _parameter.get("simulation_software", []):
|
|
368
|
-
if software.get("name") == simulation_software:
|
|
369
|
-
return software.get("internal_parameter_name", par_name)
|
|
370
|
-
except TypeError: # catches cases for which 'simulation_software' is None
|
|
371
|
-
pass
|
|
372
|
-
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)
|
|
373
506
|
|
|
374
507
|
|
|
375
|
-
def
|
|
508
|
+
def get_simulation_software_name_from_parameter_name(
|
|
509
|
+
parameter_name,
|
|
510
|
+
simulation_software="sim_telarray",
|
|
511
|
+
):
|
|
376
512
|
"""
|
|
377
|
-
Get the
|
|
513
|
+
Get the name used in the given simulation software from the model parameter name.
|
|
378
514
|
|
|
379
|
-
|
|
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.
|
|
380
517
|
|
|
381
518
|
Parameters
|
|
382
519
|
----------
|
|
383
|
-
|
|
384
|
-
|
|
520
|
+
parameter_name: str
|
|
521
|
+
Model parameter name.
|
|
522
|
+
simulation_software: str
|
|
523
|
+
Simulation software name.
|
|
385
524
|
|
|
386
525
|
Returns
|
|
387
526
|
-------
|
|
388
527
|
str
|
|
389
|
-
|
|
528
|
+
Simtel parameter name.
|
|
390
529
|
"""
|
|
391
|
-
|
|
530
|
+
_parameter = model_parameters().get(parameter_name)
|
|
531
|
+
if not _parameter:
|
|
532
|
+
raise KeyError(f"Parameter {parameter_name} without schema definition")
|
|
392
533
|
|
|
393
|
-
for
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
and software["internal_parameter_name"] == simtel_name
|
|
399
|
-
):
|
|
400
|
-
return par_name
|
|
401
|
-
except (KeyError, TypeError): # catches cases for which 'simulation_software' is None
|
|
402
|
-
pass
|
|
403
|
-
return simtel_name
|
|
534
|
+
for software in _parameter.get("simulation_software", []):
|
|
535
|
+
if software.get("name") == simulation_software:
|
|
536
|
+
return software.get("internal_parameter_name", parameter_name)
|
|
537
|
+
|
|
538
|
+
return None
|
|
404
539
|
|
|
405
540
|
|
|
406
541
|
def simtel_config_file_name(
|
|
@@ -474,28 +609,6 @@ def simtel_single_mirror_list_file_name(
|
|
|
474
609
|
return name
|
|
475
610
|
|
|
476
611
|
|
|
477
|
-
def layout_telescope_list_file_name(name, label):
|
|
478
|
-
"""
|
|
479
|
-
File name for files required at the RayTracing class.
|
|
480
|
-
|
|
481
|
-
Parameters
|
|
482
|
-
----------
|
|
483
|
-
name: str
|
|
484
|
-
Name of the array.
|
|
485
|
-
label: str
|
|
486
|
-
Instance label.
|
|
487
|
-
|
|
488
|
-
Returns
|
|
489
|
-
-------
|
|
490
|
-
str
|
|
491
|
-
File name.
|
|
492
|
-
"""
|
|
493
|
-
file_name = f"telescope_positions-{name}"
|
|
494
|
-
file_name += f"_{label}" if label is not None else ""
|
|
495
|
-
file_name += ".ecsv"
|
|
496
|
-
return file_name
|
|
497
|
-
|
|
498
|
-
|
|
499
612
|
def generate_file_name(
|
|
500
613
|
file_type,
|
|
501
614
|
suffix,
|
|
@@ -581,8 +694,7 @@ def sanitize_name(name):
|
|
|
581
694
|
if the string name can not be sanitized.
|
|
582
695
|
"""
|
|
583
696
|
if name is None:
|
|
584
|
-
|
|
585
|
-
return name
|
|
697
|
+
return None
|
|
586
698
|
sanitized = name.lower()
|
|
587
699
|
sanitized = sanitized.replace(" ", "_")
|
|
588
700
|
# Remove characters that are not alphanumerics or underscores
|
|
@@ -592,3 +704,29 @@ def sanitize_name(name):
|
|
|
592
704
|
_logger.error(msg)
|
|
593
705
|
raise ValueError(msg)
|
|
594
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)
|