gammasimtools 0.23.0__py3-none-any.whl → 0.25.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/METADATA +1 -1
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/RECORD +89 -85
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/entry_points.txt +1 -0
- simtools/_version.py +2 -2
- simtools/application_control.py +54 -4
- simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -1
- simtools/applications/db_add_file_to_db.py +2 -2
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
- simtools/applications/db_add_value_from_json_to_db.py +2 -2
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +1 -1
- simtools/applications/db_generate_compound_indexes.py +1 -1
- simtools/applications/db_get_array_layouts_from_db.py +2 -2
- simtools/applications/db_get_file_from_db.py +1 -1
- simtools/applications/db_get_parameter_from_db.py +1 -1
- simtools/applications/db_inspect_databases.py +4 -2
- simtools/applications/db_upload_model_repository.py +1 -1
- simtools/applications/derive_ctao_array_layouts.py +1 -1
- simtools/applications/derive_psf_parameters.py +5 -0
- simtools/applications/derive_pulse_shape_parameters.py +195 -0
- simtools/applications/generate_array_config.py +1 -1
- simtools/applications/maintain_simulation_model_add_production.py +11 -21
- simtools/applications/plot_array_layout.py +63 -1
- simtools/applications/production_generate_grid.py +1 -1
- simtools/applications/simulate_flasher.py +3 -2
- simtools/applications/simulate_pedestals.py +1 -1
- simtools/applications/simulate_prod.py +8 -23
- simtools/applications/simulate_prod_htcondor_generator.py +7 -0
- simtools/applications/submit_array_layouts.py +7 -5
- simtools/applications/validate_camera_fov.py +1 -1
- simtools/applications/validate_cumulative_psf.py +2 -2
- simtools/applications/validate_file_using_schema.py +49 -123
- simtools/applications/validate_optics.py +1 -1
- simtools/configuration/commandline_parser.py +15 -15
- simtools/configuration/configurator.py +1 -1
- simtools/corsika/corsika_config.py +199 -91
- simtools/data_model/model_data_writer.py +15 -3
- simtools/data_model/schema.py +145 -36
- simtools/data_model/validate_data.py +82 -48
- simtools/db/db_handler.py +61 -294
- simtools/db/db_model_upload.py +3 -2
- simtools/db/mongo_db.py +626 -0
- simtools/dependencies.py +38 -17
- simtools/io/eventio_handler.py +128 -0
- simtools/job_execution/htcondor_script_generator.py +0 -2
- simtools/layout/array_layout.py +7 -7
- simtools/layout/array_layout_utils.py +4 -4
- simtools/model/array_model.py +72 -72
- simtools/model/calibration_model.py +12 -9
- simtools/model/model_parameter.py +196 -160
- simtools/model/model_repository.py +176 -39
- simtools/model/model_utils.py +3 -3
- simtools/model/site_model.py +59 -27
- simtools/model/telescope_model.py +21 -13
- simtools/ray_tracing/mirror_panel_psf.py +4 -4
- simtools/ray_tracing/psf_analysis.py +11 -8
- simtools/ray_tracing/psf_parameter_optimisation.py +823 -680
- simtools/reporting/docs_auto_report_generator.py +1 -1
- simtools/reporting/docs_read_parameters.py +72 -11
- simtools/runners/corsika_runner.py +12 -3
- simtools/runners/corsika_simtel_runner.py +6 -0
- simtools/runners/runner_services.py +17 -7
- simtools/runners/simtel_runner.py +12 -54
- simtools/schemas/model_parameters/flasher_pulse_exp_decay.schema.yml +2 -0
- simtools/schemas/model_parameters/flasher_pulse_shape.schema.yml +50 -0
- simtools/schemas/model_parameters/flasher_pulse_width.schema.yml +2 -0
- simtools/schemas/simulation_models_info.schema.yml +4 -1
- simtools/simtel/pulse_shapes.py +268 -0
- simtools/simtel/simtel_config_writer.py +179 -21
- simtools/simtel/simtel_io_event_writer.py +2 -2
- simtools/simtel/simulator_array.py +58 -12
- simtools/simtel/simulator_light_emission.py +45 -8
- simtools/simulator.py +361 -346
- simtools/testing/assertions.py +110 -10
- simtools/testing/configuration.py +1 -1
- simtools/testing/log_inspector.py +4 -1
- simtools/testing/sim_telarray_metadata.py +1 -1
- simtools/testing/validate_output.py +46 -15
- simtools/utils/names.py +2 -4
- simtools/utils/value_conversion.py +10 -5
- simtools/version.py +61 -0
- simtools/visualization/legend_handlers.py +14 -4
- simtools/visualization/plot_array_layout.py +229 -33
- simtools/visualization/plot_mirrors.py +837 -0
- simtools/visualization/plot_pixels.py +1 -1
- simtools/visualization/plot_psf.py +1 -1
- simtools/visualization/plot_tables.py +1 -1
- simtools/simtel/simtel_io_file_info.py +0 -62
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/licenses/LICENSE +0 -0
- {gammasimtools-0.23.0.dist-info → gammasimtools-0.25.0.dist-info}/top_level.txt +0 -0
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
|
|
70
|
-
return
|
|
71
|
-
|
|
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
|
-
|
|
130
|
-
|
|
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(
|
|
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
|
-
|
|
152
|
-
|
|
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
|
simtools/layout/array_layout.py
CHANGED
|
@@ -32,8 +32,8 @@ class ArrayLayout:
|
|
|
32
32
|
|
|
33
33
|
Parameters
|
|
34
34
|
----------
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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:
|
simtools/model/array_model.py
CHANGED
|
@@ -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
|
-
|
|
26
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
488
|
-
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
|
|
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
|
-
|
|
21
|
-
|
|
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
|
|
31
|
-
calibration_device_model_name
|
|
32
|
-
|
|
33
|
-
model_version
|
|
34
|
-
label
|
|
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
|
-
|
|
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__)
|