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
simtools/utils/general.py CHANGED
@@ -1,12 +1,10 @@
1
1
  """General functions useful across different parts of the code."""
2
2
 
3
- import copy
4
3
  import datetime
5
4
  import glob
6
- import json
7
5
  import logging
8
6
  import os
9
- import tempfile
7
+ import tarfile
10
8
  import time
11
9
  import urllib.error
12
10
  import urllib.request
@@ -14,54 +12,21 @@ from pathlib import Path
14
12
  from urllib.parse import urlparse
15
13
 
16
14
  import numpy as np
17
- import yaml
18
15
 
19
16
  __all__ = [
20
- "InvalidConfigDataError",
21
17
  "change_dict_keys_case",
22
18
  "clear_default_sim_telarray_cfg_directories",
23
- "collect_data_from_file",
24
19
  "collect_final_lines",
25
20
  "collect_kwargs",
26
21
  "get_log_excerpt",
27
22
  "get_log_level_from_user",
28
23
  "remove_substring_recursively_from_dict",
29
24
  "set_default_kwargs",
30
- "sort_arrays",
31
25
  ]
32
26
 
33
27
  _logger = logging.getLogger(__name__)
34
28
 
35
29
 
36
- class InvalidConfigDataError(Exception):
37
- """Exception for invalid configuration data."""
38
-
39
-
40
- def join_url_or_path(url_or_path, *args):
41
- """
42
- Join URL or path with additional subdirectories and file.
43
-
44
- This is the equivalent to Path.join(), with extended functionality
45
- working also for URLs.
46
-
47
- Parameters
48
- ----------
49
- url_or_path: str or Path
50
- URL or path to be extended.
51
- args: list
52
- Additional arguments to be added to the URL or path.
53
-
54
- Returns
55
- -------
56
- str or Path
57
- Extended URL or path.
58
-
59
- """
60
- if "://" in str(url_or_path):
61
- return "/".join([url_or_path.rstrip("/"), *args])
62
- return Path(url_or_path).joinpath(*args)
63
-
64
-
65
30
  def is_url(url):
66
31
  """
67
32
  Check if a string is a valid URL.
@@ -106,104 +71,6 @@ def url_exists(url):
106
71
  return False
107
72
 
108
73
 
109
- def collect_data_from_http(url):
110
- """
111
- Download yaml or json file from url and return it contents as dict.
112
-
113
- File is downloaded as a temporary file and deleted afterwards.
114
-
115
- Parameters
116
- ----------
117
- url: str
118
- URL of the yaml/json file.
119
-
120
- Returns
121
- -------
122
- dict
123
- Dictionary containing the file content.
124
-
125
- Raises
126
- ------
127
- TypeError
128
- If url is not a valid URL.
129
- FileNotFoundError
130
- If downloading the yaml file fails.
131
-
132
- """
133
- try:
134
- with tempfile.NamedTemporaryFile(mode="w+t") as tmp_file:
135
- urllib.request.urlretrieve(url, tmp_file.name)
136
- data = _collect_data_from_different_file_types(
137
- tmp_file, url, Path(url).suffix.lower(), None
138
- )
139
- except TypeError as exc:
140
- raise TypeError(f"Invalid url {url}") from exc
141
- except urllib.error.HTTPError as exc:
142
- raise FileNotFoundError(f"Failed to download file from {url}") from exc
143
-
144
- _logger.debug(f"Downloaded file from {url}")
145
- return data
146
-
147
-
148
- def collect_data_from_file(file_name, yaml_document=None):
149
- """
150
- Collect data from file based on its extension.
151
-
152
- Parameters
153
- ----------
154
- file_name: str
155
- Name of the yaml/json/ascii file.
156
- yaml_document: None, int
157
- Return list of yaml documents or a single document (for yaml files with several documents).
158
-
159
- Returns
160
- -------
161
- data: dict or list
162
- Data as dict or list.
163
- """
164
- if is_url(file_name):
165
- return collect_data_from_http(file_name)
166
-
167
- suffix = Path(file_name).suffix.lower()
168
- try:
169
- with open(file_name, encoding="utf-8") as file:
170
- return _collect_data_from_different_file_types(file, file_name, suffix, yaml_document)
171
- # broad exception to catch all possible errors in reading the file
172
- except Exception as exc: # pylint: disable=broad-except
173
- raise type(exc)(f"Failed to read file {file_name}: {exc}") from exc
174
- return None
175
-
176
-
177
- def _collect_data_from_different_file_types(file, file_name, suffix, yaml_document):
178
- """Collect data from different file types."""
179
- if suffix == ".json":
180
- return json.load(file)
181
- if suffix in (".list", ".txt"):
182
- return [line.strip() for line in file.readlines()]
183
- if suffix in [".yml", ".yaml"]:
184
- return _collect_data_from_yaml_file(file, file_name, yaml_document)
185
- raise TypeError(f"File type {suffix} not supported.")
186
-
187
-
188
- def _collect_data_from_yaml_file(file, file_name, yaml_document):
189
- """Collect data from a yaml file (allow for multi-document yaml files)."""
190
- try:
191
- return yaml.safe_load(file)
192
- except yaml.constructor.ConstructorError:
193
- return _load_yaml_using_astropy(file)
194
- except yaml.composer.ComposerError:
195
- pass
196
- file.seek(0)
197
- if yaml_document is None:
198
- return list(yaml.safe_load_all(file))
199
- try:
200
- return list(yaml.safe_load_all(file))[yaml_document]
201
- except IndexError as exc:
202
- raise InvalidConfigDataError(
203
- f"YAML file {file_name} does not contain {yaml_document} documents."
204
- ) from exc
205
-
206
-
207
74
  def collect_kwargs(label, in_kwargs):
208
75
  """
