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
simtools/dependencies.py CHANGED
@@ -16,8 +16,8 @@ from pathlib import Path
16
16
 
17
17
  import yaml
18
18
 
19
- from simtools.db.db_handler import DatabaseHandler
20
19
  from simtools.io import ascii_handler
20
+ from simtools.version import __version__
21
21
 
22
22
  _logger = logging.getLogger(__name__)
23
23
 
@@ -49,6 +49,30 @@ def get_version_string(db_config=None, run_time=None):
49
49
  )
50
50
 
51
51
 
52
+ def get_software_version(software):
53
+ """
54
+ Return the version of the specified software package.
55
+
56
+ Parameters
57
+ ----------
58
+ software : str
59
+ Name of the software package.
60
+
61
+ Returns
62
+ -------
63
+ str
64
+ Version of the specified software package.
65
+ """
66
+ if software.lower() == "simtools":
67
+ return __version__
68
+
69
+ try:
70
+ version_call = f"get_{software.lower()}_version"
71
+ return globals()[version_call]()
72
+ except KeyError as exc:
73
+ raise ValueError(f"Unknown software: {software}") from exc
74
+
75
+
52
76
  def get_database_version_or_name(db_config, version=True):
53
77
  """
54
78
  Get the version or name of the simulation model data base used.
@@ -66,18 +90,17 @@ def get_database_version_or_name(db_config, version=True):
66
90
  Version or name of the simulation model data base used.
67
91
 
68
92
  """
69
- if db_config is None:
70
- return None
71
- db = DatabaseHandler(db_config)
72
- return db.mongo_db_config.get(
73
- "db_simulation_model_version" if version else "db_simulation_model"
74
- )
93
+ if version:
94
+ return db_config and db_config.get("db_simulation_model_version")
95
+ return db_config and db_config.get("db_simulation_model")
75
96
 
76
97
 
77
- def get_sim_telarray_version(run_time):
98
+ def get_sim_telarray_version(run_time=None):
78
99
  """
79
100
  Get the version of the sim_telarray package using 'sim_telarray --version'.
80
101
 
102
+ Version strings for sim_telarray are of the form "2024.271.0" (year.day_of_year.patch).
103
+
81
104
  Parameters
82
105
  ----------
83
106
  run_time : list, optional
@@ -116,6 +139,8 @@ def get_corsika_version(run_time=None):
116
139
  """
117
140
  Get the version of the CORSIKA package.
118
141
 
142
+ Version strings for CORSIKA are of the form "7.7550" (major.minor with 4-digit minor).
143
+
119
144
  Parameters
120
145
  ----------
121
146
  run_time : list, optional
@@ -126,12 +151,11 @@ def get_corsika_version(run_time=None):
126
151
  str
127
152
  Version of the CORSIKA package.
