gammasimtools 0.24.0__py3-none-any.whl → 0.26.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.24.0.dist-info → gammasimtools-0.26.0.dist-info}/METADATA +2 -1
- {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/RECORD +134 -130
- {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/entry_points.txt +3 -1
- {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +2 -2
- simtools/application_control.py +78 -0
- simtools/applications/calculate_incident_angles.py +0 -2
- simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -2
- simtools/applications/db_add_file_to_db.py +1 -1
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
- simtools/applications/db_add_value_from_json_to_db.py +1 -1
- simtools/applications/db_generate_compound_indexes.py +1 -1
- simtools/applications/db_get_array_layouts_from_db.py +2 -6
- simtools/applications/db_get_file_from_db.py +1 -1
- simtools/applications/db_get_parameter_from_db.py +1 -1
- simtools/applications/db_inspect_databases.py +1 -1
- simtools/applications/db_upload_model_repository.py +1 -1
- simtools/applications/derive_ctao_array_layouts.py +1 -2
- simtools/applications/derive_mirror_rnda.py +1 -3
- simtools/applications/derive_psf_parameters.py +5 -1
- simtools/applications/derive_pulse_shape_parameters.py +194 -0
- simtools/applications/derive_trigger_rates.py +1 -1
- simtools/applications/docs_produce_array_element_report.py +2 -8
- simtools/applications/docs_produce_calibration_reports.py +1 -3
- simtools/applications/docs_produce_model_parameter_reports.py +0 -2
- simtools/applications/docs_produce_simulation_configuration_report.py +1 -3
- simtools/applications/generate_array_config.py +0 -1
- simtools/applications/generate_corsika_histograms.py +48 -235
- simtools/applications/generate_regular_arrays.py +5 -35
- simtools/applications/generate_simtel_event_data.py +2 -2
- simtools/applications/maintain_simulation_model_add_production.py +2 -2
- simtools/applications/maintain_simulation_model_write_array_element_positions.py +87 -0
- simtools/applications/plot_array_layout.py +64 -108
- simtools/applications/plot_simulated_event_distributions.py +57 -0
- simtools/applications/plot_tabular_data.py +0 -1
- simtools/applications/plot_tabular_data_for_model_parameter.py +1 -6
- simtools/applications/production_derive_corsika_limits.py +1 -1
- simtools/applications/production_generate_grid.py +0 -1
- simtools/applications/run_application.py +1 -1
- simtools/applications/simulate_flasher.py +3 -4
- simtools/applications/simulate_illuminator.py +0 -1
- simtools/applications/simulate_pedestals.py +2 -6
- simtools/applications/simulate_prod.py +9 -28
- simtools/applications/simulate_prod_htcondor_generator.py +8 -1
- simtools/applications/submit_array_layouts.py +7 -7
- simtools/applications/submit_model_parameter_from_external.py +1 -3
- simtools/applications/validate_camera_efficiency.py +0 -1
- simtools/applications/validate_camera_fov.py +0 -1
- simtools/applications/validate_cumulative_psf.py +0 -2
- simtools/applications/validate_file_using_schema.py +49 -123
- simtools/applications/validate_optics.py +0 -13
- simtools/camera/camera_efficiency.py +1 -6
- simtools/camera/single_photon_electron_spectrum.py +2 -1
- simtools/configuration/commandline_parser.py +43 -8
- simtools/configuration/configurator.py +6 -11
- simtools/corsika/corsika_config.py +204 -99
- simtools/corsika/corsika_histograms.py +411 -1735
- simtools/corsika/primary_particle.py +1 -1
- simtools/data_model/metadata_collector.py +5 -2
- simtools/data_model/metadata_model.py +0 -4
- simtools/data_model/model_data_writer.py +27 -17
- simtools/data_model/schema.py +112 -5
- simtools/data_model/validate_data.py +80 -48
- simtools/db/db_handler.py +19 -8
- simtools/db/db_model_upload.py +2 -1
- simtools/db/mongo_db.py +133 -42
- simtools/dependencies.py +83 -44
- simtools/io/ascii_handler.py +4 -2
- simtools/io/table_handler.py +1 -1
- simtools/job_execution/htcondor_script_generator.py +0 -2
- simtools/layout/array_layout.py +4 -12
- simtools/layout/array_layout_utils.py +227 -58
- simtools/model/array_model.py +37 -18
- simtools/model/calibration_model.py +0 -4
- simtools/model/legacy_model_parameter.py +134 -0
- simtools/model/model_parameter.py +24 -14
- simtools/model/model_repository.py +18 -5
- simtools/model/model_utils.py +1 -6
- simtools/model/site_model.py +0 -4
- simtools/model/telescope_model.py +6 -11
- simtools/production_configuration/derive_corsika_limits.py +6 -11
- simtools/production_configuration/interpolation_handler.py +16 -16
- simtools/ray_tracing/incident_angles.py +5 -11
- simtools/ray_tracing/mirror_panel_psf.py +3 -7
- simtools/ray_tracing/psf_analysis.py +29 -27
- simtools/ray_tracing/psf_parameter_optimisation.py +822 -680
- simtools/ray_tracing/ray_tracing.py +6 -15
- simtools/reporting/docs_auto_report_generator.py +8 -13
- simtools/reporting/docs_read_parameters.py +70 -16
- simtools/runners/corsika_runner.py +15 -10
- simtools/runners/corsika_simtel_runner.py +9 -8
- simtools/runners/runner_services.py +17 -7
- simtools/runners/simtel_runner.py +11 -58
- simtools/runners/simtools_runner.py +2 -4
- simtools/schemas/model_parameters/flasher_pulse_exp_decay.schema.yml +2 -0
- simtools/schemas/model_parameters/flasher_pulse_shape.schema.yml +50 -0
- simtools/schemas/model_parameters/flasher_pulse_width.schema.yml +2 -0
- simtools/schemas/simulation_models_info.schema.yml +2 -0
- simtools/settings.py +154 -0
- simtools/sim_events/file_info.py +128 -0
- simtools/{simtel/simtel_io_event_histograms.py → sim_events/histograms.py} +25 -15
- simtools/{simtel/simtel_io_event_reader.py → sim_events/reader.py} +20 -17
- simtools/{simtel/simtel_io_event_writer.py → sim_events/writer.py} +84 -25
- simtools/simtel/pulse_shapes.py +273 -0
- simtools/simtel/simtel_config_writer.py +146 -22
- simtools/simtel/simtel_table_reader.py +6 -4
- simtools/simtel/simulator_array.py +62 -23
- simtools/simtel/simulator_camera_efficiency.py +4 -6
- simtools/simtel/simulator_light_emission.py +101 -19
- simtools/simtel/simulator_ray_tracing.py +4 -10
- simtools/simulator.py +360 -353
- simtools/telescope_trigger_rates.py +3 -4
- simtools/testing/assertions.py +115 -8
- simtools/testing/configuration.py +2 -3
- simtools/testing/helpers.py +2 -3
- simtools/testing/log_inspector.py +5 -1
- simtools/testing/sim_telarray_metadata.py +1 -1
- simtools/testing/validate_output.py +69 -23
- simtools/utils/general.py +37 -0
- simtools/utils/geometry.py +0 -77
- simtools/utils/names.py +7 -9
- simtools/version.py +37 -0
- simtools/visualization/legend_handlers.py +21 -10
- simtools/visualization/plot_array_layout.py +312 -41
- simtools/visualization/plot_corsika_histograms.py +143 -605
- simtools/visualization/plot_mirrors.py +834 -0
- simtools/visualization/plot_pixels.py +2 -4
- simtools/visualization/plot_psf.py +0 -1
- simtools/visualization/plot_simtel_event_histograms.py +4 -4
- simtools/visualization/plot_simtel_events.py +6 -11
- simtools/visualization/plot_tables.py +8 -19
- simtools/visualization/visualize.py +22 -2
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +0 -160
- simtools/applications/print_version.py +0 -53
- simtools/io/hdf5_handler.py +0 -139
- simtools/simtel/simtel_io_file_info.py +0 -62
- {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/top_level.txt +0 -0
simtools/db/mongo_db.py
CHANGED
|
@@ -10,7 +10,7 @@ import gridfs
|
|
|
10
10
|
import jsonschema
|
|
11
11
|
from astropy.table import Table
|
|
12
12
|
from bson.objectid import ObjectId
|
|
13
|
-
from pymongo import MongoClient
|
|
13
|
+
from pymongo import MongoClient, monitoring
|
|
14
14
|
|
|
15
15
|
from simtools.io import ascii_handler
|
|
16
16
|
|
|
@@ -57,6 +57,61 @@ jsonschema_db_dict = {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
class IdleConnectionMonitor(monitoring.ConnectionPoolListener):
|
|
61
|
+
"""
|
|
62
|
+
A listener to track MongoDB connection pool activity.
|
|
63
|
+
|
|
64
|
+
Used to monitor idle connections and log connection events.
|
|
65
|
+
Switched on in debug mode.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __init__(self):
|
|
69
|
+
self._logger = logging.getLogger("IdleConnectionMonitor")
|
|
70
|
+
self.open_connections = 0
|
|
71
|
+
|
|
72
|
+
def connection_created(self, event):
|
|
73
|
+
"""Handle connection creation event."""
|
|
74
|
+
self.open_connections += 1
|
|
75
|
+
self._logger.debug(
|
|
76
|
+
f"MongoDB connection Created: {event.address}. Total in Pool: {self.open_connections}"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def connection_closed(self, event):
|
|
80
|
+
"""Handle connection closure event."""
|
|
81
|
+
self.open_connections -= 1
|
|
82
|
+
self._logger.debug(
|
|
83
|
+
f"MongoDB connection Closed: {event.address}. Reason: {event.reason}. "
|
|
84
|
+
f"Total in Pool: {self.open_connections}"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def connection_check_out_started(self, event):
|
|
88
|
+
"""Handle connection check out started event."""
|
|
89
|
+
|
|
90
|
+
def connection_check_out_failed(self, event):
|
|
91
|
+
"""Handle connection check out failure event."""
|
|
92
|
+
|
|
93
|
+
def connection_checked_out(self, event):
|
|
94
|
+
"""Handle connection checked out event."""
|
|
95
|
+
|
|
96
|
+
def connection_checked_in(self, event):
|
|
97
|
+
"""Handle connection checked in event."""
|
|
98
|
+
|
|
99
|
+
def connection_ready(self, event):
|
|
100
|
+
"""Handle connection ready event."""
|
|
101
|
+
|
|
102
|
+
def pool_created(self, event):
|
|
103
|
+
"""Handle connection pool creation event."""
|
|
104
|
+
|
|
105
|
+
def pool_ready(self, event):
|
|
106
|
+
"""Handle connection pool ready event."""
|
|
107
|
+
|
|
108
|
+
def pool_cleared(self, event):
|
|
109
|
+
"""Handle connection pool cleared event."""
|
|
110
|
+
|
|
111
|
+
def pool_closed(self, event):
|
|
112
|
+
"""Handle connection pool closure event."""
|
|
113
|
+
|
|
114
|
+
|
|
60
115
|
class MongoDBHandler: # pylint: disable=unsubscriptable-object
|
|
61
116
|
"""
|
|
62
117
|
MongoDBHandler provides low-level interface to MongoDB operations.
|
|
@@ -70,19 +125,90 @@ class MongoDBHandler: # pylint: disable=unsubscriptable-object
|
|
|
70
125
|
Dictionary with the MongoDB configuration (see jsonschema_db_dict for details).
|
|
71
126
|
"""
|
|
72
127
|
|
|
73
|
-
db_client: MongoClient
|
|
128
|
+
db_client: MongoClient = None
|
|
74
129
|
_lock = Lock()
|
|
130
|
+
_logger = logging.getLogger(__name__)
|
|
75
131
|
|
|
76
132
|
def __init__(self, db_config=None):
|
|
77
133
|
"""Initialize the MongoDBHandler class."""
|
|
78
|
-
self._logger = logging.getLogger(__name__)
|
|
79
134
|
self.db_config = MongoDBHandler.validate_db_config(db_config)
|
|
80
135
|
self.list_of_collections = {}
|
|
81
136
|
|
|
82
|
-
if self.db_config
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
137
|
+
if self.db_config:
|
|
138
|
+
self._initialize_client(self.db_config)
|
|
139
|
+
|
|
140
|
+
@classmethod
|
|
141
|
+
def _initialize_client(cls, db_config):
|
|
142
|
+
"""
|
|
143
|
+
Initialize the MongoDB client in a thread-safe manner.
|
|
144
|
+
|
|
145
|
+
Only initializes if it hasn't been done yet. Uses double-checked locking
|
|
146
|
+
to ensure thread safety.
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
db_config: dict
|
|
151
|
+
Dictionary with the MongoDB configuration.
|
|
152
|
+
"""
|
|
153
|
+
if cls.db_client is not None:
|
|
154
|
+
return
|
|
155
|
+
with cls._lock:
|
|
156
|
+
if cls.db_client is None:
|
|
157
|
+
try:
|
|
158
|
+
uri = cls._build_uri(db_config)
|
|
159
|
+
client_kwargs = {"maxIdleTimeMS": 10000}
|
|
160
|
+
|
|
161
|
+
if cls._logger.isEnabledFor(logging.DEBUG):
|
|
162
|
+
client_kwargs["event_listeners"] = [IdleConnectionMonitor()]
|
|
163
|
+
|
|
164
|
+
cls.db_client = MongoClient(uri, **client_kwargs)
|
|
165
|
+
cls._logger.debug("MongoDB client initialized successfully.")
|
|
166
|
+
except Exception as e:
|
|
167
|
+
cls._logger.error(f"Failed to initialize MongoDB client: {e}")
|
|
168
|
+
raise
|
|
169
|
+
|
|
170
|
+
@staticmethod
|
|
171
|
+
def _build_uri(db_config):
|
|
172
|
+
"""
|
|
173
|
+
Build MongoDB URI from configuration.
|
|
174
|
+
|
|
175
|
+
Parameters
|
|
176
|
+
----------
|
|
177
|
+
db_config: dict
|
|
178
|
+
Dictionary with the MongoDB configuration.
|
|
179
|
+
|
|
180
|
+
Returns
|
|
181
|
+
-------
|
|
182
|
+
str
|
|
183
|
+
MongoDB connection URI.
|
|
184
|
+
"""
|
|
185
|
+
direct_connection = db_config["db_server"] in (
|
|
186
|
+
"localhost",
|
|
187
|
+
"simtools-mongodb",
|
|
188
|
+
"mongodb",
|
|
189
|
+
)
|
|
190
|
+
auth_source = (
|
|
191
|
+
db_config.get("db_api_authentication_database")
|
|
192
|
+
if db_config.get("db_api_authentication_database")
|
|
193
|
+
else "admin"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
username = db_config["db_api_user"]
|
|
197
|
+
password = db_config["db_api_pw"]
|
|
198
|
+
server = db_config["db_server"]
|
|
199
|
+
port = db_config["db_api_port"]
|
|
200
|
+
|
|
201
|
+
uri_base = f"mongodb://{username}:{password}@{server}:{port}/"
|
|
202
|
+
params = [f"authSource={auth_source}"]
|
|
203
|
+
|
|
204
|
+
if direct_connection:
|
|
205
|
+
params.append("directConnection=true")
|
|
206
|
+
else:
|
|
207
|
+
params.append("ssl=true")
|
|
208
|
+
params.append("tlsAllowInvalidHostnames=true")
|
|
209
|
+
params.append("tlsAllowInvalidCertificates=true")
|
|
210
|
+
|
|
211
|
+
return f"{uri_base}?{'&'.join(params)}"
|
|
86
212
|
|
|
87
213
|
@staticmethod
|
|
88
214
|
def validate_db_config(db_config):
|
|
@@ -112,41 +238,6 @@ class MongoDBHandler: # pylint: disable=unsubscriptable-object
|
|
|
112
238
|
except jsonschema.exceptions.ValidationError as err:
|
|
113
239
|
raise ValueError("Invalid MongoDB configuration") from err
|
|
114
240
|
|
|
115
|
-
def _open_db(self):
|
|
116
|
-
"""
|
|
117
|
-
Open a connection to MongoDB and return the client.
|
|
118
|
-
|
|
119
|
-
Returns
|
|
120
|
-
-------
|
|
121
|
-
MongoClient
|
|
122
|
-
A PyMongo DB client
|
|
123
|
-
|
|
124
|
-
Raises
|
|
125
|
-
------
|
|
126
|
-
KeyError
|
|
127
|
-
If the DB configuration is invalid
|
|
128
|
-
"""
|
|
129
|
-
direct_connection = self.db_config["db_server"] in (
|
|
130
|
-
"localhost",
|
|
131
|
-
"simtools-mongodb",
|
|
132
|
-
"mongodb",
|
|
133
|
-
)
|
|
134
|
-
return MongoClient(
|
|
135
|
-
self.db_config["db_server"],
|
|
136
|
-
port=self.db_config["db_api_port"],
|
|
137
|
-
username=self.db_config["db_api_user"],
|
|
138
|
-
password=self.db_config["db_api_pw"],
|
|
139
|
-
authSource=(
|
|
140
|
-
self.db_config.get("db_api_authentication_database")
|
|
141
|
-
if self.db_config.get("db_api_authentication_database")
|
|
142
|
-
else "admin"
|
|
143
|
-
),
|
|
144
|
-
directConnection=direct_connection,
|
|
145
|
-
ssl=not direct_connection,
|
|
146
|
-
tlsallowinvalidhostnames=True,
|
|
147
|
-
tlsallowinvalidcertificates=True,
|
|
148
|
-
)
|
|
149
|
-
|
|
150
241
|
@staticmethod
|
|
151
242
|
def get_db_name(db_name=None, db_simulation_model_version=None, model_name=None):
|
|
152
243
|
"""
|
simtools/dependencies.py
CHANGED
|
@@ -9,27 +9,26 @@ This modules provides two main functionalities:
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
import logging
|
|
12
|
-
import os
|
|
13
12
|
import re
|
|
14
13
|
import subprocess
|
|
15
14
|
from pathlib import Path
|
|
16
15
|
|
|
17
16
|
import yaml
|
|
18
17
|
|
|
18
|
+
from simtools import settings
|
|
19
19
|
from simtools.io import ascii_handler
|
|
20
|
+
from simtools.utils import general as gen
|
|
20
21
|
from simtools.version import __version__
|
|
21
22
|
|
|
22
23
|
_logger = logging.getLogger(__name__)
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
def get_version_string(
|
|
26
|
+
def get_version_string(run_time=None):
|
|
26
27
|
"""
|
|
27
28
|
Print the versions of the dependencies.
|
|
28
29
|
|
|
29
30
|
Parameters
|
|
30
31
|
----------
|
|
31
|
-
db_config : dict, optional
|
|
32
|
-
Database configuration dictionary.
|
|
33
32
|
run_time : list, optional
|
|
34
33
|
Runtime environment command (e.g., Docker).
|
|
35
34
|
|
|
@@ -40,10 +39,13 @@ def get_version_string(db_config=None, run_time=None):
|
|
|
40
39
|
|
|
41
40
|
"""
|
|
42
41
|
return (
|
|
43
|
-
f"Database name: {get_database_version_or_name(
|
|
44
|
-
f"Database version: {get_database_version_or_name(
|
|
42
|
+
f"Database name: {get_database_version_or_name(version=False)}\n"
|
|
43
|
+
f"Database version: {get_database_version_or_name(version=True)}\n"
|
|
45
44
|
f"sim_telarray version: {get_sim_telarray_version(run_time)}\n"
|
|
45
|
+
"sim_telarray exe: "
|
|
46
|
+
f"{settings.config.sim_telarray_exe if settings.config.sim_telarray_exe else 'None'}\n"
|
|
46
47
|
f"CORSIKA version: {get_corsika_version(run_time)}\n"
|
|
48
|
+
f"CORSIKA exe: {settings.config.corsika_exe if settings.config.corsika_exe else 'None'}\n"
|
|
47
49
|
f"Build options: {get_build_options(run_time)}\n"
|
|
48
50
|
f"Runtime environment: {run_time if run_time else 'None'}\n"
|
|
49
51
|
)
|
|
@@ -73,14 +75,12 @@ def get_software_version(software):
|
|
|
73
75
|
raise ValueError(f"Unknown software: {software}") from exc
|
|
74
76
|
|
|
75
77
|
|
|
76
|
-
def get_database_version_or_name(
|
|
78
|
+
def get_database_version_or_name(version=True):
|
|
77
79
|
"""
|
|
78
80
|
Get the version or name of the simulation model data base used.
|
|
79
81
|
|
|
80
82
|
Parameters
|
|
81
83
|
----------
|
|
82
|
-
db_config : dict
|
|
83
|
-
Dictionary containing the database configuration.
|
|
84
84
|
version : bool
|
|
85
85
|
If True, return the version of the database. If False, return the name.
|
|
86
86
|
|
|
@@ -91,8 +91,10 @@ def get_database_version_or_name(db_config, version=True):
|
|
|
91
91
|
|
|
92
92
|
"""
|
|
93
93
|
if version:
|
|
94
|
-
return db_config and db_config.get(
|
|
95
|
-
|
|
94
|
+
return settings.config.db_config and settings.config.db_config.get(
|
|
95
|
+
"db_simulation_model_version"
|
|
96
|
+
)
|
|
97
|
+
return settings.config.db_config and settings.config.db_config.get("db_simulation_model")
|
|
96
98
|
|
|
97
99
|
|
|
98
100
|
def get_sim_telarray_version(run_time=None):
|
|
@@ -111,16 +113,13 @@ def get_sim_telarray_version(run_time=None):
|
|
|
111
113
|
str
|
|
112
114
|
Version of the sim_telarray package.
|
|
113
115
|
"""
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
_logger.warning("Environment variable SIMTOOLS_SIMTEL_PATH is not set.")
|
|
116
|
+
if settings.config.sim_telarray_exe is None:
|
|
117
|
+
_logger.warning("sim_telarray environment not configured.")
|
|
117
118
|
return None
|
|
118
|
-
sim_telarray_path = Path(sim_telarray_path) / "sim_telarray" / "bin" / "sim_telarray"
|
|
119
|
-
|
|
120
119
|
if run_time is None:
|
|
121
|
-
command = [str(
|
|
120
|
+
command = [str(settings.config.sim_telarray_exe), "--version"]
|
|
122
121
|
else:
|
|
123
|
-
command = [*run_time, str(
|
|
122
|
+
command = [*run_time, str(settings.config.sim_telarray_exe), "--version"]
|
|
124
123
|
|
|
125
124
|
_logger.debug(f"Running command: {command}")
|
|
126
125
|
result = subprocess.run(command, capture_output=True, text=True, check=False)
|
|
@@ -151,20 +150,15 @@ def get_corsika_version(run_time=None):
|
|
|
151
150
|
str
|
|
152
151
|
Version of the CORSIKA package.
|
|
153
152
|
"""
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if sim_telarray_path is None:
|
|
157
|
-
_logger.warning("Environment variable SIMTOOLS_SIMTEL_PATH is not set.")
|
|
153
|
+
if settings.config.corsika_exe is None:
|
|
154
|
+
_logger.warning("CORSIKA environment not configured.")
|
|
158
155
|
return None
|
|
159
|
-
corsika_command = Path(sim_telarray_path) / "corsika-run" / "corsika"
|
|
160
156
|
|
|
161
157
|
if run_time is None:
|
|
162
|
-
command = [str(
|
|
158
|
+
command = [str(settings.config.corsika_exe)]
|
|
163
159
|
else:
|
|
164
|
-
command = [*run_time, str(
|
|
160
|
+
command = [*run_time, str(settings.config.corsika_exe)]
|
|
165
161
|
|
|
166
|
-
# Below I do not use the standard context manager because
|
|
167
|
-
# it makes mocking in the tests significantly more difficult
|
|
168
162
|
process = subprocess.Popen( # pylint: disable=consider-using-with
|
|
169
163
|
command,
|
|
170
164
|
stdout=subprocess.PIPE,
|
|
@@ -173,11 +167,8 @@ def get_corsika_version(run_time=None):
|
|
|
173
167
|
text=True,
|
|
174
168
|
)
|
|
175
169
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
line = process.stdout.readline()
|
|
179
|
-
if not line:
|
|
180
|
-
break
|
|
170
|
+
version = None
|
|
171
|
+
for line in process.stdout:
|
|
181
172
|
# Extract the version from the line "NUMBER OF VERSION : 7.7550"
|
|
182
173
|
if "NUMBER OF VERSION" in line:
|
|
183
174
|
version = line.split(":")[1].strip()
|
|
@@ -201,9 +192,14 @@ def get_corsika_version(run_time=None):
|
|
|
201
192
|
|
|
202
193
|
def get_build_options(run_time=None):
|
|
203
194
|
"""
|
|
204
|
-
Return CORSIKA / sim_telarray build options.
|
|
195
|
+
Return CORSIKA / sim_telarray config and build options.
|
|
196
|
+
|
|
197
|
+
For CORSIKA / sim_telarray build for simtools version >0.25.0:
|
|
198
|
+
expects build_opts.yml file in each CORSIKA and sim_telarray
|
|
199
|
+
directories.
|
|
205
200
|
|
|
206
|
-
|
|
201
|
+
For CORSIKA / sim_telarray build for simtools version <=0.25.0:
|
|
202
|
+
expects a build_opts.yml file in the sim_telarray directory.
|
|
207
203
|
|
|
208
204
|
Parameters
|
|
209
205
|
----------
|
|
@@ -213,28 +209,71 @@ def get_build_options(run_time=None):
|
|
|
213
209
|
Returns
|
|
214
210
|
-------
|
|
215
211
|
dict
|
|
216
|
-
|
|
212
|
+
CORSIKA / sim_telarray build options.
|
|
217
213
|
"""
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
214
|
+
build_opts = {}
|
|
215
|
+
for package in ["corsika", "sim_telarray"]:
|
|
216
|
+
path = _get_package_path(package)
|
|
217
|
+
if not path:
|
|
218
|
+
continue
|
|
219
|
+
try:
|
|
220
|
+
build_opts.update(_get_build_options_from_file(path / "build_opts.yml", run_time))
|
|
221
|
+
except (FileNotFoundError, TypeError, ValueError):
|
|
222
|
+
# legacy fallback only for sim_telarray
|
|
223
|
+
if package == "sim_telarray":
|
|
224
|
+
try:
|
|
225
|
+
legacy_path = path.parent / "build_opts.yml"
|
|
226
|
+
build_opts.update(_get_build_options_from_file(legacy_path, run_time))
|
|
227
|
+
except (FileNotFoundError, TypeError, ValueError):
|
|
228
|
+
_logger.debug(f"No build options found for {package}.")
|
|
229
|
+
if not build_opts:
|
|
230
|
+
raise FileNotFoundError("No build option file found.")
|
|
231
|
+
|
|
232
|
+
return build_opts
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _get_package_path(package):
|
|
236
|
+
"""Get the package path from settings or environment variables."""
|
|
237
|
+
path = getattr(settings.config, f"{package}_path")
|
|
238
|
+
if path is None:
|
|
239
|
+
path = gen.load_environment_variables().get(f"{package}_path")
|
|
240
|
+
return Path(path) if path else None
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _get_build_options_from_file(build_opts_path, run_time=None):
|
|
244
|
+
"""Read build options from file."""
|
|
224
245
|
if run_time is None:
|
|
225
246
|
try:
|
|
226
247
|
return ascii_handler.collect_data_from_file(build_opts_path)
|
|
227
248
|
except FileNotFoundError as exc:
|
|
228
|
-
raise FileNotFoundError("No
|
|
249
|
+
raise FileNotFoundError("No build option file found.") from exc
|
|
229
250
|
|
|
230
251
|
command = [*run_time, "cat", str(build_opts_path)]
|
|
231
|
-
_logger.debug(f"Reading
|
|
252
|
+
_logger.debug(f"Reading build option with command: {command}")
|
|
232
253
|
|
|
233
254
|
result = subprocess.run(command, capture_output=True, text=True, check=False)
|
|
234
255
|
if result.returncode:
|
|
235
|
-
raise FileNotFoundError(f"No
|
|
256
|
+
raise FileNotFoundError(f"No build option file found in container: {result.stderr}")
|
|
236
257
|
|
|
237
258
|
try:
|
|
238
259
|
return yaml.safe_load(result.stdout)
|
|
239
260
|
except yaml.YAMLError as exc:
|
|
240
261
|
raise ValueError(f"Error parsing build_opts.yml from container: {exc}") from exc
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def export_build_info(output_file, run_time=None):
|
|
265
|
+
"""
|
|
266
|
+
Export build and version information to a file.
|
|
267
|
+
|
|
268
|
+
Parameters
|
|
269
|
+
----------
|
|
270
|
+
output_file : str
|
|
271
|
+
Path to the output file.
|
|
272
|
+
run_time : list, optional
|
|
273
|
+
Runtime environment command (e.g., Docker).
|
|
274
|
+
"""
|
|
275
|
+
build_info = get_build_options(run_time)
|
|
276
|
+
build_info["simtools"] = __version__
|
|
277
|
+
build_info["database_name"] = get_database_version_or_name(version=False)
|
|
278
|
+
build_info["database_version"] = get_database_version_or_name(version=True)
|
|
279
|
+
ascii_handler.write_data_to_file(data=build_info, output_file=Path(output_file))
|
simtools/io/ascii_handler.py
CHANGED
|
@@ -208,9 +208,11 @@ def write_data_to_file(data, output_file, sort_keys=False, numpy_types=False):
|
|
|
208
208
|
"""
|
|
209
209
|
output_file = Path(output_file)
|
|
210
210
|
if output_file.suffix.lower() == ".json":
|
|
211
|
-
|
|
211
|
+
_write_to_json(data, output_file, sort_keys, numpy_types)
|
|
212
|
+
return
|
|
212
213
|
if output_file.suffix.lower() in [".yml", ".yaml"]:
|
|
213
|
-
|
|
214
|
+
_write_to_yaml(data, output_file, sort_keys)
|
|
215
|
+
return
|
|
214
216
|
|
|
215
217
|
raise ValueError(
|
|
216
218
|
f"Unsupported file type {output_file.suffix}. Only .json, .yml, and .yaml are supported."
|
simtools/io/table_handler.py
CHANGED
|
@@ -295,7 +295,7 @@ def write_table_in_hdf5(table, output_file, table_name):
|
|
|
295
295
|
None
|
|
296
296
|
"""
|
|
297
297
|
for col in table.colnames:
|
|
298
|
-
if table[col].dtype.kind == "U": #
|
|
298
|
+
if table[col].dtype.kind == "U": # hdf5 does not support unicode
|
|
299
299
|
table[col] = table[col].astype("S")
|
|
300
300
|
|
|
301
301
|
with h5py.File(output_file, "a") as f:
|
|
@@ -136,8 +136,6 @@ simtools-simulate-prod \\
|
|
|
136
136
|
--view_cone {view_cone_string} \\
|
|
137
137
|
--run_number $((process_id)) \\
|
|
138
138
|
--run_number_offset {run_number_offset} \\
|
|
139
|
-
--number_of_runs 1 \\
|
|
140
|
-
--data_directory /tmp/simtools-data \\
|
|
141
139
|
--output_path /tmp/simtools-output \\
|
|
142
140
|
--log_level {args_dict["log_level"]} \\
|
|
143
141
|
--pack_for_grid_register simtools-output
|
simtools/layout/array_layout.py
CHANGED
|
@@ -32,8 +32,6 @@ class ArrayLayout:
|
|
|
32
32
|
|
|
33
33
|
Parameters
|
|
34
34
|
----------
|
|
35
|
-
db_config: dict
|
|
36
|
-
Database configuration.
|
|
37
35
|
site: str
|
|
38
36
|
Site name or location (e.g., North/South or LaPalma/Paranal)
|
|
39
37
|
model_version: str
|
|
@@ -52,7 +50,6 @@ class ArrayLayout:
|
|
|
52
50
|
|
|
53
51
|
def __init__(
|
|
54
52
|
self,
|
|
55
|
-
db_config,
|
|
56
53
|
site,
|
|
57
54
|
model_version,
|
|
58
55
|
label=None,
|
|
@@ -67,7 +64,6 @@ class ArrayLayout:
|
|
|
67
64
|
self.model_version = model_version
|
|
68
65
|
self.label = label
|
|
69
66
|
self.name = name
|
|
70
|
-
self.db_config = db_config
|
|
71
67
|
self.site = None if site is None else names.validate_site_name(site)
|
|
72
68
|
self.site_model = None
|
|
73
69
|
self.io_handler = io_handler.IOHandler()
|
|
@@ -95,14 +91,11 @@ class ArrayLayout:
|
|
|
95
91
|
def _initialize_site_parameters_from_db(self):
|
|
96
92
|
"""Initialize site parameters required for transformations using the database."""
|
|
97
93
|
self._logger.debug("Initialize parameters from DB")
|
|
98
|
-
if self.db_config is None:
|
|
99
|
-
raise ValueError("No database configuration provided")
|
|
100
94
|
|
|
101
|
-
|
|
102
|
-
site=self.site,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
95
|
+
try:
|
|
96
|
+
self.site_model = SiteModel(site=self.site, model_version=self.model_version)
|
|
97
|
+
except RuntimeError as e:
|
|
98
|
+
raise ValueError("No database configuration provided") from e
|
|
106
99
|
self._corsika_observation_level = self.site_model.get_corsika_site_parameters().get(
|
|
107
100
|
"corsika_observation_level", None
|
|
108
101
|
)
|
|
@@ -419,7 +412,6 @@ class ArrayLayout:
|
|
|
419
412
|
site=self.site,
|
|
420
413
|
telescope_name=telescope_name,
|
|
421
414
|
model_version=self.model_version,
|
|
422
|
-
db_config=self.db_config,
|
|
423
415
|
label=self.label,
|
|
424
416
|
)
|
|
425
417
|
|