gammasimtools 0.13.0__py3-none-any.whl → 0.14.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 (226) hide show
  1. {gammasimtools-0.13.0.dist-info → gammasimtools-0.14.0.dist-info}/METADATA +3 -3
  2. {gammasimtools-0.13.0.dist-info → gammasimtools-0.14.0.dist-info}/RECORD +224 -217
  3. {gammasimtools-0.13.0.dist-info → gammasimtools-0.14.0.dist-info}/WHEEL +1 -1
  4. {gammasimtools-0.13.0.dist-info → gammasimtools-0.14.0.dist-info}/entry_points.txt +3 -1
  5. simtools/_version.py +2 -2
  6. simtools/applications/db_add_file_to_db.py +15 -0
  7. simtools/applications/db_add_value_from_json_to_db.py +18 -1
  8. simtools/applications/derive_ctao_array_layouts.py +120 -0
  9. simtools/applications/derive_photon_electron_spectrum.py +29 -1
  10. simtools/applications/docs_produce_array_element_report.py +41 -16
  11. simtools/applications/docs_produce_model_parameter_reports.py +28 -8
  12. simtools/applications/{production_extract_mc_event_data.py → generate_simtel_event_data.py} +12 -20
  13. simtools/applications/print_version.py +81 -0
  14. simtools/applications/production_derive_corsika_limits.py +172 -39
  15. simtools/applications/production_scale_events.py +59 -36
  16. simtools/applications/run_application.py +41 -11
  17. simtools/applications/simulate_light_emission.py +115 -247
  18. simtools/applications/simulate_prod_htcondor_generator.py +2 -2
  19. simtools/camera/single_photon_electron_spectrum.py +163 -15
  20. simtools/data_model/model_data_writer.py +7 -6
  21. simtools/db/db_handler.py +14 -8
  22. simtools/dependencies.py +38 -3
  23. simtools/layout/array_layout.py +1 -0
  24. simtools/layout/ctao_array_layouts.py +172 -0
  25. simtools/model/array_model.py +3 -4
  26. simtools/model/model_parameter.py +30 -87
  27. simtools/production_configuration/derive_corsika_limits.py +222 -154
  28. simtools/production_configuration/event_scaler.py +2 -2
  29. simtools/reporting/docs_auto_report_generator.py +217 -0
  30. simtools/reporting/docs_read_parameters.py +192 -110
  31. simtools/schemas/application_workflow.metaschema.yml +3 -0
  32. simtools/schemas/model_parameter.metaschema.yml +13 -0
  33. simtools/schemas/model_parameter_and_data_schema.metaschema.yml +6 -0
  34. simtools/schemas/model_parameters/adjust_gain.schema.yml +1 -1
  35. simtools/schemas/model_parameters/altitude.schema.yml +1 -1
  36. simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +3 -3
  37. simtools/schemas/model_parameters/array_element_position_ground.schema.yml +3 -3
  38. simtools/schemas/model_parameters/array_element_position_utm.schema.yml +3 -3
  39. simtools/schemas/model_parameters/array_window.schema.yml +1 -1
  40. simtools/schemas/model_parameters/asum_clipping.schema.yml +1 -1
  41. simtools/schemas/model_parameters/asum_offset.schema.yml +1 -1
  42. simtools/schemas/model_parameters/asum_threshold.schema.yml +1 -1
  43. simtools/schemas/model_parameters/axes_offsets.schema.yml +2 -2
  44. simtools/schemas/model_parameters/camera_body_diameter.schema.yml +1 -1
  45. simtools/schemas/model_parameters/camera_body_shape.schema.yml +1 -1
  46. simtools/schemas/model_parameters/camera_config_rotate.schema.yml +1 -1
  47. simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +1 -1
  48. simtools/schemas/model_parameters/camera_depth.schema.yml +1 -1
  49. simtools/schemas/model_parameters/camera_pixels.schema.yml +1 -1
  50. simtools/schemas/model_parameters/camera_transmission.schema.yml +1 -1
  51. simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
  52. simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +1 -1
  53. simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +1 -1
  54. simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +1 -1
  55. simtools/schemas/model_parameters/corsika_observation_level.schema.yml +1 -1
  56. simtools/schemas/model_parameters/dark_events.schema.yml +1 -1
  57. simtools/schemas/model_parameters/disc_bins.schema.yml +1 -1
  58. simtools/schemas/model_parameters/disc_start.schema.yml +1 -1
  59. simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +1 -1
  60. simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +1 -1
  61. simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +1 -1
  62. simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +1 -1
  63. simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +1 -1
  64. simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +1 -1
  65. simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +1 -1
  66. simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +1 -1
  67. simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +1 -1
  68. simtools/schemas/model_parameters/discriminator_threshold.schema.yml +1 -1
  69. simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +1 -1
  70. simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +1 -1
  71. simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +1 -1
  72. simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +1 -1
  73. simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +1 -1
  74. simtools/schemas/model_parameters/dish_shape_length.schema.yml +1 -1
  75. simtools/schemas/model_parameters/dsum_clipping.schema.yml +1 -1
  76. simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +1 -1
  77. simtools/schemas/model_parameters/dsum_offset.schema.yml +1 -1
  78. simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +1 -1
  79. simtools/schemas/model_parameters/dsum_prescale.schema.yml +2 -2
  80. simtools/schemas/model_parameters/dsum_presum_max.schema.yml +1 -1
  81. simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +1 -1
  82. simtools/schemas/model_parameters/dsum_threshold.schema.yml +1 -1
  83. simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +1 -1
  84. simtools/schemas/model_parameters/effective_focal_length.schema.yml +5 -5
  85. simtools/schemas/model_parameters/epsg_code.schema.yml +1 -1
  86. simtools/schemas/model_parameters/fadc_amplitude.schema.yml +1 -1
  87. simtools/schemas/model_parameters/fadc_bins.schema.yml +1 -1
  88. simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
  89. simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +1 -1
  90. simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +1 -1
  91. simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +1 -1
  92. simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +1 -1
  93. simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
  94. simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +1 -1
  95. simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +1 -1
  96. simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +1 -1
  97. simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +1 -1
  98. simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +1 -1
  99. simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +1 -1
  100. simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +1 -1
  101. simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +1 -1
  102. simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +1 -1
  103. simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +1 -1
  104. simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +1 -1
  105. simtools/schemas/model_parameters/fadc_max_signal.schema.yml +1 -1
  106. simtools/schemas/model_parameters/fadc_max_sum.schema.yml +1 -1
  107. simtools/schemas/model_parameters/fadc_mhz.schema.yml +1 -1
  108. simtools/schemas/model_parameters/fadc_noise.schema.yml +1 -1
  109. simtools/schemas/model_parameters/fadc_pedestal.schema.yml +1 -1
  110. simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +1 -1
  111. simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +1 -1
  112. simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +1 -1
  113. simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +1 -1
  114. simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +1 -1
  115. simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +1 -1
  116. simtools/schemas/model_parameters/focal_length.schema.yml +1 -1
  117. simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +20 -20
  118. simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +1 -1
  119. simtools/schemas/model_parameters/focus_offset.schema.yml +4 -4
  120. simtools/schemas/model_parameters/gain_variation.schema.yml +1 -1
  121. simtools/schemas/model_parameters/geomag_horizontal.schema.yml +1 -1
  122. simtools/schemas/model_parameters/geomag_rotation.schema.yml +1 -1
  123. simtools/schemas/model_parameters/geomag_vertical.schema.yml +1 -1
  124. simtools/schemas/model_parameters/hg_lg_variation.schema.yml +1 -1
  125. simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
  126. simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
  127. simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
  128. simtools/schemas/model_parameters/laser_external_trigger.schema.yml +1 -1
  129. simtools/schemas/model_parameters/laser_photons.schema.yml +1 -1
  130. simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +1 -1
  131. simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +1 -1
  132. simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +1 -1
  133. simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +1 -1
  134. simtools/schemas/model_parameters/laser_var_photons.schema.yml +1 -1
  135. simtools/schemas/model_parameters/laser_wavelength.schema.yml +1 -1
  136. simtools/schemas/model_parameters/led_events.schema.yml +1 -1
  137. simtools/schemas/model_parameters/led_photons.schema.yml +1 -1
  138. simtools/schemas/model_parameters/led_pulse_offset.schema.yml +1 -1
  139. simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +1 -1
  140. simtools/schemas/model_parameters/led_var_photons.schema.yml +1 -1
  141. simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
  142. simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
  143. simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +1 -1
  144. simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +4 -4
  145. simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +4 -4
  146. simtools/schemas/model_parameters/mirror_class.schema.yml +1 -1
  147. simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +1 -1
  148. simtools/schemas/model_parameters/mirror_focal_length.schema.yml +1 -1
  149. simtools/schemas/model_parameters/mirror_offset.schema.yml +1 -1
  150. simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +3 -3
  151. simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +3 -3
  152. simtools/schemas/model_parameters/multiplicity_offset.schema.yml +1 -1
  153. simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +45 -0
  154. simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +2 -2
  155. simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +1 -1
  156. simtools/schemas/model_parameters/nsb_offaxis.schema.yml +5 -5
  157. simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +1 -1
  158. simtools/schemas/model_parameters/nsb_reference_value.schema.yml +1 -1
  159. simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +1 -1
  160. simtools/schemas/model_parameters/nsb_spectrum.schema.yml +2 -2
  161. simtools/schemas/model_parameters/num_gains.schema.yml +1 -1
  162. simtools/schemas/model_parameters/pedestal_events.schema.yml +1 -1
  163. simtools/schemas/model_parameters/photon_delay.schema.yml +1 -1
  164. simtools/schemas/model_parameters/photons_per_run.schema.yml +1 -1
  165. simtools/schemas/model_parameters/pixel_cells.schema.yml +1 -1
  166. simtools/schemas/model_parameters/pixels_parallel.schema.yml +1 -1
  167. simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +1 -1
  168. simtools/schemas/model_parameters/pm_average_gain.schema.yml +1 -1
  169. simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +1 -1
  170. simtools/schemas/model_parameters/pm_gain_index.schema.yml +1 -1
  171. simtools/schemas/model_parameters/pm_transit_time.schema.yml +4 -4
  172. simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +1 -1
  173. simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +7 -3
  174. simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +1 -1
  175. simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +1 -1
  176. simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +20 -20
  177. simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +1 -1
  178. simtools/schemas/model_parameters/qe_variation.schema.yml +1 -1
  179. simtools/schemas/model_parameters/random_focal_length.schema.yml +2 -2
  180. simtools/schemas/model_parameters/random_mono_probability.schema.yml +38 -0
  181. simtools/schemas/model_parameters/reference_point_altitude.schema.yml +1 -1
  182. simtools/schemas/model_parameters/reference_point_latitude.schema.yml +4 -1
  183. simtools/schemas/model_parameters/reference_point_longitude.schema.yml +4 -1
  184. simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +1 -1
  185. simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +1 -1
  186. simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +5 -5
  187. simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
  188. simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +1 -1
  189. simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +1 -1
  190. simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +20 -20
  191. simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +1 -1
  192. simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +1 -1
  193. simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +1 -1
  194. simtools/schemas/model_parameters/stars.schema.yml +36 -0
  195. simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
  196. simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
  197. simtools/schemas/model_parameters/telescope_axis_height.schema.yml +1 -1
  198. simtools/schemas/model_parameters/telescope_random_angle.schema.yml +1 -1
  199. simtools/schemas/model_parameters/telescope_random_error.schema.yml +1 -1
  200. simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +1 -1
  201. simtools/schemas/model_parameters/telescope_transmission.schema.yml +6 -6
  202. simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +1 -1
  203. simtools/schemas/model_parameters/teltrig_min_time.schema.yml +1 -1
  204. simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +1 -1
  205. simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +1 -1
  206. simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +1 -1
  207. simtools/schemas/model_parameters/transit_time_error.schema.yml +1 -1
  208. simtools/schemas/model_parameters/transit_time_jitter.schema.yml +1 -1
  209. simtools/schemas/model_parameters/trigger_current_limit.schema.yml +1 -1
  210. simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +4 -4
  211. simtools/schemas/model_parameters/trigger_pixels.schema.yml +1 -1
  212. simtools/simtel/simtel_config_writer.py +70 -38
  213. simtools/simtel/simtel_io_event_reader.py +278 -0
  214. simtools/simtel/simtel_io_event_writer.py +317 -0
  215. simtools/simtel/simulator_light_emission.py +181 -67
  216. simtools/simulator.py +2 -2
  217. simtools/testing/configuration.py +17 -0
  218. simtools/utils/general.py +33 -7
  219. simtools/utils/geometry.py +19 -0
  220. simtools/utils/names.py +7 -1
  221. simtools/visualization/visualize.py +2 -2
  222. simtools/production_configuration/extract_mc_event_data.py +0 -253
  223. simtools/simtel/simtel_io_events.py +0 -265
  224. {gammasimtools-0.13.0.dist-info → gammasimtools-0.14.0.dist-info/licenses}/LICENSE +0 -0
  225. {gammasimtools-0.13.0.dist-info → gammasimtools-0.14.0.dist-info}/top_level.txt +0 -0
  226. /simtools/schemas/model_parameters/{nsb_skymap.schema.yml → nsb_sky_map.schema.yml} +0 -0
