gammasimtools 0.20.0__py3-none-any.whl → 0.21.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 (25) hide show
  1. {gammasimtools-0.20.0.dist-info → gammasimtools-0.21.0.dist-info}/METADATA +1 -1
  2. {gammasimtools-0.20.0.dist-info → gammasimtools-0.21.0.dist-info}/RECORD +24 -23
  3. {gammasimtools-0.20.0.dist-info → gammasimtools-0.21.0.dist-info}/entry_points.txt +1 -1
  4. simtools/_version.py +2 -2
  5. simtools/applications/db_generate_compound_indexes.py +1 -1
  6. simtools/applications/derive_psf_parameters.py +58 -39
  7. simtools/applications/generate_corsika_histograms.py +7 -184
  8. simtools/applications/maintain_simulation_model_add_production.py +105 -0
  9. simtools/applications/plot_simtel_events.py +2 -228
  10. simtools/applications/print_version.py +8 -7
  11. simtools/corsika/corsika_histograms.py +81 -0
  12. simtools/db/db_handler.py +45 -11
  13. simtools/db/db_model_upload.py +40 -14
  14. simtools/model/model_repository.py +118 -63
  15. simtools/ray_tracing/psf_parameter_optimisation.py +999 -565
  16. simtools/simtel/simtel_config_writer.py +1 -1
  17. simtools/simulator.py +1 -4
  18. simtools/version.py +89 -0
  19. simtools/{corsika/corsika_histograms_visualize.py → visualization/plot_corsika_histograms.py} +109 -0
  20. simtools/visualization/plot_psf.py +673 -0
  21. simtools/visualization/plot_simtel_events.py +284 -87
  22. simtools/applications/maintain_simulation_model_add_production_table.py +0 -71
  23. {gammasimtools-0.20.0.dist-info → gammasimtools-0.21.0.dist-info}/WHEEL +0 -0
  24. {gammasimtools-0.20.0.dist-info → gammasimtools-0.21.0.dist-info}/licenses/LICENSE +0 -0
  25. {gammasimtools-0.20.0.dist-info → gammasimtools-0.21.0.dist-info}/top_level.txt +0 -0
@@ -5,9 +5,7 @@ a gitlab repository ('SimulationModels'). This module provides service
5
5
  functions to interact with and verify the repository.
6
6
  """
7
7
 
8
- import json
9
8
  import logging
10
- import shutil
11
9
  from pathlib import Path
12
10
 
13
11
  from simtools.io import ascii_handler
@@ -136,9 +134,15 @@ def _get_model_parameter_file_path(
136
134
  )
137
135
 
138
136
 
139
- def copy_and_update_production_table(args_dict):
137
+ def generate_new_production(args_dict):
140
138
  """
141
- Copy and update simulation model production tables.
139
+ Generate a new production definition (production tables and model parameters).
140
+
141
+ The following steps are performed:
142
+
143
+ - copy of production tables from an existing base model version
144
+ - update production tables with changes defined in a YAML file
145
+ - generate new model parameter entries for changed parameters
142
146
 
143
147
  Parameters
144
148
  ----------
