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
|
@@ -5,7 +5,6 @@ import logging
|
|
|
5
5
|
import shutil
|
|
6
6
|
from copy import copy
|
|
7
7
|
from math import pi, tan
|
|
8
|
-
from pathlib import Path
|
|
9
8
|
|
|
10
9
|
import astropy.io.ascii
|
|
11
10
|
import astropy.units as u
|
|
@@ -33,8 +32,6 @@ class RayTracing:
|
|
|
33
32
|
telescope model
|
|
34
33
|
site_model: SiteModel
|
|
35
34
|
site model
|
|
36
|
-
simtel_path: str (or Path)
|
|
37
|
-
Location of sim_telarray installation.
|
|
38
35
|
label: str
|
|
39
36
|
label used for output file naming.
|
|
40
37
|
zenith_angle: astropy.units.Quantity
|
|
@@ -64,7 +61,6 @@ class RayTracing:
|
|
|
64
61
|
self,
|
|
65
62
|
telescope_model,
|
|
66
63
|
site_model,
|
|
67
|
-
simtel_path,
|
|
68
64
|
label=None,
|
|
69
65
|
zenith_angle=20.0 * u.deg,
|
|
70
66
|
off_axis_angle=[0.0] * u.deg,
|
|
@@ -78,7 +74,6 @@ class RayTracing:
|
|
|
78
74
|
self._logger = logging.getLogger(__name__)
|
|
79
75
|
self._logger.debug(f"Initializing RayTracing class {single_mirror_mode}")
|
|
80
76
|
|
|
81
|
-
self.simtel_path = Path(simtel_path)
|
|
82
77
|
self._io_handler = io_handler.IOHandler()
|
|
83
78
|
|
|
84
79
|
self.telescope_model, self.site_model = telescope_model, site_model
|
|
@@ -212,7 +207,6 @@ class RayTracing:
|
|
|
212
207
|
f"Simulating RayTracing for off_axis={this_off_axis}, mirror={mirror_number}"
|
|
213
208
|
)
|
|
214
209
|
simtel = SimulatorRayTracing(
|
|
215
|
-
simtel_path=self.simtel_path,
|
|
216
210
|
telescope_model=self.telescope_model,
|
|
217
211
|
site_model=self.site_model,
|
|
218
212
|
test=test,
|
|
@@ -408,11 +402,7 @@ class RayTracing:
|
|
|
408
402
|
PSFImage
|
|
409
403
|
PSF image object.
|
|
410
404
|
"""
|
|
411
|
-
image = PSFImage(
|
|
412
|
-
focal_length=focal_length,
|
|
413
|
-
containment_fraction=containment_fraction,
|
|
414
|
-
simtel_path=self.simtel_path,
|
|
415
|
-
)
|
|
405
|
+
image = PSFImage(focal_length=focal_length, containment_fraction=containment_fraction)
|
|
416
406
|
image.process_photon_list(photons_file, use_rx)
|
|
417
407
|
self._psf_images[this_off_axis] = copy(image)
|
|
418
408
|
return image
|
|
@@ -623,10 +613,11 @@ class RayTracing:
|
|
|
623
613
|
-------
|
|
624
614
|
List of PSFImages
|
|
625
615
|
"""
|
|
626
|
-
images = [
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
616
|
+
images = [
|
|
617
|
+
self._psf_images[this_off_axis]
|
|
618
|
+
for this_off_axis in self.off_axis_angle
|
|
619
|
+
if self._psf_images and this_off_axis in self._psf_images
|
|
620
|
+
]
|
|
630
621
|
if len(images) == 0:
|
|
631
622
|
self._logger.warning("No image found")
|
|
632
623
|
return None
|
|
@@ -16,11 +16,10 @@ logger = logging.getLogger()
|
|
|
16
16
|
class ReportGenerator:
|
|
17
17
|
"""Automate report generation."""
|
|
18
18
|
|
|
19
|
-
def __init__(self,
|
|
19
|
+
def __init__(self, args, output_path):
|
|
20
20
|
"""Initialise class."""
|
|
21
21
|
self._logger = logging.getLogger(__name__)
|
|
22
|
-
self.db = db_handler.DatabaseHandler(
|
|
23
|
-
self.db_config = db_config
|
|
22
|
+
self.db = db_handler.DatabaseHandler()
|
|
24
23
|
self.args = args
|
|
25
24
|
self.output_path = output_path
|
|
26
25
|
|
|
@@ -99,7 +98,7 @@ class ReportGenerator:
|
|
|
99
98
|
)
|
|
100
99
|
|
|
101
100
|
output_path = Path(self.output_path) / str(model_version)
|
|
102
|
-
ReadParameters(self.
|
|
101
|
+
ReadParameters(self.args, output_path).produce_array_element_report()
|
|
103
102
|
|
|
104
103
|
logger.info(
|
|
105
104
|
f"Markdown report generated for {site} "
|
|
@@ -167,9 +166,7 @@ class ReportGenerator:
|
|
|
167
166
|
}
|
|
168
167
|
)
|
|
169
168
|
|
|
170
|
-
ReadParameters(
|
|
171
|
-
self.db_config, self.args, self.output_path
|
|
172
|
-
).produce_model_parameter_reports()
|
|
169
|
+
ReadParameters(self.args, self.output_path).produce_model_parameter_reports()
|
|
173
170
|
|
|
174
171
|
logger.info(
|
|
175
172
|
f"Markdown report generated for {site} Telescope {telescope}: {self.output_path}"
|
|
@@ -211,7 +208,7 @@ class ReportGenerator:
|
|
|
211
208
|
)
|
|
212
209
|
|
|
213
210
|
output_path = Path(self.output_path) / str(model_version)
|
|
214
|
-
ReadParameters(self.
|
|
211
|
+
ReadParameters(self.args, output_path).produce_observatory_report()
|
|
215
212
|
|
|
216
213
|
logger.info(f"Observatory report generated for {site} (v{model_version}): {output_path}")
|
|
217
214
|
|
|
@@ -237,9 +234,7 @@ class ReportGenerator:
|
|
|
237
234
|
self.args.update({"model_version": version})
|
|
238
235
|
output_path = Path(self.output_path) / str(version)
|
|
239
236
|
|
|
240
|
-
ReadParameters(
|
|
241
|
-
self.db_config, self.args, output_path
|
|
242
|
-
).produce_simulation_configuration_report()
|
|
237
|
+
ReadParameters(self.args, output_path).produce_simulation_configuration_report()
|
|
243
238
|
|
|
244
239
|
logger.info(f"Configuration reports for (v{version}) produced: {output_path}")
|
|
245
240
|
|
|
@@ -262,7 +257,7 @@ class ReportGenerator:
|
|
|
262
257
|
output_path = Path(self.output_path) / str(version)
|
|
263
258
|
|
|
264
259
|
try:
|
|
265
|
-
ReadParameters(self.
|
|
260
|
+
ReadParameters(self.args, output_path).produce_calibration_reports()
|
|
266
261
|
logger.info(f"Calibration reports for (v{version}) produced: {output_path}")
|
|
267
262
|
except ValueError as err:
|
|
268
263
|
# Some model versions do not have calibration_devices in the DB;
|
|
@@ -305,7 +300,7 @@ class ReportGenerator:
|
|
|
305
300
|
|
|
306
301
|
# Generate parameter comparison reports for calibration devices
|
|
307
302
|
ReadParameters(
|
|
308
|
-
|
|
303
|
+
version_args, self.output_path
|
|
309
304
|
).generate_model_parameter_reports_for_devices(array_elements)
|
|
310
305
|
|
|
311
306
|
logger.info(
|
|
@@ -17,7 +17,7 @@ from simtools.io import ascii_handler, io_handler
|
|
|
17
17
|
from simtools.model.telescope_model import TelescopeModel
|
|
18
18
|
from simtools.utils import names
|
|
19
19
|
from simtools.version import sort_versions
|
|
20
|
-
from simtools.visualization import plot_pixels, plot_tables
|
|
20
|
+
from simtools.visualization import plot_mirrors, plot_pixels, plot_tables
|
|
21
21
|
|
|
22
22
|
logger = logging.getLogger()
|
|
23
23
|
MARKDOWN_LINK_RE = re.compile(r"\[([^\]]+)\]\(([^)]+)\)")
|
|
@@ -26,11 +26,10 @@ MARKDOWN_LINK_RE = re.compile(r"\[([^\]]+)\]\(([^)]+)\)")
|
|
|
26
26
|
class ReadParameters:
|
|
27
27
|
"""Read and manage model parameter data for report generation."""
|
|
28
28
|
|
|
29
|
-
def __init__(self,
|
|
29
|
+
def __init__(self, args, output_path):
|
|
30
30
|
"""Initialise class."""
|
|
31
31
|
self._logger = logging.getLogger(__name__)
|
|
32
|
-
self.db = db_handler.DatabaseHandler(
|
|
33
|
-
self.db_config = db_config
|
|
32
|
+
self.db = db_handler.DatabaseHandler()
|
|
34
33
|
self.array_element = args.get("telescope", None)
|
|
35
34
|
self.site = args.get("site", None)
|
|
36
35
|
self.model_version = args.get("model_version", None)
|
|
@@ -72,6 +71,12 @@ class ReadParameters:
|
|
|
72
71
|
|
|
73
72
|
if parameter == "camera_config_file":
|
|
74
73
|
plot_names = self._plot_camera_config(parameter, parameter_version, input_file, outpath)
|
|
74
|
+
elif parameter in (
|
|
75
|
+
"mirror_list",
|
|
76
|
+
"primary_mirror_segmentation",
|
|
77
|
+
"secondary_mirror_segmentation",
|
|
78
|
+
):
|
|
79
|
+
plot_names = self._plot_mirror_config(parameter, parameter_version, input_file, outpath)
|
|
75
80
|
elif parameter_version:
|
|
76
81
|
plot_names = self._plot_parameter_tables(
|
|
77
82
|
parameter,
|
|
@@ -103,7 +108,6 @@ class ReadParameters:
|
|
|
103
108
|
plot_pixels.plot(
|
|
104
109
|
config=plot_config,
|
|
105
110
|
output_file=Path(f"{outpath}/{plot_name}"),
|
|
106
|
-
db_config=self.db_config,
|
|
107
111
|
)
|
|
108
112
|
plot_names.append(plot_name)
|
|
109
113
|
else:
|
|
@@ -115,6 +119,38 @@ class ReadParameters:
|
|
|
115
119
|
|
|
116
120
|
return plot_names
|
|
117
121
|
|
|
122
|
+
def _plot_mirror_config(self, parameter, parameter_version, input_file, outpath):
|
|
123
|
+
"""Generate plots for mirror configuration files."""
|
|
124
|
+
if not parameter_version:
|
|
125
|
+
return []
|
|
126
|
+
|
|
127
|
+
plot_names = []
|
|
128
|
+
plot_name = input_file.stem.replace(".", "-")
|
|
129
|
+
plot_path = Path(f"{outpath}/{plot_name}").with_suffix(".png")
|
|
130
|
+
|
|
131
|
+
if not plot_path.exists():
|
|
132
|
+
plot_config = {
|
|
133
|
+
"parameter": parameter,
|
|
134
|
+
"telescope": self.array_element,
|
|
135
|
+
"parameter_version": parameter_version,
|
|
136
|
+
"site": self.site,
|
|
137
|
+
"model_version": self.model_version,
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
plot_mirrors.plot(
|
|
141
|
+
config=plot_config,
|
|
142
|
+
output_file=Path(f"{outpath}/{plot_name}"),
|
|
143
|
+
)
|
|
144
|
+
plot_names.append(plot_name)
|
|
145
|
+
else:
|
|
146
|
+
logger.info(
|
|
147
|
+
"Mirror configuration file plot already exists: %s",
|
|
148
|
+
plot_path,
|
|
149
|
+
)
|
|
150
|
+
plot_names.append(plot_name)
|
|
151
|
+
|
|
152
|
+
return plot_names
|
|
153
|
+
|
|
118
154
|
def _plot_parameter_tables(self, parameter, parameter_version, outpath):
|
|
119
155
|
"""Generate plots for parameter tables."""
|
|
120
156
|
tel = self._get_telescope_identifier()
|
|
@@ -126,7 +162,6 @@ class ReadParameters:
|
|
|
126
162
|
telescope=tel,
|
|
127
163
|
output_path=outpath,
|
|
128
164
|
plot_type="all",
|
|
129
|
-
db_config=self.db_config,
|
|
130
165
|
)
|
|
131
166
|
|
|
132
167
|
if not config_data:
|
|
@@ -141,7 +176,6 @@ class ReadParameters:
|
|
|
141
176
|
plot_tables.plot(
|
|
142
177
|
config=plot_config,
|
|
143
178
|
output_file=image_output_file,
|
|
144
|
-
db_config=self.db_config,
|
|
145
179
|
)
|
|
146
180
|
plt.close("all")
|
|
147
181
|
|
|
@@ -175,7 +209,7 @@ class ReadParameters:
|
|
|
175
209
|
markdown_output_file = output_data_path / output_file_name
|
|
176
210
|
|
|
177
211
|
if not markdown_output_file.exists():
|
|
178
|
-
outpath =
|
|
212
|
+
outpath = io_handler.IOHandler().get_output_directory("_images")
|
|
179
213
|
outpath.mkdir(parents=True, exist_ok=True)
|
|
180
214
|
|
|
181
215
|
plot_names = self._generate_plots(parameter, parameter_version, input_file, outpath)
|
|
@@ -543,7 +577,6 @@ class ReadParameters:
|
|
|
543
577
|
telescope_name=self.array_element,
|
|
544
578
|
model_version=self.model_version,
|
|
545
579
|
label="reports",
|
|
546
|
-
db_config=self.db_config,
|
|
547
580
|
ignore_software_version=True,
|
|
548
581
|
)
|
|
549
582
|
|
|
@@ -648,7 +681,7 @@ class ReadParameters:
|
|
|
648
681
|
|
|
649
682
|
def _write_file_flag_section(self, file, parameter, comparison_data):
|
|
650
683
|
"""Write image/plot references when parameter entries include files."""
|
|
651
|
-
outpath =
|
|
684
|
+
outpath = io_handler.IOHandler().get_output_directory("_images")
|
|
652
685
|
latest_parameter_version = max(
|
|
653
686
|
comparison_data.get(parameter),
|
|
654
687
|
key=lambda x: tuple(map(int, x["parameter_version"].split("."))),
|
|
@@ -664,13 +697,25 @@ class ReadParameters:
|
|
|
664
697
|
|
|
665
698
|
file.write("The latest parameter version is plotted below.\n\n")
|
|
666
699
|
|
|
667
|
-
if parameter
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
700
|
+
if parameter in (
|
|
701
|
+
"camera_config_file",
|
|
702
|
+
"mirror_list",
|
|
703
|
+
"primary_mirror_segmentation",
|
|
704
|
+
"secondary_mirror_segmentation",
|
|
705
|
+
):
|
|
706
|
+
self._write_file_based_plot(
|
|
707
|
+
file, parameter, comparison_data, latest_model_version, outpath
|
|
708
|
+
)
|
|
671
709
|
return
|
|
672
710
|
|
|
673
|
-
|
|
711
|
+
plot_name = f"{parameter}_{latest_parameter_version}_{self.site}_{tel}"
|
|
712
|
+
image_path = outpath / f"{plot_name}.png"
|
|
713
|
+
file.write(f"})")
|
|
714
|
+
|
|
715
|
+
def _write_file_based_plot(
|
|
716
|
+
self, file, parameter, comparison_data, latest_model_version, outpath
|
|
717
|
+
):
|
|
718
|
+
"""Write plot reference for file-based parameters."""
|
|
674
719
|
latest_value = None
|
|
675
720
|
for item in comparison_data.get(parameter):
|
|
676
721
|
if latest_model_version in item["model_version"].split(", "):
|
|
@@ -686,7 +731,16 @@ class ReadParameters:
|
|
|
686
731
|
|
|
687
732
|
filename_png = Path(match.group(1)).with_suffix(".png").name
|
|
688
733
|
image_path = outpath / filename_png
|
|
689
|
-
|
|
734
|
+
|
|
735
|
+
plot_descriptions = {
|
|
736
|
+
"camera_config_file": "Camera configuration plot",
|
|
737
|
+
"mirror_list": "Mirror panel layout",
|
|
738
|
+
"primary_mirror_segmentation": "Primary mirror segmentation",
|
|
739
|
+
"secondary_mirror_segmentation": "Secondary mirror segmentation",
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
description = plot_descriptions.get(parameter, "Parameter plot")
|
|
743
|
+
file.write(f"})")
|
|
690
744
|
|
|
691
745
|
def _write_array_layouts_section(self, file, layouts):
|
|
692
746
|
"""Write the array layouts section of the report."""
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import stat
|
|
5
|
-
from pathlib import Path
|
|
6
5
|
|
|
6
|
+
from simtools import settings
|
|
7
7
|
from simtools.io import io_handler
|
|
8
8
|
from simtools.runners.runner_services import RunnerServices
|
|
9
9
|
|
|
@@ -26,23 +26,23 @@ class CorsikaRunner:
|
|
|
26
26
|
----------
|
|
27
27
|
corsika_config_data: CorsikaConfig
|
|
28
28
|
CORSIKA configuration.
|
|
29
|
-
simtel_path: str or Path
|
|
30
|
-
Location of source of the sim_telarray/CORSIKA package.
|
|
31
29
|
label: str
|
|
32
30
|
Instance label.
|
|
33
31
|
keep_seeds: bool
|
|
34
32
|
Use seeds based on run number and primary particle. If False, use sim_telarray seeds.
|
|
35
33
|
use_multipipe: bool
|
|
36
34
|
Use multipipe to run CORSIKA and sim_telarray.
|
|
35
|
+
curved_atmosphere_min_zenith_angle: Quantity
|
|
36
|
+
Minimum zenith angle for which to use the curved-atmosphere CORSIKA binary.
|
|
37
37
|
"""
|
|
38
38
|
|
|
39
39
|
def __init__(
|
|
40
40
|
self,
|
|
41
41
|
corsika_config,
|
|
42
|
-
simtel_path,
|
|
43
42
|
label=None,
|
|
44
43
|
keep_seeds=False,
|
|
45
44
|
use_multipipe=False,
|
|
45
|
+
curved_atmosphere_min_zenith_angle=None,
|
|
46
46
|
):
|
|
47
47
|
"""Initialize CorsikaRunner."""
|
|
48
48
|
self._logger = logging.getLogger(__name__)
|
|
@@ -52,8 +52,8 @@ class CorsikaRunner:
|
|
|
52
52
|
self.corsika_config = corsika_config
|
|
53
53
|
self._keep_seeds = keep_seeds
|
|
54
54
|
self._use_multipipe = use_multipipe
|
|
55
|
+
self.curved_atmosphere_min_zenith_angle = curved_atmosphere_min_zenith_angle
|
|
55
56
|
|
|
56
|
-
self._simtel_path = Path(simtel_path)
|
|
57
57
|
self.io_handler = io_handler.IOHandler()
|
|
58
58
|
|
|
59
59
|
self.runner_service = RunnerServices(corsika_config, label)
|
|
@@ -63,7 +63,7 @@ class CorsikaRunner:
|
|
|
63
63
|
self, run_number=None, extra_commands=None, input_file=None, use_pfp=True
|
|
64
64
|
):
|
|
65
65
|
"""
|
|
66
|
-
|
|
66
|
+
Prepare and write CORSIKA run script.
|
|
67
67
|
|
|
68
68
|
Parameters
|
|
69
69
|
----------
|
|
@@ -174,7 +174,7 @@ class CorsikaRunner:
|
|
|
174
174
|
str
|
|
175
175
|
pfp command.
|
|
176
176
|
"""
|
|
177
|
-
cmd =
|
|
177
|
+
cmd = settings.config.sim_telarray_path / "bin/pfp"
|
|
178
178
|
cmd = str(cmd) + f" -V -DWITHOUT_MULTIPIPE - < {corsika_input_file}"
|
|
179
179
|
cmd += f" > {input_tmp_file} || exit\n"
|
|
180
180
|
return cmd
|
|
@@ -183,7 +183,7 @@ class CorsikaRunner:
|
|
|
183
183
|
"""
|
|
184
184
|
Get autoinputs command.
|
|
185
185
|
|
|
186
|
-
corsika_autoinputs is a tool to generate random and user/host dependent
|
|
186
|
+
corsika_autoinputs is a tool to generate random seeds and user/host dependent
|
|
187
187
|
parameters for CORSIKA configuration.
|
|
188
188
|
|
|
189
189
|
Parameters
|
|
@@ -198,13 +198,18 @@ class CorsikaRunner:
|
|
|
198
198
|
str
|
|
199
199
|
autoinputs command.
|
|
200
200
|
"""
|
|
201
|
-
|
|
201
|
+
if self.corsika_config.use_curved_atmosphere:
|
|
202
|
+
corsika_bin_path = settings.config.corsika_exe_curved
|
|
203
|
+
self._logger.debug("Using curved-atmosphere CORSIKA binary.")
|
|
204
|
+
else:
|
|
205
|
+
corsika_bin_path = settings.config.corsika_exe
|
|
206
|
+
self._logger.debug("Using flat-atmosphere CORSIKA binary.")
|
|
202
207
|
|
|
203
208
|
log_file = self.get_file_name(file_type="log", run_number=run_number)
|
|
204
209
|
if self._use_multipipe:
|
|
205
210
|
log_file = log_file.with_name(f"multipipe_{log_file.name}")
|
|
206
211
|
|
|
207
|
-
cmd =
|
|
212
|
+
cmd = settings.config.sim_telarray_path.joinpath("bin/corsika_autoinputs")
|
|
208
213
|
cmd = str(cmd) + f" --run {corsika_bin_path}"
|
|
209
214
|
cmd += f" -R {run_number}"
|
|
210
215
|
cmd += ' -p "$CORSIKA_DATA"'
|
|
@@ -5,6 +5,7 @@ import stat
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
import simtools.utils.general as gen
|
|
8
|
+
from simtools import settings
|
|
8
9
|
from simtools.runners.corsika_runner import CorsikaRunner
|
|
9
10
|
from simtools.simtel.simulator_array import SimulatorArray
|
|
10
11
|
|
|
@@ -21,8 +22,6 @@ class CorsikaSimtelRunner:
|
|
|
21
22
|
corsika_config : CorsikaConfig or list of CorsikaConfig
|
|
22
23
|
A list of "CorsikaConfig" instances which
|
|
23
24
|
contain the CORSIKA configuration parameters.
|
|
24
|
-
simtel_path : str or Path
|
|
25
|
-
Location of the sim_telarray package.
|
|
26
25
|
label : str
|
|
27
26
|
Label.
|
|
28
27
|
keep_seeds : bool
|
|
@@ -38,20 +37,19 @@ class CorsikaSimtelRunner:
|
|
|
38
37
|
def __init__(
|
|
39
38
|
self,
|
|
40
39
|
corsika_config,
|
|
41
|
-
simtel_path,
|
|
42
40
|
label=None,
|
|
43
41
|
keep_seeds=False,
|
|
44
42
|
use_multipipe=False,
|
|
45
43
|
sim_telarray_seeds=None,
|
|
46
44
|
sequential=False,
|
|
47
45
|
calibration_config=None,
|
|
46
|
+
curved_atmosphere_min_zenith_angle=None,
|
|
48
47
|
):
|
|
49
48
|
self._logger = logging.getLogger(__name__)
|
|
50
49
|
self.corsika_config = gen.ensure_iterable(corsika_config)
|
|
51
50
|
# the base corsika config is the one used to define the CORSIKA specific parameters.
|
|
52
51
|
# The others are used for the array configurations.
|
|
53
52
|
self.base_corsika_config = self.corsika_config[0]
|
|
54
|
-
self._simtel_path = simtel_path
|
|
55
53
|
self.sim_telarray_seeds = sim_telarray_seeds
|
|
56
54
|
self.label = label
|
|
57
55
|
self.sequential = "--sequential" if sequential else ""
|
|
@@ -59,10 +57,10 @@ class CorsikaSimtelRunner:
|
|
|
59
57
|
self.base_corsika_config.set_output_file_and_directory(use_multipipe)
|
|
60
58
|
self.corsika_runner = CorsikaRunner(
|
|
61
59
|
corsika_config=self.base_corsika_config,
|
|
62
|
-
simtel_path=simtel_path,
|
|
63
60
|
label=label,
|
|
64
61
|
keep_seeds=keep_seeds,
|
|
65
62
|
use_multipipe=use_multipipe,
|
|
63
|
+
curved_atmosphere_min_zenith_angle=curved_atmosphere_min_zenith_angle,
|
|
66
64
|
)
|
|
67
65
|
# The simulator array should be defined for every CORSIKA configuration
|
|
68
66
|
# because it allows to define multiple sim_telarray instances
|
|
@@ -71,7 +69,6 @@ class CorsikaSimtelRunner:
|
|
|
71
69
|
self.simulator_array.append(
|
|
72
70
|
SimulatorArray(
|
|
73
71
|
corsika_config=_corsika_config,
|
|
74
|
-
simtel_path=simtel_path,
|
|
75
72
|
label=label,
|
|
76
73
|
use_multipipe=use_multipipe,
|
|
77
74
|
sim_telarray_seeds=sim_telarray_seeds,
|
|
@@ -169,8 +166,8 @@ class CorsikaSimtelRunner:
|
|
|
169
166
|
"run_cta_multipipe"
|
|
170
167
|
)
|
|
171
168
|
with open(multipipe_script, "w", encoding="utf-8") as file:
|
|
172
|
-
multipipe_command =
|
|
173
|
-
f"
|
|
169
|
+
multipipe_command = settings.config.sim_telarray_path.joinpath(
|
|
170
|
+
f"bin/multipipe_corsika -c {multipipe_file} {self.sequential} "
|
|
174
171
|
"|| echo 'Fan-out failed'"
|
|
175
172
|
)
|
|
176
173
|
file.write(f"{multipipe_command}")
|
|
@@ -218,3 +215,7 @@ class CorsikaSimtelRunner:
|
|
|
218
215
|
else self.simulator_array[model_version_index]
|
|
219
216
|
)
|
|
220
217
|
return runner.get_file_name(file_type=file_type, run_number=run_number, mode=mode)
|
|
218
|
+
|
|
219
|
+
def get_resources(self, run_number=None):
|
|
220
|
+
"""Return computing resources used."""
|
|
221
|
+
return self.corsika_runner.get_resources(run_number)
|
|
@@ -28,7 +28,7 @@ class RunnerServices:
|
|
|
28
28
|
self.corsika_config = corsika_config
|
|
29
29
|
self.directory = {}
|
|
30
30
|
|
|
31
|
-
def _get_info_for_file_name(self, run_number):
|
|
31
|
+
def _get_info_for_file_name(self, run_number, calibration_run_mode=None):
|
|
32
32
|
"""
|
|
33
33
|
Return dictionary for building names for simulation output files.
|
|
34
34
|
|
|
@@ -36,6 +36,8 @@ class RunnerServices:
|
|
|
36
36
|
----------
|
|
37
37
|
run_number : int
|
|
38
38
|
Run number.
|
|
39
|
+
calibration_run_mode: str
|
|
40
|
+
Calibration run mode.
|
|
39
41
|
|
|
40
42
|
Returns
|
|
41
43
|
-------
|
|
@@ -43,9 +45,12 @@ class RunnerServices:
|
|
|
43
45
|
Dictionary with the keys or building the file names for simulation output files.
|
|
44
46
|
"""
|
|
45
47
|
_vc_high = self.corsika_config.get_config_parameter("VIEWCONE")[1]
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
if calibration_run_mode is not None and calibration_run_mode != "":
|
|
49
|
+
primary_name = calibration_run_mode
|
|
50
|
+
else:
|
|
51
|
+
primary_name = self.corsika_config.primary
|
|
52
|
+
if primary_name == "gamma" and _vc_high > 0:
|
|
53
|
+
primary_name = "gamma_diffuse"
|
|
49
54
|
return {
|
|
50
55
|
"run_number": self.corsika_config.validate_run_number(run_number),
|
|
51
56
|
"primary": primary_name,
|
|
@@ -119,7 +124,7 @@ class RunnerServices:
|
|
|
119
124
|
_logger.debug(f"Checking if {run_sub_file} exists")
|
|
120
125
|
return Path(run_sub_file).is_file()
|
|
121
126
|
|
|
122
|
-
def _get_file_basename(self, run_number):
|
|
127
|
+
def _get_file_basename(self, run_number, calibration_run_mode):
|
|
123
128
|
"""
|
|
124
129
|
Get the base name for the simulation files.
|
|
125
130
|
|
|
@@ -127,13 +132,15 @@ class RunnerServices:
|
|
|
127
132
|
----------
|
|
128
133
|
run_number: int
|
|
129
134
|
Run number.
|
|
135
|
+
calibration_run_mode: str
|
|
136
|
+
Calibration run mode.
|
|
130
137
|
|
|
131
138
|
Returns
|
|
132
139
|
-------
|
|
133
140
|
str
|
|
134
141
|
Base name for the simulation files.
|
|
135
142
|
"""
|
|
136
|
-
info_for_file_name = self._get_info_for_file_name(run_number)
|
|
143
|
+
info_for_file_name = self._get_info_for_file_name(run_number, calibration_run_mode)
|
|
137
144
|
file_label = f"_{info_for_file_name['label']}" if info_for_file_name.get("label") else ""
|
|
138
145
|
zenith = self.corsika_config.get_config_parameter("THETAP")[0]
|
|
139
146
|
azimuth = self.corsika_config.azimuth_angle
|
|
@@ -232,6 +239,7 @@ class RunnerServices:
|
|
|
232
239
|
file_type,
|
|
233
240
|
run_number=None,
|
|
234
241
|
mode=None,
|
|
242
|
+
calibration_run_mode=None,
|
|
235
243
|
_model_version_index=0,
|
|
236
244
|
): # pylint: disable=unused-argument
|
|
237
245
|
"""
|
|
@@ -245,6 +253,8 @@ class RunnerServices:
|
|
|
245
253
|
Run number.
|
|
246
254
|
mode: str
|
|
247
255
|
out or err (optional, relevant only for sub_log).
|
|
256
|
+
calibration_run_mode: str
|
|
257
|
+
Calibration run mode.
|
|
248
258
|
model_version_index: int
|
|
249
259
|
Index of the model version.
|
|
250
260
|
This is not used here, but in other implementations of this function is
|
|
@@ -261,7 +271,7 @@ class RunnerServices:
|
|
|
261
271
|
ValueError
|
|
262
272
|
If file_type is unknown.
|
|
263
273
|
"""
|
|
264
|
-
file_name = self._get_file_basename(run_number)
|
|
274
|
+
file_name = self._get_file_basename(run_number, calibration_run_mode)
|
|
265
275
|
|
|
266
276
|
if file_type in ["log", "histogram", "corsika_log"]:
|
|
267
277
|
return self._get_log_file_path(file_type, file_name)
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"""Base class for running sim_telarray simulations."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
import stat
|
|
5
4
|
import subprocess
|
|
6
|
-
from pathlib import Path
|
|
7
5
|
|
|
8
6
|
import simtools.utils.general as gen
|
|
9
7
|
from simtools.runners.runner_services import RunnerServices
|
|
@@ -26,23 +24,29 @@ class SimtelRunner:
|
|
|
26
24
|
|
|
27
25
|
Parameters
|
|
28
26
|
----------
|
|
29
|
-
simtel_path: str or Path
|
|
30
|
-
Location of sim_telarray installation.
|
|
31
27
|
label: str
|
|
32
28
|
Instance label. Important for output file naming.
|
|
33
29
|
corsika_config: CorsikaConfig
|
|
34
30
|
CORSIKA configuration.
|
|
35
31
|
use_multipipe: bool
|
|
36
32
|
Use multipipe to run CORSIKA and sim_telarray.
|
|
33
|
+
calibration_run_mode: str
|
|
34
|
+
Calibration run mode.
|
|
37
35
|
"""
|
|
38
36
|
|
|
39
|
-
def __init__(
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
label=None,
|
|
40
|
+
corsika_config=None,
|
|
41
|
+
use_multipipe=False,
|
|
42
|
+
calibration_run_mode=None,
|
|
43
|
+
):
|
|
40
44
|
"""Initialize SimtelRunner."""
|
|
41
45
|
self._logger = logging.getLogger(__name__)
|
|
42
46
|
|
|
43
|
-
self._simtel_path = Path(simtel_path)
|
|
44
47
|
self.label = label
|
|
45
48
|
self._base_directory = None
|
|
49
|
+
self.calibration_run_mode = calibration_run_mode
|
|
46
50
|
|
|
47
51
|
self.runs_per_set = 1
|
|
48
52
|
|
|
@@ -51,56 +55,6 @@ class SimtelRunner:
|
|
|
51
55
|
"corsika_sim_telarray" if use_multipipe else "sim_telarray"
|
|
52
56
|
)
|
|
53
57
|
|
|
54
|
-
def __repr__(self):
|
|
55
|
-
"""Return a string representation of the SimtelRunner object."""
|
|
56
|
-
return f"SimtelRunner(label={self.label})\n"
|
|
57
|
-
|
|
58
|
-
def prepare_run_script(self, test=False, input_file=None, run_number=None, extra_commands=None):
|
|
59
|
-
"""
|
|
60
|
-
Build and return the full path of the bash run script containing the sim_telarray command.
|
|
61
|
-
|
|
62
|
-
Parameters
|
|
63
|
-
----------
|
|
64
|
-
test: bool
|
|
65
|
-
Test flag for faster execution.
|
|
66
|
-
input_file: str or Path
|
|
67
|
-
Full path of the input CORSIKA file.
|
|
68
|
-
run_number: int
|
|
69
|
-
Run number.
|
|
70
|
-
extra_commands: str
|
|
71
|
-
Additional commands for running simulations given in config.yml.
|
|
72
|
-
|
|
73
|
-
Returns
|
|
74
|
-
-------
|
|
75
|
-
Path
|
|
76
|
-
Full path of the run script.
|
|
77
|
-
"""
|
|
78
|
-
script_file_path = self.get_file_name(file_type="sub_script", run_number=run_number)
|
|
79
|
-
self._logger.debug(f"Run bash script - {script_file_path}")
|
|
80
|
-
self._logger.debug(f"Extra commands to be added to the run script {extra_commands}")
|
|
81
|
-
|
|
82
|
-
command = self._make_run_command(run_number=run_number, input_file=input_file)
|
|
83
|
-
with script_file_path.open("w", encoding="utf-8") as file:
|
|
84
|
-
file.write("#!/usr/bin/env bash\n\n")
|
|
85
|
-
file.write("set -e\n")
|
|
86
|
-
file.write("set -o pipefail\n")
|
|
87
|
-
file.write("\nSECONDS=0\n")
|
|
88
|
-
|
|
89
|
-
if extra_commands is not None:
|
|
90
|
-
file.write("# Writing extras\n")
|
|
91
|
-
for line in extra_commands:
|
|
92
|
-
file.write(f"{line}\n")
|
|
93
|
-
file.write("# End of extras\n\n")
|
|
94
|
-
|
|
95
|
-
n = 1 if test else self.runs_per_set
|
|
96
|
-
for _ in range(n):
|
|
97
|
-
file.write(f"{command}\n\n")
|
|
98
|
-
|
|
99
|
-
file.write('\necho "RUNTIME: $SECONDS"\n')
|
|
100
|
-
|
|
101
|
-
script_file_path.chmod(script_file_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP)
|
|
102
|
-
return script_file_path
|
|
103
|
-
|
|
104
58
|
def run(self, test=False, input_file=None, run_number=None):
|
|
105
59
|
"""
|
|
106
60
|
Make run command and run sim_telarray.
|
|
@@ -148,8 +102,6 @@ class SimtelRunner:
|
|
|
148
102
|
msg = gen.get_log_excerpt(self._log_file)
|
|
149
103
|
else:
|
|
150
104
|
msg = "Simtel log file does not exist."
|
|
151
|
-
|
|
152
|
-
self._logger.error(msg)
|
|
153
105
|
raise SimtelExecutionError(msg)
|
|
154
106
|
|
|
155
107
|
def _run_simtel_and_check_output(self, command, stdout_file, stderr_file):
|
|
@@ -255,4 +207,5 @@ class SimtelRunner:
|
|
|
255
207
|
run_number=run_number,
|
|
256
208
|
mode=mode,
|
|
257
209
|
_model_version_index=model_version_index,
|
|
210
|
+
calibration_run_mode=self.calibration_run_mode,
|
|
258
211
|
)
|