@@ -7,15 +7,16 @@ The limits are derived based on the event loss fraction specified by the user.
7
7
 
8
8
  Command line arguments
9
9
  ----------------------
10
- event_data_file (str, required)
11
- Path to the file containing the event data.
10
+ event_data_files (str, required)
11
+ Path to a file containing event data file paths.
12
+ telescope_ids (str, required)
13
+ Path to a file containing telescope configurations.
12
14
  loss_fraction (float, required)
13
15
  Fraction of events to be lost.
14
- telescope_ids (list of int, optional)
15
- List of telescope IDs to filter the events (default is None).
16
- Definition of the telescope IDs can be found
17
- in the telescope definition file used for simulations.
18
-
16
+ plot_histograms (bool, optional)
17
+ Plot histograms of the event data.
18
+ output_file (str, optional)
19
+ Path to the output file for the derived limits.
19
20
 
20
21
  Example
21
22
  -------
@@ -23,16 +24,23 @@ Derive limits for a given file with a specified loss fraction.
23
24
 
24
25
  .. code-block:: console
25
26
 
26
- simtools-production-derive-corsika-limits\\
27
- --event_data_file path/to/event_data_file.hdf5 \\
27
+ simtools-production-derive-corsika-limits \\
28
+ --event_data_files path/to/event_data_files.yaml \\
29
+ --telescope_ids path/to/telescope_configs.yaml \\
28
30
  --loss_fraction 1e-6 \\