209
76
  Collect kwargs of the type label_* and return them as a dict.
@@ -324,10 +191,8 @@ def get_log_level_from_user(log_level):
324
191
  possible_levels = {
325
192
  "info": logging.INFO,
326
193
  "debug": logging.DEBUG,
327
- "warn": logging.WARNING,
328
194
  "warning": logging.WARNING,
329
195
  "error": logging.ERROR,
330
- "critical": logging.CRITICAL,
331
196
  }
332
197
  try:
333
198
  log_level_lower = log_level.lower()
@@ -342,26 +207,27 @@ def get_log_level_from_user(log_level):
342
207
  return possible_levels[log_level_lower]
343
208
 
344
209
 
345
- def copy_as_list(value):
210
+ def ensure_iterable(value):
346
211
  """
347
- Copy value and, if it is not a list, turn it into a list with a single entry.
212
+ Return input value as iterable.
213
+
214
+ - Single values will return as a list with a single element.
215
+ - None values will return as empty list.
216
+ - Values of list or tuple type are not changed.
348
217
 
349
218
  Parameters
350
219
  ----------
351
- value single variable of any type or list
220
+ value: any
221
+ Input value to be converted to a iterable.
352
222
 
353
223
  Returns
354
224
  -------
355
- value: list
356
- Copy of value if it is a list of [value] otherwise.
225
+ list or tuple
226
+ Converted value as list or tuple.
357
227
  """
358
- if isinstance(value, str):
359
- return [value]
360
-
361
- try:
362
- return list(value)
363
- except TypeError:
364
- return [value]
228
+ if not value:
229
+ return []
230
+ return value if isinstance(value, list | tuple) else [value]
365
231
 
366
232
 
367
233
  def program_is_executable(program):
@@ -398,17 +264,17 @@ def _search_directory(directory, filename, rec=False):
398
264
  _logger.debug(f"Directory {directory} does not exist")
399
265
  return None
400
266
 
401
- file = Path(directory).joinpath(filename)
402
- if file.exists():
267
+ _file = Path(directory).joinpath(filename)
268
+ if _file.exists():
403
269
  _logger.debug(f"File {filename} found in {directory}")
404
- return file
270
+ return _file
405
271
 
406
272
  if rec:
407
273
  for subdir in Path(directory).iterdir():
408
274
  if subdir.is_dir():
409
- file = _search_directory(subdir, filename, True)
410
- if file:
411
- return file
275
+ _file = _search_directory(subdir, filename, True)
276
+ if _file:
277
+ return _file
412
278
  return None
