gammasimtools 0.21.0__py3-none-any.whl → 0.23.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. {gammasimtools-0.21.0.dist-info → gammasimtools-0.23.0.dist-info}/METADATA +3 -3
  2. gammasimtools-0.23.0.dist-info/RECORD +414 -0
  3. {gammasimtools-0.21.0.dist-info → gammasimtools-0.23.0.dist-info}/entry_points.txt +2 -1
  4. simtools/_version.py +2 -2
  5. simtools/application_control.py +118 -0
  6. simtools/applications/calculate_incident_angles.py +17 -25
  7. simtools/applications/convert_all_model_parameters_from_simtel.py +29 -45
  8. simtools/applications/convert_geo_coordinates_of_array_elements.py +26 -45
  9. simtools/applications/convert_model_parameter_from_simtel.py +21 -42
  10. simtools/applications/db_add_file_to_db.py +12 -13
  11. simtools/applications/db_add_simulation_model_from_repository_to_db.py +20 -33
  12. simtools/applications/db_add_value_from_json_to_db.py +28 -23
  13. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +19 -34
  14. simtools/applications/db_generate_compound_indexes.py +12 -27
  15. simtools/applications/db_get_array_layouts_from_db.py +19 -39
  16. simtools/applications/db_get_file_from_db.py +15 -17
  17. simtools/applications/db_get_parameter_from_db.py +33 -35
  18. simtools/applications/db_inspect_databases.py +10 -11
  19. simtools/applications/db_upload_model_repository.py +104 -0
  20. simtools/applications/derive_ctao_array_layouts.py +16 -21
  21. simtools/applications/derive_mirror_rnda.py +9 -14
  22. simtools/applications/derive_photon_electron_spectrum.py +7 -10
  23. simtools/applications/derive_psf_parameters.py +24 -21
  24. simtools/applications/derive_trigger_rates.py +6 -9
  25. simtools/applications/docs_produce_array_element_report.py +22 -23
  26. simtools/applications/docs_produce_calibration_reports.py +26 -24
  27. simtools/applications/docs_produce_model_parameter_reports.py +15 -22
  28. simtools/applications/docs_produce_simulation_configuration_report.py +21 -22
  29. simtools/applications/generate_array_config.py +14 -33
  30. simtools/applications/generate_corsika_histograms.py +22 -43
  31. simtools/applications/generate_default_metadata.py +15 -36
  32. simtools/applications/generate_regular_arrays.py +11 -15
  33. simtools/applications/generate_simtel_event_data.py +23 -33
  34. simtools/applications/maintain_simulation_model_add_production.py +17 -48
  35. simtools/applications/maintain_simulation_model_compare_productions.py +10 -12
  36. simtools/applications/maintain_simulation_model_verify_production_tables.py +8 -11
  37. simtools/applications/merge_tables.py +15 -24
  38. simtools/applications/plot_array_layout.py +77 -55
  39. simtools/applications/plot_simtel_events.py +11 -13
  40. simtools/applications/plot_tabular_data.py +17 -38
  41. simtools/applications/plot_tabular_data_for_model_parameter.py +16 -23
  42. simtools/applications/print_version.py +14 -42
  43. simtools/applications/production_derive_corsika_limits.py +5 -9
  44. simtools/applications/production_derive_statistics.py +12 -26
  45. simtools/applications/production_generate_grid.py +20 -48
  46. simtools/applications/production_merge_corsika_limits.py +17 -21
  47. simtools/applications/run_application.py +12 -32
  48. simtools/applications/simulate_flasher.py +79 -81
  49. simtools/applications/simulate_illuminator.py +56 -197
  50. simtools/applications/{simulate_calibration_events.py → simulate_pedestals.py} +22 -68
  51. simtools/applications/simulate_prod.py +21 -33
  52. simtools/applications/simulate_prod_htcondor_generator.py +11 -25
  53. simtools/applications/submit_array_layouts.py +15 -18
  54. simtools/applications/submit_data_from_external.py +18 -34
  55. simtools/applications/submit_model_parameter_from_external.py +27 -41
  56. simtools/applications/validate_camera_efficiency.py +23 -22
  57. simtools/applications/validate_camera_fov.py +21 -27
  58. simtools/applications/validate_cumulative_psf.py +28 -37
  59. simtools/applications/validate_file_using_schema.py +35 -45
  60. simtools/applications/validate_optics.py +27 -33
  61. simtools/camera/camera_efficiency.py +8 -13
  62. simtools/configuration/commandline_parser.py +33 -11
  63. simtools/configuration/configurator.py +0 -7
  64. simtools/corsika/corsika_config.py +9 -16
  65. simtools/corsika/corsika_histograms.py +1 -1
  66. simtools/data_model/data_reader.py +0 -2
  67. simtools/data_model/metadata_collector.py +0 -2
  68. simtools/data_model/model_data_writer.py +87 -27
  69. simtools/data_model/schema.py +61 -2
  70. simtools/data_model/validate_data.py +1 -3
  71. simtools/db/db_handler.py +58 -39
  72. simtools/db/db_model_upload.py +210 -5
  73. simtools/io/hdf5_handler.py +0 -5
  74. simtools/io/io_handler.py +31 -83
  75. simtools/io/legacy_data_handler.py +0 -5
  76. simtools/job_execution/job_manager.py +43 -1
  77. simtools/layout/array_layout.py +0 -2
  78. simtools/layout/array_layout_utils.py +1 -5
  79. simtools/layout/telescope_position.py +0 -2
  80. simtools/model/array_model.py +95 -46
  81. simtools/model/calibration_model.py +0 -2
  82. simtools/model/camera.py +0 -2
  83. simtools/model/mirrors.py +0 -2
  84. simtools/model/model_parameter.py +50 -16
  85. simtools/model/model_repository.py +139 -106
  86. simtools/model/model_utils.py +21 -11
  87. simtools/model/site_model.py +0 -2
  88. simtools/model/telescope_model.py +20 -2
  89. simtools/production_configuration/calculate_statistical_uncertainties_grid_point.py +0 -2
  90. simtools/production_configuration/derive_corsika_limits.py +1 -1
  91. simtools/production_configuration/derive_production_statistics.py +0 -2
  92. simtools/production_configuration/interpolation_handler.py +0 -2
  93. simtools/ray_tracing/incident_angles.py +7 -7
  94. simtools/ray_tracing/mirror_panel_psf.py +1 -1
  95. simtools/ray_tracing/psf_analysis.py +0 -2
  96. simtools/ray_tracing/psf_parameter_optimisation.py +180 -73
  97. simtools/ray_tracing/ray_tracing.py +1 -5
  98. simtools/reporting/docs_auto_report_generator.py +108 -0
  99. simtools/reporting/docs_read_parameters.py +168 -104
  100. simtools/resources/array_elements.yml +26 -0
  101. simtools/runners/corsika_runner.py +0 -2
  102. simtools/runners/corsika_simtel_runner.py +11 -19
  103. simtools/runners/runner_services.py +5 -6
  104. simtools/runners/simtel_runner.py +0 -2
  105. simtools/runners/simtools_runner.py +0 -2
  106. simtools/schemas/application_workflow.metaschema.yml +1 -1
  107. simtools/schemas/common_definitions.schema.yml +39 -0
  108. simtools/schemas/model_parameter.metaschema.yml +19 -13
  109. simtools/schemas/model_parameter_and_data_schema.metaschema.yml +6 -12
  110. simtools/schemas/model_parameters/adjust_gain.schema.yml +0 -5
  111. simtools/schemas/model_parameters/altitude.schema.yml +0 -5
  112. simtools/schemas/model_parameters/array_coordinates.schema.yml +0 -5
  113. simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +0 -5
  114. simtools/schemas/model_parameters/array_element_position_ground.schema.yml +0 -7
  115. simtools/schemas/model_parameters/array_element_position_utm.schema.yml +0 -7
  116. simtools/schemas/model_parameters/array_layouts.schema.yml +0 -5
  117. simtools/schemas/model_parameters/array_triggers.schema.yml +0 -5
  118. simtools/schemas/model_parameters/array_window.schema.yml +0 -7
  119. simtools/schemas/model_parameters/asum_clipping.schema.yml +0 -3
  120. simtools/schemas/model_parameters/asum_offset.schema.yml +0 -7
  121. simtools/schemas/model_parameters/asum_shaping.schema.yml +0 -7
  122. simtools/schemas/model_parameters/asum_threshold.schema.yml +0 -7
  123. simtools/schemas/model_parameters/atmospheric_profile.schema.yml +0 -5
  124. simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +0 -5
  125. simtools/schemas/model_parameters/axes_offsets.schema.yml +0 -7
  126. simtools/schemas/model_parameters/calibration_devices.schema.yml +30 -0
  127. simtools/schemas/model_parameters/camera_body_diameter.schema.yml +0 -7
  128. simtools/schemas/model_parameters/camera_body_shape.schema.yml +0 -7
  129. simtools/schemas/model_parameters/camera_config_file.schema.yml +0 -7
  130. simtools/schemas/model_parameters/camera_config_rotate.schema.yml +0 -7
  131. simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +0 -7
  132. simtools/schemas/model_parameters/camera_degraded_map.schema.yml +0 -7
  133. simtools/schemas/model_parameters/camera_depth.schema.yml +0 -7
  134. simtools/schemas/model_parameters/camera_filter.schema.yml +0 -7
  135. simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +0 -3
  136. simtools/schemas/model_parameters/camera_pixels.schema.yml +0 -7
  137. simtools/schemas/model_parameters/camera_transmission.schema.yml +0 -7
  138. simtools/schemas/model_parameters/channels_per_chip.schema.yml +0 -7
  139. simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +0 -7
  140. simtools/schemas/model_parameters/corsika_observation_level.schema.yml +0 -5
  141. simtools/schemas/model_parameters/dark_events.schema.yml +4 -3
  142. simtools/schemas/model_parameters/default_trigger.schema.yml +0 -7
  143. simtools/schemas/model_parameters/design_model.schema.yml +0 -7
  144. simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +0 -7
  145. simtools/schemas/model_parameters/disc_bins.schema.yml +0 -7
  146. simtools/schemas/model_parameters/disc_start.schema.yml +0 -7
  147. simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +0 -7
  148. simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +0 -7
  149. simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +0 -7
  150. simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +0 -7
  151. simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +0 -7
  152. simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +0 -7
  153. simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +0 -7
  154. simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +0 -7
  155. simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +0 -7
  156. simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +0 -7
  157. simtools/schemas/model_parameters/discriminator_threshold.schema.yml +0 -7
  158. simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +1 -9
  159. simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +0 -7
  160. simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +0 -7
  161. simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +0 -7
  162. simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +0 -7
  163. simtools/schemas/model_parameters/dish_shape_length.schema.yml +0 -5
  164. simtools/schemas/model_parameters/dsum_clipping.schema.yml +1 -5
  165. simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +0 -3
  166. simtools/schemas/model_parameters/dsum_offset.schema.yml +0 -3
  167. simtools/schemas/model_parameters/dsum_pedsub.schema.yml +0 -3
  168. simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +0 -3
  169. simtools/schemas/model_parameters/dsum_prescale.schema.yml +0 -3
  170. simtools/schemas/model_parameters/dsum_presum_max.schema.yml +0 -3
  171. simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +0 -3
  172. simtools/schemas/model_parameters/dsum_shaping.schema.yml +0 -3
  173. simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +0 -3
  174. simtools/schemas/model_parameters/dsum_threshold.schema.yml +2 -12
  175. simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +0 -3
  176. simtools/schemas/model_parameters/effective_focal_length.schema.yml +0 -7
  177. simtools/schemas/model_parameters/epsg_code.schema.yml +0 -5
  178. simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +0 -7
  179. simtools/schemas/model_parameters/fadc_amplitude.schema.yml +2 -9
  180. simtools/schemas/model_parameters/fadc_bins.schema.yml +0 -7
  181. simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +0 -7
  182. simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +0 -2
  183. simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +0 -7
  184. simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +0 -7
  185. simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +2 -9
  186. simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +0 -7
  187. simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +0 -2
  188. simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +0 -7
  189. simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +0 -7
  190. simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +0 -7
  191. simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +0 -2
  192. simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +0 -7
  193. simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +0 -7
  194. simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +0 -7
  195. simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +0 -7
  196. simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +0 -7
  197. simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +0 -7
  198. simtools/schemas/model_parameters/fadc_long_event_threshold.schema.yml +0 -3
  199. simtools/schemas/model_parameters/fadc_long_sum_bins.schema.yml +0 -3
  200. simtools/schemas/model_parameters/fadc_long_sum_offset.schema.yml +0 -3
  201. simtools/schemas/model_parameters/fadc_max_signal.schema.yml +0 -7
  202. simtools/schemas/model_parameters/fadc_max_sum.schema.yml +0 -2
  203. simtools/schemas/model_parameters/fadc_mhz.schema.yml +0 -7
  204. simtools/schemas/model_parameters/fadc_noise.schema.yml +0 -7
  205. simtools/schemas/model_parameters/fadc_pedestal.schema.yml +0 -7
  206. simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +0 -7
  207. simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +0 -7
  208. simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +0 -7
  209. simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +0 -7
  210. simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +0 -7
  211. simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +0 -7
  212. simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +0 -7
  213. simtools/schemas/model_parameters/fake_mirror_list.schema.yml +0 -3
  214. simtools/schemas/model_parameters/flasher_angular_distribution.schema.yml +32 -0
  215. simtools/schemas/model_parameters/flasher_angular_distribution_width.schema.yml +32 -0
  216. simtools/schemas/model_parameters/flasher_bunch_size.schema.yml +28 -0
  217. simtools/schemas/model_parameters/flasher_external_trigger.schema.yml +32 -0
  218. simtools/schemas/model_parameters/flasher_photons.schema.yml +34 -0
  219. simtools/schemas/model_parameters/flasher_position.schema.yml +43 -0
  220. simtools/schemas/model_parameters/flasher_pulse_exp_decay.schema.yml +29 -0
  221. simtools/schemas/model_parameters/flasher_pulse_offset.schema.yml +35 -0
  222. simtools/schemas/model_parameters/flasher_pulse_shape.schema.yml +30 -0
  223. simtools/schemas/model_parameters/flasher_pulse_width.schema.yml +32 -0
  224. simtools/schemas/model_parameters/flasher_type.schema.yml +28 -0
  225. simtools/schemas/model_parameters/flasher_var_photons.schema.yml +31 -0
  226. simtools/schemas/model_parameters/flasher_wavelength.schema.yml +33 -0
  227. simtools/schemas/model_parameters/flatfielding.schema.yml +0 -7
  228. simtools/schemas/model_parameters/focal_length.schema.yml +0 -7
  229. simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +0 -3
  230. simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +0 -3
  231. simtools/schemas/model_parameters/focus_offset.schema.yml +0 -7
  232. simtools/schemas/model_parameters/gain_variation.schema.yml +0 -7
  233. simtools/schemas/model_parameters/geomag_horizontal.schema.yml +2 -7
  234. simtools/schemas/model_parameters/geomag_rotation.schema.yml +2 -7
  235. simtools/schemas/model_parameters/geomag_vertical.schema.yml +2 -7
  236. simtools/schemas/model_parameters/hg_lg_variation.schema.yml +0 -5
  237. simtools/schemas/model_parameters/iobuf_maximum.schema.yml +0 -7
  238. simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +0 -7
  239. simtools/schemas/model_parameters/laser_events.schema.yml +4 -3
  240. simtools/schemas/model_parameters/laser_external_trigger.schema.yml +4 -3
  241. simtools/schemas/model_parameters/laser_photons.schema.yml +4 -3
  242. simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +4 -3
  243. simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +4 -3
  244. simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +4 -3
  245. simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +4 -3
  246. simtools/schemas/model_parameters/laser_var_photons.schema.yml +4 -3
  247. simtools/schemas/model_parameters/laser_wavelength.schema.yml +4 -3
  248. simtools/schemas/model_parameters/led_events.schema.yml +4 -3
  249. simtools/schemas/model_parameters/led_photons.schema.yml +4 -3
  250. simtools/schemas/model_parameters/led_pulse_offset.schema.yml +4 -3
  251. simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +4 -3
  252. simtools/schemas/model_parameters/led_var_photons.schema.yml +4 -3
  253. simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +0 -7
  254. simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +0 -7
  255. simtools/schemas/model_parameters/min_photoelectrons.schema.yml +0 -7
  256. simtools/schemas/model_parameters/min_photons.schema.yml +0 -7
  257. simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +0 -5
  258. simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +0 -7
  259. simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +0 -7
  260. simtools/schemas/model_parameters/mirror_class.schema.yml +2 -9
  261. simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +0 -7
  262. simtools/schemas/model_parameters/mirror_focal_length.schema.yml +0 -5
  263. simtools/schemas/model_parameters/mirror_list.schema.yml +0 -7
  264. simtools/schemas/model_parameters/mirror_offset.schema.yml +0 -7
  265. simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +0 -7
  266. simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +0 -7
  267. simtools/schemas/model_parameters/multiplicity_offset.schema.yml +0 -7
  268. simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +0 -7
  269. simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +0 -7
  270. simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +0 -3
  271. simtools/schemas/model_parameters/nsb_offaxis.schema.yml +0 -7
  272. simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +0 -7
  273. simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +0 -5
  274. simtools/schemas/model_parameters/nsb_reference_value.schema.yml +0 -5
  275. simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +0 -5
  276. simtools/schemas/model_parameters/nsb_sky_map.schema.yml +0 -5
  277. simtools/schemas/model_parameters/nsb_spectrum.schema.yml +0 -5
  278. simtools/schemas/model_parameters/num_gains.schema.yml +0 -7
  279. simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +0 -7
  280. simtools/schemas/model_parameters/optics_properties.schema.yml +0 -7
  281. simtools/schemas/model_parameters/parabolic_dish.schema.yml +0 -3
  282. simtools/schemas/model_parameters/pedestal_events.schema.yml +4 -7
  283. simtools/schemas/model_parameters/photon_delay.schema.yml +0 -7
  284. simtools/schemas/model_parameters/photons_per_run.schema.yml +4 -4
  285. simtools/schemas/model_parameters/pixel_cells.schema.yml +0 -3
  286. simtools/schemas/model_parameters/pixels_parallel.schema.yml +0 -3
  287. simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +0 -7
  288. simtools/schemas/model_parameters/pm_average_gain.schema.yml +0 -5
  289. simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +0 -5
  290. simtools/schemas/model_parameters/pm_gain_index.schema.yml +0 -5
  291. simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +0 -7
  292. simtools/schemas/model_parameters/pm_transit_time.schema.yml +4 -9
  293. simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +0 -5
  294. simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +0 -7
  295. simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +0 -3
  296. simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +0 -3
  297. simtools/schemas/model_parameters/primary_mirror_incidence_angle.schema.yml +0 -3
  298. simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +0 -3
  299. simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +0 -3
  300. simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +0 -3
  301. simtools/schemas/model_parameters/qe_variation.schema.yml +0 -7
  302. simtools/schemas/model_parameters/quantum_efficiency.schema.yml +0 -7
  303. simtools/schemas/model_parameters/random_focal_length.schema.yml +2 -7
  304. simtools/schemas/model_parameters/random_generator.schema.yml +0 -7
  305. simtools/schemas/model_parameters/random_mono_probability.schema.yml +0 -7
  306. simtools/schemas/model_parameters/reference_point_altitude.schema.yml +0 -5
  307. simtools/schemas/model_parameters/reference_point_latitude.schema.yml +0 -5
  308. simtools/schemas/model_parameters/reference_point_longitude.schema.yml +0 -5
  309. simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +0 -5
  310. simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +0 -5
  311. simtools/schemas/model_parameters/sampled_output.schema.yml +0 -7
  312. simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +0 -7
  313. simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +0 -3
  314. simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +0 -3
  315. simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +0 -3
  316. simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +0 -3
  317. simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +0 -3
  318. simtools/schemas/model_parameters/secondary_mirror_incidence_angle.schema.yml +0 -3
  319. simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +0 -3
  320. simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +0 -3
  321. simtools/schemas/model_parameters/secondary_mirror_reflectivity.schema.yml +0 -3
  322. simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +0 -3
  323. simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +0 -3
  324. simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +0 -3
  325. simtools/schemas/model_parameters/stars.schema.yml +0 -5
  326. simtools/schemas/model_parameters/store_photoelectrons.schema.yml +0 -7
  327. simtools/schemas/model_parameters/tailcut_scale.schema.yml +0 -7
  328. simtools/schemas/model_parameters/telescope_axis_height.schema.yml +0 -7
  329. simtools/schemas/model_parameters/telescope_random_angle.schema.yml +0 -7
  330. simtools/schemas/model_parameters/telescope_random_error.schema.yml +0 -7
  331. simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +0 -7
  332. simtools/schemas/model_parameters/telescope_transmission.schema.yml +0 -7
  333. simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +0 -7
  334. simtools/schemas/model_parameters/teltrig_min_time.schema.yml +0 -7
  335. simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +0 -7
  336. simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +0 -7
  337. simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +0 -7
  338. simtools/schemas/model_parameters/transit_time_error.schema.yml +0 -7
  339. simtools/schemas/model_parameters/transit_time_jitter.schema.yml +0 -7
  340. simtools/schemas/model_parameters/transit_time_random.schema.yml +29 -0
  341. simtools/schemas/model_parameters/trigger_current_limit.schema.yml +0 -7
  342. simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +0 -7
  343. simtools/schemas/model_parameters/trigger_pixels.schema.yml +0 -7
  344. simtools/schemas/production_tables.schema.yml +8 -8
  345. simtools/schemas/simulation_models_info.schema.yml +78 -0
  346. simtools/simtel/simtel_config_reader.py +0 -2
  347. simtools/simtel/simtel_config_writer.py +118 -26
  348. simtools/simtel/simtel_io_metadata.py +3 -3
  349. simtools/simtel/simulator_array.py +43 -85
  350. simtools/simtel/simulator_camera_efficiency.py +0 -2
  351. simtools/simtel/simulator_light_emission.py +336 -631
  352. simtools/simtel/simulator_ray_tracing.py +2 -4
  353. simtools/simulator.py +45 -19
  354. simtools/testing/assertions.py +2 -2
  355. simtools/testing/configuration.py +21 -6
  356. simtools/testing/sim_telarray_metadata.py +4 -4
  357. simtools/utils/general.py +5 -13
  358. simtools/utils/geometry.py +34 -5
  359. simtools/utils/names.py +1 -13
  360. simtools/version.py +83 -0
  361. simtools/visualization/plot_array_layout.py +129 -23
  362. simtools/visualization/plot_incident_angles.py +0 -2
  363. simtools/visualization/plot_psf.py +163 -61
  364. simtools/visualization/plot_simtel_events.py +1 -12
  365. simtools/visualization/visualize.py +0 -12
  366. gammasimtools-0.21.0.dist-info/RECORD +0 -396
  367. simtools/model/flasher_model.py +0 -106
  368. {gammasimtools-0.21.0.dist-info → gammasimtools-0.23.0.dist-info}/WHEEL +0 -0
  369. {gammasimtools-0.21.0.dist-info → gammasimtools-0.23.0.dist-info}/licenses/LICENSE +0 -0
  370. {gammasimtools-0.21.0.dist-info → gammasimtools-0.23.0.dist-info}/top_level.txt +0 -0
