gammasimtools 0.26.0__py3-none-any.whl → 0.27.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.26.0.dist-info → gammasimtools-0.27.0.dist-info}/METADATA +5 -1
- {gammasimtools-0.26.0.dist-info → gammasimtools-0.27.0.dist-info}/RECORD +70 -66
- {gammasimtools-0.26.0.dist-info → gammasimtools-0.27.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.26.0.dist-info → gammasimtools-0.27.0.dist-info}/entry_points.txt +1 -1
- simtools/_version.py +2 -2
- simtools/applications/convert_geo_coordinates_of_array_elements.py +2 -1
- simtools/applications/db_get_array_layouts_from_db.py +1 -1
- simtools/applications/{calculate_incident_angles.py → derive_incident_angle.py} +16 -16
- simtools/applications/derive_mirror_rnda.py +111 -177
- simtools/applications/generate_corsika_histograms.py +38 -1
- simtools/applications/generate_regular_arrays.py +73 -36
- simtools/applications/simulate_flasher.py +3 -13
- simtools/applications/simulate_illuminator.py +2 -10
- simtools/applications/simulate_pedestals.py +1 -1
- simtools/applications/simulate_prod.py +8 -7
- simtools/applications/submit_data_from_external.py +2 -1
- simtools/applications/validate_camera_efficiency.py +28 -27
- simtools/applications/validate_cumulative_psf.py +1 -3
- simtools/applications/validate_optics.py +2 -1
- simtools/atmosphere.py +83 -0
- simtools/camera/camera_efficiency.py +171 -48
- simtools/camera/single_photon_electron_spectrum.py +6 -6
- simtools/configuration/commandline_parser.py +47 -9
- simtools/constants.py +5 -0
- simtools/corsika/corsika_config.py +88 -185
- simtools/corsika/corsika_histograms.py +246 -69
- simtools/data_model/model_data_writer.py +46 -49
- simtools/data_model/schema.py +2 -0
- simtools/db/db_handler.py +4 -2
- simtools/db/mongo_db.py +2 -2
- simtools/io/ascii_handler.py +51 -3
- simtools/io/io_handler.py +23 -12
- simtools/job_execution/job_manager.py +154 -79
- simtools/job_execution/process_pool.py +137 -0
- simtools/layout/array_layout.py +0 -1
- simtools/layout/array_layout_utils.py +143 -21
- simtools/model/array_model.py +22 -50
- simtools/model/calibration_model.py +4 -4
- simtools/model/model_parameter.py +123 -73
- simtools/model/model_utils.py +40 -1
- simtools/model/site_model.py +4 -4
- simtools/model/telescope_model.py +4 -5
- simtools/ray_tracing/incident_angles.py +87 -6
- simtools/ray_tracing/mirror_panel_psf.py +337 -217
- simtools/ray_tracing/psf_analysis.py +57 -42
- simtools/ray_tracing/psf_parameter_optimisation.py +3 -2
- simtools/ray_tracing/ray_tracing.py +37 -10
- simtools/runners/corsika_runner.py +52 -191
- simtools/runners/corsika_simtel_runner.py +74 -100
- simtools/runners/runner_services.py +214 -213
- simtools/runners/simtel_runner.py +27 -155
- simtools/runners/simtools_runner.py +9 -69
- simtools/schemas/application_workflow.metaschema.yml +8 -0
- simtools/settings.py +19 -0
- simtools/simtel/simtel_config_writer.py +0 -55
- simtools/simtel/simtel_seeds.py +184 -0
- simtools/simtel/simulator_array.py +115 -103
- simtools/simtel/simulator_camera_efficiency.py +66 -42
- simtools/simtel/simulator_light_emission.py +110 -123
- simtools/simtel/simulator_ray_tracing.py +78 -63
- simtools/simulator.py +135 -346
- simtools/testing/sim_telarray_metadata.py +13 -11
- simtools/testing/validate_output.py +87 -19
- simtools/utils/general.py +6 -17
- simtools/utils/random.py +36 -0
- simtools/visualization/plot_corsika_histograms.py +2 -0
- simtools/visualization/plot_incident_angles.py +48 -1
- simtools/visualization/plot_psf.py +160 -18
- {gammasimtools-0.26.0.dist-info → gammasimtools-0.27.0.dist-info}/licenses/LICENSE +0 -0
- {gammasimtools-0.26.0.dist-info → gammasimtools-0.27.0.dist-info}/top_level.txt +0 -0
simtools/model/model_utils.py
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
import math
|
|
5
5
|
|
|
6
|
+
from simtools import settings
|
|
7
|
+
from simtools.data_model import schema
|
|
8
|
+
from simtools.io import ascii_handler
|
|
6
9
|
from simtools.model.calibration_model import CalibrationModel
|
|
7
10
|
from simtools.model.site_model import SiteModel
|
|
8
11
|
from simtools.model.telescope_model import TelescopeModel
|
|
@@ -10,7 +13,11 @@ from simtools.utils import names
|
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
def initialize_simulation_models(
|
|
13
|
-
label,
|
|
16
|
+
label,
|
|
17
|
+
model_version,
|
|
18
|
+
site,
|
|
19
|
+
telescope_name,
|
|
20
|
+
calibration_device_name=None,
|
|
14
21
|
):
|
|
15
22
|
"""
|
|
16
23
|
Initialize simulation models for a single telescope, site, and calibration device model.
|
|
@@ -33,16 +40,20 @@ def initialize_simulation_models(
|
|
|
33
40
|
Tuple
|
|
34
41
|
Tuple containing the telescope site, (optional) calibration device model.
|
|
35
42
|
"""
|
|
43
|
+
overwrite_model_parameter_dict = read_overwrite_model_parameter_dict()
|
|
44
|
+
|
|
36
45
|
tel_model = TelescopeModel(
|
|
37
46
|
site=site,
|
|
38
47
|
telescope_name=telescope_name,
|
|
39
48
|
model_version=model_version,
|
|
40
49
|
label=label,
|
|
50
|
+
overwrite_model_parameter_dict=overwrite_model_parameter_dict,
|
|
41
51
|
)
|
|
42
52
|
site_model = SiteModel(
|
|
43
53
|
site=site,
|
|
44
54
|
model_version=model_version,
|
|
45
55
|
label=label,
|
|
56
|
+
overwrite_model_parameter_dict=overwrite_model_parameter_dict,
|
|
46
57
|
)
|
|
47
58
|
if calibration_device_name is not None:
|
|
48
59
|
calibration_model = CalibrationModel(
|
|
@@ -50,6 +61,7 @@ def initialize_simulation_models(
|
|
|
50
61
|
calibration_device_model_name=calibration_device_name,
|
|
51
62
|
model_version=model_version,
|
|
52
63
|
label=label,
|
|
64
|
+
overwrite_model_parameter_dict=overwrite_model_parameter_dict,
|
|
53
65
|
)
|
|
54
66
|
else:
|
|
55
67
|
calibration_model = None
|
|
@@ -58,6 +70,33 @@ def initialize_simulation_models(
|
|
|
58
70
|
return tel_model, site_model, calibration_model
|
|
59
71
|
|
|
60
72
|
|
|
73
|
+
def read_overwrite_model_parameter_dict(overwrite_model_parameters=None):
|
|
74
|
+
"""
|
|
75
|
+
Read overwrite model parameters dictionary from file.
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
overwrite_model_parameters: str, optional
|
|
80
|
+
File name with overwrite model parameters.
|
|
81
|
+
|
|
82
|
+
Returns
|
|
83
|
+
-------
|
|
84
|
+
dict
|
|
85
|
+
Dictionary with model parameters to overwrite.
|
|
86
|
+
"""
|
|
87
|
+
overwrite_model_parameter_dict = {}
|
|
88
|
+
overwrite_model_parameters = overwrite_model_parameters or settings.config.args.get(
|
|
89
|
+
"overwrite_model_parameters"
|
|
90
|
+
)
|
|
91
|
+
if overwrite_model_parameters is not None:
|
|
92
|
+
overwrite_model_parameter_dict = schema.validate_dict_using_schema(
|
|
93
|
+
data=ascii_handler.collect_data_from_file(file_name=overwrite_model_parameters),
|
|
94
|
+
schema_file="simulation_models_info.schema.yml",
|
|
95
|
+
).get("changes", {})
|
|
96
|
+
|
|
97
|
+
return overwrite_model_parameter_dict
|
|
98
|
+
|
|
99
|
+
|
|
61
100
|
def compute_telescope_transmission(pars: list[float], off_axis: float) -> float:
|
|
62
101
|
"""
|
|
63
102
|
Compute telescope transmission (0 < T < 1) for a given off-axis angle.
|
simtools/model/site_model.py
CHANGED
|
@@ -30,8 +30,8 @@ class SiteModel(ModelParameter):
|
|
|
30
30
|
Model version or list of model versions (in which case only the first one is used).
|
|
31
31
|
label: str, optional
|
|
32
32
|
Instance label.
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
overwrite_model_parameter_dict: dict, optional
|
|
34
|
+
Dictionary to overwrite model parameters from DB with provided values.
|
|
35
35
|
ignore_software_version: bool, optional
|
|
36
36
|
If True, ignore software version checks for deprecated parameters.
|
|
37
37
|
"""
|
|
@@ -41,7 +41,7 @@ class SiteModel(ModelParameter):
|
|
|
41
41
|
site,
|
|
42
42
|
model_version,
|
|
43
43
|
label=None,
|
|
44
|
-
|
|
44
|
+
overwrite_model_parameter_dict=None,
|
|
45
45
|
ignore_software_version=False,
|
|
46
46
|
):
|
|
47
47
|
"""Initialize SiteModel."""
|
|
@@ -52,7 +52,7 @@ class SiteModel(ModelParameter):
|
|
|
52
52
|
model_version=model_version,
|
|
53
53
|
label=label,
|
|
54
54
|
collection="sites",
|
|
55
|
-
|
|
55
|
+
overwrite_model_parameter_dict=overwrite_model_parameter_dict,
|
|
56
56
|
ignore_software_version=ignore_software_version,
|
|
57
57
|
)
|
|
58
58
|
|
|
@@ -30,8 +30,8 @@ class TelescopeModel(ModelParameter):
|
|
|
30
30
|
Model version.
|
|
31
31
|
label: str, optional
|
|
32
32
|
Instance label.
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
overwrite_model_parameter_dict: dict, optional
|
|
34
|
+
Dictionary to overwrite model parameters from DB with provided values.
|
|
35
35
|
ignore_software_version: bool, optional
|
|
36
36
|
If True, ignore software version checks for deprecated parameters.
|
|
37
37
|
"""
|
|
@@ -42,7 +42,7 @@ class TelescopeModel(ModelParameter):
|
|
|
42
42
|
telescope_name,
|
|
43
43
|
model_version,
|
|
44
44
|
label=None,
|
|
45
|
-
|
|
45
|
+
overwrite_model_parameter_dict=None,
|
|
46
46
|
ignore_software_version=False,
|
|
47
47
|
):
|
|
48
48
|
"""Initialize TelescopeModel."""
|
|
@@ -51,12 +51,11 @@ class TelescopeModel(ModelParameter):
|
|
|
51
51
|
array_element_name=telescope_name,
|
|
52
52
|
model_version=model_version,
|
|
53
53
|
label=label,
|
|
54
|
-
|
|
54
|
+
overwrite_model_parameter_dict=overwrite_model_parameter_dict,
|
|
55
55
|
ignore_software_version=ignore_software_version,
|
|
56
56
|
)
|
|
57
57
|
|
|
58
58
|
self._logger = logging.getLogger(__name__)
|
|
59
|
-
self._logger.debug("Init TelescopeModel %s %s", site, telescope_name)
|
|
60
59
|
|
|
61
60
|
self._single_mirror_list_file_paths = None
|
|
62
61
|
self._mirrors = None
|
|
@@ -9,14 +9,16 @@ Angle of incidence on to secondary mirror [deg] (if available).
|
|
|
9
9
|
import logging
|
|
10
10
|
import math
|
|
11
11
|
import re
|
|
12
|
-
import subprocess
|
|
13
12
|
from pathlib import Path
|
|
14
13
|
|
|
15
14
|
import astropy.units as u
|
|
16
|
-
|
|
15
|
+
import numpy as np
|
|
16
|
+
from astropy.table import QTable, vstack
|
|
17
17
|
|
|
18
18
|
from simtools import settings
|
|
19
19
|
from simtools.data_model.metadata_collector import MetadataCollector
|
|
20
|
+
from simtools.data_model.model_data_writer import ModelDataWriter
|
|
21
|
+
from simtools.job_execution import job_manager
|
|
20
22
|
from simtools.model.model_utils import initialize_simulation_models
|
|
21
23
|
|
|
22
24
|
|
|
@@ -273,8 +275,8 @@ class IncidentAnglesCalculator:
|
|
|
273
275
|
"""
|
|
274
276
|
self.logger.info("Executing %s (logging to %s)", script_path, log_file)
|
|
275
277
|
try:
|
|
276
|
-
|
|
277
|
-
except
|
|
278
|
+
job_manager.submit(script_path)
|
|
279
|
+
except job_manager.JobExecutionError as exc:
|
|
278
280
|
raise RuntimeError(f"Incident angles run failed, see log: {log_file}") from exc
|
|
279
281
|
|
|
280
282
|
def _compute_incidence_angles_from_imaging_list(self, photons_file):
|
|
@@ -283,7 +285,7 @@ class IncidentAnglesCalculator:
|
|
|
283
285
|
Column positions may differ between telescope types and sim_telarray versions.
|
|
284
286
|
Header lines (``# Column N: ...``) are parsed to find indices; otherwise
|
|
285
287
|
legacy positions (1-based) are used: focal=26, primary=32, secondary=36,
|
|
286
|
-
primary X/Y = 29/30, secondary X/Y
|
|
288
|
+
primary X/Y = 29/30, secondary X/Y=33/34.
|
|
287
289
|
|
|
288
290
|
Parameters
|
|
289
291
|
----------
|
|
@@ -692,9 +694,88 @@ class IncidentAnglesCalculator:
|
|
|
692
694
|
self.logger.warning("No results to save")
|
|
693
695
|
return
|
|
694
696
|
output_file = self.results_dir / f"incident_angles_{self._label_suffix()}.ecsv"
|
|
695
|
-
|
|
697
|
+
|
|
698
|
+
data = self.results["angle_incidence_focal"].to(u.deg).value
|
|
699
|
+
bin_centers, hist = self._calculate_histogram(data, bins=1000)
|
|
700
|
+
|
|
701
|
+
output_table = QTable()
|
|
702
|
+
output_table["Incidence angle"] = bin_centers * u.deg
|
|
703
|
+
output_table["Fraction"] = hist
|
|
704
|
+
|
|
705
|
+
output_table.write(output_file, format="ascii.ecsv", overwrite=True)
|
|
696
706
|
|
|
697
707
|
MetadataCollector.dump(
|
|
698
708
|
args_dict=self.config_data,
|
|
699
709
|
output_file=output_file.with_suffix(".yml"),
|
|
700
710
|
)
|
|
711
|
+
|
|
712
|
+
def save_model_parameters(self, results_by_offset):
|
|
713
|
+
"""
|
|
714
|
+
Write model parameters dictionary (json) + astropy table with incident angles.
|
|
715
|
+
|
|
716
|
+
Parameters
|
|
717
|
+
----------
|
|
718
|
+
results_by_offset : dict
|
|
719
|
+
Dictionary with results for each offset.
|
|
720
|
+
"""
|
|
721
|
+
# Combine results from all offsets
|
|
722
|
+
tables = [res for res in results_by_offset.values() if res is not None and len(res) > 0]
|
|
723
|
+
if not tables:
|
|
724
|
+
self.logger.warning("No results to write model parameters.")
|
|
725
|
+
return
|
|
726
|
+
|
|
727
|
+
combined_table = vstack(tables)
|
|
728
|
+
|
|
729
|
+
parameter_mapping = {
|
|
730
|
+
"camera_filter_incidence_angle": "angle_incidence_focal",
|
|
731
|
+
"primary_mirror_incidence_angle": "angle_incidence_primary",
|
|
732
|
+
"secondary_mirror_incidence_angle": "angle_incidence_secondary",
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
for param_name, col_name in parameter_mapping.items():
|
|
736
|
+
if col_name not in combined_table.colnames:
|
|
737
|
+
continue
|
|
738
|
+
|
|
739
|
+
data = combined_table[col_name].to(u.deg).value
|
|
740
|
+
# Create histogram
|
|
741
|
+
bin_centers, hist = self._calculate_histogram(data, bins=100)
|
|
742
|
+
|
|
743
|
+
table = QTable()
|
|
744
|
+
table["Incidence angle"] = bin_centers * u.deg
|
|
745
|
+
table["Fraction"] = hist
|
|
746
|
+
|
|
747
|
+
writer = ModelDataWriter(output_file=self.output_dir / f"{param_name}.ecsv")
|
|
748
|
+
writer.write(
|
|
749
|
+
product_data=table,
|
|
750
|
+
metadata=MetadataCollector(args_dict=self.config_data),
|
|
751
|
+
)
|
|
752
|
+
|
|
753
|
+
ModelDataWriter.dump_model_parameter(
|
|
754
|
+
parameter_name=param_name,
|
|
755
|
+
value=f"{param_name}.ecsv",
|
|
756
|
+
instrument=self.config_data["telescope"],
|
|
757
|
+
parameter_version=self.config_data["model_version"],
|
|
758
|
+
output_file=f"{param_name}.json",
|
|
759
|
+
output_path=self.output_dir,
|
|
760
|
+
metadata_input_dict=self.config_data,
|
|
761
|
+
)
|
|
762
|
+
|
|
763
|
+
def _calculate_histogram(self, data, bins=100):
|
|
764
|
+
"""
|
|
765
|
+
Calculate normalized histogram (density).
|
|
766
|
+
|
|
767
|
+
Parameters
|
|
768
|
+
----------
|
|
769
|
+
data : numpy.ndarray
|
|
770
|
+
Data to calculate histogram for.
|
|
771
|
+
bins : int
|
|
772
|
+
Number of bins.
|
|
773
|
+
|
|
774
|
+
Returns
|
|
775
|
+
-------
|
|
776
|
+
tuple
|
|
777
|
+
Bin centers and histogram values (density).
|
|
778
|
+
"""
|
|
779
|
+
hist, bin_edges = np.histogram(data, bins=bins, density=True)
|
|
780
|
+
bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2
|
|
781
|
+
return bin_centers, hist
|