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
@@ -1,325 +1,381 @@
1
- import copy
1
+ """CORSIKA configuration."""
2
+
2
3
  import logging
3
4
  from pathlib import Path
4
5
 
5
- import astropy.units as u
6
6
  import numpy as np
7
- from astropy.io.misc import yaml
7
+ from astropy import units as u
8
8
 
9
9
  import simtools.utils.general as gen
10
+ from simtools.corsika.primary_particle import PrimaryParticle
10
11
  from simtools.io_operations import io_handler
11
- from simtools.layout.array_layout import ArrayLayout
12
- from simtools.utils import names
13
- from simtools.utils.general import collect_data_from_file_or_dict
12
+ from simtools.model.model_parameter import ModelParameter
14
13
 
15
14
  __all__ = [
16
15
  "CorsikaConfig",
17
- "MissingRequiredInputInCorsikaConfigData",
18
- "InvalidCorsikaInput",
16
+ "InvalidCorsikaInputError",
19
17
  ]
20
18
 
21
19
 
22
- class MissingRequiredInputInCorsikaConfigData(Exception):
23
- """Exception for missing required input in corsika config data."""
24
-
25
-
26
- class InvalidCorsikaInput(Exception):
20
+ class InvalidCorsikaInputError(Exception):
27
21
  """Exception for invalid corsika input."""
28
22
 
29
23
 
30
24
  class CorsikaConfig:
31
25
  """
32
- CorsikaConfig deals with configuration for running CORSIKA. User parameters must be given by \
33
- the corsika_config_data or corsika_config_file arguments. An example of corsika_config_data
34
- follows below.
35
-
36
- .. code-block:: python
37
-
38
- corsika_config_data = {
39
- 'data_directory': .
40
- 'primary': 'proton',
41
- 'nshow': 10000,
42
- 'nrun': 1,
43
- 'zenith': 20 * u.deg,
44
- 'viewcone': 5 * u.deg,
45
- 'erange': [10 * u.GeV, 100 * u.TeV],
46
- 'eslope': -2,
47
- 'phi': 0 * u.deg,
48
- 'cscat': [10, 1500 * u.m, 0]
49
- }
26
+ Configuration for the CORSIKA air shower simulation software.
27
+
28
+ Follows closely the CORSIKA definitions and output format (see CORSIKA manual).
29
+
30
+ The configuration is set as a dict corresponding to the command line configuration groups
31
+ (especially simulation_software, simulation configuration, simulation parameters).
50
32
 
51
33
  Parameters
52
34
  ----------
53
- mongo_db_config: dict
35
+ array_model : ArrayModel
36
+ Array model.
37
+ args_dict : dict
38
+ Configuration dictionary.
39
+ db_config : dict
54
40
  MongoDB configuration.
55
- site: str
56
- North or South.
57
- layout_name: str
58
- Name of the layout.
59
- label: str
41
+ label : str
60
42
  Instance label.
61
- corsika_config_data: dict
62
- CORSIKA user parameters.
63
- corsika_config_file: str
64
- Name of the yaml configuration file. If not provided, \
65
- data/parameters/corsika_parameters.yml will be used.
66
- corsika_parameters_file: str
67
- Name of the yaml file to set remaining CORSIKA parameters.
68
- simtel_source_path: str or Path
69
- Location of source of the sim_telarray/CORSIKA package.
70
43
  """
71
44
 
72
- def __init__(
73
- self,
74
- mongo_db_config,
75
- site,
76
- layout_name,
77
- label=None,
78
- corsika_config_data=None,
79
- corsika_config_file=None,
80
- corsika_parameters_file=None,
81
- simtel_source_path=None,
82
- ):
83
- """
84
- Initialize CorsikaConfig.
85
- """
86
-
45
+ def __init__(self, array_model, args_dict, db_config=None, label=None):
46
+ """Initialize CorsikaConfig."""
87
47
  self._logger = logging.getLogger(__name__)
88
48
  self._logger.debug("Init CorsikaConfig")
89
49
 
90
50
  self.label = label
91
- self.site = names.validate_site_name(site)
92
- self.primary = None
93
- self.eslope = None
51
+ self.zenith_angle = None
52
+ self.azimuth_angle = None
53
+ self._run_number = None
94
54
  self.config_file_path = None
95
- self._output_generic_file_name = None
96
- self._simtel_source_path = simtel_source_path
55
+ # The following uses the setter defined below, that is why the args_dict is passed
56
+ self.primary_particle = args_dict
97
57
 
98
58
  self.io_handler = io_handler.IOHandler()
59
+ self.array_model = array_model
60
+ self.config = self.fill_corsika_configuration(args_dict, db_config)
61
+ self._is_file_updated = False
99
62
 