@@ -175,6 +175,10 @@ class ReportGenerator:
175
175
  f"Markdown report generated for {site} Telescope {telescope}: {self.output_path}"
176
176
  )
177
177
 
178
+ # Also generate calibration device parameter comparison reports when using --all_telescopes
179
+ if self.args.get("all_telescopes"):
180
+ self._generate_calibration_device_parameter_reports()
181
+
178
182
  def _generate_observatory_report_combinations(self) -> Generator[tuple[str, str], None, None]:
179
183
  """Generate combinations of sites and model versions for observatory reports.
180
184
 
@@ -215,3 +219,107 @@ class ReportGenerator:
215
219
  """Generate all observatory reports based on which --all_* flags are passed."""
216
220
  for params in self._generate_observatory_report_combinations():
217
221
  self._generate_single_observatory_report(*params)
222
+
223
+ def auto_generate_simulation_configuration_reports(self):
224
+ """Generate simulation configuration reports for one or all model versions.
225
+
226
+ If --all_model_versions is set, produce reports for every model version in
227
+ the DB; otherwise produce reports only for the configured model_version.
228
+ """
229
+ model_versions = (
230
+ self.db.get_model_versions()
231
+ if self.args.get("all_model_versions")
232
+ else [self.args["model_version"]]
233
+ )
234
+
235
+ for version in model_versions:
236
+ # update args and create a per-version output directory
237
+ self.args.update({"model_version": version})
238
+ output_path = Path(self.output_path) / str(version)
239
+
240
+ ReadParameters(
241
+ self.db_config, self.args, output_path
242
+ ).produce_simulation_configuration_report()
243
+
244
+ logger.info(f"Configuration reports for (v{version}) produced: {output_path}")
245
+
246
+ def auto_generate_calibration_reports(self):
247
+ """Generate calibration reports for one or all model versions.
248
+
249
+ Mirrors the pattern used by other auto_generate_* methods: if
250
+ --all_model_versions is set, produce reports for every model version in
251
+ the DB; otherwise produce reports only for the configured model_version.
252
+ """
253
+ model_versions = (
254
+ self.db.get_model_versions()
255
+ if self.args.get("all_model_versions")
256
+ else [self.args["model_version"]]
257
+ )
258
+
259
+ for version in model_versions:
260
+ # update args and create a per-version output directory
261
+ self.args.update({"model_version": version})
262
+ output_path = Path(self.output_path) / str(version)
263
+
264
+ try:
265
+ ReadParameters(self.db_config, self.args, output_path).produce_calibration_reports()
266
+ logger.info(f"Calibration reports for (v{version}) produced: {output_path}")
267
+ except ValueError as err:
268
+ # Some model versions do not have calibration_devices in the DB;
269
+ msg = str(err)
270
+ if "calibration_devices" in msg and "zero results" in msg:
271
+ logger.info(
272
+ f"Skipping model version {version}: no calibration devices defined ({msg})"
273
+ )
274
+ continue
275
+ # re-raise unexpected ValueErrors
276
+ raise
277
+
278
+ def _generate_calibration_device_parameter_reports(self):
279
+ """Generate parameter comparison reports for calibration devices for all model versions."""
280
+ # Get all model versions since no specific version is provided when using --all_telescopes
281
+ model_versions = self.db.get_model_versions()
282
+
283
+ for version in model_versions:
284
+ self._process_calibration_devices_for_version(version)
285
+
286
+ def _process_calibration_devices_for_version(self, version):
287
+ """Process calibration devices for a specific model version."""
288
+ try:
289
+ # Get all calibration devices for this version
290
+ calibration_array_elements = self.db.get_array_elements(
291
+ version, collection="calibration_devices"
292
+ )
293
+ array_elements = calibration_array_elements.copy()
294
+
295
+ # Add design models
296
+ for element in calibration_array_elements:
297
+ design_model = self.db.get_design_model(version, element, "calibration_devices")
298
+ if design_model and design_model not in array_elements:
299
+ array_elements.append(design_model)
300
+
301
+ if array_elements:
302
+ # Create a copy of args with the current version for this iteration
303
+ version_args = self.args.copy()
304
+ version_args["model_version"] = version
305
+
306
+ # Generate parameter comparison reports for calibration devices
307
+ ReadParameters(
308
+ self.db_config, version_args, self.output_path
309
+ ).generate_model_parameter_reports_for_devices(array_elements)
310
+
311
+ logger.info(
312
+ "Calibration device parameter reports generated for"
313
+ f" v{version}: {self.output_path}"
314
+ )
315
+
316
+ except ValueError as err:
317
+ # Some model versions may not have calibration_devices
318
+ msg = str(err)
319
+ if "calibration_devices" in msg and "zero results" in msg:
320
+ logger.info(
321
+ f"Skipping model version {version}: no calibration devices defined ({msg})"
322
+ )
323
+ return
324
+ # re-raise unexpected ValueErrors
325
+ raise
@@ -16,9 +16,11 @@ from simtools.db import db_handler
16
16
  from simtools.io import ascii_handler, io_handler
17
17
  from simtools.model.telescope_model import TelescopeModel
18
18
  from simtools.utils import names
19
+ from simtools.version import sort_versions
19
20
  from simtools.visualization import plot_pixels, plot_tables
20
21
 
21
22
  logger = logging.getLogger()
23
+ MARKDOWN_LINK_RE = re.compile(r"\[([^\]]+)\]\(([^)]+)\)")
22
24
 
23
25
 
24
26
  class ReadParameters:
@@ -64,7 +66,7 @@ class ReadParameters:
64
66
  )
65
67
  self._model_version = model_version
66
68
 
67
- def _generate_plots(self, parameter, parameter_version, input_file, outpath, design_type):
69
+ def _generate_plots(self, parameter, parameter_version, input_file, outpath):
68
70
  """Generate plots based on the parameter type."""
69
71
  plot_names = []
70
72
 
@@ -72,7 +74,9 @@ class ReadParameters:
72
74
  plot_names = self._plot_camera_config(parameter, parameter_version, input_file, outpath)
73
75
  elif parameter_version:
74
76
  plot_names = self._plot_parameter_tables(
75
- parameter, parameter_version, outpath, design_type
77
+ parameter,
78
+ parameter_version,
79
+ outpath,
76
80
  )
77
81
 
78
82
  return plot_names
@@ -111,18 +115,9 @@ class ReadParameters:
111
115
 
112
116
  return plot_names
113
117
 
114
- def _plot_parameter_tables(self, parameter, parameter_version, outpath, design_type):
118
+ def _plot_parameter_tables(self, parameter, parameter_version, outpath):
115
119
  """Generate plots for parameter tables."""
116
- telescope_design = self.db.get_design_model(
117
- self.model_version, self.array_element, collection="telescopes"
118
- )
119
-
120
- if not self.array_element:
121
- tel = None
122
- elif not design_type:
123
- tel = telescope_design
124
- else:
125
- tel = self.array_element
120
+ tel = self._get_telescope_identifier()
126
121
 
127
122
  config_data = plot_tables.generate_plot_configurations(
128
123
  parameter=parameter,
@@ -152,7 +147,20 @@ class ReadParameters:
152
147
 
153
148
  return plot_names
154
149
 
155
- def _convert_to_md(self, parameter, parameter_version, input_file, design_type=False):
150
+ def _get_telescope_identifier(self, model_version=None):
151
+ """Get the appropriate telescope design type for file naming (e.g., LSTN-design)."""
152
+ model_version = model_version or self.model_version
153
+ telescope_design = self.db.get_design_model(
154
+ model_version, self.array_element, collection="telescopes"
155
+ )
156
+
157
+ if not self.array_element:
158
+ return None
159
+ if not names.is_design_type(self.array_element):
160
+ return telescope_design
161
+ return self.array_element
162
+
163
+ def _convert_to_md(self, parameter, parameter_version, input_file):
156
164
  """Convert a file to a Markdown file, preserving formatting."""
157
165
  input_file = Path(input_file)
158
166
 
@@ -170,9 +178,7 @@ class ReadParameters:
170
178
  outpath = Path(io_handler.IOHandler().get_output_directory().parent / "_images")
171
179
  outpath.mkdir(parents=True, exist_ok=True)
172
180
 
173
- plot_names = self._generate_plots(
174
- parameter, parameter_version, input_file, outpath, design_type
175
- )
181
+ plot_names = self._generate_plots(parameter, parameter_version, input_file, outpath)
176
182
  # Write markdown file using the stored path
177
183
  file_contents = ascii_handler.read_file_encoded_in_utf_or_latin(input_file)
178
184
 
@@ -198,7 +204,7 @@ class ReadParameters:
198
204
  return relative_path
199
205
 
200
206
  def _format_parameter_value(
201
- self, parameter, value_data, unit, file_flag, parameter_version=None, design_type=False
207
+ self, parameter, value_data, unit, file_flag, parameter_version=None
202
208
  ):
203
209
  """Format parameter value based on type."""
204
210
  if file_flag:
@@ -209,9 +215,7 @@ class ReadParameters:
209
215
  "cta-science/simulations/simulation-model/simulation-models/-/blob/main/"
210
216
  f"simulation-models/model_parameters/Files/{value_data})"
211
217
  ).strip()
212
- output_file_name = self._convert_to_md(
213
- parameter, parameter_version, input_file_name, design_type
214
- )
218
+ output_file_name = self._convert_to_md(parameter, parameter_version, input_file_name)
215
219
  return f"[{Path(value_data).name}]({output_file_name})".strip()
216
220
  if isinstance(value_data, (str | int | float)):
217
221
  return f"{value_data} {unit}".strip()
@@ -223,26 +227,6 @@ class ReadParameters:
223
227
  else ", ".join(f"{v} {unit}" for v in value_data)
224
228
  ).strip()
225
229
 
226
- def _wrap_at_underscores(self, text, max_width):
227
- """Wrap text at underscores to fit within a specified width."""
228
- parts = text.split("_")
229
- lines = []
230
- current = []
231
-
232
- for part in parts:
233
- # Predict the new length if we add this part
234
- next_line = "_".join([*current, part])
235
- if len(next_line) <= max_width:
236
- current.append(part)
237
- else:
238
- lines.append("_".join(current))
239
- current = [part]
240
-
241
- if current:
242
- lines.append("_".join(current))
243
-
244
- return " ".join(lines)
245
-
246
230
  def _group_model_versions_by_parameter_version(self, grouped_data):
247
231
  """Group model versions by parameter version and track the parameter values."""
248
232
  result = {}
@@ -265,7 +249,7 @@ class ReadParameters:
265
249
  "value": data["value"],
266
250
  "parameter_version": param_version,
267
251
  "file_flag": data["file_flag"],
268
- "model_version": ", ".join(data["model_versions"]),
252
+ "model_version": ", ".join(sort_versions(data["model_versions"])),
269
253
  }
270
254
  for param_version, data in version_grouped.items()
271
255
  ]
@@ -397,10 +381,9 @@ class ReadParameters:
397
381
  if value_data is None:
398
382
  continue
399
383
 
400
- design_type = names.is_design_type(telescope_model.name)
401
384
  file_flag = parameter_data.get("file", False)
402
385
  value = self._format_parameter_value(
403
- parameter, value_data, unit, file_flag, parameter_version, design_type
386
+ parameter, value_data, unit, file_flag, parameter_version
404
387
  )
405
388
 
406
389
  description = parameter_descriptions.get(parameter).get("description")
@@ -410,7 +393,7 @@ class ReadParameters:
410
393
  inst_class = parameter_descriptions.get(parameter).get("inst_class")
411
394
 
412
395
  matching_instrument = parameter_data["instrument"] == telescope_model.name
413
- if not design_type and matching_instrument:
396
+ if not names.is_design_type(telescope_model.name) and matching_instrument:
414
397
  parameter = f"***{parameter}***"
415
398
  parameter_version = f"***{parameter_version}***"
416
399
  if not self.is_markdown_link(value):
@@ -453,7 +436,6 @@ class ReadParameters:
453
436
  text = short_description if short_description else description
454
437
  wrapped_text = textwrap.fill(str(text), column_widths[3]).split("\n")
455
438
  wrapped_text = " ".join(wrapped_text)
456
- parameter_name = self._wrap_at_underscores(parameter_name, column_widths[0])
457
439
 
458
440
  file.write(
459
441
  f"| {parameter_name:{column_widths[0]}} |"
@@ -628,33 +610,82 @@ class ReadParameters:
628
610
 
629
611
  description = parameter_descriptions.get("description")
630
612
  with output_filename.open("w", encoding="utf-8") as file:
631
- # Write header
632
- file.write(
633
- f"# {parameter}\n\n"
634
- f"**Telescope**: {self.array_element}\n\n"
635
- f"**Description**: {description}\n\n"
636
- "\n"
637
- )
613
+ # Write header and table
614
+ self._write_parameter_header(file, parameter, description)
615
+ self._write_table_rows(file, parameter, comparison_data)
638
616
 
639
- # Write table header
640
- file.write(
641
- "| Parameter Version | Model Version(s) "
642
- "| Value |\n"
643
- "|------------------------|--------------------"
644
- "|----------------------|\n"
645
- )
617
+ # If entries reference files, write the image/plot section
618
+ if comparison_data.get(parameter)[0]["file_flag"]:
619
+ self._write_file_flag_section(file, parameter, comparison_data)
646
620
 
647
- # Write table rows
648
- for item in comparison_data.get(parameter):
649
- file.write(
650
- f"| {item['parameter_version']} |"
651
- f" {item['model_version']} |"
652
- f"{item['value']} |\n"
653
- )
621
+ def _write_parameter_header(self, file, parameter, description):
622
+ """Write the markdown header for a parameter file."""
623
+ file.write(
624
+ f"# {parameter}\n\n"
625
+ f"**Telescope**: {self.array_element}\n\n"
626
+ f"**Description**: {description}\n\n"
627
+ "\n"
628
+ )
654
629
 
655
- file.write("\n")
656
- if comparison_data.get(parameter)[0]["file_flag"]:
657
- file.write(f"![Parameter plot.](/_images/{self.array_element}_{parameter}.png)")
630
+ def _write_table_rows(self, file, parameter, comparison_data):
631
+ """Write the comparison table header and rows for a parameter."""
632
+ # Write table header
633
+ file.write(
634
+ "| Parameter Version | Model Version(s) "
635
+ "| Value |\n"
636
+ "|------------------------|--------------------"
637
+ "|----------------------|\n"
638
+ )
639
+
640
+ # Write table rows
641
+ for item in comparison_data.get(parameter):
642
+ file.write(
643
+ f"| {item['parameter_version']} | {item['model_version']} | {item['value']} |\n"
644
+ )
645
+
646
+ file.write("\n")
647
+
648
+ def _write_file_flag_section(self, file, parameter, comparison_data):
649
+ """Write image/plot references when parameter entries include files."""
650
+ outpath = Path(io_handler.IOHandler().get_output_directory().parent / "_images")
651
+ latest_parameter_version = max(
652
+ comparison_data.get(parameter),
653
+ key=lambda x: tuple(map(int, x["parameter_version"].split("."))),
654
+ )["parameter_version"]
655
+
656
+ all_model_versions = []
657
+ for item in comparison_data.get(parameter):
658
+ model_versions = item["model_version"].split(", ")
659
+ all_model_versions.extend(model_versions)
660
+
661
+ latest_model_version = max(all_model_versions, key=lambda x: tuple(map(int, x.split("."))))
662
+ tel = self._get_telescope_identifier(latest_model_version)
663
+
664
+ file.write("The latest parameter version is plotted below.\n\n")
665
+
666
+ if parameter != "camera_config_file":
667
+ plot_name = f"{parameter}_{latest_parameter_version}_{self.site}_{tel}"
668
+ image_path = outpath / f"{plot_name}.png"
669
+ file.write(f"![Parameter plot.]({image_path.as_posix()})")
670
+ return
671
+
672
+ # camera_config_file: find latest value and convert markdown link to png filename
673
+ latest_value = None
674
+ for item in comparison_data.get(parameter):
675
+ if latest_model_version in item["model_version"].split(", "):
676
+ latest_value = item["value"]
677
+ break
678
+
679
+ if latest_value is None:
680
+ return
681
+
682
+ match = MARKDOWN_LINK_RE.search(latest_value)
683
+ if not match:
684
+ return
685
+
686
+ filename_png = Path(match.group(1)).with_suffix(".png").name
687
+ image_path = outpath / filename_png
688
+ file.write(f"![Camera configuration plot.]({image_path.as_posix()})")
658
689
 
659
690
  def _write_array_layouts_section(self, file, layouts):
660
691
  """Write the array layouts section of the report."""
@@ -840,20 +871,14 @@ class ReadParameters:
840
871
 
841
872
  def produce_calibration_reports(self):
842
873
  """Write calibration reports."""
843
- calibration_array_elements = self.db.get_array_elements(
844
- self.model_version, collection="calibration_devices"
845
- )
846
- array_elements = calibration_array_elements.copy()
847
- for element in calibration_array_elements:
848
- design_model = self.db.get_design_model(
849
- self.model_version, element, "calibration_devices"
850
- )
851
- if design_model and design_model not in array_elements:
852
- array_elements.append(design_model)
874
+ array_elements = self._collect_calibration_array_elements()
853
875
 
854
876
  for calibration_device in array_elements:
877
+ device_sites = names.get_site_from_array_element_name(calibration_device)
878
+ site = device_sites[0] if isinstance(device_sites, list) else device_sites
879
+
855
880
  all_parameter_data = self.db.get_model_parameters(
856
- site=names.get_site_from_array_element_name(calibration_device),
881
+ site=site,
857
882
  array_element_name=calibration_device,
858
883
  collection="calibration_devices",
859
884
  model_version=self.model_version,
@@ -867,32 +892,71 @@ class ReadParameters:
867
892
  self.model_version, calibration_device, "calibration_devices"
868
893
  )
869
894
 
870
- with output_filename.open("w", encoding="utf-8") as file:
871
- file.write(f"# {calibration_device}\n")
872
- file.write("\n\n")
895
+ self._write_single_calibration_report(
896
+ output_filename, calibration_device, data, design_model
897
+ )
873
898
 
874
- if not names.is_design_type(calibration_device):
875
- file.write(
876
- "The design model can be found here: "
877
- f"[{design_model}]"
878
- f"({design_model}.md).\n\n"
879
- )
880
- file.write(
881
- "Parameters shown in ***bold and italics*** are specific"
882
- " to each array element.\n"
883
- "Parameters without emphasis are inherited from the design model.\n"
884
- )
885
- file.write("\n\n")
899
+ def _collect_calibration_array_elements(self):
900
+ """Return a list of calibration devices including their design models."""
901
+ calibration_array_elements = self.db.get_array_elements(
902
+ self.model_version, collection="calibration_devices"
903
+ )
904
+ array_elements = calibration_array_elements.copy()
905
+ for element in calibration_array_elements:
906
+ design_model = self.db.get_design_model(
907
+ self.model_version, element, "calibration_devices"
908
+ )
909
+ if design_model and design_model not in array_elements:
910
+ array_elements.append(design_model)
911
+ return array_elements
886
912
 
887
- for class_name, group in groupby(data, key=lambda x: x[0]):
888
- group = sorted(group, key=lambda x: x[1])
889
- file.write(f"## {class_name}\n\n")
890
- self._write_to_file(group, file)
913
+ def _write_single_calibration_report(
914
+ self, output_filename, calibration_device, data, design_model
915
+ ):
916
+ """Write a single calibration device markdown report file."""
917
+ with output_filename.open("w", encoding="utf-8") as file:
918
+ file.write(f"# {calibration_device}\n")
919
+ file.write("\n\n")
891
920
 
892
- new_output_path = Path(self.output_path).parent.parent / "parameters"
893
- new_output_path.mkdir(parents=True, exist_ok=True)
894
- self.output_path = new_output_path
921
+ if not names.is_design_type(calibration_device):
922
+ file.write(
923
+ f"The design model can be found here: [{design_model}]({design_model}.md).\n\n"
924
+ )
925
+ file.write(
926
+ "Parameters shown in ***bold and italics*** are specific"
927
+ " to each array element.\n"
928
+ "Parameters without emphasis are inherited from the design model.\n"
929
+ )
930
+ file.write("\n\n")
931
+
932
+ for class_name, group in groupby(data, key=lambda x: x[0]):
933
+ group = sorted(group, key=lambda x: x[1])
934
+ file.write(f"## {class_name}\n\n")
935
+ # Transform parameter display names for human-readable report
936
+ display_group = []
937
+ for row in group:
938
+ param = row[1]
939
+ # Preserve markdown emphasis (***param***) if present
940
+ if isinstance(param, str) and param.startswith("***") and param.endswith("***"):
941
+ inner = param.strip("*")
942
+ new_inner = inner.replace("_", " ")
943
+ new_param = f"***{new_inner}***"
944
+ elif isinstance(param, str):
945
+ new_param = param.replace("_", " ")
946
+ else:
947
+ new_param = param
948
+
949
+ new_row = [row[0], new_param, row[2], row[3], row[4], row[5]]
950
+ display_group.append(new_row)
951
+
952
+ self._write_to_file(display_group, file)
953
+
954
+ def generate_model_parameter_reports_for_devices(self, array_elements):
955
+ """Create model-parameter comparison reports for calibration devices."""
895
956
  for calibration_device in array_elements:
896
- self.site = names.get_site_from_array_element_name(calibration_device)
957
+ device_sites = names.get_site_from_array_element_name(calibration_device)
958
+ # parameters are site independent so just take the first site to read from db
959
+ site = device_sites[0] if isinstance(device_sites, list) else device_sites
960
+ self.site = site
897
961
  self.array_element = calibration_device
898
962
  self.produce_model_parameter_reports(collection="calibration_devices")
@@ -131,6 +131,32 @@ data:
131
131
  observatory: "CTAO"
132
132
  site: "South"
133
133
  description: "Lightning sensor"
134
+ MSFx:
135
+ collection: "calibration_devices"
136
+ observatory: "CTAO"
137
+ site: ["North", "South"]
138
+ design_types: ["FlashCam", "NectarCam", "test"]
139
+ description: "Flat-fielding device (MST)"
140
+ LSFN:
141
+ collection: "calibration_devices"
142
+ observatory: "CTAO"
143
+ site: "North"
144
+ description: "Flat-fielding device (LST)"
145
+ LSFS:
146
+ collection: "calibration_devices"
147
+ observatory: "CTAO"
148
+ site: "South"
149
+ description: "Flat-fielding device (LST)"
150
+ SSFS:
151
+ collection: "calibration_devices"
152
+ observatory: "CTAO"
153
+ site: "South"
154
+ description: "Flat-fielding device (SST)"
155
+ SCFS:
156
+ collection: "calibration_devices"
157
+ observatory: "CTAO"
158
+ site: "South"
159
+ description: "Flat-fielding device (SCT)"
134
160
  HESS:
135
161
  collection: "telescopes"
136
162
  site: "South"
@@ -7,8 +7,6 @@ from pathlib import Path
7
7
  from simtools.io import io_handler
8
8
  from simtools.runners.runner_services import RunnerServices
9
9
 
10
- __all__ = ["CorsikaRunner", "MissingRequiredEntryInCorsikaConfigError"]
11
-
12
10
 
13
11
  class MissingRequiredEntryInCorsikaConfigError(Exception):
14
12
  """Exception for missing required entry in corsika config."""
@@ -4,11 +4,10 @@ import logging
4
4
  import stat
5
5
  from pathlib import Path
6
6
 
7
+ import simtools.utils.general as gen
7
8
  from simtools.runners.corsika_runner import CorsikaRunner
8
9
  from simtools.simtel.simulator_array import SimulatorArray
9
10
 
10
- __all__ = ["CorsikaSimtelRunner"]
11
-
12
11
 
13
12
  class CorsikaSimtelRunner:
14
13
  """
