gammasimtools 0.22.0__py3-none-any.whl → 0.24.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.22.0.dist-info → gammasimtools-0.24.0.dist-info}/METADATA +2 -1
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/RECORD +128 -125
- simtools/_version.py +2 -2
- simtools/application_control.py +118 -0
- simtools/applications/calculate_incident_angles.py +17 -22
- simtools/applications/convert_all_model_parameters_from_simtel.py +28 -43
- simtools/applications/convert_geo_coordinates_of_array_elements.py +26 -45
- simtools/applications/convert_model_parameter_from_simtel.py +21 -41
- simtools/applications/db_add_file_to_db.py +13 -14
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +20 -33
- simtools/applications/db_add_value_from_json_to_db.py +29 -24
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +20 -35
- simtools/applications/db_generate_compound_indexes.py +11 -13
- simtools/applications/db_get_array_layouts_from_db.py +20 -40
- simtools/applications/db_get_file_from_db.py +15 -17
- simtools/applications/db_get_parameter_from_db.py +33 -35
- simtools/applications/db_inspect_databases.py +13 -12
- simtools/applications/db_upload_model_repository.py +13 -31
- simtools/applications/derive_ctao_array_layouts.py +16 -21
- simtools/applications/derive_mirror_rnda.py +9 -14
- simtools/applications/derive_photon_electron_spectrum.py +7 -10
- simtools/applications/derive_psf_parameters.py +13 -20
- simtools/applications/derive_trigger_rates.py +6 -9
- simtools/applications/docs_produce_array_element_report.py +22 -23
- simtools/applications/docs_produce_calibration_reports.py +26 -24
- simtools/applications/docs_produce_model_parameter_reports.py +15 -22
- simtools/applications/docs_produce_simulation_configuration_report.py +21 -22
- simtools/applications/generate_array_config.py +14 -33
- simtools/applications/generate_corsika_histograms.py +22 -43
- simtools/applications/generate_default_metadata.py +15 -36
- simtools/applications/generate_regular_arrays.py +11 -15
- simtools/applications/generate_simtel_event_data.py +23 -33
- simtools/applications/maintain_simulation_model_add_production.py +20 -37
- simtools/applications/maintain_simulation_model_compare_productions.py +10 -12
- simtools/applications/maintain_simulation_model_verify_production_tables.py +8 -11
- simtools/applications/merge_tables.py +14 -23
- simtools/applications/plot_array_layout.py +77 -54
- simtools/applications/plot_simtel_events.py +11 -13
- simtools/applications/plot_tabular_data.py +17 -38
- simtools/applications/plot_tabular_data_for_model_parameter.py +16 -23
- simtools/applications/print_version.py +14 -42
- simtools/applications/production_derive_corsika_limits.py +5 -9
- simtools/applications/production_derive_statistics.py +12 -25
- simtools/applications/production_generate_grid.py +20 -48
- simtools/applications/production_merge_corsika_limits.py +17 -21
- simtools/applications/run_application.py +12 -32
- simtools/applications/simulate_flasher.py +21 -25
- simtools/applications/simulate_illuminator.py +7 -14
- simtools/applications/simulate_pedestals.py +13 -13
- simtools/applications/simulate_prod.py +21 -33
- simtools/applications/simulate_prod_htcondor_generator.py +11 -25
- simtools/applications/submit_array_layouts.py +16 -19
- simtools/applications/submit_data_from_external.py +18 -34
- simtools/applications/submit_model_parameter_from_external.py +27 -40
- simtools/applications/validate_camera_efficiency.py +23 -21
- simtools/applications/validate_camera_fov.py +21 -26
- simtools/applications/validate_cumulative_psf.py +27 -35
- simtools/applications/validate_file_using_schema.py +15 -33
- simtools/applications/validate_optics.py +27 -33
- simtools/camera/camera_efficiency.py +0 -2
- simtools/configuration/commandline_parser.py +39 -13
- simtools/configuration/configurator.py +1 -6
- simtools/corsika/corsika_config.py +2 -9
- simtools/data_model/data_reader.py +0 -2
- simtools/data_model/metadata_collector.py +0 -2
- simtools/data_model/model_data_writer.py +1 -3
- simtools/data_model/schema.py +36 -34
- simtools/data_model/validate_data.py +0 -2
- simtools/db/db_handler.py +61 -296
- simtools/db/db_model_upload.py +1 -1
- simtools/db/mongo_db.py +535 -0
- simtools/dependencies.py +33 -8
- simtools/io/hdf5_handler.py +0 -5
- simtools/io/legacy_data_handler.py +0 -5
- simtools/job_execution/job_manager.py +0 -3
- simtools/layout/array_layout.py +7 -9
- simtools/layout/array_layout_utils.py +3 -3
- simtools/layout/telescope_position.py +0 -2
- simtools/model/array_model.py +38 -71
- simtools/model/calibration_model.py +12 -11
- simtools/model/camera.py +0 -2
- simtools/model/mirrors.py +0 -2
- simtools/model/model_parameter.py +200 -140
- simtools/model/model_repository.py +159 -35
- simtools/model/model_utils.py +3 -8
- simtools/model/site_model.py +59 -29
- simtools/model/telescope_model.py +21 -15
- simtools/production_configuration/calculate_statistical_uncertainties_grid_point.py +0 -2
- simtools/production_configuration/derive_production_statistics.py +0 -2
- simtools/production_configuration/interpolation_handler.py +0 -2
- simtools/ray_tracing/mirror_panel_psf.py +4 -4
- simtools/ray_tracing/psf_analysis.py +0 -2
- simtools/ray_tracing/psf_parameter_optimisation.py +1 -1
- simtools/ray_tracing/ray_tracing.py +0 -2
- simtools/reporting/docs_auto_report_generator.py +109 -1
- simtools/reporting/docs_read_parameters.py +4 -9
- simtools/runners/corsika_runner.py +0 -2
- simtools/runners/corsika_simtel_runner.py +0 -2
- simtools/runners/simtel_runner.py +0 -2
- simtools/schemas/model_parameters/transit_time_random.schema.yml +29 -0
- simtools/schemas/simulation_models_info.schema.yml +2 -1
- simtools/simtel/simtel_config_reader.py +0 -2
- simtools/simtel/simtel_config_writer.py +128 -33
- simtools/simtel/simtel_io_metadata.py +3 -3
- simtools/simtel/simulator_array.py +9 -21
- simtools/simtel/simulator_camera_efficiency.py +0 -2
- simtools/simtel/simulator_light_emission.py +1 -3
- simtools/simtel/simulator_ray_tracing.py +0 -2
- simtools/simulator.py +2 -6
- simtools/testing/assertions.py +52 -8
- simtools/testing/configuration.py +17 -4
- simtools/testing/validate_output.py +4 -8
- simtools/utils/general.py +5 -13
- simtools/utils/geometry.py +0 -5
- simtools/utils/names.py +1 -13
- simtools/utils/value_conversion.py +10 -5
- simtools/version.py +85 -0
- simtools/visualization/plot_array_layout.py +129 -23
- simtools/visualization/plot_incident_angles.py +0 -2
- simtools/visualization/plot_pixels.py +1 -1
- simtools/visualization/plot_psf.py +1 -1
- simtools/visualization/plot_simtel_events.py +0 -11
- simtools/visualization/plot_tables.py +1 -1
- simtools/visualization/visualize.py +0 -12
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/entry_points.txt +0 -0
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/licenses/LICENSE +0 -0
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/top_level.txt +0 -0
simtools/db/db_handler.py
CHANGED
|
@@ -1,72 +1,16 @@
|
|
|
1
1
|
"""Module to handle interaction with DB."""
|
|
2
2
|
|
|
3
|
-
import io
|
|
4
3
|
import logging
|
|
5
|
-
import re
|
|
6
4
|
from collections import defaultdict
|
|
7
5
|
from pathlib import Path
|
|
8
|
-
from threading import Lock
|
|
9
|
-
|
|
10
|
-
import gridfs
|
|
11
|
-
import jsonschema
|
|
12
|
-
from astropy.table import Table
|
|
13
|
-
from bson.objectid import ObjectId
|
|
14
|
-
from pymongo import MongoClient
|
|
15
6
|
|
|
16
7
|
from simtools.data_model import validate_data
|
|
17
|
-
from simtools.
|
|
8
|
+
from simtools.db.mongo_db import MongoDBHandler
|
|
9
|
+
from simtools.io import io_handler
|
|
18
10
|
from simtools.simtel import simtel_table_reader
|
|
19
11
|
from simtools.utils import names, value_conversion
|
|
20
12
|
from simtools.version import resolve_version_to_latest_patch
|
|
21
13
|
|
|
22
|
-
__all__ = ["DatabaseHandler"]
|
|
23
|
-
|
|
24
|
-
logging.getLogger("pymongo").setLevel(logging.WARNING)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
# pylint: disable=unsubscriptable-object
|
|
28
|
-
# The above comment is because pylint does not know that DatabaseHandler.db_client is subscriptable
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
jsonschema_db_dict = {
|
|
32
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema#",
|
|
33
|
-
"type": "object",
|
|
34
|
-
"description": "MongoDB configuration",
|
|
35
|
-
"properties": {
|
|
36
|
-
"db_server": {"type": "string", "description": "DB server address"},
|
|
37
|
-
"db_api_port": {
|
|
38
|
-
"type": "integer",
|
|
39
|
-
"minimum": 1,
|
|
40
|
-
"maximum": 65535,
|
|
41
|
-
"default": 27017,
|
|
42
|
-
"description": "Port to use",
|
|
43
|
-
},
|
|
44
|
-
"db_api_user": {"type": "string", "description": "API username"},
|
|
45
|
-
"db_api_pw": {"type": "string", "description": "Password for the API user"},
|
|
46
|
-
"db_api_authentication_database": {
|
|
47
|
-
"type": ["string", "null"],
|
|
48
|
-
"default": "admin",
|
|
49
|
-
"description": "DB with user info (optional)",
|
|
50
|
-
},
|
|
51
|
-
"db_simulation_model": {
|
|
52
|
-
"type": "string",
|
|
53
|
-
"description": "Name of simulation model database",
|
|
54
|
-
},
|
|
55
|
-
"db_simulation_model_version": {
|
|
56
|
-
"type": "string",
|
|
57
|
-
"description": "Version of simulation model database",
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
"required": [
|
|
61
|
-
"db_server",
|
|
62
|
-
"db_api_port",
|
|
63
|
-
"db_api_user",
|
|
64
|
-
"db_api_pw",
|
|
65
|
-
"db_simulation_model",
|
|
66
|
-
"db_simulation_model_version",
|
|
67
|
-
],
|
|
68
|
-
}
|
|
69
|
-
|
|
70
14
|
|
|
71
15
|
class DatabaseHandler:
|
|
72
16
|
"""
|
|
@@ -74,67 +18,57 @@ class DatabaseHandler:
|
|
|
74
18
|
|
|
75
19
|
Note the two types of version variables used in this class:
|
|
76
20
|
|
|
77
|
-
- db_simulation_model_version (from
|
|
21
|
+
- db_simulation_model_version (from db_config): version of the simulation model database
|
|
78
22
|
- model_version (from production_tables): version of the model contained in the database
|
|
79
23
|
|
|
80
24
|
Parameters
|
|
81
25
|
----------
|
|
82
|
-
|
|
83
|
-
Dictionary with the
|
|
26
|
+
db_config: dict
|
|
27
|
+
Dictionary with the DB configuration.
|
|
84
28
|
"""
|
|
85
29
|
|
|
86
30
|
ALLOWED_FILE_EXTENSIONS = [".dat", ".txt", ".lis", ".cfg", ".yml", ".yaml", ".ecsv"]
|
|
87
31
|
|
|
88
|
-
db_client = None
|
|
89
32
|
production_table_cached = {}
|
|
90
33
|
model_parameters_cached = {}
|
|
91
34
|
model_versions_cached = {}
|
|
92
35
|
|
|
93
|
-
def __init__(self,
|
|
36
|
+
def __init__(self, db_config=None):
|
|
94
37
|
"""Initialize the DatabaseHandler class."""
|
|
95
38
|
self._logger = logging.getLogger(__name__)
|
|
96
39
|
|
|
97
|
-
self.
|
|
40
|
+
self.db_config = MongoDBHandler.validate_db_config(db_config)
|
|
98
41
|
self.io_handler = io_handler.IOHandler()
|
|
99
|
-
self.
|
|
42
|
+
self.mongo_db_handler = MongoDBHandler(db_config) if self.db_config else None
|
|
100
43
|
|
|
101
|
-
self._set_up_connection()
|
|
102
44
|
self.db_name = (
|
|
103
|
-
|
|
104
|
-
db_simulation_model_version=self.
|
|
105
|
-
model_name=self.
|
|
45
|
+
MongoDBHandler.get_db_name(
|
|
46
|
+
db_simulation_model_version=self.db_config.get("db_simulation_model_version"),
|
|
47
|
+
model_name=self.db_config.get("db_simulation_model"),
|
|
106
48
|
)
|
|
107
|
-
if self.
|
|
49
|
+
if self.db_config
|
|
108
50
|
else None
|
|
109
51
|
)
|
|
110
52
|
|
|
111
|
-
def _set_up_connection(self):
|
|
112
|
-
"""Open the connection to MongoDB."""
|
|
113
|
-
if self.mongo_db_config and DatabaseHandler.db_client is None:
|
|
114
|
-
lock = Lock()
|
|
115
|
-
with lock:
|
|
116
|
-
DatabaseHandler.db_client = self._open_mongo_db()
|
|
117
|
-
|
|
118
53
|
def get_db_name(self, db_name=None, db_simulation_model_version=None, model_name=None):
|
|
119
54
|
"""Build DB name from configuration."""
|
|
120
55
|
if db_name:
|
|
121
56
|
return db_name
|
|
122
57
|
if db_simulation_model_version and model_name:
|
|
123
|
-
return
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
58
|
+
return MongoDBHandler.get_db_name(
|
|
59
|
+
db_simulation_model_version=db_simulation_model_version,
|
|
60
|
+
model_name=model_name,
|
|
61
|
+
)
|
|
62
|
+
if not (db_simulation_model_version or model_name):
|
|
63
|
+
return self.db_name
|
|
64
|
+
return None
|
|
127
65
|
|
|
128
66
|
def print_connection_info(self):
|
|
129
67
|
"""Print the connection information."""
|
|
130
|
-
if self.
|
|
131
|
-
self.
|
|
132
|
-
f"Connected to MongoDB at {self.mongo_db_config['db_server']}:"
|
|
133
|
-
f"{self.mongo_db_config['db_api_port']} "
|
|
134
|
-
f"using database: {self.db_name}"
|
|
135
|
-
)
|
|
68
|
+
if self.mongo_db_handler:
|
|
69
|
+
self.mongo_db_handler.print_connection_info(self.db_name)
|
|
136
70
|
else:
|
|
137
|
-
self._logger.info("No
|
|
71
|
+
self._logger.info("No database defined.")
|
|
138
72
|
|
|
139
73
|
def is_remote_database(self):
|
|
140
74
|
"""
|
|
@@ -147,55 +81,7 @@ class DatabaseHandler:
|
|
|
147
81
|
bool
|
|
148
82
|
True if the database is remote, False otherwise.
|
|
149
83
|
"""
|
|
150
|
-
|
|
151
|
-
db_server = self.mongo_db_config["db_server"]
|
|
152
|
-
domain_pattern = r"^([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$"
|
|
153
|
-
return bool(re.match(domain_pattern, db_server))
|
|
154
|
-
return False
|
|
155
|
-
|
|
156
|
-
def _validate_mongo_db_config(self, mongo_db_config):
|
|
157
|
-
"""Validate the MongoDB configuration."""
|
|
158
|
-
if mongo_db_config is None or all(value is None for value in mongo_db_config.values()):
|
|
159
|
-
return None
|
|
160
|
-
try:
|
|
161
|
-
jsonschema.validate(instance=mongo_db_config, schema=jsonschema_db_dict)
|
|
162
|
-
return mongo_db_config
|
|
163
|
-
except jsonschema.exceptions.ValidationError as err:
|
|
164
|
-
raise ValueError("Invalid MongoDB configuration") from err
|
|
165
|
-
|
|
166
|
-
def _open_mongo_db(self):
|
|
167
|
-
"""
|
|
168
|
-
Open a connection to MongoDB and return the client to read/write to the DB with.
|
|
169
|
-
|
|
170
|
-
Returns
|
|
171
|
-
-------
|
|
172
|
-
A PyMongo DB client
|
|
173
|
-
|
|
174
|
-
Raises
|
|
175
|
-
------
|
|
176
|
-
KeyError
|
|
177
|
-
If the DB configuration is invalid
|
|
178
|
-
"""
|
|
179
|
-
direct_connection = self.mongo_db_config["db_server"] in (
|
|
180
|
-
"localhost",
|
|
181
|
-
"simtools-mongodb",
|
|
182
|
-
"mongodb",
|
|
183
|
-
)
|
|
184
|
-
return MongoClient(
|
|
185
|
-
self.mongo_db_config["db_server"],
|
|
186
|
-
port=self.mongo_db_config["db_api_port"],
|
|
187
|
-
username=self.mongo_db_config["db_api_user"],
|
|
188
|
-
password=self.mongo_db_config["db_api_pw"],
|
|
189
|
-
authSource=(
|
|
190
|
-
self.mongo_db_config.get("db_api_authentication_database")
|
|
191
|
-
if self.mongo_db_config.get("db_api_authentication_database")
|
|
192
|
-
else "admin"
|
|
193
|
-
),
|
|
194
|
-
directConnection=direct_connection,
|
|
195
|
-
ssl=not direct_connection,
|
|
196
|
-
tlsallowinvalidhostnames=True,
|
|
197
|
-
tlsallowinvalidcertificates=True,
|
|
198
|
-
)
|
|
84
|
+
return bool(self.mongo_db_handler and self.mongo_db_handler.is_remote_database())
|
|
199
85
|
|
|
200
86
|
def generate_compound_indexes_for_databases(
|
|
201
87
|
self, db_name, db_simulation_model, db_simulation_model_version
|
|
@@ -211,53 +97,10 @@ class DatabaseHandler:
|
|
|
211
97
|
Name of the simulation model.
|
|
212
98
|
db_simulation_model_version: str
|
|
213
99
|
Version of the simulation model.
|
|
214
|
-
|
|
215
|
-
Raises
|
|
216
|
-
------
|
|
217
|
-
ValueError
|
|
218
|
-
If the requested database is not found.
|
|
219
|
-
|
|
220
100
|
"""
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
]
|
|
224
|
-
requested = self.get_db_name(
|
|
225
|
-
db_name=db_name,
|
|
226
|
-
db_simulation_model_version=db_simulation_model_version,
|
|
227
|
-
model_name=db_simulation_model,
|
|
101
|
+
self.mongo_db_handler.generate_compound_indexes_for_databases(
|
|
102
|
+
db_name, db_simulation_model, db_simulation_model_version
|
|
228
103
|
)
|
|
229
|
-
if requested != "all" and requested not in databases:
|
|
230
|
-
raise ValueError(
|
|
231
|
-
f"Requested database '{requested}' not found. "
|
|
232
|
-
f"Following databases are available: {', '.join(databases)}"
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
databases = databases if requested == "all" else [requested]
|
|
236
|
-
for dbs in databases:
|
|
237
|
-
self._logger.info(f"Generating compound indexes for database: {dbs}")
|
|
238
|
-
self.generate_compound_indexes(db_name=dbs)
|
|
239
|
-
|
|
240
|
-
def generate_compound_indexes(self, db_name=None):
|
|
241
|
-
"""
|
|
242
|
-
Generate compound indexes for the MongoDB collections.
|
|
243
|
-
|
|
244
|
-
Indexes based on the typical query patterns.
|
|
245
|
-
"""
|
|
246
|
-
db_name = db_name or self.db_name
|
|
247
|
-
collection_names = [
|
|
248
|
-
"telescopes",
|
|
249
|
-
"sites",
|
|
250
|
-
"configuration_sim_telarray",
|
|
251
|
-
"configuration_corsika",
|
|
252
|
-
"calibration_devices",
|
|
253
|
-
]
|
|
254
|
-
for collection_name in collection_names:
|
|
255
|
-
db_collection = self.get_collection(collection_name, db_name=db_name)
|
|
256
|
-
db_collection.create_index(
|
|
257
|
-
[("instrument", 1), ("site", 1), ("parameter", 1), ("parameter_version", 1)]
|
|
258
|
-
)
|
|
259
|
-
db_collection = self.get_collection("production_tables", db_name=db_name)
|
|
260
|
-
db_collection.create_index([("collection", 1), ("model_version", 1)])
|
|
261
104
|
|
|
262
105
|
def get_model_parameter(
|
|
263
106
|
self,
|
|
@@ -300,9 +143,7 @@ class DatabaseHandler:
|
|
|
300
143
|
model_version = resolve_version_to_latest_patch(
|
|
301
144
|
model_version, self.get_model_versions(collection_name)
|
|
302
145
|
)
|
|
303
|
-
production_table = self.
|
|
304
|
-
collection_name, model_version
|
|
305
|
-
)
|
|
146
|
+
production_table = self.read_production_table_from_db(collection_name, model_version)
|
|
306
147
|
array_element_list = self._get_array_element_list(
|
|
307
148
|
array_element_name, site, production_table, collection_name
|
|
308
149
|
)
|
|
@@ -322,7 +163,7 @@ class DatabaseHandler:
|
|
|
322
163
|
query["instrument"] = array_element_name
|
|
323
164
|
if site:
|
|
324
165
|
query["site"] = site
|
|
325
|
-
return self.
|
|
166
|
+
return self._read_db(query=query, collection_name=collection_name)
|
|
326
167
|
|
|
327
168
|
def get_model_parameters(self, site, array_element_name, collection, model_version):
|
|
328
169
|
"""
|
|
@@ -349,7 +190,7 @@ class DatabaseHandler:
|
|
|
349
190
|
model_version = resolve_version_to_latest_patch(
|
|
350
191
|
model_version, self.get_model_versions(collection)
|
|
351
192
|
)
|
|
352
|
-
production_table = self.
|
|
193
|
+
production_table = self.read_production_table_from_db(collection, model_version)
|
|
353
194
|
array_element_list = self._get_array_element_list(
|
|
354
195
|
array_element_name, site, production_table, collection
|
|
355
196
|
)
|
|
@@ -416,7 +257,7 @@ class DatabaseHandler:
|
|
|
416
257
|
parameter_version_table = production_table["parameters"][array_element]
|
|
417
258
|
except KeyError: # allow missing array elements (parameter dict is checked later)
|
|
418
259
|
return {}
|
|
419
|
-
DatabaseHandler.model_parameters_cached[cache_key] = self.
|
|
260
|
+
DatabaseHandler.model_parameters_cached[cache_key] = self._read_db(
|
|
420
261
|
query=self._get_query_from_parameter_version_table(
|
|
421
262
|
parameter_version_table, array_element, site
|
|
422
263
|
),
|
|
@@ -441,7 +282,7 @@ class DatabaseHandler:
|
|
|
441
282
|
The collection from the DB.
|
|
442
283
|
"""
|
|
443
284
|
db_name = db_name or self.db_name
|
|
444
|
-
return
|
|
285
|
+
return self.mongo_db_handler.get_collection(collection_name, db_name)
|
|
445
286
|
|
|
446
287
|
def get_collections(self, db_name=None, model_collections_only=False):
|
|
447
288
|
"""
|
|
@@ -458,17 +299,10 @@ class DatabaseHandler:
|
|
|
458
299
|
-------
|
|
459
300
|
list
|
|
460
301
|
List of collection names
|
|
461
|
-
|
|
462
302
|
"""
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
db_name
|
|
467
|
-
].list_collection_names()
|
|
468
|
-
collections = self.list_of_collections[db_name]
|
|
469
|
-
if model_collections_only:
|
|
470
|
-
return [collection for collection in collections if not collection.startswith("fs.")]
|
|
471
|
-
return collections
|
|
303
|
+
return self.mongo_db_handler.get_collections(
|
|
304
|
+
db_name or self.db_name, model_collections_only
|
|
305
|
+
)
|
|
472
306
|
|
|
473
307
|
def export_model_file(
|
|
474
308
|
self,
|
|
@@ -557,8 +391,8 @@ class DatabaseHandler:
|
|
|
557
391
|
if Path(dest).joinpath(file_name).exists():
|
|
558
392
|
instance_ids[file_name] = "file exists"
|
|
559
393
|
else:
|
|
560
|
-
file_path_instance = self.
|
|
561
|
-
self.
|
|
394
|
+
file_path_instance = self.mongo_db_handler.get_file_from_db(db_name, file_name)
|
|
395
|
+
self._write_file_from_db_to_disk(db_name, dest, file_path_instance)
|
|
562
396
|
instance_ids[file_name] = file_path_instance._id # pylint: disable=protected-access
|
|
563
397
|
return instance_ids
|
|
564
398
|
|
|
@@ -579,7 +413,7 @@ class DatabaseHandler:
|
|
|
579
413
|
query_dict["site"] = site
|
|
580
414
|
return query_dict
|
|
581
415
|
|
|
582
|
-
def
|
|
416
|
+
def _read_db(self, query, collection_name):
|
|
583
417
|
"""
|
|
584
418
|
Query MongoDB.
|
|
585
419
|
|
|
@@ -599,20 +433,17 @@ class DatabaseHandler:
|
|
|
599
433
|
ValueError
|
|
600
434
|
if query returned no results.
|
|
601
435
|
"""
|
|
602
|
-
|
|
603
|
-
posts = list(collection.find(query))
|
|
604
|
-
if not posts:
|
|
605
|
-
raise ValueError(
|
|
606
|
-
f"The following query for {collection_name} returned zero results: {query} "
|
|
607
|
-
)
|
|
436
|
+
posts = self.mongo_db_handler.query_db(query, collection_name, self.db_name)
|
|
608
437
|
parameters = {}
|
|
609
438
|
for post in posts:
|
|
610
439
|
par_now = post["parameter"]
|
|
611
440
|
parameters[par_now] = post
|
|
612
|
-
parameters[par_now]["entry_date"] =
|
|
441
|
+
parameters[par_now]["entry_date"] = self.mongo_db_handler.get_entry_date_from_document(
|
|
442
|
+
post
|
|
443
|
+
)
|
|
613
444
|
return {k: parameters[k] for k in sorted(parameters)}
|
|
614
445
|
|
|
615
|
-
def
|
|
446
|
+
def read_production_table_from_db(self, collection_name, model_version):
|
|
616
447
|
"""
|
|
617
448
|
Read production table for the given collection from MongoDB.
|
|
618
449
|
|
|
@@ -639,8 +470,7 @@ class DatabaseHandler:
|
|
|
639
470
|
pass
|
|
640
471
|
|
|
641
472
|
query = {"model_version": model_version, "collection": collection_name}
|
|
642
|
-
|
|
643
|
-
post = collection.find_one(query)
|
|
473
|
+
post = self.mongo_db_handler.find_one(query, "production_tables", self.db_name)
|
|
644
474
|
if not post:
|
|
645
475
|
raise ValueError(f"The following query returned zero results: {query}")
|
|
646
476
|
|
|
@@ -649,7 +479,7 @@ class DatabaseHandler:
|
|
|
649
479
|
"model_version": post["model_version"],
|
|
650
480
|
"parameters": post["parameters"],
|
|
651
481
|
"design_model": post.get("design_model", {}),
|
|
652
|
-
"entry_date":
|
|
482
|
+
"entry_date": self.mongo_db_handler.get_entry_date_from_document(post),
|
|
653
483
|
}
|
|
654
484
|
|
|
655
485
|
def get_model_versions(self, collection_name="telescopes"):
|
|
@@ -693,7 +523,7 @@ class DatabaseHandler:
|
|
|
693
523
|
model_version = resolve_version_to_latest_patch(
|
|
694
524
|
model_version, self.get_model_versions(collection)
|
|
695
525
|
)
|
|
696
|
-
production_table = self.
|
|
526
|
+
production_table = self.read_production_table_from_db(collection, model_version)
|
|
697
527
|
return sorted([entry for entry in production_table["parameters"] if "-design" not in entry])
|
|
698
528
|
|
|
699
529
|
def get_design_model(self, model_version, array_element_name, collection="telescopes"):
|
|
@@ -718,7 +548,7 @@ class DatabaseHandler:
|
|
|
718
548
|
model_version = resolve_version_to_latest_patch(
|
|
719
549
|
model_version, self.get_model_versions(collection)
|
|
720
550
|
)
|
|
721
|
-
production_table = self.
|
|
551
|
+
production_table = self.read_production_table_from_db(collection, model_version)
|
|
722
552
|
try:
|
|
723
553
|
return production_table["design_model"][array_element_name]
|
|
724
554
|
except KeyError:
|
|
@@ -749,7 +579,7 @@ class DatabaseHandler:
|
|
|
749
579
|
model_version = resolve_version_to_latest_patch(
|
|
750
580
|
model_version, self.get_model_versions(collection)
|
|
751
581
|
)
|
|
752
|
-
production_table = self.
|
|
582
|
+
production_table = self.read_production_table_from_db(collection, model_version)
|
|
753
583
|
all_array_elements = production_table["parameters"]
|
|
754
584
|
return sorted(
|
|
755
585
|
[
|
|
@@ -805,38 +635,7 @@ class DatabaseHandler:
|
|
|
805
635
|
)
|
|
806
636
|
raise ValueError(f"Unknown simulation software: {simulation_software}")
|
|
807
637
|
|
|
808
|
-
|
|
809
|
-
def _get_file_mongo_db(db_name, file_name):
|
|
810
|
-
"""
|
|
811
|
-
Extract a file from MongoDB and return GridFS file instance.
|
|
812
|
-
|
|
813
|
-
Parameters
|
|
814
|
-
----------
|
|
815
|
-
db_name: str
|
|
816
|
-
the name of the DB with files of tabulated data
|
|
817
|
-
file_name: str
|
|
818
|
-
The name of the file requested
|
|
819
|
-
|
|
820
|
-
Returns
|
|
821
|
-
-------
|
|
822
|
-
GridOut
|
|
823
|
-
A file instance returned by GridFS find_one
|
|
824
|
-
|
|
825
|
-
Raises
|
|
826
|
-
------
|
|
827
|
-
FileNotFoundError
|
|
828
|
-
If the desired file is not found.
|
|
829
|
-
|
|
830
|
-
"""
|
|
831
|
-
db = DatabaseHandler.db_client[db_name]
|
|
832
|
-
file_system = gridfs.GridFS(db)
|
|
833
|
-
if file_system.exists({"filename": file_name}):
|
|
834
|
-
return file_system.find_one({"filename": file_name})
|
|
835
|
-
|
|
836
|
-
raise FileNotFoundError(f"The file {file_name} does not exist in the database {db_name}")
|
|
837
|
-
|
|
838
|
-
@staticmethod
|
|
839
|
-
def _write_file_from_mongo_to_disk(db_name, path, file):
|
|
638
|
+
def _write_file_from_db_to_disk(self, db_name, path, file):
|
|
840
639
|
"""
|
|
841
640
|
Extract a file from MongoDB and write it to disk.
|
|
842
641
|
|
|
@@ -849,10 +648,7 @@ class DatabaseHandler:
|
|
|
849
648
|
file: GridOut
|
|
850
649
|
A file instance returned by GridFS find_one
|
|
851
650
|
"""
|
|
852
|
-
|
|
853
|
-
fs_output = gridfs.GridFSBucket(db)
|
|
854
|
-
with open(Path(path).joinpath(file.filename), "wb") as output_file:
|
|
855
|
-
fs_output.download_to_stream_by_name(file.filename, output_file)
|
|
651
|
+
self.mongo_db_handler.write_file_from_db_to_disk(db_name, path, file)
|
|
856
652
|
|
|
857
653
|
def get_ecsv_file_as_astropy_table(self, file_name, db_name=None):
|
|
858
654
|
"""
|
|
@@ -872,16 +668,9 @@ class DatabaseHandler:
|
|
|
872
668
|
astropy.table.Table
|
|
873
669
|
The contents of the ECSV file as an Astropy Table.
|
|
874
670
|
"""
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
buf = io.BytesIO()
|
|
879
|
-
try:
|
|
880
|
-
fs.download_to_stream_by_name(file_name, buf)
|
|
881
|
-
except gridfs.errors.NoFile as exc:
|
|
882
|
-
raise FileNotFoundError(f"ECSV file '{file_name}' not found in DB.") from exc
|
|
883
|
-
buf.seek(0)
|
|
884
|
-
return Table.read(buf.getvalue().decode("utf-8"), format="ascii.ecsv")
|
|
671
|
+
return self.mongo_db_handler.get_ecsv_file_as_astropy_table(
|
|
672
|
+
file_name, db_name or self.db_name
|
|
673
|
+
)
|
|
885
674
|
|
|
886
675
|
def add_production_table(self, production_table, db_name=None):
|
|
887
676
|
"""
|
|
@@ -894,10 +683,10 @@ class DatabaseHandler:
|
|
|
894
683
|
db_name: str
|
|
895
684
|
the name of the DB.
|
|
896
685
|
"""
|
|
897
|
-
db_name = db_name or self.db_name
|
|
898
|
-
collection = self.get_collection("production_tables", db_name=db_name or self.db_name)
|
|
899
686
|
self._logger.debug(f"Adding production for {production_table.get('collection')} to the DB")
|
|
900
|
-
|
|
687
|
+
self.mongo_db_handler.insert_one(
|
|
688
|
+
production_table, "production_tables", db_name or self.db_name
|
|
689
|
+
)
|
|
901
690
|
DatabaseHandler.production_table_cached.clear()
|
|
902
691
|
DatabaseHandler.model_versions_cached.clear()
|
|
903
692
|
|
|
@@ -928,7 +717,6 @@ class DatabaseHandler:
|
|
|
928
717
|
par_dict = validate_data.DataValidator.validate_model_parameter(par_dict)
|
|
929
718
|
|
|
930
719
|
db_name = db_name or self.db_name
|
|
931
|
-
collection = self.get_collection(collection_name, db_name=db_name)
|
|
932
720
|
|
|
933
721
|
par_dict["value"], _base_unit, _ = value_conversion.get_value_unit_type(
|
|
934
722
|
value=par_dict["value"], unit_str=par_dict.get("unit", None)
|
|
@@ -943,14 +731,12 @@ class DatabaseHandler:
|
|
|
943
731
|
f"corresponding to the {par_dict['parameter']} parameter, must be provided."
|
|
944
732
|
)
|
|
945
733
|
file_path = Path(file_prefix).joinpath(par_dict["value"])
|
|
946
|
-
if not ascii_handler.is_utf8_file(file_path):
|
|
947
|
-
raise ValueError(f"File is not UTF-8 encoded: {file_path}")
|
|
948
734
|
files_to_add_to_db.add(f"{file_path}")
|
|
949
735
|
|
|
950
736
|
self._logger.debug(
|
|
951
737
|
f"Adding a new entry to DB {db_name} and collection {collection_name}:\n{par_dict}"
|
|
952
738
|
)
|
|
953
|
-
|
|
739
|
+
self.mongo_db_handler.insert_one(par_dict, collection_name, db_name)
|
|
954
740
|
|
|
955
741
|
for file_to_insert_now in files_to_add_to_db:
|
|
956
742
|
self._logger.debug(f"Will also add the file {file_to_insert_now} to the DB")
|
|
@@ -958,7 +744,7 @@ class DatabaseHandler:
|
|
|
958
744
|
|
|
959
745
|
self._reset_parameter_cache()
|
|
960
746
|
|
|
961
|
-
def insert_file_to_db(self, file_name, db_name=None
|
|
747
|
+
def insert_file_to_db(self, file_name, db_name=None):
|
|
962
748
|
"""
|
|
963
749
|
Insert a file to the DB.
|
|
964
750
|
|
|
@@ -968,35 +754,14 @@ class DatabaseHandler:
|
|
|
968
754
|
The name of the file to insert (full path).
|
|
969
755
|
db_name: str
|
|
970
756
|
the name of the DB
|
|
971
|
-
**kwargs (optional): keyword arguments for file creation.
|
|
972
|
-
The full list of arguments can be found in, \
|
|
973
|
-
https://www.mongodb.com/docs/manual/core/gridfs/
|
|
974
|
-
mostly these are unnecessary though.
|
|
975
757
|
|
|
976
758
|
Returns
|
|
977
759
|
-------
|
|
978
|
-
|
|
979
|
-
If the file exists, return its GridOut._id, otherwise insert the file and return
|
|
980
|
-
|
|
981
|
-
|
|
760
|
+
file_id: GridOut._id
|
|
761
|
+
If the file exists, return its GridOut._id, otherwise insert the file and return
|
|
762
|
+
its newly created DB GridOut._id.
|
|
982
763
|
"""
|
|
983
|
-
|
|
984
|
-
db = DatabaseHandler.db_client[db_name]
|
|
985
|
-
file_system = gridfs.GridFS(db)
|
|
986
|
-
|
|
987
|
-
kwargs.setdefault("content_type", "ascii/dat")
|
|
988
|
-
kwargs.setdefault("filename", Path(file_name).name)
|
|
989
|
-
|
|
990
|
-
if file_system.exists({"filename": kwargs["filename"]}):
|
|
991
|
-
self._logger.warning(
|
|
992
|
-
f"The file {kwargs['filename']} exists in the DB. Returning its ID"
|
|
993
|
-
)
|
|
994
|
-
return file_system.find_one( # pylint: disable=protected-access
|
|
995
|
-
{"filename": kwargs["filename"]}
|
|
996
|
-
)._id
|
|
997
|
-
self._logger.debug(f"Writing file to DB: {file_name}")
|
|
998
|
-
with open(file_name, "rb") as data_file:
|
|
999
|
-
return file_system.put(data_file, **kwargs)
|
|
764
|
+
return self.mongo_db_handler.insert_file_to_db(file_name, db_name or self.db_name)
|
|
1000
765
|
|
|
1001
766
|
def _cache_key(self, site=None, array_element_name=None, model_version=None, collection=None):
|
|
1002
767
|
"""
|
|
@@ -1087,7 +852,7 @@ class DatabaseHandler:
|
|
|
1087
852
|
return [array_element_name]
|
|
1088
853
|
if collection == "configuration_sim_telarray":
|
|
1089
854
|
# get design model from 'telescope' or 'calibration_device' production tables
|
|
1090
|
-
production_table = self.
|
|
855
|
+
production_table = self.read_production_table_from_db(
|
|
1091
856
|
names.get_collection_name_from_array_element_name(array_element_name),
|
|
1092
857
|
production_table["model_version"],
|
|
1093
858
|
)
|
simtools/db/db_model_upload.py
CHANGED
|
@@ -288,7 +288,7 @@ def _confirm_remote_database_upload(db):
|
|
|
288
288
|
if not db.is_remote_database():
|
|
289
289
|
return True
|
|
290
290
|
|
|
291
|
-
db_config = db.
|
|
291
|
+
db_config = db.db_config
|
|
292
292
|
db_server = db_config.get("db_server", "unknown server") if db_config else "unknown server"
|
|
293
293
|
|
|
294
294
|
try:
|