gammasimtools 0.25.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.25.0.dist-info → gammasimtools-0.27.0.dist-info}/METADATA +6 -1
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/RECORD +135 -130
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/entry_points.txt +3 -2
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +2 -2
- simtools/application_control.py +35 -7
- simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
- 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 +3 -7
- 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/{calculate_incident_angles.py → derive_incident_angle.py} +16 -18
- simtools/applications/derive_mirror_rnda.py +112 -180
- 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 +79 -229
- simtools/applications/generate_regular_arrays.py +76 -69
- 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 +3 -15
- simtools/applications/simulate_illuminator.py +2 -11
- simtools/applications/simulate_pedestals.py +1 -5
- simtools/applications/simulate_prod.py +8 -11
- simtools/applications/simulate_prod_htcondor_generator.py +1 -1
- simtools/applications/submit_array_layouts.py +2 -4
- simtools/applications/submit_data_from_external.py +2 -1
- simtools/applications/submit_model_parameter_from_external.py +1 -3
- simtools/applications/validate_camera_efficiency.py +28 -28
- simtools/applications/validate_camera_fov.py +0 -1
- simtools/applications/validate_cumulative_psf.py +1 -5
- simtools/applications/validate_optics.py +2 -14
- simtools/atmosphere.py +83 -0
- simtools/camera/camera_efficiency.py +171 -53
- simtools/camera/single_photon_electron_spectrum.py +8 -7
- simtools/configuration/commandline_parser.py +82 -11
- simtools/configuration/configurator.py +6 -11
- simtools/constants.py +5 -0
- simtools/corsika/corsika_config.py +100 -202
- simtools/corsika/corsika_histograms.py +561 -1708
- 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 +59 -64
- simtools/data_model/schema.py +2 -0
- simtools/data_model/validate_data.py +1 -3
- simtools/db/db_handler.py +23 -10
- simtools/db/mongo_db.py +2 -2
- simtools/dependencies.py +81 -38
- simtools/io/ascii_handler.py +55 -5
- simtools/io/io_handler.py +23 -12
- simtools/io/table_handler.py +1 -1
- simtools/job_execution/job_manager.py +154 -79
- simtools/job_execution/process_pool.py +137 -0
- simtools/layout/array_layout.py +4 -13
- simtools/layout/array_layout_utils.py +348 -57
- simtools/model/array_model.py +23 -63
- simtools/model/calibration_model.py +4 -8
- simtools/model/legacy_model_parameter.py +134 -0
- simtools/model/model_parameter.py +147 -86
- simtools/model/model_utils.py +40 -6
- simtools/model/site_model.py +4 -8
- simtools/model/telescope_model.py +10 -16
- simtools/production_configuration/derive_corsika_limits.py +6 -11
- simtools/production_configuration/interpolation_handler.py +16 -16
- simtools/ray_tracing/incident_angles.py +92 -17
- simtools/ray_tracing/mirror_panel_psf.py +338 -222
- simtools/ray_tracing/psf_analysis.py +62 -48
- simtools/ray_tracing/psf_parameter_optimisation.py +3 -3
- simtools/ray_tracing/ray_tracing.py +43 -25
- simtools/reporting/docs_auto_report_generator.py +8 -13
- simtools/reporting/docs_read_parameters.py +2 -8
- simtools/runners/corsika_runner.py +52 -195
- simtools/runners/corsika_simtel_runner.py +77 -108
- simtools/runners/runner_services.py +214 -213
- simtools/runners/simtel_runner.py +27 -160
- simtools/runners/simtools_runner.py +11 -73
- simtools/schemas/application_workflow.metaschema.yml +8 -0
- simtools/settings.py +173 -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 -91
- simtools/simtel/simtel_seeds.py +184 -0
- simtools/simtel/simtel_table_reader.py +6 -4
- simtools/simtel/simulator_array.py +114 -109
- simtools/simtel/simulator_camera_efficiency.py +68 -46
- simtools/simtel/simulator_light_emission.py +164 -132
- simtools/simtel/simulator_ray_tracing.py +80 -71
- simtools/simulator.py +137 -355
- 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 +14 -12
- simtools/testing/validate_output.py +121 -42
- simtools/utils/general.py +43 -17
- simtools/utils/geometry.py +0 -77
- simtools/utils/names.py +5 -5
- simtools/utils/random.py +36 -0
- simtools/visualization/legend_handlers.py +7 -6
- simtools/visualization/plot_array_layout.py +91 -16
- simtools/visualization/plot_corsika_histograms.py +145 -605
- simtools/visualization/plot_incident_angles.py +48 -1
- simtools/visualization/plot_mirrors.py +1 -4
- simtools/visualization/plot_pixels.py +2 -4
- simtools/visualization/plot_psf.py +160 -19
- 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.27.0.dist-info}/top_level.txt +0 -0
|
@@ -7,9 +7,7 @@ Main functionalities are: computing centroids, psf containers etc.
|
|
|
7
7
|
|
|
8
8
|
import gzip
|
|
9
9
|
import logging
|
|
10
|
-
import
|
|
11
|
-
import shutil
|
|
12
|
-
import subprocess
|
|
10
|
+
import tempfile
|
|
13
11
|
from math import fabs, pi, sqrt
|
|
14
12
|
from pathlib import Path
|
|
15
13
|
|
|
@@ -17,6 +15,8 @@ import astropy.units as u
|
|
|
17
15
|
import matplotlib.pyplot as plt
|
|
18
16
|
import numpy as np
|
|
19
17
|
|
|
18
|
+
from simtools import settings
|
|
19
|
+
from simtools.job_execution import job_manager
|
|
20
20
|
from simtools.utils.general import collect_kwargs, set_default_kwargs
|
|
21
21
|
|
|
22
22
|
|
|
@@ -36,8 +36,6 @@ class PSFImage:
|
|
|
36
36
|
Scatter area of all photons in cm^2. If not given, effective area cannot be computed.
|
|
37
37
|
containment_fraction: float
|
|
38
38
|
Containment fraction for PSF calculation.
|
|
39
|
-
simtel_path: str
|
|
40
|
-
Path to sim_telarray installation.
|
|
41
39
|
"""
|
|
42
40
|
|
|
43
41
|
__PSF_RADIUS = "Radius [cm]"
|
|
@@ -48,11 +46,9 @@ class PSFImage:
|
|
|
48
46
|
focal_length=None,
|
|
49
47
|
total_scattered_area=None,
|
|
50
48
|
containment_fraction=None,
|
|
51
|
-
simtel_path=None,
|
|
52
49
|
):
|
|
53
50
|
"""Initialize PSFImage class."""
|
|
54
51
|
self._logger = logging.getLogger(__name__)
|
|
55
|
-
self.simtel_path = simtel_path
|
|
56
52
|
|
|
57
53
|
self._total_photons = None
|
|
58
54
|
self._number_of_detected_photons = None
|
|
@@ -96,33 +92,49 @@ class PSFImage:
|
|
|
96
92
|
photons_file: str
|
|
97
93
|
Name of sim_telarray file with photon list.
|
|
98
94
|
"""
|
|
95
|
+
rx_command = [
|
|
96
|
+
f"{settings.config.sim_telarray_path}/bin/rx",
|
|
97
|
+
"-f",
|
|
98
|
+
f"{self._containment_fraction:.2f}",
|
|
99
|
+
"-v",
|
|
100
|
+
]
|
|
101
|
+
|
|
99
102
|
try:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
103
|
+
with tempfile.NamedTemporaryFile(mode="wb", delete=False) as tmp_file:
|
|
104
|
+
with gzip.open(photon_file, "rb") as gz:
|
|
105
|
+
tmp_file.write(gz.read())
|
|
106
|
+
tmp_file_path = tmp_file.name
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
with open(tmp_file_path, "rb") as tmp_f:
|
|
110
|
+
result = job_manager.submit(rx_command, stdin=tmp_f)
|
|
111
|
+
|
|
112
|
+
data_lines = [
|
|
113
|
+
line.strip()
|
|
114
|
+
for line in result.stdout.strip().split("\n")
|
|
115
|
+
if line.strip() and not line.startswith("#")
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
if not data_lines:
|
|
119
|
+
raise IndexError("No data line found in RX output")
|
|
120
|
+
|
|
121
|
+
rx_output = data_lines[-1].split()
|
|
122
|
+
self.set_psf(
|
|
123
|
+
2 * float(rx_output[0]), fraction=self._containment_fraction, unit="cm"
|
|
124
|
+
)
|
|
125
|
+
self.centroid_x = float(rx_output[1])
|
|
126
|
+
self.centroid_y = float(rx_output[2])
|
|
127
|
+
self._effective_area = float(rx_output[5])
|
|
128
|
+
|
|
129
|
+
finally:
|
|
130
|
+
Path(tmp_file_path).unlink(missing_ok=True)
|
|
131
|
+
|
|
114
132
|
except FileNotFoundError as e:
|
|
115
133
|
raise FileNotFoundError(f"Photon list file not found: {photon_file}") from e
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
self.centroid_y = float(rx_output[2])
|
|
121
|
-
self._effective_area = float(rx_output[5])
|
|
122
|
-
except IndexError as e:
|
|
123
|
-
raise IndexError(f"Unexpected output format from rx: {rx_output}") from e
|
|
124
|
-
except ValueError as e:
|
|
125
|
-
raise ValueError(f"Invalid output format from rx: {rx_output}") from e
|
|
134
|
+
except (IndexError, ValueError) as e:
|
|
135
|
+
raise type(e)(
|
|
136
|
+
f"Invalid RX output format: {locals().get('rx_output', 'unknown')}"
|
|
137
|
+
) from e
|
|
126
138
|
|
|
127
139
|
def read_photon_list_from_simtel_file(self, photons_file):
|
|
128
140
|
"""
|
|
@@ -150,9 +162,9 @@ class PSFImage:
|
|
|
150
162
|
self._process_simtel_line(line)
|
|
151
163
|
|
|
152
164
|
if not self._is_photon_positions_ok():
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
165
|
+
raise RuntimeError(
|
|
166
|
+
f"Problems reading sim_telarray photons file {photons_file} - invalid data"
|
|
167
|
+
)
|
|
156
168
|
|
|
157
169
|
self.centroid_x = np.mean(self.photon_pos_x)
|
|
158
170
|
self.centroid_y = np.mean(self.photon_pos_y)
|
|
@@ -384,7 +396,6 @@ class PSFImage:
|
|
|
384
396
|
if radius is not found (found_radius is False)
|
|
385
397
|
"""
|
|
386
398
|
r0, r1 = rad_min, rad_min + dr
|
|
387
|
-
s0, s1 = 0, 0
|
|
388
399
|
found_radius = False
|
|
389
400
|
while not found_radius:
|
|
390
401
|
s0, s1 = self._sum_photons_in_radius(r0), self._sum_photons_in_radius(r1)
|
|
@@ -468,9 +479,10 @@ class PSFImage:
|
|
|
468
479
|
ax.hist2d(data["X"], data["Y"], **kwargs_for_image)
|
|
469
480
|
ax.set_aspect("equal", "datalim")
|
|
470
481
|
|
|
471
|
-
# PSF circle (
|
|
482
|
+
# PSF circle (containment fraction)
|
|
483
|
+
fraction = self._containment_fraction if self._containment_fraction is not None else 0.8
|
|
472
484
|
center = (0, 0) if centralized else (self.centroid_x, self.centroid_y)
|
|
473
|
-
circle = plt.Circle(center, self.get_psf(
|
|
485
|
+
circle = plt.Circle(center, self.get_psf(fraction) / 2, **kwargs_for_psf)
|
|
474
486
|
ax.add_artist(circle)
|
|
475
487
|
|
|
476
488
|
ax.axhline(0, color="k", linestyle="--", zorder=3, linewidth=0.5)
|
|
@@ -496,11 +508,12 @@ class PSFImage:
|
|
|
496
508
|
if radius is not None:
|
|
497
509
|
radius_all = radius.to(u.cm).value if isinstance(radius, u.Quantity) else radius
|
|
498
510
|
else:
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
intensity = [
|
|
502
|
-
|
|
503
|
-
|
|
511
|
+
fraction = self._containment_fraction if self._containment_fraction is not None else 0.8
|
|
512
|
+
radius_all = list(np.linspace(0, 1.6 * self.get_psf(fraction), 30))
|
|
513
|
+
intensity = [
|
|
514
|
+
self._sum_photons_in_radius(rad) / self._number_of_detected_photons
|
|
515
|
+
for rad in radius_all
|
|
516
|
+
]
|
|
504
517
|
d_type = {
|
|
505
518
|
"names": (self.__PSF_RADIUS, self.__PSF_CUMULATIVE),
|
|
506
519
|
"formats": ("f8", "f8"),
|
|
@@ -511,15 +524,15 @@ class PSFImage:
|
|
|
511
524
|
|
|
512
525
|
return result
|
|
513
526
|
|
|
514
|
-
def plot_cumulative(self, file_name=None,
|
|
527
|
+
def plot_cumulative(self, file_name=None, psf_diameter_cm=None, **kwargs):
|
|
515
528
|
"""Plot cumulative data (intensity vs radius).
|
|
516
529
|
|
|
517
530
|
Parameters
|
|
518
531
|
----------
|
|
519
532
|
file_name: str
|
|
520
533
|
Name of the file to save the plot to.
|
|
521
|
-
|
|
522
|
-
|
|
534
|
+
psf_diameter_cm: float
|
|
535
|
+
PSF diameter value to be marked in the plot (in cm).
|
|
523
536
|
**kwargs:
|
|
524
537
|
Customization of line plot (e.g., color, linestyle, linewidth).
|
|
525
538
|
"""
|
|
@@ -528,9 +541,10 @@ class PSFImage:
|
|
|
528
541
|
ax.set_xlabel("Radius (cm)")
|
|
529
542
|
ax.set_ylabel("Contained light %")
|
|
530
543
|
ax.plot(data[self.__PSF_RADIUS], data[self.__PSF_CUMULATIVE], **kwargs)
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
544
|
+
fraction = self._containment_fraction if self._containment_fraction is not None else 0.8
|
|
545
|
+
ax.axvline(x=self.get_psf(fraction) / 2, color="b", linestyle="--", linewidth=1)
|
|
546
|
+
if psf_diameter_cm is not None:
|
|
547
|
+
ax.axvline(x=psf_diameter_cm / 2.0, color="r", linestyle="--", linewidth=1)
|
|
534
548
|
if file_name is not None:
|
|
535
549
|
fig.savefig(file_name)
|
|
536
550
|
plt.close(fig)
|
|
@@ -857,11 +857,11 @@ def _run_ray_tracing_simulation(tel_model, site_model, args_dict, pars):
|
|
|
857
857
|
if pars is None:
|
|
858
858
|
raise ValueError("No best parameters found")
|
|
859
859
|
|
|
860
|
-
tel_model.overwrite_parameters(pars)
|
|
860
|
+
tel_model.overwrite_parameters(pars, flat_dict=True)
|
|
861
861
|
ray = RayTracing(
|
|
862
862
|
telescope_model=tel_model,
|
|
863
863
|
site_model=site_model,
|
|
864
|
-
|
|
864
|
+
label=args_dict.get("label") or getattr(tel_model, "label", None),
|
|
865
865
|
zenith_angle=args_dict["zenith"] * u.deg,
|
|
866
866
|
source_distance=args_dict["src_distance"] * u.km,
|
|
867
867
|
off_axis_angle=[0.0] * u.deg,
|
|
@@ -1382,7 +1382,7 @@ def cleanup_intermediate_files(output_dir):
|
|
|
1382
1382
|
output_dir : Path
|
|
1383
1383
|
Directory containing output files to clean up.
|
|
1384
1384
|
"""
|
|
1385
|
-
patterns = ["*.log", "*.lis*"]
|
|
1385
|
+
patterns = ["*.log", "*.lis*", "*.dat"]
|
|
1386
1386
|
files_removed = 0
|
|
1387
1387
|
|
|
1388
1388
|
for pattern in patterns:
|
|
@@ -5,7 +5,6 @@ import logging
|
|
|
5
5
|
import shutil
|
|
6
6
|
from copy import copy
|
|
7
7
|
from math import pi, tan
|
|
8
|
-
from pathlib import Path
|
|
9
8
|
|
|
10
9
|
import astropy.io.ascii
|
|
11
10
|
import astropy.units as u
|
|
@@ -33,8 +32,6 @@ class RayTracing:
|
|
|
33
32
|
telescope model
|
|
34
33
|
site_model: SiteModel
|
|
35
34
|
site model
|
|
36
|
-
simtel_path: str (or Path)
|
|
37
|
-
Location of sim_telarray installation.
|
|
38
35
|
label: str
|
|
39
36
|
label used for output file naming.
|
|
40
37
|
zenith_angle: astropy.units.Quantity
|
|
@@ -54,8 +51,8 @@ class RayTracing:
|
|
|
54
51
|
"""
|
|
55
52
|
|
|
56
53
|
YLABEL = {
|
|
57
|
-
"
|
|
58
|
-
"
|
|
54
|
+
"psf_cm": "PSF",
|
|
55
|
+
"psf_deg": "PSF",
|
|
59
56
|
"eff_area": "Eff. mirror area",
|
|
60
57
|
"eff_flen": "Eff. focal length",
|
|
61
58
|
}
|
|
@@ -64,7 +61,6 @@ class RayTracing:
|
|
|
64
61
|
self,
|
|
65
62
|
telescope_model,
|
|
66
63
|
site_model,
|
|
67
|
-
simtel_path,
|
|
68
64
|
label=None,
|
|
69
65
|
zenith_angle=20.0 * u.deg,
|
|
70
66
|
off_axis_angle=[0.0] * u.deg,
|
|
@@ -78,7 +74,6 @@ class RayTracing:
|
|
|
78
74
|
self._logger = logging.getLogger(__name__)
|
|
79
75
|
self._logger.debug(f"Initializing RayTracing class {single_mirror_mode}")
|
|
80
76
|
|
|
81
|
-
self.simtel_path = Path(simtel_path)
|
|
82
77
|
self._io_handler = io_handler.IOHandler()
|
|
83
78
|
|
|
84
79
|
self.telescope_model, self.site_model = telescope_model, site_model
|
|
@@ -212,9 +207,9 @@ class RayTracing:
|
|
|
212
207
|
f"Simulating RayTracing for off_axis={this_off_axis}, mirror={mirror_number}"
|
|
213
208
|
)
|
|
214
209
|
simtel = SimulatorRayTracing(
|
|
215
|
-
simtel_path=self.simtel_path,
|
|
216
210
|
telescope_model=self.telescope_model,
|
|
217
211
|
site_model=self.site_model,
|
|
212
|
+
label=self.label,
|
|
218
213
|
test=test,
|
|
219
214
|
config_data={
|
|
220
215
|
"zenith_angle": self.zenith_angle,
|
|
@@ -408,11 +403,7 @@ class RayTracing:
|
|
|
408
403
|
PSFImage
|
|
409
404
|
PSF image object.
|
|
410
405
|
"""
|
|
411
|
-
image = PSFImage(
|
|
412
|
-
focal_length=focal_length,
|
|
413
|
-
containment_fraction=containment_fraction,
|
|
414
|
-
simtel_path=self.simtel_path,
|
|
415
|
-
)
|
|
406
|
+
image = PSFImage(focal_length=focal_length, containment_fraction=containment_fraction)
|
|
416
407
|
image.process_photon_list(photons_file, use_rx)
|
|
417
408
|
self._psf_images[this_off_axis] = copy(image)
|
|
418
409
|
return image
|
|
@@ -478,22 +469,46 @@ class RayTracing:
|
|
|
478
469
|
else:
|
|
479
470
|
self._logger.error("No results to export")
|
|
480
471
|
|
|
472
|
+
def get_psf_mm(self, row_index: int = 0) -> float:
|
|
473
|
+
"""Return PSF diameter from the analysis results in mm.
|
|
474
|
+
|
|
475
|
+
Parameters
|
|
476
|
+
----------
|
|
477
|
+
row_index : int
|
|
478
|
+
Row index into the results table (default: 0).
|
|
479
|
+
|
|
480
|
+
Returns
|
|
481
|
+
-------
|
|
482
|
+
float
|
|
483
|
+
PSF diameter in millimeters.
|
|
484
|
+
"""
|
|
485
|
+
if self._results is None:
|
|
486
|
+
raise RuntimeError("No results available; run analyze() first")
|
|
487
|
+
psf = self._results["psf_cm"][row_index]
|
|
488
|
+
|
|
489
|
+
if isinstance(psf, u.Quantity):
|
|
490
|
+
psf_cm = psf.to_value(u.cm)
|
|
491
|
+
else:
|
|
492
|
+
psf_cm = float(psf)
|
|
493
|
+
|
|
494
|
+
return psf_cm * 10.0
|
|
495
|
+
|
|
481
496
|
def _read_results(self):
|
|
482
497
|
"""Read existing results file and store it in _results."""
|
|
483
498
|
self._results = astropy.io.ascii.read(self._file_results, format="ecsv")
|
|
484
499
|
|
|
485
|
-
def plot(self, key, save=False,
|
|
500
|
+
def plot(self, key, save=False, psf_diameter_cm=None, **kwargs):
|
|
486
501
|
"""
|
|
487
502
|
Plot key vs off-axis angle and save the figure in pdf.
|
|
488
503
|
|
|
489
504
|
Parameters
|
|
490
505
|
----------
|
|
491
506
|
key: str
|
|
492
|
-
|
|
507
|
+
psf_cm, psf_deg, eff_area or eff_flen
|
|
493
508
|
save: bool
|
|
494
509
|
If True, figure will be saved.
|
|
495
|
-
|
|
496
|
-
|
|
510
|
+
psf_diameter_cm: float
|
|
511
|
+
PSF diameter value to be marked in the cumulative PSF plot (in cm).
|
|
497
512
|
**kwargs:
|
|
498
513
|
kwargs for plt.plot
|
|
499
514
|
|
|
@@ -543,7 +558,9 @@ class RayTracing:
|
|
|
543
558
|
image_cumulative_file_name
|
|
544
559
|
)
|
|
545
560
|
self._logger.info(f"Saving cumulative PSF to {image_cumulative_file}")
|
|
546
|
-
image.plot_cumulative(
|
|
561
|
+
image.plot_cumulative(
|
|
562
|
+
file_name=image_cumulative_file, psf_diameter_cm=psf_diameter_cm
|
|
563
|
+
)
|
|
547
564
|
|
|
548
565
|
def plot_histogram(self, key, **kwargs):
|
|
549
566
|
"""
|
|
@@ -552,7 +569,7 @@ class RayTracing:
|
|
|
552
569
|
Parameters
|
|
553
570
|
----------
|
|
554
571
|
key: str
|
|
555
|
-
|
|
572
|
+
psf_cm, psf_deg, eff_area or eff_flen
|
|
556
573
|
**kwargs:
|
|
557
574
|
kwargs for plt.hist
|
|
558
575
|
|
|
@@ -574,7 +591,7 @@ class RayTracing:
|
|
|
574
591
|
Parameters
|
|
575
592
|
----------
|
|
576
593
|
key: str
|
|
577
|
-
|
|
594
|
+
psf_cm, psf_deg, eff_area or eff_flen
|
|
578
595
|
|
|
579
596
|
Returns
|
|
580
597
|
-------
|
|
@@ -598,7 +615,7 @@ class RayTracing:
|
|
|
598
615
|
Parameters
|
|
599
616
|
----------
|
|
600
617
|
key: str
|
|
601
|
-
|
|
618
|
+
psf_cm, psf_deg, eff_area or eff_flen
|
|
602
619
|
|
|
603
620
|
Returns
|
|
604
621
|
-------
|
|
@@ -623,10 +640,11 @@ class RayTracing:
|
|
|
623
640
|
-------
|
|
624
641
|
List of PSFImages
|
|
625
642
|
"""
|
|
626
|
-
images = [
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
643
|
+
images = [
|
|
644
|
+
self._psf_images[this_off_axis]
|
|
645
|
+
for this_off_axis in self.off_axis_angle
|
|
646
|
+
if self._psf_images and this_off_axis in self._psf_images
|
|
647
|
+
]
|
|
630
648
|
if len(images) == 0:
|
|
631
649
|
self._logger.warning("No image found")
|
|
632
650
|
return None
|
|
@@ -16,11 +16,10 @@ logger = logging.getLogger()
|
|
|
16
16
|
class ReportGenerator:
|
|
17
17
|
"""Automate report generation."""
|
|
18
18
|
|
|
19
|
-
def __init__(self,
|
|
19
|
+
def __init__(self, args, output_path):
|
|
20
20
|
"""Initialise class."""
|
|
21
21
|
self._logger = logging.getLogger(__name__)
|
|
22
|
-
self.db = db_handler.DatabaseHandler(
|
|
23
|
-
self.db_config = db_config
|
|
22
|
+
self.db = db_handler.DatabaseHandler()
|
|
24
23
|
self.args = args
|
|
25
24
|
self.output_path = output_path
|
|
26
25
|
|
|
@@ -99,7 +98,7 @@ class ReportGenerator:
|
|
|
99
98
|
)
|
|
100
99
|
|
|
101
100
|
output_path = Path(self.output_path) / str(model_version)
|
|
102
|
-
ReadParameters(self.
|
|
101
|
+
ReadParameters(self.args, output_path).produce_array_element_report()
|
|
103
102
|
|
|
104
103
|
logger.info(
|
|
105
104
|
f"Markdown report generated for {site} "
|
|
@@ -167,9 +166,7 @@ class ReportGenerator:
|
|
|
167
166
|
}
|
|
168
167
|
)
|
|
169
168
|
|
|
170
|
-
ReadParameters(
|
|
171
|
-
self.db_config, self.args, self.output_path
|
|
172
|
-
).produce_model_parameter_reports()
|
|
169
|
+
ReadParameters(self.args, self.output_path).produce_model_parameter_reports()
|
|
173
170
|
|
|
174
171
|
logger.info(
|
|
175
172
|
f"Markdown report generated for {site} Telescope {telescope}: {self.output_path}"
|
|
@@ -211,7 +208,7 @@ class ReportGenerator:
|
|
|
211
208
|
)
|
|
212
209
|
|
|
213
210
|
output_path = Path(self.output_path) / str(model_version)
|
|
214
|
-
ReadParameters(self.
|
|
211
|
+
ReadParameters(self.args, output_path).produce_observatory_report()
|
|
215
212
|
|
|
216
213
|
logger.info(f"Observatory report generated for {site} (v{model_version}): {output_path}")
|
|
217
214
|
|
|
@@ -237,9 +234,7 @@ class ReportGenerator:
|
|
|
237
234
|
self.args.update({"model_version": version})
|
|
238
235
|
output_path = Path(self.output_path) / str(version)
|
|
239
236
|
|
|
240
|
-
ReadParameters(
|
|
241
|
-
self.db_config, self.args, output_path
|
|
242
|
-
).produce_simulation_configuration_report()
|
|
237
|
+
ReadParameters(self.args, output_path).produce_simulation_configuration_report()
|
|
243
238
|
|
|
244
239
|
logger.info(f"Configuration reports for (v{version}) produced: {output_path}")
|
|
245
240
|
|
|
@@ -262,7 +257,7 @@ class ReportGenerator:
|
|
|
262
257
|
output_path = Path(self.output_path) / str(version)
|
|
263
258
|
|
|
264
259
|
try:
|
|
265
|
-
ReadParameters(self.
|
|
260
|
+
ReadParameters(self.args, output_path).produce_calibration_reports()
|
|
266
261
|
logger.info(f"Calibration reports for (v{version}) produced: {output_path}")
|
|
267
262
|
except ValueError as err:
|
|
268
263
|
# Some model versions do not have calibration_devices in the DB;
|
|
@@ -305,7 +300,7 @@ class ReportGenerator:
|
|
|
305
300
|
|
|
306
301
|
# Generate parameter comparison reports for calibration devices
|
|
307
302
|
ReadParameters(
|
|
308
|
-
|
|
303
|
+
version_args, self.output_path
|
|
309
304
|
).generate_model_parameter_reports_for_devices(array_elements)
|
|
310
305
|
|
|
311
306
|
logger.info(
|
|
@@ -26,11 +26,10 @@ MARKDOWN_LINK_RE = re.compile(r"\[([^\]]+)\]\(([^)]+)\)")
|
|
|
26
26
|
class ReadParameters:
|
|
27
27
|
"""Read and manage model parameter data for report generation."""
|
|
28
28
|
|
|
29
|
-
def __init__(self,
|
|
29
|
+
def __init__(self, args, output_path):
|
|
30
30
|
"""Initialise class."""
|
|
31
31
|
self._logger = logging.getLogger(__name__)
|
|
32
|
-
self.db = db_handler.DatabaseHandler(
|
|
33
|
-
self.db_config = db_config
|
|
32
|
+
self.db = db_handler.DatabaseHandler()
|
|
34
33
|
self.array_element = args.get("telescope", None)
|
|
35
34
|
self.site = args.get("site", None)
|
|
36
35
|
self.model_version = args.get("model_version", None)
|
|
@@ -109,7 +108,6 @@ class ReadParameters:
|
|
|
109
108
|
plot_pixels.plot(
|
|
110
109
|
config=plot_config,
|
|
111
110
|
output_file=Path(f"{outpath}/{plot_name}"),
|
|
112
|
-
db_config=self.db_config,
|
|
113
111
|
)
|
|
114
112
|
plot_names.append(plot_name)
|
|
115
113
|
else:
|
|
@@ -142,7 +140,6 @@ class ReadParameters:
|
|
|
142
140
|
plot_mirrors.plot(
|
|
143
141
|
config=plot_config,
|
|
144
142
|
output_file=Path(f"{outpath}/{plot_name}"),
|
|
145
|
-
db_config=self.db_config,
|
|
146
143
|
)
|
|
147
144
|
plot_names.append(plot_name)
|
|
148
145
|
else:
|
|
@@ -165,7 +162,6 @@ class ReadParameters:
|
|
|
165
162
|
telescope=tel,
|
|
166
163
|
output_path=outpath,
|
|
167
164
|
plot_type="all",
|
|
168
|
-
db_config=self.db_config,
|
|
169
165
|
)
|
|
170
166
|
|
|
171
167
|
if not config_data:
|
|
@@ -180,7 +176,6 @@ class ReadParameters:
|
|
|
180
176
|
plot_tables.plot(
|
|
181
177
|
config=plot_config,
|
|
182
178
|
output_file=image_output_file,
|
|
183
|
-
db_config=self.db_config,
|
|
184
179
|
)
|
|
185
180
|
plt.close("all")
|
|
186
181
|
|
|
@@ -582,7 +577,6 @@ class ReadParameters:
|
|
|
582
577
|
telescope_name=self.array_element,
|
|
583
578
|
model_version=self.model_version,
|
|
584
579
|
label="reports",
|
|
585
|
-
db_config=self.db_config,
|
|
586
580
|
ignore_software_version=True,
|
|
587
581
|
)
|
|
588
582
|
|