@@ -32,6 +31,8 @@ class CorsikaSimtelRunner:
32
31
  Use multipipe to run CORSIKA and sim_telarray.
33
32
  sim_telarray_seeds : dict
34
33
  Dictionary with configuration for sim_telarray random instrument setup.
34
+ calibration_config : dict
35
+ Configuration for the calibration of the sim_telarray data.
35
36
  """
36
37
 
37
38
  def __init__(
@@ -43,12 +44,10 @@ class CorsikaSimtelRunner:
43
44
  use_multipipe=False,
44
45
  sim_telarray_seeds=None,
45
46
  sequential=False,
46
- calibration_runner_args=None,
47
+ calibration_config=None,
47
48
  ):
48
49
  self._logger = logging.getLogger(__name__)
49
- self.corsika_config = (
50
- corsika_config if isinstance(corsika_config, list) else [corsika_config]
51
- )
50
+ self.corsika_config = gen.ensure_iterable(corsika_config)
52
51
  # the base corsika config is the one used to define the CORSIKA specific parameters.
53
52
  # The others are used for the array configurations.
54
53
  self.base_corsika_config = self.corsika_config[0]
@@ -56,7 +55,6 @@ class CorsikaSimtelRunner:
56
55
  self.sim_telarray_seeds = sim_telarray_seeds
57
56
  self.label = label
58
57
  self.sequential = "--sequential" if sequential else ""
59
- self.calibration_runner_args = calibration_runner_args
60
58
 
61
59
  self.base_corsika_config.set_output_file_and_directory(use_multipipe)
62
60
  self.corsika_runner = CorsikaRunner(
@@ -77,6 +75,7 @@ class CorsikaSimtelRunner:
77
75
  label=label,
78
76
  use_multipipe=use_multipipe,
79
77
  sim_telarray_seeds=sim_telarray_seeds,
78
+ calibration_config=calibration_config,
80
79
  )
81
80
  )
82
81
 
@@ -126,18 +125,11 @@ class CorsikaSimtelRunner:
126
125
 
127
126
  with open(multipipe_file, "w", encoding="utf-8") as file:
128
127
  for simulator_array in self.simulator_array:
129
- if self.calibration_runner_args:
130
- run_command = simulator_array.make_run_command_for_calibration_simulations(
131
- run_number=run_number,
132
- input_file="-", # instruct sim_telarray to take input from standard output
133
- calibration_runner_args=self.calibration_runner_args,
134
- )
135
- else:
136
- run_command = simulator_array.make_run_command(
137
- run_number=run_number,
138
- input_file="-", # instruct sim_telarray to take input from standard output
139
- weak_pointing=self._determine_pointing_option(self.label),
140
- )
128
+ run_command = simulator_array.make_run_command(
129
+ run_number=run_number,
130
+ input_file="-", # instruct sim_telarray to take input from standard output
131
+ weak_pointing=self._determine_pointing_option(self.label),
132
+ )
141
133
  file.write(f"{run_command}")
142
134
  file.write("\n")
143
135
  self._logger.info(f"Multipipe script: {multipipe_file}")
@@ -90,17 +90,16 @@ class RunnerServices:
90
90
  dict
91
91
  Dictionary containing paths requires for simulation configuration.
92
92
  """