29
- --telescope_ids 1 2 3
31
+ --plot_histograms \\
32
+ --output_file corsika_simulation_limits_lookup.ecsv
30
33
  """
31
34
 
35
+ import datetime
32
36
  import logging
33
37
 
38
+ from astropy.table import Table
39
+
34
40
  import simtools.utils.general as gen
35
41
  from simtools.configuration import configurator
42
+ from simtools.data_model.metadata_collector import MetadataCollector
43
+ from simtools.io_operations import io_handler
36
44
  from simtools.production_configuration.derive_corsika_limits import LimitCalculator
37
45
 
38
46
  _logger = logging.getLogger(__name__)
@@ -44,63 +52,188 @@ def _parse():
44
52
 
45
53
  Parameters
46
54
  ----------
47
- event_data_file: str
48
- The event data file.
55
+ event_data_files: str
56
+ Path to a file listing event data file paths. These files contain the
57
+ simulation data used for deriving the limits.
49
58
  loss_fraction: float
50
- Loss fraction of events for limit derivation.
51
- telescope_ids: list of int, optional
52
- List of telescope IDs to filter the events (default is None).
53
- Definition of the telescope IDs can be found in the telescope
54
- definition file used for simulations.
59
+ Fraction of events to be excluded during limit computation. Determines
60
+ thresholds for energy, radial distance, and viewcone.
61
+ telescope_ids: str
62
+ Path to a file defining telescope configurations. Specifies telescope
63
+ arrays or IDs used to filter events during processing.
64
+ plot_histograms: bool
65
+ If True, generates and saves histograms of the event data to visualize
66
+ the computed limits and distributions.
55
67
 
56
68
  Returns
57
69
  -------
58
70
  CommandLineParser
59
71
  Command line parser object
60
-
61
72
  """