@@ -147,85 +151,134 @@ def copy_and_update_production_table(args_dict):
147
151
  """
148
152
  modifications = ascii_handler.collect_data_from_file(args_dict["modifications"])
149
153
  changes = modifications.get("changes", {})
154
+ base_model_version = args_dict["base_model_version"]
150
155
  model_version = modifications["model_version"]
151
156
 
152
157
  simulation_models_path = Path(args_dict["simulation_models_path"])
153
- source_prod_table_path = (
154
- simulation_models_path / "productions" / args_dict["source_prod_table_dir"]
155
- )
156
- target_prod_table_path = simulation_models_path / "productions" / model_version
158
+ source_path = simulation_models_path / "productions" / base_model_version
159
+ target_path = simulation_models_path / "productions" / model_version
157
160
  model_parameters_dir = simulation_models_path / "model_parameters"
161
+ patch_update = args_dict.get("patch_update", False)
158
162
 
159
- _logger.info(
160
- f"Copying production tables from {source_prod_table_path} to {target_prod_table_path}"
161
- )
163
+ _logger.info(f"Copying production tables from {source_path} to {target_path}")
162
164
 
163
- if Path(target_prod_table_path).exists():
164
- raise FileExistsError(
165
- f"The target production table directory '{target_prod_table_path}' already exists."
166
- )
167
- shutil.copytree(source_prod_table_path, target_prod_table_path)
165
+ _apply_changes_to_production_tables(
166
+ source_path,
167
+ target_path,
168
+ changes,
169
+ model_version,
170
+ patch_update,
171
+ )
168
172
 
169
- _apply_changes_to_production_tables(target_prod_table_path, changes, model_version)
173
+ _apply_changes_to_model_parameters(changes, model_parameters_dir)
170
174
 
171
- for telescope, parameters in changes.items():
172
- for param, param_data in parameters.items():
173
- if param_data.get("value"):
174
- _create_new_parameter_entry(telescope, param, param_data, model_parameters_dir)
175
175
 
176
+ def _apply_changes_to_production_tables(
177
+ source_path, target_path, changes, model_version, patch_update
178
+ ):
179
+ """
180
+ Apply changes to production tables and write them to target directory.
176
181
 
177
- def _apply_changes_to_production_tables(target_prod_table_path, changes, model_version):
178
- """Apply changes to the production tables in the target directory."""
179
- for file_path in Path(target_prod_table_path).rglob("*.json"):
180
- if file_path.name.startswith("configuration"):
181
- continue
182
+ Parameters
183
+ ----------
184
+ source_path: Path
185
+ Path to the source production tables.
186
+ target_path: Path
187
+ Path to the target production tables.
188
+ changes: dict
189
+ The changes to be applied.
190
+ model_version: str
191
+ The model version to be set in the JSON data.
192
+ patch_update: bool
193
+ Patch update, copy only tables for changed elements.
194
+ """
195
+ target_path.mkdir(parents=True, exist_ok=True)
196
+ for file_path in Path(source_path).rglob("*.json"):
182
197
  data = ascii_handler.collect_data_from_file(file_path)
183
- _apply_changes_to_production_table(data, changes, model_version)
184
- with file_path.open("w", encoding="utf-8") as f:
185
- json.dump(data, f, indent=4, sort_keys=True)
186
- f.write("\n")
198
+ write_to_disk = _apply_changes_to_production_table(
199
+ data, changes, model_version, patch_update
200
+ )
201
+ if write_to_disk:
202
+ ascii_handler.write_data_to_file(data, target_path / file_path.name, sort_keys=True)
187
203
 
188
204
 
189
- def _apply_changes_to_production_table(data, changes, model_version):
205
+ def _apply_changes_to_production_table(data, changes, model_version, patch_update):
190
206
  """
191
207
  Recursively apply changes to the new production tables.
192
208
 
193
209
  Parameters
194
210
  ----------
195
- data: dict or list
196
- The JSON data to be updated.
211
+ data: dict
212
+ The data to be updated.
197
213
  changes: dict
198
214
  The changes to be applied.
199
215
  model_version: str
200
216
  The model version to be set in the JSON data.