100
- # Grabbing layout name and building ArrayLayout
101
- self.layout_name = names.validate_array_layout_name(layout_name)
102
- self.layout = ArrayLayout.from_array_layout_name(
103
- mongo_db_config=mongo_db_config,
104
- array_layout_name=f"{self.site}-{self.layout_name}",
105
- label=self.label,
63
+ def __repr__(self):
64
+ """CorsikaConfig class representation."""
65
+ return (
66
+ f"<class {self.__class__.__name__}> "
67
+ f"(site={self.array_model.site}, "
68
+ f"layout={self.array_model.layout_name}, label={self.label})"
106
69
  )
107
70
 
108
- # Load parameters
109
- if corsika_parameters_file is None:
110
- corsika_parameters_file = self.io_handler.get_input_data_file(
111
- "parameters", "corsika_parameters.yml"
112
- )
71
+ @property
72
+ def primary_particle(self):
73
+ """Primary particle."""
74
+ return self._primary_particle
113
75
 
114
- self._corsika_parameters = self.load_corsika_parameters_file(corsika_parameters_file)
76
+ @primary_particle.setter
77
+ def primary_particle(self, args_dict):
78
+ """
79
+ Set primary particle from input dictionary.
115
80
 
116
- corsika_config_data = collect_data_from_file_or_dict(
117
- corsika_config_file, corsika_config_data
118
- )
119
- self.set_user_parameters(corsika_config_data)
120
- self._is_file_updated = False
81
+ This is to make sure that when setting the primary particle,
82
+ we get the full PrimaryParticle object expected.
121
83
 
122
- def __repr__(self):
123
- text = (
124
- f"<class {self.__class__.__name__}> "
125
- f"(site={self.site}, layout={self.layout_name}, label={self.label})"
126
- )
127
- return text
84
+ Parameters
85
+ ----------
86
+ args_dict: dict
87
+ Configuration dictionary
88
+ """
89
+ self._primary_particle = self._set_primary_particle(args_dict)
128
90
 
129
- @staticmethod
130
- def load_corsika_parameters_file(corsika_parameters_file):
91
+ def fill_corsika_configuration(self, args_dict, db_config=None):
131
92
  """
132
- Load CORSIKA parameters from the provided corsika_parameters_file.
93
+ Fill CORSIKA configuration.
94
+
95
+ Dictionary keys are CORSIKA parameter names.
96
+ Values are converted to CORSIKA-consistent units.
97
+
133
98
 
134
99
  Parameters
135
100
  ----------
136
- corsika_parameters_file: str or Path
137
- File with CORSIKA parameters.
101
+ args_dict : dict
102
+ Configuration dictionary.
103
+ db_config: dict
104
+ Database configuration.
138
105
 
139
106
  Returns
140
107
  -------
141
- corsika_parameters: dict
108
+ dict
142
109
  Dictionary with CORSIKA parameters.
143
110
  """
111
+ if args_dict is None:
112
+ return {}
113
+
114
+ self._logger.debug("Setting CORSIKA parameters ")
115
+
116
+ self._is_file_updated = False
117
+ self.azimuth_angle = int(args_dict["azimuth_angle"].to("deg").value)
118
+ self.zenith_angle = args_dict["zenith_angle"].to("deg").value
119
+
120
+ self._logger.debug(
121
+ f"Setting CORSIKA parameters from database ({args_dict['model_version']})"
122
+ )
123
+
124
+ config = {}
125
+ config["USER_INPUT"] = self._corsika_configuration_from_user_input(args_dict)
126
+
127
+ if db_config is None: # all following parameter require DB
128
+ return config
129
+
130
+ db_model_parameters = ModelParameter(
131
+ mongo_db_config=db_config, model_version=args_dict["model_version"]
132
+ )
133
+ parameters_from_db = db_model_parameters.get_simulation_software_parameters("corsika")
144
134
 
145
- logger = logging.getLogger(__name__)
146
- logger.debug(f"Loading CORSIKA parameters from file {corsika_parameters_file}")
147
- with open(corsika_parameters_file, "r", encoding="utf-8") as f:
148
- corsika_parameters = yaml.load(f)
149
- return corsika_parameters
135
+ config["INTERACTION_FLAGS"] = self._corsika_configuration_interaction_flags(
136
+ parameters_from_db
137
+ )
138
+ config["CHERENKOV_EMISSION_PARAMETERS"] = self._corsika_configuration_cherenkov_parameters(
139
+ parameters_from_db
140
+ )
141
+ config["DEBUGGING_OUTPUT_PARAMETERS"] = self._corsika_configuration_debugging_parameters()
142
+ config["IACT_PARAMETERS"] = self._corsika_configuration_iact_parameters(parameters_from_db)
143
+
144
+ return config
150
145
 
151
- def set_user_parameters(self, corsika_config_data):
146
+ def _corsika_configuration_from_user_input(self, args_dict):
152
147
  """
153
- Set user parameters from a dict.
148
+ Get CORSIKA configuration from user input.
154
149
 
155
150
  Parameters
156
151
  ----------
157
- corsika_config_data: dict
158
- Contains the user parameters. Ex.
159
-
160
- .. code-block:: python
161
-
162
- corsika_config_data = {
163
- 'primary': 'proton',
164
- 'nshow': 10000,
165
- 'nrun': 1,
166
- 'zenith': 20 * u.deg,
167
- 'viewcone': 5 * u.deg,
168
- 'erange': [10 * u.GeV, 100 * u.TeV],
169
- 'eslope': -2,
170
- 'phi': 0 * u.deg,
171
- 'cscat': [10, 1500 * u.m, 0]
172
- }
152
+ args_dict : dict
153
+ Configuration dictionary.
173
154
 
174
- Raises
175
- ------
176
- InvalidCorsikaInput
177
- If any parameter given as input has wrong len, unit or
178
- an invalid name.
179
- MissingRequiredInputInCorsikaConfigData
180
- If any required user parameter is missing.
181
- """
182
-
183
- self._logger.debug("Setting user parameters from corsika_config_data")
184
- self._user_parameters = {}
185
-
186
- user_pars = self._corsika_parameters["USER_PARAMETERS"]
187
-
188
- # Collecting all parameters given as arguments
189
- for key_args, value_args in corsika_config_data.items():
190
- # Looping over USER_PARAMETERS and searching for a match
191
- is_identified = False
192
- for par_name, par_info in user_pars.items():
193
- if key_args.upper() != par_name and key_args.upper() not in par_info["names"]:
194
- continue
195
- # Matched parameter
196
- validated_value_args = self._validate_and_convert_argument(
197
- par_name, par_info, value_args
198
- )
199
- self._user_parameters[par_name] = validated_value_args
200
- is_identified = True
201
-
202
- # Raising error for an unidentified input.
203
- if not is_identified:
204
- msg = f"Argument {key_args} cannot be identified."
205
- self._logger.error(msg)
206
- raise InvalidCorsikaInput(msg)
207
-
208
- # Checking for parameters with default option
209
- # If it is not given, filling it with the default value
210
- for par_name, par_info in user_pars.items():
211
- if par_name in self._user_parameters:
212
- continue
213
- if "default" in par_info.keys():
214
- validated_value = self._validate_and_convert_argument(
215
- par_name, par_info, par_info["default"]
216
- )
217
- self._user_parameters[par_name] = validated_value
218
- else:
219
- msg = f"Required parameters {par_name} was not given (there may be more)."
220
- self._logger.error(msg)
221
- raise MissingRequiredInputInCorsikaConfigData(msg)
155
+ Returns
156
+ -------
157
+ dict
158
+ Dictionary with CORSIKA parameters.
159
+ """
160
+ return {
161
+ "EVTNR": [args_dict["event_number_first_shower"]],
162
+ "NSHOW": [args_dict["nshow"]],
163
+ "PRMPAR": [self.primary_particle.corsika7_id],
164
+ "ESLOPE": [args_dict["eslope"]],
165
+ "ERANGE": [
166
+ args_dict["energy_range"][0].to("GeV").value,
167
+ args_dict["energy_range"][1].to("GeV").value,
168
+ ],
169
+ "THETAP": [
170
+ float(args_dict["zenith_angle"].to("deg").value),
171
+ float(args_dict["zenith_angle"].to("deg").value),
172
+ ],
173
+ "PHIP": [
174
+ self._rotate_azimuth_by_180deg(
175
+ args_dict["azimuth_angle"].to("deg").value,
176
+ correct_for_geomagnetic_field_alignment=args_dict[
177
+ "correct_for_b_field_alignment"
178
+ ],
179
+ ),
180
+ self._rotate_azimuth_by_180deg(
181
+ args_dict["azimuth_angle"].to("deg").value,
182
+ correct_for_geomagnetic_field_alignment=args_dict[
183
+ "correct_for_b_field_alignment"
184
+ ],
185
+ ),
186
+ ],
187
+ "VIEWCONE": [
188
+ args_dict["view_cone"][0].to("deg").value,
189
+ args_dict["view_cone"][1].to("deg").value,
190
+ ],
191
+ "CSCAT": [
192
+ args_dict["core_scatter"][0],
193
+ args_dict["core_scatter"][1].to("cm").value,
194
+ 0.0,
195
+ ],
196
+ }
222
197
 
223
- # Converting AZM to CORSIKA reference (PHIP)
224
- phip = 180.0 - self._user_parameters["AZM"][0]
225
- phip = phip + 360.0 if phip < 0.0 else phip
226
- phip = phip - 360.0 if phip >= 360.0 else phip
227
- self._user_parameters["PHIP"] = [phip, phip]
198
+ def _corsika_configuration_interaction_flags(self, parameters_from_db):
199
+ """
200
+ Return CORSIKA interaction flags / parameters.
228
201
 
229
- self._is_file_updated = False
202
+ Parameters
203
+ ----------
204
+ parameters_from_db : dict
205
+ CORSIKA parameters from the database.
230
206
 
231
- def _validate_and_convert_argument(self, par_name, par_info, value_args_in):
207
+ Returns
208
+ -------
209
+ interaction_parameters : dict
210
+ Dictionary with CORSIKA interaction parameters.
232
211
  """
233
- Validate input user parameter and convert it to the right units, if needed.
234
- Returns the validated arguments in a list.
212
+ parameters = {}
213
+ parameters["FIXHEI"] = self._input_config_first_interaction_height(
214
+ parameters_from_db["corsika_first_interaction_height"]
215
+ )
216
+ parameters["FIXCHI"] = [
217
+ self._input_config_corsika_starting_grammage(
218
+ parameters_from_db["corsika_starting_grammage"]
219
+ )
220
+ ]
221
+ parameters["TSTART"] = ["T"]
222
+ parameters["ECUTS"] = self._input_config_corsika_particle_kinetic_energy_cutoff(
223
+ parameters_from_db["corsika_particle_kinetic_energy_cutoff"]
224
+ )
225
+ parameters["MUADDI"] = ["F"]
226
+ parameters["MUMULT"] = ["T"]
227
+ parameters["LONGI"] = self._input_config_corsika_longitudinal_parameters(
228
+ parameters_from_db["corsika_longitudinal_shower_development"]
229
+ )
230
+ parameters["MAXPRT"] = ["10"]
231
+ parameters["ECTMAP"] = ["1.e6"]
232
+
233
+ self._logger.debug(f"Interaction parameters: {parameters}")
234
+ return parameters
235
+
236
+ def _input_config_first_interaction_height(self, entry):
237
+ """Return FIXHEI parameter CORSIKA format."""
238
+ return [f"{entry['value']*u.Unit(entry['unit']).to('cm'):.2f}", "0"]
239
+
240
+ def _input_config_corsika_starting_grammage(self, entry):
241
+ """Return FIXCHI parameter CORSIKA format."""
242
+ return f"{entry['value']*u.Unit(entry['unit']).to('g/cm2')}"
243
+
244
+ def _input_config_corsika_particle_kinetic_energy_cutoff(self, entry):
245
+ """Return ECUTS parameter CORSIKA format."""
246
+ e_cuts = gen.convert_string_to_list(entry["value"])
247
+ return [
248
+ f"{e_cuts[0]*u.Unit(entry['unit']).to('GeV')} "
249
+ f"{e_cuts[1]*u.Unit(entry['unit']).to('GeV')} "
250
+ f"{e_cuts[2]*u.Unit(entry['unit']).to('GeV')} "
251
+ f"{e_cuts[3]*u.Unit(entry['unit']).to('GeV')}"
252
+ ]
253
+
254
+ def _input_config_corsika_longitudinal_parameters(self, entry):
255
+ """Return LONGI parameter CORSIKA format."""
256
+ return ["T", f"{entry['value']*u.Unit(entry['unit']).to('g/cm2')}", "F", "F"]
257
+
258
+ def _corsika_configuration_cherenkov_parameters(self, parameters_from_db):
235
259
  """
260
+ Return CORSIKA Cherenkov emission parameters.
236
261
 
237
- # Turning value_args into a list, if it is not.
238
- value_args = gen.copy_as_list(value_args_in)
239
-
240
- if len(value_args) == 1 and par_name in ["THETAP", "AZM"]:
241
- # Fixing single value zenith or azimuth angle.
242
- # THETAP and AZM should be written as a 2 values range in the CORSIKA input file
243
- value_args = value_args * 2
244
- elif len(value_args) == 1 and par_name == "VIEWCONE":
245
- # Fixing single value viewcone.
246
- # VIEWCONE should be written as a 2 values range in the CORSIKA input file
247
- value_args = [0 * par_info["unit"][0], value_args[0]]
248
- elif par_name == "PRMPAR":
249
- value_args = self._convert_primary_input_and_store_primary_name(value_args)
250
- elif par_name == "ESLOPE":
251
- self.eslope = value_args[0]
262
+ Parameters
263
+ ----------
264
+ parameters_from_db : dict
265
+ CORSIKA parameters from the database.
252
266
 
253
- if len(value_args) != par_info["len"]:
254
- msg = f"CORSIKA input entry with wrong len: {par_name}"
255
- self._logger.error(msg)
256
- raise InvalidCorsikaInput(msg)
267
+ Returns
268
+ -------
269
+ dict
270
+ Dictionary with CORSIKA Cherenkov emission parameters.
271
+ """
272
+ parameters = {}
273
+ parameters["CERSIZ"] = [parameters_from_db["corsika_cherenkov_photon_bunch_size"]["value"]]
274
+ parameters["CERFIL"] = "0"
275
+ parameters["CWAVLG"] = self._input_config_corsika_cherenkov_wavelength(
276
+ parameters_from_db["corsika_cherenkov_photon_wavelength_range"]
277
+ )
278
+ self._logger.debug(f"Cherenkov parameters: {parameters}")
279
+ return parameters
280
+
281
+ def _input_config_corsika_cherenkov_wavelength(self, entry):
282
+ """Return CWAVLG parameter CORSIKA format."""
283
+ wavelength_range = gen.convert_string_to_list(entry["value"])
284
+ return [
285
+ f"{wavelength_range[0]*u.Unit(entry['unit']).to('nm')}",
286
+ f"{wavelength_range[1]*u.Unit(entry['unit']).to('nm')}",
287
+ ]
288
+
289
+ def _corsika_configuration_iact_parameters(self, parameters_from_db):
290
+ """
291
+ Return CORSIKA IACT parameters.
257
292
 
258
- if "unit" not in par_info.keys():
259
- return value_args
293
+ Parameters
294
+ ----------
295
+ parameters_from_db : dict
296
+ CORSIKA parameters from the database.
260
297
 
261
- # Turning par_info['unit'] into a list, if it is not.
262
- par_unit = gen.copy_as_list(par_info["unit"])
298
+ Returns
299
+ -------
300
+ dict
301
+ Dictionary with CORSIKA IACT parameters.
302
+ """
303
+ parameters = {}
304
+ parameters["SPLIT_AUTO"] = [parameters_from_db["corsika_iact_split_auto"]["value"]]
305
+ parameters["IO_BUFFER"] = [
306
+ self._input_config_io_buff(parameters_from_db["corsika_iact_io_buffer"])
307
+ ]
308
+ parameters["MAX_BUNCHES"] = [parameters_from_db["corsika_iact_max_bunches"]["value"]]
309
+ self._logger.debug(f"IACT parameters: {parameters}")
310
+ return parameters
311
+
312
+ def _corsika_configuration_debugging_parameters(self):
313
+ """Return CORSIKA debugging output parameters."""
314
+ return {
315
+ "DEBUG": ["F", 6, "F", 1000000],
316
+ "DATBAS": ["yes"],
317
+ "DIRECT": ["/dev/null"],
318
+ }
263
319
 
264
- # Checking units and converting them, if needed.
265
- value_args_with_units = []
266
- for arg, unit in zip(value_args, par_unit):
267
- if unit is None:
268
- value_args_with_units.append(arg)
269
- continue
320
+ def _input_config_io_buff(self, entry):
321
+ """Return IO_BUFFER parameter CORSIKA format."""
322
+ return f"{entry['value']}{entry['unit']}"
270
323
 
271
- if isinstance(arg, str):
272
- arg = u.quantity.Quantity(arg)
324
+ def _rotate_azimuth_by_180deg(self, az, correct_for_geomagnetic_field_alignment=True):
325
+ """
326
+ Convert azimuth angle to the CORSIKA coordinate system.
273
327
 
274
- if not isinstance(arg, u.quantity.Quantity):
275
- msg = f"CORSIKA input given without unit: {par_name}"
276
- self._logger.error(msg)
277
- raise InvalidCorsikaInput(msg)
278
- if not arg.unit.is_equivalent(unit):
279
- msg = f"CORSIKA input given with wrong unit: {par_name}"
280
- self._logger.error(msg)
281
- raise InvalidCorsikaInput(msg)
328
+ Parameters
329
+ ----------
330
+ az: float
331
+ Azimuth angle in degrees.
332
+ correct_for_geomagnetic_field_alignment: bool
333
+ Whether to correct for the geomagnetic field alignment.
282
334
 
283
- value_args_with_units.append(arg.to(unit).value)
335
+ Returns
336
+ -------
337
+ float
338
+ Azimuth angle in degrees in the CORSIKA coordinate system.
339
+ """
340
+ b_field_declination = 0
341
+ if correct_for_geomagnetic_field_alignment:
342
+ b_field_declination = self.array_model.site_model.get_parameter_value("geomag_rotation")
343
+ return (az + 180 + b_field_declination) % 360
284
344
 
285
- return value_args_with_units
345
+ @property
346
+ def primary(self):
347
+ """Primary particle name."""
348
+ return self.primary_particle.name
286
349
 
287
- def _convert_primary_input_and_store_primary_name(self, value):
350
+ def _set_primary_particle(self, args_dict):
288
351
  """
289
- Convert a primary name into the proper CORSIKA particle ID and store its name in \
290
- the self.primary attribute.
352
+ Set primary particle from input dictionary.
291
353
 
292
354
  Parameters
293
355
  ----------
294
- value: str
295
- Input primary name (e.g gamma, proton ...)
296
-
297
- Raises
298
- ------
299
- InvalidPrimary
300
- If the input name is not found.
356
+ args_dict: dict
357
+ Input dictionary.
301
358
 
302
359
  Returns
303
360
  -------
304
- int
305
- Respective number of the given primary.
361
+ PrimaryParticle
362
+ Primary particle.
363
+
306
364
  """
307
- for prim_name, prim_info in self._corsika_parameters["PRIMARIES"].items():
308
- if value[0].upper() == prim_name or value[0].upper() in prim_info["names"]:
309
- self.primary = prim_name.lower()
310
- return [prim_info["number"]]
311
- msg = f"Primary not valid: {value}"
312
- self._logger.error(msg)
313
- raise InvalidCorsikaInput(msg)
365
+ if not args_dict or args_dict.get("primary_id_type") is None:
366
+ return PrimaryParticle()
367
+ return PrimaryParticle(
368
+ particle_id_type=args_dict.get("primary_id_type"), particle_id=args_dict.get("primary")
369
+ )
314
370
 
315
- def get_user_parameter(self, par_name):
371
+ def get_config_parameter(self, par_name):
316
372
  """
317
- Get the value of a user parameter.
373
+ Get value of CORSIKA configuration parameter.
318
374
 
319
375
  Parameters
320
376
  ----------
321
377
  par_name: str
322
- Name of the parameter as used in the CORSIKA input file (e.g. PRMPAR, THETAP ...)
378
+ Name of the parameter as used in the CORSIKA input file (e.g. PRMPAR, THETAP ...).
323
379
 
324
380
  Raises
325
381
  ------
@@ -331,115 +387,130 @@ class CorsikaConfig:
331
387
  list
332
388
  Value(s) of the parameter.
333
389
  """
334
- try:
335
- par_value = self._user_parameters[par_name.upper()]
336
- except KeyError:
337
- self._logger.warning(f"Parameter {par_name} is not a user parameter")
338
- raise
339
-
390
+ par_value = []
391
+ for _, values in self.config.items():
392
+ if par_name in values:
393
+ par_value = values[par_name]
394
+ if len(par_value) == 0:
395
+ self._logger.error(f"Parameter {par_name} is not a CORSIKA config parameter")
396
+ raise KeyError
340
397
  return par_value if len(par_value) > 1 else par_value[0]
341
398
 
342
- def print_user_parameters(self):
343
- """Print user parameters for inspection."""
344
- for par, value in self._user_parameters.items():
345
- print(f"{par} = {value}")
399
+ def print_config_parameter(self):
400
+ """Print CORSIKA config parameters for inspection."""
401
+ for parameter_type, parameter_dict in self.config.items():
402
+ print(f"Parameter type: {parameter_type}\n")
403
+ for par, value in parameter_dict.items():
404
+ print(f"{par} = {value}")
405
+
406
+ @staticmethod
407
+ def _get_text_single_line(pars, line_begin=""):
408
+ """
409
+ Return one parameter per line for each input parameter.
410
+
411
+ Parameters
412
+ ----------
413
+ pars: dict
414
+ Dictionary with the parameters to be written in the file.
415
+
416
+ Returns
417
+ -------
418
+ str
419
+ Text with the parameters.
420
+ """
421
+ text = ""
422
+ for par, values in pars.items():
423
+ line = line_begin + par + " "
424
+ for v in values:
425
+ line += str(v) + " "
426
+ line += "\n"
427
+ text += line
428
+ return text
346
429
 
347
- def export_input_file(self, use_multipipe=False):
430
+ def generate_corsika_input_file(self, use_multipipe=False, use_test_seeds=False):
348
431
  """
349
- Create and export CORSIKA input file.
432
+ Generate a CORSIKA input file.
350
433
 
351
434
  Parameters
352
435
  ----------
353
436
  use_multipipe: bool
354
437
  Whether to set the CORSIKA Inputs file to pipe
355
- the output directly to sim_telarray or not.
356
- """
438
+ the output directly to sim_telarray.
357
439
 
358
- sub_dir = "corsika_simtel" if use_multipipe else "corsika"
359
- self._set_output_file_and_directory(sub_dir)
360
- self._logger.debug(f"Exporting CORSIKA input file to {self.config_file_path}")
361
-
362
- def _get_text_single_line(pars):
363
- text = ""
364
- for par, values in pars.items():
365
- line = par + " "
366
- for v in values:
367
- line += str(v) + " "
368
- line += "\n"
369
- text += line
370
- return text
371
-
372
- def _get_text_multiple_lines(pars):
373
- text = ""
374
- for par, value_list in pars.items():
375
- for value in value_list:
376
- new_pars = {par: value}
377
- text += _get_text_single_line(new_pars)
378
- return text
440
+ """
441
+ if self._is_file_updated:
442
+ self._logger.debug(f"CORSIKA input file already updated: {self.config_file_path}")
443
+ return self.config_file_path
444
+ _output_generic_file_name = self.set_output_file_and_directory(use_multipipe=use_multipipe)
445
+ self._logger.info(f"Exporting CORSIKA input file to {self.config_file_path}")
379
446
 
380
447
  with open(self.config_file_path, "w", encoding="utf-8") as file:
381
448
  file.write("\n* [ RUN PARAMETERS ]\n")
382
- # Removing AZM entry first
383
- _user_pars_temp = copy.copy(self._user_parameters)
384
- _user_pars_temp.pop("AZM")
385
- text_parameters = _get_text_single_line(_user_pars_temp)
449
+ text_parameters = self._get_text_single_line(self.config["USER_INPUT"])
386
450
  file.write(text_parameters)
387
451
 
388
452
  file.write("\n* [ SITE PARAMETERS ]\n")
389
- text_site_parameters = _get_text_single_line(
390
- self._corsika_parameters["SITE_PARAMETERS"][self.site]
453
+ text_site_parameters = self._get_text_single_line(
454
+ self.array_model.site_model.get_corsika_site_parameters(
455
+ config_file_style=True, model_directory=self.array_model.get_config_directory()
456
+ )
391
457
  )
392
458
  file.write(text_site_parameters)
393
459
 
394
- # Defining the IACT variables for the output file name
395
- file.write("\n")
396
- file.write(f"IACT setenv PRMNAME {self.primary}\n")
397
- file.write(f"IACT setenv ZA {int(self._user_parameters['THETAP'][0])}\n")
398
- file.write(f"IACT setenv AZM {int(self._user_parameters['AZM'][0])}\n")
460
+ file.write("\n* [ IACT ENV PARAMETERS ]\n")
461
+ file.write(f"IACT setenv PRMNAME {self.primary_particle.name}\n")
462
+ file.write(f"IACT setenv ZA {int(self.get_config_parameter('THETAP')[0])}\n")
463
+ file.write(f"IACT setenv AZM {self.azimuth_angle}\n")
399
464
 
400
465
  file.write("\n* [ SEEDS ]\n")
401
- self._write_seeds(file)
466
+ self._write_seeds(file, use_test_seeds)
402
467
 
403
468
  file.write("\n* [ TELESCOPES ]\n")
404
- telescope_list_text = self.layout.get_corsika_input_list()
469
+ telescope_list_text = self.get_corsika_telescope_list()
405
470
  file.write(telescope_list_text)
406
471
 
407
472
  file.write("\n* [ INTERACTION FLAGS ]\n")
408
- text_interaction_flags = _get_text_single_line(
409
- self._corsika_parameters["INTERACTION_FLAGS"]
410
- )
473
+ text_interaction_flags = self._get_text_single_line(self.config["INTERACTION_FLAGS"])
411
474
  file.write(text_interaction_flags)
412
475
 
413
476
  file.write("\n* [ CHERENKOV EMISSION PARAMETERS ]\n")
414
- text_cherenkov = _get_text_single_line(
415
- self._corsika_parameters["CHERENKOV_EMISSION_PARAMETERS"]
477
+ text_cherenkov = self._get_text_single_line(
478
+ self.config["CHERENKOV_EMISSION_PARAMETERS"]
416
479
  )
417
480
  file.write(text_cherenkov)
418
481
 
419
482
  file.write("\n* [ DEBUGGING OUTPUT PARAMETERS ]\n")
420
- text_debugging = _get_text_single_line(
421
- self._corsika_parameters["DEBUGGING_OUTPUT_PARAMETERS"]
422
- )
483
+ text_debugging = self._get_text_single_line(self.config["DEBUGGING_OUTPUT_PARAMETERS"])
423
484
  file.write(text_debugging)
424
485
 
425
- file.write("\n* [ OUTUPUT FILE ]\n")
486
+ file.write("\n* [ OUTPUT FILE ]\n")
426
487
  if use_multipipe:
427
488
  run_cta_script = Path(self.config_file_path.parent).joinpath("run_cta_multipipe")
428
- file.write(f"TELFIL |{str(run_cta_script)}\n")
489
+ file.write(f"TELFIL |{run_cta_script!s}\n")
429
490
  else:
430
- file.write(f"TELFIL {self._output_generic_file_name}\n")
491
+ file.write(f"TELFIL {_output_generic_file_name}\n")
431
492
 
432
493
  file.write("\n* [ IACT TUNING PARAMETERS ]\n")
433
- text_iact = _get_text_multiple_lines(self._corsika_parameters["IACT_TUNING_PARAMETERS"])
494
+ text_iact = self._get_text_single_line(
495
+ self.config["IACT_PARAMETERS"],
496
+ "IACT ",
497
+ )
434
498
  file.write(text_iact)
435
-
436
499
  file.write("\nEXIT")
437
500
 
501
+ # Write out the atmospheric transmission file to the model directory.
502
+ # This is done explicitly because it is not done "automatically" when CORSIKA is not piped
503
+ # to sim_telarray.
504
+ self.array_model.site_model.export_atmospheric_transmission_file(
505
+ model_directory=self.array_model.get_config_directory()
506
+ )
507
+
438
508
  self._is_file_updated = True
509
+ return self.config_file_path
439
510
 
440
- def get_file_name(self, file_type, run_number=None):
511
+ def get_corsika_config_file_name(self, file_type, run_number=None):
441
512
  """
442
- Get a CORSIKA config style file name for various file types.
513
+ Get a CORSIKA config style file name for various configuration file types.
443
514
 
444
515
  Parameters
445
516
  ----------
@@ -453,65 +524,77 @@ class CorsikaConfig:
453
524
  -------
454
525
  str
455
526
  for file_type="config_tmp":
456
- Get the CORSIKA input file for one specific run.
527
+ Return CORSIKA input file name for one specific run.
457
528
  This is the input file after being pre-processed by sim_telarray (pfp).
458
529
  for file_type="config":
459
- Get a general CORSIKA config inputs file.
530
+ Return generic CORSIKA config input file name.
460
531
  for file_type="output_generic"
461
- Get a generic file name for the TELFIL option in the CORSIKA inputs file.
532
+ Return generic file name for the TELFIL option in the CORSIKA inputs file.
462
533
  for file_type="multipipe"
463
- Get a multipipe "file name" for the TELFIL option in the CORSIKA inputs file.
534
+ Return multipipe "file name" for the TELFIL option in the CORSIKA inputs file.
464
535
 
465
536
  Raises
466
537
  ------
467
538
  ValueError
468
539
  If file_type is unknown or if the run number is not given for file_type==config_tmp.
469
540
  """
470
-
471
541
  file_label = f"_{self.label}" if self.label is not None else ""
472
- view_cone = ""
473
- if self._user_parameters["VIEWCONE"][0] != 0 or self._user_parameters["VIEWCONE"][1] != 0:
474
- view_cone = (
475
- f"_cone{int(self._user_parameters['VIEWCONE'][0]):d}-"
476
- f"{int(self._user_parameters['VIEWCONE'][1]):d}"
477
- )
478
- file_name = (
479
- f"{self.primary}_{self.site}_{self.layout_name}_"
480
- f"za{int(self._user_parameters['THETAP'][0]):03}-"
481
- f"azm{int(self._user_parameters['AZM'][0]):03}deg"
542
+
543
+ _vc_low = self.get_config_parameter("VIEWCONE")[0]
544
+ _vc_high = self.get_config_parameter("VIEWCONE")[1]
545
+ view_cone = (
546
+ f"_cone{int(_vc_low):d}-{int(_vc_high):d}" if _vc_low != 0 or _vc_high != 0 else ""
547
+ )
548
+
549
+ base_name = (
550
+ f"{self.primary_particle.name}_{self.array_model.site}_{self.array_model.layout_name}_"
551
+ f"za{int(self.get_config_parameter('THETAP')[0]):03}-"
552
+ f"azm{self.azimuth_angle:03}deg"
482
553
  f"{view_cone}{file_label}"
483
554
  )
484
555
 
485
556
  if file_type == "config_tmp":
486
- if run_number is not None:
487
- return f"corsika_config_run{run_number:06}_{file_name}.txt"
488
- raise ValueError("Must provide a run number for a temporary CORSIKA config file")
557
+ if run_number is None:
558
+ raise ValueError("Must provide a run number for a temporary CORSIKA config file")
559
+ return f"corsika_config_run{run_number:06}_{base_name}.txt"
489
560
  if file_type == "config":
490
- return f"corsika_config_{file_name}.input"
561
+ return f"corsika_config_{base_name}.input"
491
562
  if file_type == "output_generic":
492
563
  # The XXXXXX will be replaced by the run number after the pfp step with sed
493
- file_name = (
494
- f"corsika_runXXXXXX_"
495
- f"{self.primary}_za{int(self._user_parameters['THETAP'][0]):03}deg_"
496
- f"azm{int(self._user_parameters['AZM'][0]):03}deg"
497
- f"_{self.site}_{self.layout_name}{file_label}.zst"
564
+ return (
565
+ f"runXXXXXX_{base_name}_{self.array_model.site}_"
566
+ f"{self.array_model.layout_name}{file_label}.zst"
498
567
  )
499
- return file_name
500
568
  if file_type == "multipipe":
501
- return f"multi_cta-{self.site}-{self.layout_name}.cfg"
569
+ return f"multi_cta-{self.array_model.site}-{self.array_model.layout_name}.cfg"
502
570
 
503
571
  raise ValueError(f"The requested file type ({file_type}) is unknown")
504
572
 
505
- def _set_output_file_and_directory(self, sub_dir="corsika"):
506
- config_file_name = self.get_file_name(file_type="config")
573
+ def set_output_file_and_directory(self, use_multipipe=False):
574
+ """
575
+ Set output file names and directories.
576
+
577
+ Parameters
578
+ ----------
579
+ use_multipipe: bool
580
+ Whether to set the CORSIKA Inputs file to pipe
581
+ the output directly to sim_telarray. Defines directory names.
582
+
583
+ Returns
584
+ -------
585
+ str
586
+ Output file name.
587
+ """
588
+ sub_dir = "corsika_simtel" if use_multipipe else "corsika"
589
+ config_file_name = self.get_corsika_config_file_name(file_type="config")
507
590
  file_directory = self.io_handler.get_output_directory(label=self.label, sub_dir=sub_dir)
508
- self._logger.info(f"Creating directory {file_directory}, if needed.")
591
+ self._logger.debug(f"Creating directory {file_directory}")
509
592
  file_directory.mkdir(parents=True, exist_ok=True)
510
593
  self.config_file_path = file_directory.joinpath(config_file_name)
511
594
 
512
- self._output_generic_file_name = self.get_file_name(file_type="output_generic")
595
+ return self.get_corsika_config_file_name(file_type="output_generic")
513
596
 
514
- def _write_seeds(self, file):
597
+ def _write_seeds(self, file, use_test_seeds=False):
515
598
  """
516
599
  Generate and write seeds in the CORSIKA input file.
517
600
 
@@ -520,22 +603,79 @@ class CorsikaConfig:
520
603
  file: stream
521
604
  File where the telescope positions will be written.
522
605
  """
523
- random_seed = self._user_parameters["PRMPAR"][0] + self._user_parameters["RUNNR"][0]
606
+ random_seed = self.get_config_parameter("PRMPAR") + self.run_number
524
607
  rng = np.random.default_rng(random_seed)
525
- corsika_seeds = [int(rng.uniform(0, 1e7)) for i in range(4)]
526
-
608
+ corsika_seeds = [534, 220, 1104, 382]
609
+ if not use_test_seeds:
610
+ corsika_seeds = [int(rng.uniform(0, 1e7)) for _ in range(4)]
527
611
  for s in corsika_seeds:
528
612
  file.write(f"SEED {s} 0 0\n")
529
613
 
530
- def get_input_file(self, use_multipipe=False):
614
+ def get_corsika_telescope_list(self):
531
615
  """
532
- Get the full path of the CORSIKA input file.
616
+ List of telescope positions in the format required for the CORSIKA input file.
533
617
 
534
618
  Returns
535
619
  -------
536
- Path:
537
- Full path of the CORSIKA input file.
620
+ str
621
+ Piece of text to be added to the CORSIKA input file.
538
622
  """
539
- if not self._is_file_updated:
540
- self.export_input_file(use_multipipe)
541
- return self.config_file_path
623
+ corsika_input_list = ""
624
+ for telescope_name, telescope in self.array_model.telescope_model.items():
625
+ positions = telescope.get_parameter_value_with_unit("array_element_position_ground")
626
+ corsika_input_list += "TELESCOPE"
627
+ for pos in positions:
628
+ corsika_input_list += f"\t {pos.to('cm').value:.3f}"
629
+ sphere_radius = telescope.get_parameter_value_with_unit("telescope_sphere_radius").to(
630
+ "cm"
631
+ )
632
+ corsika_input_list += f"\t {sphere_radius:.3f}"
633
+ corsika_input_list += f"\t # {telescope_name}\n"
634
+
635
+ return corsika_input_list
636
+
637
+ @property
638
+ def run_number(self):
639
+ """Set run number."""
640
+ return self._run_number
641
+
642
+ @run_number.setter
643
+ def run_number(self, run_number):
644
+ """
645
+ Set run number and validate it.
646
+
647
+ Parameters
648
+ ----------
649
+ run_number: int
650
+ Run number.
651
+ """
652
+ self._run_number = self.validate_run_number(run_number)
653
+
654
+ def validate_run_number(self, run_number):
655
+ """
656
+ Validate run number and return it.
657
+
658
+ Return run number from configuration if None.
659
+
660
+ Parameters
661
+ ----------
662
+ run_number: int
663
+ Run number.
664
+
665
+ Returns
666
+ -------
667
+ int
668
+ Run number.
669
+
670
+ Raises
671
+ ------
672
+ ValueError
673
+ If run_number is not a valid value (e.g., < 1).
674
+ """
675
+ if run_number is None:
676
+ return self.run_number
677
+ if not float(run_number).is_integer() or run_number < 1 or run_number > 999999:
678
+ msg = f"Invalid type of run number ({run_number}) - it must be an uint < 1000000."
679
+ self._logger.error(msg)
680
+ raise ValueError(msg)
681
+ return run_number