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
@@ -65,7 +65,6 @@ r"""
65
65
 
66
66
  """
67
67
 
68
- import logging
69
68
  from pathlib import Path
70
69
 
71
70
  import astropy.units as u
@@ -73,18 +72,17 @@ import matplotlib.pyplot as plt
73
72
  import numpy as np
74
73
  from matplotlib.backends.backend_pdf import PdfPages
75
74
 
76
- import simtools.utils.general as gen
75
+ from simtools.application_control import get_application_label, startup_application
77
76
  from simtools.configuration import configurator
78
- from simtools.io import io_handler
79
77
  from simtools.model.model_utils import initialize_simulation_models
80
78
  from simtools.ray_tracing.ray_tracing import RayTracing
81
79
  from simtools.visualization import visualize
82
80
 
83
81
 
84
- def _parse(label):
82
+ def _parse():
85
83
  """Parse command line configuration."""
86
84
  config = configurator.Configurator(
87
- label=label,
85
+ label=get_application_label(__file__),
88
86
  description=(
89
87
  "Calculate and plot the PSF and effective mirror area as a function of off-axis angle "
90
88
  "of the telescope requested."
@@ -118,22 +116,16 @@ def _parse(label):
118
116
  return config.initialize(db_config=True, simulation_model=["telescope", "model_version"])
119
117
 
120
118
 
121
- def main(): # noqa: D103
122
- label = Path(__file__).stem
123
- args_dict, db_config = _parse(label)
119
+ def main():
120
+ """Validate the optical model parameters through ray tracing simulations."""
121
+ app_context = startup_application(_parse, setup_io_handler=True)
124
122
 
125
- logger = logging.getLogger()
126
- logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
127
-
128
- _io_handler = io_handler.IOHandler()
129
- output_dir = _io_handler.get_output_directory(label, sub_dir="application-plots")
130
-
131
- tel_model, site_model = initialize_simulation_models(
132
- label=label,
133
- db_config=db_config,
134
- site=args_dict["site"],
135
- telescope_name=args_dict["telescope"],
136
- model_version=args_dict["model_version"],
123
+ tel_model, site_model, _ = initialize_simulation_models(
124
+ label=Path(__file__).stem,
125
+ db_config=app_context.db_config,
126
+ site=app_context.args["site"],
127
+ telescope_name=app_context.args["telescope"],
128
+ model_version=app_context.args["model_version"],
137
129
  )
138
130
 
139
131
  ######################################################################
@@ -147,22 +139,24 @@ def main(): # noqa: D103
147
139
  # }
148
140
  # tel_model.change_multiple_parameters(**pars_to_change)
149
141
 
150
- print(f"\nValidating telescope optics with ray tracing simulations for {tel_model.name}\n")
142
+ app_context.logger.info(
143
+ f"\nValidating telescope optics with ray tracing simulations for {tel_model.name}\n"
144
+ )
151
145
 
152
146
  ray = RayTracing(
153
147
  telescope_model=tel_model,
154
148
  site_model=site_model,
155
- simtel_path=args_dict["simtel_path"],
156
- zenith_angle=args_dict["zenith"] * u.deg,
157
- source_distance=args_dict["src_distance"] * u.km,
149
+ simtel_path=app_context.args["simtel_path"],
150
+ zenith_angle=app_context.args["zenith"] * u.deg,
151
+ source_distance=app_context.args["src_distance"] * u.km,
158
152
  off_axis_angle=np.linspace(
159
153
  0,
160
- args_dict["max_offset"],
161
- int(args_dict["max_offset"] / args_dict["offset_steps"]) + 1,
154
+ app_context.args["max_offset"],
155
+ int(app_context.args["max_offset"] / app_context.args["offset_steps"]) + 1,
162
156
  )
163
157
  * u.deg,
164
158
  )
165
- ray.simulate(test=args_dict["test"], force=False)
159
+ ray.simulate(test=app_context.args["test"], force=False)
166
160
  ray.analyze(force=True)
167
161
 
168
162
  # Plotting
@@ -171,17 +165,17 @@ def main(): # noqa: D103
171
165
 
172
166
  ray.plot(key, marker="o", linestyle=":", color="k")
173
167
 
174
- plot_file_name = "_".join((label, tel_model.name, key))
175
- plot_file = output_dir.joinpath(plot_file_name)
168
+ plot_file_name = "_".join((app_context.args.get("label"), tel_model.name, key))
169
+ plot_file = app_context.io_handler.get_output_file(plot_file_name)
176
170
  visualize.save_figure(plt, plot_file)
177
171
 
178
172
  # Plotting images
179
- if args_dict["plot_images"]:
180
- plot_file_name = "_".join((label, tel_model.name, "images.pdf"))
181
- plot_file = output_dir.joinpath(plot_file_name)
173
+ if app_context.args["plot_images"]:
174
+ plot_file_name = "_".join((app_context.args.get("label"), tel_model.name, "images.pdf"))
175
+ plot_file = app_context.io_handler.get_output_file(plot_file_name)
182
176
  pdf_pages = PdfPages(plot_file)
183
177
 
184
- logger.info(f"Plotting images into {plot_file}")
178
+ app_context.logger.info(f"Plotting images into {plot_file}")
185
179
 
186
180
  for image in ray.images():
187
181
  fig = plt.figure(figsize=(8, 6), tight_layout=True)
@@ -15,8 +15,6 @@ from simtools.simtel.simulator_camera_efficiency import SimulatorCameraEfficienc
15
15
  from simtools.utils import names
16
16
  from simtools.visualization import visualize
17
17
 
18
- __all__ = ["CameraEfficiency"]
19
-
20
18
 
21
19
  class CameraEfficiency:
22
20
  """
@@ -40,14 +38,14 @@ class CameraEfficiency:
40
38
  self.label = label
41
39
 
42
40
  self.io_handler = io_handler.IOHandler()
43
- self.telescope_model, self.site_model = initialize_simulation_models(
44
- self.label,
45
- db_config,
46
- config_data["site"],
47
- config_data["telescope"],
48
- config_data["model_version"],
41
+ self.telescope_model, self.site_model, _ = initialize_simulation_models(
42
+ label=self.label,
43
+ db_config=db_config,
44
+ model_version=config_data["model_version"],
45
+ site=config_data["site"],
46
+ telescope_name=config_data["telescope"],
49
47
  )
50
- self.output_dir = self.io_handler.get_output_directory(self.label, sub_dir="plots")
48
+ self.output_dir = self.io_handler.get_output_directory()
51
49
 
52
50
  self._results = None
53
51
  self._has_results = False
@@ -101,10 +99,7 @@ class CameraEfficiency:
101
99
  label=self.label,
102
100
  )
103
101
 
104
- _file[label] = self.io_handler.get_output_directory(
105
- label=self.label,
106
- sub_dir="camera_efficiency",
107
- ).joinpath(file_name)
102
+ _file[label] = self.io_handler.get_output_directory().joinpath(file_name)
108
103
  return _file
109
104
 
110
105
  def simulate(self):
@@ -10,10 +10,6 @@ import astropy.units as u
10
10
  import simtools.version
11
11
  from simtools.utils import names
12
12
 
13
- __all__ = [
14
- "CommandLineParser",
15
- ]
16
-
17
13
 
18
14
  class CommandLineParser(argparse.ArgumentParser):
19
15
  """
@@ -21,7 +17,7 @@ class CommandLineParser(argparse.ArgumentParser):
21
17
 
22
18
  Wrapper around standard python argparse.ArgumentParser.
23
19
 
24
- Command line arguments should be given in snake_case, e.g. input_meta.
20
+ Command line arguments should be given in snake_case, e.g. 'input_meta'.
25
21
 
26
22
  Parameters
27
23
  ----------
@@ -102,12 +98,6 @@ class CommandLineParser(argparse.ArgumentParser):
102
98
  default="./simtools-output/",
103
99
  required=False,
104
100
  )
105
- _job_group.add_argument(
106
- "--use_plain_output_path",
107
- help="use plain output path (without the tool name and dates)",
108
- action="store_true",
109
- required=False,
110
- )
111
101
  _job_group.add_argument(
112
102
  "--model_path",
113
103
  help="path pointing towards simulation model file directory",
@@ -567,6 +557,38 @@ class CommandLineParser(argparse.ArgumentParser):
567
557
  )
568
558
  return job_group
569
559
 
560
+ @staticmethod
561
+ def scientific_int(value):
562
+ """
563
+ Convert string (including scientific notation) to integer.
564
+
565
+ Parameters
566
+ ----------
567
+ value: str or int or float
568
+ Value to convert to integer. Can be a regular integer,
569
+ float, or string in scientific notation (e.g., '1e7').
570
+
571
+ Returns
572
+ -------
573
+ int
574
+ Converted integer value
575
+
576
+ Raises
577
+ ------
578
+ argparse.ArgumentTypeError
579
+ If the value cannot be converted to an integer
580
+ """
581
+ try:
582
+ f = float(value)
583
+ if not f.is_integer():
584
+ raise ValueError
585
+ return int(f)
586
+ except (ValueError, TypeError) as exc:
587
+ raise argparse.ArgumentTypeError(
588
+ f"Invalid integer value: '{value}'. "
589
+ "Expected an integer or scientific notation like '1e7'."
590
+ ) from exc
591
+
570
592
  @staticmethod
571
593
  def site(value):
572
594
  """
@@ -14,11 +14,6 @@ from simtools.db.db_handler import jsonschema_db_dict
14
14
  from simtools.io import ascii_handler, io_handler
15
15
  from simtools.utils import general as gen
16
16
 
17
- __all__ = [
18
- "Configurator",
19
- "InvalidConfigurationParameterError",
20
- ]
21
-
22
17
 
23
18
  class InvalidConfigurationParameterError(Exception):
24
19
  """Exception for Invalid configuration parameter."""
@@ -340,8 +335,6 @@ class Configurator:
340
335
  _io_handler = io_handler.IOHandler()
341
336
  _io_handler.set_paths(
342
337
  output_path=self.config.get("output_path", None),
343
- use_plain_output_path=self.config.get("use_plain_output_path", False),
344
- data_path=self.config.get("data_path", None),
345
338
  model_path=self.config.get("model_path", None),
346
339
  )
347
340
 
@@ -10,11 +10,6 @@ from simtools.corsika.primary_particle import PrimaryParticle
10
10
  from simtools.io import io_handler
11
11
  from simtools.model.model_parameter import ModelParameter
12
12
 
13
- __all__ = [
14
- "CorsikaConfig",
15
- "InvalidCorsikaInputError",
16
- ]
17
-
18
13
 
19
14
  class InvalidCorsikaInputError(Exception):
20
15
  """Exception for invalid corsika input."""
@@ -114,8 +109,8 @@ class CorsikaConfig:
114
109
  return {}
115
110
 
116
111
  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
112
+ self.azimuth_angle = int(args_dict.get("azimuth_angle", 0.0 * u.deg).to("deg").value)
113
+ self.zenith_angle = int(args_dict.get("zenith_angle", 0.0 * u.deg).to("deg").value)
119
114
 
120
115
  self._logger.debug(
121
116
  f"Setting CORSIKA parameters from database ({args_dict['model_version']})"
@@ -563,8 +558,9 @@ class CorsikaConfig:
563
558
  if self.is_file_updated:
564
559
  self._logger.debug(f"CORSIKA input file already updated: {self.config_file_path}")
565
560
  return self.config_file_path
566
- _output_generic_file_name = self.set_output_file_and_directory(use_multipipe=use_multipipe)
567
561
  self._logger.info(f"Exporting CORSIKA input file to {self.config_file_path}")
562
+ _output_generic_file_name = self.set_output_file_and_directory(use_multipipe=use_multipipe)
563
+ self._logger.info(f"Output generic file name: {_output_generic_file_name}")
568
564
 
569
565
  with open(self.config_file_path, "w", encoding="utf-8") as file:
570
566
  file.write("\n* [ RUN PARAMETERS ]\n")
@@ -712,13 +708,10 @@ class CorsikaConfig:
712
708
  str
713
709
  Output file name.
714
710
  """
715
- sub_dir = "corsika_sim_telarray" if use_multipipe else "corsika"
716
- config_file_name = self.get_corsika_config_file_name(file_type="config")
717
- file_directory = self.io_handler.get_output_directory(label=self.label, sub_dir=sub_dir)
718
- self._logger.debug(f"Creating directory {file_directory}")
719
- file_directory.mkdir(parents=True, exist_ok=True)
720
- self.config_file_path = file_directory.joinpath(config_file_name)
721
-
711
+ self.config_file_path = self.io_handler.get_output_file(
712
+ file_name=self.get_corsika_config_file_name(file_type="config"),
713
+ sub_dir="corsika_sim_telarray" if use_multipipe else "corsika",
714
+ )
722
715
  return self.get_corsika_config_file_name(file_type="output_generic")
723
716
 
724
717
  def _write_seeds(self, file, use_test_seeds=False):
@@ -748,7 +741,7 @@ class CorsikaConfig:
748
741
  Piece of text to be added to the CORSIKA input file.
749
742
  """
750
743
  corsika_input_list = ""
751
- for telescope_name, telescope in self.array_model.telescope_model.items():
744
+ for telescope_name, telescope in self.array_model.telescope_models.items():
752
745
  positions = telescope.get_parameter_value_with_unit("array_element_position_ground")
753
746
  corsika_input_list += "TELESCOPE"
754
747
  for pos in positions:
@@ -67,7 +67,7 @@ class CorsikaHistograms:
67
67
  raise FileNotFoundError
68
68
 
69
69
  self.io_handler = io_handler.IOHandler()
70
- _default_output_path = self.io_handler.get_output_directory(self.label, "corsika")
70
+ _default_output_path = self.io_handler.get_output_directory("corsika")
71
71
 
72
72
  if output_path is None:
73
73
  self.output_path = _default_output_path
@@ -10,8 +10,6 @@ from simtools.data_model import validate_data
10
10
  from simtools.data_model.metadata_collector import MetadataCollector
11
11
  from simtools.io import ascii_handler
12
12
 
13
- __all__ = ["read_table_from_file", "read_value_from_file"]
14
-
15
13
  _logger = logging.getLogger(__name__)
16
14
 
17
15
 
@@ -18,8 +18,6 @@ from simtools.data_model import metadata_model, schema
18
18
  from simtools.io import ascii_handler, io_handler
19
19
  from simtools.utils import names
20
20
 
21
- __all__ = ["MetadataCollector"]
22
-
23
21
 
24
22
  class MetadataCollector:
25
23
  """
@@ -3,6 +3,7 @@
3
3
  import logging
4
4
  from pathlib import Path
5
5
 
6
+ import packaging.version
6
7
  from astropy.io.registry.base import IORegistryError
7
8
 
8
9
  import simtools.utils.general as gen
@@ -12,8 +13,6 @@ from simtools.db import db_handler
12
13
  from simtools.io import ascii_handler, io_handler
13
14
  from simtools.utils import names, value_conversion
14
15
 
15
- __all__ = ["ModelDataWriter"]
16
-
17
16
 
18
17
  class ModelDataWriter:
19
18
  """
@@ -29,8 +28,6 @@ class ModelDataWriter:
29
28
  Dictionary with configuration parameters.
30
29
  output_path: str or Path
31
30
  Path to output file.
32
- use_plain_output_path: bool
33
- Use plain output path.
34
31
  args_dict: dict
35
32
  Dictionary with configuration parameters.
36
33
 
@@ -41,7 +38,6 @@ class ModelDataWriter:
41
38
  product_data_file=None,
42
39
  product_data_format=None,
43
40
  output_path=None,
44
- use_plain_output_path=True,
45
41
  args_dict=None,
46
42
  ):
47
43
  """Initialize model data writer."""
@@ -50,11 +46,8 @@ class ModelDataWriter:
50
46
  self.schema_dict = {}
51
47
  if args_dict is not None:
52
48
  output_path = args_dict.get("output_path", output_path)
53
- use_plain_output_path = args_dict.get("use_plain_output_path", use_plain_output_path)
54
49
  if output_path is not None:
55
- self.io_handler.set_paths(
56
- output_path=output_path, use_plain_output_path=use_plain_output_path
57
- )
50
+ self.io_handler.set_paths(output_path=output_path)
58
51
  try:
59
52
  self.product_data_file = self.io_handler.get_output_file(file_name=product_data_file)
60
53
  except TypeError:
@@ -104,9 +97,10 @@ class ModelDataWriter:
104
97
  parameter_version,
105
98
  output_file,
106
99
  output_path=None,
107
- use_plain_output_path=False,
108
100
  metadata_input_dict=None,
109
101
  db_config=None,
102
+ unit=None,
103
+ meta_parameter=False,
110
104
  ):
111
105
  """
112
106
  Generate DB-style model parameter dict and write it to json file.
@@ -125,12 +119,12 @@ class ModelDataWriter:
125
119
  Name of output file.
126
120
  output_path: str or Path
127
121
  Path to output file.
128
- use_plain_output_path: bool
129
- Use plain output path.
130
122
  metadata_input_dict: dict
131
123
  Input to metadata collector.
132
124
  db_config: dict
133
125
  Database configuration. If not None, check if parameter with the same version exists.
126
+ unit: str
127
+ Unit of the parameter value (if applicable and value is not of type astropy Quantity).
134
128
 
135
129
  Returns
136
130
  -------
@@ -142,7 +136,6 @@ class ModelDataWriter:
142
136
  product_data_format="json",
143
137
  args_dict=None,
144
138
  output_path=output_path,
145
- use_plain_output_path=use_plain_output_path,
146
139
  )
147
140
  if db_config is not None:
148
141
  writer.check_db_for_existing_parameter(
@@ -160,7 +153,13 @@ class ModelDataWriter:
160
153
  )
161
154
 
162
155
  _json_dict = writer.get_validated_parameter_dict(
163
- parameter_name, value, instrument, parameter_version, unique_id
156
+ parameter_name,
157
+ value,
158
+ instrument,
159
+ parameter_version,
160
+ unique_id,
161
+ unit=unit,
162
+ meta_parameter=meta_parameter,
164
163
  )
165
164
  writer.write_dict_to_model_parameter_json(output_file, _json_dict)
166
165
  return _json_dict
@@ -210,6 +209,8 @@ class ModelDataWriter:
210
209
  parameter_version,
211
210
  unique_id=None,
212
211
  schema_version=None,
212
+ unit=None,
213
+ meta_parameter=False,
213
214
  ):
