gammasimtools 0.12.0__py3-none-any.whl → 0.14.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 (276) hide show
  1. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/METADATA +3 -3
  2. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/RECORD +257 -263
  3. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/WHEEL +1 -1
  4. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/entry_points.txt +4 -1
  5. simtools/_version.py +2 -2
  6. simtools/applications/convert_all_model_parameters_from_simtel.py +77 -88
  7. simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -1
  8. simtools/applications/db_add_file_to_db.py +15 -0
  9. simtools/applications/db_add_value_from_json_to_db.py +18 -1
  10. simtools/applications/db_get_parameter_from_db.py +52 -22
  11. simtools/applications/derive_ctao_array_layouts.py +120 -0
  12. simtools/applications/derive_photon_electron_spectrum.py +30 -2
  13. simtools/applications/docs_produce_array_element_report.py +42 -26
  14. simtools/applications/docs_produce_model_parameter_reports.py +28 -21
  15. simtools/applications/generate_simtel_event_data.py +117 -0
  16. simtools/applications/plot_tabular_data.py +14 -2
  17. simtools/applications/print_version.py +81 -0
  18. simtools/applications/production_derive_corsika_limits.py +240 -0
  19. simtools/applications/production_scale_events.py +59 -36
  20. simtools/applications/run_application.py +47 -18
  21. simtools/applications/simulate_light_emission.py +115 -247
  22. simtools/applications/simulate_prod_htcondor_generator.py +2 -2
  23. simtools/applications/submit_data_from_external.py +1 -1
  24. simtools/applications/submit_model_parameter_from_external.py +2 -1
  25. simtools/camera/single_photon_electron_spectrum.py +169 -17
  26. simtools/constants.py +7 -0
  27. simtools/data_model/metadata_collector.py +159 -61
  28. simtools/data_model/model_data_writer.py +18 -61
  29. simtools/data_model/schema.py +2 -1
  30. simtools/data_model/validate_data.py +5 -3
  31. simtools/db/db_handler.py +123 -33
  32. simtools/dependencies.py +38 -3
  33. simtools/layout/array_layout.py +1 -0
  34. simtools/layout/ctao_array_layouts.py +172 -0
  35. simtools/model/array_model.py +3 -4
  36. simtools/model/model_parameter.py +30 -118
  37. simtools/production_configuration/derive_corsika_limits.py +328 -0
  38. simtools/production_configuration/event_scaler.py +2 -2
  39. simtools/ray_tracing/mirror_panel_psf.py +1 -1
  40. simtools/reporting/docs_auto_report_generator.py +217 -0
  41. simtools/reporting/docs_read_parameters.py +298 -143
  42. simtools/schemas/application_workflow.metaschema.yml +3 -0
  43. simtools/schemas/metadata.metaschema.yml +7 -6
  44. simtools/schemas/model_parameter.metaschema.yml +13 -4
  45. simtools/schemas/model_parameter_and_data_schema.metaschema.yml +19 -5
  46. simtools/schemas/model_parameters/adjust_gain.schema.yml +1 -1
  47. simtools/schemas/model_parameters/altitude.schema.yml +1 -1
  48. simtools/schemas/model_parameters/array_coordinates.schema.yml +1 -1
  49. simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +3 -3
  50. simtools/schemas/model_parameters/array_element_position_ground.schema.yml +3 -3
  51. simtools/schemas/model_parameters/array_element_position_utm.schema.yml +3 -3
  52. simtools/schemas/model_parameters/array_layouts.schema.yml +3 -0
  53. simtools/schemas/model_parameters/array_window.schema.yml +1 -1
  54. simtools/schemas/model_parameters/asum_clipping.schema.yml +1 -1
  55. simtools/schemas/model_parameters/asum_offset.schema.yml +1 -1
  56. simtools/schemas/model_parameters/asum_shaping.schema.yml +1 -1
  57. simtools/schemas/model_parameters/asum_threshold.schema.yml +1 -1
  58. simtools/schemas/model_parameters/atmospheric_profile.schema.yml +1 -1
  59. simtools/schemas/model_parameters/axes_offsets.schema.yml +2 -2
  60. simtools/schemas/model_parameters/camera_body_diameter.schema.yml +1 -1
  61. simtools/schemas/model_parameters/camera_body_shape.schema.yml +1 -1
  62. simtools/schemas/model_parameters/camera_config_file.schema.yml +1 -1
  63. simtools/schemas/model_parameters/camera_config_rotate.schema.yml +1 -1
  64. simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +1 -1
  65. simtools/schemas/model_parameters/camera_degraded_map.schema.yml +1 -1
  66. simtools/schemas/model_parameters/camera_depth.schema.yml +1 -1
  67. simtools/schemas/model_parameters/camera_filter.schema.yml +1 -1
  68. simtools/schemas/model_parameters/camera_pixels.schema.yml +1 -1
  69. simtools/schemas/model_parameters/camera_transmission.schema.yml +1 -1
  70. simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
  71. simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +1 -1
  72. simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +1 -1
  73. simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +1 -1
  74. simtools/schemas/model_parameters/corsika_observation_level.schema.yml +1 -1
  75. simtools/schemas/model_parameters/dark_events.schema.yml +1 -1
  76. simtools/schemas/model_parameters/disc_bins.schema.yml +1 -1
  77. simtools/schemas/model_parameters/disc_start.schema.yml +1 -1
  78. simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +1 -1
  79. simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +1 -1
  80. simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +1 -1
  81. simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +1 -1
  82. simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +1 -1
  83. simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +1 -1
  84. simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +1 -1
  85. simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +1 -1
  86. simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +1 -1
  87. simtools/schemas/model_parameters/discriminator_threshold.schema.yml +1 -1
  88. simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +1 -1
  89. simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +1 -1
  90. simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +1 -1
  91. simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +1 -1
  92. simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +1 -1
  93. simtools/schemas/model_parameters/dish_shape_length.schema.yml +1 -1
  94. simtools/schemas/model_parameters/dsum_clipping.schema.yml +1 -1
  95. simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +1 -1
  96. simtools/schemas/model_parameters/dsum_offset.schema.yml +1 -1
  97. simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +1 -1
  98. simtools/schemas/model_parameters/dsum_prescale.schema.yml +2 -2
  99. simtools/schemas/model_parameters/dsum_presum_max.schema.yml +1 -1
  100. simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +1 -1
  101. simtools/schemas/model_parameters/dsum_shaping.schema.yml +1 -1
  102. simtools/schemas/model_parameters/dsum_threshold.schema.yml +1 -1
  103. simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +1 -1
  104. simtools/schemas/model_parameters/effective_focal_length.schema.yml +5 -5
  105. simtools/schemas/model_parameters/epsg_code.schema.yml +1 -1
  106. simtools/schemas/model_parameters/fadc_amplitude.schema.yml +1 -1
  107. simtools/schemas/model_parameters/fadc_bins.schema.yml +1 -1
  108. simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
  109. simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +2 -2
  110. simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +1 -1
  111. simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +1 -1
  112. simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +1 -1
  113. simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
  114. simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +2 -2
  115. simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +1 -1
  116. simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +1 -1
  117. simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +1 -1
  118. simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +4 -4
  119. simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +1 -1
  120. simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +1 -1
  121. simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +1 -1
  122. simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +1 -1
  123. simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +1 -1
  124. simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +1 -1
  125. simtools/schemas/model_parameters/fadc_max_signal.schema.yml +1 -1
  126. simtools/schemas/model_parameters/fadc_max_sum.schema.yml +4 -4
  127. simtools/schemas/model_parameters/fadc_mhz.schema.yml +1 -1
  128. simtools/schemas/model_parameters/fadc_noise.schema.yml +1 -1
  129. simtools/schemas/model_parameters/fadc_pedestal.schema.yml +1 -1
  130. simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +1 -1
  131. simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +1 -1
  132. simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +1 -1
  133. simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +1 -1
  134. simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +1 -1
  135. simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +1 -1
  136. simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
  137. simtools/schemas/model_parameters/focal_length.schema.yml +1 -1
  138. simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +20 -20
  139. simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +1 -1
  140. simtools/schemas/model_parameters/focus_offset.schema.yml +4 -4
  141. simtools/schemas/model_parameters/gain_variation.schema.yml +1 -1
  142. simtools/schemas/model_parameters/geomag_horizontal.schema.yml +1 -1
  143. simtools/schemas/model_parameters/geomag_rotation.schema.yml +1 -1
  144. simtools/schemas/model_parameters/geomag_vertical.schema.yml +1 -1
  145. simtools/schemas/model_parameters/hg_lg_variation.schema.yml +1 -1
  146. simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
  147. simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
  148. simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
  149. simtools/schemas/model_parameters/laser_external_trigger.schema.yml +1 -1
  150. simtools/schemas/model_parameters/laser_photons.schema.yml +1 -1
  151. simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +1 -1
  152. simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +1 -1
  153. simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +1 -1
  154. simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +1 -1
  155. simtools/schemas/model_parameters/laser_var_photons.schema.yml +1 -1
  156. simtools/schemas/model_parameters/laser_wavelength.schema.yml +1 -1
  157. simtools/schemas/model_parameters/led_events.schema.yml +1 -1
  158. simtools/schemas/model_parameters/led_photons.schema.yml +1 -1
  159. simtools/schemas/model_parameters/led_pulse_offset.schema.yml +1 -1
  160. simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +1 -1
  161. simtools/schemas/model_parameters/led_var_photons.schema.yml +1 -1
  162. simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +1 -1
  163. simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +1 -1
  164. simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
  165. simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
  166. simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +1 -1
  167. simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +4 -4
  168. simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +4 -4
  169. simtools/schemas/model_parameters/mirror_class.schema.yml +1 -1
  170. simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +1 -1
  171. simtools/schemas/model_parameters/mirror_focal_length.schema.yml +1 -1
  172. simtools/schemas/model_parameters/mirror_list.schema.yml +1 -1
  173. simtools/schemas/model_parameters/mirror_offset.schema.yml +1 -1
  174. simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +3 -3
  175. simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +3 -3
  176. simtools/schemas/model_parameters/multiplicity_offset.schema.yml +1 -1
  177. simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +45 -0
  178. simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +2 -2
  179. simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +1 -1
  180. simtools/schemas/model_parameters/nsb_offaxis.schema.yml +5 -5
  181. simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +1 -1
  182. simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +1 -1
  183. simtools/schemas/model_parameters/nsb_reference_value.schema.yml +1 -1
  184. simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +1 -1
  185. simtools/schemas/model_parameters/{nsb_skymap.schema.yml → nsb_sky_map.schema.yml} +1 -1
  186. simtools/schemas/model_parameters/nsb_spectrum.schema.yml +2 -2
  187. simtools/schemas/model_parameters/num_gains.schema.yml +1 -1
  188. simtools/schemas/model_parameters/pedestal_events.schema.yml +1 -1
  189. simtools/schemas/model_parameters/photon_delay.schema.yml +1 -1
  190. simtools/schemas/model_parameters/photons_per_run.schema.yml +1 -1
  191. simtools/schemas/model_parameters/pixel_cells.schema.yml +1 -1
  192. simtools/schemas/model_parameters/pixels_parallel.schema.yml +1 -1
  193. simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +1 -1
  194. simtools/schemas/model_parameters/pm_average_gain.schema.yml +1 -1
  195. simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +1 -1
  196. simtools/schemas/model_parameters/pm_gain_index.schema.yml +1 -1
  197. simtools/schemas/model_parameters/pm_transit_time.schema.yml +4 -4
  198. simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +1 -1
  199. simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +8 -4
  200. simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +1 -1
  201. simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +1 -1
  202. simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +20 -20
  203. simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +1 -1
  204. simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +1 -1
  205. simtools/schemas/model_parameters/qe_variation.schema.yml +1 -1
  206. simtools/schemas/model_parameters/random_focal_length.schema.yml +2 -2
  207. simtools/schemas/model_parameters/random_mono_probability.schema.yml +38 -0
  208. simtools/schemas/model_parameters/reference_point_altitude.schema.yml +1 -1
  209. simtools/schemas/model_parameters/reference_point_latitude.schema.yml +4 -1
  210. simtools/schemas/model_parameters/reference_point_longitude.schema.yml +4 -1
  211. simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +1 -1
  212. simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +1 -1
  213. simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +5 -5
  214. simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +1 -1
  215. simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
  216. simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +1 -1
  217. simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +1 -1
  218. simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +20 -20
  219. simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +1 -1
  220. simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +1 -1
  221. simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +1 -1
  222. simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +1 -1
  223. simtools/schemas/model_parameters/stars.schema.yml +36 -0
  224. simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
  225. simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
  226. simtools/schemas/model_parameters/telescope_axis_height.schema.yml +1 -1
  227. simtools/schemas/model_parameters/telescope_random_angle.schema.yml +1 -1
  228. simtools/schemas/model_parameters/telescope_random_error.schema.yml +1 -1
  229. simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +1 -1
  230. simtools/schemas/model_parameters/telescope_transmission.schema.yml +6 -6
  231. simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +1 -1
  232. simtools/schemas/model_parameters/teltrig_min_time.schema.yml +1 -1
  233. simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +1 -1
  234. simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +1 -1
  235. simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +1 -1
  236. simtools/schemas/model_parameters/transit_time_error.schema.yml +1 -1
  237. simtools/schemas/model_parameters/transit_time_jitter.schema.yml +1 -1
  238. simtools/schemas/model_parameters/trigger_current_limit.schema.yml +1 -1
  239. simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +4 -4
  240. simtools/schemas/model_parameters/trigger_pixels.schema.yml +1 -1
  241. simtools/schemas/plot_configuration.metaschema.yml +162 -0
  242. simtools/schemas/production_tables.schema.yml +1 -1
  243. simtools/simtel/simtel_config_reader.py +85 -34
  244. simtools/simtel/simtel_config_writer.py +70 -38
  245. simtools/simtel/simtel_io_event_reader.py +278 -0
  246. simtools/simtel/simtel_io_event_writer.py +317 -0
  247. simtools/simtel/simtel_table_reader.py +4 -0
  248. simtools/simtel/simulator_light_emission.py +181 -67
  249. simtools/simulator.py +2 -2
  250. simtools/testing/configuration.py +17 -0
  251. simtools/utils/general.py +83 -16
  252. simtools/utils/geometry.py +19 -0
  253. simtools/utils/names.py +14 -3
  254. simtools/visualization/plot_tables.py +25 -20
  255. simtools/visualization/visualize.py +73 -25
  256. simtools/_dev_version/__init__.py +0 -9
  257. simtools/applications/__init__.py +0 -0
  258. simtools/applications/production_derive_limits.py +0 -95
  259. simtools/configuration/__init__.py +0 -0
  260. simtools/corsika/__init__.py +0 -0
  261. simtools/data_model/__init__.py +0 -0
  262. simtools/db/__init__.py +0 -0
  263. simtools/io_operations/__init__.py +0 -0
  264. simtools/job_execution/__init__.py +0 -0
  265. simtools/layout/__init__.py +0 -0
  266. simtools/model/__init__.py +0 -0
  267. simtools/production_configuration/limits_calculation.py +0 -202
  268. simtools/ray_tracing/__init__.py +0 -0
  269. simtools/runners/__init__.py +0 -0
  270. simtools/simtel/__init__.py +0 -0
  271. simtools/simtel/simtel_io_events.py +0 -265
  272. simtools/testing/__init__.py +0 -0
  273. simtools/utils/__init__.py +0 -0
  274. simtools/visualization/__init__.py +0 -0
  275. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info/licenses}/LICENSE +0 -0
  276. {gammasimtools-0.12.0.dist-info → gammasimtools-0.14.0.dist-info}/top_level.txt +0 -0
