gammasimtools 0.9.0__py3-none-any.whl → 0.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.10.0.dist-info}/METADATA +2 -2
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.10.0.dist-info}/RECORD +94 -85
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.10.0.dist-info}/entry_points.txt +2 -1
- simtools/_version.py +2 -2
- simtools/applications/calculate_trigger_rate.py +15 -38
- simtools/applications/convert_all_model_parameters_from_simtel.py +9 -28
- simtools/applications/convert_geo_coordinates_of_array_elements.py +47 -45
- simtools/applications/convert_model_parameter_from_simtel.py +2 -2
- simtools/applications/db_add_file_to_db.py +1 -2
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +110 -0
- simtools/applications/db_add_value_from_json_to_db.py +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 +44 -32
- simtools/applications/derive_photon_electron_spectrum.py +99 -0
- simtools/applications/generate_array_config.py +17 -17
- simtools/applications/generate_regular_arrays.py +15 -15
- simtools/applications/generate_simtel_array_histograms.py +11 -48
- simtools/applications/production_generate_simulation_config.py +25 -7
- simtools/applications/production_scale_events.py +2 -2
- 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 +8 -6
- simtools/applications/validate_camera_efficiency.py +2 -2
- simtools/applications/validate_file_using_schema.py +23 -19
- simtools/camera/single_photon_electron_spectrum.py +168 -0
- simtools/configuration/commandline_parser.py +8 -1
- simtools/constants.py +10 -3
- simtools/corsika/corsika_config.py +8 -7
- simtools/corsika/corsika_histograms.py +1 -1
- simtools/data_model/data_reader.py +0 -3
- simtools/data_model/metadata_collector.py +3 -4
- simtools/data_model/metadata_model.py +8 -124
- simtools/data_model/model_data_writer.py +17 -63
- simtools/data_model/schema.py +213 -0
- simtools/data_model/validate_data.py +9 -44
- simtools/db/db_handler.py +323 -495
- simtools/db/db_model_upload.py +139 -0
- simtools/io_operations/hdf5_handler.py +54 -24
- simtools/layout/array_layout.py +33 -28
- simtools/model/array_model.py +13 -7
- simtools/model/model_parameter.py +22 -54
- simtools/model/site_model.py +2 -2
- simtools/production_configuration/calculate_statistical_errors_grid_point.py +119 -144
- simtools/production_configuration/event_scaler.py +7 -17
- simtools/production_configuration/generate_simulation_config.py +5 -32
- simtools/production_configuration/interpolation_handler.py +8 -11
- simtools/runners/corsika_simtel_runner.py +3 -1
- simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +39 -0
- simtools/schemas/input/single_pe_spectrum.schema.yml +38 -0
- simtools/schemas/integration_tests_config.metaschema.yml +10 -0
- simtools/schemas/model_parameter.metaschema.yml +7 -2
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +2 -0
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +1 -1
- simtools/schemas/model_parameters/array_window.schema.yml +37 -0
- simtools/schemas/model_parameters/asum_clipping.schema.yml +0 -4
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_offset.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +0 -2
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_noise.schema.yml +3 -3
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +33 -0
- simtools/schemas/model_parameters/laser_photons.schema.yml +2 -2
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/production_configuration_metrics.schema.yml +68 -0
- simtools/schemas/production_tables.schema.yml +41 -0
- simtools/simtel/simtel_config_writer.py +5 -6
- simtools/simtel/simtel_io_histogram.py +32 -67
- simtools/simtel/simtel_io_histograms.py +15 -30
- simtools/simtel/simulator_array.py +2 -1
- simtools/simtel/simulator_camera_efficiency.py +5 -0
- simtools/simtel/simulator_light_emission.py +3 -1
- simtools/simtel/simulator_ray_tracing.py +2 -1
- simtools/testing/helpers.py +6 -13
- simtools/testing/validate_output.py +131 -47
- simtools/utils/general.py +102 -12
- simtools/utils/names.py +24 -20
- 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.10.0.dist-info}/LICENSE +0 -0
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.10.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.10.0.dist-info}/top_level.txt +0 -0
- /simtools/{camera_efficiency.py → camera/camera_efficiency.py} +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Upload a simulation model (parameters and production tables) to the database."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import simtools.utils.general as gen
|
|
7
|
+
from simtools.utils import names
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def add_values_from_json_to_db(file, collection, db, db_name, file_prefix):
|
|
13
|
+
"""
|
|
14
|
+
Upload new model parameter from json files to db.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
file : list
|
|
19
|
+
Json file to be uploaded to the DB.
|
|
20
|
+
collection : str
|
|
21
|
+
The DB collection to which to add the file.
|
|
22
|
+
db : DatabaseHandler
|
|
23
|
+
Database handler object.
|
|
24
|
+
db_name : str
|
|
25
|
+
Name of the database to be created.
|
|
26
|
+
file_prefix : str
|
|
27
|
+
Path to location of all additional files to be uploaded.
|
|
28
|
+
"""
|
|
29
|
+
par_dict = gen.collect_data_from_file(file_name=file)
|
|
30
|
+
logger.info(
|
|
31
|
+
f"Adding the following parameter to the DB: {par_dict['parameter']} "
|
|
32
|
+
f"version {par_dict['parameter_version']} "
|
|
33
|
+
f"(collection {collection} in database {db_name})"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
db.add_new_parameter(
|
|
37
|
+
db_name=db_name,
|
|
38
|
+
par_dict=par_dict,
|
|
39
|
+
collection_name=collection,
|
|
40
|
+
file_prefix=file_prefix,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def add_model_parameters_to_db(args_dict, db):
|
|
45
|
+
"""
|
|
46
|
+
Read model parameters from a directory and upload them to the database.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
args_dict : dict
|
|
51
|
+
Command line arguments.
|
|
52
|
+
db : DatabaseHandler
|
|
53
|
+
Database handler object.
|
|
54
|
+
"""
|
|
55
|
+
input_path = Path(args_dict["input_path"])
|
|
56
|
+
logger.info(f"Reading model parameters from repository path {input_path}")
|
|
57
|
+
array_elements = [d for d in input_path.iterdir() if d.is_dir()]
|
|
58
|
+
for element in array_elements:
|
|
59
|
+
collection = names.get_collection_name_from_array_element_name(element.name, False)
|
|
60
|
+
if collection == "Files":
|
|
61
|
+
logger.info("Files (tables) are uploaded with the corresponding model parameters")
|
|
62
|
+
continue
|
|
63
|
+
logger.info(f"Reading model parameters for {element.name} into collection {collection}")
|
|
64
|
+
files_to_insert = list(Path(element).rglob("*json"))
|
|
65
|
+
for file in files_to_insert:
|
|
66
|
+
add_values_from_json_to_db(
|
|
67
|
+
file=file,
|
|
68
|
+
collection=collection,
|
|
69
|
+
db=db,
|
|
70
|
+
db_name=args_dict["db_name"],
|
|
71
|
+
file_prefix=input_path / "Files",
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def add_production_tables_to_db(args_dict, db):
|
|
76
|
+
"""
|
|
77
|
+
Read production tables from a directory and upload them to the database.
|
|
78
|
+
|
|
79
|
+
One dictionary per collection is prepared for each model version, containing
|
|
80
|
+
tables of all array elements, sites, and configuration parameters.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
args_dict : dict
|
|
85
|
+
Command line arguments.
|
|
86
|
+
db : DatabaseHandler
|
|
87
|
+
Database handler object.
|
|
88
|
+
"""
|
|
89
|
+
input_path = Path(args_dict["input_path"])
|
|
90
|
+
logger.info(f"Reading production tables from repository path {input_path}")
|
|
91
|
+
|
|
92
|
+
for model in filter(Path.is_dir, input_path.iterdir()):
|
|
93
|
+
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)
|
|
97
|
+
|
|
98
|
+
for collection, data in model_dict.items():
|
|
99
|
+
if not data["parameters"]:
|
|
100
|
+
logger.info(f"No production table for {collection} in model version {model.name}")
|
|
101
|
+
continue
|
|
102
|
+
logger.info(f"Adding production table for {collection} to the database")
|
|
103
|
+
db.add_production_table(
|
|
104
|
+
db_name=args_dict["db_name"],
|
|
105
|
+
production_table=data,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _read_production_table(model_dict, file, model_name):
|
|
110
|
+
"""Read a single production table from file."""
|
|
111
|
+
array_element = file.stem
|
|
112
|
+
collection = names.get_collection_name_from_array_element_name(array_element, False)
|
|
113
|
+
model_dict.setdefault(
|
|
114
|
+
collection,
|
|
115
|
+
{
|
|
116
|
+
"collection": collection,
|
|
117
|
+
"model_version": model_name,
|
|
118
|
+
"parameters": {},
|
|
119
|
+
"design_model": {},
|
|
120
|
+
},
|
|
121
|
+
)
|
|
122
|
+
parameter_dict = gen.collect_data_from_file(file_name=file)
|
|
123
|
+
logger.info(f"Reading production table for {array_element} (collection {collection})")
|
|
124
|
+
try:
|
|
125
|
+
if array_element in ("configuration_corsika", "configuration_sim_telarray"):
|
|
126
|
+
model_dict[collection]["parameters"] = parameter_dict["parameters"]
|
|
127
|
+
else:
|
|
128
|
+
model_dict[collection]["parameters"][array_element] = parameter_dict["parameters"][
|
|
129
|
+
array_element
|
|
130
|
+
]
|
|
131
|
+
except KeyError as exc:
|
|
132
|
+
logger.error(f"KeyError: {exc}")
|
|
133
|
+
raise
|
|
134
|
+
try:
|
|
135
|
+
model_dict[collection]["design_model"][array_element] = parameter_dict["design_model"][
|
|
136
|
+
array_element
|
|
137
|
+
]
|
|
138
|
+
except KeyError:
|
|
139
|
+
pass
|
|
@@ -41,40 +41,26 @@ def fill_hdf5_table(hist, x_bin_edges, y_bin_edges, x_label, y_label, meta_data)
|
|
|
41
41
|
meta_data: dict
|
|
42
42
|
Dictionary with the histogram metadata.
|
|
43
43
|
"""
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
validate_histogram(hist, y_bin_edges)
|
|
45
|
+
|
|
46
|
+
meta_data["x_bin_edges"] = x_bin_edges
|
|
47
47
|
meta_data["x_bin_edges_unit"] = (
|
|
48
48
|
x_bin_edges.unit if isinstance(x_bin_edges, u.Quantity) else u.dimensionless_unscaled
|
|
49
49
|
)
|
|
50
|
-
|
|
51
50
|
if y_bin_edges is not None:
|
|
52
|
-
|
|
53
|
-
meta_data["y_bin_edges"] = sanitize_name(y_label)
|
|
54
|
-
names = [
|
|
55
|
-
f"{meta_data['y_bin_edges'].split('__')[0]}_{i}"
|
|
56
|
-
for i in range(len(y_bin_edges[:-1]))
|
|
57
|
-
]
|
|
58
|
-
else:
|
|
59
|
-
names = [
|
|
60
|
-
f"{meta_data['Title'].split('__')[0]}_{i}" for i in range(len(y_bin_edges[:-1]))
|
|
61
|
-
]
|
|
51
|
+
meta_data["y_bin_edges"] = y_bin_edges
|
|
62
52
|
meta_data["y_bin_edges_unit"] = (
|
|
63
53
|
y_bin_edges.unit if isinstance(y_bin_edges, u.Quantity) else u.dimensionless_unscaled
|
|
64
54
|
)
|
|
65
55
|
|
|
66
|
-
|
|
67
|
-
[hist[i, :] for i in range(len(y_bin_edges[:-1]))],
|
|
68
|
-
names=names,
|
|
69
|
-
meta=meta_data,
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
else:
|
|
56
|
+
if hist.ndim == 1:
|
|
73
57
|
if x_label is not None:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
else:
|
|
58
|
+
names = sanitize_name(x_label)
|
|
59
|
+
try:
|
|
77
60
|
names = meta_data["Title"]
|
|
61
|
+
except KeyError:
|
|
62
|
+
_logger.warning("Title not found in metadata.")
|
|
63
|
+
|
|
78
64
|
table = Table(
|
|
79
65
|
[
|
|
80
66
|
x_bin_edges[:-1],
|
|
@@ -83,9 +69,53 @@ def fill_hdf5_table(hist, x_bin_edges, y_bin_edges, x_label, y_label, meta_data)
|
|
|
83
69
|
names=(names, sanitize_name("Values")),
|
|
84
70
|
meta=meta_data,
|
|
85
71
|
)
|
|
72
|
+
else:
|
|
73
|
+
if y_label is not None:
|
|
74
|
+
names = [
|
|
75
|
+
f"{sanitize_name(y_label).split('__')[0]}_{i}" for i in range(len(y_bin_edges[:-1]))
|
|
76
|
+
]
|
|
77
|
+
try:
|
|
78
|
+
names = [
|
|
79
|
+
f"{(meta_data['Title']).split('__')[0]}_{sanitize_name(y_label)}_{i}"
|
|
80
|
+
for i in range(len(y_bin_edges[:-1]))
|
|
81
|
+
]
|
|
82
|
+
except KeyError:
|
|
83
|
+
_logger.warning("Title not found in metadata.")
|
|
84
|
+
names = [
|
|
85
|
+
f"{sanitize_name(y_label).split('__')[0]}_{i}" for i in range(len(y_bin_edges[:-1]))
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
table = Table(
|
|
89
|
+
[hist[i, :] for i in range(len(y_bin_edges[:-1]))],
|
|
90
|
+
names=names,
|
|
91
|
+
meta=meta_data,
|
|
92
|
+
)
|
|
93
|
+
|
|
86
94
|
return table
|
|
87
95
|
|
|
88
96
|
|
|
97
|
+
def validate_histogram(hist, y_bin_edges):
|
|
98
|
+
"""Validate histogram dimensions and y_bin_edges consistency.
|
|
99
|
+
|
|
100
|
+
Parameters
|
|
101
|
+
----------
|
|
102
|
+
hist (np.ndarray): The histogram array, expected to be 1D or 2D.
|
|
103
|
+
y_bin_edges (array-like or None): Bin edges for the second dimension (if applicable).
|
|
104
|
+
|
|
105
|
+
Raises
|
|
106
|
+
------
|
|
107
|
+
ValueError: If histogram dimensions are invalid or inconsistent with y_bin_edges.
|
|
108
|
+
"""
|
|
109
|
+
if hist.ndim not in (1, 2):
|
|
110
|
+
raise ValueError("Histogram must be either 1D or 2D.")
|
|
111
|
+
|
|
112
|
+
if hist.ndim == 1 and y_bin_edges is not None:
|
|
113
|
+
raise ValueError("y_bin_edges should be None for 1D histograms.")
|
|
114
|
+
|
|
115
|
+
if hist.ndim == 2 and y_bin_edges is None:
|
|
116
|
+
raise ValueError("y_bin_edges should not be None for 2D histograms.")
|
|
117
|
+
|
|
118
|
+
|
|
89
119
|
def read_hdf5(hdf5_file_name):
|
|
90
120
|
"""
|
|
91
121
|
Read a hdf5 output file.
|
simtools/layout/array_layout.py
CHANGED
|
@@ -9,7 +9,7 @@ import numpy as np
|
|
|
9
9
|
from astropy.table import QTable
|
|
10
10
|
|
|
11
11
|
import simtools.utils.general as gen
|
|
12
|
-
from simtools.data_model import data_reader
|
|
12
|
+
from simtools.data_model import data_reader, schema
|
|
13
13
|
from simtools.io_operations import io_handler
|
|
14
14
|
from simtools.layout.geo_coordinates import GeoCoordinates
|
|
15
15
|
from simtools.layout.telescope_position import TelescopePosition
|
|
@@ -386,7 +386,9 @@ class ArrayLayout:
|
|
|
386
386
|
with Path(file_name).open("r", encoding="utf-8") as file:
|
|
387
387
|
data = json.load(file)
|
|
388
388
|
|
|
389
|
-
position =
|
|
389
|
+
position = data["value"]
|
|
390
|
+
if isinstance(position, str):
|
|
391
|
+
position = gen.convert_string_to_list(position)
|
|
390
392
|
self.site = data.get("site", None)
|
|
391
393
|
|
|
392
394
|
table = QTable()
|
|
@@ -579,7 +581,12 @@ class ArrayLayout:
|
|
|
579
581
|
|
|
580
582
|
return table
|
|
581
583
|
|
|
582
|
-
def export_one_telescope_as_json(
|
|
584
|
+
def export_one_telescope_as_json(
|
|
585
|
+
self,
|
|
586
|
+
crs_name,
|
|
587
|
+
parameter_version=None,
|
|
588
|
+
schema_version=None,
|
|
589
|
+
):
|
|
583
590
|
"""
|
|
584
591
|
Return a list containing a single telescope in simtools-DB-style json.
|
|
585
592
|
|
|
@@ -587,6 +594,8 @@ class ArrayLayout:
|
|
|
587
594
|
----------
|
|
588
595
|
crs_name: str
|
|
589
596
|
Name of coordinate system to be used for export.
|
|
597
|
+
schema_version: str
|
|
598
|
+
Version of the schema.
|
|
590
599
|
|
|
591
600
|
Returns
|
|
592
601
|
-------
|
|
@@ -596,43 +605,39 @@ class ArrayLayout:
|
|
|
596
605
|
table = self.export_telescope_list_table(crs_name)
|
|
597
606
|
if len(table) != 1:
|
|
598
607
|
raise ValueError("Only one telescope can be exported to json")
|
|
599
|
-
parameter_name =
|
|
608
|
+
parameter_name = value = None
|
|
600
609
|
if crs_name == "ground":
|
|
601
610
|
parameter_name = "array_element_position_ground"
|
|
602
|
-
|
|
603
|
-
[
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
]
|
|
608
|
-
)
|
|
611
|
+
value = [
|
|
612
|
+
table["position_x"][0].value,
|
|
613
|
+
table["position_y"][0].value,
|
|
614
|
+
table["position_z"][0].value,
|
|
615
|
+
]
|
|
609
616
|
elif crs_name == "utm":
|
|
610
617
|
parameter_name = "array_element_position_utm"
|
|
611
|
-
|
|
612
|
-
[
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
]
|
|
617
|
-
)
|
|
618
|
+
value = [
|
|
619
|
+
table["utm_east"][0].value,
|
|
620
|
+
table["utm_north"][0].value,
|
|
621
|
+
table["altitude"][0].value,
|
|
622
|
+
]
|
|
618
623
|
elif crs_name == "mercator":
|
|
619
624
|
parameter_name = "array_element_position_mercator"
|
|
620
|
-
|
|
621
|
-
[
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
)
|
|
625
|
+
value = [
|
|
626
|
+
table["latitude"][0].value,
|
|
627
|
+
table["longitude"][0].value,
|
|
628
|
+
table["altitude"][0].value,
|
|
629
|
+
]
|
|
630
|
+
|
|
627
631
|
return {
|
|
632
|
+
"schema_version": schema.get_model_parameter_schema_version(schema_version),
|
|
628
633
|
"parameter": parameter_name,
|
|
629
634
|
"instrument": table["telescope_name"][0],
|
|
630
635
|
"site": self.site,
|
|
631
|
-
"
|
|
632
|
-
"
|
|
636
|
+
"parameter_version": parameter_version,
|
|
637
|
+
"unique_id": None,
|
|
638
|
+
"value": value,
|
|
633
639
|
"unit": "m",
|
|
634
640
|
"type": "float64",
|
|
635
|
-
"applicable": True,
|
|
636
641
|
"file": False,
|
|
637
642
|
}
|
|
638
643
|
|
simtools/model/array_model.py
CHANGED
|
@@ -6,8 +6,8 @@ from pathlib import Path
|
|
|
6
6
|
import astropy.units as u
|
|
7
7
|
from astropy.table import QTable
|
|
8
8
|
|
|
9
|
-
from simtools.data_model import data_reader
|
|
10
|
-
from simtools.db import
|
|
9
|
+
from simtools.data_model import data_reader, schema
|
|
10
|
+
from simtools.db import db_handler
|
|
11
11
|
from simtools.io_operations import io_handler
|
|
12
12
|
from simtools.model.site_model import SiteModel
|
|
13
13
|
from simtools.model.telescope_model import TelescopeModel
|
|
@@ -290,7 +290,13 @@ class ArrayModel:
|
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
def _get_telescope_position_parameter(
|
|
293
|
-
self,
|
|
293
|
+
self,
|
|
294
|
+
telescope_name: str,
|
|
295
|
+
site: str,
|
|
296
|
+
x: u.Quantity,
|
|
297
|
+
y: u.Quantity,
|
|
298
|
+
z: u.Quantity,
|
|
299
|
+
parameter_version: str | None = None,
|
|
294
300
|
) -> dict:
|
|
295
301
|
"""
|
|
296
302
|
Return dictionary with telescope position parameters (following DB model database format).
|
|
@@ -314,16 +320,17 @@ class ArrayModel:
|
|
|
314
320
|
Dict with telescope position parameters.
|
|
315
321
|
"""
|
|
316
322
|
return {
|
|
323
|
+
"schema_version": schema.get_model_parameter_schema_version(),
|
|
317
324
|
"parameter": "array_element_position_ground",
|
|
318
325
|
"instrument": telescope_name,
|
|
319
326
|
"site": site,
|
|
320
|
-
"
|
|
327
|
+
"parameter_version": parameter_version,
|
|
328
|
+
"unique_id": None,
|
|
321
329
|
"value": general.convert_list_to_string(
|
|
322
330
|
[x.to("m").value, y.to("m").value, z.to("m").value]
|
|
323
331
|
),
|
|
324
332
|
"unit": "m",
|
|
325
333
|
"type": "float64",
|
|
326
|
-
"applicable": True,
|
|
327
334
|
"file": False,
|
|
328
335
|
}
|
|
329
336
|
|
|
@@ -367,9 +374,8 @@ class ArrayModel:
|
|
|
367
374
|
dict
|
|
368
375
|
Dict with array elements.
|
|
369
376
|
"""
|
|
370
|
-
all_elements =
|
|
377
|
+
all_elements = self.db.get_array_elements_of_type(
|
|
371
378
|
array_element_type=array_element_type,
|
|
372
|
-
db=self.db,
|
|
373
379
|
model_version=self.model_version,
|
|
374
380
|
collection="telescopes",
|
|
375
381
|
)
|
|
@@ -67,7 +67,6 @@ class ModelParameter:
|
|
|
67
67
|
|
|
68
68
|
self._parameters = {}
|
|
69
69
|
self._simulation_config_parameters = {"corsika": {}, "simtel": {}}
|
|
70
|
-
self._derived = None
|
|
71
70
|
self.collection = collection
|
|
72
71
|
self.label = label
|
|
73
72
|
self.model_version = model_version
|
|
@@ -111,12 +110,8 @@ class ModelParameter:
|
|
|
111
110
|
"""
|
|
112
111
|
try:
|
|
113
112
|
return self._parameters[par_name]
|
|
114
|
-
except KeyError:
|
|
115
|
-
pass
|
|
116
|
-
try:
|
|
117
|
-
return self.derived[par_name]
|
|
118
113
|
except (KeyError, ValueError) as e:
|
|
119
|
-
msg = f"Parameter {par_name} was not found in the model"
|
|
114
|
+
msg = f"Parameter {par_name} was not found in the model {self.name}, {self.site}."
|
|
120
115
|
self._logger.error(msg)
|
|
121
116
|
raise InvalidModelParameterError(msg) from e
|
|
122
117
|
|
|
@@ -180,7 +175,10 @@ class ModelParameter:
|
|
|
180
175
|
_value = self.get_parameter_value(par_name, _parameter)
|
|
181
176
|
|
|
182
177
|
try:
|
|
183
|
-
|
|
178
|
+
if isinstance(_parameter.get("unit"), str):
|
|
179
|
+
_unit = [item.strip() for item in _parameter.get("unit").split(",")]
|
|
180
|
+
else:
|
|
181
|
+
_unit = _parameter.get("unit")
|
|
184
182
|
|
|
185
183
|
# if there is only one value or the values share one unit
|
|
186
184
|
if (isinstance(_value, (int | float))) or (len(_value) > len(_unit)):
|
|
@@ -241,33 +239,6 @@ class ModelParameter:
|
|
|
241
239
|
self._logger.debug(f"Parameter {par_name} does not have a file associated with it.")
|
|
242
240
|
return False
|
|
243
241
|
|
|
244
|
-
@property
|
|
245
|
-
def derived(self):
|
|
246
|
-
"""Load the derived values and export them if the class instance hasn't done it yet."""
|
|
247
|
-
if self._derived is None:
|
|
248
|
-
self._load_derived_values()
|
|
249
|
-
self._export_derived_files()
|
|
250
|
-
return self._derived
|
|
251
|
-
|
|
252
|
-
def _load_derived_values(self):
|
|
253
|
-
"""Load derived values from the DB."""
|
|
254
|
-
self._logger.debug("Reading derived values from DB")
|
|
255
|
-
self._derived = self.db.get_derived_values(
|
|
256
|
-
self.site,
|
|
257
|
-
self.name,
|
|
258
|
-
self.model_version,
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
def _export_derived_files(self):
|
|
262
|
-
"""Write to disk a file from the derived values DB."""
|
|
263
|
-
for par_now in self.derived.values():
|
|
264
|
-
if par_now.get("File") or par_now.get("file"):
|
|
265
|
-
self.db.export_file_db(
|
|
266
|
-
db_name=self.db.DB_DERIVED_VALUES,
|
|
267
|
-
dest=self.config_file_directory,
|
|
268
|
-
file_name=(par_now.get("value") or par_now.get("Value")),
|
|
269
|
-
)
|
|
270
|
-
|
|
271
242
|
def print_parameters(self):
|
|
272
243
|
"""Print parameters and their values for debugging purposes."""
|
|
273
244
|
for par in self._parameters:
|
|
@@ -322,10 +293,11 @@ class ModelParameter:
|
|
|
322
293
|
simulation_software=simulation_software,
|
|
323
294
|
)
|
|
324
295
|
)
|
|
325
|
-
except ValueError:
|
|
296
|
+
except ValueError as exc:
|
|
326
297
|
self._logger.warning(
|
|
327
298
|
f"No {simulation_software} parameters found for "
|
|
328
|
-
f"{self.site}, {self.name} (model version {self.model_version})."
|
|
299
|
+
f"{self.site}, {self.name} (model version {self.model_version}). "
|
|
300
|
+
f" (Query {exc})"
|
|
329
301
|
)
|
|
330
302
|
|
|
331
303
|
def _load_parameters_from_db(self):
|
|
@@ -335,15 +307,18 @@ class ModelParameter:
|
|
|
335
307
|
|
|
336
308
|
if self.name is not None:
|
|
337
309
|
self._parameters = self.db.get_model_parameters(
|
|
338
|
-
self.site, self.name, self.
|
|
310
|
+
self.site, self.name, self.collection, self.model_version
|
|
339
311
|
)
|
|
340
312
|
|
|
341
313
|
if self.site is not None:
|
|
342
|
-
|
|
343
|
-
self.
|
|
314
|
+
self._parameters.update(
|
|
315
|
+
self.db.get_model_parameters(
|
|
316
|
+
self.site,
|
|
317
|
+
None,
|
|
318
|
+
"sites",
|
|
319
|
+
self.model_version,
|
|
320
|
+
)
|
|
344
321
|
)
|
|
345
|
-
self._parameters.update(_site_pars)
|
|
346
|
-
|
|
347
322
|
self._load_simulation_software_parameter()
|
|
348
323
|
|
|
349
324
|
def set_extra_label(self, extra_label):
|
|
@@ -369,7 +344,7 @@ class ModelParameter:
|
|
|
369
344
|
"""Return the extra label if defined, if not return ''."""
|
|
370
345
|
return self._extra_label if self._extra_label is not None else ""
|
|
371
346
|
|
|
372
|
-
def get_simtel_parameters(self, parameters=None
|
|
347
|
+
def get_simtel_parameters(self, parameters=None):
|
|
373
348
|
"""
|
|
374
349
|
Get simtel parameters as name and value pairs.
|
|
375
350
|
|
|
@@ -377,10 +352,6 @@ class ModelParameter:
|
|
|
377
352
|
----------
|
|
378
353
|
parameters: dict
|
|
379
354
|
Parameters (simtools) to be renamed (if necessary)
|
|
380
|
-
telescope_model: bool
|
|
381
|
-
If True, telescope model parameters are included.
|
|
382
|
-
site_model: bool
|
|
383
|
-
If True, site model parameters are included.
|
|
384
355
|
|
|
385
356
|
Returns
|
|
386
357
|
-------
|
|
@@ -394,10 +365,7 @@ class ModelParameter:
|
|
|
394
365
|
_simtel_parameter_value = {}
|
|
395
366
|
for key in parameters:
|
|
396
367
|
_par_name = names.get_simulation_software_name_from_parameter_name(
|
|
397
|
-
key,
|
|
398
|
-
simulation_software="sim_telarray",
|
|
399
|
-
search_telescope_parameters=telescope_model,
|
|
400
|
-
search_site_parameters=site_model,
|
|
368
|
+
key, simulation_software="sim_telarray"
|
|
401
369
|
)
|
|
402
370
|
if _par_name is not None:
|
|
403
371
|
_simtel_parameter_value[_par_name] = parameters[key].get("value")
|
|
@@ -513,7 +481,7 @@ class ModelParameter:
|
|
|
513
481
|
for par in self._added_parameter_files:
|
|
514
482
|
pars_from_db.pop(par)
|
|
515
483
|
|
|
516
|
-
self.db.export_model_files(pars_from_db, self.config_file_directory)
|
|
484
|
+
self.db.export_model_files(parameters=pars_from_db, dest=self.config_file_directory)
|
|
517
485
|
self._is_exported_model_files_up_to_date = True
|
|
518
486
|
|
|
519
487
|
def get_model_file_as_table(self, par_name):
|
|
@@ -535,7 +503,7 @@ class ModelParameter:
|
|
|
535
503
|
_par_entry[par_name] = self._parameters[par_name]
|
|
536
504
|
except KeyError as exc:
|
|
537
505
|
raise ValueError(f"Parameter {par_name} not found in the model.") from exc
|
|
538
|
-
self.db.export_model_files(_par_entry, self.config_file_directory)
|
|
506
|
+
self.db.export_model_files(parameters=_par_entry, dest=self.config_file_directory)
|
|
539
507
|
if _par_entry[par_name]["value"].endswith("ecsv"):
|
|
540
508
|
return Table.read(
|
|
541
509
|
self.config_file_directory.joinpath(_par_entry[par_name]["value"]),
|
|
@@ -620,7 +588,7 @@ class ModelParameter:
|
|
|
620
588
|
Model directory to export the file to.
|
|
621
589
|
"""
|
|
622
590
|
self.db.export_model_files(
|
|
623
|
-
{
|
|
591
|
+
parameters={
|
|
624
592
|
"nsb_spectrum_at_2200m": {
|
|
625
593
|
"value": self._simulation_config_parameters["simtel"][
|
|
626
594
|
"correct_nsb_spectrum_to_telescope_altitude"
|
|
@@ -628,5 +596,5 @@ class ModelParameter:
|
|
|
628
596
|
"file": True,
|
|
629
597
|
}
|
|
630
598
|
},
|
|
631
|
-
model_directory,
|
|
599
|
+
dest=model_directory,
|
|
632
600
|
)
|
simtools/model/site_model.py
CHANGED
|
@@ -151,11 +151,11 @@ class SiteModel(ModelParameter):
|
|
|
151
151
|
Model directory to export the file to.
|
|
152
152
|
"""
|
|
153
153
|
self.db.export_model_files(
|
|
154
|
-
{
|
|
154
|
+
parameters={
|
|
155
155
|
"atmospheric_transmission_file": {
|
|
156
156
|
"value": self.get_parameter_value("atmospheric_profile"),
|
|
157
157
|
"file": True,
|
|
158
158
|
}
|
|
159
159
|
},
|
|
160
|
-
model_directory,
|
|
160
|
+
dest=model_directory,
|
|
161
161
|
)
|