128
153
  """
129
- version = None
130
- sim_telarray_path = os.getenv("SIMTOOLS_SIMTEL_PATH")
131
- if sim_telarray_path is None:
154
+ corsika_path = os.getenv("SIMTOOLS_SIMTEL_PATH")
155
+ if corsika_path is None:
132
156
  _logger.warning("Environment variable SIMTOOLS_SIMTEL_PATH is not set.")
133
157
  return None
134
- corsika_command = Path(sim_telarray_path) / "corsika-run" / "corsika"
158
+ corsika_command = Path(corsika_path) / "corsika-run" / "corsika"
135
159
 
136
160
  if run_time is None:
137
161
  command = [str(corsika_command)]
@@ -148,11 +172,8 @@ def get_corsika_version(run_time=None):
148
172
  text=True,
149
173
  )
150
174
 
151
- # Capture output until it waits for input
152
- while True:
153
- line = process.stdout.readline()
154
- if not line:
155
- break
175
+ version = None
176
+ for line in process.stdout:
156
177
  # Extract the version from the line "NUMBER OF VERSION : 7.7550"
157
178
  if "NUMBER OF VERSION" in line:
158
179
  version = line.split(":")[1].strip()
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/python3
2
+ """Read file info and run headers from eventio (CORSIKA IACT, sim_telarray) files."""
3
+
4
+ import warnings
5
+
6
+ from eventio import EventIOFile, iact
7
+ from eventio.simtel import MCRunHeader, MCShower, RunHeader
8
+
9
+ # Suppress all UserWarnings from corsikaio - no CORSIKA versions <7.7 are supported anyway
10
+ warnings.filterwarnings("ignore", category=UserWarning, module=r"corsikaio\.subblocks\..*")
11
+
12
+
13
+ def get_corsika_run_number(file):
14
+ """
15
+ Return the CORSIKA run number from an eventio (CORSIKA IACT or sim_telarray) file.
16
+
17
+ Parameters
18
+ ----------
19
+ file: str
20
+ Path to the eventio file.
21
+
22
+ Returns
23
+ -------
24
+ int, None
25
+ CORSIKA run number. Returns None if not found.
26
+ """
27
+ run_header = get_combined_corsika_run_header(file)
28
+ if run_header and "run" in run_header:
29
+ return run_header["run"]
30
+ run_header, _ = get_corsika_run_and_event_headers(file)
31
+ try:
32
+ return int(run_header["run_number"])
33
+ except (TypeError, KeyError, ValueError):
34
+ return None
35
+
36
+
37
+ def get_combined_corsika_run_header(sim_telarray_file):
38
+ """
39
+ Return the CORSIKA run header information from an sim_telarray file.
40
+
41
+ Reads both RunHeader and MCRunHeader object from file and returns a merged dictionary.
42
+ Adds primary id from the first event.
43
+
44
+ Parameters
45
+ ----------
46
+ sim_telarray_file: str
47
+ Path to the sim_telarray file.
48
+
49
+ Returns
50
+ -------
51
+ dict, None
52
+ CORSIKA run header. Returns None if not found.
53
+ """
54
+ run_header = mc_run_header = None
55
+ primary_id = None
56
+
57
+ with EventIOFile(sim_telarray_file) as f:
58
+ for o in f:
59
+ if isinstance(o, RunHeader) and run_header is None:
60
+ run_header = o.parse()
61
+ elif isinstance(o, MCRunHeader) and mc_run_header is None:
62
+ mc_run_header = o.parse()
63
+ elif isinstance(o, MCShower): # get primary_id from first MCShower
64
+ primary_id = o.parse().get("primary_id")
65
+ if run_header and mc_run_header and primary_id is not None:
66
+ break
67
+
68
+ run_header = run_header or {}
69
+ mc_run_header = mc_run_header or {}
70
+ if primary_id is not None:
71
+ mc_run_header["primary_id"] = primary_id
72
+ return run_header | mc_run_header or None
73
+
74
+
75
+ def get_corsika_run_and_event_headers(corsika_iact_file):
76
+ """
77
+ Return the CORSIKA run and event headers from a CORSIKA IACT eventio file.
78
+
79
+ Parameters
80
+ ----------
81
+ corsika_iact_file: str, Path
82
+ Path to the CORSIKA IACT eventio file.
83
+
84
+ Returns
85
+ -------
86
+ tuple
87
+ CORSIKA run header and event header as dictionaries.
88
+ """
89
+ run_header = event_header = None
90
+
91
+ with EventIOFile(corsika_iact_file) as f:
92
+ for o in f:
93
+ if isinstance(o, iact.RunHeader) and run_header is None:
94
+ run_header = o.parse()
95
+ elif isinstance(o, iact.EventHeader) and event_header is None:
96
+ event_header = o.parse()
97
+ if run_header and event_header:
98
+ break
99
+
100
+ return run_header, event_header
101
+
102
+
103
+ def get_simulated_events(event_io_file):
104
+ """
105
+ Return the number of shower and MC events from a simulation (eventio) file.
106
+
107
+ For a sim_telarray file, the number of simulated showers and MC events is
108
+ determined by counting the number of MCShower (type id 2020) and MCEvent
109
+ objects (type id 2021). For a CORSIKA IACT file, the number of simulated
110
+ showers is determined by counting the number of IACTShower (type id 1202).
111
+
112
+ Parameters
113
+ ----------
114
+ event_io_file: str, Path
115
+ Path to the eventio file.
116
+
117
+ Returns
118
+ -------
119
+ tuple
120
+ Number of showers and number of MC events (MC events for sim_telarray files only).
121
+ """
122
+ counts = {1202: 0, 2020: 0, 2021: 0}
123
+ with EventIOFile(event_io_file) as f:
124
+ for o in f:
125
+ t = o.header.type
126
+ if t in counts:
127
+ counts[t] += 1
128
+ return counts[2020] if counts[2020] else counts[1202], counts[2021]
@@ -136,8 +136,6 @@ simtools-simulate-prod \\
136
136
  --view_cone {view_cone_string} \\
137
137
  --run_number $((process_id)) \\
138
138
  --run_number_offset {run_number_offset} \\
139
- --number_of_runs 1 \\
140
- --data_directory /tmp/simtools-data \\
141
139
  --output_path /tmp/simtools-output \\
142
140
  --log_level {args_dict["log_level"]} \\
143
141
  --pack_for_grid_register simtools-output
@@ -32,8 +32,8 @@ class ArrayLayout:
32
32
 
33
33
  Parameters
34
34
  ----------
35
- mongo_db_config: dict
36
- MongoDB configuration.
35
+ db_config: dict
36
+ Database configuration.
37
37
  site: str
38
38
  Site name or location (e.g., North/South or LaPalma/Paranal)
39
39
  model_version: str
@@ -52,7 +52,7 @@ class ArrayLayout:
52
52
 
53
53
  def __init__(
54
54
  self,
55
- mongo_db_config,
55
+ db_config,
56
56
  site,
57
57
  model_version,
58
58
  label=None,
@@ -67,7 +67,7 @@ class ArrayLayout:
67
67
  self.model_version = model_version
68
68
  self.label = label
69
69
  self.name = name
70
- self.mongo_db_config = mongo_db_config
70
+ self.db_config = db_config
71
71
  self.site = None if site is None else names.validate_site_name(site)
72
72
  self.site_model = None
73
73
  self.io_handler = io_handler.IOHandler()
@@ -95,13 +95,13 @@ class ArrayLayout:
95
95
  def _initialize_site_parameters_from_db(self):
96
96
  """Initialize site parameters required for transformations using the database."""
97
97
  self._logger.debug("Initialize parameters from DB")
98
- if self.mongo_db_config is None:
98
+ if self.db_config is None:
99
99
  raise ValueError("No database configuration provided")
100
100
 
101
101
  self.site_model = SiteModel(
102
102
  site=self.site,
103
103
  model_version=self.model_version,
104
- mongo_db_config=self.mongo_db_config,
104
+ db_config=self.db_config,
105
105
  )
106
106
  self._corsika_observation_level = self.site_model.get_corsika_site_parameters().get(
107
107
  "corsika_observation_level", None
@@ -419,7 +419,7 @@ class ArrayLayout:
419
419
  site=self.site,
420
420
  telescope_name=telescope_name,
421
421
  model_version=self.model_version,
422
- mongo_db_config=self.mongo_db_config,
422
+ db_config=self.db_config,
423
423
  label=self.label,
424
424
  )
425
425
 
@@ -162,7 +162,7 @@ def write_array_layouts(array_layouts, args_dict, db_config):
162
162
  ModelDataWriter.dump_model_parameter(
163
163
  parameter_name="array_layouts",
164
164
  value=array_layouts["value"],
165
- instrument=site,
165
+ instrument=f"OBS-{site}",
166
166
  parameter_version=args_dict.get("updated_parameter_version"),
167
167
  output_file=output_file,
168
168
  db_config=db_config,
@@ -280,7 +280,7 @@ def get_array_layouts_from_db(
280
280
  if layout_name:
281
281
  layout_names = gen.ensure_iterable(layout_name)
282
282
  else:
283
- site_model = SiteModel(site=site, model_version=model_version, mongo_db_config=db_config)
283
+ site_model = SiteModel(site=site, model_version=model_version, db_config=db_config)
284
284
  layout_names = site_model.get_list_of_array_layouts()
285
285
 
286
286
  layouts = []
@@ -373,7 +373,7 @@ def _get_array_layout_dict(
373
373
  ):
374
374
  """Return array layout dictionary for a given telescope list."""
375
375
  array_model = ArrayModel(
376
- mongo_db_config=db_config,
376
+ db_config=db_config,
377
377
  model_version=model_version,
378
378
  site=site,
379
379
  array_elements=telescope_list,
@@ -416,7 +416,7 @@ def get_array_elements_from_db_for_layouts(layouts, site, model_version, db_conf
416
416
  dict
417
417
  Dictionary mapping layout names to telescope IDs.
418
418
  """