62
73
  config = configurator.Configurator(
63
74
  description="Derive limits for energy, radial distance, and viewcone."
64
75
  )
65
76
  config.parser.add_argument(
66
- "--event_data_file",
77
+ "--event_data_files",
78
+ type=str,
79
+ required=True,
80
+ help="Path to a file containing event data file paths.",
81
+ )
82
+ config.parser.add_argument(
83
+ "--telescope_ids",
67
84
  type=str,
68
85
  required=True,
69
- help="Path to the event data file containing the event data.",
86
+ help="Path to a file containing telescope configurations.",
70
87
  )
71
88
  config.parser.add_argument(
72
89
  "--loss_fraction", type=float, required=True, help="Fraction of events to be lost."
73
90
  )
74
91
  config.parser.add_argument(
75
- "--telescope_ids",
76
- type=int,
77
- nargs="*",
78
- help="List of telescope IDs to filter the events as used in sim_telarray.",
92
+ "--plot_histograms",
93
+ help="Plot histograms of the event data.",
94
+ action="store_true",
95
+ default=False,
96
+ )
97
+ config.parser.add_argument(
98
+ "--output_file",
99
+ type=str,
100
+ default="corsika_simulation_limits_lookup.ecsv",
101
+ help="Output file for the derived limits (default: "
102
+ "'corsika_simulation_limits_lookup.ecsv').",
79
103
  )
80
104
  return config.initialize(db_config=False)
81
105
 
82
106
 
