gammasimtools 0.9.0__py3-none-any.whl → 0.11.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.9.0.dist-info → gammasimtools-0.11.0.dist-info}/METADATA +4 -2
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/RECORD +133 -117
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/entry_points.txt +6 -1
- simtools/_version.py +9 -4
- simtools/applications/calculate_trigger_rate.py +15 -38
- simtools/applications/convert_all_model_parameters_from_simtel.py +9 -29
- simtools/applications/convert_geo_coordinates_of_array_elements.py +47 -45
- simtools/applications/convert_model_parameter_from_simtel.py +2 -3
- simtools/applications/db_add_file_to_db.py +1 -3
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +110 -0
- simtools/applications/db_add_value_from_json_to_db.py +1 -2
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +6 -6
- simtools/applications/db_get_file_from_db.py +11 -12
- simtools/applications/db_get_parameter_from_db.py +26 -35
- simtools/applications/derive_mirror_rnda.py +1 -2
- simtools/applications/derive_photon_electron_spectrum.py +99 -0
- simtools/applications/derive_psf_parameters.py +1 -0
- simtools/applications/docs_produce_array_element_report.py +71 -0
- simtools/applications/docs_produce_model_parameter_reports.py +63 -0
- simtools/applications/generate_array_config.py +17 -17
- simtools/applications/generate_corsika_histograms.py +2 -2
- simtools/applications/generate_regular_arrays.py +19 -17
- simtools/applications/generate_simtel_array_histograms.py +11 -48
- simtools/applications/production_derive_limits.py +95 -0
- simtools/applications/production_generate_simulation_config.py +37 -33
- simtools/applications/production_scale_events.py +4 -9
- simtools/applications/run_application.py +165 -0
- simtools/applications/simulate_light_emission.py +0 -4
- simtools/applications/simulate_prod.py +1 -1
- simtools/applications/simulate_prod_htcondor_generator.py +26 -26
- simtools/applications/submit_data_from_external.py +12 -4
- simtools/applications/submit_model_parameter_from_external.py +18 -11
- simtools/applications/validate_camera_efficiency.py +2 -2
- simtools/applications/validate_file_using_schema.py +26 -22
- simtools/camera/single_photon_electron_spectrum.py +168 -0
- simtools/configuration/commandline_parser.py +37 -1
- simtools/configuration/configurator.py +8 -10
- simtools/constants.py +10 -3
- simtools/corsika/corsika_config.py +19 -17
- simtools/corsika/corsika_histograms.py +5 -7
- simtools/corsika/corsika_histograms_visualize.py +2 -4
- simtools/data_model/data_reader.py +0 -3
- simtools/data_model/metadata_collector.py +20 -12
- simtools/data_model/metadata_model.py +8 -124
- simtools/data_model/model_data_writer.py +81 -75
- simtools/data_model/schema.py +220 -0
- simtools/data_model/validate_data.py +79 -68
- simtools/db/db_handler.py +350 -492
- simtools/db/db_model_upload.py +139 -0
- simtools/dependencies.py +112 -0
- simtools/io_operations/hdf5_handler.py +54 -24
- simtools/layout/array_layout.py +38 -32
- simtools/model/array_model.py +13 -7
- simtools/model/model_parameter.py +55 -54
- simtools/model/site_model.py +2 -2
- simtools/production_configuration/calculate_statistical_errors_grid_point.py +119 -145
- simtools/production_configuration/event_scaler.py +9 -35
- simtools/production_configuration/generate_simulation_config.py +9 -44
- simtools/production_configuration/interpolation_handler.py +9 -15
- simtools/production_configuration/limits_calculation.py +202 -0
- simtools/reporting/docs_read_parameters.py +310 -0
- simtools/runners/corsika_simtel_runner.py +4 -4
- simtools/schemas/{integration_tests_config.metaschema.yml → application_workflow.metaschema.yml} +61 -27
- simtools/schemas/array_elements.yml +8 -0
- simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +39 -0
- simtools/schemas/input/single_pe_spectrum.schema.yml +38 -0
- simtools/schemas/model_parameter.metaschema.yml +103 -2
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +4 -1
- 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/correct_nsb_spectrum_to_telescope_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +4 -2
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +2 -0
- 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/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/iobuf_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_photons.schema.yml +2 -2
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/random_generator.schema.yml +1 -1
- simtools/schemas/model_parameters/sampled_output.schema.yml +1 -1
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/tailcut_scale.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_reader.py +1 -2
- simtools/simtel/simtel_config_writer.py +6 -8
- simtools/simtel/simtel_io_histogram.py +32 -68
- simtools/simtel/simtel_io_histograms.py +17 -34
- simtools/simtel/simulator_array.py +2 -1
- simtools/simtel/simulator_camera_efficiency.py +6 -3
- simtools/simtel/simulator_light_emission.py +5 -6
- simtools/simtel/simulator_ray_tracing.py +3 -4
- simtools/testing/configuration.py +2 -1
- simtools/testing/helpers.py +6 -13
- simtools/testing/validate_output.py +141 -47
- simtools/utils/general.py +114 -14
- simtools/utils/names.py +299 -157
- simtools/utils/value_conversion.py +17 -13
- simtools/version.py +2 -2
- simtools/visualization/legend_handlers.py +2 -0
- simtools/applications/db_add_model_parameters_from_repository_to_db.py +0 -176
- simtools/db/db_array_elements.py +0 -130
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/LICENSE +0 -0
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/top_level.txt +0 -0
- /simtools/{camera_efficiency.py → camera/camera_efficiency.py} +0 -0
simtools/db/db_handler.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
5
|
-
from importlib.resources import files
|
|
6
5
|
from pathlib import Path
|
|
7
6
|
from threading import Lock
|
|
8
7
|
|
|
@@ -10,11 +9,9 @@ import gridfs
|
|
|
10
9
|
import jsonschema
|
|
11
10
|
from bson.objectid import ObjectId
|
|
12
11
|
from packaging.version import Version
|
|
13
|
-
from pymongo import
|
|
14
|
-
from pymongo.errors import BulkWriteError
|
|
12
|
+
from pymongo import MongoClient
|
|
15
13
|
|
|
16
14
|
from simtools.data_model import validate_data
|
|
17
|
-
from simtools.db import db_array_elements
|
|
18
15
|
from simtools.io_operations import io_handler
|
|
19
16
|
from simtools.utils import names, value_conversion
|
|
20
17
|
|
|
@@ -66,17 +63,11 @@ class DatabaseHandler:
|
|
|
66
63
|
Dictionary with the MongoDB configuration (see jsonschema_db_dict for details).
|
|
67
64
|
"""
|
|
68
65
|
|
|
69
|
-
DB_CTA_SIMULATION_MODEL_DESCRIPTIONS = "CTA-Simulation-Model-Descriptions"
|
|
70
|
-
# DB collection with updates field names
|
|
71
|
-
DB_DERIVED_VALUES = "Staging-CTA-Simulation-Model-Derived-Values"
|
|
72
|
-
|
|
73
66
|
ALLOWED_FILE_EXTENSIONS = [".dat", ".txt", ".lis", ".cfg", ".yml", ".yaml", ".ecsv"]
|
|
74
67
|
|
|
75
68
|
db_client = None
|
|
76
|
-
|
|
69
|
+
production_table_cached = {}
|
|
77
70
|
model_parameters_cached = {}
|
|
78
|
-
model_versions_cached = {}
|
|
79
|
-
corsika_configuration_parameters_cached = {}
|
|
80
71
|
|
|
81
72
|
def __init__(self, mongo_db_config=None):
|
|
82
73
|
"""Initialize the DatabaseHandler class."""
|
|
@@ -150,12 +141,13 @@ class DatabaseHandler:
|
|
|
150
141
|
|
|
151
142
|
"""
|
|
152
143
|
try:
|
|
153
|
-
|
|
144
|
+
db_simulation_model = self.mongo_db_config["db_simulation_model"]
|
|
145
|
+
if not db_simulation_model.endswith("LATEST"):
|
|
154
146
|
return
|
|
155
|
-
except TypeError:
|
|
147
|
+
except TypeError: # db_simulation_model is None
|
|
156
148
|
return
|
|
157
149
|
|
|
158
|
-
prefix =
|
|
150
|
+
prefix = db_simulation_model.replace("LATEST", "")
|
|
159
151
|
list_of_db_names = self.db_client.list_database_names()
|
|
160
152
|
filtered_list_of_db_names = [s for s in list_of_db_names if s.startswith(prefix)]
|
|
161
153
|
versioned_strings = []
|
|
@@ -180,69 +172,116 @@ class DatabaseHandler:
|
|
|
180
172
|
else:
|
|
181
173
|
raise ValueError("Found LATEST in the DB name but no matching versions found in DB.")
|
|
182
174
|
|
|
175
|
+
def get_model_parameter(
|
|
176
|
+
self,
|
|
177
|
+
parameter,
|
|
178
|
+
parameter_version,
|
|
179
|
+
site,
|
|
180
|
+
array_element_name,
|
|
181
|
+
):
|
|
182
|
+
"""
|
|
183
|
+
Get a model parameter using the parameter version.
|
|
184
|
+
|
|
185
|
+
Parameters
|
|
186
|
+
----------
|
|
187
|
+
parameter: str
|
|
188
|
+
Name of the parameter.
|
|
189
|
+
parameter_version: str
|
|
190
|
+
Version of the parameter.
|
|
191
|
+
site: str
|
|
192
|
+
Site name.
|
|
193
|
+
array_element_name: str
|
|
194
|
+
Name of the array element model (e.g. MSTN, SSTS).
|
|
195
|
+
|
|
196
|
+
Returns
|
|
197
|
+
-------
|
|
198
|
+
dict containing the parameter
|
|
199
|
+
|
|
200
|
+
"""
|
|
201
|
+
query = {
|
|
202
|
+
"parameter_version": parameter_version,
|
|
203
|
+
"parameter": parameter,
|
|
204
|
+
}
|
|
205
|
+
if array_element_name is not None:
|
|
206
|
+
query["instrument"] = array_element_name
|
|
207
|
+
if site is not None:
|
|
208
|
+
query["site"] = site
|
|
209
|
+
return self._read_mongo_db(
|
|
210
|
+
query=query, collection_name=names.get_collection_name_from_parameter_name(parameter)
|
|
211
|
+
)
|
|
212
|
+
|
|
183
213
|
def get_model_parameters(
|
|
184
214
|
self,
|
|
185
215
|
site,
|
|
186
216
|
array_element_name,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
only_applicable=False,
|
|
217
|
+
collection,
|
|
218
|
+
model_version=None,
|
|
190
219
|
):
|
|
191
220
|
"""
|
|
192
|
-
Get parameters
|
|
221
|
+
Get model parameters using the model version.
|
|
193
222
|
|
|
194
|
-
|
|
195
|
-
Read parameters for design and for the specified array element (if necessary). This allows
|
|
196
|
-
to overwrite design parameters with specific parameters without having to copy
|
|
197
|
-
all model parameters when changing only a few.
|
|
223
|
+
Queries parameters for design and for the specified array element (if necessary).
|
|
198
224
|
|
|
199
225
|
Parameters
|
|
200
226
|
----------
|
|
201
227
|
site: str
|
|
202
228
|
Site name.
|
|
203
229
|
array_element_name: str
|
|
204
|
-
Name of the array element model (e.g. LSTN-01,
|
|
205
|
-
model_version: str
|
|
206
|
-
Version of the model.
|
|
230
|
+
Name of the array element model (e.g. LSTN-01, MSTx-FlashCam, ILLN-01).
|
|
231
|
+
model_version: str, list
|
|
232
|
+
Version(s) of the model.
|
|
207
233
|
collection: str
|
|
208
|
-
|
|
209
|
-
only_applicable: bool
|
|
210
|
-
If True, only applicable parameters will be read.
|
|
234
|
+
Collection of array element (e.g. telescopes, calibration_devices).
|
|
211
235
|
|
|
212
236
|
Returns
|
|
213
237
|
-------
|
|
214
238
|
dict containing the parameters
|
|
215
|
-
|
|
216
239
|
"""
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
)
|
|
220
|
-
array_element_list = db_array_elements.get_array_element_list_for_db_query(
|
|
221
|
-
_array_element_name, self, _model_version, collection
|
|
240
|
+
model_versions = (
|
|
241
|
+
self.get_model_versions(collection) if model_version is None else [model_version]
|
|
222
242
|
)
|
|
243
|
+
|
|
223
244
|
pars = {}
|
|
224
|
-
for
|
|
225
|
-
|
|
226
|
-
|
|
245
|
+
for _model_version in model_versions:
|
|
246
|
+
production_table = self._read_production_table_from_mongo_db(collection, _model_version)
|
|
247
|
+
array_element_list = self._get_array_element_list(
|
|
248
|
+
array_element_name, site, production_table, collection
|
|
227
249
|
)
|
|
228
|
-
|
|
229
|
-
pars.update(DatabaseHandler.model_parameters_cached[_array_elements_cache_key])
|
|
230
|
-
except KeyError:
|
|
250
|
+
for array_element in array_element_list:
|
|
231
251
|
pars.update(
|
|
232
|
-
self.
|
|
233
|
-
|
|
234
|
-
array_element_name=array_element,
|
|
235
|
-
model_version=_model_version,
|
|
236
|
-
collection_name=collection,
|
|
237
|
-
run_location=None,
|
|
238
|
-
write_files=False,
|
|
239
|
-
only_applicable=only_applicable,
|
|
252
|
+
self._get_parameter_for_model_version(
|
|
253
|
+
array_element, _model_version, site, collection, production_table
|
|
240
254
|
)
|
|
241
255
|
)
|
|
242
|
-
DatabaseHandler.model_parameters_cached[_array_elements_cache_key] = pars
|
|
243
|
-
|
|
244
256
|
return pars
|
|
245
257
|
|
|
258
|
+
def _get_parameter_for_model_version(
|
|
259
|
+
self, array_element, model_version, site, collection, production_table
|
|
260
|
+
):
|
|
261
|
+
cache_key, cache_dict = self._read_cache(
|
|
262
|
+
DatabaseHandler.model_parameters_cached,
|
|
263
|
+
names.validate_site_name(site) if site else None,
|
|
264
|
+
array_element,
|
|
265
|
+
model_version,
|
|
266
|
+
collection,
|
|
267
|
+
)
|
|
268
|
+
if cache_dict:
|
|
269
|
+
self._logger.debug(f"Found {array_element} in cache (key: {cache_key})")
|
|
270
|
+
return cache_dict
|
|
271
|
+
self._logger.debug(f"Did not find {array_element} in cache (key: {cache_key})")
|
|
272
|
+
|
|
273
|
+
try:
|
|
274
|
+
parameter_version_table = production_table["parameters"][array_element]
|
|
275
|
+
except KeyError: # allow missing array elements (parameter dict is checked later)
|
|
276
|
+
return {}
|
|
277
|
+
DatabaseHandler.model_parameters_cached[cache_key] = self._read_mongo_db(
|
|
278
|
+
query=self._get_query_from_parameter_version_table(
|
|
279
|
+
parameter_version_table, array_element, site
|
|
280
|
+
),
|
|
281
|
+
collection_name=collection,
|
|
282
|
+
)
|
|
283
|
+
return DatabaseHandler.model_parameters_cached[cache_key]
|
|
284
|
+
|
|
246
285
|
def get_collection(self, db_name, collection_name):
|
|
247
286
|
"""
|
|
248
287
|
Get a collection from the DB.
|
|
@@ -263,99 +302,102 @@ class DatabaseHandler:
|
|
|
263
302
|
db_name = self._get_db_name(db_name)
|
|
264
303
|
return DatabaseHandler.db_client[db_name][collection_name]
|
|
265
304
|
|
|
266
|
-
def
|
|
305
|
+
def get_collections(self, db_name=None, model_collections_only=False):
|
|
267
306
|
"""
|
|
268
|
-
|
|
307
|
+
List of collections in the DB.
|
|
269
308
|
|
|
270
309
|
Parameters
|
|
271
310
|
----------
|
|
272
311
|
db_name: str
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
file_name: str
|
|
277
|
-
Name of the file to get.
|
|
312
|
+
Database name.
|
|
313
|
+
model_collections_only: bool
|
|
314
|
+
If True, only return model collections (i.e. exclude fs.files, fs.chunks)
|
|
278
315
|
|
|
279
316
|
Returns
|
|
280
317
|
-------
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
Raises
|
|
285
|
-
------
|
|
286
|
-
FileNotFoundError
|
|
287
|
-
If the desired file is not found.
|
|
318
|
+
list
|
|
319
|
+
List of collection names
|
|
288
320
|
|
|
289
321
|
"""
|
|
290
|
-
db_name = self._get_db_name(
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
322
|
+
db_name = db_name or self._get_db_name()
|
|
323
|
+
if db_name not in self.list_of_collections:
|
|
324
|
+
self.list_of_collections[db_name] = DatabaseHandler.db_client[
|
|
325
|
+
db_name
|
|
326
|
+
].list_collection_names()
|
|
327
|
+
collections = self.list_of_collections[db_name]
|
|
328
|
+
if model_collections_only:
|
|
329
|
+
return [collection for collection in collections if not collection.startswith("fs.")]
|
|
330
|
+
return collections
|
|
296
331
|
|
|
297
|
-
def export_model_files(self, parameters, dest):
|
|
332
|
+
def export_model_files(self, parameters=None, file_names=None, dest=None, db_name=None):
|
|
298
333
|
"""
|
|
299
|
-
Export
|
|
334
|
+
Export files from the DB to the model directory.
|
|
335
|
+
|
|
336
|
+
The files to be exported can be specified by file_name or retrieved from the database
|
|
337
|
+
using the parameters dictionary.
|
|
300
338
|
|
|
301
339
|
Parameters
|
|
302
340
|
----------
|
|
303
341
|
parameters: dict
|
|
304
|
-
Dict of model parameters
|
|
342
|
+
Dict of model parameters
|
|
343
|
+
file_names: list, str
|
|
344
|
+
List (or string) of file names to export
|
|
305
345
|
dest: str or Path
|
|
306
346
|
Location where to write the files to.
|
|
307
347
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
348
|
+
Returns
|
|
349
|
+
-------
|
|
350
|
+
file_id: dict of GridOut._id
|
|
351
|
+
Dict of database IDs of files.
|
|
313
352
|
"""
|
|
314
|
-
|
|
315
|
-
for info in parameters.values():
|
|
316
|
-
if not info or not info.get("file") or info["value"] is None:
|
|
317
|
-
continue
|
|
318
|
-
if Path(dest).joinpath(info["value"]).exists():
|
|
319
|
-
continue
|
|
320
|
-
file = self._get_file_mongo_db(self._get_db_name(), info["value"])
|
|
321
|
-
self._write_file_from_mongo_to_disk(self._get_db_name(), dest, file)
|
|
353
|
+
db_name = self._get_db_name(db_name)
|
|
322
354
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
355
|
+
if file_names:
|
|
356
|
+
file_names = [file_names] if not isinstance(file_names, list) else file_names
|
|
357
|
+
elif parameters:
|
|
358
|
+
file_names = [
|
|
359
|
+
info["value"]
|
|
360
|
+
for info in parameters.values()
|
|
361
|
+
if info and info.get("file") and info["value"] is not None
|
|
362
|
+
]
|
|
327
363
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
364
|
+
instance_ids = {}
|
|
365
|
+
for file_name in file_names:
|
|
366
|
+
if Path(dest).joinpath(file_name).exists():
|
|
367
|
+
instance_ids[file_name] = "file exists"
|
|
368
|
+
else:
|
|
369
|
+
file_path_instance = self._get_file_mongo_db(self._get_db_name(), file_name)
|
|
370
|
+
self._write_file_from_mongo_to_disk(self._get_db_name(), dest, file_path_instance)
|
|
371
|
+
instance_ids[file_name] = file_path_instance._id # pylint: disable=protected-access
|
|
372
|
+
return instance_ids
|
|
373
|
+
|
|
374
|
+
def _get_query_from_parameter_version_table(
|
|
375
|
+
self, parameter_version_table, array_element_name, site
|
|
337
376
|
):
|
|
338
|
-
"""
|
|
339
|
-
|
|
377
|
+
"""Return query based on parameter version table."""
|
|
378
|
+
query_dict = {
|
|
379
|
+
"$or": [
|
|
380
|
+
{"parameter": param, "parameter_version": version}
|
|
381
|
+
for param, version in parameter_version_table.items()
|
|
382
|
+
],
|
|
383
|
+
}
|
|
384
|
+
# 'xSTX-design' is a placeholder to ignore 'instrument' field in query.
|
|
385
|
+
if array_element_name and array_element_name != "xSTx-design":
|
|
386
|
+
query_dict["instrument"] = array_element_name
|
|
387
|
+
if site:
|
|
388
|
+
query_dict["site"] = site
|
|
389
|
+
return query_dict
|
|
340
390
|
|
|
341
|
-
|
|
391
|
+
def _read_mongo_db(self, query, collection_name):
|
|
392
|
+
"""
|
|
393
|
+
Query MongoDB.
|
|
342
394
|
|
|
343
395
|
Parameters
|
|
344
396
|
----------
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
array_element_name: str
|
|
348
|
-
Name of the array element model (e.g. MSTN-design ...)
|
|
349
|
-
model_version: str
|
|
350
|
-
Version of the model.
|
|
351
|
-
run_location: Path or str
|
|
352
|
-
The sim_telarray run location to write the tabulated data files into.
|
|
397
|
+
query: dict
|
|
398
|
+
Query to execute.
|
|
353
399
|
collection_name: str
|
|
354
|
-
|
|
355
|
-
write_files: bool
|
|
356
|
-
If true, write the files to the run_location.
|
|
357
|
-
only_applicable: bool
|
|
358
|
-
If True, only applicable parameters will be read.
|
|
400
|
+
Collection name.
|
|
359
401
|
|
|
360
402
|
Returns
|
|
361
403
|
-------
|
|
@@ -364,154 +406,153 @@ class DatabaseHandler:
|
|
|
364
406
|
Raises
|
|
365
407
|
------
|
|
366
408
|
ValueError
|
|
367
|
-
if query returned
|
|
368
|
-
|
|
409
|
+
if query returned no results.
|
|
369
410
|
"""
|
|
411
|
+
db_name = self._get_db_name()
|
|
370
412
|
collection = self.get_collection(db_name, collection_name)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
query = {
|
|
374
|
-
"instrument": array_element_name,
|
|
375
|
-
"version": self.model_version(model_version, db_name),
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
if only_applicable:
|
|
379
|
-
query["applicable"] = True
|
|
380
|
-
if collection.count_documents(query) < 1:
|
|
413
|
+
posts = list(collection.find(query))
|
|
414
|
+
if not posts:
|
|
381
415
|
raise ValueError(
|
|
382
|
-
"The following query returned zero results
|
|
383
|
-
query,
|
|
416
|
+
f"The following query for {collection_name} returned zero results: {query} "
|
|
384
417
|
)
|
|
385
|
-
|
|
418
|
+
parameters = {}
|
|
419
|
+
for post in posts:
|
|
386
420
|
par_now = post["parameter"]
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
_parameters[par_now]["entry_date"] = ObjectId(post["_id"]).generation_time
|
|
391
|
-
if _parameters[par_now]["file"] and write_files:
|
|
392
|
-
file = self._get_file_mongo_db(db_name, _parameters[par_now]["value"])
|
|
393
|
-
self._write_file_from_mongo_to_disk(db_name, run_location, file)
|
|
394
|
-
|
|
395
|
-
return _parameters
|
|
421
|
+
parameters[par_now] = post
|
|
422
|
+
parameters[par_now]["entry_date"] = ObjectId(post["_id"]).generation_time
|
|
423
|
+
return {k: parameters[k] for k in sorted(parameters)}
|
|
396
424
|
|
|
397
|
-
def
|
|
398
|
-
self,
|
|
399
|
-
site,
|
|
400
|
-
model_version,
|
|
401
|
-
only_applicable=False,
|
|
402
|
-
):
|
|
425
|
+
def _read_production_table_from_mongo_db(self, collection_name, model_version):
|
|
403
426
|
"""
|
|
404
|
-
|
|
427
|
+
Read production table from MongoDB.
|
|
405
428
|
|
|
406
429
|
Parameters
|
|
407
430
|
----------
|
|
408
|
-
|
|
409
|
-
|
|
431
|
+
collection_name: str
|
|
432
|
+
Name of the collection.
|
|
410
433
|
model_version: str
|
|
411
434
|
Version of the model.
|
|
412
|
-
only_applicable: bool
|
|
413
|
-
If True, only applicable parameters will be read.
|
|
414
|
-
|
|
415
|
-
Returns
|
|
416
|
-
-------
|
|
417
|
-
dict containing the parameters
|
|
418
435
|
|
|
436
|
+
Raises
|
|
437
|
+
------
|
|
438
|
+
ValueError
|
|
439
|
+
if query returned no results.
|
|
419
440
|
"""
|
|
420
|
-
_site, _, _model_version = self._validate_model_input(site, None, model_version)
|
|
421
|
-
_db_name = self._get_db_name()
|
|
422
|
-
_site_cache_key = self._parameter_cache_key(site, None, model_version)
|
|
423
441
|
try:
|
|
424
|
-
return DatabaseHandler.
|
|
442
|
+
return DatabaseHandler.production_table_cached[
|
|
443
|
+
self._cache_key(None, None, model_version, collection_name)
|
|
444
|
+
]
|
|
425
445
|
except KeyError:
|
|
426
446
|
pass
|
|
427
447
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
448
|
+
query = {"model_version": model_version, "collection": collection_name}
|
|
449
|
+
collection = self.get_collection(self._get_db_name(), "production_tables")
|
|
450
|
+
post = collection.find_one(query)
|
|
451
|
+
if not post:
|
|
452
|
+
raise ValueError(f"The following query returned zero results: {query}")
|
|
453
|
+
|
|
454
|
+
return {
|
|
455
|
+
"collection": post["collection"],
|
|
456
|
+
"model_version": post["model_version"],
|
|
457
|
+
"parameters": post["parameters"],
|
|
458
|
+
"design_model": post.get("design_model", {}),
|
|
459
|
+
"entry_date": ObjectId(post["_id"]).generation_time,
|
|
460
|
+
}
|
|
437
461
|
|
|
438
|
-
def
|
|
462
|
+
def get_model_versions(self, collection_name="telescopes"):
|
|
439
463
|
"""
|
|
440
|
-
Get
|
|
464
|
+
Get list of model versions from the DB.
|
|
441
465
|
|
|
442
466
|
Parameters
|
|
443
467
|
----------
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
site: str
|
|
447
|
-
Site name.
|
|
448
|
-
model_version: str
|
|
449
|
-
Version of the model.
|
|
450
|
-
only_applicable: bool
|
|
451
|
-
If True, only applicable parameters will be read.
|
|
468
|
+
collection_name: str
|
|
469
|
+
Name of the collection.
|
|
452
470
|
|
|
453
471
|
Returns
|
|
454
472
|
-------
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
473
|
+
list
|
|
474
|
+
List of model versions
|
|
475
|
+
"""
|
|
476
|
+
collection = self.get_collection(self._get_db_name(), "production_tables")
|
|
477
|
+
return sorted(
|
|
478
|
+
{post["model_version"] for post in collection.find({"collection": collection_name})}
|
|
479
|
+
)
|
|
461
480
|
|
|
481
|
+
def get_array_elements(self, model_version, collection="telescopes"):
|
|
462
482
|
"""
|
|
463
|
-
collection
|
|
464
|
-
_parameters = {}
|
|
483
|
+
Get list array elements for a given model version and collection from the DB.
|
|
465
484
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
raise ValueError(
|
|
474
|
-
"The following query returned zero results! Check the input data and rerun.\n",
|
|
475
|
-
query,
|
|
476
|
-
)
|
|
477
|
-
for post in collection.find(query).sort("parameter", ASCENDING):
|
|
478
|
-
par_now = post["parameter"]
|
|
479
|
-
_parameters[par_now] = post
|
|
480
|
-
_parameters[par_now].pop("parameter", None)
|
|
481
|
-
_parameters[par_now].pop("site", None)
|
|
482
|
-
_parameters[par_now]["entry_date"] = ObjectId(post["_id"]).generation_time
|
|
485
|
+
Parameters
|
|
486
|
+
----------
|
|
487
|
+
model_version: str
|
|
488
|
+
Version of the model.
|
|
489
|
+
collection: str
|
|
490
|
+
Which collection to get the array elements from:
|
|
491
|
+
i.e. telescopes, calibration_devices.
|
|
483
492
|
|
|
484
|
-
|
|
493
|
+
Returns
|
|
494
|
+
-------
|
|
495
|
+
list
|
|
496
|
+
Sorted list of all array elements found in collection
|
|
497
|
+
"""
|
|
498
|
+
production_table = self._read_production_table_from_mongo_db(collection, model_version)
|
|
499
|
+
return sorted([entry for entry in production_table["parameters"] if "-design" not in entry])
|
|
485
500
|
|
|
486
|
-
def
|
|
501
|
+
def get_design_model(self, model_version, array_element_name, collection="telescopes"):
|
|
487
502
|
"""
|
|
488
|
-
Get
|
|
503
|
+
Get the design model used for a given array element and a given model version.
|
|
489
504
|
|
|
490
505
|
Parameters
|
|
491
506
|
----------
|
|
492
|
-
site: str
|
|
493
|
-
Site name.
|
|
494
|
-
array_element_name: str
|
|
495
|
-
Name of the array element model (e.g. MSTN, SSTS).
|
|
496
507
|
model_version: str
|
|
497
508
|
Version of the model.
|
|
509
|
+
array_element_name: str
|
|
510
|
+
Name of the array element model (e.g. MSTN, SSTS).
|
|
511
|
+
collection: str
|
|
512
|
+
Which collection to get the array elements from:
|
|
513
|
+
i.e. telescopes, calibration_devices.
|
|
498
514
|
|
|
499
515
|
Returns
|
|
500
516
|
-------
|
|
501
|
-
|
|
517
|
+
str
|
|
518
|
+
Design model for a given array element.
|
|
519
|
+
"""
|
|
520
|
+
production_table = self._read_production_table_from_mongo_db(collection, model_version)
|
|
521
|
+
try:
|
|
522
|
+
return production_table["design_model"][array_element_name]
|
|
523
|
+
except KeyError:
|
|
524
|
+
# for eg. array_element_name == 'LSTN-design' returns 'LSTN-design'
|
|
525
|
+
return array_element_name
|
|
502
526
|
|
|
527
|
+
def get_array_elements_of_type(self, array_element_type, model_version, collection):
|
|
503
528
|
"""
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
529
|
+
Get array elements of a certain type (e.g. 'LSTN') for a DB collection.
|
|
530
|
+
|
|
531
|
+
Does not return 'design' models.
|
|
507
532
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
533
|
+
Parameters
|
|
534
|
+
----------
|
|
535
|
+
array_element_type: str
|
|
536
|
+
Type of the array element (e.g. LSTN, MSTS).
|
|
537
|
+
model_version: str
|
|
538
|
+
Version of the model.
|
|
539
|
+
collection: str
|
|
540
|
+
Which collection to get the array elements from:
|
|
541
|
+
i.e. telescopes, calibration_devices.
|
|
542
|
+
|
|
543
|
+
Returns
|
|
544
|
+
-------
|
|
545
|
+
list
|
|
546
|
+
Sorted list of all array element names found in collection
|
|
547
|
+
"""
|
|
548
|
+
production_table = self._read_production_table_from_mongo_db(collection, model_version)
|
|
549
|
+
all_array_elements = production_table["parameters"]
|
|
550
|
+
return sorted(
|
|
551
|
+
[
|
|
552
|
+
entry
|
|
553
|
+
for entry in all_array_elements
|
|
554
|
+
if entry.startswith(array_element_type) and "-design" not in entry
|
|
555
|
+
]
|
|
515
556
|
)
|
|
516
557
|
|
|
517
558
|
def get_simulation_configuration_parameters(
|
|
@@ -541,63 +582,24 @@ class DatabaseHandler:
|
|
|
541
582
|
if simulation_software is not valid.
|
|
542
583
|
"""
|
|
543
584
|
if simulation_software == "corsika":
|
|
544
|
-
return self.
|
|
585
|
+
return self.get_model_parameters(
|
|
586
|
+
None,
|
|
587
|
+
None,
|
|
588
|
+
model_version=model_version,
|
|
589
|
+
collection="configuration_corsika",
|
|
590
|
+
)
|
|
545
591
|
if simulation_software == "simtel":
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
site,
|
|
592
|
+
return (
|
|
593
|
+
self.get_model_parameters(
|
|
594
|
+
site,
|
|
595
|
+
array_element_name,
|
|
596
|
+
model_version=model_version,
|
|
597
|
+
collection="configuration_sim_telarray",
|
|
549
598
|
)
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
def get_corsika_configuration_parameters(self, model_version):
|
|
554
|
-
"""
|
|
555
|
-
Get CORSIKA configuration parameters from the DB.
|
|
556
|
-
|
|
557
|
-
Parameters
|
|
558
|
-
----------
|
|
559
|
-
model_version : str
|
|
560
|
-
Version of the model.
|
|
561
|
-
|
|
562
|
-
Returns
|
|
563
|
-
-------
|
|
564
|
-
dict
|
|
565
|
-
Configuration parameters for CORSIKA
|
|
566
|
-
"""
|
|
567
|
-
_corsika_cache_key = self._parameter_cache_key(None, None, model_version)
|
|
568
|
-
try:
|
|
569
|
-
return DatabaseHandler.corsika_configuration_parameters_cached[_corsika_cache_key]
|
|
570
|
-
except KeyError:
|
|
571
|
-
pass
|
|
572
|
-
DatabaseHandler.corsika_configuration_parameters_cached[_corsika_cache_key] = (
|
|
573
|
-
self.read_mongo_db(
|
|
574
|
-
db_name=self._get_db_name(),
|
|
575
|
-
array_element_name=None,
|
|
576
|
-
model_version=model_version,
|
|
577
|
-
run_location=None,
|
|
578
|
-
collection_name="configuration_corsika",
|
|
579
|
-
write_files=False,
|
|
599
|
+
if site and array_element_name
|
|
600
|
+
else {}
|
|
580
601
|
)
|
|
581
|
-
)
|
|
582
|
-
return DatabaseHandler.corsika_configuration_parameters_cached[_corsika_cache_key]
|
|
583
|
-
|
|
584
|
-
def _validate_model_input(self, site, array_element_name, model_version):
|
|
585
|
-
"""
|
|
586
|
-
Validate input for model parameter queries.
|
|
587
|
-
|
|
588
|
-
site: str
|
|
589
|
-
Site name.
|
|
590
|
-
array_element_name: str
|
|
591
|
-
Name of the array element model (e.g. LSTN-01, MSTS-design)
|
|
592
|
-
model_version: str
|
|
593
|
-
Version of the model.
|
|
594
|
-
|
|
595
|
-
"""
|
|
596
|
-
return (
|
|
597
|
-
names.validate_site_name(site),
|
|
598
|
-
names.validate_array_element_name(array_element_name) if array_element_name else None,
|
|
599
|
-
self.model_version(model_version),
|
|
600
|
-
)
|
|
602
|
+
raise ValueError(f"Unknown simulation software: {simulation_software}")
|
|
601
603
|
|
|
602
604
|
@staticmethod
|
|
603
605
|
def _get_file_mongo_db(db_name, file_name):
|
|
@@ -648,76 +650,22 @@ class DatabaseHandler:
|
|
|
648
650
|
with open(Path(path).joinpath(file.filename), "wb") as output_file:
|
|
649
651
|
fs_output.download_to_stream_by_name(file.filename, output_file)
|
|
650
652
|
|
|
651
|
-
def
|
|
652
|
-
self,
|
|
653
|
-
db_name,
|
|
654
|
-
element_to_copy,
|
|
655
|
-
version_to_copy,
|
|
656
|
-
new_array_element_name,
|
|
657
|
-
collection_name="telescopes",
|
|
658
|
-
db_to_copy_to=None,
|
|
659
|
-
collection_to_copy_to=None,
|
|
660
|
-
):
|
|
653
|
+
def add_production_table(self, db_name, production_table):
|
|
661
654
|
"""
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
Only a specific version is copied.
|
|
665
|
-
This function should be rarely used and is intended to simplify unit tests.
|
|
655
|
+
Add a production table to the DB.
|
|
666
656
|
|
|
667
657
|
Parameters
|
|
668
658
|
----------
|
|
669
659
|
db_name: str
|
|
670
|
-
the name of the DB
|
|
671
|
-
|
|
672
|
-
The
|
|
673
|
-
version_to_copy: str
|
|
674
|
-
The version of the configuration to copy
|
|
675
|
-
new_array_element_name: str
|
|
676
|
-
The name of the new array element
|
|
677
|
-
collection_name: str
|
|
678
|
-
The name of the collection to copy from.
|
|
679
|
-
db_to_copy_to: str
|
|
680
|
-
The name of the DB to copy to.
|
|
681
|
-
collection_to_copy_to: str
|
|
682
|
-
The name of the collection to copy to.
|
|
683
|
-
|
|
684
|
-
Raises
|
|
685
|
-
------
|
|
686
|
-
BulkWriteError
|
|
687
|
-
|
|
660
|
+
the name of the DB.
|
|
661
|
+
production_table: dict
|
|
662
|
+
The production table to add to the DB.
|
|
688
663
|
"""
|
|
689
664
|
db_name = self._get_db_name(db_name)
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
collection_to_copy_to = collection_name
|
|
695
|
-
|
|
696
|
-
self._logger.info(
|
|
697
|
-
f"Copying version {version_to_copy} of {element_to_copy} "
|
|
698
|
-
f"to the new array element {new_array_element_name} in the {db_to_copy_to} DB"
|
|
699
|
-
)
|
|
700
|
-
|
|
701
|
-
collection = self.get_collection(db_name, collection_name)
|
|
702
|
-
db_entries = []
|
|
703
|
-
|
|
704
|
-
_version_to_copy = self.model_version(version_to_copy)
|
|
705
|
-
|
|
706
|
-
query = {
|
|
707
|
-
"instrument": element_to_copy,
|
|
708
|
-
"version": _version_to_copy,
|
|
709
|
-
}
|
|
710
|
-
for post in collection.find(query):
|
|
711
|
-
post["instrument"] = new_array_element_name
|
|
712
|
-
post.pop("_id", None)
|
|
713
|
-
db_entries.append(post)
|
|
714
|
-
|
|
715
|
-
self._logger.info(f"Creating new array element {new_array_element_name}")
|
|
716
|
-
collection = self.get_collection(db_to_copy_to, collection_to_copy_to)
|
|
717
|
-
try:
|
|
718
|
-
collection.insert_many(db_entries)
|
|
719
|
-
except BulkWriteError as exc:
|
|
720
|
-
raise BulkWriteError(str(exc.details)) from exc
|
|
665
|
+
collection = self.get_collection(db_name, "production_tables")
|
|
666
|
+
self._logger.info(f"Adding production for {production_table.get('collection')} to to DB")
|
|
667
|
+
collection.insert_one(production_table)
|
|
668
|
+
DatabaseHandler.production_table_cached.clear()
|
|
721
669
|
|
|
722
670
|
def add_new_parameter(
|
|
723
671
|
self,
|
|
@@ -727,7 +675,7 @@ class DatabaseHandler:
|
|
|
727
675
|
file_prefix=None,
|
|
728
676
|
):
|
|
729
677
|
"""
|
|
730
|
-
Add a parameter dictionary
|
|
678
|
+
Add a new parameter dictionary to the DB.
|
|
731
679
|
|
|
732
680
|
A new document will be added to the DB, with all fields taken from the input parameters.
|
|
733
681
|
Parameter dictionaries are validated before submission using the corresponding schema.
|
|
@@ -743,13 +691,7 @@ class DatabaseHandler:
|
|
|
743
691
|
file_prefix: str or Path
|
|
744
692
|
where to find files to upload to the DB
|
|
745
693
|
"""
|
|
746
|
-
|
|
747
|
-
schema_file=files("simtools")
|
|
748
|
-
/ f"schemas/model_parameters/{par_dict['parameter']}.schema.yml",
|
|
749
|
-
data_dict=par_dict,
|
|
750
|
-
check_exact_data_type=False,
|
|
751
|
-
)
|
|
752
|
-
par_dict = data_validator.validate_and_transform(is_model_parameter=True)
|
|
694
|
+
par_dict = validate_data.DataValidator.validate_model_parameter(par_dict)
|
|
753
695
|
|
|
754
696
|
db_name = self._get_db_name(db_name)
|
|
755
697
|
collection = self.get_collection(db_name, collection_name)
|
|
@@ -778,7 +720,7 @@ class DatabaseHandler:
|
|
|
778
720
|
self._logger.info(f"Will also add the file {file_to_insert_now} to the DB")
|
|
779
721
|
self.insert_file_to_db(file_to_insert_now, db_name)
|
|
780
722
|
|
|
781
|
-
self._reset_parameter_cache(
|
|
723
|
+
self._reset_parameter_cache()
|
|
782
724
|
|
|
783
725
|
def _get_db_name(self, db_name=None):
|
|
784
726
|
"""
|
|
@@ -796,42 +738,6 @@ class DatabaseHandler:
|
|
|
796
738
|
"""
|
|
797
739
|
return self.mongo_db_config["db_simulation_model"] if db_name is None else db_name
|
|
798
740
|
|
|
799
|
-
def model_version(self, version, db_name=None):
|
|
800
|
-
"""
|
|
801
|
-
Return model version and check that it is valid.
|
|
802
|
-
|
|
803
|
-
Queries the database for all available model versions and check if the
|
|
804
|
-
requested version is valid.
|
|
805
|
-
|
|
806
|
-
Parameters
|
|
807
|
-
----------
|
|
808
|
-
version : str
|
|
809
|
-
Model version.
|
|
810
|
-
db_name : str
|
|
811
|
-
Database name.
|
|
812
|
-
|
|
813
|
-
Returns
|
|
814
|
-
-------
|
|
815
|
-
str
|
|
816
|
-
Model version.
|
|
817
|
-
|
|
818
|
-
Raises
|
|
819
|
-
------
|
|
820
|
-
ValueError
|
|
821
|
-
if version not valid.
|
|
822
|
-
|
|
823
|
-
"""
|
|
824
|
-
_all_versions = self.get_all_versions(db_name=db_name)
|
|
825
|
-
if version in _all_versions:
|
|
826
|
-
return version
|
|
827
|
-
if len(_all_versions) == 0:
|
|
828
|
-
return None
|
|
829
|
-
|
|
830
|
-
raise ValueError(
|
|
831
|
-
f"Invalid model version {version} in DB {self._get_db_name(db_name)} "
|
|
832
|
-
f"(allowed are {_all_versions})"
|
|
833
|
-
)
|
|
834
|
-
|
|
835
741
|
def insert_file_to_db(self, file_name, db_name=None, **kwargs):
|
|
836
742
|
"""
|
|
837
743
|
Insert a file to the DB.
|
|
@@ -855,15 +761,11 @@ class DatabaseHandler:
|
|
|
855
761
|
|
|
856
762
|
"""
|
|
857
763
|
db_name = self._get_db_name(db_name)
|
|
858
|
-
|
|
859
764
|
db = DatabaseHandler.db_client[db_name]
|
|
860
765
|
file_system = gridfs.GridFS(db)
|
|
861
766
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
if "filename" not in kwargs:
|
|
866
|
-
kwargs["filename"] = Path(file_name).name
|
|
767
|
+
kwargs.setdefault("content_type", "ascii/dat")
|
|
768
|
+
kwargs.setdefault("filename", Path(file_name).name)
|
|
867
769
|
|
|
868
770
|
if file_system.exists({"filename": kwargs["filename"]}):
|
|
869
771
|
self._logger.warning(
|
|
@@ -872,78 +774,11 @@ class DatabaseHandler:
|
|
|
872
774
|
return file_system.find_one( # pylint: disable=protected-access
|
|
873
775
|
{"filename": kwargs["filename"]}
|
|
874
776
|
)._id
|
|
777
|
+
self._logger.debug(f"Writing file to DB: {file_name}")
|
|
875
778
|
with open(file_name, "rb") as data_file:
|
|
876
779
|
return file_system.put(data_file, **kwargs)
|
|
877
780
|
|
|
878
|
-
def
|
|
879
|
-
self,
|
|
880
|
-
parameter=None,
|
|
881
|
-
array_element_name=None,
|
|
882
|
-
site=None,
|
|
883
|
-
db_name=None,
|
|
884
|
-
collection=None,
|
|
885
|
-
):
|
|
886
|
-
"""
|
|
887
|
-
Get all version entries in the DB of collection and/or a specific parameter.
|
|
888
|
-
|
|
889
|
-
Parameters
|
|
890
|
-
----------
|
|
891
|
-
parameter: str
|
|
892
|
-
Which parameter to get the versions of
|
|
893
|
-
array_element_name: str
|
|
894
|
-
Which array element to get the versions of (in case "collection_name" is not "sites")
|
|
895
|
-
site: str
|
|
896
|
-
Site name.
|
|
897
|
-
db_name: str
|
|
898
|
-
Database name.
|
|
899
|
-
collection_name: str
|
|
900
|
-
The name of the collection in which to update the parameter.
|
|
901
|
-
|
|
902
|
-
Returns
|
|
903
|
-
-------
|
|
904
|
-
all_versions: list
|
|
905
|
-
List of all versions found
|
|
906
|
-
|
|
907
|
-
Raises
|
|
908
|
-
------
|
|
909
|
-
ValueError
|
|
910
|
-
If key to collection_name is not valid.
|
|
911
|
-
|
|
912
|
-
"""
|
|
913
|
-
db_name = self._get_db_name() if db_name is None else db_name
|
|
914
|
-
if not db_name:
|
|
915
|
-
self._logger.warning("No database name defined to determine list of model versions")
|
|
916
|
-
return []
|
|
917
|
-
_cache_key = f"model_versions_{db_name}-{collection}"
|
|
918
|
-
|
|
919
|
-
query = {}
|
|
920
|
-
if parameter is not None:
|
|
921
|
-
query["parameter"] = parameter
|
|
922
|
-
_cache_key = f"{_cache_key}-{parameter}"
|
|
923
|
-
if collection in ["telescopes", "calibration_devices"] and array_element_name is not None:
|
|
924
|
-
query["instrument"] = names.validate_array_element_name(array_element_name)
|
|
925
|
-
_cache_key = f"{_cache_key}-{query['instrument']}"
|
|
926
|
-
elif collection == "sites" and site is not None:
|
|
927
|
-
query["site"] = names.validate_site_name(site)
|
|
928
|
-
_cache_key = f"{_cache_key}-{query['site']}"
|
|
929
|
-
|
|
930
|
-
if _cache_key not in DatabaseHandler.model_versions_cached:
|
|
931
|
-
all_versions = set()
|
|
932
|
-
collections_to_query = (
|
|
933
|
-
[collection] if collection else self.get_collections(db_name, True)
|
|
934
|
-
)
|
|
935
|
-
for collection_name in collections_to_query:
|
|
936
|
-
db_collection = self.get_collection(db_name, collection_name)
|
|
937
|
-
sorted_posts = db_collection.find(query).sort("version", ASCENDING)
|
|
938
|
-
all_versions.update(post["version"] for post in sorted_posts)
|
|
939
|
-
DatabaseHandler.model_versions_cached[_cache_key] = list(all_versions)
|
|
940
|
-
|
|
941
|
-
if len(DatabaseHandler.model_versions_cached[_cache_key]) == 0:
|
|
942
|
-
self._logger.warning(f"The query {query} did not return any results. No versions found")
|
|
943
|
-
|
|
944
|
-
return DatabaseHandler.model_versions_cached[_cache_key]
|
|
945
|
-
|
|
946
|
-
def _parameter_cache_key(self, site, array_element_name, model_version, collection=None):
|
|
781
|
+
def _cache_key(self, site=None, array_element_name=None, model_version=None, collection=None):
|
|
947
782
|
"""
|
|
948
783
|
Create a cache key for the parameter cache dictionaries.
|
|
949
784
|
|
|
@@ -963,61 +798,84 @@ class DatabaseHandler:
|
|
|
963
798
|
str
|
|
964
799
|
Cache key.
|
|
965
800
|
"""
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
if array_element_name:
|
|
970
|
-
parts.append(array_element_name)
|
|
971
|
-
parts.append(model_version)
|
|
972
|
-
if collection:
|
|
973
|
-
parts.append(collection)
|
|
974
|
-
return "-".join(parts)
|
|
801
|
+
return "-".join(
|
|
802
|
+
part for part in [model_version, collection, site, array_element_name] if part
|
|
803
|
+
)
|
|
975
804
|
|
|
976
|
-
def
|
|
805
|
+
def _read_cache(
|
|
806
|
+
self, cache_dict, site=None, array_element_name=None, model_version=None, collection=None
|
|
807
|
+
):
|
|
977
808
|
"""
|
|
978
|
-
|
|
809
|
+
Read parameters from cache.
|
|
979
810
|
|
|
980
811
|
Parameters
|
|
981
812
|
----------
|
|
813
|
+
cache_dict: dict
|
|
814
|
+
Cache dictionary.
|
|
982
815
|
site: str
|
|
983
816
|
Site name.
|
|
984
817
|
array_element_name: str
|
|
985
818
|
Array element name.
|
|
986
819
|
model_version: str
|
|
987
820
|
Model version.
|
|
821
|
+
collection: str
|
|
822
|
+
DB collection name.
|
|
823
|
+
|
|
824
|
+
Returns
|
|
825
|
+
-------
|
|
826
|
+
str
|
|
827
|
+
Cache key.
|
|
988
828
|
"""
|
|
989
|
-
self.
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
829
|
+
cache_key = self._cache_key(site, array_element_name, model_version, collection)
|
|
830
|
+
try:
|
|
831
|
+
return cache_key, cache_dict[cache_key]
|
|
832
|
+
except KeyError:
|
|
833
|
+
return cache_key, None
|
|
994
834
|
|
|
995
|
-
def
|
|
835
|
+
def _reset_parameter_cache(self):
|
|
836
|
+
"""Reset the cache for the parameters."""
|
|
837
|
+
DatabaseHandler.model_parameters_cached.clear()
|
|
838
|
+
|
|
839
|
+
def _get_array_element_list(self, array_element_name, site, production_table, collection):
|
|
996
840
|
"""
|
|
997
|
-
|
|
841
|
+
Return list of array elements for DB queries (add design model if needed).
|
|
842
|
+
|
|
843
|
+
Design model is added if found in the production table.
|
|
998
844
|
|
|
999
845
|
Parameters
|
|
1000
846
|
----------
|
|
1001
|
-
|
|
1002
|
-
|
|
847
|
+
array_element_name: str
|
|
848
|
+
Name of the array element.
|
|
849
|
+
site: str
|
|
850
|
+
Site name.
|
|
851
|
+
production_table: dict
|
|
852
|
+
Production table.
|
|
853
|
+
collection: str
|
|
854
|
+
collection of array element (e.g. telescopes, calibration_devices).
|
|
1003
855
|
|
|
1004
856
|
Returns
|
|
1005
857
|
-------
|
|
1006
858
|
list
|
|
1007
|
-
List of
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
""
|
|
1012
|
-
|
|
1013
|
-
if
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
859
|
+
List of array elements
|
|
860
|
+
"""
|
|
861
|
+
if collection == "configuration_corsika":
|
|
862
|
+
return ["xSTx-design"] # placeholder to ignore 'instrument' field in query.
|
|
863
|
+
if collection == "sites":
|
|
864
|
+
return [f"OBS-{site}"]
|
|
865
|
+
if names.is_design_type(array_element_name):
|
|
866
|
+
return [array_element_name]
|
|
867
|
+
if collection == "configuration_sim_telarray":
|
|
868
|
+
# get design model from 'telescope' or 'calibration_device' production tables
|
|
869
|
+
production_table = self._read_production_table_from_mongo_db(
|
|
870
|
+
names.get_collection_name_from_array_element_name(array_element_name),
|
|
871
|
+
production_table["model_version"],
|
|
872
|
+
)
|
|
873
|
+
try:
|
|
1018
874
|
return [
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
if not collection.startswith("fs.") and collection != "metadata"
|
|
875
|
+
production_table["design_model"][array_element_name],
|
|
876
|
+
array_element_name,
|
|
1022
877
|
]
|
|
1023
|
-
|
|
878
|
+
except KeyError as exc:
|
|
879
|
+
raise KeyError(
|
|
880
|
+
f"Failed generated array element list for db query for {array_element_name}"
|
|
881
|
+
) from exc
|