gammasimtools 0.25.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.25.0.dist-info → gammasimtools-0.26.0.dist-info}/METADATA +2 -1
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/RECORD +122 -121
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/entry_points.txt +2 -1
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +2 -2
- simtools/application_control.py +35 -7
- 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 +0 -1
- simtools/applications/derive_pulse_shape_parameters.py +0 -1
- 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 +5 -111
- 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 +0 -2
- simtools/applications/simulate_illuminator.py +0 -1
- simtools/applications/simulate_pedestals.py +1 -5
- simtools/applications/simulate_prod.py +1 -5
- simtools/applications/simulate_prod_htcondor_generator.py +1 -1
- simtools/applications/submit_array_layouts.py +2 -4
- 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_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 +35 -2
- simtools/configuration/configurator.py +6 -11
- simtools/corsika/corsika_config.py +16 -21
- 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 +13 -15
- simtools/data_model/validate_data.py +1 -3
- simtools/db/db_handler.py +19 -8
- simtools/dependencies.py +81 -38
- simtools/io/ascii_handler.py +4 -2
- simtools/io/table_handler.py +1 -1
- simtools/layout/array_layout.py +4 -12
- simtools/layout/array_layout_utils.py +226 -57
- simtools/model/array_model.py +1 -13
- simtools/model/calibration_model.py +0 -4
- simtools/model/legacy_model_parameter.py +134 -0
- simtools/model/model_parameter.py +24 -13
- 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 +18 -19
- simtools/ray_tracing/psf_parameter_optimisation.py +0 -1
- simtools/ray_tracing/ray_tracing.py +6 -15
- simtools/reporting/docs_auto_report_generator.py +8 -13
- simtools/reporting/docs_read_parameters.py +2 -8
- simtools/runners/corsika_runner.py +5 -9
- simtools/runners/corsika_simtel_runner.py +3 -8
- simtools/runners/simtel_runner.py +0 -5
- simtools/runners/simtools_runner.py +2 -4
- simtools/settings.py +154 -0
- simtools/{io/eventio_handler.py → sim_events/file_info.py} +3 -3
- 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 +7 -2
- simtools/simtel/simtel_config_writer.py +79 -36
- simtools/simtel/simtel_table_reader.py +6 -4
- simtools/simtel/simulator_array.py +4 -11
- simtools/simtel/simulator_camera_efficiency.py +4 -6
- simtools/simtel/simulator_light_emission.py +69 -24
- simtools/simtel/simulator_ray_tracing.py +4 -10
- simtools/simulator.py +7 -14
- simtools/telescope_trigger_rates.py +3 -4
- simtools/testing/assertions.py +84 -33
- simtools/testing/configuration.py +1 -2
- simtools/testing/helpers.py +2 -3
- simtools/testing/log_inspector.py +1 -0
- simtools/testing/sim_telarray_metadata.py +1 -1
- simtools/testing/validate_output.py +34 -23
- simtools/utils/general.py +37 -0
- simtools/utils/geometry.py +0 -77
- simtools/utils/names.py +5 -5
- simtools/visualization/legend_handlers.py +7 -6
- simtools/visualization/plot_array_layout.py +91 -16
- simtools/visualization/plot_corsika_histograms.py +143 -605
- simtools/visualization/plot_mirrors.py +1 -4
- 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
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.26.0.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Generate a reduced dataset from
|
|
1
|
+
"""Generate a reduced dataset from simulation files (CORSIKA/sim_telarray) using astropy tables."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
from dataclasses import dataclass
|
|
@@ -6,7 +6,7 @@ from dataclasses import dataclass
|
|
|
6
6
|
import astropy.units as u
|
|
7
7
|
import numpy as np
|
|
8
8
|
from astropy.table import Table
|
|
9
|
-
from eventio import EventIOFile
|
|
9
|
+
from eventio import EventIOFile, iact
|
|
10
10
|
from eventio.simtel import (
|
|
11
11
|
ArrayEvent,
|
|
12
12
|
MCEvent,
|
|
@@ -17,7 +17,10 @@ from eventio.simtel import (
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
from simtools.corsika.primary_particle import PrimaryParticle
|
|
20
|
-
from simtools.
|
|
20
|
+
from simtools.sim_events.file_info import (
|
|
21
|
+
get_combined_eventio_run_header,
|
|
22
|
+
get_corsika_run_and_event_headers,
|
|
23
|
+
)
|
|
21
24
|
from simtools.simtel.simtel_io_metadata import (
|
|
22
25
|
get_sim_telarray_telescope_id_to_telescope_name_mapping,
|
|
23
26
|
read_sim_telarray_metadata,
|
|
@@ -68,11 +71,11 @@ class TableSchemas:
|
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
|
|
71
|
-
class
|
|
74
|
+
class EventDataWriter:
|
|
72
75
|
"""
|
|
73
|
-
Process
|
|
76
|
+
Process simulation events (CORSIKA/sim_telarray) and write tables to file.
|
|
74
77
|
|
|
75
|
-
Extracts essential information from
|
|
78
|
+
Extracts essential information from simulation files, including:
|
|
76
79
|
|
|
77
80
|
- Shower parameters (energy, core location, direction)
|
|
78
81
|
- Trigger patterns
|
|
@@ -108,7 +111,7 @@ class SimtelIOEventDataWriter:
|
|
|
108
111
|
Returns
|
|
109
112
|
-------
|
|
110
113
|
list
|
|
111
|
-
List of
|
|
114
|
+
List of tables containing processed data.
|
|
112
115
|
"""
|
|
113
116
|
for i, file in enumerate(self.input_files[: self.max_files]):
|
|
114
117
|
self._logger.info(f"Processing file {i + 1}/{self.max_files}: {file}")
|
|
@@ -117,13 +120,15 @@ class SimtelIOEventDataWriter:
|
|
|
117
120
|
return self.create_tables()
|
|
118
121
|
|
|
119
122
|
def create_tables(self):
|
|
120
|
-
"""Create
|
|
123
|
+
"""Create tables from collected data."""
|
|
121
124
|
tables = []
|
|
122
125
|
for data, schema, name in [
|
|
123
126
|
(self.shower_data, TableSchemas.shower_schema, "SHOWERS"),
|
|
124
127
|
(self.trigger_data, TableSchemas.trigger_schema, "TRIGGERS"),
|
|
125
128
|
(self.file_info, TableSchemas.file_info_schema, "FILE_INFO"),
|
|
126
129
|
]:
|
|
130
|
+
if len(data) == 0:
|
|
131
|
+
continue
|
|
127
132
|
table = Table(rows=data, names=schema.keys())
|
|
128
133
|
table.meta["EXTNAME"] = name
|
|
129
134
|
self._add_units_to_table(table, schema)
|
|
@@ -149,40 +154,69 @@ class SimtelIOEventDataWriter:
|
|
|
149
154
|
self._process_mc_event(eventio_object)
|
|
150
155
|
elif isinstance(eventio_object, ArrayEvent):
|
|
151
156
|
self._process_array_event(eventio_object, file_id)
|
|
157
|
+
elif isinstance(eventio_object, iact.EventHeader):
|
|
158
|
+
self._process_mc_shower_from_iact(eventio_object, file_id)
|
|
152
159
|
|
|
153
160
|
def _process_mc_run_header(self, eventio_object):
|
|
154
|
-
"""Process MC run header
|
|
161
|
+
"""Process MC run header (sim_telarray file)."""
|
|
155
162
|
mc_head = eventio_object.parse()
|
|
156
163
|
self.n_use = mc_head["n_use"] # reuse factor n_use needed to extend the values below
|
|
157
164
|
self._logger.info(f"Shower reuse factor: {self.n_use} (viewcone: {mc_head['viewcone']})")
|
|
158
165
|
|
|
159
166
|
def _process_file_info(self, file_id, file):
|
|
160
167
|
"""Process file information and append to file info list."""
|
|
161
|
-
run_info =
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
168
|
+
run_info = get_combined_eventio_run_header(file)
|
|
169
|
+
if run_info: # sim_telarray file
|
|
170
|
+
self.telescope_id_to_name = get_sim_telarray_telescope_id_to_telescope_name_mapping(
|
|
171
|
+
file
|
|
172
|
+
)
|
|
173
|
+
corsika7_id = PrimaryParticle(
|
|
174
|
+
particle_id_type="eventio_id",
|
|
175
|
+
particle_id=run_info.get("primary_id", 1),
|
|
176
|
+
).corsika7_id
|
|
177
|
+
nsb = self.get_nsb_level_from_sim_telarray_metadata(file)
|
|
178
|
+
|
|
179
|
+
e_min, e_max = run_info["E_range"]
|
|
180
|
+
view_cone_min, view_cone_max = run_info["viewcone"]
|
|
181
|
+
core_min, core_max = run_info["core_range"]
|
|
182
|
+
azimuth, el = np.degrees(run_info["direction"])
|
|
183
|
+
zenith = 90.0 - el
|
|
184
|
+
else: # CORSIKA IACT file
|
|
185
|
+
run_header, event_header = get_corsika_run_and_event_headers(file)
|
|
186
|
+
corsika7_id = int(event_header["particle_id"])
|
|
187
|
+
e_min = event_header["energy_min"]
|
|
188
|
+
e_max = event_header["energy_max"]
|
|
189
|
+
zenith = np.degrees(event_header["zenith"])
|
|
190
|
+
# Rotate to geographic north
|
|
191
|
+
azimuth = np.degrees(
|
|
192
|
+
event_header["azimuth"] - event_header["angle_array_x_magnetic_north"]
|
|
193
|
+
)
|
|
194
|
+
view_cone_min = event_header["viewcone_inner_angle"]
|
|
195
|
+
view_cone_max = event_header["viewcone_outer_angle"]
|
|
196
|
+
core_min = 0.0
|
|
197
|
+
core_max = run_header["x_scatter"] / 1.0e2 # cm to m
|
|
198
|
+
nsb = 0.0
|
|
199
|
+
|
|
166
200
|
self.file_info.append(
|
|
167
201
|
{
|
|
168
202
|
"file_name": str(file),
|
|
169
203
|
"file_id": file_id,
|
|
170
|
-
"particle_id":
|
|
171
|
-
"energy_min":
|
|
172
|
-
"energy_max":
|
|
173
|
-
"viewcone_min":
|
|
174
|
-
"viewcone_max":
|
|
175
|
-
"core_scatter_min":
|
|
176
|
-
"core_scatter_max":
|
|
177
|
-
"zenith":
|
|
178
|
-
"azimuth":
|
|
179
|
-
"nsb_level":
|
|
204
|
+
"particle_id": corsika7_id,
|
|
205
|
+
"energy_min": e_min,
|
|
206
|
+
"energy_max": e_max,
|
|
207
|
+
"viewcone_min": view_cone_min,
|
|
208
|
+
"viewcone_max": view_cone_max,
|
|
209
|
+
"core_scatter_min": core_min,
|
|
210
|
+
"core_scatter_max": core_max,
|
|
211
|
+
"zenith": zenith,
|
|
212
|
+
"azimuth": azimuth,
|
|
213
|
+
"nsb_level": nsb,
|
|
180
214
|
}
|
|
181
215
|
)
|
|
182
216
|
|
|
183
217
|
def _process_mc_shower(self, eventio_object, file_id):
|
|
184
218
|
"""
|
|
185
|
-
Process MC shower and update shower event list.
|
|
219
|
+
Process MC shower from sim_telarray file and update shower event list.
|
|
186
220
|
|
|
187
221
|
Duplicated entries 'self.n_use' times to match the number simulated events with
|
|
188
222
|
different core positions.
|
|
@@ -204,6 +238,31 @@ class SimtelIOEventDataWriter:
|
|
|
204
238
|
for _ in range(self.n_use)
|
|
205
239
|
)
|
|
206
240
|
|
|
241
|
+
def _process_mc_shower_from_iact(self, eventio_object, file_id):
|
|
242
|
+
"""
|
|
243
|
+
Process MC shower from IACT file and update shower event list.
|
|
244
|
+
|
|
245
|
+
Duplicated entries 'self.n_use' times to match the number simulated events with
|
|
246
|
+
different core positions.
|
|
247
|
+
"""
|
|
248
|
+
shower_header = eventio_object.parse()
|
|
249
|
+
self.n_use = int(shower_header["n_reuse"])
|
|
250
|
+
|
|
251
|
+
self.shower_data.extend(
|
|
252
|
+
{
|
|
253
|
+
"shower_id": shower_header["event_number"],
|
|
254
|
+
"event_id": shower_header["event_number"] * 100 + i,
|
|
255
|
+
"file_id": file_id,
|
|
256
|
+
"simulated_energy": shower_header["total_energy"],
|
|
257
|
+
"x_core": shower_header["reuse_x"][i] / 1.0e2,
|
|
258
|
+
"y_core": shower_header["reuse_y"][i] / 1.0e2,
|
|
259
|
+
"shower_azimuth": np.degrees(shower_header["azimuth"]),
|
|
260
|
+
"shower_altitude": 90.0 - np.degrees(shower_header["zenith"]),
|
|
261
|
+
"area_weight": 1.0,
|
|
262
|
+
}
|
|
263
|
+
for i in range(self.n_use)
|
|
264
|
+
)
|
|
265
|
+
|
|
207
266
|
def _process_mc_event(self, eventio_object):
|
|
208
267
|
"""
|
|
209
268
|
Process MC event and update shower event list.
|
simtools/simtel/pulse_shapes.py
CHANGED
|
@@ -94,8 +94,13 @@ def _exp_decay(t, tau):
|
|
|
94
94
|
numpy.ndarray
|
|
95
95
|
Exponential values at ``t`` (unitless), zero for ``t < 0``.
|
|
96
96
|
"""
|
|
97
|
-
tau = max(tau, 1e-9)
|
|
98
|
-
|
|
97
|
+
tau = max(float(tau), 1e-9)
|
|
98
|
+
t_arr = np.asarray(t, dtype=float)
|
|
99
|
+
expo = -t_arr / tau
|
|
100
|
+
expo = np.minimum(expo, 0.0)
|
|
101
|
+
with np.errstate(over="ignore", under="ignore", invalid="ignore"):
|
|
102
|
+
e = np.exp(expo)
|
|
103
|
+
return np.where(t_arr >= 0, e, 0.0)
|
|
99
104
|
|
|
100
105
|
|
|
101
106
|
def generate_gauss_expconv_pulse(
|
|
@@ -10,7 +10,7 @@ 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
14
|
from simtools.simtel.pulse_shapes import generate_pulse_from_rise_fall_times
|
|
15
15
|
from simtools.utils import names
|
|
16
16
|
|
|
@@ -56,8 +56,6 @@ class SimtelConfigWriter:
|
|
|
56
56
|
Layout name.
|
|
57
57
|
label: str
|
|
58
58
|
Instance label. Important for output file naming.
|
|
59
|
-
simtel_path: str or Path
|
|
60
|
-
Path to the sim_telarray installation directory.
|
|
61
59
|
"""
|
|
62
60
|
|
|
63
61
|
TAB = " " * 3
|
|
@@ -70,7 +68,6 @@ class SimtelConfigWriter:
|
|
|
70
68
|
telescope_model_name=None,
|
|
71
69
|
telescope_design_model=None,
|
|
72
70
|
label=None,
|
|
73
|
-
simtel_path=None,
|
|
74
71
|
):
|
|
75
72
|
"""Initialize SimtelConfigWriter."""
|
|
76
73
|
self._logger = logging.getLogger(__name__)
|
|
@@ -82,7 +79,6 @@ class SimtelConfigWriter:
|
|
|
82
79
|
self._layout_name = layout_name
|
|
83
80
|
self._telescope_model_name = telescope_model_name
|
|
84
81
|
self._telescope_design_model = telescope_design_model
|
|
85
|
-
self._simtel_path = simtel_path
|
|
86
82
|
|
|
87
83
|
def write_telescope_config_file(
|
|
88
84
|
self, config_file_path, parameters, telescope_name=None, telescope_design_model=None
|
|
@@ -125,14 +121,14 @@ class SimtelConfigWriter:
|
|
|
125
121
|
file.write(f"{meta}\n")
|
|
126
122
|
|
|
127
123
|
@staticmethod
|
|
128
|
-
def
|
|
124
|
+
def write_light_pulse_table_gauss_exp_conv(
|
|
129
125
|
file_path,
|
|
130
|
-
width_ns
|
|
131
|
-
exp_decay_ns
|
|
126
|
+
width_ns,
|
|
127
|
+
exp_decay_ns,
|
|
128
|
+
fadc_sum_bins,
|
|
132
129
|
dt_ns=0.1,
|
|
133
130
|
rise_range=(0.1, 0.9),
|
|
134
131
|
fall_range=(0.9, 0.1),
|
|
135
|
-
fadc_sum_bins=None,
|
|
136
132
|
time_margin_ns=10.0,
|
|
137
133
|
):
|
|
138
134
|
"""Write a pulse table for a Gaussian convolved with a causal exponential.
|
|
@@ -143,22 +139,19 @@ class SimtelConfigWriter:
|
|
|
143
139
|
Destination path of the ASCII pulse table to write. Parent directory must exist.
|
|
144
140
|
width_ns : float
|
|
145
141
|
Target rise time in ns between the fractional levels defined by ``rise_range``.
|
|
146
|
-
Defaults correspond to 10-90% rise time.
|
|
147
142
|
exp_decay_ns : float
|
|
148
143
|
Target fall time in ns between the fractional levels defined by ``fall_range``.
|
|
149
|
-
Defaults correspond to 90-10% fall time.
|
|
150
|
-
dt_ns : float, optional
|
|
151
|
-
Time sampling step in ns for the generated pulse table. Default is 0.1.
|
|
152
|
-
rise_range : tuple[float, float], optional
|
|
153
|
-
Fractional amplitude bounds (low, high) for rise-time definition. Default (0.1, 0.9).
|
|
154
|
-
fall_range : tuple[float, float], optional
|
|
155
|
-
Fractional amplitude bounds (high, low) for fall-time definition. Default (0.9, 0.1).
|
|
156
144
|
fadc_sum_bins : int
|
|
157
145
|
Length of the FADC integration window (treated as ns here) used to derive
|
|
158
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.
|
|
159
153
|
time_margin_ns : float, optional
|
|
160
154
|
Margin in ns to add to both ends of the FADC window when ``fadc_sum_bins`` is given.
|
|
161
|
-
Default is 5.0 ns.
|
|
162
155
|
|
|
163
156
|
Returns
|
|
164
157
|
-------
|
|
@@ -174,8 +167,10 @@ class SimtelConfigWriter:
|
|
|
174
167
|
if width_ns is None or exp_decay_ns is None:
|
|
175
168
|
raise ValueError("width_ns (rise 10-90) and exp_decay_ns (fall 90-10) are required")
|
|
176
169
|
logger.info(
|
|
177
|
-
|
|
178
|
-
f"
|
|
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"
|
|
179
174
|
)
|
|
180
175
|
width = float(fadc_sum_bins)
|
|
181
176
|
t_start_ns = -abs(time_margin_ns + width)
|
|
@@ -193,6 +188,42 @@ class SimtelConfigWriter:
|
|
|
193
188
|
|
|
194
189
|
return SimtelConfigWriter._write_ascii_pulse_table(file_path, t, y)
|
|
195
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
|
+
|
|
196
227
|
@staticmethod
|
|
197
228
|
def _write_ascii_pulse_table(file_path, t, y):
|
|
198
229
|
"""Write two-column ASCII pulse table."""
|
|
@@ -202,6 +233,15 @@ class SimtelConfigWriter:
|
|
|
202
233
|
fh.write(f"{ti:.6f} {yi:.8f}\n")
|
|
203
234
|
return Path(file_path)
|
|
204
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
|
+
|
|
205
245
|
def _get_parameters_for_sim_telarray(self, parameters, config_file_path):
|
|
206
246
|
"""
|
|
207
247
|
Convert parameter dictionary to sim_telarray configuration file format.
|
|
@@ -257,28 +297,24 @@ class SimtelConfigWriter:
|
|
|
257
297
|
Model parameters in sim_telarray format including flasher parameters.
|
|
258
298
|
|
|
259
299
|
"""
|
|
260
|
-
if "flasher_pulse_shape" not in parameters
|
|
300
|
+
if "flasher_pulse_shape" not in parameters:
|
|
261
301
|
return simtel_par
|
|
262
302
|
|
|
263
303
|
mapping = {
|
|
264
304
|
"gauss": "laser_pulse_sigtime",
|
|
265
305
|
"tophat": "laser_pulse_twidth",
|
|
306
|
+
"gauss-exponential": "laser_pulse_sigtime",
|
|
266
307
|
}
|
|
267
308
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
)
|
|
273
|
-
else:
|
|
274
|
-
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]
|
|
275
313
|
|
|
276
|
-
|
|
314
|
+
simtel_par["laser_pulse_exptime"] = exp_decay if ("exponential" in shape) else 0.0
|
|
277
315
|
|
|
278
316
|
simtel_par.update(dict.fromkeys(mapping.values(), 0.0))
|
|
279
|
-
if shape
|
|
280
|
-
simtel_par["laser_pulse_sigtime"] = width
|
|
281
|
-
elif shape in mapping:
|
|
317
|
+
if shape in mapping:
|
|
282
318
|
simtel_par[mapping[shape]] = width
|
|
283
319
|
else:
|
|
284
320
|
self._logger.warning(f"Flasher pulse shape '{shape}' without width definition")
|
|
@@ -576,17 +612,24 @@ class SimtelConfigWriter:
|
|
|
576
612
|
"simtools_model_production_version": self._model_version,
|
|
577
613
|
}
|
|
578
614
|
try:
|
|
579
|
-
build_opts =
|
|
580
|
-
Path(self._simtel_path) / "build_opts.yml"
|
|
581
|
-
)
|
|
615
|
+
build_opts = dependencies.get_build_options()
|
|
582
616
|
for key, value in build_opts.items():
|
|
583
617
|
meta_items[f"simtools_{key}"] = value
|
|
584
618
|
except (FileNotFoundError, TypeError):
|
|
585
619
|
pass # don't expect build_opts.yml to be present on all systems
|
|
586
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
|
+
|
|
587
629
|
file.write(f"{self.TAB}% Simtools parameters\n")
|
|
588
630
|
for key, value in meta_items.items():
|
|
589
|
-
|
|
631
|
+
if not isinstance(value, list):
|
|
632
|
+
file.write(f"{self.TAB}metaparam global set {key} = {value}\n")
|
|
590
633
|
|
|
591
634
|
def _write_site_parameters(
|
|
592
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
|
{
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
import stat
|
|
5
5
|
|
|
6
|
+
from simtools import settings
|
|
6
7
|
from simtools.io import io_handler
|
|
7
8
|
from simtools.runners.simtel_runner import InvalidOutputFileError, SimtelRunner
|
|
8
9
|
from simtools.utils.general import clear_default_sim_telarray_cfg_directories
|
|
@@ -16,8 +17,6 @@ class SimulatorArray(SimtelRunner):
|
|
|
16
17
|
----------
|
|
17
18
|
corsika_config_data: CorsikaConfig
|
|
18
19
|
CORSIKA configuration.
|
|
19
|
-
simtel_path: str or Path
|
|
20
|
-
Location of source of the sim_telarray/CORSIKA package.
|
|
21
20
|
label: str
|
|
22
21
|
Instance label.
|
|
23
22
|
use_multipipe: bool
|
|
@@ -29,7 +28,6 @@ class SimulatorArray(SimtelRunner):
|
|
|
29
28
|
def __init__(
|
|
30
29
|
self,
|
|
31
30
|
corsika_config,
|
|
32
|
-
simtel_path,
|
|
33
31
|
label=None,
|
|
34
32
|
use_multipipe=False,
|
|
35
33
|
sim_telarray_seeds=None,
|
|
@@ -40,7 +38,6 @@ class SimulatorArray(SimtelRunner):
|
|
|
40
38
|
self._logger.debug("Init SimulatorArray")
|
|
41
39
|
super().__init__(
|
|
42
40
|
label=label,
|
|
43
|
-
simtel_path=simtel_path,
|
|
44
41
|
corsika_config=corsika_config,
|
|
45
42
|
use_multipipe=use_multipipe,
|
|
46
43
|
calibration_run_mode=calibration_config.get("run_mode") if calibration_config else None,
|
|
@@ -181,7 +178,7 @@ class SimulatorArray(SimtelRunner):
|
|
|
181
178
|
output_file = self.get_file_name(file_type="simtel_output", run_number=run_number)
|
|
182
179
|
self.corsika_config.array_model.export_all_simtel_config_files()
|
|
183
180
|
|
|
184
|
-
command = str(
|
|
181
|
+
command = str(settings.config.sim_telarray_exe)
|
|
185
182
|
command += f" -c {self.corsika_config.array_model.config_file_path}"
|
|
186
183
|
command += f" -I{config_dir}"
|
|
187
184
|
command += super().get_config_option(
|
|
@@ -222,9 +219,7 @@ class SimulatorArray(SimtelRunner):
|
|
|
222
219
|
"fadc_sysvar_pedestal",
|
|
223
220
|
"fadc_dev_pedestal",
|
|
224
221
|
]
|
|
225
|
-
null_command_parts = []
|
|
226
|
-
for param in null_values:
|
|
227
|
-
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]
|
|
228
223
|
command = " ".join(null_command_parts)
|
|
229
224
|
|
|
230
225
|
one_values = [
|
|
@@ -233,9 +228,7 @@ class SimulatorArray(SimtelRunner):
|
|
|
233
228
|
"fadc_lg_dev_pedestal",
|
|
234
229
|
"fadc_lg_sysvar_pedestal",
|
|
235
230
|
]
|
|
236
|
-
one_command_parts = []
|
|
237
|
-
for param in one_values:
|
|
238
|
-
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]
|
|
239
232
|
command += " " + " ".join(one_command_parts)
|
|
240
233
|
return command
|
|
241
234
|
|
|
@@ -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
|
)
|