gammasimtools 0.6.1__py3-none-any.whl → 0.8.2__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 (355) hide show
  1. gammasimtools-0.8.2.dist-info/METADATA +173 -0
  2. gammasimtools-0.8.2.dist-info/RECORD +345 -0
  3. {gammasimtools-0.6.1.dist-info → gammasimtools-0.8.2.dist-info}/WHEEL +1 -1
  4. gammasimtools-0.8.2.dist-info/entry_points.txt +31 -0
  5. simtools/_dev_version/__init__.py +9 -0
  6. simtools/_version.py +2 -2
  7. simtools/applications/calculate_trigger_rate.py +210 -0
  8. simtools/applications/convert_all_model_parameters_from_simtel.py +372 -0
  9. simtools/applications/{print_array_elements.py → convert_geo_coordinates_of_array_elements.py} +58 -63
  10. simtools/applications/convert_model_parameter_from_simtel.py +119 -0
  11. simtools/applications/{add_file_to_db.py → db_add_file_to_db.py} +70 -60
  12. simtools/applications/db_add_model_parameters_from_repository_to_db.py +184 -0
  13. simtools/applications/db_add_value_from_json_to_db.py +105 -0
  14. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +180 -0
  15. simtools/applications/db_get_array_layouts_from_db.py +162 -0
  16. simtools/applications/{get_file_from_db.py → db_get_file_from_db.py} +30 -34
  17. simtools/applications/db_get_parameter_from_db.py +131 -0
  18. simtools/applications/db_inspect_databases.py +52 -0
  19. simtools/applications/derive_mirror_rnda.py +39 -255
  20. simtools/applications/derive_psf_parameters.py +441 -0
  21. simtools/applications/generate_array_config.py +82 -0
  22. simtools/applications/generate_corsika_histograms.py +52 -52
  23. simtools/applications/generate_default_metadata.py +5 -8
  24. simtools/applications/generate_regular_arrays.py +117 -0
  25. simtools/applications/generate_simtel_array_histograms.py +97 -56
  26. simtools/applications/plot_array_layout.py +345 -115
  27. simtools/applications/production_generate_simulation_config.py +158 -0
  28. simtools/applications/production_scale_events.py +168 -0
  29. simtools/applications/simulate_light_emission.py +478 -0
  30. simtools/applications/simulate_prod.py +97 -175
  31. simtools/applications/submit_data_from_external.py +9 -12
  32. simtools/applications/submit_model_parameter_from_external.py +122 -0
  33. simtools/applications/validate_camera_efficiency.py +35 -102
  34. simtools/applications/validate_camera_fov.py +20 -19
  35. simtools/applications/{compare_cumulative_psf.py → validate_cumulative_psf.py} +45 -44
  36. simtools/applications/validate_file_using_schema.py +111 -47
  37. simtools/applications/validate_optics.py +17 -22
  38. simtools/camera_efficiency.py +193 -202
  39. simtools/configuration/commandline_parser.py +384 -96
  40. simtools/configuration/configurator.py +55 -71
  41. simtools/constants.py +5 -5
  42. simtools/corsika/corsika_config.py +482 -342
  43. simtools/corsika/corsika_histograms.py +226 -204
  44. simtools/corsika/corsika_histograms_visualize.py +23 -24
  45. simtools/corsika/primary_particle.py +159 -0
  46. simtools/data_model/data_reader.py +25 -20
  47. simtools/data_model/format_checkers.py +52 -0
  48. simtools/data_model/metadata_collector.py +211 -185
  49. simtools/data_model/metadata_model.py +115 -37
  50. simtools/data_model/model_data_writer.py +335 -26
  51. simtools/data_model/validate_data.py +366 -154
  52. simtools/db/db_array_elements.py +130 -0
  53. simtools/db/db_from_repo_handler.py +106 -0
  54. simtools/db/db_handler.py +1246 -0
  55. simtools/io_operations/hdf5_handler.py +3 -1
  56. simtools/io_operations/io_handler.py +32 -57
  57. simtools/job_execution/job_manager.py +82 -69
  58. simtools/layout/array_layout.py +325 -537
  59. simtools/layout/geo_coordinates.py +8 -11
  60. simtools/layout/telescope_position.py +163 -86
  61. simtools/model/array_model.py +312 -259
  62. simtools/model/calibration_model.py +50 -0
  63. simtools/model/camera.py +277 -523
  64. simtools/model/mirrors.py +68 -49
  65. simtools/model/model_parameter.py +602 -0
  66. simtools/model/model_utils.py +11 -39
  67. simtools/model/site_model.py +161 -0
  68. simtools/model/telescope_model.py +143 -633
  69. simtools/production_configuration/calculate_statistical_errors_grid_point.py +454 -0
  70. simtools/production_configuration/event_scaler.py +146 -0
  71. simtools/production_configuration/generate_simulation_config.py +193 -0
  72. simtools/production_configuration/interpolation_handler.py +197 -0
  73. simtools/ray_tracing/__init__.py +0 -0
  74. simtools/ray_tracing/mirror_panel_psf.py +280 -0
  75. simtools/{psf_analysis.py → ray_tracing/psf_analysis.py} +133 -47
  76. simtools/ray_tracing/ray_tracing.py +646 -0
  77. simtools/runners/__init__.py +0 -0
  78. simtools/runners/corsika_runner.py +240 -0
  79. simtools/runners/corsika_simtel_runner.py +225 -0
  80. simtools/runners/runner_services.py +307 -0
  81. simtools/runners/simtel_runner.py +224 -0
  82. simtools/schemas/array_elements.yml +137 -0
  83. simtools/schemas/integration_tests_config.metaschema.yml +93 -0
  84. simtools/schemas/metadata.metaschema.yml +6 -0
  85. simtools/schemas/model_parameter.metaschema.yml +78 -0
  86. simtools/schemas/{data.metaschema.yml → model_parameter_and_data_schema.metaschema.yml} +27 -44
  87. simtools/schemas/model_parameters/adjust_gain.schema.yml +37 -0
  88. simtools/schemas/model_parameters/altitude.schema.yml +37 -0
  89. simtools/schemas/model_parameters/array_coordinates.schema.yml +33 -0
  90. simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +77 -0
  91. simtools/schemas/model_parameters/array_element_position_ground.schema.yml +39 -0
  92. simtools/schemas/model_parameters/array_element_position_utm.schema.yml +39 -0
  93. simtools/schemas/model_parameters/array_layouts.schema.yml +48 -0
  94. simtools/schemas/model_parameters/array_triggers.schema.yml +93 -0
  95. simtools/schemas/model_parameters/asum_clipping.schema.yml +38 -0
  96. simtools/schemas/model_parameters/asum_offset.schema.yml +35 -0
  97. simtools/schemas/model_parameters/asum_shaping.schema.yml +35 -0
  98. simtools/schemas/model_parameters/asum_threshold.schema.yml +38 -0
  99. simtools/schemas/model_parameters/atmospheric_profile.schema.yml +32 -0
  100. simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +35 -0
  101. simtools/schemas/model_parameters/axes_offsets.schema.yml +53 -0
  102. simtools/schemas/model_parameters/camera_body_diameter.schema.yml +40 -0
  103. simtools/schemas/model_parameters/camera_body_shape.schema.yml +45 -0
  104. simtools/schemas/model_parameters/camera_config_file.schema.yml +40 -0
  105. simtools/schemas/model_parameters/camera_config_rotate.schema.yml +36 -0
  106. simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +43 -0
  107. simtools/schemas/model_parameters/camera_degraded_map.schema.yml +42 -0
  108. simtools/schemas/model_parameters/camera_depth.schema.yml +42 -0
  109. simtools/schemas/model_parameters/camera_filter.schema.yml +45 -0
  110. simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +29 -0
  111. simtools/schemas/model_parameters/camera_pixels.schema.yml +36 -0
  112. simtools/schemas/model_parameters/camera_transmission.schema.yml +41 -0
  113. simtools/schemas/model_parameters/channels_per_chip.schema.yml +36 -0
  114. simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +35 -0
  115. simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +27 -0
  116. simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +38 -0
  117. simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +28 -0
  118. simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +23 -0
  119. simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +27 -0
  120. simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +28 -0
  121. simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +27 -0
  122. simtools/schemas/model_parameters/corsika_observation_level.schema.yml +38 -0
  123. simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +52 -0
  124. simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +27 -0
  125. simtools/schemas/model_parameters/dark_events.schema.yml +32 -0
  126. simtools/schemas/model_parameters/default_trigger.schema.yml +35 -0
  127. simtools/schemas/model_parameters/design_model.schema.yml +31 -0
  128. simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +32 -0
  129. simtools/schemas/model_parameters/disc_bins.schema.yml +39 -0
  130. simtools/schemas/model_parameters/disc_start.schema.yml +41 -0
  131. simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +42 -0
  132. simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +41 -0
  133. simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +41 -0
  134. simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +39 -0
  135. simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +40 -0
  136. simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +41 -0
  137. simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +33 -0
  138. simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +42 -0
  139. simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +37 -0
  140. simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +44 -0
  141. simtools/schemas/model_parameters/discriminator_threshold.schema.yml +36 -0
  142. simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +45 -0
  143. simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +40 -0
  144. simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +41 -0
  145. simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +38 -0
  146. simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +38 -0
  147. simtools/schemas/model_parameters/dish_shape_length.schema.yml +41 -0
  148. simtools/schemas/model_parameters/dsum_clipping.schema.yml +38 -0
  149. simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +38 -0
  150. simtools/schemas/model_parameters/dsum_offset.schema.yml +37 -0
  151. simtools/schemas/model_parameters/dsum_pedsub.schema.yml +33 -0
  152. simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +39 -0
  153. simtools/schemas/model_parameters/dsum_prescale.schema.yml +44 -0
  154. simtools/schemas/model_parameters/dsum_presum_max.schema.yml +38 -0
  155. simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +45 -0
  156. simtools/schemas/model_parameters/dsum_shaping.schema.yml +44 -0
  157. simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +32 -0
  158. simtools/schemas/model_parameters/dsum_threshold.schema.yml +43 -0
  159. simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +42 -0
  160. simtools/schemas/model_parameters/effective_focal_length.schema.yml +61 -0
  161. simtools/schemas/model_parameters/epsg_code.schema.yml +37 -0
  162. simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +35 -0
  163. simtools/schemas/model_parameters/fadc_amplitude.schema.yml +46 -0
  164. simtools/schemas/model_parameters/fadc_bins.schema.yml +40 -0
  165. simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +50 -0
  166. simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +38 -0
  167. simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +42 -0
  168. simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +49 -0
  169. simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +47 -0
  170. simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +51 -0
  171. simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +37 -0
  172. simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +43 -0
  173. simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +49 -0
  174. simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +43 -0
  175. simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +39 -0
  176. simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +42 -0
  177. simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +40 -0
  178. simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +50 -0
  179. simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +42 -0
  180. simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +41 -0
  181. simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +42 -0
  182. simtools/schemas/model_parameters/fadc_max_signal.schema.yml +43 -0
  183. simtools/schemas/model_parameters/fadc_max_sum.schema.yml +39 -0
  184. simtools/schemas/model_parameters/fadc_mhz.schema.yml +31 -0
  185. simtools/schemas/model_parameters/fadc_noise.schema.yml +41 -0
  186. simtools/schemas/model_parameters/fadc_pedestal.schema.yml +40 -0
  187. simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +39 -0
  188. simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +50 -0
  189. simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +43 -0
  190. simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +43 -0
  191. simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +42 -0
  192. simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +41 -0
  193. simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +42 -0
  194. simtools/schemas/model_parameters/flatfielding.schema.yml +37 -0
  195. simtools/schemas/model_parameters/focal_length.schema.yml +45 -0
  196. simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +158 -0
  197. simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +29 -0
  198. simtools/schemas/model_parameters/focus_offset.schema.yml +66 -0
  199. simtools/schemas/model_parameters/gain_variation.schema.yml +43 -0
  200. simtools/schemas/model_parameters/geomag_horizontal.schema.yml +34 -0
  201. simtools/schemas/model_parameters/geomag_rotation.schema.yml +37 -0
  202. simtools/schemas/model_parameters/geomag_vertical.schema.yml +34 -0
  203. simtools/schemas/model_parameters/hg_lg_variation.schema.yml +36 -0
  204. simtools/schemas/model_parameters/iobuf_maximum.schema.yml +34 -0
  205. simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +34 -0
  206. simtools/schemas/model_parameters/laser_events.schema.yml +36 -0
  207. simtools/schemas/model_parameters/laser_external_trigger.schema.yml +35 -0
  208. simtools/schemas/model_parameters/laser_photons.schema.yml +32 -0
  209. simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +34 -0
  210. simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +34 -0
  211. simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +33 -0
  212. simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +33 -0
  213. simtools/schemas/model_parameters/laser_var_photons.schema.yml +33 -0
  214. simtools/schemas/model_parameters/laser_wavelength.schema.yml +33 -0
  215. simtools/schemas/model_parameters/led_events.schema.yml +34 -0
  216. simtools/schemas/model_parameters/led_photons.schema.yml +34 -0
  217. simtools/schemas/model_parameters/led_pulse_offset.schema.yml +32 -0
  218. simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +33 -0
  219. simtools/schemas/model_parameters/led_var_photons.schema.yml +34 -0
  220. simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +41 -0
  221. simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +43 -0
  222. simtools/schemas/model_parameters/min_photoelectrons.schema.yml +35 -0
  223. simtools/schemas/model_parameters/min_photons.schema.yml +32 -0
  224. simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +36 -0
  225. simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +64 -0
  226. simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +64 -0
  227. simtools/schemas/model_parameters/mirror_class.schema.yml +41 -0
  228. simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +51 -0
  229. simtools/schemas/model_parameters/mirror_focal_length.schema.yml +42 -0
  230. simtools/schemas/model_parameters/mirror_list.schema.yml +38 -0
  231. simtools/schemas/model_parameters/mirror_offset.schema.yml +41 -0
  232. simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +39 -0
  233. simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +61 -0
  234. simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +40 -0
  235. simtools/schemas/model_parameters/multiplicity_offset.schema.yml +46 -0
  236. simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +51 -0
  237. simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +37 -0
  238. simtools/schemas/model_parameters/nsb_offaxis.schema.yml +79 -0
  239. simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +47 -0
  240. simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +34 -0
  241. simtools/schemas/model_parameters/nsb_reference_value.schema.yml +33 -0
  242. simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +35 -0
  243. simtools/schemas/model_parameters/nsb_skymap.schema.yml +39 -0
  244. simtools/schemas/model_parameters/nsb_spectrum.schema.yml +50 -0
  245. simtools/schemas/model_parameters/num_gains.schema.yml +34 -0
  246. simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +33 -0
  247. simtools/schemas/model_parameters/optics_properties.schema.yml +31 -0
  248. simtools/schemas/model_parameters/parabolic_dish.schema.yml +32 -0
  249. simtools/schemas/model_parameters/pedestal_events.schema.yml +32 -0
  250. simtools/schemas/model_parameters/photon_delay.schema.yml +38 -0
  251. simtools/schemas/model_parameters/photons_per_run.schema.yml +33 -0
  252. simtools/schemas/model_parameters/pixel_cells.schema.yml +35 -0
  253. simtools/schemas/model_parameters/pixels_parallel.schema.yml +54 -0
  254. simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +40 -0
  255. simtools/schemas/model_parameters/pm_average_gain.schema.yml +34 -0
  256. simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +40 -0
  257. simtools/schemas/model_parameters/pm_gain_index.schema.yml +36 -0
  258. simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +41 -0
  259. simtools/schemas/model_parameters/pm_transit_time.schema.yml +63 -0
  260. simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +39 -0
  261. simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +42 -0
  262. simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +33 -0
  263. simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +33 -0
  264. simtools/schemas/model_parameters/primary_mirror_incidence_angle.schema.yml +29 -0
  265. simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +168 -0
  266. simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +36 -0
  267. simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +34 -0
  268. simtools/schemas/model_parameters/qe_variation.schema.yml +43 -0
  269. simtools/schemas/model_parameters/quantum_efficiency.schema.yml +42 -0
  270. simtools/schemas/model_parameters/random_focal_length.schema.yml +45 -0
  271. simtools/schemas/model_parameters/random_generator.schema.yml +36 -0
  272. simtools/schemas/model_parameters/reference_point_altitude.schema.yml +35 -0
  273. simtools/schemas/model_parameters/reference_point_latitude.schema.yml +36 -0
  274. simtools/schemas/model_parameters/reference_point_longitude.schema.yml +36 -0
  275. simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +34 -0
  276. simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +34 -0
  277. simtools/schemas/model_parameters/sampled_output.schema.yml +31 -0
  278. simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +34 -0
  279. simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +79 -0
  280. simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +42 -0
  281. simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +41 -0
  282. simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +33 -0
  283. simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +36 -0
  284. simtools/schemas/model_parameters/secondary_mirror_incidence_angle.schema.yml +29 -0
  285. simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +168 -0
  286. simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +36 -0
  287. simtools/schemas/model_parameters/secondary_mirror_reflectivity.schema.yml +35 -0
  288. simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +37 -0
  289. simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +40 -0
  290. simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +40 -0
  291. simtools/schemas/model_parameters/store_photoelectrons.schema.yml +41 -0
  292. simtools/schemas/model_parameters/tailcut_scale.schema.yml +40 -0
  293. simtools/schemas/model_parameters/telescope_axis_height.schema.yml +31 -0
  294. simtools/schemas/model_parameters/telescope_random_angle.schema.yml +35 -0
  295. simtools/schemas/model_parameters/telescope_random_error.schema.yml +34 -0
  296. simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +37 -0
  297. simtools/schemas/model_parameters/telescope_transmission.schema.yml +113 -0
  298. simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +41 -0
  299. simtools/schemas/model_parameters/teltrig_min_time.schema.yml +36 -0
  300. simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +36 -0
  301. simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +37 -0
  302. simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +38 -0
  303. simtools/schemas/model_parameters/transit_time_error.schema.yml +45 -0
  304. simtools/schemas/model_parameters/transit_time_jitter.schema.yml +36 -0
  305. simtools/schemas/model_parameters/trigger_current_limit.schema.yml +32 -0
  306. simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +53 -0
  307. simtools/schemas/model_parameters/trigger_pixels.schema.yml +40 -0
  308. simtools/simtel/simtel_config_reader.py +353 -0
  309. simtools/simtel/simtel_config_writer.py +244 -63
  310. simtools/simtel/{simtel_events.py → simtel_io_events.py} +26 -25
  311. simtools/simtel/simtel_io_histogram.py +661 -0
  312. simtools/simtel/simtel_io_histograms.py +569 -0
  313. simtools/simtel/simulator_array.py +145 -0
  314. simtools/simtel/{simtel_runner_camera_efficiency.py → simulator_camera_efficiency.py} +76 -52
  315. simtools/simtel/simulator_light_emission.py +473 -0
  316. simtools/simtel/simulator_ray_tracing.py +262 -0
  317. simtools/simulator.py +220 -446
  318. simtools/testing/__init__.py +0 -0
  319. simtools/testing/assertions.py +151 -0
  320. simtools/testing/configuration.py +226 -0
  321. simtools/testing/helpers.py +42 -0
  322. simtools/testing/validate_output.py +240 -0
  323. simtools/utils/general.py +340 -437
  324. simtools/utils/geometry.py +12 -12
  325. simtools/utils/names.py +257 -644
  326. simtools/utils/value_conversion.py +176 -0
  327. simtools/version.py +3 -1
  328. simtools/visualization/legend_handlers.py +135 -152
  329. simtools/visualization/plot_camera.py +379 -0
  330. simtools/visualization/visualize.py +346 -167
  331. gammasimtools-0.6.1.dist-info/METADATA +0 -180
  332. gammasimtools-0.6.1.dist-info/RECORD +0 -91
  333. gammasimtools-0.6.1.dist-info/entry_points.txt +0 -23
  334. simtools/_dev_version/scm_version.py +0 -10
  335. simtools/applications/db_development_tools/add_new_parameter_to_db.py +0 -81
  336. simtools/applications/db_development_tools/add_unit_to_parameter_in_db.py +0 -59
  337. simtools/applications/db_development_tools/mark_non_optics_parameters_non_applicable.py +0 -102
  338. simtools/applications/get_parameter.py +0 -92
  339. simtools/applications/make_regular_arrays.py +0 -160
  340. simtools/applications/produce_array_config.py +0 -136
  341. simtools/applications/production.py +0 -313
  342. simtools/applications/sim_showers_for_trigger_rates.py +0 -187
  343. simtools/applications/tune_psf.py +0 -334
  344. simtools/corsika/corsika_default_config.py +0 -282
  345. simtools/corsika/corsika_runner.py +0 -450
  346. simtools/corsika_simtel/corsika_simtel_runner.py +0 -197
  347. simtools/db_handler.py +0 -1480
  348. simtools/ray_tracing.py +0 -525
  349. simtools/simtel/simtel_histograms.py +0 -414
  350. simtools/simtel/simtel_runner.py +0 -244
  351. simtools/simtel/simtel_runner_array.py +0 -293
  352. simtools/simtel/simtel_runner_ray_tracing.py +0 -277
  353. {gammasimtools-0.6.1.dist-info → gammasimtools-0.8.2.dist-info}/LICENSE +0 -0
  354. {gammasimtools-0.6.1.dist-info → gammasimtools-0.8.2.dist-info}/top_level.txt +0 -0
  355. /simtools/{corsika_simtel → db}/__init__.py +0 -0