214
215
  """
215
216
  Get validated parameter dictionary.
@@ -226,6 +227,12 @@ class ModelDataWriter:
226
227
  Version of the parameter.
227
228
  schema_version: str
228
229
  Version of the schema.
230
+ unique_id: str
231
+ Unique ID of the parameter set (from metadata).
232
+ unit: str
233
+ Unit of the parameter value (if applicable and value is not an astropy Quantity).
234
+ meta_parameter: bool
235
+ Setting for meta parameter flag.
229
236
 
230
237
  Returns
231
238
  -------
@@ -233,10 +240,10 @@ class ModelDataWriter:
233
240
  Validated parameter dictionary.
234
241
  """
235
242
  self._logger.debug(f"Getting validated parameter dictionary for {instrument}")
236
- schema_file = schema.get_model_parameter_schema_file(parameter_name)
237
- self.schema_dict = ascii_handler.collect_data_from_file(schema_file)
243
+ self.schema_dict, schema_file = self._read_schema_dict(parameter_name, schema_version)
238
244
 
239
- value, unit = value_conversion.split_value_and_unit(value)
245
+ if unit is None:
246
+ value, unit = value_conversion.split_value_and_unit(value)
240
247
 
241
248
  data_dict = {
242
249
  "schema_version": schema.get_model_parameter_schema_version(schema_version),
@@ -249,10 +256,8 @@ class ModelDataWriter:
249
256
  "unit": unit,
250
257
  "type": self._get_parameter_type(),
251
258
  "file": self._parameter_is_a_file(),
252
- "meta_parameter": False,
253
- "model_parameter_schema_version": self.schema_dict.get(
254
- "model_parameter_schema_version", "0.1.0"
255
- ),
259
+ "meta_parameter": meta_parameter,
260
+ "model_parameter_schema_version": self.schema_dict.get("schema_version", "0.1.0"),
256
261
  }