419
- site_model = SiteModel(site=site, model_version=model_version, mongo_db_config=db_config)
419
+ site_model = SiteModel(site=site, model_version=model_version, db_config=db_config)
420
420
  layout_names = site_model.get_list_of_array_layouts() if layouts == ["all"] else layouts
421
421
  layout_dict = {}
422
422
  for layout_name in layout_names:
@@ -7,7 +7,6 @@ import astropy.units as u
7
7
  from astropy.table import QTable
8
8
 
9
9
  from simtools.data_model import data_reader, schema
10
- from simtools.db import db_handler
11
10
  from simtools.io import io_handler
12
11
  from simtools.model.calibration_model import CalibrationModel
13
12
  from simtools.model.site_model import SiteModel
@@ -22,8 +21,8 @@ class ArrayModel:
22
21
 
23
22
  Parameters
24
23
  ----------
25
- mongo_db_config: dict
26
- MongoDB configuration.
24
+ db_config: dict
25
+ Database configuration.
27
26
  model_version: str
28
27
  Model version.
29
28
  label: str, optional
@@ -35,30 +34,30 @@ class ArrayModel:
35
34
  array_elements: Union[str, Path, List[str]], optional
36
35
  Array element definitions (list of array element or path to file with
37
36
  the array element positions).
38
- sim_telarray_seeds : dict, optional
39
- Dictionary with configuration for sim_telarray random instrument setup.
40
- simtel_path: str, Path, optional
41
- Path to the sim_telarray installation directory.
42
37
  calibration_device_types: List[str], optional
