gammasimtools 0.8.2__py3-none-any.whl → 0.10.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.8.2.dist-info → gammasimtools-0.10.0.dist-info}/METADATA +4 -4
- {gammasimtools-0.8.2.dist-info → gammasimtools-0.10.0.dist-info}/RECORD +119 -105
- {gammasimtools-0.8.2.dist-info → gammasimtools-0.10.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.8.2.dist-info → gammasimtools-0.10.0.dist-info}/entry_points.txt +4 -1
- simtools/_version.py +2 -2
- simtools/applications/calculate_trigger_rate.py +15 -38
- simtools/applications/convert_all_model_parameters_from_simtel.py +9 -28
- simtools/applications/convert_geo_coordinates_of_array_elements.py +54 -53
- simtools/applications/convert_model_parameter_from_simtel.py +2 -2
- simtools/applications/db_add_file_to_db.py +1 -2
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +110 -0
- simtools/applications/db_add_value_from_json_to_db.py +2 -11
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +6 -6
- simtools/applications/db_get_array_layouts_from_db.py +3 -1
- simtools/applications/db_get_file_from_db.py +11 -12
- simtools/applications/db_get_parameter_from_db.py +44 -32
- simtools/applications/derive_mirror_rnda.py +10 -1
- simtools/applications/derive_photon_electron_spectrum.py +99 -0
- simtools/applications/derive_psf_parameters.py +1 -1
- simtools/applications/generate_array_config.py +18 -22
- simtools/applications/generate_regular_arrays.py +24 -21
- simtools/applications/generate_simtel_array_histograms.py +11 -48
- simtools/applications/plot_array_layout.py +3 -1
- simtools/applications/plot_tabular_data.py +84 -0
- simtools/applications/production_generate_simulation_config.py +25 -7
- simtools/applications/production_scale_events.py +3 -4
- simtools/applications/simulate_light_emission.py +2 -2
- simtools/applications/simulate_prod.py +25 -60
- simtools/applications/simulate_prod_htcondor_generator.py +95 -0
- simtools/applications/submit_data_from_external.py +12 -4
- simtools/applications/submit_model_parameter_from_external.py +8 -6
- simtools/applications/validate_camera_efficiency.py +3 -3
- simtools/applications/validate_camera_fov.py +3 -7
- simtools/applications/validate_cumulative_psf.py +3 -7
- simtools/applications/validate_file_using_schema.py +38 -24
- simtools/applications/validate_optics.py +3 -4
- simtools/{camera_efficiency.py → camera/camera_efficiency.py} +1 -4
- simtools/camera/single_photon_electron_spectrum.py +168 -0
- simtools/configuration/commandline_parser.py +14 -13
- simtools/configuration/configurator.py +6 -19
- simtools/constants.py +10 -3
- simtools/corsika/corsika_config.py +8 -7
- simtools/corsika/corsika_histograms.py +1 -1
- simtools/data_model/data_reader.py +0 -3
- simtools/data_model/metadata_collector.py +21 -4
- simtools/data_model/metadata_model.py +8 -111
- simtools/data_model/model_data_writer.py +18 -64
- simtools/data_model/schema.py +213 -0
- simtools/data_model/validate_data.py +73 -51
- simtools/db/db_handler.py +395 -790
- simtools/db/db_model_upload.py +139 -0
- simtools/io_operations/hdf5_handler.py +54 -24
- simtools/io_operations/legacy_data_handler.py +61 -0
- simtools/job_execution/htcondor_script_generator.py +133 -0
- simtools/job_execution/job_manager.py +77 -50
- simtools/layout/array_layout.py +33 -28
- simtools/model/array_model.py +13 -7
- simtools/model/camera.py +4 -2
- simtools/model/model_parameter.py +61 -63
- simtools/model/site_model.py +3 -3
- simtools/production_configuration/calculate_statistical_errors_grid_point.py +119 -144
- simtools/production_configuration/event_scaler.py +7 -17
- simtools/production_configuration/generate_simulation_config.py +5 -32
- simtools/production_configuration/interpolation_handler.py +8 -11
- simtools/ray_tracing/mirror_panel_psf.py +47 -27
- simtools/runners/corsika_runner.py +14 -3
- simtools/runners/corsika_simtel_runner.py +3 -1
- simtools/runners/runner_services.py +3 -3
- simtools/runners/simtel_runner.py +27 -8
- simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +39 -0
- simtools/schemas/input/single_pe_spectrum.schema.yml +38 -0
- simtools/schemas/integration_tests_config.metaschema.yml +23 -3
- simtools/schemas/model_parameter.metaschema.yml +95 -2
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +2 -0
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +1 -1
- simtools/schemas/model_parameters/array_window.schema.yml +37 -0
- simtools/schemas/model_parameters/asum_clipping.schema.yml +0 -4
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_offset.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +0 -2
- simtools/schemas/model_parameters/effective_focal_length.schema.yml +31 -1
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_noise.schema.yml +3 -3
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +33 -0
- simtools/schemas/model_parameters/laser_photons.schema.yml +2 -2
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/production_configuration_metrics.schema.yml +68 -0
- simtools/schemas/production_tables.schema.yml +41 -0
- simtools/simtel/simtel_config_writer.py +5 -6
- simtools/simtel/simtel_io_histogram.py +32 -67
- simtools/simtel/simtel_io_histograms.py +15 -30
- simtools/simtel/simtel_table_reader.py +410 -0
- simtools/simtel/simulator_array.py +2 -1
- simtools/simtel/simulator_camera_efficiency.py +11 -4
- simtools/simtel/simulator_light_emission.py +5 -3
- simtools/simtel/simulator_ray_tracing.py +2 -2
- simtools/simulator.py +80 -33
- simtools/testing/configuration.py +12 -8
- simtools/testing/helpers.py +9 -16
- simtools/testing/validate_output.py +152 -68
- simtools/utils/general.py +149 -12
- simtools/utils/names.py +25 -21
- simtools/utils/value_conversion.py +9 -1
- simtools/visualization/plot_tables.py +106 -0
- simtools/visualization/visualize.py +43 -5
- simtools/applications/db_add_model_parameters_from_repository_to_db.py +0 -184
- simtools/db/db_array_elements.py +0 -130
- simtools/db/db_from_repo_handler.py +0 -106
- {gammasimtools-0.8.2.dist-info → gammasimtools-0.10.0.dist-info}/LICENSE +0 -0
- {gammasimtools-0.8.2.dist-info → gammasimtools-0.10.0.dist-info}/top_level.txt +0 -0
simtools/db/db_handler.py
CHANGED
|
@@ -6,12 +6,12 @@ from pathlib import Path
|
|
|
6
6
|
from threading import Lock
|
|
7
7
|
|
|
8
8
|
import gridfs
|
|
9
|
+
import jsonschema
|
|
9
10
|
from bson.objectid import ObjectId
|
|
10
11
|
from packaging.version import Version
|
|
11
|
-
from pymongo import
|
|
12
|
-
from pymongo.errors import BulkWriteError
|
|
12
|
+
from pymongo import MongoClient
|
|
13
13
|
|
|
14
|
-
from simtools.
|
|
14
|
+
from simtools.data_model import validate_data
|
|
15
15
|
from simtools.io_operations import io_handler
|
|
16
16
|
from simtools.utils import names, value_conversion
|
|
17
17
|
|
|
@@ -24,6 +24,35 @@ logging.getLogger("pymongo").setLevel(logging.WARNING)
|
|
|
24
24
|
# The above comment is because pylint does not know that DatabaseHandler.db_client is subscriptable
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
jsonschema_db_dict = {
|
|
28
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema#",
|
|
29
|
+
"type": "object",
|
|
30
|
+
"description": "MongoDB configuration",
|
|
31
|
+
"properties": {
|
|
32
|
+
"db_server": {"type": "string", "description": "DB server address"},
|
|
33
|
+
"db_api_port": {
|
|
34
|
+
"type": "integer",
|
|
35
|
+
"minimum": 1,
|
|
36
|
+
"maximum": 65535,
|
|
37
|
+
"default": 27017,
|
|
38
|
+
"description": "Port to use",
|
|
39
|
+
},
|
|
40
|
+
"db_api_user": {"type": "string", "description": "API username"},
|
|
41
|
+
"db_api_pw": {"type": "string", "description": "Password for the API user"},
|
|
42
|
+
"db_api_authentication_database": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"default": "admin",
|
|
45
|
+
"description": "DB with user info (optional)",
|
|
46
|
+
},
|
|
47
|
+
"db_simulation_model": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"description": "Name of simulation model database",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
"required": ["db_server", "db_api_port", "db_api_user", "db_api_pw", "db_simulation_model"],
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
27
56
|
class DatabaseHandler:
|
|
28
57
|
"""
|
|
29
58
|
DatabaseHandler provides the interface to the DB.
|
|
@@ -31,32 +60,20 @@ class DatabaseHandler:
|
|
|
31
60
|
Parameters
|
|
32
61
|
----------
|
|
33
62
|
mongo_db_config: dict
|
|
34
|
-
Dictionary with the MongoDB configuration
|
|
35
|
-
"db_server" - DB server address
|
|
36
|
-
"db_api_port" - Port to use
|
|
37
|
-
"db_api_user" - API username
|
|
38
|
-
"db_api_pw" - Password for the API user
|
|
39
|
-
"db_api_authentication_database" - DB with user info (optional, default is "admin")
|
|
40
|
-
"db_simulation_model" - Name of simulation model database
|
|
63
|
+
Dictionary with the MongoDB configuration (see jsonschema_db_dict for details).
|
|
41
64
|
"""
|
|
42
65
|
|
|
43
|
-
DB_CTA_SIMULATION_MODEL_DESCRIPTIONS = "CTA-Simulation-Model-Descriptions"
|
|
44
|
-
# DB collection with updates field names
|
|
45
|
-
DB_DERIVED_VALUES = "Staging-CTA-Simulation-Model-Derived-Values"
|
|
46
|
-
|
|
47
66
|
ALLOWED_FILE_EXTENSIONS = [".dat", ".txt", ".lis", ".cfg", ".yml", ".yaml", ".ecsv"]
|
|
48
67
|
|
|
49
68
|
db_client = None
|
|
50
|
-
|
|
69
|
+
production_table_cached = {}
|
|
51
70
|
model_parameters_cached = {}
|
|
52
|
-
model_versions_cached = {}
|
|
53
|
-
corsika_configuration_parameters_cached = {}
|
|
54
71
|
|
|
55
72
|
def __init__(self, mongo_db_config=None):
|
|
56
73
|
"""Initialize the DatabaseHandler class."""
|
|
57
74
|
self._logger = logging.getLogger(__name__)
|
|
58
75
|
|
|
59
|
-
self.mongo_db_config = mongo_db_config
|
|
76
|
+
self.mongo_db_config = self._validate_mongo_db_config(mongo_db_config)
|
|
60
77
|
self.io_handler = io_handler.IOHandler()
|
|
61
78
|
self.list_of_collections = {}
|
|
62
79
|
|
|
@@ -70,6 +87,16 @@ class DatabaseHandler:
|
|
|
70
87
|
with lock:
|
|
71
88
|
DatabaseHandler.db_client = self._open_mongo_db()
|
|
72
89
|
|
|
90
|
+
def _validate_mongo_db_config(self, mongo_db_config):
|
|
91
|
+
"""Validate the MongoDB configuration."""
|
|
92
|
+
if mongo_db_config is None or all(value is None for value in mongo_db_config.values()):
|
|
93
|
+
return None
|
|
94
|
+
try:
|
|
95
|
+
jsonschema.validate(instance=mongo_db_config, schema=jsonschema_db_dict)
|
|
96
|
+
return mongo_db_config
|
|
97
|
+
except jsonschema.exceptions.ValidationError as err:
|
|
98
|
+
raise ValueError("Invalid MongoDB configuration") from err
|
|
99
|
+
|
|
73
100
|
def _open_mongo_db(self):
|
|
74
101
|
"""
|
|
75
102
|
Open a connection to MongoDB and return the client to read/write to the DB with.
|
|
@@ -83,25 +110,21 @@ class DatabaseHandler:
|
|
|
83
110
|
KeyError
|
|
84
111
|
If the DB configuration is invalid
|
|
85
112
|
"""
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
)
|
|
102
|
-
except KeyError:
|
|
103
|
-
self._logger.error("Invalid setting of DB configuration")
|
|
104
|
-
raise
|
|
113
|
+
direct_connection = self.mongo_db_config["db_server"] in (
|
|
114
|
+
"localhost",
|
|
115
|
+
"simtools-mongodb",
|
|
116
|
+
)
|
|
117
|
+
return MongoClient(
|
|
118
|
+
self.mongo_db_config["db_server"],
|
|
119
|
+
port=self.mongo_db_config["db_api_port"],
|
|
120
|
+
username=self.mongo_db_config["db_api_user"],
|
|
121
|
+
password=self.mongo_db_config["db_api_pw"],
|
|
122
|
+
authSource=self.mongo_db_config.get("db_api_authentication_database", "admin"),
|
|
123
|
+
directConnection=direct_connection,
|
|
124
|
+
ssl=not direct_connection,
|
|
125
|
+
tlsallowinvalidhostnames=True,
|
|
126
|
+
tlsallowinvalidcertificates=True,
|
|
127
|
+
)
|
|
105
128
|
|
|
106
129
|
def _find_latest_simulation_model_db(self):
|
|
107
130
|
"""
|
|
@@ -118,12 +141,13 @@ class DatabaseHandler:
|
|
|
118
141
|
|
|
119
142
|
"""
|
|
120
143
|
try:
|
|
121
|
-
|
|
144
|
+
db_simulation_model = self.mongo_db_config["db_simulation_model"]
|
|
145
|
+
if not db_simulation_model.endswith("LATEST"):
|
|
122
146
|
return
|
|
123
|
-
except TypeError:
|
|
147
|
+
except TypeError: # db_simulation_model is None
|
|
124
148
|
return
|
|
125
149
|
|
|
126
|
-
prefix =
|
|
150
|
+
prefix = db_simulation_model.replace("LATEST", "")
|
|
127
151
|
list_of_db_names = self.db_client.list_database_names()
|
|
128
152
|
filtered_list_of_db_names = [s for s in list_of_db_names if s.startswith(prefix)]
|
|
129
153
|
versioned_strings = []
|
|
@@ -148,78 +172,117 @@ class DatabaseHandler:
|
|
|
148
172
|
else:
|
|
149
173
|
raise ValueError("Found LATEST in the DB name but no matching versions found in DB.")
|
|
150
174
|
|
|
175
|
+
def get_model_parameter(
|
|
176
|
+
self,
|
|
177
|
+
parameter,
|
|
178
|
+
parameter_version,
|
|
179
|
+
site,
|
|
180
|
+
array_element_name,
|
|
181
|
+
collection,
|
|
182
|
+
):
|
|
183
|
+
"""
|
|
184
|
+
Get a model parameter using the parameter version.
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
parameter: str
|
|
189
|
+
Name of the parameter.
|
|
190
|
+
parameter_version: str
|
|
191
|
+
Version of the parameter.
|
|
192
|
+
site: str
|
|
193
|
+
Site name.
|
|
194
|
+
array_element_name: str
|
|
195
|
+
Name of the array element model (e.g. MSTN, SSTS).
|
|
196
|
+
collection: str
|
|
197
|
+
Collection of array element (e.g. telescopes, calibration_devices).
|
|
198
|
+
|
|
199
|
+
Returns
|
|
200
|
+
-------
|
|
201
|
+
dict containing the parameter
|
|
202
|
+
|
|
203
|
+
"""
|
|
204
|
+
query = {
|
|
205
|
+
"parameter_version": parameter_version,
|
|
206
|
+
"parameter": parameter,
|
|
207
|
+
}
|
|
208
|
+
if array_element_name is not None:
|
|
209
|
+
query["instrument"] = array_element_name
|
|
210
|
+
if site is not None:
|
|
211
|
+
query["site"] = site
|
|
212
|
+
return self._read_mongo_db(query=query, collection_name=collection)
|
|
213
|
+
|
|
151
214
|
def get_model_parameters(
|
|
152
215
|
self,
|
|
153
216
|
site,
|
|
154
217
|
array_element_name,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
only_applicable=False,
|
|
218
|
+
collection,
|
|
219
|
+
model_version=None,
|
|
158
220
|
):
|
|
159
221
|
"""
|
|
160
|
-
Get parameters
|
|
222
|
+
Get model parameters using the model version.
|
|
161
223
|
|
|
162
|
-
|
|
163
|
-
Read parameters for design and for the specified array element (if necessary). This allows
|
|
164
|
-
to overwrite design parameters with specific parameters without having to copy
|
|
165
|
-
all model parameters when changing only a few.
|
|
224
|
+
Queries parameters for design and for the specified array element (if necessary).
|
|
166
225
|
|
|
167
226
|
Parameters
|
|
168
227
|
----------
|
|
169
228
|
site: str
|
|
170
229
|
Site name.
|
|
171
230
|
array_element_name: str
|
|
172
|
-
Name of the array element model (e.g. LSTN-01, MSTS-design)
|
|
173
|
-
model_version: str
|
|
174
|
-
Version of the model.
|
|
231
|
+
Name of the array element model (e.g. LSTN-01, MSTS-design, ILLN-01).
|
|
232
|
+
model_version: str, list
|
|
233
|
+
Version(s) of the model.
|
|
175
234
|
collection: str
|
|
176
|
-
|
|
177
|
-
only_applicable: bool
|
|
178
|
-
If True, only applicable parameters will be read.
|
|
235
|
+
Collection of array element (e.g. telescopes, calibration_devices).
|
|
179
236
|
|
|
180
237
|
Returns
|
|
181
238
|
-------
|
|
182
239
|
dict containing the parameters
|
|
183
|
-
|
|
184
240
|
"""
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
)
|
|
188
|
-
array_element_list = db_array_elements.get_array_element_list_for_db_query(
|
|
189
|
-
_array_element_name, self, _model_version, collection
|
|
241
|
+
model_versions = (
|
|
242
|
+
self.get_model_versions(collection) if model_version is None else [model_version]
|
|
190
243
|
)
|
|
244
|
+
|
|
191
245
|
pars = {}
|
|
192
|
-
for
|
|
193
|
-
|
|
194
|
-
|
|
246
|
+
for _model_version in model_versions:
|
|
247
|
+
production_table = self._read_production_table_from_mongo_db(collection, _model_version)
|
|
248
|
+
array_element_list = self._get_array_element_list(
|
|
249
|
+
array_element_name, site, production_table, collection
|
|
195
250
|
)
|
|
196
|
-
|
|
197
|
-
pars.update(DatabaseHandler.model_parameters_cached[_array_elements_cache_key])
|
|
198
|
-
except KeyError:
|
|
251
|
+
for array_element in array_element_list:
|
|
199
252
|
pars.update(
|
|
200
|
-
self.
|
|
201
|
-
|
|
202
|
-
array_element_name=array_element,
|
|
203
|
-
model_version=_model_version,
|
|
204
|
-
collection_name=collection,
|
|
205
|
-
run_location=None,
|
|
206
|
-
write_files=False,
|
|
207
|
-
only_applicable=only_applicable,
|
|
253
|
+
self._get_parameter_for_model_version(
|
|
254
|
+
array_element, _model_version, site, collection, production_table
|
|
208
255
|
)
|
|
209
256
|
)
|
|
210
|
-
if self.mongo_db_config.get("db_simulation_model_url", None) is not None:
|
|
211
|
-
pars = db_from_repo_handler.update_model_parameters_from_repo(
|
|
212
|
-
parameters=pars,
|
|
213
|
-
site=_site,
|
|
214
|
-
parameter_collection=collection,
|
|
215
|
-
array_element_name=array_element,
|
|
216
|
-
model_version=_model_version,
|
|
217
|
-
db_simulation_model_url=self.mongo_db_config.get("db_simulation_model_url"),
|
|
218
|
-
)
|
|
219
|
-
DatabaseHandler.model_parameters_cached[_array_elements_cache_key] = pars
|
|
220
|
-
|
|
221
257
|
return pars
|
|
222
258
|
|
|
259
|
+
def _get_parameter_for_model_version(
|
|
260
|
+
self, array_element, model_version, site, collection, production_table
|
|
261
|
+
):
|
|
262
|
+
cache_key, cache_dict = self._read_cache(
|
|
263
|
+
DatabaseHandler.model_parameters_cached,
|
|
264
|
+
names.validate_site_name(site) if site else None,
|
|
265
|
+
array_element,
|
|
266
|
+
model_version,
|
|
267
|
+
collection,
|
|
268
|
+
)
|
|
269
|
+
if cache_dict:
|
|
270
|
+
self._logger.debug(f"Found {array_element} in cache (key: {cache_key})")
|
|
271
|
+
return cache_dict
|
|
272
|
+
self._logger.debug(f"Did not find {array_element} in cache (key: {cache_key})")
|
|
273
|
+
|
|
274
|
+
try:
|
|
275
|
+
parameter_version_table = production_table["parameters"][array_element]
|
|
276
|
+
except KeyError: # allow missing array elements (parameter dict is checked later)
|
|
277
|
+
return {}
|
|
278
|
+
DatabaseHandler.model_parameters_cached[cache_key] = self._read_mongo_db(
|
|
279
|
+
query=self._get_query_from_parameter_version_table(
|
|
280
|
+
parameter_version_table, array_element, site
|
|
281
|
+
),
|
|
282
|
+
collection_name=collection,
|
|
283
|
+
)
|
|
284
|
+
return DatabaseHandler.model_parameters_cached[cache_key]
|
|
285
|
+
|
|
223
286
|
def get_collection(self, db_name, collection_name):
|
|
224
287
|
"""
|
|
225
288
|
Get a collection from the DB.
|
|
@@ -240,103 +303,102 @@ class DatabaseHandler:
|
|
|
240
303
|
db_name = self._get_db_name(db_name)
|
|
241
304
|
return DatabaseHandler.db_client[db_name][collection_name]
|
|
242
305
|
|
|
243
|
-
def
|
|
306
|
+
def get_collections(self, db_name=None, model_collections_only=False):
|
|
244
307
|
"""
|
|
245
|
-
|
|
308
|
+
List of collections in the DB.
|
|
246
309
|
|
|
247
310
|
Parameters
|
|
248
311
|
----------
|
|
249
312
|
db_name: str
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
file_name: str
|
|
254
|
-
Name of the file to get.
|
|
313
|
+
Database name.
|
|
314
|
+
model_collections_only: bool
|
|
315
|
+
If True, only return model collections (i.e. exclude fs.files, fs.chunks)
|
|
255
316
|
|
|
256
317
|
Returns
|
|
257
318
|
-------
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
Raises
|
|
262
|
-
------
|
|
263
|
-
FileNotFoundError
|
|
264
|
-
If the desired file is not found.
|
|
319
|
+
list
|
|
320
|
+
List of collection names
|
|
265
321
|
|
|
266
322
|
"""
|
|
267
|
-
db_name = self._get_db_name(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
323
|
+
db_name = db_name or self._get_db_name()
|
|
324
|
+
if db_name not in self.list_of_collections:
|
|
325
|
+
self.list_of_collections[db_name] = DatabaseHandler.db_client[
|
|
326
|
+
db_name
|
|
327
|
+
].list_collection_names()
|
|
328
|
+
collections = self.list_of_collections[db_name]
|
|
329
|
+
if model_collections_only:
|
|
330
|
+
return [collection for collection in collections if not collection.startswith("fs.")]
|
|
331
|
+
return collections
|
|
273
332
|
|
|
274
|
-
def export_model_files(self, parameters, dest):
|
|
333
|
+
def export_model_files(self, parameters=None, file_names=None, dest=None, db_name=None):
|
|
275
334
|
"""
|
|
276
|
-
Export
|
|
335
|
+
Export files from the DB to the model directory.
|
|
336
|
+
|
|
337
|
+
The files to be exported can be specified by file_name or retrieved from the database
|
|
338
|
+
using the parameters dictionary.
|
|
277
339
|
|
|
278
340
|
Parameters
|
|
279
341
|
----------
|
|
280
342
|
parameters: dict
|
|
281
343
|
Dict of model parameters
|
|
344
|
+
file_names: list, str
|
|
345
|
+
List (or string) of file names to export
|
|
282
346
|
dest: str or Path
|
|
283
347
|
Location where to write the files to.
|
|
284
348
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
349
|
+
Returns
|
|
350
|
+
-------
|
|
351
|
+
file_id: dict of GridOut._id
|
|
352
|
+
Dict of database IDs of files.
|
|
290
353
|
"""
|
|
291
|
-
|
|
292
|
-
for info in parameters.values():
|
|
293
|
-
if not info or not info.get("file") or info["value"] is None:
|
|
294
|
-
continue
|
|
295
|
-
if Path(dest).joinpath(info["value"]).exists():
|
|
296
|
-
continue
|
|
297
|
-
file = self._get_file_mongo_db(self._get_db_name(), info["value"])
|
|
298
|
-
self._write_file_from_mongo_to_disk(self._get_db_name(), dest, file)
|
|
299
|
-
if self.mongo_db_config.get("db_simulation_model_url", None) is not None:
|
|
300
|
-
self._logger.warning(
|
|
301
|
-
"Exporting model files from simulation model repository not yet implemented"
|
|
302
|
-
)
|
|
354
|
+
db_name = self._get_db_name(db_name)
|
|
303
355
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
356
|
+
if file_names:
|
|
357
|
+
file_names = [file_names] if not isinstance(file_names, list) else file_names
|
|
358
|
+
elif parameters:
|
|
359
|
+
file_names = [
|
|
360
|
+
info["value"]
|
|
361
|
+
for info in parameters.values()
|
|
362
|
+
if info and info.get("file") and info["value"] is not None
|
|
363
|
+
]
|
|
308
364
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
365
|
+
instance_ids = {}
|
|
366
|
+
for file_name in file_names:
|
|
367
|
+
if Path(dest).joinpath(file_name).exists():
|
|
368
|
+
instance_ids[file_name] = "file exists"
|
|
369
|
+
else:
|
|
370
|
+
file_path_instance = self._get_file_mongo_db(self._get_db_name(), file_name)
|
|
371
|
+
self._write_file_from_mongo_to_disk(self._get_db_name(), dest, file_path_instance)
|
|
372
|
+
instance_ids[file_name] = file_path_instance._id # pylint: disable=protected-access
|
|
373
|
+
return instance_ids
|
|
374
|
+
|
|
375
|
+
def _get_query_from_parameter_version_table(
|
|
376
|
+
self, parameter_version_table, array_element_name, site
|
|
318
377
|
):
|
|
319
|
-
"""
|
|
320
|
-
|
|
378
|
+
"""Return query based on parameter version table."""
|
|
379
|
+
query_dict = {
|
|
380
|
+
"$or": [
|
|
381
|
+
{"parameter": param, "parameter_version": version}
|
|
382
|
+
for param, version in parameter_version_table.items()
|
|
383
|
+
],
|
|
384
|
+
}
|
|
385
|
+
# 'xSTX-design' is a placeholder to ignore 'instrument' field in query.
|
|
386
|
+
if array_element_name and array_element_name != "xSTx-design":
|
|
387
|
+
query_dict["instrument"] = array_element_name
|
|
388
|
+
if site:
|
|
389
|
+
query_dict["site"] = site
|
|
390
|
+
return query_dict
|
|
321
391
|
|
|
322
|
-
|
|
392
|
+
def _read_mongo_db(self, query, collection_name):
|
|
393
|
+
"""
|
|
394
|
+
Query MongoDB.
|
|
323
395
|
|
|
324
396
|
Parameters
|
|
325
397
|
----------
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
array_element_name: str
|
|
329
|
-
Name of the array element model (e.g. MSTN-design ...)
|
|
330
|
-
model_version: str
|
|
331
|
-
Version of the model.
|
|
332
|
-
run_location: Path or str
|
|
333
|
-
The sim_telarray run location to write the tabulated data files into.
|
|
398
|
+
query: dict
|
|
399
|
+
Query to execute.
|
|
334
400
|
collection_name: str
|
|
335
|
-
|
|
336
|
-
write_files: bool
|
|
337
|
-
If true, write the files to the run_location.
|
|
338
|
-
only_applicable: bool
|
|
339
|
-
If True, only applicable parameters will be read.
|
|
401
|
+
Collection name.
|
|
340
402
|
|
|
341
403
|
Returns
|
|
342
404
|
-------
|
|
@@ -345,164 +407,127 @@ class DatabaseHandler:
|
|
|
345
407
|
Raises
|
|
346
408
|
------
|
|
347
409
|
ValueError
|
|
348
|
-
if query returned
|
|
349
|
-
|
|
410
|
+
if query returned no results.
|
|
350
411
|
"""
|
|
412
|
+
db_name = self._get_db_name()
|
|
351
413
|
collection = self.get_collection(db_name, collection_name)
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
query = {
|
|
355
|
-
"instrument": array_element_name,
|
|
356
|
-
"version": self.model_version(model_version, db_name),
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
if only_applicable:
|
|
360
|
-
query["applicable"] = True
|
|
361
|
-
if collection.count_documents(query) < 1:
|
|
414
|
+
posts = list(collection.find(query))
|
|
415
|
+
if not posts:
|
|
362
416
|
raise ValueError(
|
|
363
|
-
"The following query returned zero results
|
|
364
|
-
query,
|
|
417
|
+
f"The following query for {collection_name} returned zero results: {query} "
|
|
365
418
|
)
|
|
366
|
-
|
|
419
|
+
parameters = {}
|
|
420
|
+
for post in posts:
|
|
367
421
|
par_now = post["parameter"]
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
_parameters[par_now]["entry_date"] = ObjectId(post["_id"]).generation_time
|
|
372
|
-
if _parameters[par_now]["file"] and write_files:
|
|
373
|
-
file = self._get_file_mongo_db(db_name, _parameters[par_now]["value"])
|
|
374
|
-
self._write_file_from_mongo_to_disk(db_name, run_location, file)
|
|
375
|
-
|
|
376
|
-
return _parameters
|
|
422
|
+
parameters[par_now] = post
|
|
423
|
+
parameters[par_now]["entry_date"] = ObjectId(post["_id"]).generation_time
|
|
424
|
+
return {k: parameters[k] for k in sorted(parameters)}
|
|
377
425
|
|
|
378
|
-
def
|
|
379
|
-
self,
|
|
380
|
-
site,
|
|
381
|
-
model_version,
|
|
382
|
-
only_applicable=False,
|
|
383
|
-
):
|
|
426
|
+
def _read_production_table_from_mongo_db(self, collection_name, model_version):
|
|
384
427
|
"""
|
|
385
|
-
|
|
428
|
+
Read production table from MongoDB.
|
|
386
429
|
|
|
387
430
|
Parameters
|
|
388
431
|
----------
|
|
389
|
-
|
|
390
|
-
|
|
432
|
+
collection_name: str
|
|
433
|
+
Name of the collection.
|
|
391
434
|
model_version: str
|
|
392
435
|
Version of the model.
|
|
393
|
-
only_applicable: bool
|
|
394
|
-
If True, only applicable parameters will be read.
|
|
395
|
-
|
|
396
|
-
Returns
|
|
397
|
-
-------
|
|
398
|
-
dict containing the parameters
|
|
399
436
|
|
|
437
|
+
Raises
|
|
438
|
+
------
|
|
439
|
+
ValueError
|
|
440
|
+
if query returned no results.
|
|
400
441
|
"""
|
|
401
|
-
_site, _, _model_version = self._validate_model_input(site, None, model_version)
|
|
402
|
-
_db_name = self._get_db_name()
|
|
403
|
-
_site_cache_key = self._parameter_cache_key(site, None, model_version)
|
|
404
442
|
try:
|
|
405
|
-
return DatabaseHandler.
|
|
443
|
+
return DatabaseHandler.production_table_cached[
|
|
444
|
+
self._cache_key(None, None, model_version, collection_name)
|
|
445
|
+
]
|
|
406
446
|
except KeyError:
|
|
407
447
|
pass
|
|
408
448
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
model_version=_model_version,
|
|
423
|
-
db_simulation_model_url=self.mongo_db_config.get("db_simulation_model_url", None),
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
DatabaseHandler.site_parameters_cached[_site_cache_key] = _pars
|
|
427
|
-
return DatabaseHandler.site_parameters_cached[_site_cache_key]
|
|
449
|
+
query = {"model_version": model_version, "collection": collection_name}
|
|
450
|
+
collection = self.get_collection(self._get_db_name(), "production_tables")
|
|
451
|
+
post = collection.find_one(query)
|
|
452
|
+
if not post:
|
|
453
|
+
raise ValueError(f"The following query returned zero results: {query}")
|
|
454
|
+
|
|
455
|
+
return {
|
|
456
|
+
"collection": post["collection"],
|
|
457
|
+
"model_version": post["model_version"],
|
|
458
|
+
"parameters": post["parameters"],
|
|
459
|
+
"design_model": post.get("design_model", {}),
|
|
460
|
+
"entry_date": ObjectId(post["_id"]).generation_time,
|
|
461
|
+
}
|
|
428
462
|
|
|
429
|
-
def
|
|
463
|
+
def get_model_versions(self, collection_name="telescopes"):
|
|
430
464
|
"""
|
|
431
|
-
Get
|
|
465
|
+
Get list of model versions from the DB.
|
|
432
466
|
|
|
433
467
|
Parameters
|
|
434
468
|
----------
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
site: str
|
|
438
|
-
Site name.
|
|
439
|
-
model_version: str
|
|
440
|
-
Version of the model.
|
|
441
|
-
only_applicable: bool
|
|
442
|
-
If True, only applicable parameters will be read.
|
|
469
|
+
collection_name: str
|
|
470
|
+
Name of the collection.
|
|
443
471
|
|
|
444
472
|
Returns
|
|
445
473
|
-------
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
Raises
|
|
449
|
-
------
|
|
450
|
-
ValueError
|
|
451
|
-
if query returned zero results.
|
|
452
|
-
|
|
474
|
+
list
|
|
475
|
+
List of model versions
|
|
453
476
|
"""
|
|
454
|
-
collection = self.get_collection(
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
"site": site,
|
|
459
|
-
"version": model_version,
|
|
460
|
-
}
|
|
461
|
-
if only_applicable:
|
|
462
|
-
query["applicable"] = True
|
|
463
|
-
if collection.count_documents(query) < 1:
|
|
464
|
-
raise ValueError(
|
|
465
|
-
"The following query returned zero results! Check the input data and rerun.\n",
|
|
466
|
-
query,
|
|
467
|
-
)
|
|
468
|
-
for post in collection.find(query).sort("parameter", ASCENDING):
|
|
469
|
-
par_now = post["parameter"]
|
|
470
|
-
_parameters[par_now] = post
|
|
471
|
-
_parameters[par_now].pop("parameter", None)
|
|
472
|
-
_parameters[par_now].pop("site", None)
|
|
473
|
-
_parameters[par_now]["entry_date"] = ObjectId(post["_id"]).generation_time
|
|
474
|
-
|
|
475
|
-
return _parameters
|
|
477
|
+
collection = self.get_collection(self._get_db_name(), "production_tables")
|
|
478
|
+
return sorted(
|
|
479
|
+
[post["model_version"] for post in collection.find({"collection": collection_name})]
|
|
480
|
+
)
|
|
476
481
|
|
|
477
|
-
def
|
|
482
|
+
def get_array_elements(self, model_version, collection="telescopes"):
|
|
478
483
|
"""
|
|
479
|
-
Get
|
|
484
|
+
Get list array elements for a given model version and collection from the DB.
|
|
480
485
|
|
|
481
486
|
Parameters
|
|
482
487
|
----------
|
|
483
|
-
site: str
|
|
484
|
-
Site name.
|
|
485
|
-
array_element_name: str
|
|
486
|
-
Name of the array element model (e.g. MSTN, SSTS).
|
|
487
488
|
model_version: str
|
|
488
489
|
Version of the model.
|
|
490
|
+
collection: str
|
|
491
|
+
Which collection to get the array elements from:
|
|
492
|
+
i.e. telescopes, calibration_devices.
|
|
489
493
|
|
|
490
494
|
Returns
|
|
491
495
|
-------
|
|
492
|
-
|
|
496
|
+
list
|
|
497
|
+
Sorted list of all array elements found in collection
|
|
498
|
+
"""
|
|
499
|
+
production_table = self._read_production_table_from_mongo_db(collection, model_version)
|
|
500
|
+
return sorted([entry for entry in production_table["parameters"] if "-design" not in entry])
|
|
493
501
|
|
|
502
|
+
def get_array_elements_of_type(self, array_element_type, model_version, collection):
|
|
494
503
|
"""
|
|
495
|
-
|
|
496
|
-
site, array_element_name, model_version
|
|
497
|
-
)
|
|
504
|
+
Get array elements of a certain type (e.g. 'LSTN') for a DB collection.
|
|
498
505
|
|
|
499
|
-
return
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
+
Does not return 'design' models.
|
|
507
|
+
|
|
508
|
+
Parameters
|
|
509
|
+
----------
|
|
510
|
+
array_element_type: str
|
|
511
|
+
Type of the array element (e.g. LSTN, MSTS).
|
|
512
|
+
model_version: str
|
|
513
|
+
Version of the model.
|
|
514
|
+
collection: str
|
|
515
|
+
Which collection to get the array elements from:
|
|
516
|
+
i.e. telescopes, calibration_devices.
|
|
517
|
+
|
|
518
|
+
Returns
|
|
519
|
+
-------
|
|
520
|
+
list
|
|
521
|
+
Sorted list of all array element names found in collection
|
|
522
|
+
"""
|
|
523
|
+
production_table = self._read_production_table_from_mongo_db(collection, model_version)
|
|
524
|
+
all_array_elements = production_table["parameters"]
|
|
525
|
+
return sorted(
|
|
526
|
+
[
|
|
527
|
+
entry
|
|
528
|
+
for entry in all_array_elements
|
|
529
|
+
if entry.startswith(array_element_type) and "-design" not in entry
|
|
530
|
+
]
|
|
506
531
|
)
|
|
507
532
|
|
|
508
533
|
def get_simulation_configuration_parameters(
|
|
@@ -532,63 +557,24 @@ class DatabaseHandler:
|
|
|
532
557
|
if simulation_software is not valid.
|
|
533
558
|
"""
|
|
534
559
|
if simulation_software == "corsika":
|
|
535
|
-
return self.
|
|
560
|
+
return self.get_model_parameters(
|
|
561
|
+
None,
|
|
562
|
+
None,
|
|
563
|
+
model_version=model_version,
|
|
564
|
+
collection="configuration_corsika",
|
|
565
|
+
)
|
|
536
566
|
if simulation_software == "simtel":
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
site,
|
|
567
|
+
return (
|
|
568
|
+
self.get_model_parameters(
|
|
569
|
+
site,
|
|
570
|
+
array_element_name,
|
|
571
|
+
model_version=model_version,
|
|
572
|
+
collection="configuration_sim_telarray",
|
|
540
573
|
)
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
def get_corsika_configuration_parameters(self, model_version):
|
|
545
|
-
"""
|
|
546
|
-
Get CORSIKA configuration parameters from the DB.
|
|
547
|
-
|
|
548
|
-
Parameters
|
|
549
|
-
----------
|
|
550
|
-
model_version : str
|
|
551
|
-
Version of the model.
|
|
552
|
-
|
|
553
|
-
Returns
|
|
554
|
-
-------
|
|
555
|
-
dict
|
|
556
|
-
Configuration parameters for CORSIKA
|
|
557
|
-
"""
|
|
558
|
-
_corsika_cache_key = self._parameter_cache_key(None, None, model_version)
|
|
559
|
-
try:
|
|
560
|
-
return DatabaseHandler.corsika_configuration_parameters_cached[_corsika_cache_key]
|
|
561
|
-
except KeyError:
|
|
562
|
-
pass
|
|
563
|
-
DatabaseHandler.corsika_configuration_parameters_cached[_corsika_cache_key] = (
|
|
564
|
-
self.read_mongo_db(
|
|
565
|
-
db_name=self._get_db_name(),
|
|
566
|
-
array_element_name=None,
|
|
567
|
-
model_version=model_version,
|
|
568
|
-
run_location=None,
|
|
569
|
-
collection_name="configuration_corsika",
|
|
570
|
-
write_files=False,
|
|
574
|
+
if site and array_element_name
|
|
575
|
+
else {}
|
|
571
576
|
)
|
|
572
|
-
)
|
|
573
|
-
return DatabaseHandler.corsika_configuration_parameters_cached[_corsika_cache_key]
|
|
574
|
-
|
|
575
|
-
def _validate_model_input(self, site, array_element_name, model_version):
|
|
576
|
-
"""
|
|
577
|
-
Validate input for model parameter queries.
|
|
578
|
-
|
|
579
|
-
site: str
|
|
580
|
-
Site name.
|
|
581
|
-
array_element_name: str
|
|
582
|
-
Name of the array element model (e.g. LSTN-01, MSTS-design)
|
|
583
|
-
model_version: str
|
|
584
|
-
Version of the model.
|
|
585
|
-
|
|
586
|
-
"""
|
|
587
|
-
return (
|
|
588
|
-
names.validate_site_name(site),
|
|
589
|
-
names.validate_array_element_name(array_element_name) if array_element_name else None,
|
|
590
|
-
self.model_version(model_version),
|
|
591
|
-
)
|
|
577
|
+
raise ValueError(f"Unknown simulation software: {simulation_software}")
|
|
592
578
|
|
|
593
579
|
@staticmethod
|
|
594
580
|
def _get_file_mongo_db(db_name, file_name):
|
|
@@ -639,369 +625,77 @@ class DatabaseHandler:
|
|
|
639
625
|
with open(Path(path).joinpath(file.filename), "wb") as output_file:
|
|
640
626
|
fs_output.download_to_stream_by_name(file.filename, output_file)
|
|
641
627
|
|
|
642
|
-
def
|
|
643
|
-
self,
|
|
644
|
-
db_name,
|
|
645
|
-
element_to_copy,
|
|
646
|
-
version_to_copy,
|
|
647
|
-
new_array_element_name,
|
|
648
|
-
collection_name="telescopes",
|
|
649
|
-
db_to_copy_to=None,
|
|
650
|
-
collection_to_copy_to=None,
|
|
651
|
-
):
|
|
628
|
+
def add_production_table(self, db_name, production_table):
|
|
652
629
|
"""
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
Only a specific version is copied.
|
|
656
|
-
(This function should be rarely used, probably only during "construction".)
|
|
630
|
+
Add a production table to the DB.
|
|
657
631
|
|
|
658
632
|
Parameters
|
|
659
633
|
----------
|
|
660
634
|
db_name: str
|
|
661
|
-
the name of the DB
|
|
662
|
-
|
|
663
|
-
The
|
|
664
|
-
version_to_copy: str
|
|
665
|
-
The version of the configuration to copy
|
|
666
|
-
new_array_element_name: str
|
|
667
|
-
The name of the new array element
|
|
668
|
-
collection_name: str
|
|
669
|
-
The name of the collection to copy from.
|
|
670
|
-
db_to_copy_to: str
|
|
671
|
-
The name of the DB to copy to.
|
|
672
|
-
collection_to_copy_to: str
|
|
673
|
-
The name of the collection to copy to.
|
|
674
|
-
|
|
675
|
-
Raises
|
|
676
|
-
------
|
|
677
|
-
BulkWriteError
|
|
678
|
-
|
|
679
|
-
"""
|
|
680
|
-
db_name = self._get_db_name(db_name)
|
|
681
|
-
if db_to_copy_to is None:
|
|
682
|
-
db_to_copy_to = db_name
|
|
683
|
-
|
|
684
|
-
if collection_to_copy_to is None:
|
|
685
|
-
collection_to_copy_to = collection_name
|
|
686
|
-
|
|
687
|
-
self._logger.info(
|
|
688
|
-
f"Copying version {version_to_copy} of {element_to_copy} "
|
|
689
|
-
f"to the new array element {new_array_element_name} in the {db_to_copy_to} DB"
|
|
690
|
-
)
|
|
691
|
-
|
|
692
|
-
collection = self.get_collection(db_name, collection_name)
|
|
693
|
-
db_entries = []
|
|
694
|
-
|
|
695
|
-
_version_to_copy = self.model_version(version_to_copy)
|
|
696
|
-
|
|
697
|
-
query = {
|
|
698
|
-
"instrument": element_to_copy,
|
|
699
|
-
"version": _version_to_copy,
|
|
700
|
-
}
|
|
701
|
-
for post in collection.find(query):
|
|
702
|
-
post["instrument"] = new_array_element_name
|
|
703
|
-
post.pop("_id", None)
|
|
704
|
-
db_entries.append(post)
|
|
705
|
-
|
|
706
|
-
self._logger.info(f"Creating new array element {new_array_element_name}")
|
|
707
|
-
collection = self.get_collection(db_to_copy_to, collection_to_copy_to)
|
|
708
|
-
try:
|
|
709
|
-
collection.insert_many(db_entries)
|
|
710
|
-
except BulkWriteError as exc:
|
|
711
|
-
raise BulkWriteError(str(exc.details)) from exc
|
|
712
|
-
|
|
713
|
-
def copy_documents(self, db_name, collection, query, db_to_copy_to, collection_to_copy_to=None):
|
|
714
|
-
"""
|
|
715
|
-
Copy the documents matching to "query" to the DB "db_to_copy_to".
|
|
716
|
-
|
|
717
|
-
The documents are copied to the same collection as in "db_name".
|
|
718
|
-
(This function should be rarely used, probably only during "construction".)
|
|
719
|
-
|
|
720
|
-
Parameters
|
|
721
|
-
----------
|
|
722
|
-
db_name: str
|
|
723
|
-
the name of the DB to copy from
|
|
724
|
-
collection: str
|
|
725
|
-
the name of the collection to copy from
|
|
726
|
-
query: dict
|
|
727
|
-
A dictionary with a query to search for documents to copy.
|
|
728
|
-
For example, the query below would copy all entries of version 6.0.0
|
|
729
|
-
from telescope LSTN-01 to "db_to_copy_to".
|
|
730
|
-
|
|
731
|
-
.. code-block:: python
|
|
732
|
-
|
|
733
|
-
query = {
|
|
734
|
-
"instrument": "LSTN-01",
|
|
735
|
-
"version": "6.0.0",
|
|
736
|
-
}
|
|
737
|
-
db_to_copy_to: str
|
|
738
|
-
The name of the DB to copy to.
|
|
739
|
-
|
|
740
|
-
Raises
|
|
741
|
-
------
|
|
742
|
-
BulkWriteError
|
|
743
|
-
|
|
635
|
+
the name of the DB.
|
|
636
|
+
production_table: dict
|
|
637
|
+
The production table to add to the DB.
|
|
744
638
|
"""
|
|
745
639
|
db_name = self._get_db_name(db_name)
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
db_entries = []
|
|
751
|
-
|
|
752
|
-
for post in _collection.find(query):
|
|
753
|
-
post.pop("_id", None)
|
|
754
|
-
db_entries.append(post)
|
|
755
|
-
|
|
756
|
-
self._logger.info(
|
|
757
|
-
f"Copying documents matching the following query {query}\nto {db_to_copy_to}"
|
|
758
|
-
)
|
|
759
|
-
_collection = self.get_collection(db_to_copy_to, collection_to_copy_to)
|
|
760
|
-
try:
|
|
761
|
-
_collection.insert_many(db_entries)
|
|
762
|
-
except BulkWriteError as exc:
|
|
763
|
-
raise BulkWriteError(str(exc.details)) from exc
|
|
764
|
-
|
|
765
|
-
def delete_query(self, db_name, collection, query):
|
|
766
|
-
"""
|
|
767
|
-
Delete all entries from the DB which correspond to the provided query.
|
|
768
|
-
|
|
769
|
-
(This function should be rarely used, if at all.)
|
|
770
|
-
|
|
771
|
-
Parameters
|
|
772
|
-
----------
|
|
773
|
-
db_name: str
|
|
774
|
-
the name of the DB
|
|
775
|
-
collection: str
|
|
776
|
-
the name of the collection to copy from
|
|
777
|
-
query: dict
|
|
778
|
-
A dictionary listing the fields/values to delete.
|
|
779
|
-
For example, the query below would delete the entire version 6.0.0
|
|
780
|
-
from telescope LSTN-01.
|
|
781
|
-
|
|
782
|
-
.. code-block:: python
|
|
783
|
-
|
|
784
|
-
query = {
|
|
785
|
-
"instrument": "LSTN-01",
|
|
786
|
-
"version": "6.0.0",
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
"""
|
|
790
|
-
_collection = self.get_collection(db_name, collection)
|
|
791
|
-
|
|
792
|
-
if "version" in query:
|
|
793
|
-
query["version"] = self.model_version(query["version"])
|
|
794
|
-
|
|
795
|
-
self._logger.info(f"Deleting {_collection.count_documents(query)} entries from {db_name}")
|
|
796
|
-
|
|
797
|
-
_collection.delete_many(query)
|
|
798
|
-
|
|
799
|
-
def update_parameter_field(
|
|
800
|
-
self,
|
|
801
|
-
db_name,
|
|
802
|
-
model_version,
|
|
803
|
-
parameter,
|
|
804
|
-
field,
|
|
805
|
-
new_value,
|
|
806
|
-
array_element_name=None,
|
|
807
|
-
site=None,
|
|
808
|
-
collection_name="telescopes",
|
|
809
|
-
):
|
|
810
|
-
"""
|
|
811
|
-
Update a parameter field value for a specific array element/version.
|
|
812
|
-
|
|
813
|
-
This function only modifies the value of one of the following
|
|
814
|
-
DB entries: Applicable, units, Type, items, minimum, maximum.
|
|
815
|
-
These type of changes should be very rare. However they can
|
|
816
|
-
be done without changing the Object ID of the entry since
|
|
817
|
-
they are generally "harmless".
|
|
818
|
-
|
|
819
|
-
Parameters
|
|
820
|
-
----------
|
|
821
|
-
db_name: str
|
|
822
|
-
the name of the DB
|
|
823
|
-
model_version: str
|
|
824
|
-
Which model version to update
|
|
825
|
-
parameter: str
|
|
826
|
-
Which parameter to update
|
|
827
|
-
field: str
|
|
828
|
-
Field to update (only options are Applicable, units, Type, items, minimum, maximum).
|
|
829
|
-
If the field does not exist, it will be added.
|
|
830
|
-
new_value: type identical to the original field type
|
|
831
|
-
The new value to set to the field given in "field".
|
|
832
|
-
array_element_name: str
|
|
833
|
-
Which array element to update, if None then update a site parameter
|
|
834
|
-
site: str, North or South
|
|
835
|
-
Update a site parameter (the array_element_name argument must be None)
|
|
836
|
-
collection_name: str
|
|
837
|
-
The name of the collection in which to update the parameter.
|
|
838
|
-
|
|
839
|
-
Raises
|
|
840
|
-
------
|
|
841
|
-
ValueError
|
|
842
|
-
if field not in allowed fields
|
|
843
|
-
|
|
844
|
-
"""
|
|
845
|
-
db_name = self._get_db_name(db_name)
|
|
846
|
-
allowed_fields = ["applicable", "unit", "type", "items", "minimum", "maximum"]
|
|
847
|
-
if field not in allowed_fields:
|
|
848
|
-
raise ValueError(f"The field {field} must be one of {', '.join(allowed_fields)}")
|
|
849
|
-
|
|
850
|
-
collection = self.get_collection(db_name, collection_name)
|
|
851
|
-
_model_version = self.model_version(model_version, db_name)
|
|
852
|
-
|
|
853
|
-
query = {
|
|
854
|
-
"version": _model_version,
|
|
855
|
-
"parameter": parameter,
|
|
856
|
-
}
|
|
857
|
-
if array_element_name is not None:
|
|
858
|
-
query["instrument"] = array_element_name
|
|
859
|
-
logger_info = f"instrument {array_element_name}"
|
|
860
|
-
elif site is not None and site in names.site_names():
|
|
861
|
-
query["site"] = site
|
|
862
|
-
logger_info = f"site {site}"
|
|
863
|
-
else:
|
|
864
|
-
raise ValueError("You need to specify an array element or a site.")
|
|
865
|
-
|
|
866
|
-
par_entry = collection.find_one(query)
|
|
867
|
-
if par_entry is None:
|
|
868
|
-
self._logger.warning(
|
|
869
|
-
f"The query {query} did not return any results. I will not make any changes."
|
|
870
|
-
)
|
|
871
|
-
return
|
|
872
|
-
|
|
873
|
-
if field in par_entry:
|
|
874
|
-
old_field_value = par_entry[field]
|
|
875
|
-
|
|
876
|
-
if old_field_value == new_value:
|
|
877
|
-
self._logger.warning(
|
|
878
|
-
f"The value of the field {field} is already {new_value}. No changes necessary"
|
|
879
|
-
)
|
|
880
|
-
return
|
|
881
|
-
|
|
882
|
-
self._logger.info(
|
|
883
|
-
f"For {logger_info}, version {_model_version}, parameter {parameter}, "
|
|
884
|
-
f"replacing field {field} value from {old_field_value} to {new_value}"
|
|
885
|
-
)
|
|
886
|
-
else:
|
|
887
|
-
self._logger.info(
|
|
888
|
-
f"For {logger_info}, version {_model_version}, parameter {parameter}, "
|
|
889
|
-
f"the field {field} does not exist, adding it"
|
|
890
|
-
)
|
|
891
|
-
|
|
892
|
-
query_update = {"$set": {field: new_value}}
|
|
893
|
-
collection.update_one(query, query_update)
|
|
894
|
-
|
|
895
|
-
self._reset_parameter_cache(
|
|
896
|
-
site=(
|
|
897
|
-
site
|
|
898
|
-
if site is not None
|
|
899
|
-
else names.get_site_from_array_element_name(array_element_name)
|
|
900
|
-
),
|
|
901
|
-
array_element_name=array_element_name,
|
|
902
|
-
model_version=_model_version,
|
|
903
|
-
)
|
|
640
|
+
collection = self.get_collection(db_name, "production_tables")
|
|
641
|
+
self._logger.info(f"Adding production for {production_table.get('collection')} to to DB")
|
|
642
|
+
collection.insert_one(production_table)
|
|
643
|
+
DatabaseHandler.production_table_cached.clear()
|
|
904
644
|
|
|
905
645
|
def add_new_parameter(
|
|
906
646
|
self,
|
|
907
647
|
db_name,
|
|
908
|
-
|
|
909
|
-
parameter,
|
|
910
|
-
value,
|
|
911
|
-
array_element_name=None,
|
|
912
|
-
site=None,
|
|
648
|
+
par_dict,
|
|
913
649
|
collection_name="telescopes",
|
|
914
650
|
file_prefix=None,
|
|
915
|
-
**kwargs,
|
|
916
651
|
):
|
|
917
652
|
"""
|
|
918
|
-
Add a parameter
|
|
653
|
+
Add a new parameter dictionary to the DB.
|
|
919
654
|
|
|
920
|
-
A new document will be added to the DB,
|
|
921
|
-
|
|
655
|
+
A new document will be added to the DB, with all fields taken from the input parameters.
|
|
656
|
+
Parameter dictionaries are validated before submission using the corresponding schema.
|
|
922
657
|
|
|
923
658
|
Parameters
|
|
924
659
|
----------
|
|
925
660
|
db_name: str
|
|
926
661
|
the name of the DB
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
parameter: str
|
|
930
|
-
Which parameter to add
|
|
931
|
-
value: can be any type, preferably given in kwargs
|
|
932
|
-
The value to set for the new parameter
|
|
933
|
-
array_element_name: str
|
|
934
|
-
The name of the array element to add a parameter to
|
|
935
|
-
(only used if collection_name is not "sites").
|
|
936
|
-
site: str
|
|
937
|
-
Site name; ignored if collection_name is "telescopes".
|
|
662
|
+
par_dict: dict
|
|
663
|
+
dictionary with parameter data
|
|
938
664
|
collection_name: str
|
|
939
665
|
The name of the collection to add a parameter to.
|
|
940
666
|
file_prefix: str or Path
|
|
941
667
|
where to find files to upload to the DB
|
|
942
|
-
kwargs: dict
|
|
943
|
-
Any additional fields to add to the parameter
|
|
944
|
-
|
|
945
|
-
Raises
|
|
946
|
-
------
|
|
947
|
-
ValueError
|
|
948
|
-
If key to collection_name is not valid.
|
|
949
|
-
|
|
950
668
|
"""
|
|
669
|
+
par_dict = validate_data.DataValidator.validate_model_parameter(par_dict)
|
|
670
|
+
|
|
951
671
|
db_name = self._get_db_name(db_name)
|
|
952
672
|
collection = self.get_collection(db_name, collection_name)
|
|
953
673
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
key in collection_name
|
|
957
|
-
for key in ["telescopes", "calibration_devices", "configuration_sim_telarray"]
|
|
958
|
-
):
|
|
959
|
-
db_entry["instrument"] = names.validate_array_element_name(array_element_name)
|
|
960
|
-
elif "sites" in collection_name:
|
|
961
|
-
db_entry["instrument"] = names.validate_site_name(site)
|
|
962
|
-
elif "configuration_corsika" in collection_name:
|
|
963
|
-
db_entry["instrument"] = None
|
|
964
|
-
else:
|
|
965
|
-
raise ValueError(f"Cannot add parameter to collection {collection_name}")
|
|
966
|
-
|
|
967
|
-
db_entry["version"] = version
|
|
968
|
-
db_entry["parameter"] = parameter
|
|
969
|
-
if site is not None:
|
|
970
|
-
db_entry["site"] = names.validate_site_name(site)
|
|
971
|
-
|
|
972
|
-
_base_value, _base_unit, _base_type = value_conversion.get_value_unit_type(
|
|
973
|
-
value=value, unit_str=kwargs.get("unit", None)
|
|
674
|
+
par_dict["value"], _base_unit, _ = value_conversion.get_value_unit_type(
|
|
675
|
+
value=par_dict["value"], unit_str=par_dict.get("unit", None)
|
|
974
676
|
)
|
|
975
|
-
|
|
976
|
-
if _base_unit is not None:
|
|
977
|
-
db_entry["unit"] = _base_unit
|
|
978
|
-
db_entry["type"] = kwargs["type"] if "type" in kwargs else _base_type
|
|
677
|
+
par_dict["unit"] = _base_unit if _base_unit else None
|
|
979
678
|
|
|
980
679
|
files_to_add_to_db = set()
|
|
981
|
-
|
|
982
|
-
if self._is_file(value):
|
|
983
|
-
db_entry["file"] = True
|
|
680
|
+
if par_dict["file"] and par_dict["value"]:
|
|
984
681
|
if file_prefix is None:
|
|
985
682
|
raise FileNotFoundError(
|
|
986
683
|
"The location of the file to upload, "
|
|
987
|
-
f"corresponding to the {parameter} parameter, must be provided."
|
|
684
|
+
f"corresponding to the {par_dict['parameter']} parameter, must be provided."
|
|
988
685
|
)
|
|
989
|
-
file_path = Path(file_prefix).joinpath(value)
|
|
686
|
+
file_path = Path(file_prefix).joinpath(par_dict["value"])
|
|
990
687
|
files_to_add_to_db.add(f"{file_path}")
|
|
991
688
|
|
|
992
|
-
kwargs.pop("type", None)
|
|
993
|
-
db_entry.update(kwargs)
|
|
994
|
-
|
|
995
689
|
self._logger.info(
|
|
996
|
-
f"
|
|
690
|
+
f"Adding a new entry to DB {db_name} and collection {db_name}:\n{par_dict}"
|
|
997
691
|
)
|
|
692
|
+
collection.insert_one(par_dict)
|
|
998
693
|
|
|
999
|
-
collection.insert_one(db_entry)
|
|
1000
694
|
for file_to_insert_now in files_to_add_to_db:
|
|
1001
695
|
self._logger.info(f"Will also add the file {file_to_insert_now} to the DB")
|
|
1002
696
|
self.insert_file_to_db(file_to_insert_now, db_name)
|
|
1003
697
|
|
|
1004
|
-
self._reset_parameter_cache(
|
|
698
|
+
self._reset_parameter_cache()
|
|
1005
699
|
|
|
1006
700
|
def _get_db_name(self, db_name=None):
|
|
1007
701
|
"""
|
|
@@ -1019,42 +713,6 @@ class DatabaseHandler:
|
|
|
1019
713
|
"""
|
|
1020
714
|
return self.mongo_db_config["db_simulation_model"] if db_name is None else db_name
|
|
1021
715
|
|
|
1022
|
-
def model_version(self, version, db_name=None):
|
|
1023
|
-
"""
|
|
1024
|
-
Return model version and check that it is valid.
|
|
1025
|
-
|
|
1026
|
-
Queries the database for all available model versions and check if the
|
|
1027
|
-
requested version is valid.
|
|
1028
|
-
|
|
1029
|
-
Parameters
|
|
1030
|
-
----------
|
|
1031
|
-
version : str
|
|
1032
|
-
Model version.
|
|
1033
|
-
db_name : str
|
|
1034
|
-
Database name.
|
|
1035
|
-
|
|
1036
|
-
Returns
|
|
1037
|
-
-------
|
|
1038
|
-
str
|
|
1039
|
-
Model version.
|
|
1040
|
-
|
|
1041
|
-
Raises
|
|
1042
|
-
------
|
|
1043
|
-
ValueError
|
|
1044
|
-
if version not valid.
|
|
1045
|
-
|
|
1046
|
-
"""
|
|
1047
|
-
_all_versions = self.get_all_versions(db_name=db_name)
|
|
1048
|
-
if version in _all_versions:
|
|
1049
|
-
return version
|
|
1050
|
-
if len(_all_versions) == 0:
|
|
1051
|
-
return None
|
|
1052
|
-
|
|
1053
|
-
raise ValueError(
|
|
1054
|
-
f"Invalid model version {version} in DB {self._get_db_name(db_name)} "
|
|
1055
|
-
f"(allowed are {_all_versions})"
|
|
1056
|
-
)
|
|
1057
|
-
|
|
1058
716
|
def insert_file_to_db(self, file_name, db_name=None, **kwargs):
|
|
1059
717
|
"""
|
|
1060
718
|
Insert a file to the DB.
|
|
@@ -1078,15 +736,11 @@ class DatabaseHandler:
|
|
|
1078
736
|
|
|
1079
737
|
"""
|
|
1080
738
|
db_name = self._get_db_name(db_name)
|
|
1081
|
-
|
|
1082
739
|
db = DatabaseHandler.db_client[db_name]
|
|
1083
740
|
file_system = gridfs.GridFS(db)
|
|
1084
741
|
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
if "filename" not in kwargs:
|
|
1089
|
-
kwargs["filename"] = Path(file_name).name
|
|
742
|
+
kwargs.setdefault("content_type", "ascii/dat")
|
|
743
|
+
kwargs.setdefault("filename", Path(file_name).name)
|
|
1090
744
|
|
|
1091
745
|
if file_system.exists({"filename": kwargs["filename"]}):
|
|
1092
746
|
self._logger.warning(
|
|
@@ -1095,78 +749,11 @@ class DatabaseHandler:
|
|
|
1095
749
|
return file_system.find_one( # pylint: disable=protected-access
|
|
1096
750
|
{"filename": kwargs["filename"]}
|
|
1097
751
|
)._id
|
|
752
|
+
self._logger.debug(f"Writing file to DB: {file_name}")
|
|
1098
753
|
with open(file_name, "rb") as data_file:
|
|
1099
754
|
return file_system.put(data_file, **kwargs)
|
|
1100
755
|
|
|
1101
|
-
def
|
|
1102
|
-
self,
|
|
1103
|
-
parameter=None,
|
|
1104
|
-
array_element_name=None,
|
|
1105
|
-
site=None,
|
|
1106
|
-
db_name=None,
|
|
1107
|
-
collection=None,
|
|
1108
|
-
):
|
|
1109
|
-
"""
|
|
1110
|
-
Get all version entries in the DB of collection and/or a specific parameter.
|
|
1111
|
-
|
|
1112
|
-
Parameters
|
|
1113
|
-
----------
|
|
1114
|
-
parameter: str
|
|
1115
|
-
Which parameter to get the versions of
|
|
1116
|
-
array_element_name: str
|
|
1117
|
-
Which array element to get the versions of (in case "collection_name" is not "sites")
|
|
1118
|
-
site: str
|
|
1119
|
-
Site name.
|
|
1120
|
-
db_name: str
|
|
1121
|
-
Database name.
|
|
1122
|
-
collection_name: str
|
|
1123
|
-
The name of the collection in which to update the parameter.
|
|
1124
|
-
|
|
1125
|
-
Returns
|
|
1126
|
-
-------
|
|
1127
|
-
all_versions: list
|
|
1128
|
-
List of all versions found
|
|
1129
|
-
|
|
1130
|
-
Raises
|
|
1131
|
-
------
|
|
1132
|
-
ValueError
|
|
1133
|
-
If key to collection_name is not valid.
|
|
1134
|
-
|
|
1135
|
-
"""
|
|
1136
|
-
db_name = self._get_db_name() if db_name is None else db_name
|
|
1137
|
-
if not db_name:
|
|
1138
|
-
self._logger.warning("No database name defined to determine list of model versions")
|
|
1139
|
-
return []
|
|
1140
|
-
_cache_key = f"model_versions_{db_name}-{collection}"
|
|
1141
|
-
|
|
1142
|
-
query = {}
|
|
1143
|
-
if parameter is not None:
|
|
1144
|
-
query["parameter"] = parameter
|
|
1145
|
-
_cache_key = f"{_cache_key}-{parameter}"
|
|
1146
|
-
if collection in ["telescopes", "calibration_devices"] and array_element_name is not None:
|
|
1147
|
-
query["instrument"] = names.validate_array_element_name(array_element_name)
|
|
1148
|
-
_cache_key = f"{_cache_key}-{query['instrument']}"
|
|
1149
|
-
elif collection == "sites" and site is not None:
|
|
1150
|
-
query["site"] = names.validate_site_name(site)
|
|
1151
|
-
_cache_key = f"{_cache_key}-{query['site']}"
|
|
1152
|
-
|
|
1153
|
-
if _cache_key not in DatabaseHandler.model_versions_cached:
|
|
1154
|
-
all_versions = set()
|
|
1155
|
-
collections_to_query = (
|
|
1156
|
-
[collection] if collection else self.get_collections(db_name, True)
|
|
1157
|
-
)
|
|
1158
|
-
for collection_name in collections_to_query:
|
|
1159
|
-
db_collection = self.get_collection(db_name, collection_name)
|
|
1160
|
-
sorted_posts = db_collection.find(query).sort("version", ASCENDING)
|
|
1161
|
-
all_versions.update(post["version"] for post in sorted_posts)
|
|
1162
|
-
DatabaseHandler.model_versions_cached[_cache_key] = list(all_versions)
|
|
1163
|
-
|
|
1164
|
-
if len(DatabaseHandler.model_versions_cached[_cache_key]) == 0:
|
|
1165
|
-
self._logger.warning(f"The query {query} did not return any results. No versions found")
|
|
1166
|
-
|
|
1167
|
-
return DatabaseHandler.model_versions_cached[_cache_key]
|
|
1168
|
-
|
|
1169
|
-
def _parameter_cache_key(self, site, array_element_name, model_version, collection=None):
|
|
756
|
+
def _cache_key(self, site=None, array_element_name=None, model_version=None, collection=None):
|
|
1170
757
|
"""
|
|
1171
758
|
Create a cache key for the parameter cache dictionaries.
|
|
1172
759
|
|
|
@@ -1186,61 +773,79 @@ class DatabaseHandler:
|
|
|
1186
773
|
str
|
|
1187
774
|
Cache key.
|
|
1188
775
|
"""
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
parts.append(collection)
|
|
1197
|
-
return "-".join(parts)
|
|
1198
|
-
|
|
1199
|
-
def _reset_parameter_cache(self, site, array_element_name, model_version):
|
|
776
|
+
return "-".join(
|
|
777
|
+
part for part in [model_version, collection, site, array_element_name] if part
|
|
778
|
+
)
|
|
779
|
+
|
|
780
|
+
def _read_cache(
|
|
781
|
+
self, cache_dict, site=None, array_element_name=None, model_version=None, collection=None
|
|
782
|
+
):
|
|
1200
783
|
"""
|
|
1201
|
-
|
|
784
|
+
Read parameters from cache.
|
|
1202
785
|
|
|
1203
786
|
Parameters
|
|
1204
787
|
----------
|
|
788
|
+
cache_dict: dict
|
|
789
|
+
Cache dictionary.
|
|
1205
790
|
site: str
|
|
1206
791
|
Site name.
|
|
1207
792
|
array_element_name: str
|
|
1208
793
|
Array element name.
|
|
1209
794
|
model_version: str
|
|
1210
795
|
Model version.
|
|
796
|
+
collection: str
|
|
797
|
+
DB collection name.
|
|
798
|
+
|
|
799
|
+
Returns
|
|
800
|
+
-------
|
|
801
|
+
str
|
|
802
|
+
Cache key.
|
|
1211
803
|
"""
|
|
1212
|
-
self.
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
804
|
+
cache_key = self._cache_key(site, array_element_name, model_version, collection)
|
|
805
|
+
try:
|
|
806
|
+
return cache_key, cache_dict[cache_key]
|
|
807
|
+
except KeyError:
|
|
808
|
+
return cache_key, None
|
|
1217
809
|
|
|
1218
|
-
def
|
|
810
|
+
def _reset_parameter_cache(self):
|
|
811
|
+
"""Reset the cache for the parameters."""
|
|
812
|
+
DatabaseHandler.model_parameters_cached.clear()
|
|
813
|
+
|
|
814
|
+
def _get_array_element_list(self, array_element_name, site, production_table, collection):
|
|
1219
815
|
"""
|
|
1220
|
-
|
|
816
|
+
Return list of array elements for DB queries (add design model if needed).
|
|
817
|
+
|
|
818
|
+
Design model is added if found in the production table.
|
|
1221
819
|
|
|
1222
820
|
Parameters
|
|
1223
821
|
----------
|
|
1224
|
-
|
|
1225
|
-
|
|
822
|
+
array_element_name: str
|
|
823
|
+
Name of the array element.
|
|
824
|
+
site: str
|
|
825
|
+
Site name.
|
|
826
|
+
production_table: dict
|
|
827
|
+
Production table.
|
|
828
|
+
collection: str
|
|
829
|
+
collection of array element (e.g. telescopes, calibration_devices).
|
|
1226
830
|
|
|
1227
831
|
Returns
|
|
1228
832
|
-------
|
|
1229
833
|
list
|
|
1230
|
-
List of
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
""
|
|
1235
|
-
|
|
1236
|
-
if
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
834
|
+
List of array elements
|
|
835
|
+
"""
|
|
836
|
+
if collection == "configuration_corsika":
|
|
837
|
+
return ["xSTx-design"] # placeholder to ignore 'instrument' field in query.
|
|
838
|
+
if collection == "sites":
|
|
839
|
+
return [f"OBS-{site}"]
|
|
840
|
+
if "-design" in array_element_name:
|
|
841
|
+
return [array_element_name]
|
|
842
|
+
try:
|
|
843
|
+
return [
|
|
844
|
+
production_table["design_model"][array_element_name],
|
|
845
|
+
array_element_name,
|
|
846
|
+
]
|
|
847
|
+
except KeyError:
|
|
1241
848
|
return [
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
if not collection.startswith("fs.") and collection != "metadata"
|
|
849
|
+
f"{names.get_array_element_type_from_name(array_element_name)}-design",
|
|
850
|
+
array_element_name,
|
|
1245
851
|
]
|
|
1246
|
-
return self.list_of_collections[db_name]
|