gammasimtools 0.16.0__py3-none-any.whl → 0.18.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.16.0.dist-info → gammasimtools-0.18.0.dist-info}/METADATA +5 -2
- {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/RECORD +82 -74
- {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/entry_points.txt +4 -1
- simtools/_version.py +2 -2
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +10 -1
- simtools/applications/derive_ctao_array_layouts.py +5 -5
- simtools/applications/derive_mirror_rnda.py +1 -1
- simtools/applications/generate_simtel_event_data.py +128 -46
- simtools/applications/merge_tables.py +102 -0
- simtools/applications/plot_array_layout.py +145 -258
- simtools/applications/plot_tabular_data.py +12 -1
- simtools/applications/plot_tabular_data_for_model_parameter.py +103 -0
- simtools/applications/production_derive_corsika_limits.py +78 -225
- simtools/applications/production_derive_statistics.py +77 -43
- simtools/applications/simulate_light_emission.py +1 -0
- simtools/applications/simulate_prod.py +30 -18
- simtools/applications/simulate_prod_htcondor_generator.py +0 -1
- simtools/applications/submit_array_layouts.py +93 -0
- simtools/applications/verify_simulation_model_production_tables.py +52 -0
- simtools/camera/camera_efficiency.py +3 -3
- simtools/configuration/commandline_parser.py +30 -35
- simtools/configuration/configurator.py +0 -4
- simtools/constants.py +2 -0
- simtools/corsika/corsika_config.py +17 -12
- simtools/corsika/primary_particle.py +46 -13
- simtools/data_model/metadata_collector.py +7 -3
- simtools/data_model/schema.py +15 -1
- simtools/db/db_handler.py +16 -11
- simtools/db/db_model_upload.py +2 -2
- simtools/io_operations/io_handler.py +2 -2
- simtools/io_operations/io_table_handler.py +345 -0
- simtools/job_execution/htcondor_script_generator.py +2 -2
- simtools/job_execution/job_manager.py +7 -121
- simtools/layout/array_layout_utils.py +389 -0
- simtools/model/array_model.py +10 -1
- simtools/model/model_repository.py +134 -0
- simtools/production_configuration/{calculate_statistical_errors_grid_point.py → calculate_statistical_uncertainties_grid_point.py} +101 -112
- simtools/production_configuration/derive_corsika_limits.py +239 -111
- simtools/production_configuration/derive_corsika_limits_grid.py +232 -0
- simtools/production_configuration/derive_production_statistics.py +57 -26
- simtools/production_configuration/derive_production_statistics_handler.py +70 -37
- simtools/production_configuration/interpolation_handler.py +296 -94
- simtools/ray_tracing/ray_tracing.py +7 -6
- simtools/reporting/docs_read_parameters.py +104 -62
- simtools/resources/array-element-ids.json +126 -0
- simtools/runners/corsika_simtel_runner.py +4 -1
- simtools/runners/runner_services.py +5 -4
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +5 -1
- simtools/schemas/model_parameters/atmospheric_profile.schema.yml +41 -0
- simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +43 -0
- simtools/schemas/model_parameters/camera_filter.schema.yml +10 -0
- simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +10 -0
- simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +31 -0
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +12 -0
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +10 -0
- simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +10 -0
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +12 -0
- simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +19 -0
- simtools/schemas/model_parameters/quantum_efficiency.schema.yml +10 -0
- simtools/schemas/plot_configuration.metaschema.yml +46 -57
- simtools/schemas/production_configuration_metrics.schema.yml +2 -2
- simtools/simtel/simtel_config_writer.py +34 -14
- simtools/simtel/simtel_io_event_reader.py +301 -194
- simtools/simtel/simtel_io_event_writer.py +237 -221
- simtools/simtel/simtel_io_file_info.py +9 -4
- simtools/simtel/simtel_io_metadata.py +119 -8
- simtools/simtel/simulator_array.py +2 -2
- simtools/simtel/simulator_light_emission.py +79 -34
- simtools/simtel/simulator_ray_tracing.py +2 -2
- simtools/simulator.py +101 -68
- simtools/testing/validate_output.py +4 -1
- simtools/utils/general.py +1 -3
- simtools/utils/names.py +76 -7
- simtools/visualization/plot_array_layout.py +242 -0
- simtools/visualization/plot_pixels.py +680 -0
- simtools/visualization/plot_tables.py +81 -2
- simtools/visualization/visualize.py +3 -219
- simtools/applications/production_generate_simulation_config.py +0 -152
- simtools/layout/ctao_array_layouts.py +0 -172
- simtools/production_configuration/generate_simulation_config.py +0 -158
- {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/licenses/LICENSE +0 -0
- {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/top_level.txt +0 -0
- /simtools/{schemas → resources}/array_elements.yml +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
|
|
3
|
+
r"""
|
|
4
|
+
Submit array-layouts definition and corresponding metadata and validate list of telescopes.
|
|
5
|
+
|
|
6
|
+
Includes validation that all defined telescope exists.
|
|
7
|
+
|
|
8
|
+
Command line arguments
|
|
9
|
+
----------------------
|
|
10
|
+
array_layouts (str, required)
|
|
11
|
+
Array layouts file.
|
|
12
|
+
updated_parameter_version (str, optional)
|
|
13
|
+
Updated parameter version.
|
|
14
|
+
input_meta (str, optional)
|
|
15
|
+
Input meta data file(s) associated to input data (wildcards or list of files allowed).
|
|
16
|
+
model_version (str, required)
|
|
17
|
+
Model version.
|
|
18
|
+
|
|
19
|
+
Example
|
|
20
|
+
-------
|
|
21
|
+
|
|
22
|
+
Submit a new array layout dictionary:
|
|
23
|
+
|
|
24
|
+
.. code-block:: console
|
|
25
|
+
|
|
26
|
+
simtools-submit-array-layouts \
|
|
27
|
+
--array_layouts array_layouts.json \\
|
|
28
|
+
--model_version 6.0.0 \\
|
|
29
|
+
--updated_parameter_version 0.1.0 \\
|
|
30
|
+
--input_meta array_layouts.metadata.yml
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
import logging
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
|
|
38
|
+
import simtools.utils.general as gen
|
|
39
|
+
from simtools.configuration import configurator
|
|
40
|
+
from simtools.db import db_handler
|
|
41
|
+
from simtools.layout.array_layout_utils import validate_array_layouts_with_db, write_array_layouts
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _parse(label, description):
|
|
45
|
+
"""Parse command line configuration."""
|
|
46
|
+
config = configurator.Configurator(label=label, description=description)
|
|
47
|
+
|
|
48
|
+
config.parser.add_argument(
|
|
49
|
+
"--array_layouts",
|
|
50
|
+
type=str,
|
|
51
|
+
required=True,
|
|
52
|
+
help="Array layout dictionary file.",
|
|
53
|
+
)
|
|
54
|
+
config.parser.add_argument(
|
|
55
|
+
"--updated_parameter_version",
|
|
56
|
+
help="Updated parameter version.",
|
|
57
|
+
type=str,
|
|
58
|
+
required=False,
|
|
59
|
+
)
|
|
60
|
+
config.parser.add_argument(
|
|
61
|
+
"--input_meta",
|
|
62
|
+
help="meta data file(s) associated to input data (wildcards or list of files allowed)",
|
|
63
|
+
type=str,
|
|
64
|
+
nargs="+",
|
|
65
|
+
required=False,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
return config.initialize(output=True, db_config=True, simulation_model=["model_version"])
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def main(): # noqa: D103
|
|
72
|
+
args_dict, db_config = _parse(
|
|
73
|
+
label=Path(__file__).stem,
|
|
74
|
+
description="Submit and validate array layouts.",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
logger = logging.getLogger()
|
|
78
|
+
logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
|
|
79
|
+
|
|
80
|
+
db = db_handler.DatabaseHandler(mongo_db_config=db_config)
|
|
81
|
+
|
|
82
|
+
array_layouts = validate_array_layouts_with_db(
|
|
83
|
+
production_table=db.read_production_table_from_mongo_db(
|
|
84
|
+
collection_name="telescopes", model_version=args_dict["model_version"]
|
|
85
|
+
),
|
|
86
|
+
array_layouts=gen.collect_data_from_file(args_dict["array_layouts"]),
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
write_array_layouts(array_layouts=array_layouts, args_dict=args_dict, db_config=db_config)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == "__main__":
|
|
93
|
+
main()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Verify simulation model production tables and model parameters for completeness.
|
|
5
|
+
|
|
6
|
+
This application is a utility to be used in the CI pipeline of the SimulationModels
|
|
7
|
+
repository. It checks that all model parameters defined in the production tables
|
|
8
|
+
exist in the simulation models repository.
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
|
|
14
|
+
from simtools.configuration import configurator
|
|
15
|
+
from simtools.model import model_repository
|
|
16
|
+
from simtools.utils import general as gen
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _parse():
|
|
20
|
+
"""Parse command line arguments."""
|
|
21
|
+
config = configurator.Configurator(
|
|
22
|
+
description=(
|
|
23
|
+
"Verify simulation model production tables and model parameters for completeness. "
|
|
24
|
+
"This application checks that all model parameters defined in the production tables "
|
|
25
|
+
"exist in the simulation models repository."
|
|
26
|
+
)
|
|
27
|
+
)
|
|
28
|
+
config.parser.add_argument(
|
|
29
|
+
"--simulation_models_path",
|
|
30
|
+
help="Path to the simulation models repository.",
|
|
31
|
+
type=str,
|
|
32
|
+
required=True,
|
|
33
|
+
)
|
|
34
|
+
return config.initialize(db_config=False, output=False, paths=False)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def main(): # noqa: D103
|
|
38
|
+
args_dict, _ = _parse()
|
|
39
|
+
|
|
40
|
+
logger = logging.getLogger()
|
|
41
|
+
logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
|
|
42
|
+
|
|
43
|
+
if not model_repository.verify_simulation_model_production_tables(
|
|
44
|
+
simulation_models_path=args_dict["simulation_models_path"]
|
|
45
|
+
):
|
|
46
|
+
raise RuntimeError(
|
|
47
|
+
"Verification failed: Some model parameters are missing in the repository."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
if __name__ == "__main__":
|
|
52
|
+
main()
|
|
@@ -114,7 +114,7 @@ class CameraEfficiency:
|
|
|
114
114
|
):
|
|
115
115
|
file_name = names.generate_file_name(
|
|
116
116
|
file_type=(
|
|
117
|
-
"
|
|
117
|
+
"camera_efficiency_table" if label == "results" else "camera_efficiency"
|
|
118
118
|
),
|
|
119
119
|
suffix=suffix,
|
|
120
120
|
site=self.telescope_model.site,
|
|
@@ -126,7 +126,7 @@ class CameraEfficiency:
|
|
|
126
126
|
|
|
127
127
|
_file[label] = self.io_handler.get_output_directory(
|
|
128
128
|
label=self.label,
|
|
129
|
-
sub_dir="
|
|
129
|
+
sub_dir="camera_efficiency",
|
|
130
130
|
).joinpath(file_name)
|
|
131
131
|
return _file
|
|
132
132
|
|
|
@@ -292,7 +292,7 @@ class CameraEfficiency:
|
|
|
292
292
|
self._results, self._file["results"], format="basic", overwrite=True
|
|
293
293
|
)
|
|
294
294
|
_results_summary_file = (
|
|
295
|
-
str(self._file["results"]).replace(".ecsv", ".txt").replace("
|
|
295
|
+
str(self._file["results"]).replace(".ecsv", ".txt").replace("_table_", "_summary_")
|
|
296
296
|
)
|
|
297
297
|
self._logger.info(f"Exporting summary results to {_results_summary_file}")
|
|
298
298
|
with open(_results_summary_file, "w", encoding="utf-8") as file:
|
|
@@ -37,7 +37,6 @@ class CommandLineParser(argparse.ArgumentParser):
|
|
|
37
37
|
simulation_model=None,
|
|
38
38
|
simulation_configuration=None,
|
|
39
39
|
db_config=False,
|
|
40
|
-
job_submission=False,
|
|
41
40
|
):
|
|
42
41
|
"""
|
|
43
42
|
Initialize default arguments used by all applications (e.g., log level or test flag).
|
|
@@ -55,13 +54,9 @@ class CommandLineParser(argparse.ArgumentParser):
|
|
|
55
54
|
Dict of simulation software configuration parameters to add to list of args.
|
|
56
55
|
db_config: bool
|
|
57
56
|
Add database configuration parameters to list of args.
|
|
58
|
-
job_submission: bool
|
|
59
|
-
Add job submission configuration parameters to list of args.
|
|
60
57
|
"""
|
|
61
58
|
self.initialize_simulation_model_arguments(simulation_model)
|
|
62
59
|
self.initialize_simulation_configuration_arguments(simulation_configuration)
|
|
63
|
-
if job_submission:
|
|
64
|
-
self.initialize_job_submission_arguments()
|
|
65
60
|
if db_config:
|
|
66
61
|
self.initialize_db_config_arguments()
|
|
67
62
|
if paths:
|
|
@@ -228,28 +223,6 @@ class CommandLineParser(argparse.ArgumentParser):
|
|
|
228
223
|
default=None,
|
|
229
224
|
)
|
|
230
225
|
|
|
231
|
-
def initialize_job_submission_arguments(self):
|
|
232
|
-
"""Initialize job submission arguments for simulator."""
|
|
233
|
-
_job_group = self.add_argument_group("job submission")
|
|
234
|
-
_job_group.add_argument(
|
|
235
|
-
"--submit_engine",
|
|
236
|
-
help="job submission command",
|
|
237
|
-
type=str,
|
|
238
|
-
required=True,
|
|
239
|
-
choices=[
|
|
240
|
-
"qsub",
|
|
241
|
-
"htcondor",
|
|
242
|
-
"local",
|
|
243
|
-
],
|
|
244
|
-
default="local",
|
|
245
|
-
)
|
|
246
|
-
_job_group.add_argument(
|
|
247
|
-
"--submit_options",
|
|
248
|
-
help="additional options (comma separated) for submission command",
|
|
249
|
-
type=str,
|
|
250
|
-
required=False,
|
|
251
|
-
)
|
|
252
|
-
|
|
253
226
|
def initialize_simulation_model_arguments(self, model_options):
|
|
254
227
|
"""
|
|
255
228
|
Initialize default arguments for simulation model definition.
|
|
@@ -303,7 +276,7 @@ class CommandLineParser(argparse.ArgumentParser):
|
|
|
303
276
|
if "layout" in model_options or "layout_file" in model_options:
|
|
304
277
|
_job_group = self._add_model_option_layout(
|
|
305
278
|
job_group=_job_group,
|
|
306
|
-
|
|
279
|
+
model_options=model_options,
|
|
307
280
|
# layout info is always required for layout related tasks with the exception
|
|
308
281
|
# of listing the available layouts in the DB
|
|
309
282
|
required="--list_available_layouts" not in self._option_string_actions,
|
|
@@ -389,8 +362,14 @@ class CommandLineParser(argparse.ArgumentParser):
|
|
|
389
362
|
"type": int,
|
|
390
363
|
"required": False,
|
|
391
364
|
},
|
|
392
|
-
"
|
|
393
|
-
"help": "
|
|
365
|
+
"run_number_offset": {
|
|
366
|
+
"help": "An offset for the run number to be simulated.",
|
|
367
|
+
"type": int,
|
|
368
|
+
"required": False,
|
|
369
|
+
"default": 0,
|
|
370
|
+
},
|
|
371
|
+
"run_number": {
|
|
372
|
+
"help": "Run number to be simulated.",
|
|
394
373
|
"type": int,
|
|
395
374
|
"required": True,
|
|
396
375
|
"default": 1,
|
|
@@ -477,7 +456,7 @@ class CommandLineParser(argparse.ArgumentParser):
|
|
|
477
456
|
pass
|
|
478
457
|
|
|
479
458
|
@staticmethod
|
|
480
|
-
def _add_model_option_layout(job_group,
|
|
459
|
+
def _add_model_option_layout(job_group, model_options, required=True):
|
|
481
460
|
"""
|
|
482
461
|
Add layout option to the job group.
|
|
483
462
|
|
|
@@ -485,8 +464,8 @@ class CommandLineParser(argparse.ArgumentParser):
|
|
|
485
464
|
----------
|
|
486
465
|
job_group: argparse.ArgumentParser
|
|
487
466
|
Job group
|
|
488
|
-
|
|
489
|
-
|
|
467
|
+
model_options: list
|
|
468
|
+
List of model options.
|
|
490
469
|
|
|
491
470
|
Returns
|
|
492
471
|
-------
|
|
@@ -495,7 +474,8 @@ class CommandLineParser(argparse.ArgumentParser):
|
|
|
495
474
|
_layout_group = job_group.add_mutually_exclusive_group(required=required)
|
|
496
475
|
_layout_group.add_argument(
|
|
497
476
|
"--array_layout_name",
|
|
498
|
-
help="array layout name (e.g., alpha, subsystem_msts)",
|
|
477
|
+
help="array layout name(s) (e.g., alpha, subsystem_msts)",
|
|
478
|
+
nargs="+",
|
|
499
479
|
type=str,
|
|
500
480
|
required=False,
|
|
501
481
|
)
|
|
@@ -507,7 +487,7 @@ class CommandLineParser(argparse.ArgumentParser):
|
|
|
507
487
|
required=False,
|
|
508
488
|
default=None,
|
|
509
489
|
)
|
|
510
|
-
if
|
|
490
|
+
if "layout_file" in model_options:
|
|
511
491
|
_layout_group.add_argument(
|
|
512
492
|
"--array_layout_file",
|
|
513
493
|
help="file(s) with the list of array elements (astropy table format).",
|
|
@@ -516,6 +496,21 @@ class CommandLineParser(argparse.ArgumentParser):
|
|
|
516
496
|
required=False,
|
|
517
497
|
default=None,
|
|
518
498
|
)
|
|
499
|
+
if "layout_parameter_file" in model_options:
|
|
500
|
+
_layout_group.add_argument(
|
|
501
|
+
"--array_layout_parameter_file",
|
|
502
|
+
help="Array layout model parameter file (typically in JSON format).",
|
|
503
|
+
type=str,
|
|
504
|
+
required=False,
|
|
505
|
+
default=None,
|
|
506
|
+
)
|
|
507
|
+
if "plot_all_layouts" in model_options:
|
|
508
|
+
_layout_group.add_argument(
|
|
509
|
+
"--plot_all_layouts",
|
|
510
|
+
help="plot all available layouts",
|
|
511
|
+
action="store_true",
|
|
512
|
+
required=False,
|
|
513
|
+
)
|
|
519
514
|
return job_group
|
|
520
515
|
|
|
521
516
|
def _add_model_option_site(self, job_group):
|
|
@@ -106,7 +106,6 @@ class Configurator:
|
|
|
106
106
|
simulation_model=None,
|
|
107
107
|
simulation_configuration=None,
|
|
108
108
|
db_config=False,
|
|
109
|
-
job_submission=False,
|
|
110
109
|
):
|
|
111
110
|
"""
|
|
112
111
|
Initialize application configuration.
|
|
@@ -134,8 +133,6 @@ class Configurator:
|
|
|
134
133
|
Dict of simulation software configuration parameters to add to list of args.
|
|
135
134
|
db_config: bool
|
|
136
135
|
Add database configuration parameters to list of args.
|
|
137
|
-
job_submission: bool
|
|
138
|
-
Add job submission configuration to list of args.
|
|
139
136
|
|
|
140
137
|
Returns
|
|
141
138
|
-------
|
|
@@ -151,7 +148,6 @@ class Configurator:
|
|
|
151
148
|
simulation_model=simulation_model,
|
|
152
149
|
simulation_configuration=simulation_configuration,
|
|
153
150
|
db_config=db_config,
|
|
154
|
-
job_submission=job_submission,
|
|
155
151
|
)
|
|
156
152
|
|
|
157
153
|
self._fill_from_command_line(require_command_line=require_command_line)
|
simtools/constants.py
CHANGED
|
@@ -638,6 +638,9 @@ class CorsikaConfig:
|
|
|
638
638
|
ValueError
|
|
639
639
|
If file_type is unknown or if the run number is not given for file_type==config_tmp.
|
|
640
640
|
"""
|
|
641
|
+
if file_type == "config_tmp" and run_number is None:
|
|
642
|
+
raise ValueError("Must provide a run number for a temporary CORSIKA config file")
|
|
643
|
+
|
|
641
644
|
file_label = f"_{self.label}" if self.label is not None else ""
|
|
642
645
|
|
|
643
646
|
_vc_low = self.get_config_parameter("VIEWCONE")[0]
|
|
@@ -646,25 +649,27 @@ class CorsikaConfig:
|
|
|
646
649
|
f"_cone{int(_vc_low):d}-{int(_vc_high):d}" if _vc_low != 0 or _vc_high != 0 else ""
|
|
647
650
|
)
|
|
648
651
|
|
|
652
|
+
run_number_in_file_name = ""
|
|
653
|
+
if file_type == "output_generic":
|
|
654
|
+
# The XXXXXX will be replaced by the run number after the pfp step with sed
|
|
655
|
+
run_number_in_file_name = "runXXXXXX_"
|
|
656
|
+
if file_type == "config_tmp":
|
|
657
|
+
run_number_in_file_name = f"run{run_number:06}_"
|
|
658
|
+
|
|
649
659
|
base_name = (
|
|
650
|
-
f"{self.primary_particle.name}_{
|
|
651
|
-
f"za{int(self.get_config_parameter('THETAP')[0]):03}
|
|
652
|
-
f"azm{self.azimuth_angle:03}deg"
|
|
653
|
-
f"{
|
|
660
|
+
f"{self.primary_particle.name}_{run_number_in_file_name}"
|
|
661
|
+
f"za{int(self.get_config_parameter('THETAP')[0]):03}deg_"
|
|
662
|
+
f"azm{self.azimuth_angle:03}deg{view_cone}_"
|
|
663
|
+
f"{self.array_model.site}_{self.array_model.layout_name}_"
|
|
664
|
+
f"{self.array_model.model_version}{file_label}"
|
|
654
665
|
)
|
|
655
666
|
|
|
656
667
|
if file_type == "config_tmp":
|
|
657
|
-
|
|
658
|
-
raise ValueError("Must provide a run number for a temporary CORSIKA config file")
|
|
659
|
-
return f"corsika_config_run{run_number:06}_{base_name}.txt"
|
|
668
|
+
return f"corsika_config_{base_name}.txt"
|
|
660
669
|
if file_type == "config":
|
|
661
670
|
return f"corsika_config_{base_name}.input"
|
|
662
671
|
if file_type == "output_generic":
|
|
663
|
-
|
|
664
|
-
return (
|
|
665
|
-
f"runXXXXXX_{base_name}_{self.array_model.site}_"
|
|
666
|
-
f"{self.array_model.layout_name}{file_label}.zst"
|
|
667
|
-
)
|
|
672
|
+
return f"{base_name}.zst"
|
|
668
673
|
if file_type == "multipipe":
|
|
669
674
|
return f"multi_cta-{self.array_model.site}-{self.array_model.layout_name}.cfg"
|
|
670
675
|
|
|
@@ -7,7 +7,7 @@ from particle import Corsika7ID, InvalidParticle, Particle
|
|
|
7
7
|
|
|
8
8
|
class PrimaryParticle:
|
|
9
9
|
"""
|
|
10
|
-
Primary particle definition using CORSIKA7 or PDG ID.
|
|
10
|
+
Primary particle definition using CORSIKA7, eventio, or PDG ID.
|
|
11
11
|
|
|
12
12
|
Uses a dictionary to map particle common names to CORSIKA7 IDs.
|
|
13
13
|
Particles not found in the dictionary are searched in the PDG particle database.
|
|
@@ -20,27 +20,31 @@ class PrimaryParticle:
|
|
|
20
20
|
The actual ID of the primary particle.
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
+
_valid_types = {
|
|
24
|
+
"corsika7_id": "corsika7_id",
|
|
25
|
+
"common_name": "name",
|
|
26
|
+
"pdg_id": "pdg_id",
|
|
27
|
+
"eventio_id": "eventio_id",
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
def __init__(self, particle_id_type=None, particle_id=None):
|
|
24
31
|
self._logger = logging.getLogger(__name__)
|
|
25
|
-
|
|
26
32
|
self._corsika7_id = None
|
|
27
33
|
self._name = None
|
|
28
34
|
self._pdg_id = None
|
|
29
35
|
self._pdg_name = None
|
|
36
|
+
self._eventio_id = None
|
|
30
37
|
|
|
31
|
-
if
|
|
38
|
+
if (particle_id_type is None) != (particle_id is None):
|
|
32
39
|
raise ValueError("Both 'particle_id_type' and 'particle_id' must be provided together.")
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
self.name = particle_id
|
|
42
|
-
elif particle_id_type == "pdg_id":
|
|
43
|
-
self.pdg_id = particle_id
|
|
41
|
+
if particle_id_type:
|
|
42
|
+
try:
|
|
43
|
+
setattr(self, self._valid_types[particle_id_type], particle_id)
|
|
44
|
+
except KeyError as exc:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"Particle ID type must be one of {set(self._valid_types)}"
|
|
47
|
+
) from exc
|
|
44
48
|
|
|
45
49
|
def __str__(self):
|
|
46
50
|
"""Return a string representation of the primary particle."""
|
|
@@ -70,6 +74,35 @@ class PrimaryParticle:
|
|
|
70
74
|
raise ValueError(f"Invalid CORSIKA7 ID: {value}") from exc
|
|
71
75
|
self._corsika7_id = int(value)
|
|
72
76
|
|
|
77
|
+
@property
|
|
78
|
+
def eventio_id(self):
|
|
79
|
+
"""
|
|
80
|
+
EventIO ID of the primary particle.
|
|
81
|
+
|
|
82
|
+
0 (gamma), 1(e-), 2(mu-), 100*A+Z for nucleons and nuclei, negative for antimatter.
|
|
83
|
+
"""
|
|
84
|
+
return self._eventio_id
|
|
85
|
+
|
|
86
|
+
@eventio_id.setter
|
|
87
|
+
def eventio_id(self, value):
|
|
88
|
+
"""Set EventIO ID of the primary particle."""
|
|
89
|
+
mapping = {
|
|
90
|
+
0: 1,
|
|
91
|
+
1: 3,
|
|
92
|
+
-1: 2,
|
|
93
|
+
2: 6,
|
|
94
|
+
-2: 5,
|
|
95
|
+
100: 13,
|
|
96
|
+
101: 14,
|
|
97
|
+
-101: 15,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
self.corsika7_id = mapping.get(value, value)
|
|
102
|
+
except (ValueError, InvalidParticle) as exc:
|
|
103
|
+
raise ValueError(f"Invalid EventIO ID: {value}") from exc
|
|
104
|
+
self._eventio_id = value
|
|
105
|
+
|
|
73
106
|
@property
|
|
74
107
|
def name(self):
|
|
75
108
|
"""Common name of the primary particle."""
|
|
@@ -13,7 +13,6 @@ from pathlib import Path
|
|
|
13
13
|
|
|
14
14
|
import yaml
|
|
15
15
|
|
|
16
|
-
import simtools.constants
|
|
17
16
|
import simtools.utils.general as gen
|
|
18
17
|
import simtools.version
|
|
19
18
|
from simtools.constants import METADATA_JSON_SCHEMA
|
|
@@ -209,7 +208,7 @@ class MetadataCollector:
|
|
|
209
208
|
url = self.input_metadata[0][self.observatory]["product"]["data"]["model"]["url"]
|
|
210
209
|
self._logger.debug(f"Schema file from input metadata: {url}")
|
|
211
210
|
return url
|
|
212
|
-
except (KeyError, TypeError):
|
|
211
|
+
except (KeyError, TypeError, IndexError):
|
|
213
212
|
pass
|
|
214
213
|
|
|
215
214
|
self._logger.warning("No schema file found.")
|
|
@@ -254,7 +253,7 @@ class MetadataCollector:
|
|
|
254
253
|
)
|
|
255
254
|
if _site is not None:
|
|
256
255
|
return names.validate_site_name(_site)
|
|
257
|
-
except (KeyError, TypeError):
|
|
256
|
+
except (KeyError, TypeError, IndexError):
|
|
258
257
|
pass
|
|
259
258
|
return None
|
|
260
259
|
|
|
@@ -360,6 +359,11 @@ class MetadataCollector:
|
|
|
360
359
|
_input_metadata = self._read_input_metadata_from_yml_or_json(metadata_file)
|
|
361
360
|
elif Path(metadata_file).suffix == ".ecsv":
|
|
362
361
|
_input_metadata = self._read_input_metadata_from_ecsv(metadata_file)
|
|
362
|
+
elif Path(metadata_file).name.endswith((".simtel.zst", ".simtel")):
|
|
363
|
+
self._logger.warning(
|
|
364
|
+
"Metadata extraction from sim_telarray files is not supported yet."
|
|
365
|
+
)
|
|
366
|
+
continue
|
|
363
367
|
else:
|
|
364
368
|
raise gen.InvalidConfigDataError(f"Unknown metadata file format: {metadata_file}")
|
|
365
369
|
|
simtools/data_model/schema.py
CHANGED
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
6
|
import jsonschema
|
|
7
|
+
from referencing import Registry, Resource
|
|
7
8
|
|
|
8
9
|
import simtools.utils.general as gen
|
|
9
10
|
from simtools.constants import (
|
|
@@ -119,8 +120,14 @@ def validate_dict_using_schema(data, schema_file=None, json_schema=None):
|
|
|
119
120
|
), # default version to ensure backward compatibility
|
|
120
121
|
)
|
|
121
122
|
|
|
123
|
+
validator = jsonschema.Draft6Validator(
|
|
124
|
+
schema=json_schema,
|
|
125
|
+
format_checker=format_checkers.format_checker,
|
|
126
|
+
registry=Registry(retrieve=_retrieve_yaml_schema_from_uri),
|
|
127
|
+
)
|
|
128
|
+
|
|
122
129
|
try:
|
|
123
|
-
|
|
130
|
+
validator.validate(instance=data)
|
|
124
131
|
except jsonschema.exceptions.ValidationError as exc:
|
|
125
132
|
_logger.error(f"Validation failed using schema: {json_schema} for data: {data}")
|
|
126
133
|
raise exc
|
|
@@ -135,6 +142,13 @@ def validate_dict_using_schema(data, schema_file=None, json_schema=None):
|
|
|
135
142
|
return data
|
|
136
143
|
|
|
137
144
|
|
|
145
|
+
def _retrieve_yaml_schema_from_uri(uri):
|
|
146
|
+
"""Load schema from a file URI."""
|
|
147
|
+
path = SCHEMA_PATH / Path(uri.removeprefix("file:/"))
|
|
148
|
+
contents = gen.collect_data_from_file(file_name=path)
|
|
149
|
+
return Resource.from_contents(contents)
|
|
150
|
+
|
|
151
|
+
|
|
138
152
|
def load_schema(schema_file=None, schema_version=None):
|
|
139
153
|
"""
|
|
140
154
|
Load parameter schema from file.
|
simtools/db/db_handler.py
CHANGED
|
@@ -217,7 +217,7 @@ class DatabaseHandler:
|
|
|
217
217
|
raise ValueError(
|
|
218
218
|
"Only one model version can be passed to get_model_parameter, not a list."
|
|
219
219
|
)
|
|
220
|
-
production_table = self.
|
|
220
|
+
production_table = self.read_production_table_from_mongo_db(
|
|
221
221
|
collection_name, model_version
|
|
222
222
|
)
|
|
223
223
|
array_element_list = self._get_array_element_list(
|
|
@@ -263,7 +263,7 @@ class DatabaseHandler:
|
|
|
263
263
|
dict containing the parameters
|
|
264
264
|
"""
|
|
265
265
|
pars = {}
|
|
266
|
-
production_table = self.
|
|
266
|
+
production_table = self.read_production_table_from_mongo_db(collection, model_version)
|
|
267
267
|
array_element_list = self._get_array_element_list(
|
|
268
268
|
array_element_name, site, production_table, collection
|
|
269
269
|
)
|
|
@@ -409,6 +409,11 @@ class DatabaseHandler:
|
|
|
409
409
|
Version of the model.
|
|
410
410
|
export_file_as_table: bool
|
|
411
411
|
If True, export the file as an astropy table (ecsv format).
|
|
412
|
+
|
|
413
|
+
Returns
|
|
414
|
+
-------
|
|
415
|
+
astropy.table.Table or None
|
|
416
|
+
If export_file_as_table is True
|
|
412
417
|
"""
|
|
413
418
|
parameters = self.get_model_parameter(
|
|
414
419
|
parameter,
|
|
@@ -518,9 +523,9 @@ class DatabaseHandler:
|
|
|
518
523
|
parameters[par_now]["entry_date"] = ObjectId(post["_id"]).generation_time
|
|
519
524
|
return {k: parameters[k] for k in sorted(parameters)}
|
|
520
525
|
|
|
521
|
-
def
|
|
526
|
+
def read_production_table_from_mongo_db(self, collection_name, model_version):
|
|
522
527
|
"""
|
|
523
|
-
Read production table from MongoDB.
|
|
528
|
+
Read production table for the given collection from MongoDB.
|
|
524
529
|
|
|
525
530
|
Parameters
|
|
526
531
|
----------
|
|
@@ -591,7 +596,7 @@ class DatabaseHandler:
|
|
|
591
596
|
list
|
|
592
597
|
Sorted list of all array elements found in collection
|
|
593
598
|
"""
|
|
594
|
-
production_table = self.
|
|
599
|
+
production_table = self.read_production_table_from_mongo_db(collection, model_version)
|
|
595
600
|
return sorted([entry for entry in production_table["parameters"] if "-design" not in entry])
|
|
596
601
|
|
|
597
602
|
def get_design_model(self, model_version, array_element_name, collection="telescopes"):
|
|
@@ -613,7 +618,7 @@ class DatabaseHandler:
|
|
|
613
618
|
str
|
|
614
619
|
Design model for a given array element.
|
|
615
620
|
"""
|
|
616
|
-
production_table = self.
|
|
621
|
+
production_table = self.read_production_table_from_mongo_db(collection, model_version)
|
|
617
622
|
try:
|
|
618
623
|
return production_table["design_model"][array_element_name]
|
|
619
624
|
except KeyError:
|
|
@@ -641,7 +646,7 @@ class DatabaseHandler:
|
|
|
641
646
|
list
|
|
642
647
|
Sorted list of all array element names found in collection
|
|
643
648
|
"""
|
|
644
|
-
production_table = self.
|
|
649
|
+
production_table = self.read_production_table_from_mongo_db(collection, model_version)
|
|
645
650
|
all_array_elements = production_table["parameters"]
|
|
646
651
|
return sorted(
|
|
647
652
|
[
|
|
@@ -759,7 +764,7 @@ class DatabaseHandler:
|
|
|
759
764
|
"""
|
|
760
765
|
db_name = self._get_db_name(db_name)
|
|
761
766
|
collection = self.get_collection(db_name, "production_tables")
|
|
762
|
-
self._logger.
|
|
767
|
+
self._logger.debug(f"Adding production for {production_table.get('collection')} to to DB")
|
|
763
768
|
collection.insert_one(production_table)
|
|
764
769
|
DatabaseHandler.production_table_cached.clear()
|
|
765
770
|
|
|
@@ -809,13 +814,13 @@ class DatabaseHandler:
|
|
|
809
814
|
raise ValueError(f"File is not UTF-8 encoded: {file_path}")
|
|
810
815
|
files_to_add_to_db.add(f"{file_path}")
|
|
811
816
|
|
|
812
|
-
self._logger.
|
|
817
|
+
self._logger.debug(
|
|
813
818
|
f"Adding a new entry to DB {db_name} and collection {collection_name}:\n{par_dict}"
|
|
814
819
|
)
|
|
815
820
|
collection.insert_one(par_dict)
|
|
816
821
|
|
|
817
822
|
for file_to_insert_now in files_to_add_to_db:
|
|
818
|
-
self._logger.
|
|
823
|
+
self._logger.debug(f"Will also add the file {file_to_insert_now} to the DB")
|
|
819
824
|
self.insert_file_to_db(file_to_insert_now, db_name)
|
|
820
825
|
|
|
821
826
|
self._reset_parameter_cache()
|
|
@@ -964,7 +969,7 @@ class DatabaseHandler:
|
|
|
964
969
|
return [array_element_name]
|
|
965
970
|
if collection == "configuration_sim_telarray":
|
|
966
971
|
# get design model from 'telescope' or 'calibration_device' production tables
|
|
967
|
-
production_table = self.
|
|
972
|
+
production_table = self.read_production_table_from_mongo_db(
|
|
968
973
|
names.get_collection_name_from_array_element_name(array_element_name),
|
|
969
974
|
production_table["model_version"],
|
|
970
975
|
)
|
simtools/db/db_model_upload.py
CHANGED
|
@@ -27,7 +27,7 @@ def add_values_from_json_to_db(file, collection, db, db_name, file_prefix):
|
|
|
27
27
|
Path to location of all additional files to be uploaded.
|
|
28
28
|
"""
|
|
29
29
|
par_dict = gen.collect_data_from_file(file_name=file)
|
|
30
|
-
logger.
|
|
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
33
|
f"(collection {collection} in database {db_name})"
|
|
@@ -120,7 +120,7 @@ def _read_production_table(model_dict, file, model_name):
|
|
|
120
120
|
},
|
|
121
121
|
)
|
|
122
122
|
parameter_dict = gen.collect_data_from_file(file_name=file)
|
|
123
|
-
logger.
|
|
123
|
+
logger.debug(f"Reading production table for {array_element} (collection {collection})")
|
|
124
124
|
try:
|
|
125
125
|
if array_element in ("configuration_corsika", "configuration_sim_telarray"):
|
|
126
126
|
model_dict[collection]["parameters"] = parameter_dict["parameters"]
|