43
38
  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
+ overwrite_model_parameters: str, optional
42
+ File name to overwrite model parameters from DB with provided values.
44
43
  """
45
44
 
46
45
  def __init__(
47
46
  self,
48
- mongo_db_config,
47
+ db_config,
49
48
  model_version,
50
49
  label=None,
51
50
  site=None,
52
51
  layout_name=None,
53
52
  array_elements=None,
54
- sim_telarray_seeds=None,
55
- simtel_path=None,
56
53
  calibration_device_types=None,
54
+ simtel_path=None,
55
+ overwrite_model_parameters=None,
57
56
  ):
58
57
  """Initialize ArrayModel."""
59
58
  self._logger = logging.getLogger(__name__)
60
59
  self._logger.debug("Init ArrayModel")
61
- self.mongo_db_config = mongo_db_config
60
+ self.db_config = db_config
62
61
  self.model_version = model_version
63
62
  self.label = label
64
63
  self.layout_name = (
@@ -69,7 +68,8 @@ class ArrayModel:
69
68
  self._config_file_path = None
70
69
  self._config_file_directory = None
71
70
  self.io_handler = io_handler.IOHandler()
72
- self.db = db_handler.DatabaseHandler(mongo_db_config=mongo_db_config)
71
+
72
+ self.overwrite_model_parameters = overwrite_model_parameters
73
73
 
74
74
  self.array_elements, self.site_model, self.telescope_models, self.calibration_models = (
75
75
  self._initialize(site, array_elements, calibration_device_types)
@@ -77,7 +77,7 @@ class ArrayModel:
77
77
 
78
78
  self._telescope_model_files_exported = False
79
79
  self._array_model_file_exported = False
80
- self.sim_telarray_seeds = sim_telarray_seeds
80
+ self._sim_telarray_seeds = None
81
81
  self.simtel_path = simtel_path
82
82
 
83
83
  def _initialize(self, site, array_elements_config, calibration_device_types):
@@ -105,9 +105,10 @@ class ArrayModel:
105
105
  self._logger.debug(f"Getting site parameters from DB ({site})")
106
106
  site_model = SiteModel(
107
107
  site=names.validate_site_name(site),
108
- mongo_db_config=self.mongo_db_config,
108
+ db_config=self.db_config,
109
109
  model_version=self.model_version,
110
110
  label=self.label,
111
+ overwrite_model_parameters=self.overwrite_model_parameters,
111
112
  )
112
113
 
113
114
  # Case 1: array_elements is a file name
@@ -117,7 +118,7 @@ class ArrayModel:
117
118
  )
118
119
  # Case 2: array elements is a list of elements
119
120
  elif isinstance(array_elements_config, list):
120
- array_elements = self._get_array_elements_from_list(array_elements_config)
121
+ array_elements = self._get_array_elements_from_list(array_elements_config, site_model)
121
122
  # Case 3: array elements defined in DB by array layout name
122
123
  elif self.layout_name is not None:
123
124
  array_elements = self._get_array_elements_from_list(
@@ -135,6 +136,41 @@ class ArrayModel:
135
136
 
136
137
  return array_elements, site_model, telescope_models, calibration_models
137
138
 
139
+ @property
140
+ def sim_telarray_seeds(self):
141
+ """
142
+ Return sim_telarray seeds.
143
+
144
+ Returns
145
+ -------
146
+ dict
147
+ Dictionary with sim_telarray seeds.
148
+ """
149
+ return self._sim_telarray_seeds
150
+
151
+ @sim_telarray_seeds.setter
152
+ def sim_telarray_seeds(self, value):
153
+ """
154
+ Set sim_telarray seeds.
155
+
156
+ Parameters
157
+ ----------
158
+ value: dict
159
+ Dictionary with sim_telarray seeds.
160
+ """
161
+ if isinstance(value, dict):
162
+ required_keys = {
163
+ "seed",
164
+ "random_instrument_instances",
165
+ "seed_file_name",
166
+ }
167
+ if not required_keys.issubset(value):
168
+ raise ValueError(
169
+ "sim_telarray_seeds dictionary must contain the following keys: "
170
+ f"{required_keys}"
171
+ )
172
+ self._sim_telarray_seeds = value
173
+
138
174
  @property
139
175
  def config_file_path(self):
140
176
  """