257
262
  return self.validate_and_transform(
258
263
  product_data_dict=data_dict,
@@ -260,19 +265,74 @@ class ModelDataWriter:
260
265
  is_model_parameter=True,
261
266
  )
262
267
 
268
+ def _read_schema_dict(self, parameter_name, schema_version):
269
+ """
270
+ Read schema dict for given parameter name and version.
271
+
272
+ Use newest schema version if schema_version is None.
273
+
274
+ Parameters
275
+ ----------
276
+ parameter_name: str
277
+ Name of the parameter.
278
+ schema_version: str
279
+ Schema version.
280
+
281
+ Returns
282
+ -------
283
+ dict
284
+ Schema dictionary.
285
+ """
286
+ schema_file = schema.get_model_parameter_schema_file(parameter_name)
287
+ schemas = ascii_handler.collect_data_from_file(schema_file)
288
+ if isinstance(schemas, list):
289
+ if schema_version is None:
290
+ return self._find_highest_schema_version(schemas), schema_file
291
+ for entry in schemas:
292
+ if entry.get("schema_version") == schema_version:
293
+ return entry, schema_file
294
+ else:
295
+ return schemas, schema_file
296
+
297
+ raise ValueError(f"Schema version {schema_version} not found for {parameter_name}")
298
+
299
+ def _find_highest_schema_version(self, schema_list):
300
+ """
301
+ Find entry with highest schema_version in a list of schema dicts.
302
+
303
+ Parameters
304
+ ----------
305
+ schema_list: list
306
+ List of schema dictionaries.
307
+
308
+ Returns
309
+ -------
310
+ dict
311
+ Schema dictionary with highest schema_version.
312
+ """
313
+ try:
314
+ valid_entries = [entry for entry in schema_list if "schema_version" in entry]
315
+ except TypeError as exc:
316
+ raise TypeError("No valid schema versions found in the list.") from exc
317
+ return max(valid_entries, key=lambda e: packaging.version.Version(e["schema_version"]))
318
+
263
319
  def _get_parameter_type(self):