413
279
 
414
280
 
@@ -436,15 +302,15 @@ def find_file(name, loc):
436
302
  all_locations = [loc] if not isinstance(loc, list) else loc
437
303
 
438
304
  # Searching file locally
439
- file = _search_directory(".", name)
440
- if file:
441
- return file
305
+ _file = _search_directory(".", name)
306
+ if _file:
307
+ return _file
442
308
 
443
309
  # Searching file in given locations
444
310
  for location in all_locations:
445
- file = _search_directory(location, name, True)
446
- if file:
447
- return file
311
+ _file = _search_directory(location, name, True)
312
+ if _file:
313
+ return _file
448
314
 
449
315
  msg = f"File {name} could not be found in {all_locations}"
450
316
  _logger.error(msg)
@@ -479,6 +345,29 @@ def resolve_file_patterns(file_names):
479
345
  return _files
480
346
 
481
347
 
348
+ def pack_tar_file(tar_file_name, file_list):
349
+ """
350
+ Pack files into a tar.gz archive.
351
+
352
+ Parameters
353
+ ----------
354
+ tar_file_name: str
355
+ Name of the output tar.gz file.
356
+ file_list: list
357
+ List of files to include in the archive.
358
+ """
359
+ file_list = [Path(f) for f in file_list]
360
+ base = Path(os.path.commonpath([f.resolve() for f in file_list]))
361
+ base_resolved = base.resolve()
362
+ for f in file_list:
363
+ if not f.is_file() or not f.resolve().is_relative_to(base_resolved):
364
+ raise ValueError(f"Unsafe file path: {f}")
365
+
366
+ with tarfile.open(tar_file_name, "w:gz") as tar:
367
+ for file in file_list:
368
+ tar.add(file, arcname=file.name)
369
+
370
+
482
371
  def get_log_excerpt(log_file, n_last_lines=30):
483
372
  """
484
373
  Get an excerpt from a log file, namely the n_last_lines of the file.
@@ -617,29 +506,6 @@ def remove_substring_recursively_from_dict(data_dict, substring="\n"):
617
506
  return data_dict
618
507
 
619
508
 
620
- def sort_arrays(*args):
621
- """Sort arrays.
622
-
623
- Parameters
624
- ----------
625
- *args
626
- Arguments to be sorted.
627
-
628
- Returns
629
- -------
630
- list
631
- Sorted args.
632
- """
633
- if len(args) == 0:
634
- return args
635
- order_array = copy.copy(args[0])
636
- new_args = []
637
- for arg in args:
638
- _, value = zip(*sorted(zip(order_array, arg)))
639
- new_args.append(list(value))
640
- return new_args
641
-
642
-
643
509
  def user_confirm():
644
510
  """
645
511
  Ask the user to enter y or n (case-insensitive) on the command line.
