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
@@ -0,0 +1,71 @@
1
+ r"""
2
+ Generate new simulation model production tables by copying existing table and apply modifications.
3
+
4
+ This script should be used to maintain the simulation model repository. It allow to create a
5
+ new production table by copying an existing base version and apply modification defined in a YAML
6
+ file (see the example file listed below).
7
+
8
+ Example
9
+ -------
10
+ .. code-block:: console
11
+
12
+ simtools-maintain-simulation-model-add-production-table \\
13
+ --simulation_models_path ../simulation-models-dev/simulation-models/ \\
14
+ --source_prod_table_dir 6.0.0 \\
15
+ --modifications tests/resources/production_tables_changes_for_threshold_study_6.2.0.yml
16
+
17
+ """
18
+
19
+ import logging
20
+ from pathlib import Path
21
+
22
+ import simtools.utils.general as gen
23
+ from simtools.configuration import configurator
24
+ from simtools.model import model_repository
25
+
26
+
27
+ def _parse(label, description):
28
+ """
29
+ Parse command line arguments.
30
+
31
+ Returns
32
+ -------
33
+ dict
34
+ Parsed command-line arguments.
35
+ """
36
+ config = configurator.Configurator(label=label, description=description)
37
+ config.parser.add_argument(
38
+ "--simulation_models_path",
39
+ type=str,
40
+ required=True,
41
+ help="Path to the simulation models repository.",
42
+ )
43
+ config.parser.add_argument(
44
+ "--source_prod_table_dir",
45
+ type=str,
46
+ required=True,
47
+ help="The source production table directory to copy from.",
48
+ )
49
+ config.parser.add_argument(
50
+ "--modifications",
51
+ type=str,
52
+ required=True,
53
+ help="File containing the list of changes to apply.",
54
+ )
55
+
56
+ return config.initialize(db_config=False, output=False)
57
+
58
+
59
+ def main(): # noqa: D103
60
+ label = Path(__file__).stem
61
+ args_dict, _ = _parse(
62
+ label=label, description=("Copy and update simulation model production tables.")
63
+ )
64
+ logger = logging.getLogger()
65
+ logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
66
+
67
+ model_repository.copy_and_update_production_table(args_dict)
68
+
69
+
70
+ if __name__ == "__main__":
71
+ main()
@@ -0,0 +1,98 @@
1
+ r"""
2
+ Compare two directories with model production tables in JSON format.
3
+
4
+ This script should be used to support the maintenance the simulation model repository.
5
+
6
+ Example
7
+ -------
8
+ .. code-block:: console
9
+
10
+ simtools-maintain-simulation-model-compare-productions \\
11
+ --directory_1 ../simulation-models-dev/simulation-models/6.0.0/ \\
12
+ --directory_2 ../simulation-models-dev/simulation-models/6.2.0
13
+
14
+ """
15
+
16
+ import logging
17
+ from pathlib import Path
18
+
19
+ import simtools.utils.general as gen
20
+ from simtools.configuration import configurator
21
+ from simtools.io import ascii_handler
22
+
23
+
24
+ def _parse(label, description):
25
+ """Parse command line arguments."""
26
+ config = configurator.Configurator(label=label, description=description)
27
+ config.parser.add_argument(
28
+ "--directory_1",
29
+ type=str,
30
+ required=True,
31
+ help="Path to the first directory containing JSON files.",
32
+ )
33
+ config.parser.add_argument(
34
+ "--directory_2",
35
+ type=str,
36
+ required=True,
37
+ help="Path to the second directory containing JSON files.",
38
+ )
39
+ return config.initialize(db_config=False, output=False)
40
+
41
+
42
+ def _print_differences(differences, rel_path):
43
+ """Print differences in a readable format."""
44
+ print(f"Difference in {rel_path}:\n{'-' * 40}")
45
+ for diff in differences:
46
+ # Clean up the path formatting for better readability
47
+ clean_diff = diff.replace("['parameters']['", "parameters.").replace("']['", ".")
48
+ clean_diff = clean_diff.replace("['", "").replace("']", "")
49
+ print(f" {clean_diff}")
50
+ print(f"{'-' * 40}\n")
51
+
52
+
53
+ def _compare_json_dirs(dir1, dir2, ignore_key="model_version"):
54
+ """Compare two directories containing JSON files, ignoring a specific key."""
55
+ for path1 in dir1.rglob("*.json"):
56
+ rel_path = path1.relative_to(dir1)
57
+ path2 = dir2 / rel_path
58
+
59
+ if not path2.exists():
60
+ print(f"Missing in dir2: {rel_path}")
61
+ continue
62
+
63
+ try:
64
+ json1 = gen.remove_key_from_dict(
65
+ ascii_handler.collect_data_from_file(path1), ignore_key
66
+ )
67
+ json2 = gen.remove_key_from_dict(
68
+ ascii_handler.collect_data_from_file(path2), ignore_key
69
+ )
70
+ except FileNotFoundError as e:
71
+ print(f"Error reading {rel_path}: {e}")
72
+ continue
73
+
74
+ differences = gen.find_differences_in_json_objects(json1, json2)
75
+ if differences:
76
+ _print_differences(differences, rel_path)
77
+
78
+ # Check for files present in dir2 but not dir1
79
+ for path2 in dir2.rglob("*.json"):
80
+ rel_path = path2.relative_to(dir2)
81
+ if not (dir1 / rel_path).exists():
82
+ print(f"Missing in dir1: {rel_path}")
83
+
84
+
85
+ def main(): # noqa: D103
86
+ label = Path(__file__).stem
87
+ args_dict, _ = _parse(
88
+ label=label,
89
+ description=("Compare two directories with model production tables in JSON format."),
90
+ )
91
+ logger = logging.getLogger()
92
+ logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
93
+
94
+ _compare_json_dirs(Path(args_dict["directory_1"]), Path(args_dict["directory_2"]))
95
+
96
+
97
+ if __name__ == "__main__":
98
+ main()
@@ -1,12 +1,20 @@
1
1
  #!/usr/bin/python3