@@ -0,0 +1,193 @@
1
+ """
2
+ Configures and generates simulation parameters for a specific grid point.
3
+
4
+ Used to configure and generate simulation parameters for a specific grid point
5
+ based on statistical uncertainties.
6
+ The class considers parameters, such as azimuth, elevation, and night sky background,
7
+ to compute core scatter area, viewcone, and the required number of simulated events.
8
+
9
+ Key Components:
10
+ ---------------
11
+ - `SimulationConfig`: Main class to handle simulation configuration for a grid point.
12
+ - Attributes:
13
+ - `grid_point` (dict): Contains azimuth, elevation, and night sky background.
14
+ - `ctao_data_level` (str): The data level for the simulation (e.g., 'A', 'B', 'C').
15
+ - `science_case` (str): The science case for the simulation.
16
+ - `file_path` (str): Path to the DL2 MC event file
17
+ used for statistical error evaluation.
18
+ - `file_type` (str): Type of the DL2 MC event file ('point-like' or 'cone').
19
+ - `metrics` (dict, optional): Dictionary of metrics to evaluate.
20
+
21
+ """
22
+
23
+ import logging
24
+
25
+ from simtools.production_configuration.calculate_statistical_errors_grid_point import (
26
+ StatisticalErrorEvaluator,
27
+ )
28
+ from simtools.production_configuration.event_scaler import EventScaler
29
+
30
+ _logger = logging.getLogger(__name__)
31
+
32
+
33
+ class SimulationConfig:
34
+ """
35
+ Configures simulation parameters for a specific grid point.
36
+
37
+ Parameters
38
+ ----------
39
+ grid_point : dict
40
+ Dictionary representing a grid point with azimuth, elevation, and night sky background.
41
+ ctao_data_level : str
42
+ The data level (e.g., 'A', 'B', 'C') for the simulation configuration.
43
+ science_case : str
44
+ The science case for the simulation configuration.
45
+ file_path : str
46
+ Path to the DL2 MC event file for statistical uncertainty evaluation.
47
+ file_type : str
48
+ Type of the DL2 MC event file ('point-like' or 'cone').
49
+ metrics : dict, optional
50
+ Dictionary of metrics to evaluate.
51
+ """
52
+
53
+ def __init__(
54
+ self,
55
+ grid_point: dict[str, float],
56
+ ctao_data_level: str,
57
+ science_case: str,
58
+ file_path: str,
59
+ file_type: str,
60
+ metrics: dict[str, float] | None = None,
61
+ ):
62
+ """Initialize the simulation configuration for a grid point."""
63
+ self.grid_point = grid_point
64
+ self.ctao_data_level = ctao_data_level
65
+ self.science_case = science_case
66
+ self.file_path = file_path
67
+ self.file_type = file_type
68
+ self.metrics = metrics or {}
69
+ self.evaluator = StatisticalErrorEvaluator(file_path, file_type, metrics)
70
+ self.event_scaler = EventScaler(self.evaluator, science_case, self.metrics)
71
+ self.simulation_params = {}
72
+
73
+ def configure_simulation(self) -> dict[str, float]:
74
+ """
75
+ Configure the simulation parameters for the grid point, data level, and science case.
76
+
77
+ Returns
78
+ -------
79
+ dict
80
+ A dictionary with simulation parameters such as core scatter area,
81
+ viewcone, and number of simulated events.
82
+ """
83
+ core_scatter_area = self._calculate_core_scatter_area()
84
+ viewcone = self._calculate_viewcone()
85
+ number_of_events = self.calculate_required_events()
86
+
87
+ self.simulation_params = {
88
+ "core_scatter_area": core_scatter_area,
89
+ "viewcone": viewcone,
90
+ "number_of_events": number_of_events,
91
+ }
92
+
93
+ return self.simulation_params
94
+
95
+ def calculate_required_events(self) -> int:
96
+ """
97
+ Calculate the required number of simulated events based on statistical error metrics.
98
+
99
+ Uses the EventScaler to scale the events.
100
+
101
+ Returns
102
+ -------
103
+ int
104
+ The number of simulated events required.
105
+ """
106
+ return self.event_scaler.scale_events()
107
+
108
+ def _calculate_core_scatter_area(self) -> float:
109
+ """
110
+ Calculate the core scatter area based on the grid point and data level.
111
+
112
+ Returns
113
+ -------
114
+ float
115
+ The core scatter area.
116
+ """
117
+ base_area = self._fetch_simulated_core_scatter_area()
118
+ area_factor = self._get_area_factor_from_grid_point()
119
+ return base_area * area_factor
120
+
121
+ def _calculate_viewcone(self) -> float:
122
+ """
123
+ Calculate the viewcone based on the grid point conditions and data level.
124
+
125
+ Returns
126
+ -------
127
+ float
128
+ The viewcone value.
129
+ """
130
+ base_viewcone = self._fetch_simulated_viewcone()
131
+ viewcone_factor = self._get_viewcone_factor_from_grid_point()
132
+
133
+ return base_viewcone * viewcone_factor
134
+
135
+ def _get_area_factor_from_grid_point(self) -> float:
136
+ """
137
+ Determine the area factor.
138
+
139
+ The area factor is based on the grid point's azimuth,
140
+ elevation, and night sky background.
141
+
142
+ Returns
143
+ -------
144
+ float
145
+ The area factor.
146
+ """
147
+ azimuth = self.grid_point.get("azimuth", 0)
148
+ elevation = self.grid_point.get("elevation", 0)
149
+ night_sky_background = self.grid_point.get("night_sky_background", 0)
150
+
151
+ # Implement reading of factor from LUT
152
+ return azimuth + elevation + night_sky_background
153
+
154
+ def _get_viewcone_factor_from_grid_point(self) -> float:
155
+ """
156
+ Determine the viewcone factor.
157
+
158
+ The factor is based on the grid point's azimuth,
159
+ elevation, and night sky background.
160
+
161
+ Returns
162
+ -------
163
+ float
164
+ The viewcone factor.
165
+ """
166
+ azimuth = self.grid_point.get("azimuth", 0)
167
+ elevation = self.grid_point.get("elevation", 0)
168
+ night_sky_background = self.grid_point.get("night_sky_background", 0)
169
+
170
+ # Implement reading of factor from LUT
171
+ return azimuth + elevation + night_sky_background
172
+
173
+ def _fetch_simulated_core_scatter_area(self) -> float:
174
+ """
175
+ Fetch the core scatter area from existing simulated files based on grid point conditions.
176
+
177
+ Returns
178
+ -------
179
+ float
180
+ The fetched core scatter outer bound.
181
+ """
182
+ return self.evaluator.data["core_range"]
183
+
184
+ def _fetch_simulated_viewcone(self) -> float:
185
+ """
186
+ Fetch the viewcone from existing simulated files based on grid point conditions.
187
+
188
+ Returns
189
+ -------
190
+ float
191
+ The fetched viewcone outer bound.
192
+ """
193
+ return self.evaluator.data["viewcone"]
@@ -0,0 +1,197 @@
1
+ """Interpolates between instances of StatisticalErrorEvaluator using EventScaler."""
2
+
3
+ import astropy.units as u
4
+ import numpy as np
5
+ from scipy.interpolate import griddata
6
+
7
+ from simtools.production_configuration.calculate_statistical_errors_grid_point import (
8
+ StatisticalErrorEvaluator,
9
+ )
10
+ from simtools.production_configuration.event_scaler import EventScaler
11
+
12
+
13
+ class InterpolationHandler:
14
+ """Handle interpolation between multiple StatisticalErrorEvaluator instances."""
15
+
16
+ def __init__(
17
+ self, evaluators: list["StatisticalErrorEvaluator"], science_case: str, metrics: dict
18
+ ):
19
+ self.evaluators = evaluators
20
+ self.science_case = science_case
21
+ self.metrics = metrics
22
+ self.event_scalers = [
23
+ EventScaler(e, self.science_case, self.metrics) for e in self.evaluators
24
+ ]
25
+
26
+ self.azimuths = [e.grid_point[1].to(u.deg).value for e in self.evaluators]
27
+ self.zeniths = [e.grid_point[2].to(u.deg).value for e in self.evaluators]
28
+ self.nsbs = [e.grid_point[3] for e in self.evaluators]
29
+ self.offsets = [e.grid_point[4].to(u.deg).value for e in self.evaluators]
30
+
31
+ self.energy_grids = [
32
+ (e.data["bin_edges_low"][:-1] + e.data["bin_edges_high"][:-1]) / 2
33
+ for e in self.evaluators
34
+ ]
35
+ self.scaled_events = [
36
+ scaler.scale_events(return_sum=False) for scaler in self.event_scalers
37
+ ]
38
+ self.energy_thresholds = np.array([e.energy_threshold for e in self.evaluators])
39
+
40
+ self.data, self.grid_points = self._build_data_array()
41
+
42
+ def _build_data_array(self):
43
+ """
44
+ Build a data array with interpolated values across all dimensions including energy.
45
+
46
+ Returns
47
+ -------
48
+ np.ndarray
49
+ The data array with interpolated values.
50
+ np.ndarray
51
+ The corresponding grid points.
52
+ """
53
+ # Flatten the energy grid and other dimensions into a combined array
54
+ flat_data_list = []
55
+ flat_grid_points = []
56
+
57
+ for e, energy_grid, scaled_events in zip(
58
+ self.evaluators, self.energy_grids, self.scaled_events
59
+ ):
60
+ az = np.full(len(energy_grid), e.grid_point[1].to(u.deg).value)
61
+ zen = np.full(len(energy_grid), e.grid_point[2].to(u.deg).value)
62
+ nsb = np.full(len(energy_grid), e.grid_point[3])
63
+ offset = np.full(len(energy_grid), e.grid_point[4].to(u.deg).value)
64
+
65
+ # Combine grid points and data
66
+ grid_points = np.column_stack([energy_grid.to(u.TeV).value, az, zen, nsb, offset])
67
+ flat_grid_points.append(grid_points)
68
+ flat_data_list.append(scaled_events)
69
+
70
+ # Flatten the list and convert to numpy arrays
71
+ flat_grid_points = np.vstack(flat_grid_points)
72
+ flat_data = np.hstack(flat_data_list)
73
+
74
+ # Sort the grid points and corresponding data by energy
75
+ sorted_indices = np.argsort(flat_grid_points[:, 0])
76
+ sorted_grid_points = flat_grid_points[sorted_indices]
77
+ sorted_data = flat_data[sorted_indices]
78
+
79
+ return sorted_data, sorted_grid_points
80
+
81
+ def _remove_flat_dimensions(self, grid_points):
82
+ """Identify and remove flat dimensions (dimensions with no variance)."""
83
+ variance = np.var(grid_points, axis=0)
84
+ non_flat_mask = variance > 1e-6 # Threshold for determining flatness
85
+ reduced_grid_points = grid_points[:, non_flat_mask]
86
+ return reduced_grid_points, non_flat_mask
87
+
88
+ def interpolate(self, query_points: np.ndarray) -> np.ndarray:
89
+ """
90
+ Interpolate the number of simulated events given query points.
91
+
92
+ Parameters
93
+ ----------
94
+ query_points : np.ndarray
95
+ Array of query points with shape (n, 5), where n is the number of points,
96
+ and 5 represents (energy, azimuth, zenith, nsb, offset).
97
+
98
+ Returns
99
+ -------
100
+ np.ndarray
101
+ Interpolated values at the query points.
102
+ """
103
+ reduced_grid_points, non_flat_mask = self._remove_flat_dimensions(self.grid_points)
104
+ reduced_query_points = query_points[:, non_flat_mask]
105
+
106
+ # Interpolate using the reduced dimensions
107
+ return griddata(
108
+ reduced_grid_points,
109
+ self.data,
110
+ reduced_query_points,
111
+ method="linear",
112
+ fill_value=np.nan,
113
+ rescale=True,
114
+ )
115
+
116
+ def interpolate_energy_threshold(self, query_point: np.ndarray) -> float:
117
+ """
118
+ Interpolate the energy threshold for a given grid point.
119
+
120
+ Parameters
121
+ ----------
122
+ query_point : np.ndarray
123
+ Array specifying the grid point (energy, azimuth, zenith, NSB, offset).
124
+
125
+ Returns
126
+ -------
127
+ float
128
+ Interpolated energy threshold.
129
+ """
130
+ flat_grid_points = []
131
+ flat_energy_thresholds = []
132
+
133
+ for e in self.evaluators:
134
+ az = e.grid_point[1].to(u.deg).value
135
+ zen = e.grid_point[2].to(u.deg).value
136
+ nsb = e.grid_point[3]
137
+ offset = e.grid_point[4].to(u.deg).value
138
+ grid_point = np.array([az, zen, nsb, offset])
139
+ flat_grid_points.append(grid_point)
140
+ flat_energy_thresholds.append(e.energy_threshold)
141
+
142
+ flat_grid_points = np.array(flat_grid_points)
143
+ flat_energy_thresholds = np.array(flat_energy_thresholds)
144
+
145
+ reduced_grid_points, non_flat_mask = self._remove_flat_dimensions(flat_grid_points)
146
+ full_non_flat_mask = np.concatenate(([False], non_flat_mask))
147
+ reduced_query_point = query_point[0][full_non_flat_mask]
148
+
149
+ interpolated_threshold = griddata(
150
+ reduced_grid_points,
151
+ flat_energy_thresholds,
152
+ reduced_query_point,
153
+ method="linear",
154
+ fill_value=np.nan,
155
+ rescale=False,
156
+ )
157
+
158
+ return interpolated_threshold.item()
159
+
160
+ def plot_comparison(self, evaluator: "StatisticalErrorEvaluator"):
161
+ """
162
+ Plot a comparison between the simulated, scaled, and triggered events.
163
+
164
+ Parameters
165
+ ----------
166
+ evaluator : StatisticalErrorEvaluator
167
+ The evaluator for which to plot the comparison.
168
+ """
169
+ import matplotlib.pyplot as plt # pylint: disable=import-outside-toplevel
170
+
171
+ midpoints = 0.5 * (evaluator.data["bin_edges_high"] + evaluator.data["bin_edges_low"])
172
+
173
+ self.grid_points = np.column_stack(
174
+ [
175
+ midpoints,
176
+ np.full_like(midpoints, evaluator.grid_point[1]),
177
+ np.full_like(midpoints, evaluator.grid_point[2]),
178
+ np.full_like(midpoints, evaluator.grid_point[3]),
179
+ np.full_like(midpoints, evaluator.grid_point[4]),
180
+ ]
181
+ )
182
+
183
+ self.interpolate(self.grid_points)
184
+
185
+ plt.plot(midpoints, evaluator.scaled_events, label="Scaled")
186
+
187
+ triggered_event_histogram, _ = np.histogram(
188
+ evaluator.data["event_energies_reco"], bins=evaluator.data["bin_edges_low"]
189
+ )
190
+ plt.plot(midpoints[:-1], triggered_event_histogram, label="Triggered")
191
+
192
+ plt.legend()
193
+ plt.xscale("log")
194
+ plt.xlabel("Energy (Midpoint of Bin Edges)")
195
+ plt.ylabel("Event Count")
196
+ plt.title("Comparison of Simulated, Scaled, and Triggered Events")
197
+ plt.show()
File without changes
@@ -0,0 +1,280 @@
1
+ """Mirror panel PSF calculation."""
2
+
3
+ import logging
4
+
5
+ import astropy.units as u
6
+ import numpy as np
7
+ from astropy.table import QTable, Table
8
+
9
+ import simtools.data_model.model_data_writer as writer
10
+ import simtools.utils.general as gen
11
+ from simtools.data_model.metadata_collector import MetadataCollector
12
+ from simtools.model.telescope_model import TelescopeModel
13
+ from simtools.ray_tracing.ray_tracing import RayTracing
14
+
15
+
16
+ class MirrorPanelPSF:
17
+ """
18
+ Mirror panel PSF and random reflection angle calculation.
19
+
20
+ This class is used to derive the random reflection angle for the mirror panels in the telescope.
21
+
22
+ Known limitations: single Gaussian PSF model, no support for multiple PSF components (as allowed
23
+ in the model parameters).
24
+
25
+ Parameters
26
+ ----------
27
+ label: str
28
+ Application label.
29
+ args_dict: dict
30
+ Dictionary with input arguments.
31
+ db_config:
32
+ Dictionary with database configuration.
33
+ """
34
+
35
+ def __init__(self, label, args_dict, db_config):
36
+ """Initialize the MirrorPanelPSF class."""
37
+ self._logger = logging.getLogger(__name__)
38
+ self._logger.debug("Initializing MirrorPanelPSF")
39
+
40
+ self.args_dict = args_dict
41
+ self.telescope_model = self._define_telescope_model(label, db_config)
42
+
43
+ if self.args_dict["test"]:
44
+ self.args_dict["number_of_mirrors_to_test"] = 2
45
+
46
+ if self.args_dict["psf_measurement"]:
47
+ self._get_psf_containment()
48
+ if not self.args_dict["psf_measurement_containment_mean"]:
49
+ raise ValueError("Missing PSF measurement")
50
+
51
+ self.mean_d80 = None
52
+ self.sig_d80 = None
53
+ self.rnda_start = self._get_starting_value()
54
+ self.rnda_opt = None
55
+ self.results_rnda = []
56
+ self.results_mean = []
57
+ self.results_sig = []
58
+
59
+ def _define_telescope_model(self, label, db_config):
60
+ """
61
+ Define telescope model.
62
+
63
+ This includes updating the configuration with mirror list and/or random focal length given
64
+ as input.
65
+
66
+ Attributes
67
+ ----------
68
+ label: str
69
+ Application label.
70
+ db_config:
71
+ Dictionary with database configuration.
72
+
73
+ Returns
74
+ -------
75
+ tel TelescopeModel
76
+ telescope model
77
+
78
+ """
79
+ tel = TelescopeModel(
80
+ site=self.args_dict["site"],
81
+ telescope_name=self.args_dict["telescope"],
82
+ model_version=self.args_dict["model_version"],
83
+ mongo_db_config=db_config,
84
+ label=label,
85
+ )
86
+ if self.args_dict["mirror_list"] is not None:
87
+ mirror_list_file = gen.find_file(
88
+ name=self.args_dict["mirror_list"], loc=self.args_dict["model_path"]
89
+ )
90
+ tel.change_parameter("mirror_list", self.args_dict["mirror_list"])
91
+ tel.export_parameter_file("mirror_list", mirror_list_file)
92
+ if self.args_dict["random_focal_length"] is not None:
93
+ tel.change_parameter("random_focal_length", str(self.args_dict["random_focal_length"]))
94
+ tel.export_model_files()
95
+
96
+ return tel
97
+
98
+ def _get_psf_containment(self):
99
+ """Read measured single-mirror point-spread function from file and return mean and sigma."""
100
+ # If this is a test, read just the first few lines since we only simulate those mirrors
101
+ data_end = (
102
+ self.args_dict["number_of_mirrors_to_test"] + 1 if self.args_dict["test"] else None
103
+ )
104
+ _psf_list = Table.read(
105
+ self.args_dict["psf_measurement"], format="ascii.ecsv", data_end=data_end
106
+ )
107
+ try:
108
+ self.args_dict["psf_measurement_containment_mean"] = np.nanmean(
109
+ np.array(_psf_list["psf_opt"].to("cm").value)
110
+ )
111
+ self.args_dict["psf_measurement_containment_sigma"] = np.nanstd(
112
+ np.array(_psf_list["psf_opt"].to("cm").value)
113
+ )
114
+ except KeyError as exc:
115
+ raise KeyError(
116
+ f"Missing column psf measurement (psf_opt) in {self.args_dict['psf_measurement']}"
117
+ ) from exc
118
+
119
+ self._logger.info(
120
+ f"Determined PSF containment to {self.args_dict['psf_measurement_containment_mean']:.4}"
121
+ f" +- {self.args_dict['psf_measurement_containment_sigma']:.4} cm"
122
+ )
123
+
124
+ def derive_random_reflection_angle(self, save_figures=False):
125
+ """
126
+ Minimize the difference between measured and simulated PSF for reflection angle.
127
+
128
+ Main loop of the optimization process. The method iterates over different values of the
129
+ random reflection angle until the difference in the mean value of the D80 containment
130
+ is minimal.
131
+ """
132
+ if self.args_dict["no_tuning"]:
133
+ self.rnda_opt = self.rnda_start
134
+ else:
135
+ self._optimize_reflection_angle()
136
+
137
+ self.mean_d80, self.sig_d80 = self.run_simulations_and_analysis(
138
+ self.rnda_opt, save_figures=save_figures
139
+ )
140
+
141
+ def _optimize_reflection_angle(self, step_size=0.1):
142
+ """Optimize the random reflection angle to minimize the difference in D80 containment."""
143
+
144
+ def collect_results(rnda, mean, sig):
145
+ self.results_rnda.append(rnda)
146
+ self.results_mean.append(mean)
147
+ self.results_sig.append(sig)
148
+
149
+ stop = False
150
+ mean_d80, sig_d80 = self.run_simulations_and_analysis(self.rnda_start)
151
+ rnda = self.rnda_start
152
+ sign_delta = np.sign(mean_d80 - self.args_dict["psf_measurement_containment_mean"])
153
+ collect_results(rnda, mean_d80, sig_d80)
154
+ while not stop:
155
+ rnda = rnda - (step_size * self.rnda_start * sign_delta)
156
+ if rnda < 0:
157
+ rnda = 0
158
+ collect_results(rnda, mean_d80, sig_d80)
159
+ break
160
+ mean_d80, sig_d80 = self.run_simulations_and_analysis(rnda)
161
+ new_sign_delta = np.sign(mean_d80 - self.args_dict["psf_measurement_containment_mean"])
162
+ stop = new_sign_delta != sign_delta
163
+ sign_delta = new_sign_delta
164
+ collect_results(rnda, mean_d80, sig_d80)
165
+
166
+ self._interpolate_optimal_rnda()
167
+
168
+ def _interpolate_optimal_rnda(self):
169
+ """Interpolate to find the optimal random reflection angle."""
170
+ self.results_rnda, self.results_mean, self.results_sig = gen.sort_arrays(
171
+ self.results_rnda, self.results_mean, self.results_sig
172
+ )
173
+ self.rnda_opt = np.interp(
174
+ x=self.args_dict["psf_measurement_containment_mean"],
175
+ xp=self.results_mean,
176
+ fp=self.results_rnda,
177
+ )
178
+
179
+ def _get_starting_value(self):
180
+ """Get optimization starting value from command line or previous model."""
181
+ if self.args_dict["rnda"] != 0:
182
+ rnda_start = self.args_dict["rnda"]
183
+ else:
184
+ rnda_start = self.telescope_model.get_parameter_value("mirror_reflection_random_angle")[
185
+ 0
186
+ ]
187
+
188
+ self._logger.info(f"Start value for mirror_reflection_random_angle: {rnda_start} deg")
189
+ return rnda_start
190
+
191
+ def run_simulations_and_analysis(self, rnda, save_figures=False):
192
+ """
193
+ Run ray tracing simulations and analysis for one given value of rnda.
194
+
195
+ Parameters
196
+ ----------
197
+ rnda: float
198
+ Random reflection angle in degrees.
199
+ save_figures: bool
200
+ Save figures.
201
+
202
+ Returns
203
+ -------
204
+ mean_d80: float
205
+ Mean value of D80 in cm.
206
+ sig_d80: float
207
+ Standard deviation of D80 in cm.
208
+ """
209
+ self.telescope_model.change_parameter("mirror_reflection_random_angle", rnda)
210
+ ray = RayTracing(
211
+ telescope_model=self.telescope_model,
212
+ simtel_path=self.args_dict.get("simtel_path", None),
213
+ single_mirror_mode=True,
214
+ mirror_numbers=(
215
+ list(range(1, self.args_dict["number_of_mirrors_to_test"] + 1))
216
+ if self.args_dict["test"]
217
+ else "all"
218
+ ),
219
+ use_random_focal_length=self.args_dict["use_random_focal_length"],
220
+ )
221
+ ray.simulate(test=self.args_dict["test"], force=True) # force has to be True, always
222
+ ray.analyze(force=True)
223
+ if save_figures:
224
+ ray.plot("d80_cm", save=True, d80=self.args_dict["psf_measurement_containment_mean"])
225
+
226
+ return (
227
+ ray.get_mean("d80_cm").to(u.cm).value,
228
+ ray.get_std_dev("d80_cm").to(u.cm).value,
229
+ )
230
+
231
+ def print_results(self):
232
+ """Print results to stdout."""
233
+ containment_fraction_percent = int(self.args_dict["containment_fraction"] * 100)
234
+
235
+ print(f"\nMeasured D{containment_fraction_percent}:")
236
+ if self.args_dict["psf_measurement_containment_sigma"] is not None:
237
+ print(
238
+ f"Mean = {self.args_dict['psf_measurement_containment_mean']:.3f} cm, "
239
+ f"StdDev = {self.args_dict['psf_measurement_containment_sigma']:.3f} cm"
240
+ )
241
+ else:
242
+ print(f"Mean = {self.args_dict['psf_measurement_containment_mean']:.3f} cm")
243
+ print(f"\nSimulated D{containment_fraction_percent}:")
244
+ print(f"Mean = {self.mean_d80:.3f} cm, StdDev = {self.sig_d80:.3f} cm")
245
+ print("\nmirror_random_reflection_angle")
246
+ print(f"Previous value = {self.rnda_start:.6f}")
247
+ print(f"New value = {self.rnda_opt:.6f}\n")
248
+
249
+ def write_optimization_data(self):
250
+ """
251
+ Write optimization results to an astropy table (ecsv file).
252
+
253
+ Used mostly for debugging of the optimization process.
254
+ The first entry of the table is the best fit result.
255
+ """
256
+ containment_fraction_percent = int(self.args_dict["containment_fraction"] * 100)
257
+
258
+ result_table = QTable(
259
+ [
260
+ [True] + [False] * len(self.results_rnda),
261
+ [self.rnda_opt, *self.results_rnda] * u.deg,
262
+ ([0.0] * (len(self.results_rnda) + 1)),
263
+ ([0.0] * (len(self.results_rnda) + 1)) * u.deg,
264
+ [self.mean_d80, *self.results_mean] * u.cm,
265
+ [self.sig_d80, *self.results_sig] * u.cm,
266
+ ],
267
+ names=(
268
+ "best_fit",
269
+ "mirror_reflection_random_angle_sigma1",
270
+ "mirror_reflection_random_angle_fraction2",
271
+ "mirror_reflection_random_angle_sigma2",
272
+ f"containment_radius_D{containment_fraction_percent}",
273
+ f"containment_radius_sigma_D{containment_fraction_percent}",
274
+ ),
275
+ )
276
+ writer.ModelDataWriter.dump(
277
+ args_dict=self.args_dict,
278
+ metadata=MetadataCollector(args_dict=self.args_dict).top_level_meta,
279
+ product_data=result_table,
280
+ )