83
- def main():
84
- """Derive limits for energy, radial distance, and viewcone."""
85
- args_dict, _ = _parse()
86
-
87
- logger = logging.getLogger()
88
- logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
107
+ def process_file(file_path, telescope_ids, loss_fraction, plot_histograms):
108
+ """
109
+ Process a single file and compute limits.
89
110
 
90
- event_data_file_path = args_dict["event_data_file"]
91
- loss_fraction = args_dict["loss_fraction"]
92
- telescope_ids = args_dict.get("telescope_ids")
111
+ Parameters
112
+ ----------
113
+ file_path : str
114
+ Path to the event data file.
115
+ telescope_ids : list[int]
116
+ List of telescope IDs to filter the events.
117
+ loss_fraction : float
118
+ Fraction of events to be lost.
119
+ plot_histograms : bool
120
+ Whether to plot histograms.
93
121
 
94
- calculator = LimitCalculator(event_data_file_path, telescope_list=telescope_ids)
122
+ Returns
123
+ -------
124
+ dict
125
+ Dictionary containing the computed limits.
126
+ """
127
+ calculator = LimitCalculator(file_path, telescope_list=telescope_ids)
95
128
 
96
129
  lower_energy_limit = calculator.compute_lower_energy_limit(loss_fraction)
97
- _logger.info(f"Lower energy threshold: {lower_energy_limit}")
98
-
99
130
  upper_radial_distance = calculator.compute_upper_radial_distance(loss_fraction)
100
- _logger.info(f"Upper radius threshold: {upper_radial_distance}")
101
-
102
131
  viewcone = calculator.compute_viewcone(loss_fraction)
103
- _logger.info(f"Viewcone radius: {viewcone}")
132
+
133
+ if plot_histograms:
134
+ _logger.info(
135
+ f"Plotting histograms written to {io_handler.IOHandler().get_output_directory()}"
136
+ )
137
+ calculator.plot_data(
138
+ lower_energy_limit,
139
+ upper_radial_distance,
140
+ viewcone,
141
+ io_handler.IOHandler().get_output_directory(),
142
+ )
143
+
144
+ return {
145
+ "file_path": file_path,
146
+ "telescope_ids": telescope_ids,
147
+ "lower_energy_threshold": lower_energy_limit,
148
+ "upper_radius_threshold": upper_radial_distance,
149
+ "viewcone_radius": viewcone,
150
+ }
151
+
152
+
153
+ def create_results_table(results, loss_fraction):
154
+ """
155
+ Create an Astropy Table from the results.
156
+
157
+ Parameters
158
+ ----------
159
+ results : list[dict]
160
+ List of dictionaries containing the computed limits for each file
161
+ and telescope configuration.
162
+ loss_fraction : float
163
+ Fraction of events to be lost, added as metadata to the table.
164
+
165
+ Returns
166
+ -------
167
+ astropy.table.Table
168
+ An Astropy Table containing the results with appropriate units and metadata.
169
+ """
170
+ table = Table(
171
+ rows=[
172
+ (
173
+ res["file_path"],
174
+ res["telescope_ids"],
175
+ res["lower_energy_threshold"],
176
+ res["upper_radius_threshold"],
177
+ res["viewcone_radius"],
178
+ )
179
+ for res in results
180
+ ],
181
+ names=[
182
+ "file_path",
183
+ "telescope_ids",
184
+ "lower_energy_threshold",
185
+ "upper_radius_threshold",
186
+ "viewcone_radius",
187
+ ],
188
+ )
189
+
190
+ table["lower_energy_threshold"].unit = "TeV"
191
+ table["upper_radius_threshold"].unit = "m"
192
+ table["viewcone_radius"].unit = "deg"
193
+
194
+ table.meta["created"] = datetime.datetime.now().isoformat()
195
+ table.meta["description"] = (
196
+ "Lookup table for CORSIKA limits computed from gamma-ray shower simulations."
197
+ )
198
+ table.meta["loss_fraction"] = loss_fraction
199
+
200
+ return table
201
+
202
+
203
+ def main():
204
+ """Derive limits for energy, radial distance, and viewcone."""
205
+ args_dict, _ = _parse()
206
+
207
+ logger = logging.getLogger()
208
+ logger.setLevel(gen.get_log_level_from_user(args_dict.get("log_level", "info")))
209
+
210
+ event_data_files = gen.collect_data_from_file(args_dict["event_data_files"])["files"]
211
+ telescope_configs = gen.collect_data_from_file(args_dict["telescope_ids"])["telescope_configs"]
212
+
213
+ results = []
214
+ for file_path in event_data_files:
215
+ for array_name, telescope_ids in telescope_configs.items():
216
+ _logger.info(f"Processing file: {file_path} with telescope config: {array_name}")
217
+ result = process_file(
218
+ file_path,
219
+ telescope_ids,
220
+ args_dict["loss_fraction"],
221
+ args_dict["plot_histograms"],
222
+ )
223
+ result["layout"] = array_name
224
+ results.append(result)
225
+
226
+ table = create_results_table(results, args_dict["loss_fraction"])
227
+
228
+ output_dir = io_handler.IOHandler().get_output_directory("corsika_limits")
229
+ output_file = f"{output_dir}/{args_dict['output_file']}"
230
+
231
+ table.write(output_file, format="ascii.ecsv", overwrite=True)
232
+ _logger.info(f"Results saved to {output_file}")
233
+
234
+ metadata_file = f"{output_dir}/metadata.yml"
235
+ MetadataCollector.dump(args_dict, metadata_file)
236
+ _logger.info(f"Metadata saved to {metadata_file}")
104
237
 
