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.
Files changed (90) hide show
  1. {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/METADATA +1 -1
  2. {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/RECORD +89 -85
  3. {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/entry_points.txt +1 -0
  4. simtools/_version.py +2 -2
  5. simtools/application_control.py +54 -4
  6. simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -1
  7. simtools/applications/db_add_file_to_db.py +2 -2
  8. simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
  9. simtools/applications/db_add_value_from_json_to_db.py +2 -2
  10. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +1 -1
  11. simtools/applications/db_generate_compound_indexes.py +1 -1
  12. simtools/applications/db_get_array_layouts_from_db.py +2 -2
  13. simtools/applications/db_get_file_from_db.py +1 -1
  14. simtools/applications/db_get_parameter_from_db.py +1 -1
  15. simtools/applications/db_inspect_databases.py +4 -2
  16. simtools/applications/db_upload_model_repository.py +1 -1
  17. simtools/applications/derive_ctao_array_layouts.py +1 -1
  18. simtools/applications/derive_psf_parameters.py +5 -0
  19. simtools/applications/derive_pulse_shape_parameters.py +195 -0
  20. simtools/applications/generate_array_config.py +1 -1
  21. simtools/applications/maintain_simulation_model_add_production.py +11 -21
  22. simtools/applications/plot_array_layout.py +63 -1
  23. simtools/applications/production_generate_grid.py +1 -1
  24. simtools/applications/simulate_flasher.py +3 -2
  25. simtools/applications/simulate_pedestals.py +1 -1
  26. simtools/applications/simulate_prod.py +8 -23
  27. simtools/applications/simulate_prod_htcondor_generator.py +7 -0
  28. simtools/applications/submit_array_layouts.py +7 -5
  29. simtools/applications/validate_camera_fov.py +1 -1
  30. simtools/applications/validate_cumulative_psf.py +2 -2
  31. simtools/applications/validate_file_using_schema.py +49 -123
  32. simtools/applications/validate_optics.py +1 -1
  33. simtools/configuration/commandline_parser.py +15 -15
  34. simtools/configuration/configurator.py +1 -1
  35. simtools/corsika/corsika_config.py +199 -91
  36. simtools/data_model/model_data_writer.py +15 -3
  37. simtools/data_model/schema.py +145 -36
  38. simtools/data_model/validate_data.py +82 -48
  39. simtools/db/db_handler.py +61 -294
  40. simtools/db/db_model_upload.py +3 -2
  41. simtools/db/mongo_db.py +626 -0
  42. simtools/dependencies.py +38 -17
  43. simtools/io/eventio_handler.py +128 -0
  44. simtools/job_execution/htcondor_script_generator.py +0 -2
  45. simtools/layout/array_layout.py +7 -7
  46. simtools/layout/array_layout_utils.py +4 -4
  47. simtools/model/array_model.py +72 -72
  48. simtools/model/calibration_model.py +12 -9
  49. simtools/model/model_parameter.py +196 -160
  50. simtools/model/model_repository.py +176 -39
  51. simtools/model/model_utils.py +3 -3
  52. simtools/model/site_model.py +59 -27
  53. simtools/model/telescope_model.py +21 -13
  54. simtools/ray_tracing/mirror_panel_psf.py +4 -4
  55. simtools/ray_tracing/psf_analysis.py +11 -8
  56. simtools/ray_tracing/psf_parameter_optimisation.py +823 -680
  57. simtools/reporting/docs_auto_report_generator.py +1 -1
  58. simtools/reporting/docs_read_parameters.py +72 -11
  59. simtools/runners/corsika_runner.py +12 -3
  60. simtools/runners/corsika_simtel_runner.py +6 -0
  61. simtools/runners/runner_services.py +17 -7
  62. simtools/runners/simtel_runner.py +12 -54
  63. simtools/schemas/model_parameters/flasher_pulse_exp_decay.schema.yml +2 -0
  64. simtools/schemas/model_parameters/flasher_pulse_shape.schema.yml +50 -0
  65. simtools/schemas/model_parameters/flasher_pulse_width.schema.yml +2 -0
  66. simtools/schemas/simulation_models_info.schema.yml +4 -1
  67. simtools/simtel/pulse_shapes.py +268 -0
  68. simtools/simtel/simtel_config_writer.py +179 -21
  69. simtools/simtel/simtel_io_event_writer.py +2 -2
  70. simtools/simtel/simulator_array.py +58 -12
  71. simtools/simtel/simulator_light_emission.py +45 -8
  72. simtools/simulator.py +361 -346
  73. simtools/testing/assertions.py +110 -10
  74. simtools/testing/configuration.py +1 -1
  75. simtools/testing/log_inspector.py +4 -1
  76. simtools/testing/sim_telarray_metadata.py +1 -1
  77. simtools/testing/validate_output.py +46 -15
  78. simtools/utils/names.py +2 -4
  79. simtools/utils/value_conversion.py +10 -5
  80. simtools/version.py +61 -0
  81. simtools/visualization/legend_handlers.py +14 -4
  82. simtools/visualization/plot_array_layout.py +229 -33
  83. simtools/visualization/plot_mirrors.py +837 -0
  84. simtools/visualization/plot_pixels.py +1 -1
  85. simtools/visualization/plot_psf.py +1 -1
  86. simtools/visualization/plot_tables.py +1 -1
  87. simtools/simtel/simtel_io_file_info.py +0 -62
  88. {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/WHEEL +0 -0
  89. {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/licenses/LICENSE +0 -0
  90. {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
- db: DatabaseHandler
31
- Database handler.
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
- mongo_db_config,
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._parameters = {}
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._load_parameters_from_db()
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
- @property
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
- Returns
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, parameter_dict=None):
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
- KeyError
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
- _parameter = parameter_dict["value"]
144
+ value = self._get_parameter_dict(par_name)["value"]
185
145
  except KeyError as exc:
186
- self._logger.error(f"Parameter {par_name} does not have a value")
187
- raise exc
188
- if isinstance(_parameter, str):
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 (InvalidModelParameterError, TypeError): # float - in case we don't know
151
+ except (
152
+ InvalidModelParameterError,
153
+ TypeError,
154
+ AttributeError,
155
+ ): # float - in case we don't know
193
156
  _is_float = True
194
- _parameter = gen.convert_string_to_list(_parameter, is_float=_is_float)
195
- _parameter = _parameter if len(_parameter) > 1 else _parameter[0]
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
- Returns
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, _parameter)
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
- self._create_quantity_for_value(_value[i], _unit[i] if i < len(_unit) else None)
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 or None
276
- type of the parameter (None if no type is defined)
277
-
216
+ str
217
+ type of the parameter
278
218
  """
279
- parameter_dict = self._get_parameter_dict(par_name)
280
219
  try:
281
- return parameter_dict["type"]
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 parameter_dict["file"]
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
- """Read parameters from DB and store them in _parameters."""
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
- self._parameters = self.db.get_model_parameters(
388
- self.site, self.name, self.collection, self.model_version
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
- @property
394
- def extra_label(self):
395
- """Return the extra label if defined, if not return ''."""
396
- return self._extra_label if self._extra_label is not None else ""
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
- def change_parameter(self, par_name, value):
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
- Change the value of an existing parameter.
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
- This function does not modify the DB, it affects only the current instance.
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
- Value of the parameter.
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
- value = gen.convert_string_to_list(value) if isinstance(value, str) else value
420
-
421
- par_type = self.get_parameter_type(par_name)
422
- if not gen.validate_data_type(
423
- reference_dtype=par_type,
424
- value=value,
425
- dtype=None,
426
- allow_subtypes=True,
427
- ):
428
- raise ValueError(f"Could not cast {value} of type {type(value)} to {par_type}.")
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
- self._logger.debug(
431
- f"Changing parameter {par_name} from {self.get_parameter_value(par_name)} to {value}"
432
- )
433
- self.parameters[par_name]["value"] = value
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
- self._is_config_file_up_to_date = False
440
-
441
- def change_multiple_parameters_from_file(self, file_name):
424
+ def overwrite_parameters_from_file(self, file_name):
442
425
  """
443
- Change values of multiple existing parameters in the model from a file.
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
- self._logger.warning(
454
- "Changing multiple parameters from file is a feature for developers."
455
- "Insufficient validation of parameters."
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
- self._logger.debug(f"Changing parameters from file {file_name}")
458
- self.change_multiple_parameters(**ascii_handler.collect_data_from_file(file_name=file_name))
481
+ if design_type in changes_data:
482
+ return design_type
483
+
484
+ return None
459
485
 
460
- def change_multiple_parameters(self, **kwargs):
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
- **kwargs
469
- Parameters should be passed as parameter_name=value.
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
- for par, value in kwargs.items():
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
- self._is_config_file_up_to_date = False
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 the model files into the config file directory.
531
+ Export model files from the database into the config file directory.
496
532
 
497
533
  Parameters
498
534
  ----------