@@ -149,7 +185,6 @@ class ArrayModel:
149
185
  config_file_name = names.simtel_config_file_name(
150
186
  array_name=self.layout_name,
151
187
  site=self.site_model.site,
152
- model_version=self.model_version,
153
188
  label=self.label,
154
189
  )
155
190
  self._config_file_path = self.get_config_directory().joinpath(config_file_name)
@@ -168,7 +203,7 @@ class ArrayModel:
168
203
  return len(self.telescope_models)
169
204
 
170
205
  @property
171
- def site(self) -> str:
206
+ def site(self):
172
207
  """
173
208
  Return site.
174
209
 
@@ -179,34 +214,6 @@ class ArrayModel:
179
214
  """
180
215
  return self.site_model.site
181
216
 
182
- @property
183
- def model_version(self):
184
- """Model version."""
185
- return self._model_version
186
-
187
- @model_version.setter
188
- def model_version(self, model_version):
189
- """
190
- Set model version.
191
-
192
- Parameters
193
- ----------
194
- _model_version: str or list
195
- Model version (e.g., "6.0.0").
196
- If a list is passed, it must contain exactly one element,
197
- and only that element will be used.
198
-
199
- Raises
200
- ------
201
- ValueError
202
- If more than one model version is passed.
203
- """
204
- if isinstance(model_version, list):
205
- raise ValueError(
206
- f"Only one model version can be passed to {self.__class__.__name__}, not a list."
207
- )
208
- self._model_version = model_version
209
-
210
217
  def _build_telescope_models(self, site_model, array_elements, calibration_device_types):