105
238
 
106
239
  if __name__ == "__main__":
@@ -4,8 +4,8 @@ r"""
4
4
  Application to run the StatisticalErrorEvaluator and interpolate results.
5
5
 
6
6
  This application evaluates statistical uncertainties from DL2 MC event files
7
- based on input parameters like zenith angles and offsets, and can perform interpolation
8
- for a specified grid point.
7
+ based on input parameters like zenith angles and offsets, and performs interpolation
8
+ for a specified query point.
9
9
 
10
10
  Command line arguments
11
11
  ----------------------
@@ -15,10 +15,20 @@ zeniths (list of int, required)
15
15
  List of zenith angles to consider.
16
16
  offsets (list of int, required)
17
17
  List of offsets in degrees.
18
- interpolate (bool, optional)
19
- If set, performs interpolation for a specific grid point.
20
- query_point (list of int, optional)
21
- Grid point for interpolation (energy, azimuth, zenith, NSB, offset).
18
+ query_point (list of float, required)
19
+ Query point for interpolation. The query point must contain exactly 5 values:
20
+ - Energy (TeV)
21
+ - Azimuth (degrees)
22
+ - Zenith (degrees)
23
+ - NSB (MHz)
24
+ - Offset (degrees)
25
+ output_file (str, optional)
26
+ Output file to store the results. Default: 'interpolated_scaled_events.json'.
27
+ metrics_file (str, optional)
28
+ Path to the metrics definition file. Default: 'production_simulation_config_metrics.yml'.
29
+ file_name_template (str, optional)
30
+ Template for the file name. Default:
31
+ 'prod6_LaPalma-{zenith}deg_gamma_cone.N.Am-4LSTs09MSTs_ID0_reduced.fits'.
22
32
 
23
33
  Example
24
34
  -------
@@ -26,14 +36,16 @@ To evaluate statistical uncertainties and perform interpolation, run the command
26
36
 
27
37
  .. code-block:: console
28
38
 
29
- simtools-production-scale-events --base_path tests/resources/production_dl2_fits/ \
30
- --zeniths 20 52 40 60 --offsets 0 --interpolate --query_point 1 180 30 0 0 \
31
- --metrics_file "path/to/metrics.yaml"
39
+ simtools-production-scale-events --base_path tests/resources/production_dl2_fits/ \\
40
+ --zeniths 20 40 52 60 --offsets 0 --query_point 1 180 30 0 0 \\
41
+ --metrics_file "path/to/metrics.yaml" \\
42
+ --output_file "output.json"
32
43
 
33
-
34
- The output will display the scaled events for the specified grid point.
44
+ The output will display the scaled events for the specified query point and save
45
+ the results to the specified output file.
35
46
  """
36
47
 
48
+ import itertools
37
49
  import json
38
50
  import logging
39
51
  from pathlib import Path
@@ -69,33 +81,47 @@ def _parse(label, description):
69
81
  help="Path to the DL2 MC event files for interpolation.",
70
82
  )
71
83
  config.parser.add_argument(
72
- "--zeniths", nargs="+", type=CommandLineParser.zenith_angle, help="List of zenith angles."
84
+ "--zeniths",
85
+ required=True,
86
+ nargs="+",
87
+ type=CommandLineParser.zenith_angle,
88
+ help="List of zenith angles.",
73
89
  )
74
90
  config.parser.add_argument(
75
- "--offsets", nargs="+", type=float, help="List of offsets in degrees."
91
+ "--offsets", required=True, nargs="+", type=float, help="List of offsets in degrees."
76
92
  )
77
93
 
78
- config.parser.add_argument(
79
- "--interpolate", action="store_true", help="Interpolate results for a specific grid point."
80
- )
81
94
  config.parser.add_argument(
82
95
  "--query_point",
96
+ required=True,
83
97
  nargs=5,
84
98
  type=float,
85
99
  help="Grid point for interpolation (energy, azimuth, zenith, NSB, offset).",
86
100
  )