2
2
 
3
- """
3
+ r"""
4
4
  Verify simulation model production tables and model parameters for completeness.
5
5
 
6
6
  This application is a utility to be used in the CI pipeline of the SimulationModels
7
7
  repository. It checks that all model parameters defined in the production tables
8
8
  exist in the simulation models repository.
9
9
 
10
+ Example
11
+ -------
12
+
13
+ .. code-block:: console
14
+
15
+ simtools-maintain-simulation-model-verify-production-tables \\
16
+ --simulation_models_path /path/to/simulation/models/repository
17
+
10
18
  """
11
19
 
12
20
  import logging
@@ -1,11 +1,11 @@
1
1
  r"""
2
2
  Merge tables from multiple input files into single tables.
3
3
 
4
- Allows to merge tables from multiple input files into a single file.
5
- The input files can be in HDF5 or FITS format. The merged tables will be saved in the
4
+ Allows to merge tables (e.g., astropy tables) from multiple input files into a single file.
5
+ The input files can be of HDF5 or FITS format.
6
6
  specified output file.
7
7
 
8
- Note that merging large tables in FITS are not recommended, as it may lead to
8
+ Merging large tables in FITS are not recommended, as it may lead to
9
9
  performance issues.
10
10
 
11
11
  Command line arguments
@@ -14,7 +14,7 @@ input str
14
14
  Input file(s) (e.g., 'file1 file2').
15
15
  input_list str
16
16
  File with list of input files with tables.
17
- table_names str
17
+ table_names list of str
18
18
  Names of tables to merge from each input file.
19
19
  output_file str
20
20
  Output file name.
@@ -24,12 +24,12 @@ output_path str
24
24
  Example
25
25
  -------
26
26
 
27
- Merge tables from two files into a single file.
27
+ Merge tables from two files generated with 'simtools-generate-simtel-event-data' into a single file.
28
28
 
