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
|
@@ -10,9 +10,12 @@ import numpy as np
|
|
|
10
10
|
|
|
11
11
|
import simtools.utils.general as gen
|
|
12
12
|
import simtools.version
|
|
13
|
-
from simtools
|
|
13
|
+
from simtools import dependencies, settings
|
|
14
|
+
from simtools.simtel.pulse_shapes import generate_pulse_from_rise_fall_times
|
|
14
15
|
from simtools.utils import names
|
|
15
16
|
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
16
19
|
|
|
17
20
|
def sim_telarray_random_seeds(seed, number):
|
|
18
21
|
"""
|
|
@@ -53,8 +56,6 @@ class SimtelConfigWriter:
|
|
|
53
56
|
Layout name.
|
|
54
57
|
label: str
|
|
55
58
|
Instance label. Important for output file naming.
|
|
56
|
-
simtel_path: str or Path
|
|
57
|
-
Path to the sim_telarray installation directory.
|
|
58
59
|
"""
|
|
59
60
|
|
|
60
61
|
TAB = " " * 3
|
|
@@ -67,7 +68,6 @@ class SimtelConfigWriter:
|
|
|
67
68
|
telescope_model_name=None,
|
|
68
69
|
telescope_design_model=None,
|
|
69
70
|
label=None,
|
|
70
|
-
simtel_path=None,
|
|
71
71
|
):
|
|
72
72
|
"""Initialize SimtelConfigWriter."""
|
|
73
73
|
self._logger = logging.getLogger(__name__)
|
|
@@ -79,7 +79,6 @@ class SimtelConfigWriter:
|
|
|
79
79
|
self._layout_name = layout_name
|
|
80
80
|
self._telescope_model_name = telescope_model_name
|
|
81
81
|
self._telescope_design_model = telescope_design_model
|
|
82
|
-
self._simtel_path = simtel_path
|
|
83
82
|
|
|
84
83
|
def write_telescope_config_file(
|
|
85
84
|
self, config_file_path, parameters, telescope_name=None, telescope_design_model=None
|
|
@@ -121,6 +120,128 @@ class SimtelConfigWriter:
|
|
|
121
120
|
):
|
|
122
121
|
file.write(f"{meta}\n")
|
|
123
122
|
|
|
123
|
+
@staticmethod
|
|
124
|
+
def write_light_pulse_table_gauss_exp_conv(
|
|
125
|
+
file_path,
|
|
126
|
+
width_ns,
|
|
127
|
+
exp_decay_ns,
|
|
128
|
+
fadc_sum_bins,
|
|
129
|
+
dt_ns=0.1,
|
|
130
|
+
rise_range=(0.1, 0.9),
|
|
131
|
+
fall_range=(0.9, 0.1),
|
|
132
|
+
time_margin_ns=10.0,
|
|
133
|
+
):
|
|
134
|
+
"""Write a pulse table for a Gaussian convolved with a causal exponential.
|
|
135
|
+
|
|
136
|
+
Parameters
|
|
137
|
+
----------
|
|
138
|
+
file_path : str or pathlib.Path
|
|
139
|
+
Destination path of the ASCII pulse table to write. Parent directory must exist.
|
|
140
|
+
width_ns : float
|
|
141
|
+
Target rise time in ns between the fractional levels defined by ``rise_range``.
|
|
142
|
+
exp_decay_ns : float
|
|
143
|
+
Target fall time in ns between the fractional levels defined by ``fall_range``.
|
|
144
|
+
fadc_sum_bins : int
|
|
145
|
+
Length of the FADC integration window (treated as ns here) used to derive
|
|
146
|
+
the internal time sampling window of the solver as [-(margin), bins + margin].
|
|
147
|
+
dt_ns : float, optional
|
|
148
|
+
Time sampling step in ns for the generated pulse table.
|
|
149
|
+
rise_range : tuple[float, float], optional
|
|
150
|
+
Fractional amplitude bounds (low, high) for rise-time definition.
|
|
151
|
+
fall_range : tuple[float, float], optional
|
|
152
|
+
Fractional amplitude bounds (high, low) for fall-time definition.
|
|
153
|
+
time_margin_ns : float, optional
|
|
154
|
+
Margin in ns to add to both ends of the FADC window when ``fadc_sum_bins`` is given.
|
|
155
|
+
|
|
156
|
+
Returns
|
|
157
|
+
-------
|
|
158
|
+
pathlib.Path
|
|
159
|
+
The path to the created pulse table file.
|
|
160
|
+
|
|
161
|
+
Notes
|
|
162
|
+
-----
|
|
163
|
+
The underlying model is a Gaussian convolved with a causal exponential. The model
|
|
164
|
+
parameters (sigma, tau) are solved such that the normalized pulse matches the requested
|
|
165
|
+
rise and fall times. The pulse is normalized to a peak amplitude of 1.
|
|
166
|
+
"""
|
|
167
|
+
if width_ns is None or exp_decay_ns is None:
|
|
168
|
+
raise ValueError("width_ns (rise 10-90) and exp_decay_ns (fall 90-10) are required")
|
|
169
|
+
logger.info(
|
|
170
|
+
"Generating pulse-shape table with "
|
|
171
|
+
f"rise{int(rise_range[0] * 100)}-{int(rise_range[1] * 100)}={width_ns} ns, "
|
|
172
|
+
f"fall{int(fall_range[0] * 100)}-{int(fall_range[1] * 100)}={exp_decay_ns} ns, "
|
|
173
|
+
f"dt={dt_ns} ns"
|
|
174
|
+
)
|
|
175
|
+
width = float(fadc_sum_bins)
|
|
176
|
+
t_start_ns = -abs(time_margin_ns + width)
|
|
177
|
+
t_stop_ns = +abs(time_margin_ns + width)
|
|
178
|
+
t, y = generate_pulse_from_rise_fall_times(
|
|
179
|
+
width_ns,
|
|
180
|
+
exp_decay_ns,
|
|
181
|
+
dt_ns=dt_ns,
|
|
182
|
+
rise_range=rise_range,
|
|
183
|
+
fall_range=fall_range,
|
|
184
|
+
t_start_ns=t_start_ns,
|
|
185
|
+
t_stop_ns=t_stop_ns,
|
|
186
|
+
center_on_peak=True,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return SimtelConfigWriter._write_ascii_pulse_table(file_path, t, y)
|
|
190
|
+
|
|
191
|
+
@staticmethod
|
|
192
|
+
def write_angular_distribution_table_lambertian(
|
|
193
|
+
file_path,
|
|
194
|
+
max_angle_deg,
|
|
195
|
+
n_samples=100,
|
|
196
|
+
):
|
|
197
|
+
"""Write a Lambertian angular distribution table (I(t) ~ cos(t)).
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
file_path : str or pathlib.Path
|
|
202
|
+
Destination path of the ASCII table to write. Parent directory must exist.
|
|
203
|
+
max_angle_deg : float
|
|
204
|
+
Maximum angle (deg) for the distribution sampling range [0, max_angle_deg].
|
|
205
|
+
n_samples : int, optional
|
|
206
|
+
Number of samples (including end point) from 0 to max_angle_deg. Default 100.
|
|
207
|
+
|
|
208
|
+
Returns
|
|
209
|
+
-------
|
|
210
|
+
pathlib.Path
|
|
211
|
+
Path to created angular distribution table.
|
|
212
|
+
"""
|
|
213
|
+
logger.info(
|
|
214
|
+
f"Generating Lambertian angular distribution table up to {max_angle_deg} deg "
|
|
215
|
+
f"with {n_samples} samples"
|
|
216
|
+
)
|
|
217
|
+
angles = np.linspace(0.0, float(max_angle_deg), int(n_samples), dtype=float)
|
|
218
|
+
intensities = np.cos(np.deg2rad(angles))
|
|
219
|
+
intensities[intensities < 0] = 0.0
|
|
220
|
+
if intensities.max() > 0:
|
|
221
|
+
intensities /= intensities.max()
|
|
222
|
+
|
|
223
|
+
return SimtelConfigWriter._write_ascii_angle_distribution_table(
|
|
224
|
+
file_path, angles, intensities
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
@staticmethod
|
|
228
|
+
def _write_ascii_pulse_table(file_path, t, y):
|
|
229
|
+
"""Write two-column ASCII pulse table."""
|
|
230
|
+
with open(file_path, "w", encoding="utf-8") as fh:
|
|
231
|
+
fh.write("# time[ns] amplitude\n")
|
|
232
|
+
for ti, yi in zip(t, y):
|
|
233
|
+
fh.write(f"{ti:.6f} {yi:.8f}\n")
|
|
234
|
+
return Path(file_path)
|
|
235
|
+
|
|
236
|
+
@staticmethod
|
|
237
|
+
def _write_ascii_angle_distribution_table(file_path, angles, intensities):
|
|
238
|
+
"""Write two-column ASCII angular distribution table."""
|
|
239
|
+
with open(file_path, "w", encoding="utf-8") as fh:
|
|
240
|
+
fh.write("# angle[deg] relative_intensity\n")
|
|
241
|
+
for a, i in zip(angles, intensities):
|
|
242
|
+
fh.write(f"{a:.6f} {i:.8f}\n")
|
|
243
|
+
return Path(file_path)
|
|
244
|
+
|
|
124
245
|
def _get_parameters_for_sim_telarray(self, parameters, config_file_path):
|
|
125
246
|
"""
|
|
126
247
|
Convert parameter dictionary to sim_telarray configuration file format.
|
|
@@ -176,28 +297,24 @@ class SimtelConfigWriter:
|
|
|
176
297
|
Model parameters in sim_telarray format including flasher parameters.
|
|
177
298
|
|
|
178
299
|
"""
|
|
179
|
-
if "flasher_pulse_shape" not in parameters
|
|
300
|
+
if "flasher_pulse_shape" not in parameters:
|
|
180
301
|
return simtel_par
|
|
181
302
|
|
|
182
303
|
mapping = {
|
|
183
304
|
"gauss": "laser_pulse_sigtime",
|
|
184
305
|
"tophat": "laser_pulse_twidth",
|
|
306
|
+
"gauss-exponential": "laser_pulse_sigtime",
|
|
185
307
|
}
|
|
186
308
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
)
|
|
192
|
-
else:
|
|
193
|
-
simtel_par["laser_pulse_exptime"] = 0.0
|
|
309
|
+
shape_value = parameters.get("flasher_pulse_shape", {}).get("value")
|
|
310
|
+
shape = shape_value[0].lower()
|
|
311
|
+
width = shape_value[1]
|
|
312
|
+
exp_decay = shape_value[2]
|
|
194
313
|
|
|
195
|
-
|
|
314
|
+
simtel_par["laser_pulse_exptime"] = exp_decay if ("exponential" in shape) else 0.0
|
|
196
315
|
|
|
197
316
|
simtel_par.update(dict.fromkeys(mapping.values(), 0.0))
|
|
198
|
-
if shape
|
|
199
|
-
simtel_par["laser_pulse_sigtime"] = width
|
|
200
|
-
elif shape in mapping:
|
|
317
|
+
if shape in mapping:
|
|
201
318
|
simtel_par[mapping[shape]] = width
|
|
202
319
|
else:
|
|
203
320
|
self._logger.warning(f"Flasher pulse shape '{shape}' without width definition")
|
|
@@ -221,7 +338,7 @@ class SimtelConfigWriter:
|
|
|
221
338
|
value = "none" if value is None else value # simtel requires 'none'
|
|
222
339
|
if isinstance(value, bool):
|
|
223
340
|
value = 1 if value else 0
|
|
224
|
-
elif isinstance(value,
|
|
341
|
+
elif isinstance(value, list | np.ndarray):
|
|
225
342
|
value = gen.convert_list_to_string(value, shorten_list=True)
|
|
226
343
|
return value
|
|
227
344
|
|
|
@@ -495,17 +612,24 @@ class SimtelConfigWriter:
|
|
|
495
612
|
"simtools_model_production_version": self._model_version,
|
|
496
613
|
}
|
|
497
614
|
try:
|
|
498
|
-
build_opts =
|
|
499
|
-
Path(self._simtel_path) / "build_opts.yml"
|
|
500
|
-
)
|
|
615
|
+
build_opts = dependencies.get_build_options()
|
|
501
616
|
for key, value in build_opts.items():
|
|
502
617
|
meta_items[f"simtools_{key}"] = value
|
|
503
618
|
except (FileNotFoundError, TypeError):
|
|
504
619
|
pass # don't expect build_opts.yml to be present on all systems
|
|
505
620
|
|
|
621
|
+
# CORSIKA executable without _flat/_curved suffix (do not know here if curved or flat)
|
|
622
|
+
try:
|
|
623
|
+
meta_items["simtools_corsika_exec"] = settings.config.corsika_exe.name.removesuffix(
|
|
624
|
+
"_flat"
|
|
625
|
+
)
|
|
626
|
+
except AttributeError as exc:
|
|
627
|
+
raise AttributeError("CORSIKA executable path is not set in settings.") from exc
|
|
628
|
+
|
|
506
629
|
file.write(f"{self.TAB}% Simtools parameters\n")
|
|
507
630
|
for key, value in meta_items.items():
|
|
508
|
-
|
|
631
|
+
if not isinstance(value, list):
|
|
632
|
+
file.write(f"{self.TAB}metaparam global set {key} = {value}\n")
|
|
509
633
|
|
|
510
634
|
def _write_site_parameters(
|
|
511
635
|
self, file, site_parameters, model_path, telescope_model, additional_metadata=None
|
|
@@ -154,14 +154,16 @@ def _data_columns_mirror_reflectivity(n_columns, n_dim):
|
|
|
154
154
|
{"name": "wavelength", "description": "Wavelength", "unit": "nm"},
|
|
155
155
|
]
|
|
156
156
|
if n_dim:
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
_columns.extend(
|
|
158
|
+
[
|
|
159
159
|
{
|
|
160
160
|
"name": f"reflectivity_{angle}deg",
|
|
161
161
|
"description": f"Mirror reflectivity at {angle} deg",
|
|
162
162
|
"unit": None,
|
|
163
|
-
}
|
|
164
|
-
|
|
163
|
+
}
|
|
164
|
+
for angle in n_dim
|
|
165
|
+
]
|
|
166
|
+
)
|
|
165
167
|
else:
|
|
166
168
|
_columns.append(
|
|
167
169
|
{
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""Simulation runner for array simulations."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import stat
|
|
4
5
|
|
|
6
|
+
from simtools import settings
|
|
5
7
|
from simtools.io import io_handler
|
|
6
8
|
from simtools.runners.simtel_runner import InvalidOutputFileError, SimtelRunner
|
|
7
9
|
from simtools.utils.general import clear_default_sim_telarray_cfg_directories
|
|
@@ -15,8 +17,6 @@ class SimulatorArray(SimtelRunner):
|
|
|
15
17
|
----------
|
|
16
18
|
corsika_config_data: CorsikaConfig
|
|
17
19
|
CORSIKA configuration.
|
|
18
|
-
simtel_path: str or Path
|
|
19
|
-
Location of source of the sim_telarray/CORSIKA package.
|
|
20
20
|
label: str
|
|
21
21
|
Instance label.
|
|
22
22
|
use_multipipe: bool
|
|
@@ -28,7 +28,6 @@ class SimulatorArray(SimtelRunner):
|
|
|
28
28
|
def __init__(
|
|
29
29
|
self,
|
|
30
30
|
corsika_config,
|
|
31
|
-
simtel_path,
|
|
32
31
|
label=None,
|
|
33
32
|
use_multipipe=False,
|
|
34
33
|
sim_telarray_seeds=None,
|
|
@@ -39,9 +38,9 @@ class SimulatorArray(SimtelRunner):
|
|
|
39
38
|
self._logger.debug("Init SimulatorArray")
|
|
40
39
|
super().__init__(
|
|
41
40
|
label=label,
|
|
42
|
-
simtel_path=simtel_path,
|
|
43
41
|
corsika_config=corsika_config,
|
|
44
42
|
use_multipipe=use_multipipe,
|
|
43
|
+
calibration_run_mode=calibration_config.get("run_mode") if calibration_config else None,
|
|
45
44
|
)
|
|
46
45
|
|
|
47
46
|
self.sim_telarray_seeds = sim_telarray_seeds
|
|
@@ -50,6 +49,52 @@ class SimulatorArray(SimtelRunner):
|
|
|
50
49
|
self.io_handler = io_handler.IOHandler()
|
|
51
50
|
self._log_file = None
|
|
52
51
|
|
|
52
|
+
def prepare_run_script(self, test=False, input_file=None, run_number=None, extra_commands=None):
|
|
53
|
+
"""
|
|
54
|
+
Build and return the full path of the bash run script containing the sim_telarray command.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
test: bool
|
|
59
|
+
Test flag for faster execution.
|
|
60
|
+
input_file: str or Path
|
|
61
|
+
Full path of the input CORSIKA file.
|
|
62
|
+
run_number: int
|
|
63
|
+
Run number.
|
|
64
|
+
extra_commands: list[str]
|
|
65
|
+
Additional commands for running simulations given in config.yml.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
Path
|
|
70
|
+
Full path of the run script.
|
|
71
|
+
"""
|
|
72
|
+
script_file_path = self.get_file_name(file_type="sub_script", run_number=run_number)
|
|
73
|
+
self._logger.debug(f"Run bash script - {script_file_path}")
|
|
74
|
+
self._logger.debug(f"Extra commands to be added to the run script {extra_commands}")
|
|
75
|
+
|
|
76
|
+
command = self.make_run_command(run_number=run_number, input_file=input_file)
|
|
77
|
+
with script_file_path.open("w", encoding="utf-8") as file:
|
|
78
|
+
file.write("#!/usr/bin/env bash\n\n")
|
|
79
|
+
file.write("set -e\n")
|
|
80
|
+
file.write("set -o pipefail\n")
|
|
81
|
+
file.write("\nSECONDS=0\n")
|
|
82
|
+
|
|
83
|
+
if extra_commands:
|
|
84
|
+
file.write("# Writing extras\n")
|
|
85
|
+
for line in extra_commands:
|
|
86
|
+
file.write(f"{line}\n")
|
|
87
|
+
file.write("# End of extras\n\n")
|
|
88
|
+
|
|
89
|
+
n = 1 if test else self.runs_per_set
|
|
90
|
+
for _ in range(n):
|
|
91
|
+
file.write(f"{command}\n\n")
|
|
92
|
+
|
|
93
|
+
file.write('\necho "RUNTIME: $SECONDS"\n')
|
|
94
|
+
|
|
95
|
+
script_file_path.chmod(script_file_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP)
|
|
96
|
+
return script_file_path
|
|
97
|
+
|
|
53
98
|
def make_run_command(self, run_number=None, input_file=None, weak_pointing=None):
|
|
54
99
|
"""
|
|
55
100
|
Build and return the command to run sim_telarray.
|
|
@@ -111,12 +156,12 @@ class SimulatorArray(SimtelRunner):
|
|
|
111
156
|
command += super().get_config_option(key, cfg[key])
|
|
112
157
|
|
|
113
158
|
run_mode = cfg.get("run_mode")
|
|
114
|
-
if run_mode in ("pedestals", "
|
|
159
|
+
if run_mode in ("pedestals", "pedestals_nsb_only"):
|
|
115
160
|
n_events = cfg.get("number_of_pedestal_events", cfg["number_of_events"])
|
|
116
161
|
command += super().get_config_option("pedestal_events", n_events)
|
|
117
|
-
if run_mode == "
|
|
118
|
-
command += self.
|
|
119
|
-
if run_mode == "
|
|
162
|
+
if run_mode == "pedestals_nsb_only":
|
|
163
|
+
command += self._pedestals_nsb_only_command()
|
|
164
|
+
if run_mode == "pedestals_dark":
|
|
120
165
|
n_events = cfg.get("number_of_dark_events", cfg["number_of_events"])
|
|
121
166
|
command += super().get_config_option("dark_events", n_events)
|
|
122
167
|
if run_mode == "direct_injection":
|
|
@@ -133,7 +178,7 @@ class SimulatorArray(SimtelRunner):
|
|
|
133
178
|
output_file = self.get_file_name(file_type="simtel_output", run_number=run_number)
|
|
134
179
|
self.corsika_config.array_model.export_all_simtel_config_files()
|
|
135
180
|
|
|
136
|
-
command = str(
|
|
181
|
+
command = str(settings.config.sim_telarray_exe)
|
|
137
182
|
command += f" -c {self.corsika_config.array_model.config_file_path}"
|
|
138
183
|
command += f" -I{config_dir}"
|
|
139
184
|
command += super().get_config_option(
|
|
@@ -155,7 +200,7 @@ class SimulatorArray(SimtelRunner):
|
|
|
155
200
|
|
|
156
201
|
return command
|
|
157
202
|
|
|
158
|
-
def
|
|
203
|
+
def _pedestals_nsb_only_command(self):
|
|
159
204
|
"""
|
|
160
205
|
Generate the command to run sim_telarray for nsb-only pedestal simulations.
|
|
161
206
|
|
|
@@ -174,9 +219,7 @@ class SimulatorArray(SimtelRunner):
|
|
|
174
219
|
"fadc_sysvar_pedestal",
|
|
175
220
|
"fadc_dev_pedestal",
|
|
176
221
|
]
|
|
177
|
-
null_command_parts = []
|
|
178
|
-
for param in null_values:
|
|
179
|
-
null_command_parts.append(super().get_config_option(param, 0.0))
|
|
222
|
+
null_command_parts = [super().get_config_option(param, 0.0) for param in null_values]
|
|
180
223
|
command = " ".join(null_command_parts)
|
|
181
224
|
|
|
182
225
|
one_values = [
|
|
@@ -185,15 +228,13 @@ class SimulatorArray(SimtelRunner):
|
|
|
185
228
|
"fadc_lg_dev_pedestal",
|
|
186
229
|
"fadc_lg_sysvar_pedestal",
|
|
187
230
|
]
|
|
188
|
-
one_command_parts = []
|
|
189
|
-
for param in one_values:
|
|
190
|
-
one_command_parts.append(super().get_config_option(param, -1.0))
|
|
231
|
+
one_command_parts = [super().get_config_option(param, -1.0) for param in one_values]
|
|
191
232
|
command += " " + " ".join(one_command_parts)
|
|
192
233
|
return command
|
|
193
234
|
|
|
194
235
|
def _check_run_result(self, run_number=None):
|
|
195
236
|
"""
|
|
196
|
-
Check if
|
|
237
|
+
Check if sim_telarray output file exists.
|
|
197
238
|
|
|
198
239
|
Parameters
|
|
199
240
|
----------
|
|
@@ -203,18 +244,16 @@ class SimulatorArray(SimtelRunner):
|
|
|
203
244
|
Returns
|
|
204
245
|
-------
|
|
205
246
|
bool
|
|
206
|
-
True if
|
|
247
|
+
True if sim_telarray output file exists.
|
|
207
248
|
|
|
208
249
|
Raises
|
|
209
250
|
------
|
|
210
251
|
InvalidOutputFileError
|
|
211
|
-
If
|
|
252
|
+
If sim_telarray output file does not exist.
|
|
212
253
|
"""
|
|
213
254
|
output_file = self.get_file_name(file_type="simtel_output", run_number=run_number)
|
|
214
255
|
if not output_file.exists():
|
|
215
|
-
|
|
216
|
-
self._logger.error(msg)
|
|
217
|
-
raise InvalidOutputFileError(msg)
|
|
256
|
+
raise InvalidOutputFileError(f"sim_telarray output file {output_file} does not exist.")
|
|
218
257
|
self._logger.debug(f"sim_telarray output file {output_file} exists.")
|
|
219
258
|
return True
|
|
220
259
|
|
|
@@ -223,7 +262,7 @@ class SimulatorArray(SimtelRunner):
|
|
|
223
262
|
"""
|
|
224
263
|
Get the power law index for sim_telarray.
|
|
225
264
|
|
|
226
|
-
Events will be
|
|
265
|
+
Events will be filled in histograms in sim_telarray with a weight according to
|
|
227
266
|
the difference between this exponent and the one used for the shower simulations.
|
|
228
267
|
|
|
229
268
|
Parameters
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
+
from simtools import settings
|
|
6
7
|
from simtools.io import ascii_handler
|
|
7
8
|
from simtools.runners.simtel_runner import SimtelRunner
|
|
8
9
|
from simtools.utils import general
|
|
@@ -20,8 +21,6 @@ class SimulatorCameraEfficiency(SimtelRunner):
|
|
|
20
21
|
Instance of SiteModel class.
|
|
21
22
|
label: str
|
|
22
23
|
Instance label. Important for output file naming.
|
|
23
|
-
simtel_path: str or Path
|
|
24
|
-
Location of sim_telarray installation.
|
|
25
24
|
file_simtel: str or Path
|
|
26
25
|
Location of the sim_telarray testeff tool output file.
|
|
27
26
|
zenith_angle: float
|
|
@@ -37,7 +36,6 @@ class SimulatorCameraEfficiency(SimtelRunner):
|
|
|
37
36
|
telescope_model,
|
|
38
37
|
site_model,
|
|
39
38
|
label=None,
|
|
40
|
-
simtel_path=None,
|
|
41
39
|
file_simtel=None,
|
|
42
40
|
file_log=None,
|
|
43
41
|
zenith_angle=None,
|
|
@@ -48,7 +46,7 @@ class SimulatorCameraEfficiency(SimtelRunner):
|
|
|
48
46
|
self._logger = logging.getLogger(__name__)
|
|
49
47
|
self._logger.debug("Init SimulatorCameraEfficiency")
|
|
50
48
|
|
|
51
|
-
super().__init__(label=label
|
|
49
|
+
super().__init__(label=label)
|
|
52
50
|
|
|
53
51
|
self._telescope_model = telescope_model
|
|
54
52
|
self._site_model = site_model
|
|
@@ -109,7 +107,7 @@ class SimulatorCameraEfficiency(SimtelRunner):
|
|
|
109
107
|
"mirror_reflectivity", "secondary_mirror_incidence_angle"
|
|
110
108
|
)
|
|
111
109
|
|
|
112
|
-
command = str(
|
|
110
|
+
command = str(settings.config.sim_telarray_path / "bin/testeff")
|
|
113
111
|
if self.skip_correction_to_nsb_spectrum:
|
|
114
112
|
command += " -nc" # Do not apply correction to original altitude where B&E was derived
|
|
115
113
|
command += " -I" # Clear the fall-back configuration directories
|
|
@@ -150,7 +148,7 @@ class SimulatorCameraEfficiency(SimtelRunner):
|
|
|
150
148
|
command = general.clear_default_sim_telarray_cfg_directories(command)
|
|
151
149
|
|
|
152
150
|
return (
|
|
153
|
-
f"cd {
|
|
151
|
+
f"cd {settings.config.sim_telarray_path} && {command}",
|
|
154
152
|
self._file_simtel,
|
|
155
153
|
self._file_log,
|
|
156
154
|
)
|