217
+ patch_update: bool
218
+ Patch update, copy only tables for changed elements.
219
+
220
+ Returns
221
+ -------
222
+ bool
223
+ True if data was modified and should be written to disk (patch updates) and always
224
+ for full updates.
201
225
  """
202
226
  if isinstance(data, dict):
203
- if "model_version" in data:
204
- data["model_version"] = model_version
205
- _update_parameters(data.get("parameters", {}), changes)
206
-
207
- elif isinstance(data, list):
208
- for item in data:
209
- _apply_changes_to_production_table(item, changes, model_version)
210
-
211
-
212
- def _update_parameters(params, changes):
213
- """Update parameters in the given dictionary based on changes."""
214
- for telescope, updates in changes.items():
215
- if telescope not in params:
216
- continue
217
- for param, param_data in updates.items():
218
- if param in params[telescope]:
219
- old = params[telescope][param]
220
- new = param_data["version"]
221
- _logger.info(f"Updating '{telescope} - {param}' from {old} to {new}")
222
- params[telescope][param] = new
223
- else:
224
- _logger.info(
225
- f"Adding new parameter '{telescope} - {param}' "
226
- f"with version {param_data['version']}"
227
- )
228
- params[telescope][param] = param_data["version"]
227
+ table_name = data["production_table_name"]
228
+ data["model_version"] = model_version
229
+ if table_name in changes:
230
+ data["parameters"] = _update_parameters(
231
+ {} if patch_update else data["parameters"].get(table_name, {}), changes, table_name
232
+ )
233
+ elif patch_update:
234
+ return False
235
+ else:
236
+ raise TypeError(f"Unsupported data type {type(data)} in production table update")
237
+
238
+ return True
239
+
240
+
241
+ def _update_parameters(table_parameters, changes, table_name):
242
+ """
243
+ Create a new parameters dictionary containing only the parameters for the specified table.
244
+
245
+ Parameters
246
+ ----------
247
+ table_parameters: dict
248
+ Parameters for the specific table.
249
+ changes: dict
250
+ The changes to be applied, containing table and parameter information.
251
+ table_name: str
252
+ The name of the production table to filter parameters for.
253
+
254
+ Returns
255
+ -------
256
+ dict
257
+ Dictionary containing only the new/changed parameters for the specified table.
258
+ """
259
+ updated_parameters_dict = {table_name: table_parameters}
260
+ for param, data in changes[table_name].items():
261
+ version = data["version"]
262
+ _logger.info(f"Setting '{table_name} - {param}' to version {version}")
263
+ updated_parameters_dict[table_name][param] = version
264
+ return updated_parameters_dict
265
+
266
+
267
+ def _apply_changes_to_model_parameters(changes, model_parameters_dir):
268
+ """
269
+ Apply changes to model parameters by creating new parameter entries.
270
+
271
+ Parameters
272
+ ----------
273
+ changes: dict
274
+ The changes to be applied.
275
+ model_parameters_dir: str
276
+ Path to the model parameters directory.
277
+ """
278
+ for telescope, parameters in changes.items():
279
+ for param, param_data in parameters.items():
280
+ if param_data.get("value"):
281
+ _create_new_parameter_entry(telescope, param, param_data, model_parameters_dir)
229
282
 
230
283
 
231
284
  def _create_new_parameter_entry(telescope, param, param_data, model_parameters_dir):
@@ -266,14 +319,16 @@ def _create_new_parameter_entry(telescope, param, param_data, model_parameters_d
266
319
  json_data["parameter_version"] = _update_model_parameter_version(
267
320
  json_data, param_data, param, telescope
268
321
  )
269
- json_data["value"] = param_data["value"]
322
+ # important for e.g. nsb_pixel_rate
323
+ if isinstance(json_data["value"], list) and not isinstance(param_data["value"], list):
324
+ json_data["value"] = [param_data["value"]] * len(json_data["value"])
325
+ else:
326
+ json_data["value"] = param_data["value"]
270
327
 
271
328
  new_file_name = f"{param}-{param_data['version']}.json"
272
329
  new_file_path = param_dir / new_file_name
273
330
 
274
- with new_file_path.open("w", encoding="utf-8") as f:
275
- json.dump(json_data, f, indent=4)
276
- f.write("\n")
331
+ ascii_handler.write_data_to_file(json_data, new_file_path, sort_keys=True)
277
332
  _logger.info(f"Created new model parameter JSON file: {new_file_path}")
278
333
 
279
334