211
218
  """
212
219
  Build telescope models for all telescopes of this array.
@@ -243,8 +250,9 @@ class ArrayModel:
243
250
  site=site_model.site,
244
251
  telescope_name=element_name,
245
252
  model_version=self.model_version,
246
- mongo_db_config=self.mongo_db_config,
253
+ db_config=self.db_config,
247
254
  label=self.label,
255
+ overwrite_model_parameters=self.overwrite_model_parameters,
248
256
  )
249
257
  calibration_models[element_name] = self._build_calibration_models(
250
258
  telescope_models[element_name],
@@ -274,9 +282,10 @@ class ArrayModel:
274
282
  calibration_models[device_name] = CalibrationModel(
275
283
  site=site_model.site,
276
284
  calibration_device_model_name=device_name,
277
- mongo_db_config=self.mongo_db_config,
285
+ db_config=self.db_config,
278
286
  model_version=self.model_version,
279
287
  label=self.label,
288
+ overwrite_model_parameters=self.overwrite_model_parameters,
280
289
  )
281
290
  return calibration_models
282
291
 
@@ -289,9 +298,7 @@ class ArrayModel:
289
298
  """Export sim_telarray configuration files for all telescopes into the model directory."""
290
299
  exported_models = []
291
300
  for tel_model in self.telescope_models.values():
292
- name = tel_model.name + (
293
- "_" + tel_model.extra_label if tel_model.extra_label != "" else ""
294
- )
301
+ name = tel_model.name
295
302
  if name not in exported_models:
296
303
  self._logger.debug(f"Exporting configuration file for telescope {name}")
297
304
  tel_model.write_sim_telarray_config_file(
@@ -336,7 +343,7 @@ class ArrayModel:
336
343
  if not self._array_model_file_exported:
337
344
  self.export_sim_telarray_config_file()
338
345
 
339
- def get_config_directory(self) -> Path:
346
+ def get_config_directory(self):
340
347
  """
341
348
  Get the path of the array config directory for sim_telarray.
342
349
 
@@ -370,9 +377,7 @@ class ArrayModel:
370
377
  self._logger.info(f"Packed model files into {archive_name}")
371
378
  return archive_name
372
379
 
373
- def _load_array_element_positions_from_file(
374
- self, array_elements_file: str | Path, site: str
375
- ) -> dict:
380
+ def _load_array_element_positions_from_file(self, array_elements_file, site):
376
381
  """
377
382
  Load array element (e.g. telescope) positions from a file into a dict.
378
383
 
@@ -400,14 +405,8 @@ class ArrayModel:
400
405
  }
401
406
 
402
407
  def _get_telescope_position_parameter(
403
- self,
404
- telescope_name: str,
405
- site: str,
406
- x: u.Quantity,
407
- y: u.Quantity,
408
- z: u.Quantity,
409
- parameter_version: str | None = None,
410
- ) -> dict:
408
+ self, telescope_name, site, x, y, z, parameter_version=None
409
+ ):
411
410
  """