87
101
  config.parser.add_argument(
88
102
  "--output_file",
103
+ required=False,
89
104
  type=str,
90
105
  default="interpolated_scaled_events.json",
91
106
  help="Output file to store the results. (default: 'interpolated_scaled_events.json').",
92
107
  )
93
108
  config.parser.add_argument(
94
109
  "--metrics_file",
110
+ required=False,
95
111
  type=str,
96
112
  default="production_simulation_config_metrics.yml",
97
113
  help="Metrics definition file. (default: production_simulation_config_metrics.yml)",
98
114
  )
115
+ config.parser.add_argument(
116
+ "--file_name_template",
117
+ required=False,
118
+ type=str,
119
+ default=("prod6_LaPalma-{zenith}deg_gamma_cone.N.Am-4LSTs09MSTs_ID0_reduced.fits"),
120
+ help=(
121
+ "Template for the file name. (default: "
122
+ "'prod6_LaPalma-{zenith}deg_gamma_cone.N.Am-4LSTs09MSTs_ID0_reduced.fits')"
123
+ ),
124
+ )
99
125
  return config.initialize(db_config=False)
100
126
 
101
127
 
@@ -115,27 +141,25 @@ def main():
115
141
 
116
142
  evaluator_instances = []
117
143
 
118
- metrics = (
119
- gen.collect_data_from_file(args_dict["metrics_file"]) if "metrics_file" in args_dict else {}
120
- )
144
+ metrics = gen.collect_data_from_file(args_dict["metrics_file"])
121
145
 
122
146
  if args_dict["base_path"] and args_dict["zeniths"] and args_dict["offsets"]:
123
- for zenith in args_dict["zeniths"]:
124
- for offset in args_dict["offsets"]:
125
- # Build file path based on base_path, zenith, and offset
126
- file_name = f"prod6_LaPalma-{int(zenith.value)}deg_"
127
- file_name += "gamma_cone.N.Am-4LSTs09MSTs_ID0_reduced.fits"
128
- file_path = Path(args_dict["base_path"]).joinpath(file_name)
129
-
130
- evaluator = StatisticalErrorEvaluator(
131
- file_path,
132
- file_type="Gamma-cone",
133
- metrics=metrics,
134
- grid_point=(1 * u.TeV, 180 * u.deg, zenith, 0, offset * u.deg),
135
- )
136
-
137
- evaluator.calculate_metrics()
138
- evaluator_instances.append(evaluator)
147
+ for zenith, offset in itertools.product(args_dict["zeniths"], args_dict["offsets"]):
148
+ file_name = args_dict["file_name_template"].format(zenith=int(zenith.value))
149
+ file_path = Path(args_dict["base_path"]).joinpath(file_name)
150
+
151
+ if not file_path.exists():
152
+ logger.warning(f"File not found: {file_path}. Skipping.")
153
+ continue
154
+
155
+ evaluator = StatisticalErrorEvaluator(
156
+ file_path,
157
+ file_type="Gamma-cone",
158
+ metrics=metrics,
159
+ grid_point=(1 * u.TeV, 180 * u.deg, zenith, 0, offset * u.deg),
160
+ )
161
+ evaluator.calculate_metrics()
162
+ evaluator_instances.append(evaluator)
139
163
 
140
164
  else:
141
165
  logger.warning("No files read")
@@ -143,7 +167,6 @@ def main():
143
167
  logger.warning(f"Zeniths: {args_dict['zeniths']}")
144
168
  logger.warning(f"Offsets: {args_dict['offsets']}")
145
169
 
146
- # Perform interpolation for the given query point
147
170
  interpolation_handler = InterpolationHandler(evaluator_instances, metrics=metrics)
148
171
  query_points = np.array([args_dict["query_point"]])
149
172
  scaled_events = interpolation_handler.interpolate(query_points)
@@ -1,12 +1,30 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  """
4
- Run simtools applications from configuration files for setting workflows.
4
+ Run several simtools applications using a configuration file.
5
5
 
6
6
  Allows to run several simtools applications with a single configuration file, which includes
7
7
  both the name of the simtools application and the configuration for the application.
8
8
 
9
- Strong assumption on the directory structure for input and output files of applications.
9
+ This application is used for model parameter setting workflows.
10
+ Strong assumptions are applied on the directory structure for input and output files of
11
+ applications.
12
+
13
+ Example
14
+ -------
15
+
16
+ Run the application with the configuration file 'config_file_name':
17
+
18
+ .. code-block:: console
19
+
20
+ simtools-run-application --configuration_file config_file_name
21
+
22
+ Run the application with the configuration file 'config_file_name', but skipping all steps except
23
+ step 2 and 3 (useful for debugging):
24
+
25
+ .. code-block:: console
26
+
27
+ simtools-run-application --configuration_file config_file_name --steps 2 3
10
28
 
11
29
  """