@@ -4,10 +4,13 @@ r"""Class to read and manage relevant model parameters for a given telescope mod
4
4
 
5
5
  import logging
6
6
  import textwrap
7
+ from collections import defaultdict
7
8
  from itertools import groupby
8
9
  from pathlib import Path
9
10
 
10
- from simtools.io_operations import io_handler
11
+ import numpy as np
12
+
13
+ from simtools.db import db_handler
11
14
  from simtools.model.telescope_model import TelescopeModel
12
15
  from simtools.utils import names
13
16
 
@@ -15,28 +18,21 @@ logger = logging.getLogger()
15
18
 
16
19
 
17
20
  class ReadParameters:
18
- """Read and manage model parameter data."""
21
+ """Read and manage model parameter data for report generation."""
19
22
 
20
- def __init__(self, db_config, telescope_model, output_path):
21
- """Initialise class with a telescope model."""
23
+ def __init__(self, db_config, args, output_path):
24
+ """Initialise class."""
22
25
  self._logger = logging.getLogger(__name__)
26
+ self.db = db_handler.DatabaseHandler(mongo_db_config=db_config)
23
27
  self.db_config = db_config
24
- self.telescope_model = telescope_model
28
+ self.array_element = args.get("telescope")
29
+ self.site = args.get("site")
30
+ self.model_version = args.get("model_version", None)
25
31
  self.output_path = output_path
32
+ self.observatory = args.get("observatory")
26
33
 
27
34
  def _convert_to_md(self, input_file):
28
- """
29
- Convert a '.dat' or '.ecsv' file to a Markdown file, preserving formatting.
30
-
31
- Parameters
32
- ----------
33
- input_file: Path, str
34
- Simulation data file (in '.dat' or '.ecsv' format).
35
-
36
- Returns
37
- -------
38
- - Path to the created Markdown file.
39
- """
35
+ """Convert a file to a Markdown file, preserving formatting."""
40
36
  input_file = Path(input_file)
41
37
  output_data_path = Path(self.output_path / "_data_files")
42
38
  output_data_path.mkdir(parents=True, exist_ok=True)
@@ -44,18 +40,20 @@ class ReadParameters:
44
40
  output_file = output_data_path / output_file_name
45
41
 
46
42
  try:
47
- with (
48
- input_file.open("r", encoding="utf-8") as infile,
49
- output_file.open("w", encoding="utf-8") as outfile,
50
- ):
51
- outfile.write(f"# {input_file.stem}")
52
- outfile.write("\n")
53
- outfile.write("```")
54
- outfile.write("\n")
55
- file_contents = infile.read()
43
+ # First try with utf-8
44
+ try:
45
+ with input_file.open("r", encoding="utf-8") as infile:
46
+ file_contents = infile.read()
47
+ except UnicodeDecodeError:
48
+ # If utf-8 fails, try with latin-1 (which can read any byte sequence)
49
+ with input_file.open("r", encoding="latin-1") as infile:
50
+ file_contents = infile.read()
51
+
52
+ with output_file.open("w", encoding="utf-8") as outfile:
53
+ outfile.write(f"# {input_file.stem}\n")
54
+ outfile.write("```\n")
56
55
  outfile.write(file_contents)
57
- outfile.write("\n")
58
- outfile.write("```")
56
+ outfile.write("\n```")
59
57
 
60
58
  except FileNotFoundError as exc:
61
59
  logger.exception(f"Data file not found: {input_file}.")
@@ -63,6 +61,113 @@ class ReadParameters:
63
61
 
64
62
  return f"_data_files/{output_file_name}"
65
63
 
64
+ def _format_parameter_value(self, value_data, unit, file_flag):
65
+ """Format parameter value based on type."""
66
+ if file_flag:
67
+ input_file_name = f"{self.output_path}/model/{value_data}"
68
+ output_file_name = self._convert_to_md(input_file_name)
69
+ return f"[{Path(value_data).name}]({output_file_name})".strip()
70
+ if isinstance(value_data, (str | int | float)):
71
+ return f"{value_data} {unit}".strip()
72
+ if len(value_data) > 5 and np.allclose(value_data, value_data[0]):
73
+ return f"all: {value_data[0]} {unit}".strip()
74
+ return (
75
+ ", ".join(f"{v} {u}" for v, u in zip(value_data, unit))
76
+ if isinstance(unit, list)
77
+ else ", ".join(f"{v} {unit}" for v in value_data)
78
+ ).strip()
79
+
80
+ def _group_model_versions_by_parameter_version(self, grouped_data):
81
+ """Group model versions by parameter version and track the parameter values."""
82
+ result = {}
83
+
84
+ for parameter_name, items in grouped_data.items():
85
+ version_grouped = defaultdict(
86
+ lambda: {"model_versions": [], "value": None, "file_flag": None}
87
+ )
88
+
89
+ for item in items:
90
+ param_version = item["parameter_version"]
91
+ version_grouped[param_version]["model_versions"].append(item["model_version"])
92
+
93
+ if version_grouped[param_version]["value"] is None:
94
+ version_grouped[param_version]["value"] = item["value"]
95
+ version_grouped[param_version]["file_flag"] = item["file_flag"]
96
+
97
+ result[parameter_name] = [
98
+ {
99
+ "value": data["value"],
100
+ "parameter_version": param_version,
101
+ "file_flag": data["file_flag"],
102
+ "model_version": ", ".join(data["model_versions"]),
103
+ }
104
+ for param_version, data in version_grouped.items()
105
+ ]
106
+
107
+ return result
108
+
109
+ def _compare_parameter_across_versions(self, all_param_data, all_parameter_names):
110
+ """
111
+ Compare a parameter's value across different model versions.
112
+
113
+ Parameters
114
+ ----------
115
+ all_param_data : dict
116
+ The dictionary containing parameter data for all versions.
117
+
118
+ all_parameter_names : list
119
+ The list of parameter names to compare across versions.
120
+
121
+ Returns
122
+ -------
123
+ list
124
+ A list of dictionaries containing model version, parameter value, description.
125
+ """
126
+ all_versions = self.db.get_model_versions()
127
+ all_versions.reverse() # latest first
128
+ grouped_data = defaultdict(list)
129
+
130
+ # Iterate over each model version
131
+ for version in all_versions:
132
+ parameter_dict = all_param_data.get(version, {})
133
+ if not parameter_dict:
134
+ continue
135
+
136
+ Path(f"{self.output_path}/model").mkdir(parents=True, exist_ok=True)
137
+ self.db.export_model_files(
138
+ parameters=all_param_data.get(version), dest=f"{self.output_path}/model"
139
+ )
140
+
141
+ for parameter_name in filter(parameter_dict.__contains__, all_parameter_names):
142
+ parameter_data = parameter_dict.get(parameter_name)
143
+
144
+ # Skip if instrument doesn't match
145
+ if parameter_data.get("instrument") != self.array_element:
146
+ continue
147
+
148
+ unit = parameter_data.get("unit") or " "
149
+ value_data = parameter_data.get("value")
150
+
151
+ if value_data is None:
152
+ continue
153
+
154
+ file_flag = parameter_data.get("file", False)
155
+ value = self._format_parameter_value(value_data, unit, file_flag)
156
+ parameter_version = parameter_data.get("parameter_version")
157
+ model_version = version
158
+
159
+ # Group the data by parameter version and store model versions as a list
160
+ grouped_data[parameter_name].append(
161
+ {
162
+ "value": value,
163
+ "parameter_version": parameter_version,
164
+ "model_version": model_version,
165
+ "file_flag": file_flag,
166
+ }
167
+ )
168
+
169
+ return self._group_model_versions_by_parameter_version(grouped_data)
170
+
66
171
  def get_all_parameter_descriptions(self):
67
172
  """
