gammasimtools 0.17.0__py3-none-any.whl → 0.19.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 (363) hide show
  1. {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/METADATA +27 -69
  2. gammasimtools-0.19.0.dist-info/RECORD +393 -0
  3. {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/entry_points.txt +10 -2
  4. {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/licenses/LICENSE +1 -1
  5. simtools/_version.py +16 -3
  6. simtools/applications/calculate_trigger_rate.py +1 -1
  7. simtools/applications/convert_all_model_parameters_from_simtel.py +4 -3
  8. simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
  9. simtools/applications/db_add_simulation_model_from_repository_to_db.py +10 -1
  10. simtools/applications/db_add_value_from_json_to_db.py +2 -1
  11. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +8 -13
  12. simtools/applications/db_generate_compound_indexes.py +61 -0
  13. simtools/applications/db_get_file_from_db.py +1 -1
  14. simtools/applications/db_get_parameter_from_db.py +4 -4
  15. simtools/applications/db_inspect_databases.py +20 -10
  16. simtools/applications/derive_mirror_rnda.py +18 -12
  17. simtools/applications/derive_psf_parameters.py +59 -309
  18. simtools/applications/docs_produce_array_element_report.py +1 -1
  19. simtools/applications/docs_produce_calibration_reports.py +1 -1
  20. simtools/applications/docs_produce_model_parameter_reports.py +1 -1
  21. simtools/applications/docs_produce_simulation_configuration_report.py +1 -1
  22. simtools/applications/generate_corsika_histograms.py +1 -1
  23. simtools/applications/generate_default_metadata.py +8 -24
  24. simtools/applications/generate_sim_telarray_histograms.py +1 -1
  25. simtools/applications/generate_simtel_event_data.py +97 -5
  26. simtools/applications/maintain_simulation_model_add_production_table.py +71 -0
  27. simtools/applications/maintain_simulation_model_compare_productions.py +98 -0
  28. simtools/applications/{verify_simulation_model_production_tables.py → maintain_simulation_model_verify_production_tables.py} +9 -1
  29. simtools/applications/merge_tables.py +16 -18
  30. simtools/applications/plot_array_layout.py +3 -3
  31. simtools/applications/plot_simtel_events.py +379 -0
  32. simtools/applications/plot_tabular_data.py +21 -3
  33. simtools/applications/plot_tabular_data_for_model_parameter.py +104 -0
  34. simtools/applications/print_version.py +8 -9
  35. simtools/applications/production_derive_corsika_limits.py +64 -27
  36. simtools/applications/production_derive_statistics.py +1 -1
  37. simtools/applications/production_generate_grid.py +2 -2
  38. simtools/applications/production_merge_corsika_limits.py +214 -0
  39. simtools/applications/run_application.py +47 -113
  40. simtools/applications/simulate_calibration_events.py +166 -0
  41. simtools/applications/simulate_flasher.py +141 -0
  42. simtools/applications/{simulate_light_emission.py → simulate_illuminator.py} +35 -99
  43. simtools/applications/simulate_prod.py +6 -24
  44. simtools/applications/simulate_prod_htcondor_generator.py +7 -0
  45. simtools/applications/submit_array_layouts.py +2 -1
  46. simtools/applications/submit_model_parameter_from_external.py +1 -1
  47. simtools/applications/validate_camera_efficiency.py +30 -12
  48. simtools/applications/validate_camera_fov.py +1 -1
  49. simtools/applications/validate_cumulative_psf.py +1 -1
  50. simtools/applications/validate_file_using_schema.py +2 -1
  51. simtools/applications/validate_optics.py +1 -1
  52. simtools/camera/camera_efficiency.py +61 -45
  53. simtools/camera/single_photon_electron_spectrum.py +1 -1
  54. simtools/configuration/commandline_parser.py +31 -1
  55. simtools/configuration/configurator.py +4 -4
  56. simtools/constants.py +2 -0
  57. simtools/corsika/corsika_config.py +45 -25
  58. simtools/corsika/corsika_histograms.py +6 -5
  59. simtools/data_model/data_reader.py +2 -3
  60. simtools/data_model/metadata_collector.py +32 -36
  61. simtools/data_model/metadata_model.py +15 -12
  62. simtools/data_model/model_data_writer.py +13 -32
  63. simtools/data_model/schema.py +88 -24
  64. simtools/data_model/validate_data.py +34 -9
  65. simtools/db/db_handler.py +48 -37
  66. simtools/db/db_model_upload.py +3 -3
  67. simtools/dependencies.py +88 -25
  68. simtools/io/ascii_handler.py +279 -0
  69. simtools/{io_operations → io}/io_handler.py +25 -3
  70. simtools/{io_operations/io_table_handler.py → io/table_handler.py} +1 -1
  71. simtools/job_execution/htcondor_script_generator.py +15 -4
  72. simtools/layout/array_layout.py +1 -1
  73. simtools/layout/array_layout_utils.py +19 -8
  74. simtools/model/array_model.py +28 -5
  75. simtools/model/flasher_model.py +106 -0
  76. simtools/model/model_parameter.py +4 -4
  77. simtools/model/model_repository.py +197 -2
  78. simtools/model/telescope_model.py +3 -1
  79. simtools/production_configuration/derive_corsika_limits.py +361 -427
  80. simtools/production_configuration/derive_production_statistics_handler.py +7 -6
  81. simtools/production_configuration/generate_production_grid.py +9 -11
  82. simtools/production_configuration/merge_corsika_limits.py +528 -0
  83. simtools/ray_tracing/mirror_panel_psf.py +1 -0
  84. simtools/ray_tracing/psf_parameter_optimisation.py +792 -0
  85. simtools/ray_tracing/ray_tracing.py +6 -2
  86. simtools/reporting/docs_read_parameters.py +150 -62
  87. simtools/resources/array-element-ids.json +126 -0
  88. simtools/runners/corsika_runner.py +1 -1
  89. simtools/runners/corsika_simtel_runner.py +14 -5
  90. simtools/runners/runner_services.py +10 -5
  91. simtools/runners/simtools_runner.py +267 -0
  92. simtools/schemas/application_workflow.metaschema.yml +101 -68
  93. simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +1 -1
  94. simtools/schemas/input/single_pe_spectrum.schema.yml +1 -1
  95. simtools/schemas/metadata.metaschema.yml +577 -3
  96. simtools/schemas/model_parameter.metaschema.yml +6 -6
  97. simtools/schemas/model_parameter_and_data_schema.metaschema.yml +7 -3
  98. simtools/schemas/model_parameters/adjust_gain.schema.yml +1 -1
  99. simtools/schemas/model_parameters/altitude.schema.yml +1 -1
  100. simtools/schemas/model_parameters/array_coordinates.schema.yml +1 -1
  101. simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +1 -1
  102. simtools/schemas/model_parameters/array_element_position_ground.schema.yml +1 -1
  103. simtools/schemas/model_parameters/array_element_position_utm.schema.yml +1 -1
  104. simtools/schemas/model_parameters/array_layouts.schema.yml +1 -1
  105. simtools/schemas/model_parameters/array_triggers.schema.yml +1 -1
  106. simtools/schemas/model_parameters/array_window.schema.yml +1 -1
  107. simtools/schemas/model_parameters/asum_clipping.schema.yml +1 -1
  108. simtools/schemas/model_parameters/asum_offset.schema.yml +1 -1
  109. simtools/schemas/model_parameters/asum_shaping.schema.yml +1 -1
  110. simtools/schemas/model_parameters/asum_threshold.schema.yml +1 -1
  111. simtools/schemas/model_parameters/atmospheric_profile.schema.yml +42 -1
  112. simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +44 -1
  113. simtools/schemas/model_parameters/axes_offsets.schema.yml +1 -1
  114. simtools/schemas/model_parameters/camera_body_diameter.schema.yml +1 -1
  115. simtools/schemas/model_parameters/camera_body_shape.schema.yml +1 -1
  116. simtools/schemas/model_parameters/camera_config_file.schema.yml +1 -1
  117. simtools/schemas/model_parameters/camera_config_rotate.schema.yml +1 -1
  118. simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +1 -1
  119. simtools/schemas/model_parameters/camera_degraded_map.schema.yml +1 -1
  120. simtools/schemas/model_parameters/camera_depth.schema.yml +1 -1
  121. simtools/schemas/model_parameters/camera_filter.schema.yml +11 -1
  122. simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +11 -1
  123. simtools/schemas/model_parameters/camera_pixels.schema.yml +1 -1
  124. simtools/schemas/model_parameters/camera_transmission.schema.yml +1 -1
  125. simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
  126. simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +1 -1
  127. simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +1 -1
  128. simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +1 -1
  129. simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +1 -1
  130. simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +1 -1
  131. simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +1 -1
  132. simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +1 -1
  133. simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +1 -1
  134. simtools/schemas/model_parameters/corsika_observation_level.schema.yml +1 -1
  135. simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +1 -1
  136. simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +3 -3
  137. simtools/schemas/model_parameters/dark_events.schema.yml +1 -1
  138. simtools/schemas/model_parameters/default_trigger.schema.yml +1 -1
  139. simtools/schemas/model_parameters/design_model.schema.yml +1 -1
  140. simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +1 -1
  141. simtools/schemas/model_parameters/disc_bins.schema.yml +1 -1
  142. simtools/schemas/model_parameters/disc_start.schema.yml +1 -1
  143. simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +1 -1
  144. simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +1 -1
  145. simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +1 -1
  146. simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +1 -1
  147. simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +1 -1
  148. simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +1 -1
  149. simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +32 -1
  150. simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +1 -1
  151. simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +1 -1
  152. simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +1 -1
  153. simtools/schemas/model_parameters/discriminator_threshold.schema.yml +1 -1
  154. simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +1 -1
  155. simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +1 -1
  156. simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +1 -1
  157. simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +1 -1
  158. simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +1 -1
  159. simtools/schemas/model_parameters/dish_shape_length.schema.yml +1 -1
  160. simtools/schemas/model_parameters/dsum_clipping.schema.yml +1 -1
  161. simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +1 -1
  162. simtools/schemas/model_parameters/dsum_offset.schema.yml +1 -1
  163. simtools/schemas/model_parameters/dsum_pedsub.schema.yml +1 -1
  164. simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +1 -1
  165. simtools/schemas/model_parameters/dsum_prescale.schema.yml +1 -1
  166. simtools/schemas/model_parameters/dsum_presum_max.schema.yml +1 -1
  167. simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +1 -1
  168. simtools/schemas/model_parameters/dsum_shaping.schema.yml +1 -1
  169. simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +1 -1
  170. simtools/schemas/model_parameters/dsum_threshold.schema.yml +2 -2
  171. simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +1 -1
  172. simtools/schemas/model_parameters/effective_focal_length.schema.yml +1 -1
  173. simtools/schemas/model_parameters/epsg_code.schema.yml +1 -1
  174. simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +1 -1
  175. simtools/schemas/model_parameters/fadc_amplitude.schema.yml +1 -1
  176. simtools/schemas/model_parameters/fadc_bins.schema.yml +1 -1
  177. simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
  178. simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +1 -1
  179. simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +1 -1
  180. simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +1 -1
  181. simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +1 -1
  182. simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
  183. simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +1 -1
  184. simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +1 -1
  185. simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +1 -1
  186. simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +1 -1
  187. simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +1 -1
  188. simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +1 -1
  189. simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +1 -1
  190. simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +1 -1
  191. simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +1 -1
  192. simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +1 -1
  193. simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +1 -1
  194. simtools/schemas/model_parameters/fadc_long_event_threshold.schema.yml +35 -0
  195. simtools/schemas/model_parameters/fadc_long_sum_bins.schema.yml +41 -0
  196. simtools/schemas/model_parameters/fadc_long_sum_offset.schema.yml +38 -0
  197. simtools/schemas/model_parameters/fadc_max_signal.schema.yml +1 -1
  198. simtools/schemas/model_parameters/fadc_max_sum.schema.yml +1 -1
  199. simtools/schemas/model_parameters/fadc_mhz.schema.yml +1 -1
  200. simtools/schemas/model_parameters/fadc_noise.schema.yml +1 -1
  201. simtools/schemas/model_parameters/fadc_pedestal.schema.yml +1 -1
  202. simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +13 -1
  203. simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +1 -1
  204. simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +1 -1
  205. simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +1 -1
  206. simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +1 -1
  207. simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +1 -1
  208. simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +1 -1
  209. simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
  210. simtools/schemas/model_parameters/flatfielding.schema.yml +1 -1
  211. simtools/schemas/model_parameters/focal_length.schema.yml +1 -1
  212. simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +1 -1
  213. simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +1 -1
  214. simtools/schemas/model_parameters/focus_offset.schema.yml +1 -1
  215. simtools/schemas/model_parameters/gain_variation.schema.yml +1 -1
  216. simtools/schemas/model_parameters/geomag_horizontal.schema.yml +1 -1
  217. simtools/schemas/model_parameters/geomag_rotation.schema.yml +1 -1
  218. simtools/schemas/model_parameters/geomag_vertical.schema.yml +1 -1
  219. simtools/schemas/model_parameters/hg_lg_variation.schema.yml +1 -1
  220. simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
  221. simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
  222. simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
  223. simtools/schemas/model_parameters/laser_external_trigger.schema.yml +1 -1
  224. simtools/schemas/model_parameters/laser_photons.schema.yml +1 -1
  225. simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +1 -1
  226. simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +1 -1
  227. simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +1 -1
  228. simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +1 -1
  229. simtools/schemas/model_parameters/laser_var_photons.schema.yml +1 -1
  230. simtools/schemas/model_parameters/laser_wavelength.schema.yml +1 -1
  231. simtools/schemas/model_parameters/led_events.schema.yml +1 -1
  232. simtools/schemas/model_parameters/led_photons.schema.yml +1 -1
  233. simtools/schemas/model_parameters/led_pulse_offset.schema.yml +1 -1
  234. simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +1 -1
  235. simtools/schemas/model_parameters/led_var_photons.schema.yml +1 -1
  236. simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +11 -1
  237. simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +50 -1
  238. simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
  239. simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
  240. simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +1 -1
  241. simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +1 -1
  242. simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +1 -1
  243. simtools/schemas/model_parameters/mirror_class.schema.yml +1 -1
  244. simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +1 -1
  245. simtools/schemas/model_parameters/mirror_focal_length.schema.yml +1 -1
  246. simtools/schemas/model_parameters/mirror_list.schema.yml +1 -1
  247. simtools/schemas/model_parameters/mirror_offset.schema.yml +1 -1
  248. simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +1 -1
  249. simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +1 -1
  250. simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +11 -1
  251. simtools/schemas/model_parameters/multiplicity_offset.schema.yml +1 -1
  252. simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +1 -1
  253. simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +1 -1
  254. simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +1 -1
  255. simtools/schemas/model_parameters/nsb_offaxis.schema.yml +1 -1
  256. simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +1 -1
  257. simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +13 -1
  258. simtools/schemas/model_parameters/nsb_reference_value.schema.yml +1 -1
  259. simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +1 -1
  260. simtools/schemas/model_parameters/nsb_sky_map.schema.yml +1 -1
  261. simtools/schemas/model_parameters/nsb_spectrum.schema.yml +1 -1
  262. simtools/schemas/model_parameters/num_gains.schema.yml +1 -1
  263. simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +1 -1
  264. simtools/schemas/model_parameters/optics_properties.schema.yml +1 -1
  265. simtools/schemas/model_parameters/parabolic_dish.schema.yml +1 -1
  266. simtools/schemas/model_parameters/pedestal_events.schema.yml +1 -1
  267. simtools/schemas/model_parameters/photon_delay.schema.yml +1 -1
  268. simtools/schemas/model_parameters/photons_per_run.schema.yml +1 -1
  269. simtools/schemas/model_parameters/pixel_cells.schema.yml +1 -1
  270. simtools/schemas/model_parameters/pixels_parallel.schema.yml +1 -1
  271. simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +1 -1
  272. simtools/schemas/model_parameters/pm_average_gain.schema.yml +1 -1
  273. simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +1 -1
  274. simtools/schemas/model_parameters/pm_gain_index.schema.yml +1 -1
  275. simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +20 -1
  276. simtools/schemas/model_parameters/pm_transit_time.schema.yml +1 -1
  277. simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +1 -1
  278. simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +1 -1
  279. simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +1 -1
  280. simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +1 -1
  281. simtools/schemas/model_parameters/primary_mirror_incidence_angle.schema.yml +11 -1
  282. simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +1 -1
  283. simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +1 -1
  284. simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +1 -1
  285. simtools/schemas/model_parameters/qe_variation.schema.yml +1 -1
  286. simtools/schemas/model_parameters/quantum_efficiency.schema.yml +11 -1
  287. simtools/schemas/model_parameters/random_focal_length.schema.yml +1 -1
  288. simtools/schemas/model_parameters/random_generator.schema.yml +1 -1
  289. simtools/schemas/model_parameters/random_mono_probability.schema.yml +1 -1
  290. simtools/schemas/model_parameters/reference_point_altitude.schema.yml +1 -1
  291. simtools/schemas/model_parameters/reference_point_latitude.schema.yml +1 -1
  292. simtools/schemas/model_parameters/reference_point_longitude.schema.yml +1 -1
  293. simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +1 -1
  294. simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +1 -1
  295. simtools/schemas/model_parameters/sampled_output.schema.yml +1 -1
  296. simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +1 -1
  297. simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +1 -1
  298. simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +1 -1
  299. simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
  300. simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +1 -1
  301. simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +1 -1
  302. simtools/schemas/model_parameters/secondary_mirror_incidence_angle.schema.yml +11 -1
  303. simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +1 -1
  304. simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +1 -1
  305. simtools/schemas/model_parameters/secondary_mirror_reflectivity.schema.yml +11 -1
  306. simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +1 -1
  307. simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +1 -1
  308. simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +1 -1
  309. simtools/schemas/model_parameters/stars.schema.yml +1 -1
  310. simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
  311. simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
  312. simtools/schemas/model_parameters/telescope_axis_height.schema.yml +1 -1
  313. simtools/schemas/model_parameters/telescope_random_angle.schema.yml +1 -1
  314. simtools/schemas/model_parameters/telescope_random_error.schema.yml +1 -1
  315. simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +1 -1
  316. simtools/schemas/model_parameters/telescope_transmission.schema.yml +1 -1
  317. simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +1 -1
  318. simtools/schemas/model_parameters/teltrig_min_time.schema.yml +1 -1
  319. simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +1 -1
  320. simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +1 -1
  321. simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +1 -1
  322. simtools/schemas/model_parameters/transit_time_error.schema.yml +1 -1
  323. simtools/schemas/model_parameters/transit_time_jitter.schema.yml +1 -1
  324. simtools/schemas/model_parameters/trigger_current_limit.schema.yml +1 -1
  325. simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +1 -1
  326. simtools/schemas/model_parameters/trigger_pixels.schema.yml +1 -1
  327. simtools/schemas/plot_configuration.metaschema.yml +51 -59
  328. simtools/schemas/production_configuration_metrics.schema.yml +12 -2
  329. simtools/schemas/production_tables.schema.yml +2 -2
  330. simtools/simtel/simtel_config_reader.py +2 -2
  331. simtools/simtel/simtel_config_writer.py +16 -4
  332. simtools/simtel/simtel_io_event_histograms.py +746 -0
  333. simtools/simtel/simtel_io_event_reader.py +16 -43
  334. simtools/simtel/simtel_io_event_writer.py +46 -10
  335. simtools/simtel/simtel_io_histogram.py +3 -1
  336. simtools/simtel/simtel_io_histograms.py +7 -3
  337. simtools/simtel/simtel_io_metadata.py +99 -3
  338. simtools/simtel/simtel_table_reader.py +92 -10
  339. simtools/simtel/simulator_array.py +138 -10
  340. simtools/simtel/simulator_camera_efficiency.py +32 -23
  341. simtools/simtel/simulator_light_emission.py +437 -271
  342. simtools/simtel/simulator_ray_tracing.py +1 -1
  343. simtools/simulator.py +105 -147
  344. simtools/testing/configuration.py +24 -26
  345. simtools/testing/helpers.py +2 -2
  346. simtools/testing/log_inspector.py +50 -0
  347. simtools/testing/validate_output.py +87 -37
  348. simtools/utils/general.py +125 -257
  349. simtools/utils/geometry.py +36 -0
  350. simtools/utils/names.py +72 -3
  351. simtools/visualization/legend_handlers.py +180 -264
  352. simtools/visualization/plot_array_layout.py +20 -8
  353. simtools/visualization/plot_pixels.py +1 -2
  354. simtools/visualization/plot_tables.py +202 -27
  355. simtools/visualization/simtel_event_plots.py +816 -0
  356. simtools/visualization/visualize.py +4 -101
  357. gammasimtools-0.17.0.dist-info/RECORD +0 -374
  358. simtools/production_configuration/derive_corsika_limits_grid.py +0 -189
  359. {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/WHEEL +0 -0
  360. {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/top_level.txt +0 -0
  361. /simtools/{io_operations → io}/hdf5_handler.py +0 -0
  362. /simtools/{io_operations → io}/legacy_data_handler.py +0 -0
  363. /simtools/{schemas → resources}/array_elements.yml +0 -0
@@ -5,11 +5,11 @@ from dataclasses import dataclass, field
5
5
 
6
6
  import astropy.units as u
7
7
  import numpy as np
8
- from astropy.coordinates import AltAz, angular_separation
9
- from ctapipe.coordinates import GroundFrame, TiltedGroundFrame
8
+ from astropy.coordinates import angular_separation
10
9
 
11
10
  from simtools.corsika.primary_particle import PrimaryParticle
12
- from simtools.io_operations import io_table_handler
11
+ from simtools.io import table_handler
12
+ from simtools.utils.geometry import transform_ground_to_shower_coordinates
13
13
 
14
14
 
15
15
  @dataclass
@@ -71,7 +71,7 @@ class SimtelIOEventDataReader:
71
71
  list
72
72
  List of dictionaries containing the data from the tables.
73
73
  """
74
- dataset_dict = io_table_handler.read_table_list(
74
+ dataset_dict = table_handler.read_table_list(
75
75
  event_data_file,
76
76
  ["SHOWERS", "TRIGGERS", "FILE_INFO"],
77
77
  include_indexed_tables=True,
@@ -110,16 +110,17 @@ class SimtelIOEventDataReader:
110
110
  if table[col].unit:
111
111
  setattr(shower_data, f"{col}_unit", table[col].unit)
112
112
 
113
- shower_data.x_core_shower, shower_data.y_core_shower = (
114
- self._transform_to_shower_coordinates(
113
+ shower_data.x_core_shower, shower_data.y_core_shower, _ = (
114
+ transform_ground_to_shower_coordinates(
115
115
  shower_data.x_core,
116
116
  shower_data.y_core,
117
+ 0.0,
117
118
  shower_data.shower_azimuth,
118
119
  shower_data.shower_altitude,
119
120
  )
120
121
  )
121
- shower_data.core_distance_shower = np.sqrt(
122
- shower_data.x_core_shower**2 + shower_data.y_core_shower**2
122
+ shower_data.core_distance_shower = np.hypot(
123
+ shower_data.x_core_shower, shower_data.y_core_shower
123
124
  )
124
125
 
125
126
  return shower_data
@@ -144,7 +145,7 @@ class SimtelIOEventDataReader:
144
145
  for col in table.colnames:
145
146
  if col == "telescope_list":
146
147
  arrays = [
147
- np.array(list(map(int, tel_list.split(","))), dtype=np.int16)
148
+ np.array(list(map(str, tel_list.split(","))), dtype=np.str_)
148
149
  for tel_list in table[col]
149
150
  ]
150
151
  triggered_data.telescope_list = arrays
@@ -191,7 +192,7 @@ class SimtelIOEventDataReader:
191
192
  & (shower_data.event_id == tr_event_id)
192
193
  & (shower_data.file_id == tr_file_id)
193
194
  )
194
- matched_idx = np.where(mask)[0]
195
+ matched_idx = np.nonzero(mask)[0]
195
196
  if len(matched_idx) == 1:
196
197
  matched_indices.append(matched_idx[0])
197
198
  else:
@@ -233,7 +234,7 @@ class SimtelIOEventDataReader:
233
234
  def get_name(key):
234
235
  return table_name_map.get(key, key)
235
236
 
236
- tables = io_table_handler.read_tables(
237
+ tables = table_handler.read_tables(
237
238
  event_data_file,
238
239
  table_names=[get_name(k) for k in ("SHOWERS", "TRIGGERS", "FILE_INFO")],
239
240
  )
@@ -249,10 +250,10 @@ class SimtelIOEventDataReader:
249
250
 
250
251
  triggered_data.angular_distance = (
251
252
  angular_separation(
252
- triggered_shower.shower_azimuth * u.rad,
253
- triggered_shower.shower_altitude * u.rad,
254
- triggered_data.array_azimuth * u.rad,
255
- triggered_data.array_altitude * u.rad,
253
+ triggered_shower.shower_azimuth * u.deg,
254
+ triggered_shower.shower_altitude * u.deg,
255
+ triggered_data.array_azimuth * u.deg,
256
+ triggered_data.array_altitude * u.deg,
256
257
  )
257
258
  .to(u.deg)
258
259
  .value
@@ -298,34 +299,6 @@ class SimtelIOEventDataReader:
298
299
 
299
300
  return filtered_triggered_data, filtered_triggered_shower_data
300
301
 
301
- def _transform_to_shower_coordinates(self, x_core, y_core, shower_azimuth, shower_altitude):
302
- """
303
- Transform core positions from ground coordinates to shower coordinates.
304
-
305
- Parameters
306
- ----------
307
- x_core : np.ndarray
308
- Core x positions in ground coordinates.
309
- y_core : np.ndarray
310
- Core y positions in ground coordinates.
311
- shower_azimuth : np.ndarray
312
- Shower azimuth angles.
313
- shower_altitude : np.ndarray
314
- Shower altitude angles.
315
-
316
- Returns
317
- -------
318
- tuple
319
- Core positions in shower coordinates (x, y).
320
- """
321
- ground = GroundFrame(x=x_core * u.m, y=y_core * u.m, z=np.zeros_like(x_core) * u.m)
322
- shower_frame = ground.transform_to(
323
- TiltedGroundFrame(
324
- pointing_direction=AltAz(az=shower_azimuth * u.rad, alt=shower_altitude * u.rad)
325
- )
326
- )
327
- return shower_frame.x.value, shower_frame.y.value
328
-
329
302
  def get_reduced_simulation_file_info(self, simulation_file_info):
330
303
  """
331
304
  Return reduced simulation file info assuming single-valued parameters.
@@ -18,7 +18,11 @@ from eventio.simtel import (
18
18
 
19
19
  from simtools.corsika.primary_particle import PrimaryParticle
20
20
  from simtools.simtel.simtel_io_file_info import get_corsika_run_header
21
+ from simtools.simtel.simtel_io_metadata import (
22
+ get_sim_telarray_telescope_id_to_telescope_name_mapping,
23
+ )
21
24
  from simtools.utils.geometry import calculate_circular_mean
25
+ from simtools.utils.names import get_common_identifier_from_array_element_name
22
26
 
23
27
 
24
28
  @dataclass
@@ -32,8 +36,8 @@ class TableSchemas:
32
36
  "simulated_energy": (np.float64, u.TeV),
33
37
  "x_core": (np.float64, u.m),
34
38
  "y_core": (np.float64, u.m),
35
- "shower_azimuth": (np.float64, u.rad),
36
- "shower_altitude": (np.float64, u.rad),
39
+ "shower_azimuth": (np.float64, u.deg),
40
+ "shower_altitude": (np.float64, u.deg),
37
41
  "area_weight": (np.float64, None),
38
42
  }
39
43
 
@@ -41,9 +45,10 @@ class TableSchemas:
41
45
  "shower_id": (np.uint32, None),
42
46
  "event_id": (np.uint32, None),
43
47
  "file_id": (np.uint32, None),
44
- "array_altitude": (np.float64, u.rad),
45
- "array_azimuth": (np.float64, u.rad),
48
+ "array_altitude": (np.float64, u.deg),
49
+ "array_azimuth": (np.float64, u.deg),
46
50
  "telescope_list": (str, None), # Store as comma-separated string
51
+ "telescope_list_common_id": (str, None), # Store as comma-separated string
47
52
  }
48
53
 
49
54
  file_info_schema = {
@@ -93,6 +98,7 @@ class SimtelIOEventDataWriter:
93
98
  self.shower_data = []
94
99
  self.trigger_data = []
95
100
  self.file_info = []
101
+ self.telescope_id_to_name = {}
96
102
 
97
103
  def process_files(self):
98
104
  """
@@ -152,6 +158,7 @@ class SimtelIOEventDataWriter:
152
158
  def _process_file_info(self, file_id, file):
153
159
  """Process file information and append to file info list."""
154
160
  run_info = get_corsika_run_header(file)
161
+ self.telescope_id_to_name = get_sim_telarray_telescope_id_to_telescope_name_mapping(file)
155
162
  particle = PrimaryParticle(
156
163
  particle_id_type="eventio_id", particle_id=run_info.get("primary_id", 1)
157
164
  )
@@ -189,8 +196,8 @@ class SimtelIOEventDataWriter:
189
196
  "simulated_energy": shower["energy"],
190
197
  "x_core": None, # filled in _process_mc_event
191
198
  "y_core": None, # filled in _process_mc_event
192
- "shower_azimuth": shower["azimuth"],
193
- "shower_altitude": shower["altitude"],
199
+ "shower_azimuth": np.degrees(shower["azimuth"]),
200
+ "shower_altitude": np.degrees(shower["altitude"]),
194
201
  "area_weight": None, # filled in _process_mc_event
195
202
  }
196
203
  for _ in range(self.n_use)
@@ -240,13 +247,18 @@ class SimtelIOEventDataWriter:
240
247
  tracking_position = obj.parse()
241
248
  tracking_positions.append(
242
249
  {
243
- "altitude": tracking_position["altitude_raw"],
244
- "azimuth": tracking_position["azimuth_raw"],
250
+ "altitude": np.degrees(tracking_position["altitude_raw"]),
251
+ "azimuth": np.degrees(tracking_position["azimuth_raw"]),
245
252
  }
246
253
  )
247
254
 
248
255
  if len(telescopes) > 0 and tracking_positions:
249
- self._fill_array_event(telescopes, tracking_positions, eventio_object.event_id, file_id)
256
+ self._fill_array_event(
257
+ self._map_telescope_names(telescopes),
258
+ tracking_positions,
259
+ eventio_object.event_id,
260
+ file_id,
261
+ )
250
262
 
251
263
  def _fill_array_event(self, telescopes, tracking_positions, event_id, file_id):
252
264
  """Add array event triggered events with tracking positions."""
@@ -259,11 +271,35 @@ class SimtelIOEventDataWriter:
259
271
  "event_id": event_id,
260
272
  "file_id": file_id,
261
273
  "array_altitude": float(np.mean(altitudes)),
262
- "array_azimuth": float(calculate_circular_mean(azimuths)),
274
+ "array_azimuth": float(np.degrees(calculate_circular_mean(np.deg2rad(azimuths)))),
263
275
  "telescope_list": ",".join(map(str, telescopes)),
276
+ "telescope_list_common_id": ",".join(
277
+ [
278
+ str(get_common_identifier_from_array_element_name(tel, 0))
279
+ for tel in telescopes
280
+ ]
281
+ ),
264
282
  }
265
283
  )
266
284
 
285
+ def _map_telescope_names(self, telescope_ids):
286
+ """
287
+ Map sim_telarray telescopes IDs to CTAO array element names.
288
+
289
+ Parameters
290
+ ----------
291
+ telescope_ids : list
292
+ List of telescope IDs.
293
+
294
+ Returns
295
+ -------
296
+ list
297
+ List of telescope names corresponding to the IDs.
298
+ """
299
+ return [
300
+ self.telescope_id_to_name.get(tel_id, f"Unknown_{tel_id}") for tel_id in telescope_ids
301
+ ]
302
+
267
303
  def _get_preliminary_nsb_level(self, file):
268
304
  """
269
305
  Return preliminary NSB level from file name.
@@ -177,7 +177,7 @@ class SimtelIOHistogram:
177
177
  histograms = {hist["id"]: hist for hist in self.histogram if hist["id"] in {1, 2}}
178
178
  if 1 in histograms and 2 in histograms:
179
179
  return histograms[1], histograms[2]
180
- self._logger.error("Histograms ids not found. Please check your files.")
180
+ self._logger.error("Histograms ids not found. Please check files.")
181
181
  raise HistogramIdNotFoundError
182
182
 
183
183
  def _set_view_cone(self, view_cone):
@@ -560,6 +560,8 @@ class SimtelIOHistogram:
560
560
  self.energy_range[0],
561
561
  self.energy_range[1],
562
562
  )
563
+ if first_estimate == 0:
564
+ return 0.0 * u.s
563
565
  if stacked_num_simulated_events is None:
564
566
  _simulated_events, _ = self.total_number_of_events
565
567
  return (_simulated_events / first_estimate) * u.s
@@ -9,7 +9,7 @@ from eventio import EventIOFile, Histograms
9
9
  from eventio.search_utils import yield_toplevel_of_type
10
10
 
11
11
  from simtools import version
12
- from simtools.io_operations.hdf5_handler import fill_hdf5_table
12
+ from simtools.io.hdf5_handler import fill_hdf5_table
13
13
  from simtools.simtel.simtel_io_histogram import (
14
14
  HistogramIdNotFoundError,
15
15
  InconsistentHistogramFormatError,
@@ -159,7 +159,7 @@ class SimtelIOHistograms:
159
159
  if sim_hist is None or trig_hist is None:
160
160
  msg = (
161
161
  "Simulated and triggered histograms were not found in the stacked histograms."
162
- " Please check your sim_telarray files!"
162
+ " Please check sim_telarray files!"
163
163
  )
164
164
  self._logger.error(msg)
165
165
  raise HistogramIdNotFoundError
@@ -285,7 +285,11 @@ class SimtelIOHistograms:
285
285
  f"Estimated equivalent observation time corresponding to the number of "
286
286
  f"events simulated: {obs_time.value} s"
287
287
  )
288
- sim_event_rate = _simulated_events / obs_time
288
+ if obs_time != 0:
289
+ sim_event_rate = _simulated_events / obs_time
290
+ else:
291
+ sim_event_rate = 0.0 * obs_time.unit
292
+ logging.warning("Observation time is zero, cannot calculate event rate.")
289
293
  sim_event_rates.append(sim_event_rate)
290
294
  logging.info(f"Simulated event rate: {sim_event_rate.value:.4e} Hz")
291
295
 
@@ -2,11 +2,15 @@
2
2
  """Read metadata from sim_telarray files."""
3
3
 
4
4
  import logging
5
+ import re
5
6
  from functools import cache
6
7
 
7
8
  from eventio import EventIOFile
9
+ from eventio.iact import InputCard
8
10
  from eventio.simtel import HistoryMeta
9
11
 
12
+ from simtools.utils import names
13
+
10
14
  _logger = logging.getLogger(__name__)
11
15
 
12
16
 
@@ -56,9 +60,12 @@ def read_sim_telarray_metadata(file, encoding="utf8"):
56
60
  return {k: v.strip() if isinstance(v, str) else v for k, v in meta.items()}
57
61
 
58
62
  # keys to lower case and strip leading '*', trailing spaces
59
- return clean_meta(global_meta), {
60
- tel_id: clean_meta(meta) for tel_id, meta in telescope_meta.items()
61
- }
63
+ try:
64
+ return clean_meta(global_meta), {
65
+ tel_id: clean_meta(meta) for tel_id, meta in telescope_meta.items()
66
+ }
67
+ except AttributeError as e:
68
+ raise AttributeError(f"Error reading metadata from file {file}: {e}") from e
62
69
 
63
70
 
64
71
  def _decode_dictionary(meta, encoding="utf8"):
@@ -104,3 +111,92 @@ def get_sim_telarray_telescope_id(telescope_name, file):
104
111
  telescope_name_to_sim_telarray_id[telescope_name] = tel_id
105
112
 
106
113
  return telescope_name_to_sim_telarray_id.get(telescope_name, None)
114
+
115
+
116
+ def get_sim_telarray_telescope_id_to_telescope_name_mapping(file):
117
+ """
118
+ Return a mapping of telescope IDs to telescope names from a sim_telarray file.
119
+
120
+ Parameters
121
+ ----------
122
+ file: str
123
+ Path to the sim_telarray file.
124
+
125
+ Returns
126
+ -------
127
+ dict
128
+ Dictionary mapping telescope IDs to telescope names.
129
+ """
130
+ _, telescope_meta = read_sim_telarray_metadata(file)
131
+ telescope_map = {}
132
+ for i, (tel_id, meta) in enumerate(telescope_meta.items()):
133
+ try:
134
+ telescope_name = names.validate_array_element_name(
135
+ meta.get("optics_config_name", f"Unknown-{tel_id}")
136
+ )
137
+ except ValueError:
138
+ telescope_name = _guess_telescope_name_for_legacy_files(i, file)
139
+ if telescope_name is not None:
140
+ telescope_map[tel_id] = telescope_name
141
+
142
+ return telescope_map
143
+
144
+
145
+ def _guess_telescope_name_for_legacy_files(tel_counter, file):
146
+ """
147
+ Guess telescope names for legacy prod6 sim_telarray files with incomplete metadata.
148
+
149
+ Parameters
150
+ ----------
151
+ tel_counter: int
152
+ Telescope counter, used to index into the telescope list.
153
+ file: str, Path
154
+ Path to the sim_telarray file.
155
+
156
+ Returns
157
+ -------
158
+ str, None
159
+ Guessed telescope name or None if not found.
160
+ """
161
+ telescope_list = _get_telescope_list_from_input_card(file)
162
+ try:
163
+ return names.validate_array_element_name(telescope_list[tel_counter])
164
+ except (IndexError, ValueError):
165
+ pass
166
+ return None
167
+
168
+
169
+ @cache
170
+ def _get_telescope_list_from_input_card(file):
171
+ r"""
172
+ Return telescope list from CORSIKA input card.
173
+
174
+ Note hardwired regex pattern with telescope naming convention.
175
+ This function is intended for legacy files generated for prod6,
176
+ where metadata is incomplete.
177
+
178
+ Expected format in input card:
179
+
180
+ .. code-block:: console
181
+ TELESCOPE -70.91E2 -52.35E2 45.00E2 12.50E2 # (ID=1) LSTN 01 2B5\n
182
+
183
+ Parameters
184
+ ----------
185
+ file: str, Path
186
+ Path to the sim_telarray file.
187
+
188
+ Returns
189
+ -------
190
+ list
191
+ List of telescope names as found in CORSIKA input card.
192
+ """
193
+ with EventIOFile(file) as f:
194
+ for o in f:
195
+ if isinstance(o, InputCard):
196
+ input_card = o.parse().decode("utf-8")
197
+ regex = (
198
+ r"TELESCOPE\s+[-\d.E]+\s+[-\d.E]+\s+[-\d.E]+\s+[-\d.E]+\s+"
199
+ r"# \(ID=\d+\)\s+(LST[N|S]|MST[N|S]|S[S|C]TS)\s+([^\s]+)"
200
+ )
201
+ return [f"{m[0]}-{m[1]}" for m in re.findall(regex, input_card)]
202
+ return []
@@ -6,9 +6,10 @@ import re
6
6
  from pathlib import Path
7
7
 
8
8
  import astropy.units as u
9
+ import numpy as np
9
10
  from astropy.table import Table
10
11
 
11
- from simtools.utils import general as gen
12
+ from simtools.io import ascii_handler
12
13
 
13
14
  logger = logging.getLogger(__name__)
14
15
 
@@ -132,11 +133,6 @@ def _data_columns_camera_filter():
132
133
  )
133
134
 
134
135
 
135
- def _data_columns_lightguide_efficiency_vs_wavelength():
136
- """Column description for parameter lightguide_efficiency_vs_wavelength."""
137
- return _data_columns_lightguide_efficiency_vs_incidence_angle()
138
-
139
-
140
136
  def _data_columns_lightguide_efficiency_vs_incidence_angle():
141
137
  """Column description for (parameter lightguide_efficiency_vs_incidence_angle."""
142
138
  return (
@@ -201,6 +197,16 @@ def _data_columns_mirror_reflectivity(n_columns, n_dim):
201
197
  return _columns, "Mirror reflectivity"
202
198
 
203
199
 
200
+ def _data_columns_secondary_mirror_reflectivity():
201
+ """Column description for secondary mirror reflectivity."""
202
+ columns = [
203
+ {"name": "wavelength", "description": "Wavelength", "unit": "nm"},
204
+ {"name": "reflectivity", "description": "Reflectivity", "unit": None},
205
+ ]
206
+
207
+ return columns, "Secondary mirror reflectivity vs wavelength"
208
+
209
+
204
210
  def _data_columns_pulse_shape(n_columns):
205
211
  """Column description for parameters discriminator_pulse_shape, fadc_pulse_shape."""
206
212
  _columns = [
@@ -259,6 +265,8 @@ def read_simtel_table(parameter_name, file_path):
259
265
 
260
266
  if parameter_name == "atmospheric_transmission":
261
267
  return _read_simtel_data_for_atmospheric_transmission(file_path)
268
+ if parameter_name == "lightguide_efficiency_vs_wavelength":
269
+ return _read_simtel_data_for_lightguide_efficiency(file_path)
262
270
 
263
271
  rows, meta_from_simtel, n_columns, n_dim = _read_simtel_data(file_path)
264
272
  columns_info, description = _data_columns(parameter_name, n_columns, n_dim)
@@ -291,6 +299,17 @@ def _adjust_columns_length(rows, n_columns):
291
299
  return [row[:n_columns] + [0.0] * max(0, n_columns - len(row)) for row in rows]
292
300
 
293
301
 
302
+ def _process_line_parts(parts):
303
+ """Convert parts to floats, skipping non-float entries."""
304
+ row = []
305
+ for p in parts:
306
+ try:
307
+ row.append(float(p))
308
+ except ValueError:
309
+ logger.debug(f"Skipping non-float part: {p}")
310
+ return row
311
+
312
+
294
313
  def _read_simtel_data(file_path):
295
314
  """
296
315
  Read data, comments, and (if available) axis definition from sim_telarray table.
@@ -311,7 +330,7 @@ def _read_simtel_data(file_path):
311
330
  n_dim_axis = None
312
331
  r_pol_axis = None
313
332
 
314
- lines = gen.read_file_encoded_in_utf_or_latin(file_path)
333
+ lines = ascii_handler.read_file_encoded_in_utf_or_latin(file_path)
315
334
 
316
335
  for line in lines:
317
336
  stripped = line.strip()
@@ -326,12 +345,75 @@ def _read_simtel_data(file_path):
326
345
  elif stripped: # Data
327
346
  data_lines.append(stripped.split("%%%")[0].split("#")[0].strip()) # Remove comments
328
347
 
329
- rows = [[float(part) for part in line.split()] for line in data_lines]
348
+ rows = [_process_line_parts(line.split()) for line in data_lines]
330
349
  n_columns = max(len(row) for row in rows) if rows else 0
331
350
 
332
351
  return rows, "\n".join(meta_lines), n_columns, n_dim_axis
333
352
 
334
353
 
354
+ def _read_simtel_data_for_lightguide_efficiency(file_path):
355
+ """
356
+ Read angular efficiency data and return a table with columns: angle, wavelength, efficiency.
357
+
358
+ Parameters
359
+ ----------
360
+ file_path : str or Path
361
+
362
+ Returns
363
+ -------
364
+ astropy.table.Table
365
+ """
366
+ wavelengths = []
367
+ data = []
368
+ meta_lines = []
369
+
370
+ lines = ascii_handler.read_file_encoded_in_utf_or_latin(file_path)
371
+
372
+ def extract_wavelengths_from_header(line):
373
+ match = re.search(r"orig\.:\s*(.*)", line)
374
+ return [float(wl.replace("nm", "")) for wl in match.group(1).split()]
375
+
376
+ for line in lines:
377
+ line = line.strip()
378
+
379
+ if not line:
380
+ continue
381
+
382
+ if line.startswith("#"):
383
+ meta_lines.append(line.lstrip("#").strip())
384
+ if "orig.:" in line:
385
+ wavelengths = extract_wavelengths_from_header(line)
386
+ continue
387
+
388
+ parts = line.split()
389
+ try:
390
+ theta = float(parts[0])
391
+ eff_values = list(map(float, parts[-len(wavelengths) :]))
392
+ data.extend((theta, wl, eff) for wl, eff in zip(wavelengths, eff_values))
393
+ except (ValueError, IndexError):
394
+ logger.debug(f"Skipping malformed line: {line}")
395
+ continue
396
+
397
+ if not data or not wavelengths:
398
+ raise ValueError("No valid data or wavelengths found in file")
399
+
400
+ table = Table(rows=data, names=["angle", "wavelength", "efficiency"])
401
+ table["angle"].unit = u.deg
402
+ table["wavelength"].unit = u.nm
403
+ table["efficiency"].unit = u.dimensionless_unscaled
404
+
405
+ table.meta.update(
406
+ {
407
+ "Name": "angular_efficiency",
408
+ "File": str(file_path),
409
+ "Description": "Angular efficiency vs wavelength",
410
+ "Context_from_sim_telarray": "\n".join(meta_lines),
411
+ }
412
+ )
413
+
414
+ return table
415
+
416
+
335
417
  def _read_simtel_data_for_atmospheric_transmission(file_path):
336
418
  """
337
419
  Read data and comments from sim_telarray table for atmospheric_transmission.
@@ -346,7 +428,7 @@ def _read_simtel_data_for_atmospheric_transmission(file_path):
346
428
  astropy table
347
429
  Table with atmospheric transmission.
348
430
  """
349
- lines = lines = gen.read_file_encoded_in_utf_or_latin(file_path)
431
+ lines = ascii_handler.read_file_encoded_in_utf_or_latin(file_path)
350
432
 
351
433
  observatory_level, height_bins = _read_header_line_for_atmospheric_transmission(
352
434
  lines, file_path
@@ -366,7 +448,7 @@ def _read_simtel_data_for_atmospheric_transmission(file_path):
366
448
  wl = float(parts[0])
367
449
  for i, height in enumerate(height_bins):
368
450
  extinction_value = float(parts[i + 1])
369
- if extinction_value == 99999.0:
451
+ if np.isclose(extinction_value, 99999.0):
370
452
  continue
371
453
  wavelengths.append(wl)
372
454
  heights.append(height)