12
30
 
@@ -49,6 +67,12 @@ def _parse(label, description, usage):
49
67
  required=True,
50
68
  default=None,
51
69
  )
70
+ config.parser.add_argument(
71
+ "--steps",
72
+ type=int,
73
+ nargs="+",
74
+ help="List of steps to be execution (e.g., '--steps 7 8 9'; do not specify to run all).",
75
+ )
52
76
  return config.initialize(db_config=True)
53
77
 
54
78
 
@@ -81,7 +105,7 @@ def get_subdirectory_name(path):
81
105
  raise ValueError(f"Could not find subdirectory under 'input': {exc}") from exc
82
106
 
83
107
 
84
- def read_application_configuration(configuration_file, logger):
108
+ def read_application_configuration(configuration_file, steps, logger):
85
109
  """
86
110
  Read application configuration from file and modify for setting workflows.
87
111
 
@@ -97,6 +121,8 @@ def read_application_configuration(configuration_file, logger):
97
121
  ----------
98
122
  configuration_file : str
99
123
  Configuration file name.
124
+ steps : list
125
+ List of steps to be executed (None: all steps).
100
126
  logger : Logger
101
127
  Logger object.
102
128
 
@@ -111,20 +137,20 @@ def read_application_configuration(configuration_file, logger):
111
137
  application_config = gen.collect_data_from_file(configuration_file).get("CTA_SIMPIPE")
112
138
  place_holder = "__SETTING_WORKFLOW__"
113
139
  workflow_dir, setting_workflow = get_subdirectory_name(configuration_file)
114
- output_path = (
115
- workflow_dir.with_name(workflow_dir.name.replace("input", "output")) / setting_workflow
116
- )
140
+ output_path = Path(str(workflow_dir).replace("input", "output")) / Path(setting_workflow)
117
141
  output_path.mkdir(parents=True, exist_ok=True)
118
142
  logger.info(f"Setting workflow output path to {output_path}")
119
143
  log_file = output_path / "simtools.log"
120
144
  configurations = application_config.get("APPLICATIONS")
121
- for config in configurations:
145
+ for step_count, config in enumerate(configurations, start=1):
146
+ config["RUN_APPLICATION"] = step_count in steps if steps else True
122
147
  for key, value in config.get("CONFIGURATION", {}).items():
123
148
  if isinstance(value, str):
124
149
  config["CONFIGURATION"][key] = value.replace(place_holder, setting_workflow)
125
150
  if isinstance(value, list):
126
151
  config["CONFIGURATION"][key] = [
127
- item.replace(place_holder, setting_workflow) for item in value
152
+ item.replace(place_holder, setting_workflow) if isinstance(item, str) else item
153
+ for item in value
128
154
  ]
129
155
  config["CONFIGURATION"]["USE_PLAIN_OUTPUT_PATH"] = True
130
156
  config["CONFIGURATION"]["OUTPUT_PATH"] = str(output_path)
@@ -135,21 +161,25 @@ def read_application_configuration(configuration_file, logger):
135
161
  def main(): # noqa: D103
136
162
  args_dict, db_config = _parse(
137
163
  Path(__file__).stem,
138
- description="Run simtools applications from configuration file.",
164
+ description="Run simtools applications using a configuration file.",
139
165
  usage="simtools-run-application --config_file config_file_name",
140
166
  )
141
167
  logger = logging.getLogger()
142
168
  logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
143
169
 
144
170
  configurations, log_file = read_application_configuration(
145
- args_dict["configuration_file"], logger
171
+ args_dict["configuration_file"], args_dict["steps"], logger
146
172
  )
147
173
 
148
174
  with log_file.open("w", encoding="utf-8") as file:
149
175
  file.write("Running simtools applications\n")
150
176
  file.write(dependencies.get_version_string(db_config))
151
177
  for config in configurations:
152
- logger.info(f"Running application: {config.get('APPLICATION')}")
178
+ if config.get("RUN_APPLICATION"):
179
+ logger.info(f"Running application: {config.get('APPLICATION')}")
180
+ else:
181
+ logger.info(f"Skipping application: {config.get('APPLICATION')}")
182
+ continue
153
183
  config = gen.change_dict_keys_case(config, False)
154
184
  stdout, stderr = run_application(
155
185
  config.get("APPLICATION"), config.get("CONFIGURATION"), logger