412
411
  Return dictionary with telescope position parameters (following DB model database format).
413
412
 
@@ -444,7 +443,7 @@ class ArrayModel:
444
443
  "model_parameter_schema_version": "0.1.0",
445
444
  }
446
445
 
447
- def _get_array_elements_from_list(self, array_elements_list: list[str]) -> dict:
446
+ def _get_array_elements_from_list(self, array_elements_list, site_model=None):
448
447
  """
449
448
  Return dictionary with array elements from a list of telescope names.
450
449
 
@@ -456,6 +455,8 @@ class ArrayModel:
456
455
  ----------
457
456
  array_elements_list: list
458
457
  List of telescope names.
458
+ site_model: SiteModel
459
+ Site model.
459
460
 
460
461
  Returns
461
462
  -------
@@ -467,31 +468,30 @@ class ArrayModel:
467
468
  try:
468
469
  array_elements_dict[names.validate_array_element_name(name)] = None
469
470
  except ValueError:
470
- array_elements_dict.update(self._get_all_array_elements_of_type(name))
471
+ array_elements_dict.update(self._get_all_array_elements_of_type(name, site_model))
471
472
  return array_elements_dict
472
473
 
473
- def _get_all_array_elements_of_type(self, array_element_type: str) -> dict:
474
+ def _get_all_array_elements_of_type(self, array_element_type, site_model):
474
475
  """
475
- Return all array elements of a specific type using the database.
476
+ Return all array elements of a specific type.
476
477
 
477
478
  Parameters
478
479
  ----------
479
480
  array_element_type : str
480
481
  Type of the array element (e.g. LSTN, MSTS)
482
+ site_model: SiteModel
483
+ Site model.
481
484
 
482
485
  Returns
483
486
  -------
484
487
  dict
485
488
  Dict with array elements.
486
489
  """
487
- all_elements = self.db.get_array_elements_of_type(
488
- array_element_type=array_element_type,
489
- model_version=self.model_version,
490
- collection="telescopes",
490
+ return self._get_array_elements_from_list(
491
+ site_model.get_array_elements_of_type(array_element_type)
491
492
  )
492
- return self._get_array_elements_from_list(all_elements)
493
493
 
494
- def export_array_elements_as_table(self, coordinate_system: str = "ground") -> QTable:
494
+ def export_array_elements_as_table(self, coordinate_system="ground"):
495
495
  """
496
496
  Export array elements positions to astropy table.
497
497
 
@@ -17,31 +17,34 @@ 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
- mongo_db_config: dict
21
- MongoDB configuration.
20
+ db_config: dict
21
+ Database configuration.
22
22
  model_version: str
23
23
  Model version.
24
24
  label: str, optional
25
25
  Instance label. Important for output file naming.
26
+ overwrite_model_parameters: str, optional
27
+ File name to overwrite model parameters from DB with provided values.
26
28
  """
27
29
 
28
30
  def __init__(
29
31
  self,
30
- site: str,
31
- calibration_device_model_name: str,
32
- mongo_db_config: dict,
33
- model_version: str,
34
- label: str | None = None,
32
+ site,
33
+ calibration_device_model_name,
34
+ db_config,
35
+ model_version,
36
+ label=None,
37
+ overwrite_model_parameters=None,
35
38
  ):
36
39
  """Initialize CalibrationModel."""
37
40
  super().__init__(
38
41
  site=site,
39
42
  array_element_name=calibration_device_model_name,
40
43
  collection="calibration_devices",
41
- mongo_db_config=mongo_db_config,
44
+ db_config=db_config,
42
45
  model_version=model_version,
43
- db=None,
44
46
  label=label,
47
+ overwrite_model_parameters=overwrite_model_parameters,
45
48
  )
46
49
 
47
50
  self._logger = logging.getLogger(__name__)