29
29
  .. code-block:: console
30
30
 
31
31
  simtools-merge-tables \\
32
- --input file1 file2' \\
32
+ --input_files file1 file2' \\
33
33
  --table_names 'SHOWERS TRIGGERS FILE_INFO' \\
34
34
  --output_file merged_tables.hdf5
35
35
 
@@ -41,7 +41,7 @@ from pathlib import Path
41
41
 
42
42
  import simtools.utils.general as gen
43
43
  from simtools.configuration import configurator
44
- from simtools.io_operations import io_handler, io_table_handler
44
+ from simtools.io import io_handler, table_handler
45
45
 
46
46
 
47
47
  def _parse(label, description):
@@ -57,15 +57,10 @@ def _parse(label, description):
57
57
 
58
58
  input_group = config.parser.add_mutually_exclusive_group(required=True)
59
59
  input_group.add_argument(
60
- "--input",
60
+ "--input_files",
61
61
  type=str,
62
62
  nargs="+",
63
- help="Input file(s) (e.g., 'file1 file2')",
64
- )
65
- input_group.add_argument(
66
- "--input_list",
67
- type=str,
68
- help="File with list of input files with tables.",
63
+ help="Input file(s) (e.g., 'file1 file2') or a file with a list of input files.",
69
64
  )
70
65
  config.parser.add_argument(
71
66
  "--table_names",
@@ -86,14 +81,17 @@ def main(): # noqa: D103
86
81
  )
87
82
  logger = logging.getLogger()
88
83
  logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
89
- logger.info(f"Loading input files from: {args_dict['input']}")
84
+ logger.info(f"Loading input files: {args_dict['input_files']}")
85
+
86
+ # accept fits.gz files (.gz)
87
+ input_files = gen.get_list_of_files_from_command_line(
88
+ args_dict["input_files"], [".hdf5", ".gz"]
89
+ )
90
90
 
91
91
  output_path = io_handler.IOHandler().get_output_directory(label)
92
92
  output_filepath = Path(output_path).joinpath(f"{args_dict['output_file']}")
93
93
 
