gammasimtools 0.19.0__py3-none-any.whl → 0.21.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.19.0.dist-info → gammasimtools-0.21.0.dist-info}/METADATA +1 -3
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/RECORD +54 -51
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/entry_points.txt +3 -3
- simtools/_version.py +2 -2
- simtools/applications/calculate_incident_angles.py +182 -0
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +17 -14
- simtools/applications/db_add_value_from_json_to_db.py +6 -9
- simtools/applications/db_generate_compound_indexes.py +7 -3
- simtools/applications/db_get_file_from_db.py +11 -23
- simtools/applications/derive_psf_parameters.py +58 -39
- simtools/applications/derive_trigger_rates.py +91 -0
- simtools/applications/generate_corsika_histograms.py +7 -184
- simtools/applications/maintain_simulation_model_add_production.py +105 -0
- simtools/applications/plot_simtel_events.py +5 -189
- simtools/applications/print_version.py +8 -7
- simtools/applications/validate_file_using_schema.py +7 -4
- simtools/configuration/commandline_parser.py +17 -11
- simtools/corsika/corsika_histograms.py +81 -0
- simtools/data_model/validate_data.py +8 -3
- simtools/db/db_handler.py +122 -31
- simtools/db/db_model_upload.py +51 -30
- simtools/dependencies.py +10 -5
- simtools/layout/array_layout_utils.py +37 -5
- simtools/model/array_model.py +18 -1
- simtools/model/model_repository.py +118 -63
- simtools/model/site_model.py +25 -0
- simtools/production_configuration/derive_corsika_limits.py +9 -34
- simtools/ray_tracing/incident_angles.py +706 -0
- simtools/ray_tracing/psf_parameter_optimisation.py +999 -565
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +2 -2
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_spectrum.schema.yml +22 -29
- simtools/schemas/model_parameters/stars.schema.yml +1 -1
- simtools/schemas/production_tables.schema.yml +5 -0
- simtools/simtel/simtel_config_writer.py +18 -20
- simtools/simtel/simtel_io_event_histograms.py +253 -516
- simtools/simtel/simtel_io_event_reader.py +51 -2
- simtools/simtel/simtel_io_event_writer.py +31 -11
- simtools/simtel/simtel_io_metadata.py +1 -1
- simtools/simtel/simtel_table_reader.py +3 -3
- simtools/simulator.py +1 -4
- simtools/telescope_trigger_rates.py +119 -0
- simtools/testing/log_inspector.py +13 -11
- simtools/utils/geometry.py +20 -0
- simtools/version.py +89 -0
- simtools/{corsika/corsika_histograms_visualize.py → visualization/plot_corsika_histograms.py} +109 -0
- simtools/visualization/plot_incident_angles.py +431 -0
- simtools/visualization/plot_psf.py +673 -0
- simtools/visualization/plot_simtel_event_histograms.py +376 -0
- simtools/visualization/{simtel_event_plots.py → plot_simtel_events.py} +284 -87
- simtools/visualization/visualize.py +1 -3
- simtools/applications/calculate_trigger_rate.py +0 -187
- simtools/applications/generate_sim_telarray_histograms.py +0 -196
- simtools/applications/maintain_simulation_model_add_production_table.py +0 -71
- simtools/simtel/simtel_io_histogram.py +0 -623
- simtools/simtel/simtel_io_histograms.py +0 -556
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/licenses/LICENSE +0 -0
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/top_level.txt +0 -0
simtools/db/db_handler.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Module to handle interaction with DB."""
|
|
2
2
|
|
|
3
|
+
import io
|
|
3
4
|
import logging
|
|
4
5
|
import re
|
|
5
6
|
from collections import defaultdict
|
|
@@ -8,6 +9,7 @@ from threading import Lock
|
|
|
8
9
|
|
|
9
10
|
import gridfs
|
|
10
11
|
import jsonschema
|
|
12
|
+
from astropy.table import Table
|
|
11
13
|
from bson.objectid import ObjectId
|
|
12
14
|
from packaging.version import Version
|
|
13
15
|
from pymongo import MongoClient
|
|
@@ -16,6 +18,7 @@ from simtools.data_model import validate_data
|
|
|
16
18
|
from simtools.io import ascii_handler, io_handler
|
|
17
19
|
from simtools.simtel import simtel_table_reader
|
|
18
20
|
from simtools.utils import names, value_conversion
|
|
21
|
+
from simtools.version import resolve_version_to_latest_patch
|
|
19
22
|
|
|
20
23
|
__all__ = ["DatabaseHandler"]
|
|
21
24
|
|
|
@@ -50,8 +53,19 @@ jsonschema_db_dict = {
|
|
|
50
53
|
"type": "string",
|
|
51
54
|
"description": "Name of simulation model database",
|
|
52
55
|
},
|
|
56
|
+
"db_simulation_model_version": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"description": "Version of simulation model database",
|
|
59
|
+
},
|
|
53
60
|
},
|
|
54
|
-
"required": [
|
|
61
|
+
"required": [
|
|
62
|
+
"db_server",
|
|
63
|
+
"db_api_port",
|
|
64
|
+
"db_api_user",
|
|
65
|
+
"db_api_pw",
|
|
66
|
+
"db_simulation_model",
|
|
67
|
+
"db_simulation_model_version",
|
|
68
|
+
],
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
|
|
@@ -59,6 +73,11 @@ class DatabaseHandler:
|
|
|
59
73
|
"""
|
|
60
74
|
DatabaseHandler provides the interface to the DB.
|
|
61
75
|
|
|
76
|
+
Note the two types of version variables used in this class:
|
|
77
|
+
|
|
78
|
+
- db_simulation_model_version (from mongo_db_config): version of the simulation model database
|
|
79
|
+
- model_version (from production_tables): version of the model contained in the database
|
|
80
|
+
|
|
62
81
|
Parameters
|
|
63
82
|
----------
|
|
64
83
|
mongo_db_config: dict
|
|
@@ -70,6 +89,7 @@ class DatabaseHandler:
|
|
|
70
89
|
db_client = None
|
|
71
90
|
production_table_cached = {}
|
|
72
91
|
model_parameters_cached = {}
|
|
92
|
+
model_versions_cached = {}
|
|
73
93
|
|
|
74
94
|
def __init__(self, mongo_db_config=None):
|
|
75
95
|
"""Initialize the DatabaseHandler class."""
|
|
@@ -82,7 +102,12 @@ class DatabaseHandler:
|
|
|
82
102
|
self._set_up_connection()
|
|
83
103
|
self._find_latest_simulation_model_db()
|
|
84
104
|
self.db_name = (
|
|
85
|
-
self.
|
|
105
|
+
self.get_db_name(
|
|
106
|
+
db_simulation_model_version=self.mongo_db_config.get("db_simulation_model_version"),
|
|
107
|
+
model_name=self.mongo_db_config.get("db_simulation_model"),
|
|
108
|
+
)
|
|
109
|
+
if self.mongo_db_config
|
|
110
|
+
else None
|
|
86
111
|
)
|
|
87
112
|
|
|
88
113
|
def _set_up_connection(self):
|
|
@@ -92,6 +117,16 @@ class DatabaseHandler:
|
|
|
92
117
|
with lock:
|
|
93
118
|
DatabaseHandler.db_client = self._open_mongo_db()
|
|
94
119
|
|
|
120
|
+
def get_db_name(self, db_name=None, db_simulation_model_version=None, model_name=None):
|
|
121
|
+
"""Build DB name from configuration."""
|
|
122
|
+
if db_name:
|
|
123
|
+
return db_name
|
|
124
|
+
if db_simulation_model_version and model_name:
|
|
125
|
+
return f"{model_name}-{db_simulation_model_version.replace('.', '-')}"
|
|
126
|
+
if db_simulation_model_version or model_name:
|
|
127
|
+
return None
|
|
128
|
+
return None if (db_simulation_model_version or model_name) else self.db_name
|
|
129
|
+
|
|
95
130
|
def _validate_mongo_db_config(self, mongo_db_config):
|
|
96
131
|
"""Validate the MongoDB configuration."""
|
|
97
132
|
if mongo_db_config is None or all(value is None for value in mongo_db_config.values()):
|
|
@@ -140,8 +175,7 @@ class DatabaseHandler:
|
|
|
140
175
|
"""
|
|
141
176
|
Find the latest released version of the simulation model and update the DB config.
|
|
142
177
|
|
|
143
|
-
This is indicated by
|
|
144
|
-
(field "db_simulation_model" in the database configuration dictionary).
|
|
178
|
+
This is indicated by "LATEST" to the simulation model data base version.
|
|
145
179
|
Only released versions are considered, pre-releases are ignored.
|
|
146
180
|
|
|
147
181
|
Raises
|
|
@@ -151,27 +185,27 @@ class DatabaseHandler:
|
|
|
151
185
|
|
|
152
186
|
"""
|
|
153
187
|
try:
|
|
188
|
+
db_simulation_model_version = self.mongo_db_config["db_simulation_model_version"]
|
|
154
189
|
db_simulation_model = self.mongo_db_config["db_simulation_model"]
|
|
155
|
-
if
|
|
190
|
+
if db_simulation_model_version != "LATEST":
|
|
156
191
|
return
|
|
157
|
-
except TypeError: #
|
|
192
|
+
except TypeError: # db_simulation_model_version is None
|
|
158
193
|
return
|
|
159
194
|
|
|
160
|
-
prefix = db_simulation_model.replace("LATEST", "")
|
|
161
195
|
list_of_db_names = self.db_client.list_database_names()
|
|
162
|
-
filtered_list_of_db_names = [
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
)
|
|
196
|
+
filtered_list_of_db_names = [
|
|
197
|
+
s for s in list_of_db_names if s.startswith(db_simulation_model)
|
|
198
|
+
]
|
|
199
|
+
pattern = re.compile(rf"{re.escape(db_simulation_model)}-v(\d+)-(\d+)-(\d+)(?:-(.+))?$")
|
|
167
200
|
|
|
201
|
+
versioned_strings = []
|
|
168
202
|
for s in filtered_list_of_db_names:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
203
|
+
m = pattern.match(s)
|
|
204
|
+
if m:
|
|
205
|
+
# skip pre-releases (have suffix)
|
|
206
|
+
if m.group(4) is None:
|
|
207
|
+
version_str = f"{m.group(1)}.{m.group(2)}.{m.group(3)}"
|
|
208
|
+
versioned_strings.append((s, Version(version_str)))
|
|
175
209
|
|
|
176
210
|
if versioned_strings:
|
|
177
211
|
latest_string, _ = max(versioned_strings, key=lambda x: x[1])
|
|
@@ -180,7 +214,7 @@ class DatabaseHandler:
|
|
|
180
214
|
f"Updated the DB simulation model to the latest version {latest_string}"
|
|
181
215
|
)
|
|
182
216
|
else:
|
|
183
|
-
raise ValueError("
|
|
217
|
+
raise ValueError("LATEST requested but no released versions found in DB.")
|
|
184
218
|
|
|
185
219
|
def generate_compound_indexes(self, db_name=None):
|
|
186
220
|
"""
|
|
@@ -242,6 +276,9 @@ class DatabaseHandler:
|
|
|
242
276
|
raise ValueError(
|
|
243
277
|
"Only one model version can be passed to get_model_parameter, not a list."
|
|
244
278
|
)
|
|
279
|
+
model_version = resolve_version_to_latest_patch(
|
|
280
|
+
model_version, self.get_model_versions(collection_name)
|
|
281
|
+
)
|
|
245
282
|
production_table = self.read_production_table_from_mongo_db(
|
|
246
283
|
collection_name, model_version
|
|
247
284
|
)
|
|
@@ -288,6 +325,9 @@ class DatabaseHandler:
|
|
|
288
325
|
dict containing the parameters
|
|
289
326
|
"""
|
|
290
327
|
pars = {}
|
|
328
|
+
model_version = resolve_version_to_latest_patch(
|
|
329
|
+
model_version, self.get_model_versions(collection)
|
|
330
|
+
)
|
|
291
331
|
production_table = self.read_production_table_from_mongo_db(collection, model_version)
|
|
292
332
|
array_element_list = self._get_array_element_list(
|
|
293
333
|
array_element_name, site, production_table, collection
|
|
@@ -334,6 +374,11 @@ class DatabaseHandler:
|
|
|
334
374
|
def _get_parameter_for_model_version(
|
|
335
375
|
self, array_element, model_version, site, collection, production_table
|
|
336
376
|
):
|
|
377
|
+
"""
|
|
378
|
+
Get parameters for a specific model version and array element.
|
|
379
|
+
|
|
380
|
+
Uses caching wherever possible.
|
|
381
|
+
"""
|
|
337
382
|
cache_key, cache_dict = self._read_cache(
|
|
338
383
|
DatabaseHandler.model_parameters_cached,
|
|
339
384
|
names.validate_site_name(site) if site else None,
|
|
@@ -562,6 +607,9 @@ class DatabaseHandler:
|
|
|
562
607
|
ValueError
|
|
563
608
|
if query returned no results.
|
|
564
609
|
"""
|
|
610
|
+
model_version = resolve_version_to_latest_patch(
|
|
611
|
+
model_version, self.get_model_versions(collection_name)
|
|
612
|
+
)
|
|
565
613
|
try:
|
|
566
614
|
return DatabaseHandler.production_table_cached[
|
|
567
615
|
self._cache_key(None, None, model_version, collection_name)
|
|
@@ -585,7 +633,7 @@ class DatabaseHandler:
|
|
|
585
633
|
|
|
586
634
|
def get_model_versions(self, collection_name="telescopes"):
|
|
587
635
|
"""
|
|
588
|
-
Get list of model versions from the DB.
|
|
636
|
+
Get list of model versions from the DB with caching.
|
|
589
637
|
|
|
590
638
|
Parameters
|
|
591
639
|
----------
|
|
@@ -597,10 +645,12 @@ class DatabaseHandler:
|
|
|
597
645
|
list
|
|
598
646
|
List of model versions
|
|
599
647
|
"""
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
648
|
+
if collection_name not in DatabaseHandler.model_versions_cached:
|
|
649
|
+
collection = self.get_collection("production_tables", db_name=self.db_name)
|
|
650
|
+
DatabaseHandler.model_versions_cached[collection_name] = sorted(
|
|
651
|
+
{post["model_version"] for post in collection.find({"collection": collection_name})}
|
|
652
|
+
)
|
|
653
|
+
return DatabaseHandler.model_versions_cached[collection_name]
|
|
604
654
|
|
|
605
655
|
def get_array_elements(self, model_version, collection="telescopes"):
|
|
606
656
|
"""
|
|
@@ -619,6 +669,9 @@ class DatabaseHandler:
|
|
|
619
669
|
list
|
|
620
670
|
Sorted list of all array elements found in collection
|
|
621
671
|
"""
|
|
672
|
+
model_version = resolve_version_to_latest_patch(
|
|
673
|
+
model_version, self.get_model_versions(collection)
|
|
674
|
+
)
|
|
622
675
|
production_table = self.read_production_table_from_mongo_db(collection, model_version)
|
|
623
676
|
return sorted([entry for entry in production_table["parameters"] if "-design" not in entry])
|
|
624
677
|
|
|
@@ -641,6 +694,9 @@ class DatabaseHandler:
|
|
|
641
694
|
str
|
|
642
695
|
Design model for a given array element.
|
|
643
696
|
"""
|
|
697
|
+
model_version = resolve_version_to_latest_patch(
|
|
698
|
+
model_version, self.get_model_versions(collection)
|
|
699
|
+
)
|
|
644
700
|
production_table = self.read_production_table_from_mongo_db(collection, model_version)
|
|
645
701
|
try:
|
|
646
702
|
return production_table["design_model"][array_element_name]
|
|
@@ -669,6 +725,9 @@ class DatabaseHandler:
|
|
|
669
725
|
list
|
|
670
726
|
Sorted list of all array element names found in collection
|
|
671
727
|
"""
|
|
728
|
+
model_version = resolve_version_to_latest_patch(
|
|
729
|
+
model_version, self.get_model_versions(collection)
|
|
730
|
+
)
|
|
672
731
|
production_table = self.read_production_table_from_mongo_db(collection, model_version)
|
|
673
732
|
all_array_elements = production_table["parameters"]
|
|
674
733
|
return sorted(
|
|
@@ -774,26 +833,57 @@ class DatabaseHandler:
|
|
|
774
833
|
with open(Path(path).joinpath(file.filename), "wb") as output_file:
|
|
775
834
|
fs_output.download_to_stream_by_name(file.filename, output_file)
|
|
776
835
|
|
|
777
|
-
def
|
|
836
|
+
def get_ecsv_file_as_astropy_table(self, file_name, db_name=None):
|
|
778
837
|
"""
|
|
779
|
-
|
|
838
|
+
Read contents of an ECSV file from the database and return it as an Astropy Table.
|
|
839
|
+
|
|
840
|
+
Files are not written to disk.
|
|
780
841
|
|
|
781
842
|
Parameters
|
|
782
843
|
----------
|
|
844
|
+
file_name: str
|
|
845
|
+
The name of the ECSV file.
|
|
783
846
|
db_name: str
|
|
784
|
-
|
|
847
|
+
The name of the database.
|
|
848
|
+
|
|
849
|
+
Returns
|
|
850
|
+
-------
|
|
851
|
+
astropy.table.Table
|
|
852
|
+
The contents of the ECSV file as an Astropy Table.
|
|
853
|
+
"""
|
|
854
|
+
db = DatabaseHandler.db_client[db_name or self.db_name]
|
|
855
|
+
fs = gridfs.GridFSBucket(db)
|
|
856
|
+
|
|
857
|
+
buf = io.BytesIO()
|
|
858
|
+
try:
|
|
859
|
+
fs.download_to_stream_by_name(file_name, buf)
|
|
860
|
+
except gridfs.errors.NoFile as exc:
|
|
861
|
+
raise FileNotFoundError(f"ECSV file '{file_name}' not found in DB.") from exc
|
|
862
|
+
buf.seek(0)
|
|
863
|
+
return Table.read(buf.getvalue().decode("utf-8"), format="ascii.ecsv")
|
|
864
|
+
|
|
865
|
+
def add_production_table(self, production_table, db_name=None):
|
|
866
|
+
"""
|
|
867
|
+
Add a production table to the DB.
|
|
868
|
+
|
|
869
|
+
Parameters
|
|
870
|
+
----------
|
|
785
871
|
production_table: dict
|
|
786
872
|
The production table to add to the DB.
|
|
873
|
+
db_name: str
|
|
874
|
+
the name of the DB.
|
|
787
875
|
"""
|
|
876
|
+
db_name = db_name or self.db_name
|
|
788
877
|
collection = self.get_collection("production_tables", db_name=db_name or self.db_name)
|
|
789
878
|
self._logger.debug(f"Adding production for {production_table.get('collection')} to to DB")
|
|
790
879
|
collection.insert_one(production_table)
|
|
791
880
|
DatabaseHandler.production_table_cached.clear()
|
|
881
|
+
DatabaseHandler.model_versions_cached.clear()
|
|
792
882
|
|
|
793
883
|
def add_new_parameter(
|
|
794
884
|
self,
|
|
795
|
-
db_name,
|
|
796
885
|
par_dict,
|
|
886
|
+
db_name=None,
|
|
797
887
|
collection_name="telescopes",
|
|
798
888
|
file_prefix=None,
|
|
799
889
|
):
|
|
@@ -805,10 +895,10 @@ class DatabaseHandler:
|
|
|
805
895
|
|
|
806
896
|
Parameters
|
|
807
897
|
----------
|
|
808
|
-
db_name: str
|
|
809
|
-
the name of the DB
|
|
810
898
|
par_dict: dict
|
|
811
899
|
dictionary with parameter data
|
|
900
|
+
db_name: str
|
|
901
|
+
the name of the DB
|
|
812
902
|
collection_name: str
|
|
813
903
|
The name of the collection to add a parameter to.
|
|
814
904
|
file_prefix: str or Path
|
|
@@ -859,7 +949,7 @@ class DatabaseHandler:
|
|
|
859
949
|
the name of the DB
|
|
860
950
|
**kwargs (optional): keyword arguments for file creation.
|
|
861
951
|
The full list of arguments can be found in, \
|
|
862
|
-
https://
|
|
952
|
+
https://www.mongodb.com/docs/manual/core/gridfs/
|
|
863
953
|
mostly these are unnecessary though.
|
|
864
954
|
|
|
865
955
|
Returns
|
|
@@ -944,6 +1034,7 @@ class DatabaseHandler:
|
|
|
944
1034
|
def _reset_parameter_cache(self):
|
|
945
1035
|
"""Reset the cache for the parameters."""
|
|
946
1036
|
DatabaseHandler.model_parameters_cached.clear()
|
|
1037
|
+
DatabaseHandler.model_versions_cached.clear()
|
|
947
1038
|
|
|
948
1039
|
def _get_array_element_list(self, array_element_name, site, production_table, collection):
|
|
949
1040
|
"""
|
simtools/db/db_model_upload.py
CHANGED
|
@@ -3,26 +3,26 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
+
from packaging.version import Version
|
|
7
|
+
|
|
6
8
|
from simtools.io import ascii_handler
|
|
7
9
|
from simtools.utils import names
|
|
8
10
|
|
|
9
11
|
logger = logging.getLogger(__name__)
|
|
10
12
|
|
|
11
13
|
|
|
12
|
-
def add_values_from_json_to_db(file, collection, db,
|
|
14
|
+
def add_values_from_json_to_db(file, collection, db, file_prefix):
|
|
13
15
|
"""
|
|
14
16
|
Upload new model parameter from json files to db.
|
|
15
17
|
|
|
16
18
|
Parameters
|
|
17
19
|
----------
|
|
18
20
|
file : list
|
|
19
|
-
|
|
21
|
+
JSON file to be uploaded to the DB.
|
|
20
22
|
collection : str
|
|
21
23
|
The DB collection to which to add the file.
|
|
22
24
|
db : DatabaseHandler
|
|
23
25
|
Database handler object.
|
|
24
|
-
db_name : str
|
|
25
|
-
Name of the database to be created.
|
|
26
26
|
file_prefix : str
|
|
27
27
|
Path to location of all additional files to be uploaded.
|
|
28
28
|
"""
|
|
@@ -30,32 +30,30 @@ def add_values_from_json_to_db(file, collection, db, db_name, file_prefix):
|
|
|
30
30
|
logger.debug(
|
|
31
31
|
f"Adding the following parameter to the DB: {par_dict['parameter']} "
|
|
32
32
|
f"version {par_dict['parameter_version']} "
|
|
33
|
-
f"(collection {collection} in database {
|
|
33
|
+
f"(collection {collection} in database {db.get_db_name()})"
|
|
34
34
|
)
|
|
35
35
|
|
|
36
36
|
db.add_new_parameter(
|
|
37
|
-
db_name=db_name,
|
|
38
37
|
par_dict=par_dict,
|
|
39
38
|
collection_name=collection,
|
|
40
39
|
file_prefix=file_prefix,
|
|
41
40
|
)
|
|
42
41
|
|
|
43
42
|
|
|
44
|
-
def add_model_parameters_to_db(
|
|
43
|
+
def add_model_parameters_to_db(input_path, db):
|
|
45
44
|
"""
|
|
46
45
|
Read model parameters from a directory and upload them to the database.
|
|
47
46
|
|
|
48
47
|
Parameters
|
|
49
48
|
----------
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
input_path : Path, str
|
|
50
|
+
Path to the directory containing the model parameters.
|
|
52
51
|
db : DatabaseHandler
|
|
53
52
|
Database handler object.
|
|
54
53
|
"""
|
|
55
|
-
input_path = Path(
|
|
54
|
+
input_path = Path(input_path)
|
|
56
55
|
logger.info(f"Reading model parameters from repository path {input_path}")
|
|
57
|
-
|
|
58
|
-
for element in array_elements:
|
|
56
|
+
for element in filter(Path.is_dir, input_path.iterdir()):
|
|
59
57
|
collection = names.get_collection_name_from_array_element_name(element.name, False)
|
|
60
58
|
if collection == "Files":
|
|
61
59
|
logger.info("Files (tables) are uploaded with the corresponding model parameters")
|
|
@@ -67,12 +65,11 @@ def add_model_parameters_to_db(args_dict, db):
|
|
|
67
65
|
file=file,
|
|
68
66
|
collection=collection,
|
|
69
67
|
db=db,
|
|
70
|
-
db_name=args_dict["db_name"],
|
|
71
68
|
file_prefix=input_path / "Files",
|
|
72
69
|
)
|
|
73
70
|
|
|
74
71
|
|
|
75
|
-
def add_production_tables_to_db(
|
|
72
|
+
def add_production_tables_to_db(input_path, db):
|
|
76
73
|
"""
|
|
77
74
|
Read production tables from a directory and upload them to the database.
|
|
78
75
|
|
|
@@ -81,29 +78,50 @@ def add_production_tables_to_db(args_dict, db):
|
|
|
81
78
|
|
|
82
79
|
Parameters
|
|
83
80
|
----------
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
input_path : Path, str
|
|
82
|
+
Path to the directory containing the production tables.
|
|
86
83
|
db : DatabaseHandler
|
|
87
84
|
Database handler object.
|
|
88
85
|
"""
|
|
89
|
-
input_path = Path(
|
|
86
|
+
input_path = Path(input_path)
|
|
90
87
|
logger.info(f"Reading production tables from repository path {input_path}")
|
|
91
88
|
|
|
92
89
|
for model in filter(Path.is_dir, input_path.iterdir()):
|
|
93
90
|
logger.info(f"Reading production tables for model version {model.name}")
|
|
94
|
-
model_dict =
|
|
95
|
-
for file in sorted(model.rglob("*json")):
|
|
96
|
-
_read_production_table(model_dict, file, model.name)
|
|
91
|
+
model_dict = _read_production_tables(model)
|
|
97
92
|
|
|
98
93
|
for collection, data in model_dict.items():
|
|
99
|
-
if
|
|
94
|
+
if data["parameters"]:
|
|
95
|
+
logger.info(f"Adding production table for {collection} to the database")
|
|
96
|
+
db.add_production_table(production_table=data)
|
|
97
|
+
else:
|
|
100
98
|
logger.info(f"No production table for {collection} in model version {model.name}")
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _read_production_tables(model_path):
|
|
102
|
+
"""
|
|
103
|
+
Read production tables from a directory.
|
|
104
|
+
|
|
105
|
+
Take into account that some productions include patch updates only. Read in this cases
|
|
106
|
+
the base models first.
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
model_path : Path
|
|
111
|
+
Path to the directory containing the production tables for a specific model version.
|
|
112
|
+
"""
|
|
113
|
+
model_dict = {}
|
|
114
|
+
models = [model_path.name]
|
|
115
|
+
if (model_path / "info.yml").exists():
|
|
116
|
+
info = ascii_handler.collect_data_from_file(file_name=model_path / "info.yml")
|
|
117
|
+
models.extend(info.get("model_version_history", []))
|
|
118
|
+
# sort oldest --> newest
|
|
119
|
+
models = sorted(set(models), key=Version, reverse=False)
|
|
120
|
+
for model in models:
|
|
121
|
+
for file in sorted((model_path.parent / model).rglob("*json")):
|
|
122
|
+
_read_production_table(model_dict, file, model)
|
|
123
|
+
|
|
124
|
+
return model_dict
|
|
107
125
|
|
|
108
126
|
|
|
109
127
|
def _read_production_table(model_dict, file, model_name):
|
|
@@ -125,9 +143,10 @@ def _read_production_table(model_dict, file, model_name):
|
|
|
125
143
|
if array_element in ("configuration_corsika", "configuration_sim_telarray"):
|
|
126
144
|
model_dict[collection]["parameters"] = parameter_dict["parameters"]
|
|
127
145
|
else:
|
|
128
|
-
model_dict[collection]["parameters"]
|
|
129
|
-
array_element
|
|
130
|
-
|
|
146
|
+
model_dict[collection]["parameters"].setdefault(array_element, {}).update(
|
|
147
|
+
parameter_dict["parameters"][array_element]
|
|
148
|
+
)
|
|
149
|
+
|
|
131
150
|
except KeyError as exc:
|
|
132
151
|
logger.error(f"KeyError: {exc}")
|
|
133
152
|
raise
|
|
@@ -137,3 +156,5 @@ def _read_production_table(model_dict, file, model_name):
|
|
|
137
156
|
]
|
|
138
157
|
except KeyError:
|
|
139
158
|
pass
|
|
159
|
+
|
|
160
|
+
model_dict[collection]["model_version"] = model_name
|
simtools/dependencies.py
CHANGED
|
@@ -40,7 +40,8 @@ def get_version_string(db_config=None, run_time=None):
|
|
|
40
40
|
|
|
41
41
|
"""
|
|
42
42
|
return (
|
|
43
|
-
f"Database
|
|
43
|
+
f"Database name: {get_database_version_or_name(db_config, version=False)}\n"
|
|
44
|
+
f"Database version: {get_database_version_or_name(db_config, version=True)}\n"
|
|
44
45
|
f"sim_telarray version: {get_sim_telarray_version(run_time)}\n"
|
|
45
46
|
f"CORSIKA version: {get_corsika_version(run_time)}\n"
|
|
46
47
|
f"Build options: {get_build_options(run_time)}\n"
|
|
@@ -48,25 +49,29 @@ def get_version_string(db_config=None, run_time=None):
|
|
|
48
49
|
)
|
|
49
50
|
|
|
50
51
|
|
|
51
|
-
def
|
|
52
|
+
def get_database_version_or_name(db_config, version=True):
|
|
52
53
|
"""
|
|
53
|
-
Get the version of the simulation model data base used.
|
|
54
|
+
Get the version or name of the simulation model data base used.
|
|
54
55
|
|
|
55
56
|
Parameters
|
|
56
57
|
----------
|
|
57
58
|
db_config : dict
|
|
58
59
|
Dictionary containing the database configuration.
|
|
60
|
+
version : bool
|
|
61
|
+
If True, return the version of the database. If False, return the name.
|
|
59
62
|
|
|
60
63
|
Returns
|
|
61
64
|
-------
|
|
62
65
|
str
|
|
63
|
-
Version of the simulation model data base used.
|
|
66
|
+
Version or name of the simulation model data base used.
|
|
64
67
|
|
|
65
68
|
"""
|
|
66
69
|
if db_config is None:
|
|
67
70
|
return None
|
|
68
71
|
db = DatabaseHandler(db_config)
|
|
69
|
-
return db.mongo_db_config.get(
|
|
72
|
+
return db.mongo_db_config.get(
|
|
73
|
+
"db_simulation_model_version" if version else "db_simulation_model"
|
|
74
|
+
)
|
|
70
75
|
|
|
71
76
|
|
|
72
77
|
def get_sim_telarray_version(run_time):
|
|
@@ -282,11 +282,7 @@ def get_array_layouts_from_db(
|
|
|
282
282
|
"""
|
|
283
283
|
layout_names = []
|
|
284
284
|
if layout_name:
|
|
285
|
-
layout_names.
|
|
286
|
-
layout_name[0]
|
|
287
|
-
if isinstance(layout_name, list) and len(layout_name) == 1
|
|
288
|
-
else layout_name
|
|
289
|
-
)
|
|
285
|
+
layout_names = gen.ensure_iterable(layout_name)
|
|
290
286
|
else:
|
|
291
287
|
site_model = SiteModel(site=site, model_version=model_version, mongo_db_config=db_config)
|
|
292
288
|
layout_names = site_model.get_list_of_array_layouts()
|
|
@@ -394,3 +390,39 @@ def _get_array_layout_dict(
|
|
|
394
390
|
coordinate_system=coordinate_system
|
|
395
391
|
),
|
|
396
392
|
}
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def get_array_elements_from_db_for_layouts(layouts, site, model_version, db_config):
|
|
396
|
+
"""
|
|
397
|
+
Get list of array elements from the database for given list of layout names.
|
|
398
|
+
|
|
399
|
+
Structure of the returned dictionary::
|
|
400
|
+
|
|
401
|
+
{
|
|
402
|
+
"layout_name_1": [telescope_id_1, telescope_id_2, ...],
|
|
403
|
+
"layout_name_2": [telescope_id_3, telescope_id_4, ...],
|
|
404
|
+
...
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
Parameters
|
|
408
|
+
----------
|
|
409
|
+
layouts : list[str]
|
|
410
|
+
List of layout names to read. If "all", read all available layouts.
|
|
411
|
+
site : str
|
|
412
|
+
Site name for the array layouts.
|
|
413
|
+
model_version : str
|
|
414
|
+
Model version for the array layouts.
|
|
415
|
+
db_config : dict
|
|
416
|
+
Database configuration dictionary.
|
|
417
|
+
|
|
418
|
+
Returns
|
|
419
|
+
-------
|
|
420
|
+
dict
|
|
421
|
+
Dictionary mapping layout names to telescope IDs.
|
|
422
|
+
"""
|
|
423
|
+
site_model = SiteModel(site=site, model_version=model_version, mongo_db_config=db_config)
|
|
424
|
+
layout_names = site_model.get_list_of_array_layouts() if layouts == ["all"] else layouts
|
|
425
|
+
layout_dict = {}
|
|
426
|
+
for layout_name in layout_names:
|
|
427
|
+
layout_dict[layout_name] = site_model.get_array_elements_for_layout(layout_name)
|
|
428
|
+
return layout_dict
|
simtools/model/array_model.py
CHANGED
|
@@ -272,7 +272,7 @@ class ArrayModel:
|
|
|
272
272
|
config_file_path=self.config_file_path,
|
|
273
273
|
telescope_model=self.telescope_model,
|
|
274
274
|
site_model=self.site_model,
|
|
275
|
-
|
|
275
|
+
additional_metadata=self._get_additional_simtel_metadata(),
|
|
276
276
|
)
|
|
277
277
|
self._array_model_file_exported = True
|
|
278
278
|
|
|
@@ -484,3 +484,20 @@ class ArrayModel:
|
|
|
484
484
|
|
|
485
485
|
table.sort("telescope_name")
|
|
486
486
|
return table
|
|
487
|
+
|
|
488
|
+
def _get_additional_simtel_metadata(self):
|
|
489
|
+
"""
|
|
490
|
+
Collect additional metadata to be included in sim_telarray output.
|
|
491
|
+
|
|
492
|
+
Returns
|
|
493
|
+
-------
|
|
494
|
+
dict
|
|
495
|
+
Dictionary with additional metadata.
|
|
496
|
+
"""
|
|
497
|
+
metadata = {}
|
|
498
|
+
if self.sim_telarray_seeds is not None:
|
|
499
|
+
metadata.update(self.sim_telarray_seeds)
|
|
500
|
+
|
|
501
|
+
metadata["nsb_integrated_flux"] = self.site_model.get_nsb_integrated_flux()
|
|
502
|
+
|
|
503
|
+
return metadata
|