93
- self.directory["output"] = io_handler.IOHandler().get_output_directory(self.label)
93
+ ioh = io_handler.IOHandler()
94
+ self.directory["output"] = ioh.get_output_directory()
94
95
  _logger.debug(f"Creating output dir {self.directory['output']}")
95
96
  for dir_name in ["sub_scripts", "sub_logs"]:
96
- self.directory[dir_name] = self.directory["output"].joinpath(dir_name)
97
- self.directory[dir_name].mkdir(parents=True, exist_ok=True)
97
+ self.directory[dir_name] = ioh.get_output_directory(dir_name)
98
98
  for _simulation_software in self._get_simulation_software_list(simulation_software):
99
99
  for dir_name in ["data", "inputs", "logs"]:
100
- self.directory[dir_name] = self.directory["output"].joinpath(
101
- _simulation_software, dir_name
100
+ self.directory[dir_name] = ioh.get_output_directory(
101
+ [_simulation_software, dir_name]
102
102
  )
103
- self.directory[dir_name].mkdir(parents=True, exist_ok=True)
104
103
  self._logger.debug(f"Data directories for {simulation_software}: {self.directory}")
105
104
  return self.directory
106
105
 
@@ -8,8 +8,6 @@ from pathlib import Path
8
8
  import simtools.utils.general as gen
9
9
  from simtools.runners.runner_services import RunnerServices
10
10
 
11
- __all__ = ["InvalidOutputFileError", "SimtelExecutionError", "SimtelRunner"]
12
-
13
11
 
14
12
  class SimtelExecutionError(Exception):
15
13
  """Exception for sim_telarray execution error."""