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
|
@@ -11,6 +11,7 @@ import simtools.utils.general as gen
|
|
|
11
11
|
from simtools.data_model import schema
|
|
12
12
|
from simtools.db import db_handler
|
|
13
13
|
from simtools.io import ascii_handler, io_handler
|
|
14
|
+
from simtools.model import legacy_model_parameter
|
|
14
15
|
from simtools.simtel.simtel_config_writer import SimtelConfigWriter
|
|
15
16
|
from simtools.utils import names, value_conversion
|
|
16
17
|
|
|
@@ -28,8 +29,6 @@ class ModelParameter:
|
|
|
28
29
|
|
|
29
30
|
Parameters
|
|
30
31
|
----------
|
|
31
|
-
db_config:
|
|
32
|
-
Database configuration dictionary.
|
|
33
32
|
model_version: str
|
|
34
33
|
Version of the model (ex. 5.0.0).
|
|
35
34
|
site: str
|
|
@@ -51,7 +50,6 @@ class ModelParameter:
|
|
|
51
50
|
|
|
52
51
|
def __init__(
|
|
53
52
|
self,
|
|
54
|
-
db_config,
|
|
55
53
|
model_version,
|
|
56
54
|
site=None,
|
|
57
55
|
array_element_name=None,
|
|
@@ -62,7 +60,9 @@ class ModelParameter:
|
|
|
62
60
|
):
|
|
63
61
|
self._logger = logging.getLogger(__name__)
|
|
64
62
|
self.io_handler = io_handler.IOHandler()
|
|
65
|
-
self.db = db_handler.DatabaseHandler(
|
|
63
|
+
self.db = db_handler.DatabaseHandler()
|
|
64
|
+
if not self.db.is_configured():
|
|
65
|
+
raise RuntimeError("Database is not configured.")
|
|
66
66
|
|
|
67
67
|
self.parameters = {}
|
|
68
68
|
self._simulation_config_parameters = {sw: {} for sw in names.simulation_software()}
|
|
@@ -271,7 +271,6 @@ class ModelParameter:
|
|
|
271
271
|
# Setting file name and the location
|
|
272
272
|
config_file_name = names.simtel_config_file_name(
|
|
273
273
|
self.site,
|
|
274
|
-
self.model_version,
|
|
275
274
|
telescope_model_name=self.name,
|
|
276
275
|
label=self.label,
|
|
277
276
|
)
|
|
@@ -328,35 +327,46 @@ class ModelParameter:
|
|
|
328
327
|
)
|
|
329
328
|
if self.overwrite_model_parameters:
|
|
330
329
|
self.overwrite_parameters_from_file(self.overwrite_model_parameters)
|
|
331
|
-
self.
|
|
330
|
+
self._check_model_parameter_versions(self.parameters)
|
|
332
331
|
|
|
333
332
|
self._load_simulation_software_parameter()
|
|
334
333
|
for software_name, parameters in self._simulation_config_parameters.items():
|
|
335
|
-
self.
|
|
336
|
-
parameters.keys(), software_name=software_name
|
|
337
|
-
)
|
|
334
|
+
self._check_model_parameter_versions(parameters, software_name=software_name)
|
|
338
335
|
|
|
339
|
-
def
|
|
336
|
+
def _check_model_parameter_versions(self, parameters, software_name=None):
|
|
340
337
|
"""
|
|
341
|
-
Ensure
|
|
338
|
+
Ensure parameters follow the latest schema and are compatible with installed software.
|
|
342
339
|
|
|
343
340
|
Compares software versions listed in schema files with the installed software versions
|
|
344
341
|
(e.g., sim_telarray, CORSIKA).
|
|
345
342
|
|
|
343
|
+
For outdated model parameter schemas, legacy update functions are called to update
|
|
344
|
+
the parameters to the latest schema version.
|
|
345
|
+
|
|
346
346
|
Parameters
|
|
347
347
|
----------
|
|
348
|
-
|
|
349
|
-
|
|
348
|
+
parameters: dict
|
|
349
|
+
Dictionary containing model parameters.
|
|
350
350
|
software_name: str
|
|
351
351
|
Name of the software for which the parameters are checked.
|
|
352
352
|
"""
|
|
353
|
-
|
|
353
|
+
_legacy_updates = {}
|
|
354
|
+
for par_name, par_data in parameters.items():
|
|
354
355
|
if par_name in (parameter_schema := names.model_parameters()):
|
|
355
356
|
schema.validate_deprecation_and_version(
|
|
356
357
|
data=parameter_schema[par_name],
|
|
357
358
|
software_name=software_name,
|
|
358
359
|
ignore_software_version=self.ignore_software_version,
|
|
359
360
|
)
|
|
361
|
+
_latest_schema_version = parameter_schema[par_name]["schema_version"]
|
|
362
|
+
if par_data["model_parameter_schema_version"] != _latest_schema_version:
|
|
363
|
+
_legacy_updates.update(
|
|
364
|
+
legacy_model_parameter.update_parameter(
|
|
365
|
+
par_name, parameters, _latest_schema_version
|
|
366
|
+
)
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
legacy_model_parameter.apply_legacy_updates_to_parameters(parameters, _legacy_updates)
|
|
360
370
|
|
|
361
371
|
def overwrite_model_parameter(self, par_name, value, parameter_version=None):
|
|
362
372
|
"""
|
|
@@ -361,7 +361,7 @@ def _get_changes_to_production(
|
|
|
361
361
|
_version_changes, base_model_version = _get_changes_to_production(
|
|
362
362
|
_changes_dict, simulation_models_path, update_type="full_update"
|
|
363
363
|
)
|
|
364
|
-
changes = _update_two_levels_in_changes_dict(
|
|
364
|
+
changes = _update_two_levels_in_changes_dict(_version_changes, changes)
|
|
365
365
|
# stop iterative loop after reaching first full version of production tables
|
|
366
366
|
if _changes_dict.get("model_update", "full_update") == "full_update":
|
|
367
367
|
break
|
|
@@ -461,7 +461,7 @@ def _create_new_model_parameter_entry(telescope, param, param_data, simulation_m
|
|
|
461
461
|
|
|
462
462
|
param_dir = telescope_dir / param
|
|
463
463
|
try:
|
|
464
|
-
latest_file = _get_latest_model_parameter_file(param_dir, param)
|
|
464
|
+
latest_file = _get_latest_model_parameter_file(param_dir, param, param_data["version"])
|
|
465
465
|
except FileNotFoundError:
|
|
466
466
|
latest_file = None
|
|
467
467
|
|
|
@@ -484,10 +484,11 @@ def _create_new_model_parameter_entry(telescope, param, param_data, simulation_m
|
|
|
484
484
|
output_path=param_dir,
|
|
485
485
|
unit=param_data.get("unit"),
|
|
486
486
|
meta_parameter=param_data.get("meta_parameter", False),
|
|
487
|
+
model_parameter_schema_version=param_data.get("model_parameter_schema_version", None),
|
|
487
488
|
)
|
|
488
489
|
|
|
489
490
|
|
|
490
|
-
def _get_latest_model_parameter_file(directory, parameter):
|
|
491
|
+
def _get_latest_model_parameter_file(directory, parameter, max_version):
|
|
491
492
|
"""
|
|
492
493
|
Get the latest model parameter JSON file for a parameter in the given directory.
|
|
493
494
|
|
|
@@ -499,11 +500,14 @@ def _get_latest_model_parameter_file(directory, parameter):
|
|
|
499
500
|
Path to the directory containing parameter JSON files.
|
|
500
501
|
parameter: str
|
|
501
502
|
Name of the parameter to find.
|
|
503
|
+
max_version: str
|
|
504
|
+
Maximum version to consider (inclusive). Files with versions greater than
|
|
505
|
+
this will be excluded.
|
|
502
506
|
|
|
503
507
|
Returns
|
|
504
508
|
-------
|
|
505
509
|
str
|
|
506
|
-
Path to the latest JSON file for the parameter.
|
|
510
|
+
Path to the latest JSON file for the parameter with version <= max_version.
|
|
507
511
|
|
|
508
512
|
Raises
|
|
509
513
|
------
|
|
@@ -521,7 +525,16 @@ def _get_latest_model_parameter_file(directory, parameter):
|
|
|
521
525
|
# version is part after first '-'
|
|
522
526
|
return parse_version(path.stem.split("-", 1)[1])
|
|
523
527
|
|
|
524
|
-
|
|
528
|
+
max_ver = parse_version(max_version)
|
|
529
|
+
filtered_files = [f for f in files if extract_version(f) <= max_ver]
|
|
530
|
+
|
|
531
|
+
if not filtered_files:
|
|
532
|
+
raise FileNotFoundError(
|
|
533
|
+
f"No JSON files found for parameter '{parameter}' with version <= {max_version} "
|
|
534
|
+
f"in directory '{directory}'."
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
latest_file = max(filtered_files, key=extract_version)
|
|
525
538
|
return str(latest_file)
|
|
526
539
|
|
|
527
540
|
|
simtools/model/model_utils.py
CHANGED
|
@@ -10,7 +10,7 @@ from simtools.utils import names
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def initialize_simulation_models(
|
|
13
|
-
label,
|
|
13
|
+
label, model_version, site, telescope_name, calibration_device_name=None
|
|
14
14
|
):
|
|
15
15
|
"""
|
|
16
16
|
Initialize simulation models for a single telescope, site, and calibration device model.
|
|
@@ -19,8 +19,6 @@ def initialize_simulation_models(
|
|
|
19
19
|
----------
|
|
20
20
|
label: str
|
|
21
21
|
Label for the simulation.
|
|
22
|
-
db_config: dict
|
|
23
|
-
Database configuration.
|
|
24
22
|
model_version: str
|
|
25
23
|
Version of the simulation model
|
|
26
24
|
site: str
|
|
@@ -38,21 +36,18 @@ def initialize_simulation_models(
|
|
|
38
36
|
tel_model = TelescopeModel(
|
|
39
37
|
site=site,
|
|
40
38
|
telescope_name=telescope_name,
|
|
41
|
-
db_config=db_config,
|
|
42
39
|
model_version=model_version,
|
|
43
40
|
label=label,
|
|
44
41
|
)
|
|
45
42
|
site_model = SiteModel(
|
|
46
43
|
site=site,
|
|
47
44
|
model_version=model_version,
|
|
48
|
-
db_config=db_config,
|
|
49
45
|
label=label,
|
|
50
46
|
)
|
|
51
47
|
if calibration_device_name is not None:
|
|
52
48
|
calibration_model = CalibrationModel(
|
|
53
49
|
site=site,
|
|
54
50
|
calibration_device_model_name=calibration_device_name,
|
|
55
|
-
db_config=db_config,
|
|
56
51
|
model_version=model_version,
|
|
57
52
|
label=label,
|
|
58
53
|
)
|
simtools/model/site_model.py
CHANGED
|
@@ -26,8 +26,6 @@ class SiteModel(ModelParameter):
|
|
|
26
26
|
----------
|
|
27
27
|
site: str
|
|
28
28
|
Site name (e.g., South or North).
|
|
29
|
-
db_config: dict
|
|
30
|
-
Database configuration.
|
|
31
29
|
model_version: str or list
|
|
32
30
|
Model version or list of model versions (in which case only the first one is used).
|
|
33
31
|
label: str, optional
|
|
@@ -41,7 +39,6 @@ class SiteModel(ModelParameter):
|
|
|
41
39
|
def __init__(
|
|
42
40
|
self,
|
|
43
41
|
site,
|
|
44
|
-
db_config,
|
|
45
42
|
model_version,
|
|
46
43
|
label=None,
|
|
47
44
|
overwrite_model_parameters=None,
|
|
@@ -52,7 +49,6 @@ class SiteModel(ModelParameter):
|
|
|
52
49
|
self._logger.debug("Init SiteModel for site %s", site)
|
|
53
50
|
super().__init__(
|
|
54
51
|
site=site,
|
|
55
|
-
db_config=db_config,
|
|
56
52
|
model_version=model_version,
|
|
57
53
|
label=label,
|
|
58
54
|
collection="sites",
|
|
@@ -26,8 +26,6 @@ class TelescopeModel(ModelParameter):
|
|
|
26
26
|
Site name (e.g., South or North).
|
|
27
27
|
telescope_name: str
|
|
28
28
|
Telescope name (ex. LSTN-01, LSTN-design, ...).
|
|
29
|
-
db_config: dict
|
|
30
|
-
Database configuration.
|
|
31
29
|
model_version: str
|
|
32
30
|
Model version.
|
|
33
31
|
label: str, optional
|
|
@@ -42,7 +40,6 @@ class TelescopeModel(ModelParameter):
|
|
|
42
40
|
self,
|
|
43
41
|
site,
|
|
44
42
|
telescope_name,
|
|
45
|
-
db_config,
|
|
46
43
|
model_version,
|
|
47
44
|
label=None,
|
|
48
45
|
overwrite_model_parameters=None,
|
|
@@ -52,7 +49,6 @@ class TelescopeModel(ModelParameter):
|
|
|
52
49
|
super().__init__(
|
|
53
50
|
site=site,
|
|
54
51
|
array_element_name=telescope_name,
|
|
55
|
-
db_config=db_config,
|
|
56
52
|
model_version=model_version,
|
|
57
53
|
label=label,
|
|
58
54
|
overwrite_model_parameters=overwrite_model_parameters,
|
|
@@ -326,13 +322,12 @@ class TelescopeModel(ModelParameter):
|
|
|
326
322
|
average_curve: astropy.table.Table
|
|
327
323
|
Instance of astropy.table.Table with the averaged curve.
|
|
328
324
|
"""
|
|
329
|
-
weights = [
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
)
|
|
325
|
+
weights = [
|
|
326
|
+
incidence_angle_dist["Fraction"][
|
|
327
|
+
np.nanargmin(np.abs(angle_now - incidence_angle_dist["Incidence angle"].value))
|
|
328
|
+
]
|
|
329
|
+
for angle_now in curves["Angle"]
|
|
330
|
+
]
|
|
336
331
|
|
|
337
332
|
return Table(
|
|
338
333
|
[curves["Wavelength"], np.average(curves["z"], weights=weights, axis=0)],
|
|
@@ -10,13 +10,13 @@ from astropy.table import Column, Table
|
|
|
10
10
|
from simtools.data_model.metadata_collector import MetadataCollector
|
|
11
11
|
from simtools.io import ascii_handler, io_handler
|
|
12
12
|
from simtools.layout.array_layout_utils import get_array_elements_from_db_for_layouts
|
|
13
|
-
from simtools.
|
|
13
|
+
from simtools.sim_events.histograms import EventDataHistograms
|
|
14
14
|
from simtools.visualization import plot_simtel_event_histograms
|
|
15
15
|
|
|
16
16
|
_logger = logging.getLogger(__name__)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def generate_corsika_limits_grid(args_dict
|
|
19
|
+
def generate_corsika_limits_grid(args_dict):
|
|
20
20
|
"""
|
|
21
21
|
Generate CORSIKA limits.
|
|
22
22
|
|
|
@@ -24,15 +24,12 @@ def generate_corsika_limits_grid(args_dict, db_config=None):
|
|
|
24
24
|
----------
|
|
25
25
|
args_dict : dict
|
|
26
26
|
Dictionary containing command line arguments.
|
|
27
|
-
db_config : dict, optional
|
|
28
|
-
Database configuration dictionary.
|
|
29
27
|
"""
|
|
30
28
|
if args_dict.get("array_layout_name"):
|
|
31
29
|
telescope_configs = get_array_elements_from_db_for_layouts(
|
|
32
30
|
args_dict["array_layout_name"],
|
|
33
31
|
args_dict.get("site"),
|
|
34
32
|
args_dict.get("model_version"),
|
|
35
|
-
db_config,
|
|
36
33
|
)
|
|
37
34
|
else:
|
|
38
35
|
telescope_configs = ascii_handler.collect_data_from_file(args_dict["telescope_ids"])[
|
|
@@ -81,9 +78,7 @@ def _process_file(file_path, array_name, telescope_ids, loss_fraction, plot_hist
|
|
|
81
78
|
dict
|
|
82
79
|
Dictionary containing the computed limits and metadata.
|
|
83
80
|
"""
|
|
84
|
-
histograms =
|
|
85
|
-
file_path, array_name=array_name, telescope_list=telescope_ids
|
|
86
|
-
)
|
|
81
|
+
histograms = EventDataHistograms(file_path, array_name=array_name, telescope_list=telescope_ids)
|
|
87
82
|
histograms.fill()
|
|
88
83
|
|
|
89
84
|
limits = {
|
|
@@ -257,7 +252,7 @@ def compute_lower_energy_limit(histograms, loss_fraction):
|
|
|
257
252
|
|
|
258
253
|
Parameters
|
|
259
254
|
----------
|
|
260
|
-
histograms :
|
|
255
|
+
histograms : EventDataHistograms
|
|
261
256
|
Histograms.
|
|
262
257
|
loss_fraction : float
|
|
263
258
|
Fraction of events to be lost.
|
|
@@ -299,7 +294,7 @@ def compute_upper_radius_limit(histograms, loss_fraction):
|
|
|
299
294
|
|
|
300
295
|
Parameters
|
|
301
296
|
----------
|
|
302
|
-
histograms :
|
|
297
|
+
histograms : EventDataHistograms
|
|
303
298
|
Histograms.
|
|
304
299
|
loss_fraction : float
|
|
305
300
|
Fraction of events to be lost.
|
|
@@ -337,7 +332,7 @@ def compute_viewcone(histograms, loss_fraction):
|
|
|
337
332
|
|
|
338
333
|
Parameters
|
|
339
334
|
----------
|
|
340
|
-
histograms :
|
|
335
|
+
histograms : EventDataHistograms
|
|
341
336
|
Histograms.
|
|
342
337
|
loss_fraction : float
|
|
343
338
|
Fraction of events to be lost.
|
|
@@ -214,17 +214,15 @@ class InterpolationHandler:
|
|
|
214
214
|
np.ndarray
|
|
215
215
|
Reduced production grid points.
|
|
216
216
|
"""
|
|
217
|
-
production_grid_points = [
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
[
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
]
|
|
227
|
-
)
|
|
217
|
+
production_grid_points = [
|
|
218
|
+
[
|
|
219
|
+
point["azimuth"]["value"],
|
|
220
|
+
point["zenith_angle"]["value"],
|
|
221
|
+
point["nsb"]["value"],
|
|
222
|
+
point["offset"]["value"],
|
|
223
|
+
]
|
|
224
|
+
for point in self.grid_points_production
|
|
225
|
+
]
|
|
228
226
|
|
|
229
227
|
production_grid_points = np.array(production_grid_points)
|
|
230
228
|
|
|
@@ -280,11 +278,13 @@ class InterpolationHandler:
|
|
|
280
278
|
reduced_production_grid_points = self._prepare_production_grid_points()
|
|
281
279
|
energy_grid = self.energy_grids[0] if self.energy_grids else []
|
|
282
280
|
|
|
283
|
-
energy_query_grid = [
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
281
|
+
energy_query_grid = [
|
|
282
|
+
[
|
|
283
|
+
np.hstack([energy.to(u.TeV).value, grid_point])
|
|
284
|
+
for energy in energy_grid
|
|
285
|
+
for grid_point in reduced_production_grid_points
|
|
286
|
+
]
|
|
287
|
+
]
|
|
288
288
|
energy_query_grid = np.array(energy_query_grid)
|
|
289
289
|
|
|
290
290
|
self._logger.debug(f"Grid points with energy shape: {grid_points_energy.shape}")
|
|
@@ -15,6 +15,7 @@ from pathlib import Path
|
|
|
15
15
|
import astropy.units as u
|
|
16
16
|
from astropy.table import QTable
|
|
17
17
|
|
|
18
|
+
from simtools import settings
|
|
18
19
|
from simtools.data_model.metadata_collector import MetadataCollector
|
|
19
20
|
from simtools.model.model_utils import initialize_simulation_models
|
|
20
21
|
|
|
@@ -24,10 +25,6 @@ class IncidentAnglesCalculator:
|
|
|
24
25
|
|
|
25
26
|
Parameters
|
|
26
27
|
----------
|
|
27
|
-
simtel_path : str or pathlib.Path
|
|
28
|
-
Path to the sim_telarray installation directory (containing ``sim_telarray/bin``).
|
|
29
|
-
db_config : dict
|
|
30
|
-
Database configuration passed to ``initialize_simulation_models``.
|
|
31
28
|
config_data : dict
|
|
32
29
|
Simulation configuration (e.g. ``site``, ``telescope``, ``model_version``,
|
|
33
30
|
``off_axis_angle``, ``source_distance``, ``number_of_photons``).
|
|
@@ -48,15 +45,12 @@ class IncidentAnglesCalculator:
|
|
|
48
45
|
|
|
49
46
|
def __init__(
|
|
50
47
|
self,
|
|
51
|
-
simtel_path,
|
|
52
|
-
db_config,
|
|
53
48
|
config_data,
|
|
54
49
|
output_dir,
|
|
55
50
|
label=None,
|
|
56
51
|
):
|
|
57
52
|
self.logger = logging.getLogger(__name__)
|
|
58
53
|
|
|
59
|
-
self._simtel_path = Path(simtel_path)
|
|
60
54
|
self.config_data = config_data
|
|
61
55
|
self.output_dir = Path(output_dir)
|
|
62
56
|
self.label = label or f"incident_angles_{config_data['telescope']}"
|
|
@@ -82,7 +76,6 @@ class IncidentAnglesCalculator:
|
|
|
82
76
|
)
|
|
83
77
|
self.telescope_model, self.site_model, _ = initialize_simulation_models(
|
|
84
78
|
label=self.label,
|
|
85
|
-
db_config=db_config,
|
|
86
79
|
site=config_data["site"],
|
|
87
80
|
telescope_name=config_data["telescope"],
|
|
88
81
|
model_version=config_data["model_version"],
|
|
@@ -216,8 +209,6 @@ class IncidentAnglesCalculator:
|
|
|
216
209
|
Path to the generated shell script.
|
|
217
210
|
"""
|
|
218
211
|
script_path = self.scripts_dir / f"run_incident_angles_{self._label_suffix()}.sh"
|
|
219
|
-
simtel_bin = self._simtel_path / "sim_telarray/bin/sim_telarray_debug_trace"
|
|
220
|
-
corsika_dummy = self._simtel_path / "sim_telarray/run9991.corsika.gz"
|
|
221
212
|
|
|
222
213
|
theta = self.ZENITH_ANGLE_DEG
|
|
223
214
|
off = float(self.config_data["off_axis_angle"].to_value(u.deg))
|
|
@@ -258,7 +249,10 @@ class IncidentAnglesCalculator:
|
|
|
258
249
|
cfg("camera_filter", "none"),
|
|
259
250
|
]
|
|
260
251
|
|
|
261
|
-
command =
|
|
252
|
+
command = (
|
|
253
|
+
f"{settings.config.sim_telarray_exe_debug_trace} {' '.join(opts)} "
|
|
254
|
+
f"{settings.config.corsika_dummy_file}"
|
|
255
|
+
)
|
|
262
256
|
with script_path.open("w", encoding="utf-8") as sh:
|
|
263
257
|
sh.write("#!/usr/bin/env bash\n\n")
|
|
264
258
|
sh.write("set -e\nset -o pipefail\n\n")
|
|
@@ -28,17 +28,15 @@ class MirrorPanelPSF:
|
|
|
28
28
|
Application label.
|
|
29
29
|
args_dict: dict
|
|
30
30
|
Dictionary with input arguments.
|
|
31
|
-
db_config:
|
|
32
|
-
Dictionary with database configuration.
|
|
33
31
|
"""
|
|
34
32
|
|
|
35
|
-
def __init__(self, label, args_dict
|
|
33
|
+
def __init__(self, label, args_dict):
|
|
36
34
|
"""Initialize the MirrorPanelPSF class."""
|
|
37
35
|
self._logger = logging.getLogger(__name__)
|
|
38
36
|
self._logger.debug("Initializing MirrorPanelPSF")
|
|
39
37
|
|
|
40
38
|
self.args_dict = args_dict
|
|
41
|
-
self.telescope_model, self.site_model = self._define_telescope_model(label
|
|
39
|
+
self.telescope_model, self.site_model = self._define_telescope_model(label)
|
|
42
40
|
|
|
43
41
|
if self.args_dict["test"]:
|
|
44
42
|
self.args_dict["number_of_mirrors_to_test"] = 2
|
|
@@ -56,7 +54,7 @@ class MirrorPanelPSF:
|
|
|
56
54
|
self.results_mean = []
|
|
57
55
|
self.results_sig = []
|
|
58
56
|
|
|
59
|
-
def _define_telescope_model(self, label
|
|
57
|
+
def _define_telescope_model(self, label):
|
|
60
58
|
"""
|
|
61
59
|
Define telescope model.
|
|
62
60
|
|
|
@@ -72,7 +70,6 @@ class MirrorPanelPSF:
|
|
|
72
70
|
"""
|
|
73
71
|
tel_model, site_model, _ = initialize_simulation_models(
|
|
74
72
|
label=label,
|
|
75
|
-
db_config=db_config,
|
|
76
73
|
site=self.args_dict["site"],
|
|
77
74
|
telescope_name=self.args_dict["telescope"],
|
|
78
75
|
model_version=self.args_dict["model_version"],
|
|
@@ -225,7 +222,6 @@ class MirrorPanelPSF:
|
|
|
225
222
|
ray = RayTracing(
|
|
226
223
|
telescope_model=self.telescope_model,
|
|
227
224
|
site_model=self.site_model,
|
|
228
|
-
simtel_path=self.args_dict.get("simtel_path", None),
|
|
229
225
|
single_mirror_mode=True,
|
|
230
226
|
mirror_numbers=(
|
|
231
227
|
list(range(1, self.args_dict["number_of_mirrors_to_test"] + 1))
|
|
@@ -17,6 +17,7 @@ import astropy.units as u
|
|
|
17
17
|
import matplotlib.pyplot as plt
|
|
18
18
|
import numpy as np
|
|
19
19
|
|
|
20
|
+
from simtools import settings
|
|
20
21
|
from simtools.utils.general import collect_kwargs, set_default_kwargs
|
|
21
22
|
|
|
22
23
|
|
|
@@ -36,8 +37,6 @@ class PSFImage:
|
|
|
36
37
|
Scatter area of all photons in cm^2. If not given, effective area cannot be computed.
|
|
37
38
|
containment_fraction: float
|
|
38
39
|
Containment fraction for PSF calculation.
|
|
39
|
-
simtel_path: str
|
|
40
|
-
Path to sim_telarray installation.
|
|
41
40
|
"""
|
|
42
41
|
|
|
43
42
|
__PSF_RADIUS = "Radius [cm]"
|
|
@@ -48,11 +47,9 @@ class PSFImage:
|
|
|
48
47
|
focal_length=None,
|
|
49
48
|
total_scattered_area=None,
|
|
50
49
|
containment_fraction=None,
|
|
51
|
-
simtel_path=None,
|
|
52
50
|
):
|
|
53
51
|
"""Initialize PSFImage class."""
|
|
54
52
|
self._logger = logging.getLogger(__name__)
|
|
55
|
-
self.simtel_path = simtel_path
|
|
56
53
|
|
|
57
54
|
self._total_photons = None
|
|
58
55
|
self._number_of_detected_photons = None
|
|
@@ -97,20 +94,23 @@ class PSFImage:
|
|
|
97
94
|
Name of sim_telarray file with photon list.
|
|
98
95
|
"""
|
|
99
96
|
try:
|
|
100
|
-
|
|
97
|
+
with subprocess.Popen(
|
|
101
98
|
shlex.split(
|
|
102
|
-
f"{
|
|
99
|
+
f"{settings.config.sim_telarray_path}/bin/rx "
|
|
100
|
+
f"-f {self._containment_fraction:.2f} -v"
|
|
103
101
|
),
|
|
104
102
|
stdin=subprocess.PIPE,
|
|
105
103
|
stdout=subprocess.PIPE,
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
104
|
+
) as rx_process:
|
|
105
|
+
with gzip.open(photon_file, "rb") as _stdin:
|
|
106
|
+
with rx_process.stdin:
|
|
107
|
+
shutil.copyfileobj(_stdin, rx_process.stdin)
|
|
108
|
+
try:
|
|
109
|
+
rx_output = rx_process.communicate()[0].splitlines()[-1:][0].split()
|
|
110
|
+
except IndexError as e:
|
|
111
|
+
raise IndexError(
|
|
112
|
+
f"Unexpected output format from rx: {rx_process}"
|
|
113
|
+
) from e
|
|
114
114
|
except FileNotFoundError as e:
|
|
115
115
|
raise FileNotFoundError(f"Photon list file not found: {photon_file}") from e
|
|
116
116
|
|
|
@@ -384,7 +384,6 @@ class PSFImage:
|
|
|
384
384
|
if radius is not found (found_radius is False)
|
|
385
385
|
"""
|
|
386
386
|
r0, r1 = rad_min, rad_min + dr
|
|
387
|
-
s0, s1 = 0, 0
|
|
388
387
|
found_radius = False
|
|
389
388
|
while not found_radius:
|
|
390
389
|
s0, s1 = self._sum_photons_in_radius(r0), self._sum_photons_in_radius(r1)
|
|
@@ -497,10 +496,10 @@ class PSFImage:
|
|
|
497
496
|
radius_all = radius.to(u.cm).value if isinstance(radius, u.Quantity) else radius
|
|
498
497
|
else:
|
|
499
498
|
radius_all = list(np.linspace(0, 1.6 * self.get_psf(0.8), 30))
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
499
|
+
intensity = [
|
|
500
|
+
self._sum_photons_in_radius(rad) / self._number_of_detected_photons
|
|
501
|
+
for rad in radius_all
|
|
502
|
+
]
|
|
504
503
|
d_type = {
|
|
505
504
|
"names": (self.__PSF_RADIUS, self.__PSF_CUMULATIVE),
|
|
506
505
|
"formats": ("f8", "f8"),
|
|
@@ -516,18 +515,21 @@ class PSFImage:
|
|
|
516
515
|
|
|
517
516
|
Parameters
|
|
518
517
|
----------
|
|
518
|
+
file_name: str
|
|
519
|
+
Name of the file to save the plot to.
|
|
520
|
+
d80: float
|
|
521
|
+
d80 value to be marked in the plot (in cm).
|
|
519
522
|
**kwargs:
|
|
520
|
-
|
|
523
|
+
Customization of line plot (e.g., color, linestyle, linewidth).
|
|
521
524
|
"""
|
|
522
525
|
data = self.get_cumulative_data()
|
|
523
|
-
ax = plt.
|
|
524
|
-
plt.tight_layout(pad=1.5)
|
|
526
|
+
fig, ax = plt.subplots(constrained_layout=True)
|
|
525
527
|
ax.set_xlabel("Radius (cm)")
|
|
526
528
|
ax.set_ylabel("Contained light %")
|
|
527
|
-
|
|
528
|
-
|
|
529
|
+
ax.plot(data[self.__PSF_RADIUS], data[self.__PSF_CUMULATIVE], **kwargs)
|
|
530
|
+
ax.axvline(x=self.get_psf(0.8) / 2, color="b", linestyle="--", linewidth=1)
|
|
529
531
|
if d80 is not None:
|
|
530
|
-
|
|
532
|
+
ax.axvline(x=d80 / 2.0, color="r", linestyle="--", linewidth=1)
|
|
531
533
|
if file_name is not None:
|
|
532
|
-
|
|
533
|
-
plt.close()
|
|
534
|
+
fig.savefig(file_name)
|
|
535
|
+
plt.close(fig)
|