gammasimtools 0.5.1__py3-none-any.whl → 0.6.1__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.5.1.dist-info → gammasimtools-0.6.1.dist-info}/METADATA +80 -28
- gammasimtools-0.6.1.dist-info/RECORD +91 -0
- {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/WHEEL +1 -1
- {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/entry_points.txt +4 -2
- simtools/_version.py +14 -2
- simtools/applications/add_file_to_db.py +2 -1
- simtools/applications/compare_cumulative_psf.py +10 -15
- simtools/applications/db_development_tools/add_new_parameter_to_db.py +12 -6
- simtools/applications/derive_mirror_rnda.py +95 -71
- simtools/applications/generate_corsika_histograms.py +216 -131
- simtools/applications/generate_default_metadata.py +110 -0
- simtools/applications/generate_simtel_array_histograms.py +192 -0
- simtools/applications/get_file_from_db.py +1 -1
- simtools/applications/get_parameter.py +3 -3
- simtools/applications/make_regular_arrays.py +89 -93
- simtools/applications/{plot_layout_array.py → plot_array_layout.py} +15 -14
- simtools/applications/print_array_elements.py +81 -34
- simtools/applications/produce_array_config.py +2 -2
- simtools/applications/production.py +39 -5
- simtools/applications/sim_showers_for_trigger_rates.py +26 -30
- simtools/applications/simulate_prod.py +49 -107
- simtools/applications/submit_data_from_external.py +8 -10
- simtools/applications/tune_psf.py +16 -18
- simtools/applications/validate_camera_efficiency.py +63 -9
- simtools/applications/validate_camera_fov.py +9 -13
- simtools/applications/validate_file_using_schema.py +127 -0
- simtools/applications/validate_optics.py +13 -15
- simtools/camera_efficiency.py +73 -80
- simtools/configuration/commandline_parser.py +52 -22
- simtools/configuration/configurator.py +98 -33
- simtools/constants.py +9 -0
- simtools/corsika/corsika_config.py +28 -22
- simtools/corsika/corsika_default_config.py +282 -0
- simtools/corsika/corsika_histograms.py +328 -282
- simtools/corsika/corsika_histograms_visualize.py +162 -163
- simtools/corsika/corsika_runner.py +8 -4
- simtools/corsika_simtel/corsika_simtel_runner.py +18 -23
- simtools/data_model/data_reader.py +129 -0
- simtools/data_model/metadata_collector.py +346 -118
- simtools/data_model/metadata_model.py +123 -218
- simtools/data_model/model_data_writer.py +79 -22
- simtools/data_model/validate_data.py +96 -46
- simtools/db_handler.py +67 -42
- simtools/io_operations/__init__.py +0 -0
- simtools/io_operations/hdf5_handler.py +112 -0
- simtools/{io_handler.py → io_operations/io_handler.py} +51 -22
- simtools/job_execution/job_manager.py +1 -1
- simtools/layout/{layout_array.py → array_layout.py} +168 -199
- simtools/layout/geo_coordinates.py +196 -0
- simtools/layout/telescope_position.py +12 -12
- simtools/model/array_model.py +16 -14
- simtools/model/camera.py +5 -8
- simtools/model/mirrors.py +136 -73
- simtools/model/model_utils.py +1 -69
- simtools/model/telescope_model.py +32 -25
- simtools/psf_analysis.py +26 -19
- simtools/ray_tracing.py +54 -26
- simtools/schemas/data.metaschema.yml +400 -0
- simtools/schemas/metadata.metaschema.yml +566 -0
- simtools/simtel/simtel_config_writer.py +14 -5
- simtools/simtel/simtel_histograms.py +266 -83
- simtools/simtel/simtel_runner.py +8 -7
- simtools/simtel/simtel_runner_array.py +7 -8
- simtools/simtel/simtel_runner_camera_efficiency.py +48 -2
- simtools/simtel/simtel_runner_ray_tracing.py +61 -25
- simtools/simulator.py +43 -50
- simtools/utils/general.py +232 -286
- simtools/utils/geometry.py +163 -0
- simtools/utils/names.py +294 -142
- simtools/visualization/legend_handlers.py +115 -9
- simtools/visualization/visualize.py +13 -13
- gammasimtools-0.5.1.dist-info/RECORD +0 -83
- simtools/applications/plot_simtel_histograms.py +0 -120
- simtools/applications/validate_schema_files.py +0 -135
- simtools/corsika/corsika_output_visualize.py +0 -345
- simtools/data_model/validate_schema.py +0 -285
- {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/LICENSE +0 -0
- {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/top_level.txt +0 -0
|
@@ -6,13 +6,12 @@
|
|
|
6
6
|
This application produces a set of histograms of the distribution of Cherenkov photons on the
|
|
7
7
|
ground (at observation level) read from the CORSIKA IACT output file provided as input.
|
|
8
8
|
|
|
9
|
-
The histograms can be saved both
|
|
10
|
-
formats.
|
|
9
|
+
The histograms can be saved both into pdfs and in a hdf5 file.
|
|
11
10
|
|
|
12
11
|
The following 2D histograms are produced:
|
|
13
12
|
- Number of Cherenkov photons on the ground;
|
|
14
13
|
- Density of Cherenkov photons on the ground;
|
|
15
|
-
- Incoming direction (directive
|
|
14
|
+
- Incoming direction (directive cosines) of the Cherenkov photons;
|
|
16
15
|
- Time of arrival (ns) vs altitude of production (km);
|
|
17
16
|
- Number of Cherenkov photons per event per telescope.
|
|
18
17
|
|
|
@@ -25,10 +24,13 @@
|
|
|
25
24
|
- Number of photons per telescope;
|
|
26
25
|
- Number of photons per event.
|
|
27
26
|
|
|
27
|
+
Histograms for the distribution of CORSIKA event header elements can also be generated by using
|
|
28
|
+
the `--event_1d_histograms` and `--event_2d_histograms` arguments. The accepted arguments (keys)
|
|
29
|
+
are to be found in the CORSIKA manual, e.g., "total_energy", "zenith", "azimuth".
|
|
28
30
|
|
|
29
31
|
Command line arguments
|
|
30
32
|
----------------------
|
|
31
|
-
|
|
33
|
+
iact_file (str, required)
|
|
32
34
|
The name of the CORSIKA IACT file resulted from the CORSIKA simulation.
|
|
33
35
|
|
|
34
36
|
telescope_indices (list, optional)
|
|
@@ -40,88 +42,106 @@
|
|
|
40
42
|
Indicates whether single histograms are generated for the individual telescopes, or if
|
|
41
43
|
a master histogram is generated for all the telescopes together.
|
|
42
44
|
If the argument is not given, the Cherenkov photons from the given telescopes are considered
|
|
43
|
-
|
|
45
|
+
together in the same histograms.
|
|
44
46
|
|
|
45
|
-
hist_config (
|
|
47
|
+
hist_config (hdf5 or dict, optional)
|
|
46
48
|
The configuration used for generating the histograms.
|
|
47
49
|
It includes information about the bin sizes, the ranges, scale of the plot and units.
|
|
48
50
|
By construction, three major histograms are created to start with:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
- hist_direction (2D): Directive cosines (x and y) for the incoming photons;
|
|
52
|
+
- hist_position (3D): position x, position y, and wavelength;
|
|
53
|
+
- hist_time_altitude (2D): time of arrival and altitude of emission;
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
If the argument is not given, the default configuration is generated:
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
.. code-block:: console
|
|
58
|
+
|
|
59
|
+
hist_direction:
|
|
60
|
+
x axis: {bins: 100, scale: linear, start: -1, stop: 1}
|
|
61
|
+
y axis: {bins: 100, scale: linear, start: -1, stop: 1}
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
hist_position:
|
|
64
|
+
x axis:
|
|
62
65
|
bins: 100
|
|
63
66
|
scale: linear
|
|
64
67
|
start: !astropy.units.Quantity
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
unit: &id001 !astropy.units.Unit {unit: m}
|
|
69
|
+
value: -1000.0
|
|
67
70
|
stop: &id002 !astropy.units.Quantity
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
unit: *id001
|
|
72
|
+
value: 1000.0
|
|
73
|
+
y axis:
|
|
71
74
|
bins: 100
|
|
72
75
|
scale: linear
|
|
73
76
|
start: !astropy.units.Quantity
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
unit: *id001
|
|
78
|
+
value: -1000.0
|
|
76
79
|
stop: *id002
|
|
77
|
-
|
|
80
|
+
z axis:
|
|
78
81
|
bins: 80
|
|
79
82
|
scale: linear
|
|
80
83
|
start: !astropy.units.Quantity
|
|
81
|
-
|
|
82
|
-
|
|
84
|
+
unit: &id003 !astropy.units.Unit {unit: nm}
|
|
85
|
+
value: 200.0
|
|
83
86
|
stop: !astropy.units.Quantity
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
unit: *id003
|
|
88
|
+
value: 1000.0
|
|
89
|
+
hist_time_altitude:
|
|
90
|
+
x axis:
|
|
88
91
|
bins: 100
|
|
89
92
|
scale: linear
|
|
90
93
|
start: !astropy.units.Quantity
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
unit: &id004 !astropy.units.Unit {unit: ns}
|
|
95
|
+
value: -2000.0
|
|
93
96
|
stop: !astropy.units.Quantity
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
unit: *id004
|
|
98
|
+
value: 2000.0
|
|
99
|
+
y axis:
|
|
97
100
|
bins: 100
|
|
98
101
|
scale: linear
|
|
99
102
|
start: !astropy.units.Quantity
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
unit: &id005 !astropy.units.Unit {unit: km}
|
|
104
|
+
value: 120.0
|
|
102
105
|
stop: !astropy.units.Quantity
|
|
103
|
-
|
|
104
|
-
|
|
106
|
+
unit: *id005
|
|
107
|
+
value: 0.0
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
pdf (bool, optional)
|
|
111
|
+
If set, histograms are saved into pdf files.
|
|
112
|
+
One pdf file contains all the histograms for the Cherenkov photons.
|
|
113
|
+
The name of the file is controlled via `hdf5_file_name`.
|
|
114
|
+
If event_1d_histograms and event_2d_histograms are used, two separate pdf files might be
|
|
115
|
+
created to accommodate the histograms for the CORSIKA event header elements. The core names
|
|
116
|
+
of these output pdf files are also given by `hdf5_file_name` argument with the addition of
|
|
117
|
+
'event_1d_histograms' and 'event_2d_histograms'.
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
hdf5 (bool, optional)
|
|
121
|
+
If set, histograms are saved into hdf5 files.
|
|
105
122
|
|
|
106
|
-
|
|
107
|
-
|
|
123
|
+
hdf5_file_name (str, optional)
|
|
124
|
+
The name of the output hdf5 data (without the path).
|
|
125
|
+
It requires the `--hdf5` flag.
|
|
126
|
+
If not given, `hdf5_file_name` takes the name from the input IACT file (`input_file`).
|
|
127
|
+
If the output `hdf5_file_name` file already exists, the tables associated to the chosen
|
|
128
|
+
flags (e.g. `hdf5`, `event_1d_histograms`, `event_2d_histograms`) will be overwritten. The
|
|
129
|
+
remaining tables, if any, will stay untouched.
|
|
108
130
|
|
|
109
|
-
ecsv (bool, optional)
|
|
110
|
-
If true, histograms are saved into ecsv files.
|
|
111
131
|
|
|
112
|
-
|
|
113
|
-
Produce 1D histograms for elements given in `--
|
|
114
|
-
header and save into
|
|
132
|
+
event_1d_histograms (str, optional)
|
|
133
|
+
Produce 1D histograms for elements given in `--event_1d_histograms` from the CORSIKA event
|
|
134
|
+
header and save into hdf5/pdf files.
|
|
115
135
|
It allows more than one argument, separated by simple spaces.
|
|
116
|
-
Usage: `--
|
|
136
|
+
Usage: `--event_1d_histograms first_interaction_height total_energy`.
|
|
117
137
|
|
|
118
|
-
|
|
119
|
-
Produce 2D histograms for elements given in `--
|
|
120
|
-
header and save into
|
|
138
|
+
event_2d_histograms (str, optional)
|
|
139
|
+
Produce 2D histograms for elements given in `--event_2d_histograms` from the CORSIKA event
|
|
140
|
+
header and save into hdf5/pdf files.
|
|
121
141
|
It allows more than one argument, separated by simple spaces.
|
|
122
142
|
The elements are grouped into pairs and the 2D histograms are produced always for two
|
|
123
143
|
subsequent elements.
|
|
124
|
-
For example, `--
|
|
144
|
+
For example, `--event_2d_histograms first_interaction_height total_energy zenith azimuth`
|
|
125
145
|
will produce one 2D histogram for `first_interaction_height` `total_energy` and another 2D
|
|
126
146
|
histogram for `zenith` and `azimuth`.
|
|
127
147
|
|
|
@@ -131,29 +151,31 @@
|
|
|
131
151
|
|
|
132
152
|
.. code-block:: console
|
|
133
153
|
|
|
134
|
-
simtools-generate-corsika-histograms --
|
|
135
|
-
resources/tel_output_10GeV-2-gamma-20deg-CTAO-South.corsikaio --
|
|
136
|
-
--
|
|
154
|
+
simtools-generate-corsika-histograms --iact_file /workdir/external/simtools/tests/\
|
|
155
|
+
resources/tel_output_10GeV-2-gamma-20deg-CTAO-South.corsikaio --pdf --hdf5
|
|
156
|
+
--event_2d_histograms zenith azimuth --event_1d_histograms total_energy
|
|
137
157
|
|
|
138
158
|
|
|
139
159
|
Expected final print-out message:
|
|
140
160
|
|
|
141
161
|
.. code-block:: console
|
|
162
|
+
|
|
142
163
|
INFO::generate_corsika_histograms(l358)::main::Finalizing the application.
|
|
143
164
|
Total time needed: 8s.
|
|
144
165
|
"""
|
|
145
166
|
|
|
146
167
|
import logging
|
|
168
|
+
import re
|
|
147
169
|
import time
|
|
148
170
|
from pathlib import Path
|
|
149
171
|
|
|
150
172
|
import numpy as np
|
|
151
173
|
|
|
152
174
|
import simtools.utils.general as gen
|
|
153
|
-
from simtools import io_handler
|
|
154
175
|
from simtools.configuration import configurator
|
|
155
176
|
from simtools.corsika import corsika_histograms_visualize
|
|
156
177
|
from simtools.corsika.corsika_histograms import CorsikaHistograms
|
|
178
|
+
from simtools.io_operations import io_handler
|
|
157
179
|
|
|
158
180
|
logger = logging.getLogger()
|
|
159
181
|
|
|
@@ -178,7 +200,7 @@ def _parse(label, description):
|
|
|
178
200
|
config = configurator.Configurator(label=label, description=description)
|
|
179
201
|
|
|
180
202
|
config.parser.add_argument(
|
|
181
|
-
"--
|
|
203
|
+
"--iact_file",
|
|
182
204
|
help="Name of the CORSIKA IACT file from which to generate the histograms.",
|
|
183
205
|
type=str,
|
|
184
206
|
required=True,
|
|
@@ -204,35 +226,43 @@ def _parse(label, description):
|
|
|
204
226
|
|
|
205
227
|
config.parser.add_argument(
|
|
206
228
|
"--hist_config",
|
|
207
|
-
help="
|
|
229
|
+
help="hdf5 file with the configuration parameters to create the histograms.",
|
|
208
230
|
type=str,
|
|
209
231
|
required=False,
|
|
210
232
|
default=None,
|
|
211
233
|
)
|
|
212
234
|
|
|
213
235
|
config.parser.add_argument(
|
|
214
|
-
"--
|
|
236
|
+
"--pdf", help="Save histograms into a pdf file.", action="store_true", required=False
|
|
215
237
|
)
|
|
216
238
|
|
|
217
239
|
config.parser.add_argument(
|
|
218
|
-
"--
|
|
240
|
+
"--hdf5", help="Save histograms into hdf5 files.", action="store_true", required=False
|
|
219
241
|
)
|
|
220
242
|
|
|
221
243
|
config.parser.add_argument(
|
|
222
|
-
"--
|
|
244
|
+
"--hdf5_file_name",
|
|
245
|
+
help="Name of the hdf5 file where to save the histograms.",
|
|
246
|
+
type=str,
|
|
247
|
+
required=False,
|
|
248
|
+
default=None,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
config.parser.add_argument(
|
|
252
|
+
"--event_1d_histograms",
|
|
223
253
|
help="The keys from the CORSIKA event header to be used for the generation of 1D "
|
|
224
|
-
|
|
225
|
-
|
|
254
|
+
"histograms. The available choices can been found in the `all_event_keys` attribute of"
|
|
255
|
+
"the CorsikaHistograms.",
|
|
226
256
|
required=False,
|
|
227
257
|
default=None,
|
|
228
258
|
nargs="*",
|
|
229
259
|
)
|
|
230
260
|
|
|
231
261
|
config.parser.add_argument(
|
|
232
|
-
"--
|
|
262
|
+
"--event_2d_histograms",
|
|
233
263
|
help="The keys from the CORSIKA event header to be used for the generation of 2D "
|
|
234
|
-
|
|
235
|
-
|
|
264
|
+
"histograms. The available choices can been found in the `all_event_keys` attribute of"
|
|
265
|
+
"the CorsikaHistograms.",
|
|
236
266
|
required=False,
|
|
237
267
|
default=None,
|
|
238
268
|
nargs="*",
|
|
@@ -240,13 +270,21 @@ def _parse(label, description):
|
|
|
240
270
|
|
|
241
271
|
config_parser, _ = config.initialize(db_config=False, paths=True)
|
|
242
272
|
|
|
243
|
-
if not config_parser["
|
|
244
|
-
|
|
273
|
+
if not config_parser["pdf"]:
|
|
274
|
+
if (
|
|
275
|
+
not config_parser["hdf5"]
|
|
276
|
+
and not config_parser["event_1d_histograms"]
|
|
277
|
+
and not config_parser["event_2d_histograms"]
|
|
278
|
+
):
|
|
279
|
+
config.parser.error(
|
|
280
|
+
"At least one argument is required: `--pdf`, `--hdf5`, `--event_1d_histograms`, or "
|
|
281
|
+
"`--event_2d_histograms`."
|
|
282
|
+
)
|
|
245
283
|
|
|
246
284
|
return config_parser, _
|
|
247
285
|
|
|
248
286
|
|
|
249
|
-
def _plot_figures(corsika_histograms_instance):
|
|
287
|
+
def _plot_figures(corsika_histograms_instance, test=False):
|
|
250
288
|
"""
|
|
251
289
|
Auxiliary function to centralize the plotting functions.
|
|
252
290
|
|
|
@@ -254,6 +292,8 @@ def _plot_figures(corsika_histograms_instance):
|
|
|
254
292
|
----------
|
|
255
293
|
corsika_histograms_instance: `CorsikaHistograms` instance.
|
|
256
294
|
The CorsikaHistograms instance created in main.
|
|
295
|
+
test: bool
|
|
296
|
+
If true plots the figures for the first two functions only.
|
|
257
297
|
"""
|
|
258
298
|
|
|
259
299
|
plot_function_names = [
|
|
@@ -262,87 +302,114 @@ def _plot_figures(corsika_histograms_instance):
|
|
|
262
302
|
if plotting_method.startswith("plot_")
|
|
263
303
|
and "event_header_distribution" not in plotting_method
|
|
264
304
|
]
|
|
305
|
+
if test:
|
|
306
|
+
plot_function_names = plot_function_names[:2]
|
|
265
307
|
|
|
308
|
+
figure_list = []
|
|
266
309
|
for function_name in plot_function_names:
|
|
267
310
|
function = getattr(corsika_histograms_visualize, function_name)
|
|
268
|
-
figures
|
|
269
|
-
for
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
311
|
+
figures = function(corsika_histograms_instance)
|
|
312
|
+
for fig in figures:
|
|
313
|
+
figure_list.append(fig)
|
|
314
|
+
|
|
315
|
+
figure_list = np.array(figure_list).flatten()
|
|
316
|
+
core_name = re.sub(r"\.hdf5$", "", corsika_histograms_instance.hdf5_file_name)
|
|
317
|
+
output_file_name = Path(corsika_histograms_instance.output_path).joinpath(f"{core_name}.pdf")
|
|
318
|
+
corsika_histograms_visualize.save_figs_to_pdf(figure_list, output_file_name)
|
|
273
319
|
|
|
274
320
|
|
|
275
|
-
def
|
|
321
|
+
def _derive_event_1d_histograms(
|
|
322
|
+
corsika_histograms_instance, event_1d_header_keys, pdf, hdf5, overwrite=False
|
|
323
|
+
):
|
|
276
324
|
"""
|
|
277
|
-
Auxiliary function to derive the histograms for the arguments given by
|
|
325
|
+
Auxiliary function to derive the histograms for the arguments given by event_1d_histograms.
|
|
278
326
|
|
|
279
327
|
Parameters
|
|
280
328
|
----------
|
|
281
329
|
corsika_histograms_instance: `CorsikaHistograms` instance.
|
|
282
330
|
The CorsikaHistograms instance created in main.
|
|
283
|
-
|
|
284
|
-
Produce 1D histograms for elements given in `
|
|
285
|
-
header and save into
|
|
286
|
-
|
|
287
|
-
If true, histograms are saved into
|
|
288
|
-
|
|
289
|
-
If true, histograms are saved into
|
|
331
|
+
event_1d_header_keys: str
|
|
332
|
+
Produce 1D histograms for elements given in `event_1d_header_keys` from the CORSIKA event
|
|
333
|
+
header and save into hdf5/pdf files.
|
|
334
|
+
pdf: bool
|
|
335
|
+
If true, histograms are saved into a pdf file.
|
|
336
|
+
hdf5: bool
|
|
337
|
+
If true, histograms are saved into hdf5 files.
|
|
338
|
+
overwrite: bool
|
|
339
|
+
If true, overwrites the current output hdf5 file.
|
|
290
340
|
"""
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
341
|
+
figure_list = []
|
|
342
|
+
for event_header_element in event_1d_header_keys:
|
|
343
|
+
if pdf:
|
|
344
|
+
figure = corsika_histograms_visualize.plot_1d_event_header_distribution(
|
|
294
345
|
corsika_histograms_instance, event_header_element
|
|
295
346
|
)
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
corsika_histograms_instance.export_event_header_1D_histogram(
|
|
301
|
-
event_header_element, bins=50, hist_range=None
|
|
347
|
+
figure_list.append(figure)
|
|
348
|
+
if hdf5:
|
|
349
|
+
corsika_histograms_instance.export_event_header_1d_histogram(
|
|
350
|
+
event_header_element, bins=50, hist_range=None, overwrite=overwrite
|
|
302
351
|
)
|
|
352
|
+
if pdf:
|
|
353
|
+
figures_list = np.array(figure_list).flatten()
|
|
354
|
+
output_file_name = Path(corsika_histograms_instance.output_path).joinpath(
|
|
355
|
+
f"{corsika_histograms_instance.hdf5_file_name}_event_1d_histograms.pdf"
|
|
356
|
+
)
|
|
357
|
+
corsika_histograms_visualize.save_figs_to_pdf(figures_list, output_file_name)
|
|
303
358
|
|
|
304
359
|
|
|
305
|
-
def
|
|
360
|
+
def _derive_event_2d_histograms(
|
|
361
|
+
corsika_histograms_instance, event_2d_header_keys, pdf, hdf5, overwrite=False
|
|
362
|
+
):
|
|
306
363
|
"""
|
|
307
|
-
Auxiliary function to derive the histograms for the arguments given by
|
|
364
|
+
Auxiliary function to derive the histograms for the arguments given by event_1d_histograms.
|
|
308
365
|
If an odd number of event header keys are given, the last one is discarded.
|
|
309
366
|
|
|
310
367
|
Parameters
|
|
311
368
|
----------
|
|
312
369
|
corsika_histograms_instance: `CorsikaHistograms` instance.
|
|
313
370
|
The CorsikaHistograms instance created in main.
|
|
314
|
-
|
|
315
|
-
Produce 1D histograms for elements given in `
|
|
316
|
-
header and save into
|
|
317
|
-
|
|
318
|
-
If true, histograms are saved into
|
|
319
|
-
|
|
320
|
-
If true, histograms are saved into
|
|
371
|
+
event_2d_header_keys: str
|
|
372
|
+
Produce 1D histograms for elements given in `event_1d_header_keys` from the CORSIKA event
|
|
373
|
+
header and save into hdf5/pdf files.
|
|
374
|
+
pdf: bool
|
|
375
|
+
If true, histograms are saved into a pdf file.
|
|
376
|
+
hdf5: bool
|
|
377
|
+
If true, histograms are saved into hdf5 files.
|
|
378
|
+
overwrite: bool
|
|
379
|
+
If true, overwrites the current output hdf5 file.
|
|
321
380
|
"""
|
|
322
|
-
|
|
381
|
+
figure_list = []
|
|
382
|
+
for i_event_header_element, _ in enumerate(event_2d_header_keys[::2]):
|
|
323
383
|
# [::2] to discard the last one in case an odd number of keys are passed
|
|
324
384
|
|
|
325
|
-
if len(
|
|
326
|
-
msg =
|
|
327
|
-
|
|
385
|
+
if len(event_2d_header_keys) % 2 == 1: # if odd number of keys
|
|
386
|
+
msg = (
|
|
387
|
+
"An odd number of keys was passed to produce 2D histograms."
|
|
388
|
+
"The last key is being ignored."
|
|
389
|
+
)
|
|
328
390
|
logger.warning(msg)
|
|
329
391
|
|
|
330
|
-
if
|
|
331
|
-
figure
|
|
392
|
+
if pdf:
|
|
393
|
+
figure = corsika_histograms_visualize.plot_2d_event_header_distribution(
|
|
332
394
|
corsika_histograms_instance,
|
|
333
|
-
|
|
334
|
-
|
|
395
|
+
event_2d_header_keys[i_event_header_element],
|
|
396
|
+
event_2d_header_keys[i_event_header_element + 1],
|
|
335
397
|
)
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
event_2D_header_keys[i_event_header_element],
|
|
342
|
-
event_2D_header_keys[i_event_header_element + 1],
|
|
398
|
+
figure_list.append(figure)
|
|
399
|
+
if hdf5:
|
|
400
|
+
corsika_histograms_instance.export_event_header_2d_histogram(
|
|
401
|
+
event_2d_header_keys[i_event_header_element],
|
|
402
|
+
event_2d_header_keys[i_event_header_element + 1],
|
|
343
403
|
bins=50,
|
|
344
404
|
hist_range=None,
|
|
405
|
+
overwrite=overwrite,
|
|
345
406
|
)
|
|
407
|
+
if pdf:
|
|
408
|
+
figures_list = np.array(figure_list).flatten()
|
|
409
|
+
output_file_name = Path(corsika_histograms_instance.output_path).joinpath(
|
|
410
|
+
f"{corsika_histograms_instance.hdf5_file_name}_event_2d_histograms.pdf"
|
|
411
|
+
)
|
|
412
|
+
corsika_histograms_visualize.save_figs_to_pdf(figures_list, output_file_name)
|
|
346
413
|
|
|
347
414
|
|
|
348
415
|
def main():
|
|
@@ -351,13 +418,15 @@ def main():
|
|
|
351
418
|
io_handler_instance = io_handler.IOHandler()
|
|
352
419
|
args_dict, _ = _parse(label, description)
|
|
353
420
|
|
|
354
|
-
output_path = io_handler_instance.get_output_directory(label,
|
|
421
|
+
output_path = io_handler_instance.get_output_directory(label, sub_dir="application-plots")
|
|
355
422
|
|
|
356
423
|
logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
|
|
357
424
|
initial_time = time.time()
|
|
358
425
|
logger.info("Starting the application.")
|
|
359
426
|
|
|
360
|
-
corsika_histograms_instance = CorsikaHistograms(
|
|
427
|
+
corsika_histograms_instance = CorsikaHistograms(
|
|
428
|
+
args_dict["iact_file"], output_path=output_path, hdf5_file_name=args_dict["hdf5_file_name"]
|
|
429
|
+
)
|
|
361
430
|
if args_dict["telescope_indices"] is not None:
|
|
362
431
|
try:
|
|
363
432
|
indices = np.array(args_dict["telescope_indices"]).astype(int)
|
|
@@ -370,6 +439,18 @@ def main():
|
|
|
370
439
|
raise
|
|
371
440
|
else:
|
|
372
441
|
indices = None
|
|
442
|
+
# If the hdf5 output file already exists, the results are appended to it.
|
|
443
|
+
if (Path(corsika_histograms_instance.hdf5_file_name).exists()) and (
|
|
444
|
+
args_dict["hdf5"] or args_dict["event_1d_histograms"] or args_dict["event_2d_histograms"]
|
|
445
|
+
):
|
|
446
|
+
msg = (
|
|
447
|
+
f"Output hdf5 file {corsika_histograms_instance.hdf5_file_name} already exists. "
|
|
448
|
+
f"Overwriting it."
|
|
449
|
+
)
|
|
450
|
+
logger.warning(msg)
|
|
451
|
+
overwrite = True
|
|
452
|
+
else:
|
|
453
|
+
overwrite = False
|
|
373
454
|
corsika_histograms_instance.set_histograms(
|
|
374
455
|
telescope_indices=indices,
|
|
375
456
|
individual_telescopes=args_dict["individual_telescopes"],
|
|
@@ -377,25 +458,29 @@ def main():
|
|
|
377
458
|
)
|
|
378
459
|
|
|
379
460
|
# Cherenkov photons
|
|
380
|
-
if args_dict["
|
|
381
|
-
_plot_figures(
|
|
382
|
-
|
|
383
|
-
|
|
461
|
+
if args_dict["pdf"]:
|
|
462
|
+
_plot_figures(
|
|
463
|
+
corsika_histograms_instance=corsika_histograms_instance, test=args_dict["test"]
|
|
464
|
+
)
|
|
465
|
+
if args_dict["hdf5"]:
|
|
466
|
+
corsika_histograms_instance.export_histograms(overwrite=overwrite)
|
|
384
467
|
|
|
385
468
|
# Event information
|
|
386
|
-
if args_dict["
|
|
387
|
-
|
|
469
|
+
if args_dict["event_1d_histograms"] is not None:
|
|
470
|
+
_derive_event_1d_histograms(
|
|
388
471
|
corsika_histograms_instance,
|
|
389
|
-
args_dict["
|
|
390
|
-
args_dict["
|
|
391
|
-
args_dict["
|
|
472
|
+
args_dict["event_1d_histograms"],
|
|
473
|
+
args_dict["pdf"],
|
|
474
|
+
args_dict["hdf5"],
|
|
475
|
+
overwrite=not args_dict["hdf5"],
|
|
392
476
|
)
|
|
393
|
-
if args_dict["
|
|
394
|
-
|
|
477
|
+
if args_dict["event_2d_histograms"] is not None:
|
|
478
|
+
_derive_event_2d_histograms(
|
|
395
479
|
corsika_histograms_instance,
|
|
396
|
-
args_dict["
|
|
397
|
-
args_dict["
|
|
398
|
-
args_dict["
|
|
480
|
+
args_dict["event_2d_histograms"],
|
|
481
|
+
args_dict["pdf"],
|
|
482
|
+
args_dict["hdf5"],
|
|
483
|
+
overwrite=not (args_dict["hdf5"] or args_dict["event_1d_histograms"]),
|
|
399
484
|
)
|
|
400
485
|
|
|
401
486
|
final_time = time.time()
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
Summary
|
|
4
|
+
-------
|
|
5
|
+
Generate a default simtools metadata file from a json schema.
|
|
6
|
+
|
|
7
|
+
Command line arguments
|
|
8
|
+
----------------------
|
|
9
|
+
schema (str, optional)
|
|
10
|
+
Schema file describing the input data
|
|
11
|
+
(default: simtools/schemas/metadata.metaschema.yml)
|
|
12
|
+
output_file (str, optional)
|
|
13
|
+
Output file name.
|
|
14
|
+
|
|
15
|
+
Example
|
|
16
|
+
-------
|
|
17
|
+
.. code-block:: console
|
|
18
|
+
|
|
19
|
+
simtools-generate-default-metadata
|
|
20
|
+
--schema simtools/schemas/metadata.metaschema.yml
|
|
21
|
+
--output_file default_metadata.yml
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
import json
|
|
27
|
+
import logging
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
import yaml
|
|
31
|
+
|
|
32
|
+
import simtools.utils.general as gen
|
|
33
|
+
from simtools.configuration import configurator
|
|
34
|
+
from simtools.data_model import metadata_model
|
|
35
|
+
from simtools.io_operations import io_handler
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _parse(label, description):
|
|
39
|
+
"""
|
|
40
|
+
Parse command line configuration
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
label: str
|
|
45
|
+
Label describing application.
|
|
46
|
+
description: str
|
|
47
|
+
Description of application.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
CommandLineParser
|
|
52
|
+
Command line parser object
|
|
53
|
+
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
config = configurator.Configurator(label=label, description=description)
|
|
57
|
+
|
|
58
|
+
config.parser.add_argument(
|
|
59
|
+
"--schema",
|
|
60
|
+
help="schema file describing input data",
|
|
61
|
+
type=str,
|
|
62
|
+
required=True,
|
|
63
|
+
)
|
|
64
|
+
config.parser.add_argument(
|
|
65
|
+
"--output_file",
|
|
66
|
+
help="output file name (if not given: print to stdout)",
|
|
67
|
+
type=str,
|
|
68
|
+
required=False,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
return config.initialize(output=False, require_command_line=True)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def main():
|
|
75
|
+
label = Path(__file__).stem
|
|
76
|
+
args_dict, _ = _parse(
|
|
77
|
+
label, description="Generate a default simtools metadata file from a json schema."
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
_logger = logging.getLogger()
|
|
81
|
+
_logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
|
|
82
|
+
|
|
83
|
+
default_values = metadata_model.get_default_metadata_dict(args_dict["schema"])
|
|
84
|
+
|
|
85
|
+
if args_dict["output_file"] is None:
|
|
86
|
+
print(default_values)
|
|
87
|
+
else:
|
|
88
|
+
_io_handler = io_handler.IOHandler()
|
|
89
|
+
_out_file = _io_handler.get_output_file(args_dict["output_file"])
|
|
90
|
+
_logger.info(f"Writing default values to {_out_file}")
|
|
91
|
+
if args_dict["output_file"].endswith((".yml", ".yaml")):
|
|
92
|
+
with open(_out_file, "w", encoding="utf-8") as file:
|
|
93
|
+
yaml.dump(
|
|
94
|
+
default_values,
|
|
95
|
+
file,
|
|
96
|
+
default_flow_style=False,
|
|
97
|
+
sort_keys=False,
|
|
98
|
+
)
|
|
99
|
+
if args_dict["output_file"].endswith(".json"):
|
|
100
|
+
with open(_out_file, "w", encoding="utf-8") as file:
|
|
101
|
+
json.dump(
|
|
102
|
+
default_values,
|
|
103
|
+
file,
|
|
104
|
+
indent=4,
|
|
105
|
+
sort_keys=False,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
if __name__ == "__main__":
|
|
110
|
+
main()
|