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.
Files changed (138) hide show
  1. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/METADATA +6 -1
  2. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/RECORD +135 -130
  3. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/WHEEL +1 -1
  4. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/entry_points.txt +3 -2
  5. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/licenses/LICENSE +1 -1
  6. simtools/_version.py +2 -2
  7. simtools/application_control.py +35 -7
  8. simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
  9. simtools/applications/db_add_file_to_db.py +1 -1
  10. simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
  11. simtools/applications/db_add_value_from_json_to_db.py +1 -1
  12. simtools/applications/db_generate_compound_indexes.py +1 -1
  13. simtools/applications/db_get_array_layouts_from_db.py +3 -7
  14. simtools/applications/db_get_file_from_db.py +1 -1
  15. simtools/applications/db_get_parameter_from_db.py +1 -1
  16. simtools/applications/db_inspect_databases.py +1 -1
  17. simtools/applications/db_upload_model_repository.py +1 -1
  18. simtools/applications/derive_ctao_array_layouts.py +1 -2
  19. simtools/applications/{calculate_incident_angles.py → derive_incident_angle.py} +16 -18
  20. simtools/applications/derive_mirror_rnda.py +112 -180
  21. simtools/applications/derive_psf_parameters.py +0 -1
  22. simtools/applications/derive_pulse_shape_parameters.py +0 -1
  23. simtools/applications/derive_trigger_rates.py +1 -1
  24. simtools/applications/docs_produce_array_element_report.py +2 -8
  25. simtools/applications/docs_produce_calibration_reports.py +1 -3
  26. simtools/applications/docs_produce_model_parameter_reports.py +0 -2
  27. simtools/applications/docs_produce_simulation_configuration_report.py +1 -3
  28. simtools/applications/generate_array_config.py +0 -1
  29. simtools/applications/generate_corsika_histograms.py +79 -229
  30. simtools/applications/generate_regular_arrays.py +76 -69
  31. simtools/applications/generate_simtel_event_data.py +2 -2
  32. simtools/applications/maintain_simulation_model_add_production.py +2 -2
  33. simtools/applications/maintain_simulation_model_write_array_element_positions.py +87 -0
  34. simtools/applications/plot_array_layout.py +5 -111
  35. simtools/applications/plot_simulated_event_distributions.py +57 -0
  36. simtools/applications/plot_tabular_data.py +0 -1
  37. simtools/applications/plot_tabular_data_for_model_parameter.py +1 -6
  38. simtools/applications/production_derive_corsika_limits.py +1 -1
  39. simtools/applications/production_generate_grid.py +0 -1
  40. simtools/applications/run_application.py +1 -1
  41. simtools/applications/simulate_flasher.py +3 -15
  42. simtools/applications/simulate_illuminator.py +2 -11
  43. simtools/applications/simulate_pedestals.py +1 -5
  44. simtools/applications/simulate_prod.py +8 -11
  45. simtools/applications/simulate_prod_htcondor_generator.py +1 -1
  46. simtools/applications/submit_array_layouts.py +2 -4
  47. simtools/applications/submit_data_from_external.py +2 -1
  48. simtools/applications/submit_model_parameter_from_external.py +1 -3
  49. simtools/applications/validate_camera_efficiency.py +28 -28
  50. simtools/applications/validate_camera_fov.py +0 -1
  51. simtools/applications/validate_cumulative_psf.py +1 -5
  52. simtools/applications/validate_optics.py +2 -14
  53. simtools/atmosphere.py +83 -0
  54. simtools/camera/camera_efficiency.py +171 -53
  55. simtools/camera/single_photon_electron_spectrum.py +8 -7
  56. simtools/configuration/commandline_parser.py +82 -11
  57. simtools/configuration/configurator.py +6 -11
  58. simtools/constants.py +5 -0
  59. simtools/corsika/corsika_config.py +100 -202
  60. simtools/corsika/corsika_histograms.py +561 -1708
  61. simtools/corsika/primary_particle.py +1 -1
  62. simtools/data_model/metadata_collector.py +5 -2
  63. simtools/data_model/metadata_model.py +0 -4
  64. simtools/data_model/model_data_writer.py +59 -64
  65. simtools/data_model/schema.py +2 -0
  66. simtools/data_model/validate_data.py +1 -3
  67. simtools/db/db_handler.py +23 -10
  68. simtools/db/mongo_db.py +2 -2
  69. simtools/dependencies.py +81 -38
  70. simtools/io/ascii_handler.py +55 -5
  71. simtools/io/io_handler.py +23 -12
  72. simtools/io/table_handler.py +1 -1
  73. simtools/job_execution/job_manager.py +154 -79
  74. simtools/job_execution/process_pool.py +137 -0
  75. simtools/layout/array_layout.py +4 -13
  76. simtools/layout/array_layout_utils.py +348 -57
  77. simtools/model/array_model.py +23 -63
  78. simtools/model/calibration_model.py +4 -8
  79. simtools/model/legacy_model_parameter.py +134 -0
  80. simtools/model/model_parameter.py +147 -86
  81. simtools/model/model_utils.py +40 -6
  82. simtools/model/site_model.py +4 -8
  83. simtools/model/telescope_model.py +10 -16
  84. simtools/production_configuration/derive_corsika_limits.py +6 -11
  85. simtools/production_configuration/interpolation_handler.py +16 -16
  86. simtools/ray_tracing/incident_angles.py +92 -17
  87. simtools/ray_tracing/mirror_panel_psf.py +338 -222
  88. simtools/ray_tracing/psf_analysis.py +62 -48
  89. simtools/ray_tracing/psf_parameter_optimisation.py +3 -3
  90. simtools/ray_tracing/ray_tracing.py +43 -25
  91. simtools/reporting/docs_auto_report_generator.py +8 -13
  92. simtools/reporting/docs_read_parameters.py +2 -8
  93. simtools/runners/corsika_runner.py +52 -195
  94. simtools/runners/corsika_simtel_runner.py +77 -108
  95. simtools/runners/runner_services.py +214 -213
  96. simtools/runners/simtel_runner.py +27 -160
  97. simtools/runners/simtools_runner.py +11 -73
  98. simtools/schemas/application_workflow.metaschema.yml +8 -0
  99. simtools/settings.py +173 -0
  100. simtools/{io/eventio_handler.py → sim_events/file_info.py} +3 -3
  101. simtools/{simtel/simtel_io_event_histograms.py → sim_events/histograms.py} +25 -15
  102. simtools/{simtel/simtel_io_event_reader.py → sim_events/reader.py} +20 -17
  103. simtools/{simtel/simtel_io_event_writer.py → sim_events/writer.py} +84 -25
  104. simtools/simtel/pulse_shapes.py +7 -2
  105. simtools/simtel/simtel_config_writer.py +79 -91
  106. simtools/simtel/simtel_seeds.py +184 -0
  107. simtools/simtel/simtel_table_reader.py +6 -4
  108. simtools/simtel/simulator_array.py +114 -109
  109. simtools/simtel/simulator_camera_efficiency.py +68 -46
  110. simtools/simtel/simulator_light_emission.py +164 -132
  111. simtools/simtel/simulator_ray_tracing.py +80 -71
  112. simtools/simulator.py +137 -355
  113. simtools/telescope_trigger_rates.py +3 -4
  114. simtools/testing/assertions.py +84 -33
  115. simtools/testing/configuration.py +1 -2
  116. simtools/testing/helpers.py +2 -3
  117. simtools/testing/log_inspector.py +1 -0
  118. simtools/testing/sim_telarray_metadata.py +14 -12
  119. simtools/testing/validate_output.py +121 -42
  120. simtools/utils/general.py +43 -17
  121. simtools/utils/geometry.py +0 -77
  122. simtools/utils/names.py +5 -5
  123. simtools/utils/random.py +36 -0
  124. simtools/visualization/legend_handlers.py +7 -6
  125. simtools/visualization/plot_array_layout.py +91 -16
  126. simtools/visualization/plot_corsika_histograms.py +145 -605
  127. simtools/visualization/plot_incident_angles.py +48 -1
  128. simtools/visualization/plot_mirrors.py +1 -4
  129. simtools/visualization/plot_pixels.py +2 -4
  130. simtools/visualization/plot_psf.py +160 -19
  131. simtools/visualization/plot_simtel_event_histograms.py +4 -4
  132. simtools/visualization/plot_simtel_events.py +6 -11
  133. simtools/visualization/plot_tables.py +8 -19
  134. simtools/visualization/visualize.py +22 -2
  135. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +0 -160
  136. simtools/applications/print_version.py +0 -53
  137. simtools/io/hdf5_handler.py +0 -139
  138. {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 shlex
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
- rx_output = subprocess.Popen( # pylint: disable=consider-using-with
101
- shlex.split(
102
- f"{self.simtel_path}/sim_telarray/bin/rx -f {self._containment_fraction:.2f} -v"
103
- ),
104
- stdin=subprocess.PIPE,
105
- stdout=subprocess.PIPE,
106
- )
107
- with gzip.open(photon_file, "rb") as _stdin:
108
- with rx_output.stdin:
109
- shutil.copyfileobj(_stdin, rx_output.stdin)
110
- try:
111
- rx_output = rx_output.communicate()[0].splitlines()[-1:][0].split()
112
- except IndexError as e:
113
- raise IndexError(f"Unexpected output format from rx: {rx_output}") from e
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
- try:
118
- self.set_psf(2 * float(rx_output[0]), fraction=self._containment_fraction, unit="cm")
119
- self.centroid_x = float(rx_output[1])
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
- msg = "Problems reading sim_telarray file - invalid data"
154
- self._logger.error(msg)
155
- raise RuntimeError(msg)
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 (80%)
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(0.8) / 2, **kwargs_for_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
- radius_all = list(np.linspace(0, 1.6 * self.get_psf(0.8), 30))
500
-
501
- intensity = []
502
- for rad in radius_all:
503
- intensity.append(self._sum_photons_in_radius(rad) / self._number_of_detected_photons)
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, d80=None, **kwargs):
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
- d80: float
522
- d80 value to be marked in the plot (in cm).
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
- ax.axvline(x=self.get_psf(0.8) / 2, color="b", linestyle="--", linewidth=1)
532
- if d80 is not None:
533
- ax.axvline(x=d80 / 2.0, color="r", linestyle="--", linewidth=1)
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
- simtel_path=args_dict["simtel_path"],
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
- "d80_cm": r"$D_{80}$",
58
- "d80_deg": r"$D_{80}$",
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, d80=None, **kwargs):
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
- d80_cm, d80_deg, eff_area or eff_flen
507
+ psf_cm, psf_deg, eff_area or eff_flen
493
508
  save: bool
494
509
  If True, figure will be saved.
495
- d80: float
496
- d80 for cumulative PSF plot.
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(file_name=image_cumulative_file, d80=d80)
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
- d80_cm, d80_deg, eff_area or eff_flen
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
- d80_cm, d80_deg, eff_area or eff_flen
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
- d80_cm, d80_deg, eff_area or eff_flen
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
- for this_off_axis in self.off_axis_angle:
628
- if self._psf_images and this_off_axis in self._psf_images:
629
- images.append(self._psf_images[this_off_axis])
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, db_config, args, output_path):
19
+ def __init__(self, args, output_path):
20
20
  """Initialise class."""
21
21
  self._logger = logging.getLogger(__name__)
22
- self.db = db_handler.DatabaseHandler(db_config=db_config)
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.db_config, self.args, output_path).produce_array_element_report()
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.db_config, self.args, output_path).produce_observatory_report()
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.db_config, self.args, output_path).produce_calibration_reports()
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
- self.db_config, version_args, self.output_path
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, db_config, args, output_path):
29
+ def __init__(self, args, output_path):
30
30
  """Initialise class."""
31
31
  self._logger = logging.getLogger(__name__)
32
- self.db = db_handler.DatabaseHandler(db_config=db_config)
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