264
320
  """
265
321
  Return parameter type from schema.
266
322
 
323
+ Reduce list of types to single type if all types are the same.
324
+
267
325
  Returns
268
326
  -------
269
- str
327
+ str or list[str]
270
328
  Parameter type
271
329
  """
272
- _parameter_type = []
273
- for data in self.schema_dict["data"]:
274
- _parameter_type.append(data["type"])
275
- return _parameter_type if len(_parameter_type) > 1 else _parameter_type[0]
330
+ _parameter_type = [data["type"] for data in self.schema_dict["data"]]
331
+ return (
332
+ _parameter_type[0]
333
+ if all(t == _parameter_type[0] for t in _parameter_type)
334
+ else _parameter_type
335
+ )
276
336
 
277
337
  def _parameter_is_a_file(self):
278
338
  """
@@ -399,7 +459,7 @@ class ModelDataWriter:
399
459
  ascii_handler.write_data_to_file(
400
460
  data=data_dict,
401
461
  output_file=self.io_handler.get_output_file(file_name),
402
- sort_keys=False,
462
+ sort_keys=True,
403
463
  numpy_types=True,
404
464
  )
405
465
 
@@ -4,9 +4,12 @@ import logging
4
4
  from pathlib import Path
5
5
 
6
6
  import jsonschema
7
+ from packaging.specifiers import SpecifierSet
8
+ from packaging.version import Version
7
9
  from referencing import Registry, Resource
8
10
 
9
11
  import simtools.utils.general as gen
12
+ from simtools import version
10
13
  from simtools.constants import (
11
14
  METADATA_JSON_SCHEMA,
12
15
  MODEL_PARAMETER_METASCHEMA,
@@ -66,7 +69,7 @@ def get_model_parameter_schema_file(parameter):
66
69
 
67
70
  def get_model_parameter_schema_version(schema_version=None):
68
71
  """
