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,454 @@
1
+ """
2
+ Provides functionality to evaluate statistical uncertainties from DL2 MC event files.
3
+
4
+ Classes
5
+ -------
6
+ StatisticalErrorEvaluator
7
+ Handles error calculation for given DL2 MC event files and specified metrics.
8
+
9
+
10
+ """
11
+
12
+ import logging
13
+
14
+ import numpy as np
15
+ from astropy import units as u
16
+ from astropy.io import fits
17
+
18
+ _logger = logging.getLogger(__name__)
19
+
20
+
21
+ class StatisticalErrorEvaluator:
22
+ """
23
+ Evaluates statistical uncertainties from a DL2 MC event file.
24
+
25
+ Parameters
26
+ ----------
27
+ file_path : str
28
+ Path to the DL2 MC event file.
29
+ file_type : str
30
+ Type of the file, either 'point-like' or 'cone'.
31
+ metrics : dict, optional
32
+ Dictionary of metrics to evaluate. Default is None.
33
+ grid_point : tuple, optional
34
+ Tuple specifying the grid point (energy, azimuth, zenith, NSB, offset).
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ file_path: str,
40
+ file_type: str,
41
+ metrics: dict[str, float],
42
+ grid_point: tuple[float, float, float, float, float] | None = None,
43
+ ):
44
+ """
45
+ Init the evaluator with a DL2 MC event file, its type, and metrics to calculate.
46
+
47
+ Parameters
48
+ ----------
49
+ file_path : str
50
+ The path to the DL2 MC event file.
51
+ file_type : str
52
+ The type of the file ('point-like' or 'cone').
53
+ metrics : dict, optional
54
+ Dictionary specifying which metrics to compute and their reference values.
55
+ grid_point : tuple, optional
56
+ Tuple specifying the grid point (energy, azimuth, zenith, NSB, offset).
57
+ """
58
+ self.file_path = file_path
59
+ self.file_type = file_type
60
+ self.metrics = metrics
61
+ self.grid_point = grid_point
62
+
63
+ self.data = self.load_data_from_file()
64
+
65
+ self.uncertainty_effective_area = None
66
+ self.energy_estimate = None
67
+ self.sigma_energy = None
68
+ self.delta_energy = None
69
+
70
+ self.metric_results = None
71
+ self.energy_threshold = None
72
+
73
+ def load_data_from_file(self):
74
+ """
75
+ Load data from the DL2 MC event file and return dictionaries with units.
76
+
77
+ Returns
78
+ -------
79
+ dict
80
+ Dictionary containing data from the DL2 MC event file with units.
81
+ """
82
+ data = {}
83
+ try:
84
+ with fits.open(self.file_path) as hdul:
85
+ events_data = hdul["EVENTS"].data # pylint: disable=E1101
86
+ sim_events_data = hdul["SIMULATED EVENTS"].data # pylint: disable=E1101
87
+ event_units = {}
88
+ for idx, col_name in enumerate(events_data.columns.names, start=1):
89
+ unit_key = f"TUNIT{idx}"
90
+ if unit_key in hdul["EVENTS"].header: # pylint: disable=E1101
91
+ event_units[col_name] = u.Unit(
92
+ hdul["EVENTS"].header[unit_key] # pylint: disable=E1101
93
+ )
94
+ else:
95
+ event_units[col_name] = None
96
+
97
+ sim_units = {}
98
+ for idx, col_name in enumerate(sim_events_data.columns.names, start=1):
99
+ unit_key = f"TUNIT{idx}"
100
+ if unit_key in hdul["SIMULATED EVENTS"].header: # pylint: disable=E1101
101
+ sim_units[col_name] = u.Unit(
102
+ hdul["SIMULATED EVENTS"].header[unit_key] # pylint: disable=E1101
103
+ )
104
+ else:
105
+ sim_units[col_name] = None
106
+ # dl2 files are required to have units for these entries
107
+ event_energies_reco = events_data["ENERGY"] * event_units["ENERGY"]
108
+
109
+ event_energies_mc = events_data["MC_ENERGY"] * event_units["MC_ENERGY"]
110
+
111
+ bin_edges_low = sim_events_data["MC_ENERG_LO"] * sim_units["MC_ENERG_LO"]
112
+
113
+ bin_edges_high = sim_events_data["MC_ENERG_HI"] * sim_units["MC_ENERG_HI"]
114
+
115
+ simulated_event_histogram = sim_events_data["EVENTS"] * u.count
116
+
117
+ viewcone = hdul[3].data["viewcone"][0][1] # pylint: disable=E1101
118
+ core_range = hdul[3].data["core_range"][0][1] # pylint: disable=E1101
119
+
120
+ data = {
121
+ "event_energies_reco": event_energies_reco,
122
+ "event_energies_mc": event_energies_mc,
123
+ "bin_edges_low": bin_edges_low,
124
+ "bin_edges_high": bin_edges_high,
125
+ "simulated_event_histogram": simulated_event_histogram,
126
+ "viewcone": viewcone,
127
+ "core_range": core_range,
128
+ }
129
+ unique_azimuths = np.unique(events_data["PNT_AZ"]) * u.deg
130
+ unique_zeniths = 90 * u.deg - np.unique(events_data["PNT_ALT"]) * u.deg
131
+ if self.grid_point is None:
132
+ _logger.info(f"Unique azimuths: {unique_azimuths}")
133
+ _logger.info(f"Unique zeniths: {unique_zeniths}")
134
+
135
+ if len(unique_azimuths) == 1 and len(unique_zeniths) == 1:
136
+ _logger.info(
137
+ f"Setting initial grid point with azimuth: {unique_azimuths[0]}"
138
+ f" zenith: {unique_zeniths[0]}"
139
+ )
140
+ self.grid_point = (
141
+ 1 * u.TeV,
142
+ unique_azimuths[0],
143
+ unique_zeniths[0],
144
+ 0,
145
+ 0 * u.deg,
146
+ ) # Initialize grid point with azimuth and zenith
147
+ else:
148
+ msg = "Multiple unique values found for azimuth or zenith."
149
+ _logger.error(msg)
150
+ raise ValueError(msg)
151
+ else:
152
+ _logger.warning(
153
+ f"Grid point already set to: {self.grid_point}. "
154
+ "Overwriting with new values from file."
155
+ )
156
+
157
+ self.grid_point = (
158
+ 1 * u.TeV,
159
+ unique_azimuths[0],
160
+ unique_zeniths[0],
161
+ 0,
162
+ 0 * u.deg,
163
+ )
164
+ _logger.info(f"New grid point values: {self.grid_point}")
165
+
166
+ except FileNotFoundError as e:
167
+ error_message = f"Error loading file {self.file_path}: {e}"
168
+ _logger.error(error_message)
169
+ raise FileNotFoundError(error_message) from e
170
+ return data
171
+
172
+ def create_bin_edges(self):
173
+ """
174
+ Create unique energy bin edges.
175
+
176
+ Returns
177
+ -------
178
+ bin_edges : array
179
+ Array of unique energy bin edges.
180
+ """
181
+ bin_edges_low = self.data["bin_edges_low"]
182
+ bin_edges_high = self.data["bin_edges_high"]
183
+ bin_edges = np.concatenate([bin_edges_low, [bin_edges_high[-1]]])
184
+ return np.unique(bin_edges)
185
+
186
+ def compute_triggered_event_histogram(self, event_energies_reco, bin_edges):
187
+ """
188
+ Compute histogram for triggered events.
189
+
190
+ Parameters
191
+ ----------
192
+ event_energies_reco : array
193
+ Array of reconstructed energy per event.
194
+ bin_edges : array
195
+ Array of energy bin edges.
196
+
197
+ Returns
198
+ -------
199
+ triggered_event_histogram : array
200
+ Histogram of triggered events.
201
+ """
202
+ event_energies_reco = event_energies_reco.to(bin_edges.unit)
203
+
204
+ triggered_event_histogram, _ = np.histogram(event_energies_reco.value, bins=bin_edges.value)
205
+ return triggered_event_histogram * u.count
206
+
207
+ def compute_efficiency_and_errors(self, triggered_event_counts, simulated_event_counts):
208
+ """
209
+ Compute trigger efficiency and its statistical error using the binomial distribution.
210
+
211
+ Parameters
212
+ ----------
213
+ triggered_event_counts : array with units
214
+ Histogram counts of the triggered events.
215
+ simulated_event_counts : array with units
216
+ Histogram counts of the simulated events.
217
+
218
+ Returns
219
+ -------
220
+ efficiencies : array
221
+ Array of calculated efficiencies.
222
+ relative_errors : array
223
+ Array of relative uncertainties.
224
+ """
225
+ # Ensure the inputs have compatible units
226
+ triggered_event_counts = triggered_event_counts.to(u.ct)
227
+ simulated_event_counts = simulated_event_counts.to(u.ct)
228
+
229
+ # Compute efficiencies, ensuring the output is dimensionless
230
+ efficiencies = np.divide(
231
+ triggered_event_counts,
232
+ simulated_event_counts,
233
+ out=np.zeros_like(triggered_event_counts),
234
+ where=simulated_event_counts > 0,
235
+ ).to(u.dimensionless_unscaled)
236
+
237
+ # Set up a mask for valid data with a unit-consistent threshold
238
+ if np.any(triggered_event_counts > simulated_event_counts):
239
+ raise ValueError(
240
+ "Triggered event counts exceed simulated event counts. Please check input data."
241
+ )
242
+ valid = (simulated_event_counts > 0 * u.ct) & (triggered_event_counts > 0 * u.ct)
243
+
244
+ uncertainties = np.zeros_like(triggered_event_counts.value) * u.dimensionless_unscaled
245
+
246
+ if np.any(valid):
247
+ uncertainties[valid] = np.sqrt(
248
+ np.maximum(
249
+ simulated_event_counts[valid]
250
+ / triggered_event_counts[valid]
251
+ * (1 - triggered_event_counts[valid] / simulated_event_counts[valid]),
252
+ 0,
253
+ )
254
+ )
255
+
256
+ # Compute relative errors
257
+ relative_errors = np.divide(
258
+ uncertainties,
259
+ np.sqrt(simulated_event_counts.value),
260
+ out=np.zeros_like(uncertainties, dtype=float),
261
+ where=uncertainties > 0,
262
+ )
263
+
264
+ return efficiencies, relative_errors
265
+
266
+ def calculate_energy_threshold(self, requested_eff_area_fraction=0.1):
267
+ """
268
+ Calculate the energy threshold where the effective area exceeds 10% of its maximum value.
269
+
270
+ Returns
271
+ -------
272
+ float
273
+ Energy threshold value.
274
+ """
275
+ bin_edges = self.create_bin_edges()
276
+ triggered_event_histogram = self.compute_triggered_event_histogram(
277
+ self.data["event_energies_mc"], bin_edges
278
+ )
279
+ simulated_event_histogram = self.data["simulated_event_histogram"]
280
+
281
+ efficiencies, _ = self.compute_efficiency_and_errors(
282
+ triggered_event_histogram, simulated_event_histogram
283
+ )
284
+
285
+ # Determine the effective area threshold (10% of max effective area)
286
+ max_efficiency = np.max(efficiencies)
287
+ threshold_efficiency = requested_eff_area_fraction * max_efficiency
288
+
289
+ threshold_index = np.argmax(efficiencies >= threshold_efficiency)
290
+ if threshold_index == 0 and efficiencies[0] < threshold_efficiency:
291
+ return
292
+
293
+ self.energy_threshold = bin_edges[threshold_index]
294
+
295
+ def calculate_uncertainty_effective_area(self):
296
+ """
297
+ Calculate the uncertainties on the effective collection area.
298
+
299
+ Returns
300
+ -------
301
+ errors : dict
302
+ Dictionary with uncertainties for the file.
303
+ """
304
+ bin_edges = self.create_bin_edges()
305
+ triggered_event_histogram = self.compute_triggered_event_histogram(
306
+ self.data["event_energies_mc"], bin_edges
307
+ )
308
+ simulated_event_histogram = self.data["simulated_event_histogram"]
309
+ _, relative_errors = self.compute_efficiency_and_errors(
310
+ triggered_event_histogram, simulated_event_histogram
311
+ )
312
+ return {"relative_errors": relative_errors}
313
+
314
+ def calculate_energy_estimate(self):
315
+ """
316
+ Calculate the uncertainties in energy estimation.
317
+
318
+ Returns
319
+ -------
320
+ float
321
+ The calculated uncertainty for energy estimation.
322
+ """
323
+ logging.info("Calculating Energy Resolution Error")
324
+
325
+ event_energies_reco = self.data["event_energies_reco"]
326
+ event_energies_mc = self.data["event_energies_mc"]
327
+
328
+ if len(event_energies_reco) != len(event_energies_mc):
329
+ raise ValueError(f"Mismatch in the number of energies for file {self.file_path}")
330
+
331
+ energy_deviation = (event_energies_reco - event_energies_mc) / event_energies_mc
332
+
333
+ bin_edges = self.create_bin_edges()
334
+ bin_indices = np.digitize(event_energies_reco, bin_edges) - 1
335
+
336
+ energy_deviation_by_bin = [
337
+ energy_deviation[bin_indices == i] for i in range(len(bin_edges) - 1)
338
+ ]
339
+
340
+ # Calculate sigma for each bin
341
+ sigma_energy = [np.std(d) if len(d) > 0 else np.nan for d in energy_deviation_by_bin]
342
+
343
+ # Calculate delta_energy as the mean deviation for each bin
344
+ delta_energy = [np.mean(d) if len(d) > 0 else np.nan for d in energy_deviation_by_bin]
345
+
346
+ # Combine sigma into a single measure
347
+ overall_uncertainty = np.nanmean(sigma_energy)
348
+
349
+ return overall_uncertainty, sigma_energy, delta_energy
350
+
351
+ def calculate_metrics(self):
352
+ """Calculate all defined metrics as specified in self.metrics and store results."""
353
+ if "uncertainty_effective_area" in self.metrics:
354
+
355
+ self.uncertainty_effective_area = self.calculate_uncertainty_effective_area()
356
+ if self.uncertainty_effective_area:
357
+ validity_range = self.metrics.get("uncertainty_effective_area", {}).get(
358
+ "valid_range"
359
+ )
360
+ min_energy, max_energy = validity_range["value"][0] * u.Unit(
361
+ validity_range["unit"]
362
+ ), validity_range["value"][1] * u.Unit(validity_range["unit"])
363
+
364
+ valid_errors = [
365
+ error
366
+ for energy, error in zip(
367
+ self.data["bin_edges_low"],
368
+ self.uncertainty_effective_area["relative_errors"],
369
+ )
370
+ if min_energy <= energy <= max_energy
371
+ ]
372
+ self.uncertainty_effective_area["max_error"] = (
373
+ max(valid_errors) if valid_errors else 0.0
374
+ )
375
+ ref_value = self.metrics.get("uncertainty_effective_area", {}).get("target_error")[
376
+ "value"
377
+ ]
378
+ _logger.info(
379
+ f"Effective Area Error (max in validity range): "
380
+ f"{self.uncertainty_effective_area['max_error'].value:.6f}, "
381
+ f"Reference: {ref_value:.3f}"
382
+ )
383
+
384
+ if "energy_estimate" in self.metrics:
385
+ self.energy_estimate, self.sigma_energy, self.delta_energy = (
386
+ self.calculate_energy_estimate()
387
+ )
388
+ ref_value = self.metrics.get("energy_estimate", {}).get("target_error")["value"]
389
+ _logger.info(
390
+ f"Energy Estimate Error: {self.energy_estimate:.3f}, Reference: {ref_value:.3f}"
391
+ )
392
+ else:
393
+ raise ValueError("Invalid metric specified.")
394
+ self.metric_results = {
395
+ "uncertainty_effective_area": self.uncertainty_effective_area,
396
+ "energy_estimate": self.energy_estimate,
397
+ }
398
+ return self.metric_results
399
+
400
+ def calculate_max_error_for_effective_area(self):
401
+ """
402
+ Calculate the maximum relative error for effective area.
403
+
404
+ Returns
405
+ -------
406
+ max_error : float
407
+ Maximum relative error.
408
+ """
409
+ if "relative_errors" in self.metric_results["uncertainty_effective_area"]:
410
+ return np.max(self.metric_results["uncertainty_effective_area"]["relative_errors"])
411
+ if self.uncertainty_effective_area:
412
+ return np.max(self.uncertainty_effective_area["relative_errors"])
413
+ return None
414
+
415
+ def calculate_overall_metric(self, metric="average"):
416
+ """
417
+ Calculate an overall metric for the statistical uncertainties.
418
+
419
+ Parameters
420
+ ----------
421
+ metric : str
422
+ The metric to calculate ('average', 'maximum').
423
+
424
+ Returns
425
+ -------
426
+ dict
427
+ Dictionary with overall maximum errors for each metric.
428
+ """
429
+ # Decide how to combine the metrics
430
+ if self.metric_results is None:
431
+ raise ValueError("Metrics have not been computed yet.")
432
+
433
+ overall_max_errors = {}
434
+
435
+ for metric_name, result in self.metric_results.items():
436
+ if metric_name == "uncertainty_effective_area":
437
+ max_errors = self.calculate_max_error_for_effective_area()
438
+ overall_max_errors[metric_name] = max_errors if max_errors else 0
439
+ elif metric_name in [
440
+ "error_gamma_ray_psf",
441
+ ]:
442
+ overall_max_errors[metric_name] = result
443
+ else:
444
+ raise ValueError(f"Unsupported result type for {metric_name}: {type(result)}")
445
+ _logger.info(f"overall_max_errors {overall_max_errors}")
446
+ all_max_errors = list(overall_max_errors.values())
447
+ if metric == "average":
448
+ overall_metric = np.mean(all_max_errors)
449
+ elif metric == "maximum":
450
+ overall_metric = np.max(all_max_errors)
451
+ else:
452
+ raise ValueError(f"Unsupported metric: {metric}")
453
+
454
+ return overall_metric
@@ -0,0 +1,146 @@
1
+ """
2
+ Calculate the scaled number of events based on metrics.
3
+
4
+ Module for scaling events based on statistical error metrics. Contains the `EventScaler` class,
5
+ which scales the number of events for both the entire dataset and specific grid points.
6
+ Scaling factors are calculated using error metrics and the evaluator's results.
7
+ """
8
+
9
+ import logging
10
+
11
+ import astropy.units as u
12
+ import numpy as np
13
+
14
+ from simtools.production_configuration.calculate_statistical_errors_grid_point import (
15
+ StatisticalErrorEvaluator,
16
+ )
17
+
18
+ _logger = logging.getLogger(__name__)
19
+
20
+
21
+ class EventScaler:
22
+ """
23
+ Scales the number of events based on statistical error metrics.
24
+
25
+ Supports scaling both the entire dataset and specific grid points like energy values.
26
+ """
27
+
28
+ def __init__(self, evaluator: StatisticalErrorEvaluator, science_case: str, metrics: dict):
29
+ """
30
+ Initialize the EventScaler with the evaluator, science case, and metrics.
31
+
32
+ Parameters
33
+ ----------
34
+ evaluator : StatisticalErrorEvaluator
35
+ The evaluator responsible for calculating metrics and handling event data.
36
+ science_case : str
37
+ The science case used to adjust the uncertainty factor.
38
+ metrics : dict
39
+ Dictionary containing metrics, including target error for effective area.
40
+ """
41
+ self.evaluator = evaluator
42
+ self.science_case = science_case
43
+ self.metrics = metrics
44
+
45
+ def scale_events(self, return_sum: bool = True) -> u.Quantity:
46
+ """
47
+ Calculate the scaled number of events based on statistical error metrics.
48
+
49
+ If `return_sum` is `True`, the method returns the sum of scaled events for the entire
50
+ dataset. If `return_sum` is `False`, it returns the scaled number of events for each
51
+ grid point (e.g., along the energy axis).
52
+
53
+ Parameters
54
+ ----------
55
+ return_sum : bool, optional
56
+ If `True`, returns the sum of scaled events for the entire dataset. If `False`,
57
+ returns the scaled events for each grid point along the energy axis. Default is `True`.
58
+
59
+ Returns
60
+ -------
61
+ u.Quantity
62
+ If `return_sum` is `True`, returns the total scaled number of events as a `u.Quantity`.
63
+ If `return_sum` is `False`, returns an array of scaled events along the energy axis as
64
+ a `u.Quantity`.
65
+ """
66
+ scaling_factor = self._compute_scaling_factor()
67
+
68
+ base_events = self._number_of_simulated_events()
69
+
70
+ if return_sum:
71
+ return np.sum(base_events * scaling_factor)
72
+ return base_events * scaling_factor
73
+
74
+ def _compute_scaling_factor(self) -> float:
75
+ """
76
+ Compute the scaling factor based on the error metrics.
77
+
78
+ Returns
79
+ -------
80
+ float
81
+ The scaling factor.
82
+ """
83
+ metric_results = self.evaluator.calculate_metrics()
84
+ uncertainty_effective_area = metric_results.get("uncertainty_effective_area", {})
85
+ current_max_error = uncertainty_effective_area.get("max_error")
86
+ target_max_error = self.metrics.get("uncertainty_effective_area", {}).get("target_error")[
87
+ "value"
88
+ ]
89
+
90
+ return (
91
+ current_max_error / target_max_error
92
+ ) ** 2 * self._apply_science_case_scaling_factor()
93
+
94
+ def _apply_science_case_scaling_factor(self) -> float:
95
+ """
96
+ Apply the uncertainty factor based on the science case.
97
+
98
+ Returns
99
+ -------
100
+ float
101
+ The final scaling factor after applying uncertainty.
102
+ """
103
+ return 1 if self.science_case == "science case 1" else 1.0
104
+
105
+ def _number_of_simulated_events(self) -> u.Quantity:
106
+ """
107
+ Fetch the number of simulated events from the evaluator's data.
108
+
109
+ Returns
110
+ -------
111
+ u.Quantity
112
+ The number of simulated events.
113
+ """
114
+ return self.evaluator.data.get("simulated_event_histogram")
115
+
116
+ def calculate_scaled_events_at_grid_point(
117
+ self,
118
+ grid_point: tuple,
119
+ ) -> u.Quantity:
120
+ """
121
+ Calculate the scaled number of events for a specific energy grid point.
122
+
123
+ Parameters
124
+ ----------
125
+ grid_point : tuple
126
+ The grid point specifying energy, azimuth, zenith, NSB, and offset.
127
+
128
+ Returns
129
+ -------
130
+ float
131
+ The scaled number of events at the specified grid point (energy).
132
+ """
133
+ energy = grid_point[0]
134
+ bin_edges = self.evaluator.create_bin_edges()
135
+ bin_idx = np.digitize(energy, bin_edges) - 1
136
+
137
+ scaling_factor = self._compute_scaling_factor()
138
+
139
+ simulated_event_histogram = self.evaluator.data.get("simulated_event_histogram", [])
140
+
141
+ if bin_idx < 0 or bin_idx >= len(simulated_event_histogram):
142
+ raise ValueError(f"Energy {energy} is outside the range of the simulated events data.")
143
+
144
+ base_events = self._number_of_simulated_events()
145
+ base_event_at_energy = base_events[bin_idx]
146
+ return base_event_at_energy * scaling_factor