gammasimtools 0.25.0__py3-none-any.whl → 0.26.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 (125) hide show
  1. {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/METADATA +2 -1
  2. {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/RECORD +122 -121
  3. {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/entry_points.txt +2 -1
  4. {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/licenses/LICENSE +1 -1
  5. simtools/_version.py +2 -2
  6. simtools/application_control.py +35 -7
  7. simtools/applications/calculate_incident_angles.py +0 -2
  8. simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -2
  9. simtools/applications/db_add_file_to_db.py +1 -1
  10. simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
  11. simtools/applications/db_add_value_from_json_to_db.py +1 -1
  12. simtools/applications/db_generate_compound_indexes.py +1 -1
  13. simtools/applications/db_get_array_layouts_from_db.py +2 -6
  14. simtools/applications/db_get_file_from_db.py +1 -1
  15. simtools/applications/db_get_parameter_from_db.py +1 -1
  16. simtools/applications/db_inspect_databases.py +1 -1
  17. simtools/applications/db_upload_model_repository.py +1 -1
  18. simtools/applications/derive_ctao_array_layouts.py +1 -2
  19. simtools/applications/derive_mirror_rnda.py +1 -3
  20. simtools/applications/derive_psf_parameters.py +0 -1
  21. simtools/applications/derive_pulse_shape_parameters.py +0 -1
  22. simtools/applications/derive_trigger_rates.py +1 -1
  23. simtools/applications/docs_produce_array_element_report.py +2 -8
  24. simtools/applications/docs_produce_calibration_reports.py +1 -3
  25. simtools/applications/docs_produce_model_parameter_reports.py +0 -2
  26. simtools/applications/docs_produce_simulation_configuration_report.py +1 -3
  27. simtools/applications/generate_array_config.py +0 -1
  28. simtools/applications/generate_corsika_histograms.py +48 -235
  29. simtools/applications/generate_regular_arrays.py +5 -35
  30. simtools/applications/generate_simtel_event_data.py +2 -2
  31. simtools/applications/maintain_simulation_model_add_production.py +2 -2
  32. simtools/applications/maintain_simulation_model_write_array_element_positions.py +87 -0
  33. simtools/applications/plot_array_layout.py +5 -111
  34. simtools/applications/plot_simulated_event_distributions.py +57 -0
  35. simtools/applications/plot_tabular_data.py +0 -1
  36. simtools/applications/plot_tabular_data_for_model_parameter.py +1 -6
  37. simtools/applications/production_derive_corsika_limits.py +1 -1
  38. simtools/applications/production_generate_grid.py +0 -1
  39. simtools/applications/run_application.py +1 -1
  40. simtools/applications/simulate_flasher.py +0 -2
  41. simtools/applications/simulate_illuminator.py +0 -1
  42. simtools/applications/simulate_pedestals.py +1 -5
  43. simtools/applications/simulate_prod.py +1 -5
  44. simtools/applications/simulate_prod_htcondor_generator.py +1 -1
  45. simtools/applications/submit_array_layouts.py +2 -4
  46. simtools/applications/submit_model_parameter_from_external.py +1 -3
  47. simtools/applications/validate_camera_efficiency.py +0 -1
  48. simtools/applications/validate_camera_fov.py +0 -1
  49. simtools/applications/validate_cumulative_psf.py +0 -2
  50. simtools/applications/validate_optics.py +0 -13
  51. simtools/camera/camera_efficiency.py +1 -6
  52. simtools/camera/single_photon_electron_spectrum.py +2 -1
  53. simtools/configuration/commandline_parser.py +35 -2
  54. simtools/configuration/configurator.py +6 -11
  55. simtools/corsika/corsika_config.py +16 -21
  56. simtools/corsika/corsika_histograms.py +411 -1735
  57. simtools/corsika/primary_particle.py +1 -1
  58. simtools/data_model/metadata_collector.py +5 -2
  59. simtools/data_model/metadata_model.py +0 -4
  60. simtools/data_model/model_data_writer.py +13 -15
  61. simtools/data_model/validate_data.py +1 -3
  62. simtools/db/db_handler.py +19 -8
  63. simtools/dependencies.py +81 -38
  64. simtools/io/ascii_handler.py +4 -2
  65. simtools/io/table_handler.py +1 -1
  66. simtools/layout/array_layout.py +4 -12
  67. simtools/layout/array_layout_utils.py +226 -57
  68. simtools/model/array_model.py +1 -13
  69. simtools/model/calibration_model.py +0 -4
  70. simtools/model/legacy_model_parameter.py +134 -0
  71. simtools/model/model_parameter.py +24 -13
  72. simtools/model/model_utils.py +1 -6
  73. simtools/model/site_model.py +0 -4
  74. simtools/model/telescope_model.py +6 -11
  75. simtools/production_configuration/derive_corsika_limits.py +6 -11
  76. simtools/production_configuration/interpolation_handler.py +16 -16
  77. simtools/ray_tracing/incident_angles.py +5 -11
  78. simtools/ray_tracing/mirror_panel_psf.py +3 -7
  79. simtools/ray_tracing/psf_analysis.py +18 -19
  80. simtools/ray_tracing/psf_parameter_optimisation.py +0 -1
  81. simtools/ray_tracing/ray_tracing.py +6 -15
  82. simtools/reporting/docs_auto_report_generator.py +8 -13
  83. simtools/reporting/docs_read_parameters.py +2 -8
  84. simtools/runners/corsika_runner.py +5 -9
  85. simtools/runners/corsika_simtel_runner.py +3 -8
  86. simtools/runners/simtel_runner.py +0 -5
  87. simtools/runners/simtools_runner.py +2 -4
  88. simtools/settings.py +154 -0
  89. simtools/{io/eventio_handler.py → sim_events/file_info.py} +3 -3
  90. simtools/{simtel/simtel_io_event_histograms.py → sim_events/histograms.py} +25 -15
  91. simtools/{simtel/simtel_io_event_reader.py → sim_events/reader.py} +20 -17
  92. simtools/{simtel/simtel_io_event_writer.py → sim_events/writer.py} +84 -25
  93. simtools/simtel/pulse_shapes.py +7 -2
  94. simtools/simtel/simtel_config_writer.py +79 -36
  95. simtools/simtel/simtel_table_reader.py +6 -4
  96. simtools/simtel/simulator_array.py +4 -11
  97. simtools/simtel/simulator_camera_efficiency.py +4 -6
  98. simtools/simtel/simulator_light_emission.py +69 -24
  99. simtools/simtel/simulator_ray_tracing.py +4 -10
  100. simtools/simulator.py +7 -14
  101. simtools/telescope_trigger_rates.py +3 -4
  102. simtools/testing/assertions.py +84 -33
  103. simtools/testing/configuration.py +1 -2
  104. simtools/testing/helpers.py +2 -3
  105. simtools/testing/log_inspector.py +1 -0
  106. simtools/testing/sim_telarray_metadata.py +1 -1
  107. simtools/testing/validate_output.py +34 -23
  108. simtools/utils/general.py +37 -0
  109. simtools/utils/geometry.py +0 -77
  110. simtools/utils/names.py +5 -5
  111. simtools/visualization/legend_handlers.py +7 -6
  112. simtools/visualization/plot_array_layout.py +91 -16
  113. simtools/visualization/plot_corsika_histograms.py +143 -605
  114. simtools/visualization/plot_mirrors.py +1 -4
  115. simtools/visualization/plot_pixels.py +2 -4
  116. simtools/visualization/plot_psf.py +0 -1
  117. simtools/visualization/plot_simtel_event_histograms.py +4 -4
  118. simtools/visualization/plot_simtel_events.py +6 -11
  119. simtools/visualization/plot_tables.py +8 -19
  120. simtools/visualization/visualize.py +22 -2
  121. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +0 -160
  122. simtools/applications/print_version.py +0 -53
  123. simtools/io/hdf5_handler.py +0 -139
  124. {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/WHEEL +0 -0
  125. {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,9 @@
3
3
  import logging
4
4
  from pathlib import Path
5
5
 
6
+ import astropy.units as u
7
+ from astropy.table import QTable, Table
8
+
6
9
  import simtools.utils.general as gen
7
10
  from simtools.data_model import data_reader
8
11
  from simtools.data_model.metadata_collector import MetadataCollector
@@ -137,7 +140,7 @@ def merge_array_layouts(layouts_1, layouts_2):
137
140
  return merged_layout
138
141
 
139
142
 
140
- def write_array_layouts(array_layouts, args_dict, db_config):
143
+ def write_array_layouts(array_layouts, args_dict):
141
144
  """
142
145
  Write array layouts as model parameter.
143
146
 
@@ -147,8 +150,6 @@ def write_array_layouts(array_layouts, args_dict, db_config):
147
150
  Command line arguments.
148
151
  array_layouts : dict
149
152
  Array layouts to be written.
150
- db_config : dict
151
- Database configuration.
152
153
  """
153
154
  site = args_dict.get("site") or array_layouts.get("site")
154
155
  _logger.info(f"Writing updated array layouts to the database for site {site}.")
@@ -165,7 +166,6 @@ def write_array_layouts(array_layouts, args_dict, db_config):
165
166
  instrument=f"OBS-{site}",
166
167
  parameter_version=args_dict.get("updated_parameter_version"),
167
168
  output_file=output_file,
168
- db_config=db_config,
169
169
  )
170
170
  MetadataCollector.dump(
171
171
  args_dict,
@@ -208,9 +208,7 @@ def validate_array_layouts_with_db(production_table, array_layouts):
208
208
  return array_layouts
209
209
 
210
210
 
211
- def get_array_layouts_from_parameter_file(
212
- file_path, model_version, db_config, coordinate_system="ground"
213
- ):
211
+ def get_array_layouts_from_parameter_file(file_path, model_version, coordinate_system="ground"):
214
212
  """
215
213
  Retrieve array layouts from parameter file.
216
214
 
@@ -220,8 +218,6 @@ def get_array_layouts_from_parameter_file(
220
218
  Path to the array layout parameter file.
221
219
  model_version : str
222
220
  Model version to retrieve.
223
- db_config : dict
224
- Database configuration.
225
221
  coordinate_system : str
226
222
  Coordinate system to use for the array elements (default is "ground").
227
223
 
@@ -237,24 +233,19 @@ def get_array_layouts_from_parameter_file(
237
233
  raise ValueError("Missing 'value' key in layout file.") from exc
238
234
  site = array_layouts.get("site")
239
235
 
240
- layouts = []
241
- for layout in value:
242
- layouts.append(
243
- _get_array_layout_dict(
244
- db_config,
245
- model_version,
246
- site,
247
- layout.get("elements"),
248
- layout["name"],
249
- coordinate_system,
250
- )
236
+ return [
237
+ _get_array_layout_dict(
238
+ model_version,
239
+ site,
240
+ layout.get("elements"),
241
+ layout["name"],
242
+ coordinate_system,
251
243
  )
252
- return layouts
244
+ for layout in value
245
+ ]
253
246
 
254
247
 
255
- def get_array_layouts_from_db(
256
- layout_name, site, model_version, db_config, coordinate_system="ground"
257
- ):
248
+ def get_array_layouts_from_db(layout_name, site, model_version, coordinate_system="ground"):
258
249
  """
259
250
  Retrieve all array layouts from the database and return as list of astropy tables.
260
251
 
@@ -266,8 +257,6 @@ def get_array_layouts_from_db(
266
257
  Site identifier.
267
258
  model_version : str
268
259
  Model version to retrieve.
269
- db_config : dict
270
- Database configuration.
271
260
  coordinate_system : str
272
261
  Coordinate system to use for the array elements (default is "ground").
273
262
 
@@ -280,23 +269,20 @@ def get_array_layouts_from_db(
280
269
  if layout_name:
281
270
  layout_names = gen.ensure_iterable(layout_name)
282
271
  else:
283
- site_model = SiteModel(site=site, model_version=model_version, db_config=db_config)
272
+ site_model = SiteModel(site=site, model_version=model_version)
284
273
  layout_names = site_model.get_list_of_array_layouts()
285
274
 
286
- layouts = []
287
- for _layout_name in layout_names:
288
- layouts.append(
289
- _get_array_layout_dict(
290
- db_config, model_version, site, None, _layout_name, coordinate_system
291
- )
292
- )
275
+ layouts = [
276
+ _get_array_layout_dict(model_version, site, None, _layout_name, coordinate_system)
277
+ for _layout_name in layout_names
278
+ ]
293
279
  if len(layouts) == 1:
294
280
  return layouts[0]
295
281
  return layouts
296
282
 
297
283
 
298
284
  def get_array_layouts_using_telescope_lists_from_db(
299
- telescope_lists, site, model_version, db_config, coordinate_system="ground"
285
+ telescope_lists, site, model_version, coordinate_system="ground"
300
286
  ):
301
287
  """
302
288
  Retrieve array layouts from the database using telescope lists.
@@ -309,8 +295,6 @@ def get_array_layouts_using_telescope_lists_from_db(
309
295
  Site identifier.
310
296
  model_version : str
311
297
  Model version to retrieve.
312
- db_config : dict
313
- Database configuration.
314
298
  coordinate_system : str
315
299
  Coordinate system to use for the array elements (default is "ground").
316
300
 
@@ -333,9 +317,7 @@ def get_array_layouts_using_telescope_lists_from_db(
333
317
  _site = sites.pop()
334
318
 
335
319
  layouts.append(
336
- _get_array_layout_dict(
337
- db_config, model_version, _site, telescope_list, None, coordinate_system
338
- )
320
+ _get_array_layout_dict(model_version, _site, telescope_list, None, coordinate_system)
339
321
  )
340
322
  return layouts
341
323
 
@@ -357,23 +339,18 @@ def get_array_layouts_from_file(file_path):
357
339
  if isinstance(file_path, str | Path):
358
340
  file_path = [file_path]
359
341
 
360
- layouts = []
361
- for _file in file_path:
362
- layouts.append(
363
- {
364
- "name": (Path(_file).name).split(".")[0],
365
- "array_elements": data_reader.read_table_from_file(file_name=_file),
366
- }
367
- )
368
- return layouts
342
+ return [
343
+ {
344
+ "name": Path(_file).stem,
345
+ "array_elements": data_reader.read_table_from_file(file_name=_file),
346
+ }
347
+ for _file in file_path
348
+ ]
369
349
 
370
350
 
371
- def _get_array_layout_dict(
372
- db_config, model_version, site, telescope_list, layout_name, coordinate_system
373
- ):
351
+ def _get_array_layout_dict(model_version, site, telescope_list, layout_name, coordinate_system):
374
352
  """Return array layout dictionary for a given telescope list."""
375
353
  array_model = ArrayModel(
376
- db_config=db_config,
377
354
  model_version=model_version,
378
355
  site=site,
379
356
  array_elements=telescope_list,
@@ -388,7 +365,7 @@ def _get_array_layout_dict(
388
365
  }
389
366
 
390
367
 
391
- def get_array_elements_from_db_for_layouts(layouts, site, model_version, db_config):
368
+ def get_array_elements_from_db_for_layouts(layouts, site, model_version):
392
369
  """
393
370
  Get list of array elements from the database for given list of layout names.
394
371
 
@@ -408,17 +385,209 @@ def get_array_elements_from_db_for_layouts(layouts, site, model_version, db_conf
408
385
  Site name for the array layouts.
409
386
  model_version : str
410
387
  Model version for the array layouts.
411
- db_config : dict
412
- Database configuration dictionary.
413
388
 
414
389
  Returns
415
390
  -------
416
391
  dict
417
392
  Dictionary mapping layout names to telescope IDs.
418
393
  """
419
- site_model = SiteModel(site=site, model_version=model_version, db_config=db_config)
394
+ site_model = SiteModel(site=site, model_version=model_version)
420
395
  layout_names = site_model.get_list_of_array_layouts() if layouts == ["all"] else layouts
421
396
  layout_dict = {}
422
397
  for layout_name in layout_names:
423
398
  layout_dict[layout_name] = site_model.get_array_elements_for_layout(layout_name)
424
399
  return layout_dict
400
+
401
+
402
+ def read_layouts(args_dict):
403
+ """
404
+ Read array layouts from the database or parameter file.
405
+
406
+ Parameters
407
+ ----------
408
+ args_dict : dict
409
+ Dictionary with command line arguments.
410
+
411
+ Returns
412
+ -------
413
+ tuple
414
+ A tuple containing:
415
+ - list: List of array layouts.
416
+ - list or None: Background layout or None if not provided.
417
+ """
418
+ background_layout = None
419
+ if args_dict.get("array_layout_name_background"):
420
+ background_layout = get_array_layouts_from_db(
421
+ args_dict["array_layout_name_background"],
422
+ args_dict["site"],
423
+ args_dict["model_version"],
424
+ args_dict["coordinate_system"],
425
+ )["array_elements"]
426
+
427
+ if args_dict["array_layout_name"] is not None or args_dict["plot_all_layouts"]:
428
+ _logger.info("Plotting array from DB using layout array name(s).")
429
+ layouts = get_array_layouts_from_db(
430
+ args_dict["array_layout_name"],
431
+ args_dict["site"],
432
+ args_dict["model_version"],
433
+ args_dict["coordinate_system"],
434
+ )
435
+ if isinstance(layouts, list):
436
+ return layouts, background_layout
437
+ return [layouts], background_layout
438
+
439
+ if args_dict["array_layout_parameter_file"] is not None:
440
+ _logger.info("Plotting array from parameter file(s).")
441
+ return get_array_layouts_from_parameter_file(
442
+ args_dict["array_layout_parameter_file"],
443
+ args_dict["model_version"],
444
+ args_dict["coordinate_system"],
445
+ ), background_layout
446
+
447
+ if args_dict["array_layout_file"] is not None:
448
+ _logger.info("Plotting array from telescope table file(s).")
449
+ return get_array_layouts_from_file(args_dict["array_layout_file"]), background_layout
450
+ if args_dict["array_element_list"] is not None:
451
+ _logger.info("Plotting array from list of array elements.")
452
+ return get_array_layouts_using_telescope_lists_from_db(
453
+ [args_dict["array_element_list"]],
454
+ args_dict["site"],
455
+ args_dict["model_version"],
456
+ args_dict["coordinate_system"],
457
+ ), background_layout
458
+
459
+ return [], background_layout
460
+
461
+
462
+ def _get_array_name(array_name):
463
+ """
464
+ Return telescope size and number of telescopes from regular array name.
465
+
466
+ Finetuned to array names like "4MST", "1LST", etc.
467
+
468
+ Parameters
469
+ ----------
470
+ array_name : str
471
+ Name of the regular array (e.g. "4MST").
472
+
473
+ Returns
474
+ -------
475
+ tel_size : str
476
+ Telescope size (e.g. "MST").
477
+ n_tel : int
478
+ Number of telescopes (e.g. 4).
479
+ """
480
+ if len(array_name) < 2 or not array_name[0].isdigit():
481
+ raise ValueError(f"Invalid array_name: '{array_name}'")
482
+
483
+ return array_name[1:], int(array_name[0])
484
+
485
+
486
+ def create_regular_array(array_name, site, telescope_distance):
487
+ """
488
+ Create a regular array layout table.
489
+
490
+ Parameters
491
+ ----------
492
+ array_name : str
493
+ Name of the regular array (e.g. "4MST").
494
+ site : str
495
+ Site identifier.
496
+ telescope_distance : dict
497
+ Dictionary with telescope distances per telescope type.
498
+
499
+ Returns
500
+ -------
501
+ astropy.table.Table
502
+ Table with the regular array layout.
503
+ """
504
+ tel_name, pos_x, pos_y, pos_z = [], [], [], []
505
+ tel_size, n_tel = _get_array_name(array_name)
506
+ tel_size = array_name[1:4]
507
+
508
+ # Single telescope at the center
509
+ if n_tel == 1:
510
+ tel_name.append(names.generate_array_element_name_from_type_site_id(tel_size, site, "01"))
511
+ pos_x.append(0 * u.m)
512
+ pos_y.append(0 * u.m)
513
+ pos_z.append(0 * u.m)
514
+ # 4 telescopes in a regular square grid
515
+ elif n_tel == 4:
516
+ for i in range(1, 5):
517
+ tel_name.append(
518
+ names.generate_array_element_name_from_type_site_id(tel_size, site, f"0{i}")
519
+ )
520
+ pos_x.append(telescope_distance[tel_size] * (-1) ** (i // 2))
521
+ pos_y.append(telescope_distance[tel_size] * (-1) ** (i % 2))
522
+ pos_z.append(0 * u.m)
523
+ else:
524
+ raise ValueError(f"Unsupported number of telescopes: {n_tel}.")
525
+
526
+ table = QTable(meta={"array_name": array_name, "site": site})
527
+ table["telescope_name"] = tel_name
528
+ table["position_x"] = pos_x
529
+ table["position_y"] = pos_y
530
+ table["position_z"] = pos_z
531
+ table.sort("telescope_name")
532
+ _logger.info(f"Regular array layout table:\n{table}")
533
+
534
+ return table
535
+
536
+
537
+ def write_array_elements_from_file_to_repository(
538
+ coordinate_system, input_file, repository_path, parameter_version
539
+ ):
540
+ """
541
+ Read array elements from file and write their positions to model repository.
542
+
543
+ Writes one model parameter file per array elements.
544
+
545
+ Parameters
546
+ ----------
547
+ coordinate_system : str
548
+ Coordinate system of array element positions (utm or ground).
549
+ input_file : str or Path
550
+ Path to input file with array element positions.
551
+ repository_path : str or Path
552
+ Path to model repository.
553
+ parameter_version : str
554
+ Parameter version to use when writing to repository.
555
+ """
556
+ repository_path = Path(repository_path)
557
+
558
+ array_elements = Table.read(input_file)
559
+
560
+ if coordinate_system == "ground":
561
+ parameter_name = "array_element_position_ground"
562
+ x = array_elements["position_x"].quantity.to(u.m).value
563
+ y = array_elements["position_y"].quantity.to(u.m).value
564
+ alt = array_elements["position_z"].quantity.to(u.m).value
565
+ elif coordinate_system == "utm":
566
+ x = array_elements["utm_east"].quantity.to(u.m).value
567
+ y = array_elements["utm_north"].quantity.to(u.m).value
568
+ alt = array_elements["altitude"].quantity.to(u.m).value
569
+ parameter_name = "array_element_position_utm"
570
+ else:
571
+ raise ValueError(
572
+ f"Unsupported coordinate system: {coordinate_system}. Allowed are 'utm' and 'ground'."
573
+ )
574
+
575
+ for i, row in enumerate(array_elements):
576
+ instrument = (
577
+ row["telescope_name"]
578
+ if "telescope_name" in array_elements.colnames
579
+ else f"{row['asset_code']}-{row['sequence_number']}"
580
+ )
581
+ output_path = repository_path / f"{instrument}"
582
+ output_path.mkdir(parents=True, exist_ok=True)
583
+ _logger.info(f"Writing array element positions ({coordinate_system}) to {output_path}")
584
+
585
+ ModelDataWriter.dump_model_parameter(
586
+ parameter_name=parameter_name,
587
+ instrument=instrument,
588
+ value=f"{x[i]} {y[i]} {alt[i]}",
589
+ unit="m",
590
+ parameter_version=parameter_version,
591
+ output_path=repository_path / instrument,
592
+ output_file=f"{parameter_name}.json",
593
+ )
@@ -1,4 +1,4 @@
1
- """Definition of the ArrayModel class."""
1
+ """Array model represents an observatory consisting of site, telescopes, and further devices."""
2
2
 
3
3
  import logging
4
4
  from pathlib import Path
@@ -21,8 +21,6 @@ class ArrayModel:
21
21
 
22
22
  Parameters
23
23
  ----------
24
- db_config: dict
25
- Database configuration.
26
24
  model_version: str
27
25
  Model version.
28
26
  label: str, optional
@@ -36,28 +34,23 @@ class ArrayModel:
36
34
  the array element positions).
37
35
  calibration_device_types: List[str], optional
38
36
  List of calibration device types (e.g., 'flat_fielding') attached to each telescope.
39
- simtel_path: str, Path, optional
40
- Path to the sim_telarray installation directory.
41
37
  overwrite_model_parameters: str, optional
42
38
  File name to overwrite model parameters from DB with provided values.
43
39
  """
44
40
 
45
41
  def __init__(
46
42
  self,
47
- db_config,
48
43
  model_version,
49
44
  label=None,
50
45
  site=None,
51
46
  layout_name=None,
52
47
  array_elements=None,
53
48
  calibration_device_types=None,
54
- simtel_path=None,
55
49
  overwrite_model_parameters=None,
56
50
  ):
57
51
  """Initialize ArrayModel."""
58
52
  self._logger = logging.getLogger(__name__)
59
53
  self._logger.debug("Init ArrayModel")
60
- self.db_config = db_config
61
54
  self.model_version = model_version
62
55
  self.label = label
63
56
  self.layout_name = (
@@ -78,7 +71,6 @@ class ArrayModel:
78
71
  self._telescope_model_files_exported = False
79
72
  self._array_model_file_exported = False
80
73
  self._sim_telarray_seeds = None
81
- self.simtel_path = simtel_path
82
74
 
83
75
  def _initialize(self, site, array_elements_config, calibration_device_types):
84
76
  """
@@ -105,7 +97,6 @@ class ArrayModel:
105
97
  self._logger.debug(f"Getting site parameters from DB ({site})")
106
98
  site_model = SiteModel(
107
99
  site=names.validate_site_name(site),
108
- db_config=self.db_config,
109
100
  model_version=self.model_version,
110
101
  label=self.label,
111
102
  overwrite_model_parameters=self.overwrite_model_parameters,
@@ -250,7 +241,6 @@ class ArrayModel:
250
241
  site=site_model.site,
251
242
  telescope_name=element_name,
252
243
  model_version=self.model_version,
253
- db_config=self.db_config,
254
244
  label=self.label,
255
245
  overwrite_model_parameters=self.overwrite_model_parameters,
256
246
  )
@@ -282,7 +272,6 @@ class ArrayModel:
282
272
  calibration_models[device_name] = CalibrationModel(
283
273
  site=site_model.site,
284
274
  calibration_device_model_name=device_name,
285
- db_config=self.db_config,
286
275
  model_version=self.model_version,
287
276
  label=self.label,
288
277
  overwrite_model_parameters=self.overwrite_model_parameters,
@@ -322,7 +311,6 @@ class ArrayModel:
322
311
  layout_name=self.layout_name,
323
312
  model_version=self.model_version,
324
313
  label=self.label,
325
- simtel_path=self.simtel_path,
326
314
  )
327
315
  simtel_writer.write_array_config_file(
328
316
  config_file_path=self.config_file_path,
@@ -17,8 +17,6 @@ class CalibrationModel(ModelParameter):
17
17
  Site name (e.g., South or North).
18
18
  calibration_device_model_name: str
19
19
  Calibration device model name (ex. ILLS-01, ILLN-01, ...).
20
- db_config: dict
21
- Database configuration.
22
20
  model_version: str
23
21
  Model version.
24
22
  label: str, optional
@@ -31,7 +29,6 @@ class CalibrationModel(ModelParameter):
31
29
  self,
32
30
  site,
33
31
  calibration_device_model_name,
34
- db_config,
35
32
  model_version,
36
33
  label=None,
37
34
  overwrite_model_parameters=None,
@@ -41,7 +38,6 @@ class CalibrationModel(ModelParameter):
41
38
  site=site,
42
39
  array_element_name=calibration_device_model_name,
43
40
  collection="calibration_devices",
44
- db_config=db_config,
45
41
  model_version=model_version,
46
42
  label=label,
47
43
  overwrite_model_parameters=overwrite_model_parameters,
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/python3
2
+ """
3
+ Handling of legacy model parameters for backward compatibility.
4
+
5
+ Collects routines to convert legacy model parameters to more recent
6
+ formats. This is a fine-tuned process and requires to hard wire the
7
+ changes. All code related to legacy model parameters should go into
8
+ this module.
9
+
10
+ """
11
+
12
+ import logging
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ UPDATE_HANDLERS = {}
18
+
19
+
20
+ def register_update(name):
21
+ """Register update handler for legacy model parameter."""
22
+
23
+ def deco(func):
24
+ UPDATE_HANDLERS[name] = func
25
+ return func
26
+
27
+ return deco
28
+
29
+
30
+ def apply_legacy_updates_to_parameters(parameters, legacy_updates):
31
+ """Apply legacy updates to model parameters.
32
+
33
+ Modifies the parameters dictionary in-place.
34
+
35
+ Parameters
36
+ ----------
37
+ parameters: dict
38
+ Dictionary of model parameters (all parameters).
39
+ legacy_updates: dict
40
+ Dictionary of legacy updates to apply.
41
+ """
42
+ for par_name, legacy_data in legacy_updates.items():
43
+ if legacy_data is None or par_name not in parameters:
44
+ continue
45
+ for key in parameters[par_name].keys():
46
+ if key in legacy_data:
47
+ parameters[par_name][key] = legacy_data[key]
48
+ if legacy_data.get("remove_parameter", False):
49
+ parameters.pop(par_name)
50
+
51
+
52
+ def update_parameter(par_name, parameters, schema_version):
53
+ """Update legacy model parameters to recent formats.
54
+
55
+ Parameters
56
+ ----------
57
+ par_name: str
58
+ Model parameter name.
59
+ parameters: dict
60
+ Dictionary of model parameters (all parameters).
61
+ schema_version: str
62
+ Target schema version.
63
+
64
+ Returns
65
+ -------
66
+ dict
67
+ Updated model parameter.
68
+ """
69
+ handler = UPDATE_HANDLERS.get(par_name)
70
+ if handler is None:
71
+ raise ValueError(_get_unsupported_update_message(parameters[par_name], schema_version))
72
+ return handler(parameters, schema_version)
73
+
74
+
75
+ @register_update("dsum_threshold")
76
+ def _update_dsum_threshold(parameters, schema_version):
77
+ """Update legacy dsum_threshold parameter."""
78
+ para_data = parameters["dsum_threshold"]
79
+ if para_data["model_parameter_schema_version"] == "0.1.0" and schema_version == "0.2.0":
80
+ logger.info(
81
+ "Updating legacy model parameter dsum_threshold from schema version "
82
+ f"{para_data['model_parameter_schema_version']} to {schema_version}"
83
+ )
84
+ return {
85
+ para_data["parameter"]: {
86
+ "value": int(para_data["value"]),
87
+ "model_parameter_schema_version": schema_version,
88
+ }
89
+ }
90
+ raise ValueError(_get_unsupported_update_message(para_data, schema_version))
91
+
92
+
93
+ @register_update("corsika_starting_grammage")
94
+ def _update_corsika_starting_grammage(parameters, schema_version):
95
+ """Update legacy corsika_starting_grammage parameter (dummy function until model is updated)."""
96
+ logger.debug(f"No fix applied to corsika_starting_grammage to schema version {schema_version}")
97
+ return {
98
+ parameters["corsika_starting_grammage"]["parameter"]: None,
99
+ }
100
+
101
+
102
+ @register_update("flasher_pulse_shape")
103
+ def _update_flasher_pulse_shape(parameters, schema_version):
104
+ """Update legacy flasher_pulse_shape parameter."""
105
+ para_data = parameters["flasher_pulse_shape"]
106
+ if para_data["model_parameter_schema_version"] == "0.1.0" and schema_version == "0.2.0":
107
+ logger.info(
108
+ f"Updating legacy model parameter flasher_pulse_shape from schema version "
109
+ f"{para_data['model_parameter_schema_version']} to {schema_version}"
110
+ )
111
+ return {
112
+ para_data["parameter"]: {
113
+ "value": [
114
+ para_data["value"],
115
+ parameters.get("flasher_pulse_width", {}).get("value", 0.0),
116
+ parameters.get("flasher_pulse_exp_decay", {}).get("value", 0.0),
117
+ ],
118
+ "model_parameter_schema_version": schema_version,
119
+ "unit": [None, "ns", "ns"],
120
+ "type": ["string", "float64", "float64"],
121
+ },
122
+ "flasher_pulse_width": {"remove_parameter": True},
123
+ "flasher_pulse_exp_decay": {"remove_parameter": True},
124
+ }
125
+
126
+ raise ValueError(_get_unsupported_update_message(para_data, schema_version))
127
+
128
+
129
+ def _get_unsupported_update_message(para_data, schema_version):
130
+ """Get unsupported update message."""
131
+ return (
132
+ f"Unsupported update for legacy parameter {para_data['parameter']}: "
133
+ f"{para_data['model_parameter_schema_version']} to {schema_version}"
134
+ )