@@ -816,123 +682,125 @@ def convert_string_to_list(data_string, is_float=True, force_comma_separation=Fa
816
682
  return data_string
817
683
 
818
684
 
819
- def _load_yaml_using_astropy(file):
685
+ def get_structure_array_from_table(table, column_names):
820
686
  """
821
- Load a yaml file using astropy's yaml loader.
687
+ Get a structured array from an astropy table for a selected list of columns.
822
688
 
823
689
  Parameters
824
690
  ----------
825
- file: file
826
- File to be loaded.
691
+ table: astropy.table.Table
692
+ Table to be converted.
693
+ column_names: list
694
+ List of column names to be included in the structured array.
827
695
 
828
696
  Returns
829
697
  -------
830
- dict
831
- Dictionary containing the file content.
698
+ numpy.ndarray
699
+ Structured array containing the table data.
832
700
  """
833
- # pylint: disable=import-outside-toplevel
834
- import astropy.io.misc.yaml as astropy_yaml
835
-
836
- file.seek(0)
837
- return astropy_yaml.load(file)
701
+ return np.array(
702
+ list(zip(*[np.array(table[col]) for col in column_names if col in table.colnames])),
703
+ dtype=[(col, np.array(table[col]).dtype) for col in column_names if col in table.colnames],
704
+ )
838
705
 
839
706
 
840
- def is_utf8_file(file_name):
707
+ def convert_keys_in_dict_to_lowercase(data):
841
708
  """
842
- Check if a file is encoded in UTF-8.
709
+ Recursively convert all dictionary keys to lowercase.
843
710
 
844
711
  Parameters
845
712
  ----------
846
- file_name: str, Path
847
- Name of the file to be checked.
713
+ data: dict
714
+ Dictionary to be converted.
848
715
 
849
716
  Returns
850
717
  -------
851
- bool
852
- True if the file is encoded in UTF-8, False otherwise.
718
+ dict
719
+ Dictionary with all keys converted to lowercase.
853
720
  """
854
- try:
855
- with open(file_name, encoding="utf-8") as file:
856
- file.read()
857
- return True
858
- except UnicodeDecodeError:
859
- return False
721
+ if isinstance(data, dict):
722
+ return {k.lower(): convert_keys_in_dict_to_lowercase(v) for k, v in data.items()}
723
+ if isinstance(data, list):
724
+ return [convert_keys_in_dict_to_lowercase(i) for i in data]
725
+ return data
860
726
 
861
727
 
862
- def read_file_encoded_in_utf_or_latin(file_name):
728
+ def remove_key_from_dict(data, key_to_remove):
863
729
  """
864
- Read a file encoded in UTF-8 or Latin-1.
730
+ Remove a specific key from a dictionary recursively.
865
731
 
866
732
  Parameters
867
733
  ----------
868
- file_name: str
869
- Name of the file to be read.
734
+ data: dict
735
+ Dictionary to be processed.
736
+ key_to_remove: str
737
+ Key to be removed from the dictionary.
870
738
 
871
739
  Returns
872
740
  -------
873
- list
874
- List of lines read from the file.
875
-
876
- Raises
877
- ------
878
- UnicodeDecodeError
879
- If the file cannot be decoded using UTF-8 or Latin-1.
741
+ dict
742
+ Dictionary with the specified key removed.
880
743
  """
881
- try:
882
- with open(file_name, encoding="utf-8") as file:
883
- lines = file.readlines()
884
- except UnicodeDecodeError:
885
- logging.debug("Unable to decode file using UTF-8. Trying Latin-1.")
886
- try:
887
- with open(file_name, encoding="latin-1") as file:
888
- lines = file.readlines()
889
- except UnicodeDecodeError as exc:
890
- raise UnicodeDecodeError("Unable to decode file using UTF-8 or Latin-1.") from exc
744
+ if isinstance(data, dict):
745
+ return {
746
+ k: remove_key_from_dict(v, key_to_remove) for k, v in data.items() if k != key_to_remove
747
+ }
748
+ if isinstance(data, list):
749
+ return [remove_key_from_dict(i, key_to_remove) for i in data]
750
+ return data
751
+
891
752
 
892
- return lines
753
+ def _find_differences_dict(obj1, obj2, path, diffs):
754
+ """Recursively find differences between two dictionaries."""
755
+ for key in sorted(set(obj1) | set(obj2)):
756
+ subpath = f"{path}['{key}']" if path else f"['{key}']"
757
+ if key not in obj1:
758
+ diffs.append(f"{subpath}: added in second object")
759
+ elif key not in obj2:
760
+ diffs.append(f"{subpath}: removed in second object")
761
+ else:
762
+ diffs.extend(find_differences_in_json_objects(obj1[key], obj2[key], subpath))
893
763
 
894
764
 
895
- def get_structure_array_from_table(table, column_names):
765
+ def find_differences_in_json_objects(obj1, obj2, path=""):
896
766
  """
897
- Get a structured array from an astropy table for a selected list of columns.
767
+ Recursively find differences between two JSON-like objects.
898
768
 
899
769
  Parameters
900
770
  ----------
901
- table: astropy.table.Table
902
- Table to be converted.
903
- column_names: list
904
- List of column names to be included in the structured array.
771
+ obj1: dict, list, or any
772
+ First object to compare.
773
+ obj2: dict, list, or any
774
+ Second object to compare.
775
+ path: str
776
+ Path to the current object in the JSON structure, used for reporting differences.
905
777
 
906
778
  Returns
907
779
  -------
908
- numpy.ndarray
909
- Structured array containing the table data.
780
+ list
781
+ List of differences found between the two objects, with paths indicating where the
782
+ differences occur.
910
783
  """
911
- return np.array(
912
- list(zip(*[np.array(table[col]) for col in column_names if col in table.colnames])),
913
- dtype=[(col, np.array(table[col]).dtype) for col in column_names if col in table.colnames],
914
- )
784
+ diffs = []
915
785
 
786
+ if not isinstance(obj1, type(obj2)):
787
+ diffs.append(f"{path}: type changed from {type(obj1).__name__} to {type(obj2).__name__}")
788
+ return diffs
916
789
 
917
- def convert_keys_in_dict_to_lowercase(data):
918
- """
919
- Recursively convert all dictionary keys to lowercase.
790
+ if isinstance(obj1, dict):
791
+ _find_differences_dict(obj1, obj2, path, diffs)
920
792
 
921
- Parameters
922
- ----------
923
- data: dict
924
- Dictionary to be converted.
793
+ elif isinstance(obj1, list):
794
+ if len(obj1) != len(obj2):
795
+ diffs.append(f"{path}: list length changed from {len(obj1)} to {len(obj2)}")
796
+ for i, (a, b) in enumerate(zip(obj1, obj2)):
797
+ subpath = f"{path}[{i}]" if path else f"[{i}]"
798
+ diffs.extend(find_differences_in_json_objects(a, b, subpath))
925
799
 
926
- Returns
927
- -------
928
- dict
929
- Dictionary with all keys converted to lowercase.
930
- """
931
- if isinstance(data, dict):
932
- return {k.lower(): convert_keys_in_dict_to_lowercase(v) for k, v in data.items()}
933
- if isinstance(data, list):
934
- return [convert_keys_in_dict_to_lowercase(i) for i in data]
935
- return data
800
+ elif obj1 != obj2:
801
+ diffs.append(f"{path}: value changed from {obj1} to {obj2}")
802
+
803
+ return diffs
936
804
 
937
805
 
938
806
  def clear_default_sim_telarray_cfg_directories(command):
@@ -180,3 +180,39 @@ def calculate_circular_mean(angles):
180
180
  sin_sum = np.sum(np.sin(angles))
181
181
  cos_sum = np.sum(np.cos(angles))
182
182
  return np.arctan2(sin_sum, cos_sum)
183
+
184
+
185
+ def transform_ground_to_shower_coordinates(x_ground, y_ground, z_ground, azimuth, altitude):
186
+ """
187
+ Transform ground to shower coordinates.
188
+
189
+ Assume ground to be of type 'North-West-Up' (NWU) coordinates.
190
+
191
+ Parameters
192
+ ----------
193
+ x_ground: numpy.array
194
+ Ground x coordinate.
195
+ y_ground: numpy.array
196
+ Ground y coordinate.
197
+ z_ground: numpy.array
198
+ Ground z coordinate.
199
+ azimuth: numpy.array
200
+ Azimuth angle of the shower (in radians).
201
+ altitude: numpy.array
202
+ Altitude angle of the shower (in radians).
203
+
204
+ Returns
205
+ -------
206
+ tuple
207
+ Transformed shower coordinates (x', y', z').
208
+ """
209
+ x, y, z, az, alt = np.broadcast_arrays(x_ground, y_ground, z_ground, azimuth, altitude)
210
+
211
+ ca, sa = np.cos(az), np.sin(az)
212
+ cz, sz = np.sin(alt), np.cos(alt)
213
+
214
+ x_s = ca * cz * x - sa * y + ca * sz * z
215
+ y_s = sa * cz * x + ca * y + sa * sz * z
216
+ z_s = -sz * x + cz * z
217
+
218
+ return x_s, y_s, z_s
simtools/utils/names.py CHANGED
@@ -12,6 +12,7 @@ Naming in simtools:
12
12
 
13
13
  """
14
14
 
15
+ import json
15
16
  import logging
16
17
  import re
17
18
  from functools import cache
@@ -22,7 +23,7 @@ import yaml
22
23
  from simtools.constants import (
23
24
  MODEL_PARAMETER_DESCRIPTION_METASCHEMA,
24
25
  MODEL_PARAMETER_SCHEMA_PATH,
25
- SCHEMA_PATH,
26
+ RESOURCE_PATH,
26
27
  )
27
28
 
28
29
  _logger = logging.getLogger(__name__)
@@ -59,10 +60,30 @@ def array_elements():
59
60
  dict
60
61
  Array elements.
61
62
  """
62
- with open(Path(SCHEMA_PATH) / "array_elements.yml", encoding="utf-8") as file:
63
+ # for efficiency reason, no functions from simtools.utils.general are used here
64
+ with open(Path(RESOURCE_PATH) / "array_elements.yml", encoding="utf-8") as file:
63
65
  return yaml.safe_load(file)["data"]
64
66
 
65
67
 
68
+ @cache
69
+ def array_element_common_identifiers():
70
+ """
71
+ Get array element IDs from CTAO common identifier.
72
+
73
+ Returns
74
+ -------
75
+ dict, dict
76
+ Dictionary mapping array element names to their IDs and vice versa.
77
+ """
78
+ # for efficiency reason, no functions from simtools.utils.general are used here
79
+ id_to_name = {}
80
+ with open(Path(RESOURCE_PATH) / "array-element-ids.json", encoding="utf-8") as file:
81
+ data = json.load(file)
82
+ id_to_name = {e["id"]: e["name"] for e in data["array_elements"]}
83
+ name_to_id = {e["name"]: e["id"] for e in data["array_elements"]}
84
+ return id_to_name, name_to_id
85
+
86
+
66
87
  @cache
67
88
  def simulation_software():
68
89
  """
@@ -415,6 +436,54 @@ def get_array_element_id_from_name(array_element_name):
415
436
  raise ValueError(f"Invalid name {array_element_name}") from exc
416
437
 
417
438
 
439
+ def get_common_identifier_from_array_element_name(array_element_name, default_return=None):
440
+ """
441
+ Get numerical common identifier from array element name as used by CTAO.
442
+
443
+ Common identifiers are numerical IDs used by the CTAO ACADA and DPPS systems.
444
+
445
+ Parameters
446
+ ----------
447
+ array_element_name: str
448
+ Array element name (e.g. LSTN-01)
449
+
450
+ Returns
451
+ -------
452
+ int
453
+ Common identifier.
454
+ """
455
+ _, name_to_id = array_element_common_identifiers()
456
+ try:
457
+ return name_to_id[array_element_name]
458
+ except KeyError as exc:
459
+ if default_return is not None:
460
+ return default_return
461
+ raise ValueError(f"Unknown array element name {array_element_name}") from exc
462
+
463
+
464
+ def get_array_element_name_from_common_identifier(common_identifier):
465
+ """
466
+ Get array element name from common identifier as used by CTAO.
467
+
468
+ Common identifiers are numerical IDs used by the CTAO ACADA and DPPS systems.
469
+
470
+ Parameters
471
+ ----------
472
+ common_identifier: int
473
+ Common identifier.
474
+
475
+ Returns
476
+ -------
477
+ str
478
+ Array element name.
479
+ """
480
+ id_to_name, _ = array_element_common_identifiers()
481
+ try:
482
+ return id_to_name[common_identifier]
483
+ except KeyError as exc:
484
+ raise ValueError(f"Unknown common identifier {common_identifier}") from exc
485
+
486
+
418
487
  def get_list_of_array_element_types(
419
488
  array_element_class="telescopes", site=None, observatory="CTAO"
420
489
  ):
@@ -760,6 +829,6 @@ def file_name_with_version(file_name, suffix):
760
829
  if file_name is None or suffix is None:
761
830
  return None
762
831
  file_name = str(file_name)
763
- if bool(re.search(r"\d+\.\d+\.\d+$", file_name)):
832
+ if re.search(r"\d{1,8}\.\d{1,8}\.\d{1,8}\Z", file_name):
764
833
  return Path(file_name + suffix)
765
834
  return Path(file_name).with_suffix(suffix)