94
- input_files = args_dict.get("input") or gen.collect_data_from_file(args_dict["input_list"])
95
-
96
- io_table_handler.merge_tables(
94
+ table_handler.merge_tables(
97
95
  input_files,
98
96
  input_table_names=args_dict["table_names"],
99
97
  output_file=output_filepath,
@@ -13,7 +13,7 @@ For the following options, array element positions are retrieved from the model
13
13
  (``--plot_all_layouts``)
14
14
 
15
15
  * from a model parameter file
16
- (e.g., ``-array_layout_parameter_file tests/resources/model_parameters/array_layouts-2.0.1.json``)
16
+ (e.g., ``-array_layout_parameter_file tests/resources/model_parameters/array_layouts-2.0.2.json``)
17
17
 
18
18
  * from a list of array elements (e.g., ``-array_element_list MSTN-01, MSTN-02``).
19
19
  Positions are retrieved from the database.
@@ -88,7 +88,7 @@ Plot layout from a parameter file with a list of telescopes:
88
88
  .. code-block:: console
89
89
 
90
90
  simtools-plot-array-layout
91
- --array_layout_parameter_file tests/resources/model_parameters/array_layouts-2.0.1.json
91
+ --array_layout_parameter_file tests/resources/model_parameters/array_layouts-2.0.2.json
92
92
  --model_version 6.0.0
93
93
 
94
94
 
@@ -108,7 +108,7 @@ import matplotlib.pyplot as plt
108
108
  import simtools.layout.array_layout_utils as layout_utils
109
109
  import simtools.utils.general as gen
110
110
  from simtools.configuration import configurator
111
- from simtools.io_operations import io_handler
111
+ from simtools.io import io_handler
112
112
  from simtools.visualization import visualize
113
113
  from simtools.visualization.plot_array_layout import plot_array_layout
114
114
 
@@ -0,0 +1,379 @@
1
+ #!/usr/bin/python3
2
+
3
+ r"""
4
+ Plot simulated events.
5
+
6
+ This application produces figures from one or more sim_telarray (.simtel.zst) files
7
+ by calling functions in ``simtools.visualization.simtel_event_plots``. It is meant to
8
+ run after simulations (e.g., simtools-simulate-flasher, simtools-simulate-illuminator).
9
+
10
+ What it does
11
+ ------------
12
+ - Loads each provided sim_telarray file
13
+ - Generates selected plots (camera image, time traces, waveform matrices, peak timing, etc.)
14
+ - Optionally saves all figures to a single multi-page PDF per input file
15
+ - Optionally also saves individual PNGs
16
+
17
+ Command line arguments
18
+ ----------------------
19
+ simtel_files (list, required)
20
+ One or more sim_telarray files to visualize (.simtel.zst).
21
+ plots (list, optional)
22
+ Which plots to generate. Choose from: event_image, time_traces, waveform_matrix,
23
+ step_traces, integrated_signal_image, integrated_pedestal_image, peak_timing, all.
24
+ Default: event_image.
25
+ tel_id (int, optional)
26
+ Telescope ID to visualize. If omitted, the first available telescope will be used.
27
+ n_pixels (int, optional)
28
+ For time_traces: number of pixel traces to draw. Default: 3.
29
+ pixel_step (int, optional)
30
+ For step_traces and waveform_matrix: step between pixel indices. Default: 100.
31
+ max_pixels (int, optional)
32
+ For step_traces: cap the number of plotted pixels. Default: None.
33
+ vmax (float, optional)
34
+ For waveform_matrix: upper limit of color scale. Default: None.
35
+ half_width (int, optional)
36
+ For integrated_*_image: half window width in samples. Default: 8.
37
+ offset (int, optional)
38
+ For integrated_pedestal_image: offset between pedestal and peak windows. Default: 16.
39
+ sum_threshold (float, optional)
40
+ For peak_timing: minimum pixel sum to consider a pixel. Default: 10.0.
41
+ peak_width (int, optional)
42
+ For peak_timing: expected peak width in samples. Default: 8.
43
+ examples (int, optional)
44
+ For peak_timing: show example traces. Default: 3.
45
+ timing_bins (int, optional)
46
+ For peak_timing: number of histogram bins for peak sample. Default: None (contiguous bins).
47
+ distance (float, optional)
48
+ Optional distance annotation for event_image.
49
+ output_file (str, optional)
50
+ Base name for output. If provided, outputs will be placed under the standard IOHandler
51
+ output directory and named ``<base>_<inputstem>.pdf``. If omitted, defaults are derived
52
+ from each input file name.
53
+ save_pngs (flag, optional)
54
+ Also save individual PNG files per figure.
55
+ dpi (int, optional)
56
+ DPI for PNG outputs. Default: 300.
57
+ output_path (str, optional)
58
+ Path to save the output files.
59
+
60
+ Examples
61
+ --------
62
+ 1) Camera image and time traces for a single file, save a PDF:
63
+
64
+ simtools-plot-simtel-events \
65
+ --simtel_files tests/resources/ff-1m_flasher.simtel.zst \
66
+ --plots event_image time_traces \
67
+ --tel_id 1 \
68
+ --output_file simulate_illuminator_inspect
69
+
70
+ 2) All plots for multiple files, PNGs and PDFs:
71
+
72
+ simtools-plot-simtel-events \
73
+ --simtel_files f1.simtel.zst f2.simtel.zst \
74
+ --plots all \
75
+ --save_pngs --dpi 200
76
+
77
+ """
78
+
79
+ import logging
80
+ from pathlib import Path
81
+
82
+ import simtools.utils.general as gen
83
+ from simtools.configuration import configurator
84
+ from simtools.corsika.corsika_histograms_visualize import save_figs_to_pdf
85
+ from simtools.data_model.metadata_collector import MetadataCollector
86
+ from simtools.io import io_handler
87
+ from simtools.visualization.simtel_event_plots import (
88
+ plot_simtel_event_image,
89
+ plot_simtel_integrated_pedestal_image,
90
+ plot_simtel_integrated_signal_image,
91
+ plot_simtel_peak_timing,
92
+ plot_simtel_step_traces,
93
+ plot_simtel_time_traces,
94
+ plot_simtel_waveform_matrix,
95
+ )
96
+
97
+ PLOT_CHOICES = {
98
+ "event_image": "event_image",
99
+ "time_traces": "time_traces",
100
+ "waveform_matrix": "waveform_matrix",
101
+ "step_traces": "step_traces",
102
+ "integrated_signal_image": "integrated_signal_image",
103
+ "integrated_pedestal_image": "integrated_pedestal_image",
104
+ "peak_timing": "peak_timing",
105
+ "all": "all",
106
+ }
107
+
108
+
109
+ def _parse(label: str):
110
+ """Parse command line configuration."""
111
+ config = configurator.Configurator(
112
+ label=label,
113
+ description=(
114
+ "Create diagnostic plots from sim_telarray files using simtools visualization."
115
+ ),
116
+ )
117
+
118
+ config.parser.add_argument(
119
+ "--simtel_files",
120
+ help="One or more sim_telarray files (.simtel.zst)",
121
+ nargs="+",
122
+ required=True,
123
+ )
124
+ config.parser.add_argument(
125
+ "--plots",
126
+ help=f"Plots to generate. Choices: {', '.join(sorted(PLOT_CHOICES))}",
127
+ nargs="+",
128
+ default=["event_image"],
129
+ choices=sorted(PLOT_CHOICES),
130
+ )
131
+ # common plotting options
132
+ config.parser.add_argument("--tel_id", type=int, default=None, help="Telescope ID")
133
+ config.parser.add_argument(
134
+ "--n_pixels", type=int, default=3, help="For time_traces: number of pixel traces"
135
+ )
136
+ config.parser.add_argument(
137
+ "--pixel_step", type=int, default=100, help="Step between pixel ids for step plots"
138
+ )
139
+ config.parser.add_argument(
140
+ "--max_pixels", type=int, default=None, help="Cap number of pixels for step traces"
141
+ )
142
+ config.parser.add_argument("--vmax", type=float, default=None, help="Color scale vmax")
143
+ config.parser.add_argument(
144
+ "--half_width", type=int, default=8, help="Half window width for integrated images"
145
+ )
146
+ config.parser.add_argument(
147
+ "--offset",
148
+ type=int,
149
+ default=16,
150
+ help="offset between pedestal and peak windows (integrated_pedestal_image)",
151
+ )
152
+ config.parser.add_argument(
153
+ "--sum_threshold",
154
+ type=float,
155
+ default=10.0,
156
+ help="Minimum pixel sum to consider in peak timing",
157
+ )
158
+ config.parser.add_argument(
159
+ "--peak_width", type=int, default=8, help="Expected peak width in samples"
160
+ )
161
+ config.parser.add_argument(
162
+ "--examples", type=int, default=3, help="Number of example traces to draw"
163
+ )
164
+ config.parser.add_argument(
165
+ "--timing_bins",
166
+ type=int,
167
+ default=None,
168
+ help="Number of bins for timing histogram (contiguous if not set)",
169
+ )
170
+ config.parser.add_argument(
171
+ "--distance",
172
+ type=float,
173
+ default=None,
174
+ help="Optional distance annotation for event_image (same units as input expects)",
175
+ )
176
+ config.parser.add_argument(
177
+ "--event_index",
178
+ type=int,
179
+ default=None,
180
+ help="0-based index of the event to plot; default is the first event",
181
+ )
182
+ # outputs
183
+ config.parser.add_argument(
184
+ "--output_file",
185
+ type=str,
186
+ default=None,
187
+ help=(
188
+ "Base name for output. If set, PDFs will be named '<base>_<inputstem>.pdf' "
189
+ "in the standard output directory"
190
+ ),
191
+ )
192
+ config.parser.add_argument(
193
+ "--save_pngs",
194
+ action="store_true",
195
+ help="Also save individual PNG images per plot",
196
+ )
197
+ config.parser.add_argument("--dpi", type=int, default=300, help="PNG dpi")
198
+
199
+ return config.initialize(db_config=False, require_command_line=True)
200
+
201
+
202
+ def _save_png(fig, out_dir: Path, stem: str, suffix: str, dpi: int):
203
+ """Save ``fig`` as a PNG into ``out_dir`` using ``stem`` and ``suffix``.
204
+
205
+ Errors during saving are logged as warnings and otherwise ignored.
206
+ """
207
+ png_path = out_dir.joinpath(f"{stem}_{suffix}.png")
208
+ try:
209
+ fig.savefig(png_path, dpi=dpi, bbox_inches="tight")
210
+ except Exception as ex: # pylint:disable=broad-except
211
+ logging.getLogger(__name__).warning("Failed to save PNG %s: %s", png_path, ex)
212
+
213
+
214
+ def _make_output_paths(
215
+ ioh: io_handler.IOHandler, base: str | None, input_file: Path
216
+ ) -> tuple[Path, Path]:
217
+ """Return (out_dir, pdf_path) based on base and input_file."""
218
+ out_dir = ioh.get_output_directory(label=Path(__file__).stem)
219
+ if base:
220
+ pdf_path = ioh.get_output_file(f"{base}_{input_file.stem}")
221
+ else:
222
+ pdf_path = ioh.get_output_file(input_file.stem)
223
+ pdf_path = Path(f"{pdf_path}.pdf") if pdf_path.suffix != ".pdf" else Path(pdf_path)
224
+ return out_dir, pdf_path
225
+
226
+
227
+ def _collect_figures_for_file(
228
+ filename: Path,
229
+ plots: list[str],
230
+ args: dict,
231
+ out_dir: Path,
232
+ base_stem: str,
233
+ save_pngs: bool,
234
+ dpi: int,
235
+ ):
236
+ """Generate the selected plots for a single sim_telarray file.
237
+
238
+ Returns a list of figures. If ``save_pngs`` is True, also writes PNGs to
239
+ ``out_dir`` using ``base_stem`` for filenames.
240
+ """
241
+ logger = logging.getLogger(__name__)
242
+ figures: list[object] = []
243
+
244
+ def add(fig, tag: str):
245
+ if fig is not None:
246
+ figures.append(fig)
247
+ if save_pngs:
248
+ _save_png(fig, out_dir, base_stem, tag, dpi)
249
+ else:
250
+ logger.warning("Plot '%s' returned no figure for %s", tag, filename)
251
+
252
+ plots_to_run = (
253
+ [
254
+ "event_image",
255
+ "time_traces",
256
+ "waveform_matrix",
257
+ "step_traces",
258
+ "integrated_signal_image",
259
+ "integrated_pedestal_image",
260
+ "peak_timing",
261
+ ]
262
+ if "all" in plots
263
+ else list(plots)
264
+ )
265
+
266
+ def _call_peak_timing():
267
+ try:
268
+ fig_stats = plot_simtel_peak_timing(
269
+ filename,
270
+ tel_id=args.get("tel_id"),
271
+ sum_threshold=args.get("sum_threshold", 10.0),
272
+ peak_width=args.get("peak_width", 8),
273
+ examples=args.get("examples", 3),
274
+ timing_bins=args.get("timing_bins"),
275
+ return_stats=True,
276
+ event_index=args.get("event_index"),
277
+ )
278
+ return fig_stats[0] if isinstance(fig_stats, tuple) else fig_stats
279
+ except TypeError:
280
+ return plot_simtel_peak_timing(
281
+ filename,
282
+ tel_id=args.get("tel_id"),
283
+ sum_threshold=args.get("sum_threshold", 10.0),
284
+ peak_width=args.get("peak_width", 8),
285
+ examples=args.get("examples", 3),
286
+ timing_bins=args.get("timing_bins"),
287
+ event_index=args.get("event_index"),
288
+ )
289
+
290
+ # function name -> (callable, defaults)
291
+ dispatch: dict[str, tuple[object, dict[str, object]]] = {
292
+ "event_image": (
293
+ plot_simtel_event_image,
294
+ {"distance": None, "event_index": None},
295
+ ),
296
+ "time_traces": (
297
+ plot_simtel_time_traces,
298
+ {"tel_id": None, "n_pixels": 3, "event_index": None},
299
+ ),
300
+ "waveform_matrix": (
301
+ plot_simtel_waveform_matrix,
302
+ {"tel_id": None, "vmax": None, "event_index": None},
303
+ ),
304
+ "step_traces": (
305
+ plot_simtel_step_traces,
306
+ {"tel_id": None, "pixel_step": None, "max_pixels": None, "event_index": None},
307
+ ),
308
+ "integrated_signal_image": (
309
+ plot_simtel_integrated_signal_image,
310
+ {"tel_id": None, "half_width": 8, "event_index": None},
311
+ ),
312
+ "integrated_pedestal_image": (
313
+ plot_simtel_integrated_pedestal_image,
314
+ {"tel_id": None, "half_width": 8, "offset": 16, "event_index": None},
315
+ ),
316
+ }
317
+
318
+ for plot_name in plots_to_run:
319
+ if plot_name == "peak_timing":
320
+ add(_call_peak_timing(), "peak_timing")
321
+ continue
322
+ entry = dispatch.get(plot_name)
323
+ if entry is None:
324
+ logger.warning("Unknown plot selection '%s'", plot_name)
325
+ continue
326
+ func, defaults = entry
327
+ # Build kwargs with user args overriding defaults
328
+ kwargs = {k: args.get(k, v) for k, v in defaults.items()}
329
+ fig = func(filename, **kwargs) # type: ignore[misc]
330
+ add(fig, plot_name)
331
+
332
+ return figures
333
+
334
+
335
+ def main():
336
+ """Generate plots from sim_telarray files."""
337
+ label = Path(__file__).stem
338
+ args, _db = _parse(label)
339
+
340
+ logger = logging.getLogger()
341
+ logger.setLevel(gen.get_log_level_from_user(args.get("log_level", "INFO")))
342
+
343
+ ioh = io_handler.IOHandler()
344
+
345
+ simtel_files = [Path(p).expanduser() for p in gen.ensure_iterable(args["simtel_files"])]
346
+ plots = list(gen.ensure_iterable(args.get("plots")))
347
+
348
+ for simtel in simtel_files:
349
+ out_dir, pdf_path = _make_output_paths(ioh, args.get("output_file"), simtel)
350
+ figures = _collect_figures_for_file(
351
+ filename=simtel,
352
+ plots=plots,
353
+ args=args,
354
+ out_dir=out_dir,
355
+ base_stem=simtel.stem,
356
+ save_pngs=bool(args.get("save_pngs", False)),
357
+ dpi=int(args.get("dpi", 300)),
358
+ )
359
+
360
+ if not figures:
361
+ logger.warning("No figures produced for %s", simtel)
362
+ continue
363
+
364
+ # Save a multipage PDF
365
+ try:
366
+ save_figs_to_pdf(figures, pdf_path)
367
+ logger.info("Saved PDF: %s", pdf_path)
368
+ except Exception as ex: # pylint:disable=broad-except
369
+ logger.error("Failed to save PDF %s: %s", pdf_path, ex)
370
+
371
+ # Dump run metadata alongside PDF
372
+ try:
373
+ MetadataCollector.dump(args, pdf_path, add_activity_name=True)
374
+ except Exception as ex: # pylint:disable=broad-except
375
+ logger.warning("Failed to write metadata for %s: %s", pdf_path, ex)
376
+
377
+
378
+ if __name__ == "__main__":
379
+ main()