gammasimtools 0.23.0__py3-none-any.whl → 0.25.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.23.0.dist-info → gammasimtools-0.25.0.dist-info}/METADATA +1 -1
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/RECORD +89 -85
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/entry_points.txt +1 -0
- simtools/_version.py +2 -2
- simtools/application_control.py +54 -4
- simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -1
- simtools/applications/db_add_file_to_db.py +2 -2
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
- simtools/applications/db_add_value_from_json_to_db.py +2 -2
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +1 -1
- simtools/applications/db_generate_compound_indexes.py +1 -1
- simtools/applications/db_get_array_layouts_from_db.py +2 -2
- simtools/applications/db_get_file_from_db.py +1 -1
- simtools/applications/db_get_parameter_from_db.py +1 -1
- simtools/applications/db_inspect_databases.py +4 -2
- simtools/applications/db_upload_model_repository.py +1 -1
- simtools/applications/derive_ctao_array_layouts.py +1 -1
- simtools/applications/derive_psf_parameters.py +5 -0
- simtools/applications/derive_pulse_shape_parameters.py +195 -0
- simtools/applications/generate_array_config.py +1 -1
- simtools/applications/maintain_simulation_model_add_production.py +11 -21
- simtools/applications/plot_array_layout.py +63 -1
- simtools/applications/production_generate_grid.py +1 -1
- simtools/applications/simulate_flasher.py +3 -2
- simtools/applications/simulate_pedestals.py +1 -1
- simtools/applications/simulate_prod.py +8 -23
- simtools/applications/simulate_prod_htcondor_generator.py +7 -0
- simtools/applications/submit_array_layouts.py +7 -5
- simtools/applications/validate_camera_fov.py +1 -1
- simtools/applications/validate_cumulative_psf.py +2 -2
- simtools/applications/validate_file_using_schema.py +49 -123
- simtools/applications/validate_optics.py +1 -1
- simtools/configuration/commandline_parser.py +15 -15
- simtools/configuration/configurator.py +1 -1
- simtools/corsika/corsika_config.py +199 -91
- simtools/data_model/model_data_writer.py +15 -3
- simtools/data_model/schema.py +145 -36
- simtools/data_model/validate_data.py +82 -48
- simtools/db/db_handler.py +61 -294
- simtools/db/db_model_upload.py +3 -2
- simtools/db/mongo_db.py +626 -0
- simtools/dependencies.py +38 -17
- simtools/io/eventio_handler.py +128 -0
- simtools/job_execution/htcondor_script_generator.py +0 -2
- simtools/layout/array_layout.py +7 -7
- simtools/layout/array_layout_utils.py +4 -4
- simtools/model/array_model.py +72 -72
- simtools/model/calibration_model.py +12 -9
- simtools/model/model_parameter.py +196 -160
- simtools/model/model_repository.py +176 -39
- simtools/model/model_utils.py +3 -3
- simtools/model/site_model.py +59 -27
- simtools/model/telescope_model.py +21 -13
- simtools/ray_tracing/mirror_panel_psf.py +4 -4
- simtools/ray_tracing/psf_analysis.py +11 -8
- simtools/ray_tracing/psf_parameter_optimisation.py +823 -680
- simtools/reporting/docs_auto_report_generator.py +1 -1
- simtools/reporting/docs_read_parameters.py +72 -11
- simtools/runners/corsika_runner.py +12 -3
- simtools/runners/corsika_simtel_runner.py +6 -0
- simtools/runners/runner_services.py +17 -7
- simtools/runners/simtel_runner.py +12 -54
- simtools/schemas/model_parameters/flasher_pulse_exp_decay.schema.yml +2 -0
- simtools/schemas/model_parameters/flasher_pulse_shape.schema.yml +50 -0
- simtools/schemas/model_parameters/flasher_pulse_width.schema.yml +2 -0
- simtools/schemas/simulation_models_info.schema.yml +4 -1
- simtools/simtel/pulse_shapes.py +268 -0
- simtools/simtel/simtel_config_writer.py +179 -21
- simtools/simtel/simtel_io_event_writer.py +2 -2
- simtools/simtel/simulator_array.py +58 -12
- simtools/simtel/simulator_light_emission.py +45 -8
- simtools/simulator.py +361 -346
- simtools/testing/assertions.py +110 -10
- simtools/testing/configuration.py +1 -1
- simtools/testing/log_inspector.py +4 -1
- simtools/testing/sim_telarray_metadata.py +1 -1
- simtools/testing/validate_output.py +46 -15
- simtools/utils/names.py +2 -4
- simtools/utils/value_conversion.py +10 -5
- simtools/version.py +61 -0
- simtools/visualization/legend_handlers.py +14 -4
- simtools/visualization/plot_array_layout.py +229 -33
- simtools/visualization/plot_mirrors.py +837 -0
- simtools/visualization/plot_pixels.py +1 -1
- simtools/visualization/plot_psf.py +1 -1
- simtools/visualization/plot_tables.py +1 -1
- simtools/simtel/simtel_io_file_info.py +0 -62
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/licenses/LICENSE +0 -0
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/top_level.txt +0 -0
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/python3
|
|
2
|
-
"""Base class for simulation model parameters."""
|
|
2
|
+
"""Base class for simulation model parameters (e.g., for SiteModel or TelescopeModel)."""
|
|
3
3
|
|
|
4
4
|
import logging
|
|
5
5
|
import shutil
|
|
6
|
-
from copy import copy
|
|
6
|
+
from copy import copy, deepcopy
|
|
7
7
|
|
|
8
8
|
import astropy.units as u
|
|
9
9
|
|
|
10
10
|
import simtools.utils.general as gen
|
|
11
|
+
from simtools.data_model import schema
|
|
11
12
|
from simtools.db import db_handler
|
|
12
13
|
from simtools.io import ascii_handler, io_handler
|
|
13
14
|
from simtools.simtel.simtel_config_writer import SimtelConfigWriter
|
|
14
|
-
from simtools.utils import names
|
|
15
|
+
from simtools.utils import names, value_conversion
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class InvalidModelParameterError(Exception):
|
|
@@ -27,8 +28,8 @@ class ModelParameter:
|
|
|
27
28
|
|
|
28
29
|
Parameters
|
|
29
30
|
----------
|
|
30
|
-
|
|
31
|
-
Database
|
|
31
|
+
db_config:
|
|
32
|
+
Database configuration dictionary.
|
|
32
33
|
model_version: str
|
|
33
34
|
Version of the model (ex. 5.0.0).
|
|
34
35
|
site: str
|
|
@@ -38,35 +39,37 @@ class ModelParameter:
|
|
|
38
39
|
collection: str
|
|
39
40
|
instrument class (e.g. telescopes, calibration_devices)
|
|
40
41
|
as stored under collection in the DB.
|
|
41
|
-
mongo_db_config: dict
|
|
42
|
-
MongoDB configuration.
|
|
43
42
|
label: str
|
|
43
|
+
Instance label. Used for output file naming.
|
|
44
|
+
overwrite_model_parameters: str, optional
|
|
45
|
+
File name to overwrite model parameters from DB with provided values.
|
|
44
46
|
Instance label. Important for output file naming.
|
|
45
|
-
|
|
47
|
+
ignore_software_version: bool
|
|
48
|
+
If True, ignore software version checks for deprecated parameters.
|
|
49
|
+
Useful for documentation generation.
|
|
46
50
|
"""
|
|
47
51
|
|
|
48
52
|
def __init__(
|
|
49
53
|
self,
|
|
50
|
-
|
|
54
|
+
db_config,
|
|
51
55
|
model_version,
|
|
52
56
|
site=None,
|
|
53
57
|
array_element_name=None,
|
|
54
58
|
collection="telescopes",
|
|
55
|
-
db=None,
|
|
56
59
|
label=None,
|
|
60
|
+
overwrite_model_parameters=None,
|
|
61
|
+
ignore_software_version=False,
|
|
57
62
|
):
|
|
58
63
|
self._logger = logging.getLogger(__name__)
|
|
59
|
-
self._extra_label = None
|
|
60
64
|
self.io_handler = io_handler.IOHandler()
|
|
61
|
-
self.db = (
|
|
62
|
-
db if db is not None else db_handler.DatabaseHandler(mongo_db_config=mongo_db_config)
|
|
63
|
-
)
|
|
65
|
+
self.db = db_handler.DatabaseHandler(db_config=db_config)
|
|
64
66
|
|
|
65
|
-
self.
|
|
67
|
+
self.parameters = {}
|
|
66
68
|
self._simulation_config_parameters = {sw: {} for sw in names.simulation_software()}
|
|
67
69
|
self.collection = collection
|
|
68
70
|
self.label = label
|
|
69
71
|
self.model_version = model_version
|
|
72
|
+
self.ignore_software_version = ignore_software_version
|
|
70
73
|
self.site = names.validate_site_name(site) if site is not None else None
|
|
71
74
|
self.name = (
|
|
72
75
|
names.validate_array_element_name(array_element_name)
|
|
@@ -78,56 +81,17 @@ class ModelParameter:
|
|
|
78
81
|
)
|
|
79
82
|
self._config_file_directory = None
|
|
80
83
|
self._config_file_path = None
|
|
81
|
-
self.
|
|
82
|
-
|
|
83
|
-
self.simtel_config_writer = None
|
|
84
|
+
self.overwrite_model_parameters = overwrite_model_parameters
|
|
84
85
|
self._added_parameter_files = None
|
|
85
|
-
self._is_config_file_up_to_date = False
|
|
86
86
|
self._is_exported_model_files_up_to_date = False
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
def model_version(self):
|
|
90
|
-
"""Model version."""
|
|
91
|
-
return self._model_version
|
|
92
|
-
|
|
93
|
-
@model_version.setter
|
|
94
|
-
def model_version(self, model_version):
|
|
95
|
-
"""
|
|
96
|
-
Set model version.
|
|
97
|
-
|
|
98
|
-
Parameters
|
|
99
|
-
----------
|
|
100
|
-
model_version: str or list
|
|
101
|
-
Model version (e.g., "6.0.0").
|
|
102
|
-
If a list is passed, it must contain exactly one element,
|
|
103
|
-
and only that element will be used.
|
|
104
|
-
|
|
105
|
-
Raises
|
|
106
|
-
------
|
|
107
|
-
ValueError
|
|
108
|
-
If more than one model version is passed.
|
|
109
|
-
"""
|
|
110
|
-
if isinstance(model_version, list):
|
|
111
|
-
raise ValueError(
|
|
112
|
-
f"Only one model version can be passed to {self.__class__.__name__}, not a list."
|
|
113
|
-
)
|
|
114
|
-
self._model_version = model_version
|
|
115
|
-
|
|
116
|
-
@property
|
|
117
|
-
def parameters(self):
|
|
118
|
-
"""
|
|
119
|
-
Model parameters dictionary.
|
|
88
|
+
self._load_parameters_from_db()
|
|
120
89
|
|
|
121
|
-
|
|
122
|
-
-------
|
|
123
|
-
dict
|
|
124
|
-
Dictionary containing all model parameters
|
|
125
|
-
"""
|
|
126
|
-
return self._parameters
|
|
90
|
+
self.simtel_config_writer = None
|
|
127
91
|
|
|
128
92
|
def _get_parameter_dict(self, par_name):
|
|
129
93
|
"""
|
|
130
|
-
Get model parameter dictionary as stored in the DB.
|
|
94
|
+
Get model parameter dictionary for a specific parameter as stored in the DB.
|
|
131
95
|
|
|
132
96
|
No conversion to values are applied for the use in simtools
|
|
133
97
|
(e.g., no conversion from the string representation of lists
|
|
@@ -155,7 +119,7 @@ class ModelParameter:
|
|
|
155
119
|
f"Parameter {par_name} was not found in the model {self.name}, {self.site}."
|
|
156
120
|
) from e
|
|
157
121
|
|
|
158
|
-
def get_parameter_value(self, par_name
|
|
122
|
+
def get_parameter_value(self, par_name):
|
|
159
123
|
"""
|
|
160
124
|
Get the value of a model parameter.
|
|
161
125
|
|
|
@@ -166,9 +130,6 @@ class ModelParameter:
|
|
|
166
130
|
----------
|
|
167
131
|
par_name: str
|
|
168
132
|
Name of the parameter.
|
|
169
|
-
parameter_dict: dict
|
|
170
|
-
Dictionary with complete DB entry for the given parameter
|
|
171
|
-
(including the 'value', 'units' fields).
|
|
172
133
|
|
|
173
134
|
Returns
|
|
174
135
|
-------
|
|
@@ -176,50 +137,28 @@ class ModelParameter:
|
|
|
176
137
|
|
|
177
138
|
Raises
|
|
178
139
|
------
|
|
179
|
-
|
|
140
|
+
InvalidModelParameterError
|
|
180
141
|
If par_name does not match any parameter in this model.
|
|
181
142
|
"""
|
|
182
|
-
parameter_dict = parameter_dict if parameter_dict else self._get_parameter_dict(par_name)
|
|
183
143
|
try:
|
|
184
|
-
|
|
144
|
+
value = self._get_parameter_dict(par_name)["value"]
|
|
185
145
|
except KeyError as exc:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if isinstance(
|
|
189
|
-
_is_float = False
|
|
146
|
+
raise InvalidModelParameterError(f"Parameter {par_name} does not have a value") from exc
|
|
147
|
+
|
|
148
|
+
if isinstance(value, str):
|
|
190
149
|
try:
|
|
191
150
|
_is_float = self.get_parameter_type(par_name).startswith("float")
|
|
192
|
-
except (
|
|
151
|
+
except (
|
|
152
|
+
InvalidModelParameterError,
|
|
153
|
+
TypeError,
|
|
154
|
+
AttributeError,
|
|
155
|
+
): # float - in case we don't know
|
|
193
156
|
_is_float = True
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
return _parameter
|
|
198
|
-
|
|
199
|
-
def _create_quantity_for_value(self, value, unit):
|
|
200
|
-
"""
|
|
201
|
-
Create an astropy quantity for a single value and unit.
|
|
202
|
-
|
|
203
|
-
Parameters
|
|
204
|
-
----------
|
|
205
|
-
value: numeric or str
|
|
206
|
-
The value to create a quantity for.
|
|
207
|
-
unit: str or None
|
|
208
|
-
The unit string or None.
|
|
157
|
+
value = gen.convert_string_to_list(value, is_float=_is_float)
|
|
158
|
+
if len(value) == 1:
|
|
159
|
+
value = value[0]
|
|
209
160
|
|
|
210
|
-
|
|
211
|
-
-------
|
|
212
|
-
astropy.Quantity or original value
|
|
213
|
-
Astropy quantity for numeric values with units,
|
|
214
|
-
original value for non-numeric values.
|
|
215
|
-
"""
|
|
216
|
-
if not isinstance(value, int | float):
|
|
217
|
-
return value
|
|
218
|
-
|
|
219
|
-
if unit is None or unit == "null":
|
|
220
|
-
return value * u.dimensionless_unscaled
|
|
221
|
-
|
|
222
|
-
return value * u.Unit(unit)
|
|
161
|
+
return value
|
|
223
162
|
|
|
224
163
|
def get_parameter_value_with_unit(self, par_name):
|
|
225
164
|
"""
|
|
@@ -237,7 +176,7 @@ class ModelParameter:
|
|
|
237
176
|
|
|
238
177
|
"""
|
|
239
178
|
_parameter = self._get_parameter_dict(par_name)
|
|
240
|
-
_value = self.get_parameter_value(par_name
|
|
179
|
+
_value = self.get_parameter_value(par_name)
|
|
241
180
|
|
|
242
181
|
try:
|
|
243
182
|
if isinstance(_parameter.get("unit"), str):
|
|
@@ -251,7 +190,9 @@ class ModelParameter:
|
|
|
251
190
|
|
|
252
191
|
# Create list of quantities for multiple values with different units
|
|
253
192
|
return [
|
|
254
|
-
|
|
193
|
+
value_conversion.get_value_as_quantity(
|
|
194
|
+
_value[i], _unit[i] if i < len(_unit) else None
|
|
195
|
+
)
|
|
255
196
|
for i in range(len(_value))
|
|
256
197
|
]
|
|
257
198
|
|
|
@@ -272,13 +213,11 @@ class ModelParameter:
|
|
|
272
213
|
|
|
273
214
|
Returns
|
|
274
215
|
-------
|
|
275
|
-
str
|
|
276
|
-
type of the parameter
|
|
277
|
-
|
|
216
|
+
str
|
|
217
|
+
type of the parameter
|
|
278
218
|
"""
|
|
279
|
-
parameter_dict = self._get_parameter_dict(par_name)
|
|
280
219
|
try:
|
|
281
|
-
return
|
|
220
|
+
return self._get_parameter_dict(par_name)["type"]
|
|
282
221
|
except KeyError:
|
|
283
222
|
self._logger.debug(f"Parameter {par_name} does not have a type.")
|
|
284
223
|
return None
|
|
@@ -298,9 +237,8 @@ class ModelParameter:
|
|
|
298
237
|
True if file flag is set.
|
|
299
238
|
|
|
300
239
|
"""
|
|
301
|
-
parameter_dict = self._get_parameter_dict(par_name)
|
|
302
240
|
try:
|
|
303
|
-
return
|
|
241
|
+
return self._get_parameter_dict(par_name)["file"]
|
|
304
242
|
except KeyError:
|
|
305
243
|
self._logger.debug(f"Parameter {par_name} does not have a file associated with it.")
|
|
306
244
|
return False
|
|
@@ -321,11 +259,6 @@ class ModelParameter:
|
|
|
321
259
|
"""
|
|
322
260
|
return self._get_parameter_dict(par_name)["parameter_version"]
|
|
323
261
|
|
|
324
|
-
def print_parameters(self):
|
|
325
|
-
"""Print parameters and their values for debugging purposes."""
|
|
326
|
-
for par in self.parameters:
|
|
327
|
-
print(f"{par} = {self.get_parameter_value(par)}")
|
|
328
|
-
|
|
329
262
|
def _set_config_file_directory_and_name(self):
|
|
330
263
|
"""Set and create the directory and the name of the config file."""
|
|
331
264
|
if self.name is None and self.site is None:
|
|
@@ -338,10 +271,8 @@ class ModelParameter:
|
|
|
338
271
|
# Setting file name and the location
|
|
339
272
|
config_file_name = names.simtel_config_file_name(
|
|
340
273
|
self.site,
|
|
341
|
-
self.model_version,
|
|
342
274
|
telescope_model_name=self.name,
|
|
343
275
|
label=self.label,
|
|
344
|
-
extra_label=self._extra_label,
|
|
345
276
|
)
|
|
346
277
|
self._config_file_path = self.config_file_directory.joinpath(config_file_name)
|
|
347
278
|
|
|
@@ -379,34 +310,71 @@ class ModelParameter:
|
|
|
379
310
|
pass
|
|
380
311
|
|
|
381
312
|
def _load_parameters_from_db(self):
|
|
382
|
-
"""
|
|
313
|
+
"""
|
|
314
|
+
Read parameters from Database.
|
|
315
|
+
|
|
316
|
+
This is the main function to load the model parameters from the DB.
|
|
317
|
+
"""
|
|
383
318
|
if self.db is None:
|
|
384
319
|
return
|
|
385
320
|
|
|
386
321
|
if self.name or self.site:
|
|
387
|
-
|
|
388
|
-
|
|
322
|
+
# copy parameters dict, is it may be modified later on
|
|
323
|
+
self.parameters = deepcopy(
|
|
324
|
+
self.db.get_model_parameters(
|
|
325
|
+
self.site, self.name, self.collection, self.model_version
|
|
326
|
+
)
|
|
389
327
|
)
|
|
328
|
+
if self.overwrite_model_parameters:
|
|
329
|
+
self.overwrite_parameters_from_file(self.overwrite_model_parameters)
|
|
330
|
+
self._check_model_parameter_software_versions(self.parameters.keys())
|
|
390
331
|
|
|
391
332
|
self._load_simulation_software_parameter()
|
|
333
|
+
for software_name, parameters in self._simulation_config_parameters.items():
|
|
334
|
+
self._check_model_parameter_software_versions(
|
|
335
|
+
parameters.keys(), software_name=software_name
|
|
336
|
+
)
|
|
392
337
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
338
|
+
def _check_model_parameter_software_versions(self, parameter_list, software_name=None):
|
|
339
|
+
"""
|
|
340
|
+
Ensure that model parameters are compatible with the installed software versions.
|
|
341
|
+
|
|
342
|
+
Compares software versions listed in schema files with the installed software versions
|
|
343
|
+
(e.g., sim_telarray, CORSIKA).
|
|
397
344
|
|
|
398
|
-
|
|
345
|
+
Parameters
|
|
346
|
+
----------
|
|
347
|
+
parameter_list: list
|
|
348
|
+
List containing model parameter names.
|
|
349
|
+
software_name: str
|
|
350
|
+
Name of the software for which the parameters are checked.
|
|
351
|
+
"""
|
|
352
|
+
for par_name in parameter_list:
|
|
353
|
+
if par_name in (parameter_schema := names.model_parameters()):
|
|
354
|
+
schema.validate_deprecation_and_version(
|
|
355
|
+
data=parameter_schema[par_name],
|
|
356
|
+
software_name=software_name,
|
|
357
|
+
ignore_software_version=self.ignore_software_version,
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
def overwrite_model_parameter(self, par_name, value, parameter_version=None):
|
|
399
361
|
"""
|
|
400
|
-
|
|
362
|
+
Overwrite the parameter dictionary for a specific parameter in the model.
|
|
363
|
+
|
|
364
|
+
This function does not modify the DB, it affects only the current instance of
|
|
365
|
+
the model parameter dictionary.
|
|
401
366
|
|
|
402
|
-
|
|
367
|
+
If the parameter version is given only, the parameter dictionary is updated
|
|
368
|
+
from the database for the given version.
|
|
403
369
|
|
|
404
370
|
Parameters
|
|
405
371
|
----------
|
|
406
372
|
par_name: str
|
|
407
373
|
Name of the parameter.
|
|
408
374
|
value:
|
|
409
|
-
|
|
375
|
+
New value for the parameter.
|
|
376
|
+
parameter_version: str, optional
|
|
377
|
+
New version for the parameter.
|
|
410
378
|
|
|
411
379
|
Raises
|
|
412
380
|
------
|
|
@@ -416,31 +384,48 @@ class ModelParameter:
|
|
|
416
384
|
if par_name not in self.parameters:
|
|
417
385
|
raise InvalidModelParameterError(f"Parameter {par_name} not in the model")
|
|
418
386
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
387
|
+
if value is None and parameter_version:
|
|
388
|
+
_para_dict = self.db.get_model_parameter(
|
|
389
|
+
parameter=par_name,
|
|
390
|
+
site=self.site,
|
|
391
|
+
array_element_name=self.name,
|
|
392
|
+
parameter_version=parameter_version,
|
|
393
|
+
)
|
|
394
|
+
if _para_dict:
|
|
395
|
+
self.parameters[par_name] = _para_dict.get(par_name)
|
|
396
|
+
self._logger.debug(
|
|
397
|
+
f"Changing parameter {par_name} to version {parameter_version} with value "
|
|
398
|
+
f"{self.parameters[par_name]['value']}"
|
|
399
|
+
)
|
|
400
|
+
else:
|
|
401
|
+
value = gen.convert_string_to_list(value) if isinstance(value, str) else value
|
|
402
|
+
|
|
403
|
+
par_type = self.get_parameter_type(par_name)
|
|
404
|
+
if not gen.validate_data_type(
|
|
405
|
+
reference_dtype=par_type,
|
|
406
|
+
value=value,
|
|
407
|
+
dtype=None,
|
|
408
|
+
allow_subtypes=True,
|
|
409
|
+
):
|
|
410
|
+
raise ValueError(f"Could not cast {value} of type {type(value)} to {par_type}.")
|
|
429
411
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
412
|
+
self._logger.debug(
|
|
413
|
+
f"Changing parameter {par_name} from {self.get_parameter_value(par_name)} "
|
|
414
|
+
f"to {value}"
|
|
415
|
+
)
|
|
416
|
+
self.parameters[par_name]["value"] = value
|
|
417
|
+
if parameter_version:
|
|
418
|
+
self.parameters[par_name]["parameter_version"] = parameter_version
|
|
434
419
|
|
|
435
420
|
# In case parameter is a file, the model files will be outdated
|
|
436
421
|
if self.get_parameter_file_flag(par_name):
|
|
437
422
|
self._is_exported_model_files_up_to_date = False
|
|
438
423
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
def change_multiple_parameters_from_file(self, file_name):
|
|
424
|
+
def overwrite_parameters_from_file(self, file_name):
|
|
442
425
|
"""
|
|
443
|
-
|
|
426
|
+
Overwrite parameters from a file.
|
|
427
|
+
|
|
428
|
+
File is expected to follow the format described in 'simulation_models_info.schema.yml'.
|
|
444
429
|
|
|
445
430
|
This function does not modify the DB, it affects only the current instance.
|
|
446
431
|
This feature is intended for developers and lacks validation.
|
|
@@ -450,34 +435,85 @@ class ModelParameter:
|
|
|
450
435
|
file_name: str
|
|
451
436
|
File containing the parameters to be changed.
|
|
452
437
|
"""
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
"
|
|
438
|
+
changes_data = schema.validate_dict_using_schema(
|
|
439
|
+
data=ascii_handler.collect_data_from_file(file_name=file_name),
|
|
440
|
+
schema_file="simulation_models_info.schema.yml",
|
|
441
|
+
).get("changes", {})
|
|
442
|
+
|
|
443
|
+
key_for_changes = self._get_key_for_parameter_changes(self.site, self.name, changes_data)
|
|
444
|
+
self.overwrite_parameters(changes_data.get(key_for_changes, {}) if key_for_changes else {})
|
|
445
|
+
|
|
446
|
+
def _get_key_for_parameter_changes(self, site, array_element_name, changes_data):
|
|
447
|
+
"""
|
|
448
|
+
Get the key for parameter changes based on site and array element name.
|
|
449
|
+
|
|
450
|
+
For array elements, the following cases are taken into account:
|
|
451
|
+
|
|
452
|
+
- array element name in changes_data: specific array element is returned
|
|
453
|
+
- design type in changes_data: specific design type is returned if array
|
|
454
|
+
element matches this design
|
|
455
|
+
|
|
456
|
+
Parameters
|
|
457
|
+
----------
|
|
458
|
+
site: str
|
|
459
|
+
Site name.
|
|
460
|
+
array_element_name: str
|
|
461
|
+
Array element name.
|
|
462
|
+
changes_data: dict
|
|
463
|
+
Dictionary containing the changes data.
|
|
464
|
+
|
|
465
|
+
Returns
|
|
466
|
+
-------
|
|
467
|
+
str
|
|
468
|
+
Key for parameter changes.
|
|
469
|
+
"""
|
|
470
|
+
if site and not array_element_name:
|
|
471
|
+
return f"OBS-{site}"
|
|
472
|
+
|
|
473
|
+
if array_element_name in changes_data:
|
|
474
|
+
return array_element_name
|
|
475
|
+
|
|
476
|
+
design_type = self.db.get_design_model(
|
|
477
|
+
model_version=self.model_version,
|
|
478
|
+
array_element_name=array_element_name,
|
|
479
|
+
collection=self.collection,
|
|
456
480
|
)
|
|
457
|
-
|
|
458
|
-
|
|
481
|
+
if design_type in changes_data:
|
|
482
|
+
return design_type
|
|
483
|
+
|
|
484
|
+
return None
|
|
459
485
|
|
|
460
|
-
def
|
|
486
|
+
def overwrite_parameters(self, changes):
|
|
461
487
|
"""
|
|
462
488
|
Change the value of multiple existing parameters in the model.
|
|
463
489
|
|
|
464
490
|
This function does not modify the DB, it affects only the current instance.
|
|
465
491
|
|
|
492
|
+
Allows for two types of 'changes' dictionary:
|
|
493
|
+
|
|
494
|
+
- simple: '{parameter_name: new_value, ...}'
|
|
495
|
+
- model repository style:
|
|
496
|
+
'{parameter_name: {"value": new_value, "version": new_version}, ...}'
|
|
497
|
+
|
|
466
498
|
Parameters
|
|
467
499
|
----------
|
|
468
|
-
|
|
469
|
-
Parameters
|
|
500
|
+
changes: dict
|
|
501
|
+
Parameters to be changed.
|
|
502
|
+
"""
|
|
503
|
+
for par_name, par_value in changes.items():
|
|
504
|
+
if par_name in self.parameters:
|
|
505
|
+
if isinstance(par_value, dict) and ("value" in par_value or "version" in par_value):
|
|
506
|
+
self.overwrite_model_parameter(
|
|
507
|
+
par_name, par_value.get("value"), par_value.get("version")
|
|
508
|
+
)
|
|
509
|
+
else:
|
|
510
|
+
self.overwrite_model_parameter(par_name, par_value)
|
|
470
511
|
|
|
512
|
+
def overwrite_model_file(self, par_name, file_path):
|
|
471
513
|
"""
|
|
472
|
-
|
|
473
|
-
if par in self.parameters:
|
|
474
|
-
self.change_parameter(par, value)
|
|
514
|
+
Overwrite the existing model file in the config file directory.
|
|
475
515
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
def export_parameter_file(self, par_name, file_path):
|
|
479
|
-
"""
|
|
480
|
-
Export a file to the config file directory.
|
|
516
|
+
Keeps track of updated model file with '_added_parameter_files' attribute.
|
|
481
517
|
|
|
482
518
|
Parameters
|
|
483
519
|
----------
|
|
@@ -492,7 +528,7 @@ class ModelParameter:
|
|
|
492
528
|
|
|
493
529
|
def export_model_files(self, destination_path=None, update_if_necessary=False):
|
|
494
530
|
"""
|
|
495
|
-
Export
|
|
531
|
+
Export model files from the database into the config file directory.
|
|
496
532
|
|
|
497
533
|
Parameters
|
|
498
534
|
----------
|