69
- Validate and return schema versions.
72
+ Validate and return schema versions.
70
73
 
71
74
  If no schema_version is given, the most recent version is provided.
72
75
 
@@ -92,7 +95,9 @@ def get_model_parameter_schema_version(schema_version=None):
92
95
  raise ValueError(f"Schema version {schema_version} not found in {MODEL_PARAMETER_METASCHEMA}.")
93
96
 
94
97
 
95
- def validate_dict_using_schema(data, schema_file=None, json_schema=None):
98
+ def validate_dict_using_schema(
99
+ data, schema_file=None, json_schema=None, ignore_software_version=False
100
+ ):
96
101
  """
97
102
  Validate a data dictionary against a schema.
98
103
 
@@ -102,6 +107,10 @@ def validate_dict_using_schema(data, schema_file=None, json_schema=None):
102
107
  dictionary to be validated
103
108
  schema_file (dict)
104
109
  schema used for validation
110
+ json_schema (dict)
111
+ schema used for validation
112
+ ignore_software_version: bool
113
+ If True, ignore software version check.
105
114
 
106
115
  Raises
107
116
  ------
@@ -115,6 +124,8 @@ def validate_dict_using_schema(data, schema_file=None, json_schema=None):
115
124
  if json_schema is None:
116
125
  json_schema = load_schema(schema_file, get_schema_version_from_data(data))
117
126
 
127
+ _validate_deprecation_and_version(data, ignore_software_version)
128
+
118
129
  validator = jsonschema.Draft6Validator(
119
130
  schema=json_schema,
120
131
  format_checker=format_checkers.format_checker,
@@ -294,3 +305,51 @@ def _add_array_elements(key, schema):
294
305
 
295
306
  recursive_search(schema, key)
296
307
  return schema
308
+
309
+
310
+ def _validate_deprecation_and_version(
311
+ data, software_name="simtools", ignore_software_version=False
312
+ ):
313
+ """
314
+ Check if data contains deprecated parameters or version mismatches.
315
+
316
+ Parameters
317
+ ----------
318
+ data: dict
319
+ Data dictionary to check.
320
+ software_name: str
321
+ Name of the software to check version against.
322
+ ignore_software_version: bool
323
+ If True, ignore software version check.
324
+ """
325
+ if not isinstance(data, dict):
326
+ return
327
+
328
+ if data.get("deprecated", False):
329
+ note = data.get("deprecation_note", "(no deprecation note provided)")
330
+ _logger.warning(f"Data is deprecated. Note: {note}")
331
+
332
+ def check_version(sw):
333
+ constraint = sw.get("version")
334
+ if constraint is None:
335
+ return
336
+ constraint = constraint.strip()
337
+ spec = SpecifierSet(constraint, prereleases=True)
338
+ if Version(version.__version__) in spec:
339
+ _logger.debug(
340
+ f"Version {version.__version__} of {software_name} matches constraint {constraint}."
341
+ )
342
+ else:
343
+ msg = (
344
+ f"Version {version.__version__} of {software_name} "
345
+ f"does not match constraint {constraint}."
346
+ )
347
+ if ignore_software_version:
348
+ _logger.warning(f"{msg}, but version check is ignored.")
349
+ return
350
+ raise ValueError(msg)
351
+
352
+ for sw in data.get("simulation_software", []):
353
+ if sw.get("name") == software_name:
354
+ check_version(sw)
355
+ break