68
173
  Get descriptions for all model parameters.
@@ -86,9 +191,9 @@ class ReadParameters:
86
191
 
87
192
  def get_array_element_parameter_data(self, telescope_model, collection="telescopes"):
88
193
  """
89
- Get model parameter data for a given array element.
194
+ Get model parameter data and descriptions for a given array element.
90
195
 
91
- Currently only configures for telescope.
196
+ Currently only configured for telescope.
92
197
 
93
198
  Parameters
94
199
  ----------
@@ -100,29 +205,31 @@ class ReadParameters:
100
205
  list: A list of lists containing parameter names, values with units,
101
206
  descriptions, and short descriptions.
102
207
  """
103
- all_params = telescope_model.db.get_model_parameters(
208
+ all_parameter_data = self.db.get_model_parameters(
104
209
  site=telescope_model.site,
105
210
  array_element_name=telescope_model.name,
106
211
  collection=collection,
212
+ model_version=telescope_model.model_version,
107
213
  )
108
214
 
109
- telescope_model.export_model_files()
215
+ Path(f"{self.output_path}/model").mkdir(parents=True, exist_ok=True)
216
+ self.db.export_model_files(parameters=all_parameter_data, dest=f"{self.output_path}/model")
110
217
  parameter_descriptions = self.get_all_parameter_descriptions()
111
218
  data = []
112
219
 
113
- for parameter in all_params:
114
- if all_params[parameter]["instrument"] != telescope_model.name:
220
+ for parameter in filter(all_parameter_data.__contains__, names.model_parameters().keys()):
221
+ parameter_data = all_parameter_data.get(parameter)
222
+ if parameter_data["instrument"] != telescope_model.name:
115
223
  continue
116
224
  parameter_version = telescope_model.get_parameter_version(parameter)
117
- value = telescope_model.get_parameter_value_with_unit(parameter)
118
- if telescope_model.get_parameter_file_flag(parameter) and value:
119
- input_file_name = telescope_model.config_file_directory / Path(value)
120
- output_file_name = self._convert_to_md(input_file_name)
121
- value = f"[{Path(value).name}]({output_file_name})"
122
- elif isinstance(value, list):
123
- value = ", ".join(str(q) for q in value)
124
- else:
125
- value = str(value)
225
+ unit = parameter_data.get("unit") or " "
226
+ value_data = parameter_data.get("value")
227
+
228
+ if value_data is None:
229
+ continue
230
+
231
+ file_flag = parameter_data.get("file", False)
232
+ value = self._format_parameter_value(value_data, unit, file_flag)
126
233
 
127
234
  description = parameter_descriptions[0].get(parameter)
128
235
  short_description = parameter_descriptions[1].get(parameter, description)
@@ -140,75 +247,41 @@ class ReadParameters:
140
247
 
141
248
  return data
142
249
 
143
- def _compare_parameter_across_versions(self, parameter_name):
144
- """
145
- Compare a parameter's value across different model versions.
146
-
147
- Parameters
148
- ----------
149
- parameter_name : str
150
- The name of the parameter to compare.
151
-
152
- Returns
153
- -------
154
- list
155
- A list of dictionaries containing model version, parameter value, and description.
156
- """
157
- all_versions = self.telescope_model.db.get_model_versions()
158
- all_versions.reverse()
159
- comparison_data = []
160
-
161
- for model_version in all_versions:
162
- telescope_model = TelescopeModel(
163
- site=self.telescope_model.site,
164
- telescope_name=self.telescope_model.name,
165
- model_version=model_version,
166
- label="reports",
167
- mongo_db_config=self.db_config,
168
- )
169
-
170
- if not telescope_model.has_parameter(parameter_name):
171
- return comparison_data
172
-
173
- parameter_data = self.get_array_element_parameter_data(telescope_model)
174
- for param in parameter_data:
175
- if param[1] == parameter_name:
176
- comparison_data.append(
177
- {
178
- "model_version": model_version,
179
- "parameter_version": param[2],
180
- "value": param[3],
181
- "description": param[4],
182
- }
183
- )
184
- break
185
- return comparison_data
186
-
187
250
  def produce_array_element_report(self):
188
251
  """
189
252
  Produce a markdown report of all model parameters per array element.
190
253
 
191
- Output
192
- ----------
193
- One markdown report of a given array element listing parameter values,
254
+ Outputs one markdown report of a given array element listing parameter values,
194
255
  versions, and descriptions.
195
256
  """
196
- output_filename = Path(self.output_path / (self.telescope_model.name + ".md"))
257
+ if self.observatory:
258
+ self.produce_observatory_report()
259
+ return
260
+
261
+ telescope_model = TelescopeModel(
262
+ site=self.site,
263
+ telescope_name=self.array_element,
264
+ model_version=self.model_version,
265
+ label="reports",
266
+ mongo_db_config=self.db_config,
267
+ )
268
+
269
+ output_filename = Path(self.output_path / (telescope_model.name + ".md"))
197
270
  output_filename.parent.mkdir(parents=True, exist_ok=True)
198
- data = self.get_array_element_parameter_data(self.telescope_model)
271
+ data = self.get_array_element_parameter_data(telescope_model)
199
272
  # Sort data by class to prepare for grouping
200
273
  if not isinstance(data, str):
201
274
  data.sort(key=lambda x: (x[0], x[1]), reverse=True)
202
275
 
203
276
  with output_filename.open("w", encoding="utf-8") as file:
204
277
  # Group by class and write sections
205
- file.write(f"# {self.telescope_model.name}\n")
278
+ file.write(f"# {telescope_model.name}\n")
206
279
 
207
- if self.telescope_model.name != self.telescope_model.design_model:
280
+ if telescope_model.name != telescope_model.design_model:
208
281
  file.write(
209
282
  "The design model can be found here: "
210
- f"[{self.telescope_model.design_model}]"
211
- f"({self.telescope_model.design_model}.md).\n"
283
+ f"[{telescope_model.design_model}]"
284
+ f"({telescope_model.design_model}.md).\n"
212
285
  )
213
286
  file.write("\n\n")
214
287
 
@@ -249,62 +322,144 @@ class ReadParameters:
249
322
  """
250
323
  Produce a markdown report per parameter for a given array element.
251
324
 
252
- Output
253
- ----------
254
- One markdown report per model parameter of a given array element comparing
325
+ Outputs one markdown report per model parameter of a given array element comparing
255
326
  values across model versions.
256
327
  """
257
328
  logger.info(
258
- f"Comparing parameters across model versions for Telescope: {self.telescope_model.name}"
259
- f" and Site: {self.telescope_model.site}."
329
+ f"Comparing parameters across model versions for Telescope: {self.array_element}"
330
+ f" and Site: {self.site}."
260
331
  )
261
- io_handler_instance = io_handler.IOHandler()
262
- output_path = io_handler_instance.get_output_directory(
263
- label="reports", sub_dir=f"parameters/{self.telescope_model.name}"
332
+ output_path = self.output_path / f"{self.array_element}"
333
+ Path(output_path).mkdir(parents=True, exist_ok=True)
334
+
335
+ all_parameter_names = names.model_parameters(None).keys()
336
+ all_parameter_data = self.db.get_model_parameters_for_all_model_versions(
337
+ site=self.site, array_element_name=self.array_element, collection="telescopes"
264
338
  )
265
339
 
266
- all_params = self.telescope_model.db.get_model_parameters(
267
- site=self.telescope_model.site,
268
- array_element_name=self.telescope_model.name,
269
- collection="telescopes",
340
+ comparison_data = self._compare_parameter_across_versions(
341
+ all_parameter_data, all_parameter_names
270
342
  )
271
343
 
272
- for parameter in all_params:
273
- comparison_data = []
274
- if all_params[parameter]["instrument"] == self.telescope_model.name:
275
- comparison_data = self._compare_parameter_across_versions(parameter)
276
- if comparison_data:
277
- output_filename = output_path / f"{parameter}.md"
278
- with output_filename.open("w", encoding="utf-8") as file:
279
- # Write header
280
- file.write(
281
- f"# {parameter}\n\n"
282
- f"**Telescope**: {self.telescope_model.name}\n\n"
283
- f"**Description**: {comparison_data[0]['description']}\n\n"
284
- "\n"
285
- )
344
+ for parameter in all_parameter_names:
345
+ parameter_data = comparison_data.get(parameter)
346
+ if not parameter_data:
347
+ continue
348
+
349
+ output_filename = output_path / f"{parameter}.md"
350
+ description = self.get_all_parameter_descriptions()[0].get(parameter)
351
+ with output_filename.open("w", encoding="utf-8") as file:
352
+ # Write header
353
+ file.write(
354
+ f"# {parameter}\n\n"
355
+ f"**Telescope**: {self.array_element}\n\n"
356
+ f"**Description**: {description}\n\n"
357
+ "\n"
358
+ )
359
+
360
+ # Write table header
361
+ file.write(
362
+ "| Parameter Version | Model Version(s) "
363
+ "| Value |\n"
364
+ "|------------------------|--------------------"
365
+ "|----------------------|\n"
366
+ )
286
367
 
287
- # Write table header
368
+ # Write table rows
369
+ for item in comparison_data.get(parameter):
288
370
  file.write(
289
- "| Model Version | Parameter Version "
290
- "| Value |\n"
291
- "|--------------------|------------------------"
292
- "|----------------------|\n"
371
+ f"| {item['parameter_version']} |"
372
+ f" {item['model_version']} |"
373
+ f"{item['value'].replace('](', '](../')} |\n"
293
374
  )
294
375
 
295
- # Write table rows
296
- for item in comparison_data:
297
- file.write(
298
- f"| {item['model_version']} |"
299
- f" {item['parameter_version']} |"
300
- f"{item['value'].replace('](', '](../')} |\n"
301
- )
302
-
303
- file.write("\n")
304
- if isinstance(comparison_data[0]["value"], str) and comparison_data[0][
305
- "value"
306
- ].endswith(".md)"):
307
- file.write(
308
- f"![Parameter plot.](_images/"
309
- f"{self.telescope_model.name}_{parameter}.png)"
310
- )
376
+ file.write("\n")
377
+ if comparison_data.get(parameter)[0]["file_flag"]:
378
+ file.write(f"![Parameter plot.](_images/{self.array_element}_{parameter}.png)")
379
+
380
+ def _write_array_layouts_section(self, file, layouts):
381
+ """Write the array layouts section of the report."""
382
+ file.write("\n## Array Layouts {#array-layouts-details}\n\n")
383
+ for layout in layouts:
384
+ layout_name = layout["name"]
385
+ elements = layout["elements"]
386
+ file.write(f"### {layout_name}\n\n")
387
+ file.write("| Element |\n|---------|\n")
388
+ for element in sorted(elements):
389
+ file.write(f"| [{element}]({element}.md) |\n")
390
+ file.write("\n")
391
+
392
+ def _write_array_triggers_section(self, file, trigger_configs):
393
+ """Write the array triggers section of the report."""
394
+ file.write("\n## Array Trigger Configurations {#array-triggers-details}\n\n")
395
+ file.write(
396
+ "| Trigger Name | Multiplicity | Width | Hard Stereo | Min Separation |\n"
397
+ "|--------------|--------------|--------|-------------|----------------|\n"
398
+ )
399
+ for config in trigger_configs:
400
+ name = config["name"]
401
+ mult = f"{config['multiplicity']['value']} {config['multiplicity']['unit'] or ''}"
402
+ width = f"{config['width']['value']} {config['width']['unit'] or ''}"
403
+ stereo = "Yes" if config["hard_stereo"]["value"] else "No"
404
+ min_sep = (
405
+ f"{config['min_separation']['value']} {config['min_separation']['unit'] or '-'}"
406
+ )
407
+ file.write(
408
+ f"| {name} | {mult.strip()} | {width.strip()} | {stereo} | {min_sep.strip()} |\n"
409
+ )
410
+ file.write("\n")
411
+
412
+ def _write_parameters_table(self, file, all_parameter_data):
413
+ """Write the main parameters table of the report."""
414
+ file.write("| Parameter | Value |\n|-----------|--------|\n")
415
+ for param_name, param_data in sorted(all_parameter_data.items()):
416
+ value = param_data.get("value")
417
+ unit = param_data.get("unit") or " "
418
+ file_flag = param_data.get("file", False)
419
+
420
+ if value is None:
421
+ continue
422
+
423
+ if param_name == "array_layouts":
424
+ file.write("| array_layouts | [View Array Layouts](#array-layouts-details) |\n")
425
+ elif param_name == "array_triggers":
426
+ file.write(
427
+ "| array_triggers | [View Trigger Configurations](#array-triggers-details) |\n"
428
+ )
429
+ else:
430
+ formatted_value = self._format_parameter_value(value, unit, file_flag)
431
+ file.write(f"| {param_name} | {formatted_value} |\n")
432
+ file.write("\n")
433
+
434
+ def produce_observatory_report(self):
435
+ """Produce a markdown report of all observatory parameters for a given site."""
436
+ output_filename = Path(self.output_path / f"OBS-{self.site}.md")
437
+ output_filename.parent.mkdir(parents=True, exist_ok=True)
438
+
439
+ all_parameter_data = self.db.get_model_parameters(
440
+ site=self.site,
441
+ array_element_name="OBS-" + self.site,
442
+ collection="sites",
443
+ model_version=self.model_version,
444
+ )
445
+
446
+ if not all_parameter_data:
447
+ logger.warning(f"No observatory parameters found for site {self.site}")
448
+ return
449
+
450
+ Path(f"{self.output_path}/model").mkdir(parents=True, exist_ok=True)
451
+ self.db.export_model_files(parameters=all_parameter_data, dest=f"{self.output_path}/model")
452
+
453
+ with output_filename.open("w", encoding="utf-8") as file:
454
+ file.write(f"# Observatory Parameters - {self.site} Site\n\n")
455
+ self._write_parameters_table(file, all_parameter_data)
456
+
457
+ if "array_layouts" in all_parameter_data:
458
+ self._write_array_layouts_section(
459
+ file, all_parameter_data["array_layouts"]["value"]
460
+ )
461
+
462
+ if "array_triggers" in all_parameter_data:
463
+ self._write_array_triggers_section(
464
+ file, all_parameter_data["array_triggers"]["value"]
465
+ )
@@ -48,6 +48,9 @@ definitions:
48
48
  TEST_NAME:
49
49
  type: string
50
50
  description: "Test name. Should be unique for this application."
51
+ SKIP_FOR_PRODUCTION_DB:
52
+ type: boolean
53
+ description: "Skip test if production DB is used."
51
54
  MODEL_VERSION_USE_CURRENT:
52
55
  type: boolean
53
56
  description: |
@@ -51,9 +51,7 @@ definitions:
51
51
  Describes the person or institution that is responsible for this
52
52
  data product.
53
53
  required:
54
- - EMAIL
55
54
  - NAME
56
- - ORGANIZATION
57
55
  type: object
58
56
  additionalProperties: false
59
57
  properties:
@@ -90,10 +88,8 @@ definitions:
90
88
  links to the data model definition.
91
89
  required:
92
90
  - DATA
93
- - DESCRIPTION
94
91
  - FORMAT
95
92
  - ID
96
- - VALID
97
93
  type: object
98
94
  additionalProperties: false
99
95
  properties:
@@ -125,7 +121,6 @@ definitions:
125
121
  title: Data
126
122
  required:
127
123
  - CATEGORY
128
- - ASSOCIATION
129
124
  - LEVEL
130
125
  - MODEL
131
126
  type: object
@@ -346,7 +341,6 @@ definitions:
346
341
  associated ID.
347
342
  required:
348
343
  - TYPE
349
- - ID
350
344
  type: object
351
345
  additionalProperties: false
352
346
  properties:
@@ -524,6 +518,13 @@ definitions:
524
518
  - type: string
525
519
  - type: "null"
526
520
  default: null
521
+ AUTHOR:
522
+ description: |-
523
+ Author of document.
524
+ anyOf:
525
+ - type: string
526
+ - type: "null"
527
+ default: null
527
528
  ID:
528
529
  description: |-
529
530
  Unique identifier of document.
@@ -14,6 +14,7 @@ definitions:
14
14
  SimtoolsModelParameters:
15
15
  description: ""
16
16
  type: object
17
+ additionalProperties: false
17
18
  properties:
18
19
  _id:
19
20
  type: string
@@ -29,6 +30,12 @@ definitions:
29
30
  - string
30
31
  - "null"
31
32
  description: "Associated instrument."
33
+ meta_parameter:
34
+ type: boolean
35
+ description: "Meta parameter flag for sim_telarray."
36
+ parameter:
37
+ type: string
38
+ description: "Parameter name."
32
39
  site:
33
40
  anyOf:
34
41
  - type: string
@@ -62,6 +69,11 @@ definitions:
62
69
  anyOf:
63
70
  - type: string
64
71
  - type: "null"
72
+ - type: array
73
+ items:
74
+ type:
75
+ - string
76
+ - "null"
65
77
  description: "Unit of the parameter."
66
78
  value:
67
79
  anyOf:
@@ -87,6 +99,7 @@ definitions:
87
99
  required:
88
100
  - file
89
101
  - instrument
102
+ - parameter
90
103
  - parameter_version
91
104
  - schema_version
92
105
  - site
@@ -205,9 +218,6 @@ definitions:
205
218
  _id:
206
219
  type: string
207
220
  description: "DB unique identifier"
208
- applicable:
209
- type: boolean
210
- description: "Model parameter to be used for this telescope and site"
211
221
  entry_date:
212
222
  type: string
213
223
  description: "Value entry data"
@@ -257,7 +267,6 @@ definitions:
257
267
  - type: "null"
258
268
  description: "Model version."
259
269
  required:
260
- - applicable
261
270
  - file
262
271
  - instrument
263
272
  - site