gammasimtools 0.25.0__py3-none-any.whl → 0.27.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 (138) hide show
  1. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/METADATA +6 -1
  2. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/RECORD +135 -130
  3. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/WHEEL +1 -1
  4. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/entry_points.txt +3 -2
  5. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/licenses/LICENSE +1 -1
  6. simtools/_version.py +2 -2
  7. simtools/application_control.py +35 -7
  8. simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
  9. simtools/applications/db_add_file_to_db.py +1 -1
  10. simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
  11. simtools/applications/db_add_value_from_json_to_db.py +1 -1
  12. simtools/applications/db_generate_compound_indexes.py +1 -1
  13. simtools/applications/db_get_array_layouts_from_db.py +3 -7
  14. simtools/applications/db_get_file_from_db.py +1 -1
  15. simtools/applications/db_get_parameter_from_db.py +1 -1
  16. simtools/applications/db_inspect_databases.py +1 -1
  17. simtools/applications/db_upload_model_repository.py +1 -1
  18. simtools/applications/derive_ctao_array_layouts.py +1 -2
  19. simtools/applications/{calculate_incident_angles.py → derive_incident_angle.py} +16 -18
  20. simtools/applications/derive_mirror_rnda.py +112 -180
  21. simtools/applications/derive_psf_parameters.py +0 -1
  22. simtools/applications/derive_pulse_shape_parameters.py +0 -1
  23. simtools/applications/derive_trigger_rates.py +1 -1
  24. simtools/applications/docs_produce_array_element_report.py +2 -8
  25. simtools/applications/docs_produce_calibration_reports.py +1 -3
  26. simtools/applications/docs_produce_model_parameter_reports.py +0 -2
  27. simtools/applications/docs_produce_simulation_configuration_report.py +1 -3
  28. simtools/applications/generate_array_config.py +0 -1
  29. simtools/applications/generate_corsika_histograms.py +79 -229
  30. simtools/applications/generate_regular_arrays.py +76 -69
  31. simtools/applications/generate_simtel_event_data.py +2 -2
  32. simtools/applications/maintain_simulation_model_add_production.py +2 -2
  33. simtools/applications/maintain_simulation_model_write_array_element_positions.py +87 -0
  34. simtools/applications/plot_array_layout.py +5 -111
  35. simtools/applications/plot_simulated_event_distributions.py +57 -0
  36. simtools/applications/plot_tabular_data.py +0 -1
  37. simtools/applications/plot_tabular_data_for_model_parameter.py +1 -6
  38. simtools/applications/production_derive_corsika_limits.py +1 -1
  39. simtools/applications/production_generate_grid.py +0 -1
  40. simtools/applications/run_application.py +1 -1
  41. simtools/applications/simulate_flasher.py +3 -15
  42. simtools/applications/simulate_illuminator.py +2 -11
  43. simtools/applications/simulate_pedestals.py +1 -5
  44. simtools/applications/simulate_prod.py +8 -11
  45. simtools/applications/simulate_prod_htcondor_generator.py +1 -1
  46. simtools/applications/submit_array_layouts.py +2 -4
  47. simtools/applications/submit_data_from_external.py +2 -1
  48. simtools/applications/submit_model_parameter_from_external.py +1 -3
  49. simtools/applications/validate_camera_efficiency.py +28 -28
  50. simtools/applications/validate_camera_fov.py +0 -1
  51. simtools/applications/validate_cumulative_psf.py +1 -5
  52. simtools/applications/validate_optics.py +2 -14
  53. simtools/atmosphere.py +83 -0
  54. simtools/camera/camera_efficiency.py +171 -53
  55. simtools/camera/single_photon_electron_spectrum.py +8 -7
  56. simtools/configuration/commandline_parser.py +82 -11
  57. simtools/configuration/configurator.py +6 -11
  58. simtools/constants.py +5 -0
  59. simtools/corsika/corsika_config.py +100 -202
  60. simtools/corsika/corsika_histograms.py +561 -1708
  61. simtools/corsika/primary_particle.py +1 -1
  62. simtools/data_model/metadata_collector.py +5 -2
  63. simtools/data_model/metadata_model.py +0 -4
  64. simtools/data_model/model_data_writer.py +59 -64
  65. simtools/data_model/schema.py +2 -0
  66. simtools/data_model/validate_data.py +1 -3
  67. simtools/db/db_handler.py +23 -10
  68. simtools/db/mongo_db.py +2 -2
  69. simtools/dependencies.py +81 -38
  70. simtools/io/ascii_handler.py +55 -5
  71. simtools/io/io_handler.py +23 -12
  72. simtools/io/table_handler.py +1 -1
  73. simtools/job_execution/job_manager.py +154 -79
  74. simtools/job_execution/process_pool.py +137 -0
  75. simtools/layout/array_layout.py +4 -13
  76. simtools/layout/array_layout_utils.py +348 -57
  77. simtools/model/array_model.py +23 -63
  78. simtools/model/calibration_model.py +4 -8
  79. simtools/model/legacy_model_parameter.py +134 -0
  80. simtools/model/model_parameter.py +147 -86
  81. simtools/model/model_utils.py +40 -6
  82. simtools/model/site_model.py +4 -8
  83. simtools/model/telescope_model.py +10 -16
  84. simtools/production_configuration/derive_corsika_limits.py +6 -11
  85. simtools/production_configuration/interpolation_handler.py +16 -16
  86. simtools/ray_tracing/incident_angles.py +92 -17
  87. simtools/ray_tracing/mirror_panel_psf.py +338 -222
  88. simtools/ray_tracing/psf_analysis.py +62 -48
  89. simtools/ray_tracing/psf_parameter_optimisation.py +3 -3
  90. simtools/ray_tracing/ray_tracing.py +43 -25
  91. simtools/reporting/docs_auto_report_generator.py +8 -13
  92. simtools/reporting/docs_read_parameters.py +2 -8
  93. simtools/runners/corsika_runner.py +52 -195
  94. simtools/runners/corsika_simtel_runner.py +77 -108
  95. simtools/runners/runner_services.py +214 -213
  96. simtools/runners/simtel_runner.py +27 -160
  97. simtools/runners/simtools_runner.py +11 -73
  98. simtools/schemas/application_workflow.metaschema.yml +8 -0
  99. simtools/settings.py +173 -0
  100. simtools/{io/eventio_handler.py → sim_events/file_info.py} +3 -3
  101. simtools/{simtel/simtel_io_event_histograms.py → sim_events/histograms.py} +25 -15
  102. simtools/{simtel/simtel_io_event_reader.py → sim_events/reader.py} +20 -17
  103. simtools/{simtel/simtel_io_event_writer.py → sim_events/writer.py} +84 -25
  104. simtools/simtel/pulse_shapes.py +7 -2
  105. simtools/simtel/simtel_config_writer.py +79 -91
  106. simtools/simtel/simtel_seeds.py +184 -0
  107. simtools/simtel/simtel_table_reader.py +6 -4
  108. simtools/simtel/simulator_array.py +114 -109
  109. simtools/simtel/simulator_camera_efficiency.py +68 -46
  110. simtools/simtel/simulator_light_emission.py +164 -132
  111. simtools/simtel/simulator_ray_tracing.py +80 -71
  112. simtools/simulator.py +137 -355
  113. simtools/telescope_trigger_rates.py +3 -4
  114. simtools/testing/assertions.py +84 -33
  115. simtools/testing/configuration.py +1 -2
  116. simtools/testing/helpers.py +2 -3
  117. simtools/testing/log_inspector.py +1 -0
  118. simtools/testing/sim_telarray_metadata.py +14 -12
  119. simtools/testing/validate_output.py +121 -42
  120. simtools/utils/general.py +43 -17
  121. simtools/utils/geometry.py +0 -77
  122. simtools/utils/names.py +5 -5
  123. simtools/utils/random.py +36 -0
  124. simtools/visualization/legend_handlers.py +7 -6
  125. simtools/visualization/plot_array_layout.py +91 -16
  126. simtools/visualization/plot_corsika_histograms.py +145 -605
  127. simtools/visualization/plot_incident_angles.py +48 -1
  128. simtools/visualization/plot_mirrors.py +1 -4
  129. simtools/visualization/plot_pixels.py +2 -4
  130. simtools/visualization/plot_psf.py +160 -19
  131. simtools/visualization/plot_simtel_event_histograms.py +4 -4
  132. simtools/visualization/plot_simtel_events.py +6 -11
  133. simtools/visualization/plot_tables.py +8 -19
  134. simtools/visualization/visualize.py +22 -2
  135. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +0 -160
  136. simtools/applications/print_version.py +0 -53
  137. simtools/io/hdf5_handler.py +0 -139
  138. {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/top_level.txt +0 -0
@@ -1,174 +1,78 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  r"""
4
- Generates a set of histograms Cherenkov photon distributions from CORSIKA output.
4
+ Generates a set of histograms with Cherenkov photon distributions from CORSIKA output.
5
5
 
6
6
  The Cherenkov photons (from observation level) are read from a CORSIKA IACT
7
- output file provided as input.
8
-
9
- The histograms can be saved both into pdfs and in a hdf5 file.
7
+ output file(s) provided as input.
10
8
 
11
9
  The following 2D histograms are generated:
12
- - Number of Cherenkov photons on the ground;
13
- - Density of Cherenkov photons on the ground;
14
- - Incoming direction (directive cosines) of the Cherenkov photons;
15
- - Time of arrival (ns) vs altitude of production (km);
16
- - Number of Cherenkov photons per event per telescope.
10
+
11
+ - Density of Cherenkov photons on the ground
12
+ - Incoming direction (directive cosines) of the Cherenkov photons
13
+ - Time of arrival (ns) vs altitude of production (km)
17
14
 
18
15
  The following 1D histograms are generated:
19
- - Wavelength;
20
- - Counts;
21
- - Density;
22
- - Time of arrival;
23
- - Altitude of production;
24
- - Number of photons per telescope;
25
- - Number of photons per event.
26
16
 
27
- Histograms for the distribution of CORSIKA event header elements can also be generated by using
28
- the --event_1d_histograms and --event_2d_histograms arguments. The accepted arguments (keys)
29
- are to be found in the CORSIKA manual, e.g., "total_energy", "zenith", "azimuth".
17
+ - Wavelength distribution of Cherenkov photons
18
+ - Time of arrival (ns) distribution of Cherenkov photons
19
+ - Altitude of production (km) distribution of Cherenkov photons
20
+ - Lateral distribution of Cherenkov photons (distance from shower core in m)
30
21
 
31
22
  Command line arguments
32
23
  ----------------------
33
- iact_file (str, required)
34
- The name of the CORSIKA IACT file resulted from the CORSIKA simulation.
35
-
36
- telescope_indices (list, optional)
37
- The list with the telescope indices to be considered in the generation of the histograms.
38
- Telescopes that are not in the list will not contribute with photons to the histograms.
39
- If the argument is not given, all telescopes are considered.
40
-
41
- individual_telescopes (bool, optional)
42
- Indicates whether single histograms are generated for the individual telescopes, or if
43
- a master histogram is generated for all the telescopes together.
44
- If the argument is not given, the Cherenkov photons from the given telescopes are considered
45
- together in the same histograms.
46
-
47
- hist_config (hdf5 or dict, optional)
48
- The configuration used for generating the histograms.
49
- It includes information about the bin sizes, the ranges, scale of the plot and units.
50
- By construction, three major histograms are created to start with:
51
- - hist_direction (2D): Directive cosines (x and y) for the incoming photons;
52
- - hist_position (3D): position x, position y, and wavelength;
53
- - hist_time_altitude (2D): time of arrival and altitude of emission;
54
-
55
- If the argument is not given, the default configuration is generated:
56
-
57
- .. code-block:: console
58
-
59
- hist_direction:
60
- x axis: {bins: 100, scale: linear, start: -1, stop: 1}
61
- y axis: {bins: 100, scale: linear, start: -1, stop: 1}
62
-
63
- hist_position:
64
- x axis:
65
- bins: 100
66
- scale: linear
67
- start: !astropy.units.Quantity
68
- unit: &id001 m
69
- value: -1000.0
70
- stop: &id002 !astropy.units.Quantity
71
- unit: *id001
72
- value: 1000.0
73
- y axis:
74
- bins: 100
75
- scale: linear
76
- start: !astropy.units.Quantity
77
- unit: *id001
78
- value: -1000.0
79
- stop: *id002
80
- z axis:
81
- bins: 80
82
- scale: linear
83
- start: !astropy.units.Quantity
84
- unit: nm
85
- value: 200.0
86
- stop: !astropy.units.Quantity
87
- unit: *id003
88
- value: 1000.0
89
- hist_time_altitude:
90
- x axis:
91
- bins: 100
92
- scale: linear
93
- start: !astropy.units.Quantity
94
- unit: ns
95
- value: -2000.0
96
- stop: !astropy.units.Quantity
97
- unit: *id004
98
- value: 2000.0
99
- y axis:
100
- bins: 100
101
- scale: linear
102
- start: !astropy.units.Quantity
103
- unit: km
104
- value: 120.0
105
- stop: !astropy.units.Quantity
106
- unit: *id005
107
- value: 0.0
108
-
109
-
110
- pdf (bool, optional)
111
- If set, histograms are saved into pdf files.
112
- One pdf file contains all the histograms for the Cherenkov photons.
113
- The name of the file is controlled via hdf5_file_name.
114
- If event_1d_histograms and event_2d_histograms are used, two separate pdf files might be
115
- created to accommodate the histograms for the CORSIKA event header elements. The core names
116
- of these output pdf files are also given by hdf5_file_name argument with the addition of
117
- 'event_1d_histograms' and 'event_2d_histograms'.
118
-
24
+ input_files (str, required)
25
+ The name(s) of the CORSIKA IACT file(s) resulted from the CORSIKA simulation.
119
26
 
120
- hdf5 (bool, optional)
121
- If set, histograms are saved into hdf5 files.
27
+ pdf_file_name (str, optional)
28
+ The name of the output pdf file to save the histograms. If not provided,
29
+ the histograms are only shown on screen.
122
30
 
123
- hdf5_file_name (str, optional)
124
- The name of the output hdf5 data (without the path).
125
- It requires the --hdf5 flag.
126
- If not given, hdf5_file_name takes the name from the input IACT file (input_file).
127
- If the output hdf5_file_name file already exists, the tables associated to the chosen
128
- flags (e.g. hdf5, event_1d_histograms, event_2d_histograms) will be overwritten. The
129
- remaining tables, if any, will stay untouched.
130
-
131
-
132
- event_1d_histograms (str, optional)
133
- Generate 1D histograms for elements given in --event_1d_histograms from the CORSIKA event
134
- header and save into hdf5/pdf files.
135
- It allows more than one argument, separated by simple spaces.
136
- Usage: --event_1d_histograms first_interaction_height total_energy.
137
-
138
- event_2d_histograms (str, optional)
139
- Generate 2D histograms for elements given in --event_2d_histograms from the CORSIKA event
140
- header and save into hdf5/pdf files.
141
- It allows more than one argument, separated by simple spaces.
142
- The elements are grouped into pairs and the 2D histograms are generated always for two
143
- subsequent elements.
144
- For example, --event_2d_histograms first_interaction_height total_energy zenith azimuth
145
- will generate one 2D histogram for first_interaction_height total_energy and another 2D
146
- histogram for zenith and azimuth.
31
+ file_labels (str, optional)
32
+ Labels for the input files (in the same order as input_files). If not provided,
33
+ the file names are used as labels.
147
34
 
148
35
  Example
149
36
  -------
150
- Generate the histograms for a test IACT file:
37
+ Fill and plot histograms for a test IACT file:
151
38
 
152
39
  .. code-block:: console
153
40
 
154
- simtools-generate-corsika-histograms --iact_file /workdir/external/simtools/\\
41
+ simtools-generate-corsika-histograms --input_files /workdir/external/simtools/\\
155
42
  tests/resources/tel_output_10GeV-2-gamma-20deg-CTAO-South.corsikaio \\
156
- --pdf --hdf5 \\
157
- --event_2d_histograms zenith azimuth --event_1d_histograms total_energy
43
+ --pdf_file_name test.pdf
44
+
45
+ Fill and plot histograms for several files:
46
+
47
+ .. code-block:: console
158
48
 
159
- Expected final print-out message:
49
+ simtools-generate-corsika-histograms --input_files file1 file 2 \\
50
+ --file_lablels label1 label2 \\
51
+ --pdf_file_name test.pdf
160
52
 
161
- .. code-block:: console
53
+ Notes
54
+ -----
55
+ The typical use case of this application is to generate lateral photon density distribution
56
+ to compare different CORSIKA simulation settings or different CORSIKA versions. The following
57
+ steps are recommended:
162
58
 
163
- INFO::generate_corsika_histograms(l358)::main::Finalizing the application.
164
- Total time needed: 8s.
59
+ - generate a 'star'-like array of telescopes with the 'simtools-generate-regular-arrays'
60
+ application. There should be a sufficient number of telescopes (e.g. 50 or more) in the
61
+ layout with non-overlapping telescope definitions
62
+
63
+ - run CORSIKA simulations with the desired settings using this telescope layout (use the
64
+ 'overwrite_model_parameters' option to point to the generated layout simulation model
65
+ change file (in the format given by 'simulation_models_info.schema.yml').
66
+
67
+ - run this application to generate the histograms for the produced CORSIKA IACT output
165
68
  """
166
69
 
167
- import time
70
+ from astropy import units as u
168
71
 
169
72
  from simtools.application_control import get_application_label, startup_application
170
73
  from simtools.configuration import configurator
171
74
  from simtools.corsika.corsika_histograms import CorsikaHistograms
75
+ from simtools.visualization import plot_corsika_histograms
172
76
 
173
77
 
174
78
  def _parse():
@@ -177,117 +81,63 @@ def _parse():
177
81
  label=get_application_label(__file__),
178
82
  description="Generate histograms for the Cherenkov photons saved in the CORSIKA IACT file.",
179
83
  )
180
-
181
84
  config.parser.add_argument(
182
- "--iact_file",
183
- help="Name of the CORSIKA IACT file from which to generate the histograms.",
85
+ "--input_files",
86
+ help="Name(s) of the CORSIKA IACT file(s) to process",
184
87
  type=str,
88
+ nargs="+",
185
89
  required=True,
186
90
  )
187
-
188
91
  config.parser.add_argument(
189
- "--telescope_indices",
190
- help="List of telescope indices to be considered in the generation of the histograms",
92
+ "--file_labels",
93
+ help="Labels for the input files (in the same order as input_files)",
191
94
  type=str,
192
- required=False,
193
95
  nargs="+",
194
- default=None,
96
+ required=None,
195
97
  )
196
-
197
- config.parser.add_argument(
198
- "--individual_telescopes",
199
- help="if False, the histograms are filled for all given telescopes together, otherwise"
200
- "one histogram is set for each telescope separately.",
201
- action="store_true",
202
- required=False,
203
- default=False,
204
- )
205
-
206
98
  config.parser.add_argument(
207
- "--hist_config",
208
- help="hdf5 file with the configuration parameters to create the histograms.",
99
+ "--normalization",
100
+ help="Normalization method for histograms. Options: 'per-telescope', 'per-bin'",
209
101
  type=str,
210
- required=False,
211
- default=None,
212
- )
213
-
214
- config.parser.add_argument(
215
- "--pdf", help="Save histograms into a pdf file.", action="store_true", required=False
102
+ choices=["per-telescope", "per-bin"],
103
+ default="per-telescope",
216
104
  )
217
-
218
105
  config.parser.add_argument(
219
- "--hdf5", help="Save histograms into hdf5 files.", action="store_true", required=False
106
+ "--axis_distance",
107
+ help=(
108
+ "Distance from x/y axes to consider when calculating "
109
+ "the lateral density profiles (in meters)."
110
+ ),
111
+ type=float,
112
+ default=1000.0,
220
113
  )
221
-
222
114
  config.parser.add_argument(
223
- "--hdf5_file_name",
224
- help="Name of the hdf5 file where to save the histograms.",
115
+ "--pdf_file_name",
116
+ help="Save histograms into a pdf file.",
225
117
  type=str,
226
- required=False,
227
- default=None,
118
+ required=None,
228
119
  )
229
-
230
- config.parser.add_argument(
231
- "--event_1d_histograms",
232
- help="The keys from the CORSIKA event header to be used for the generation of 1D "
233
- "histograms. The available choices can been found in the all_event_keys attribute of"
234
- "the CorsikaHistograms.",
235
- required=False,
236
- default=None,
237
- nargs="*",
238
- )
239
-
240
- config.parser.add_argument(
241
- "--event_2d_histograms",
242
- help="The keys from the CORSIKA event header to be used for the generation of 2D "
243
- "histograms. The available choices can been found in the all_event_keys attribute of"
244
- "the CorsikaHistograms.",
245
- required=False,
246
- default=None,
247
- nargs="*",
248
- )
249
-
250
- config_parser, _ = config.initialize(db_config=False, paths=True)
251
-
252
- if (
253
- not config_parser["pdf"]
254
- and not config_parser["hdf5"]
255
- and not config_parser["event_1d_histograms"]
256
- and not config_parser["event_2d_histograms"]
257
- ):
258
- config.parser.error(
259
- "At least one argument is required: --pdf, --hdf5, --event_1d_histograms, or "
260
- "--event_2d_histograms."
261
- )
262
-
263
- return config_parser, _
120
+ return config.initialize(db_config=False, paths=True)
264
121
 
265
122
 
266
123
  def main():
267
- """Generate a set of histograms for the Cherenkov photons saved in the CORSIKA IACT file."""
124
+ """Generate a set of histograms for the Cherenkov photons from CORSIKA IACT file(s)."""
268
125
  app_context = startup_application(_parse)
269
126
 
270
- initial_time = time.time()
271
-
272
- corsika_histograms_instance = CorsikaHistograms(
273
- app_context.args["iact_file"],
274
- output_path=app_context.io_handler.get_output_directory(),
275
- hdf5_file_name=app_context.args["hdf5_file_name"],
276
- )
277
- corsika_histograms_instance.run_export_pipeline(
278
- individual_telescopes=app_context.args["individual_telescopes"],
279
- hist_config=app_context.args["hist_config"],
280
- indices_arg=app_context.args["telescope_indices"],
281
- write_pdf=app_context.args["pdf"],
282
- write_hdf5=app_context.args["hdf5"],
283
- event1d=app_context.args["event_1d_histograms"],
284
- event2d=app_context.args["event_2d_histograms"],
285
- test=app_context.args["test"],
286
- )
127
+ all_histograms = []
128
+ for input_file in app_context.args["input_files"]:
129
+ corsika_histograms = CorsikaHistograms(
130
+ input_file,
131
+ normalization_method=app_context.args["normalization"],
132
+ axis_distance=app_context.args["axis_distance"] * u.m,
133
+ )
134
+ corsika_histograms.fill()
135
+ all_histograms.append(corsika_histograms)
287
136
 
288
- final_time = time.time()
289
- app_context.logger.info(
290
- f"Finalizing the application. Total time needed: {round(final_time - initial_time)}s."
137
+ plot_corsika_histograms.export_all_photon_figures_pdf(
138
+ all_histograms,
139
+ app_context.io_handler.get_output_file(app_context.args.get("pdf_file_name")),
140
+ app_context.args.get("file_labels"),
291
141
  )
292
142
 
293
143
 
@@ -1,15 +1,25 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  """
4
- Make a regular array of telescopes and save it as astropy table.
4
+ Make a regular array of telescopes and save it to file.
5
5
 
6
- The arrays consist of one telescope at the center of the array and or of 4 telescopes
7
- in a square grid. These arrays are used for trigger rate simulations.
6
+ Arrays can consist of single (central) telescopes, square grids or star-like (with
7
+ telescopes arranged on main axes) patterns. All telescopes in the array are of
8
+ the same type and are placed at regular distances.
8
9
 
9
- The array layout files created will be available at the data/layout directory.
10
+ Output files are saved as astropy tables in ASCII ECSV format and in the simtools format
11
+ required to be used for the overwrite model parameter configuration.
10
12
 
11
13
  Command line arguments
12
14
  ----------------------
15
+ telescope_type (str)
16
+ Type of telescope (e.g., LST, MST, SST).
17
+ n_telescopes (int)
18
+ Number of telescopes in the array.
19
+ telescope_distance (float)
20
+ Distance between telescopes in the array (in meters).
21
+ array_shape (str)
22
+ Shape of the array ('square', 'star').
13
23
  site (str, required)
14
24
  observatory site (e.g., North or South).
15
25
  model_version (str, optional)
@@ -27,28 +37,42 @@ Runtime < 10 s.
27
37
  from pathlib import Path
28
38
 
29
39
  import astropy.units as u
30
- from astropy.table import QTable
31
40
 
32
41
  import simtools.data_model.model_data_writer as writer
33
42
  from simtools.application_control import get_application_label, startup_application
34
43
  from simtools.configuration import configurator
35
- from simtools.utils import names
36
-
37
- # Telescope distances for 4 tel square arrays
38
- # !HARDCODED
39
- telescope_distance = {"LST": 57.5 * u.m, "MST": 70 * u.m, "SST": 80 * u.m}
44
+ from simtools.layout.array_layout_utils import create_regular_array, write_array_elements_info_yaml
40
45
 
41
46
 
42
47
  def _parse():
43
48
  config = configurator.Configurator(
44
49
  label=get_application_label(__file__),
45
- description=(
46
- "Generate a regular array of telescope and save as astropy table.\n"
47
- "Default telescope distances for 4 telescope square arrays are: \n"
48
- f" LST: {telescope_distance['LST']}\n"
49
- f" MST: {telescope_distance['MST']}\n"
50
- f" SST: {telescope_distance['SST']}\n"
51
- ),
50
+ description=("Generate a regular array of telescope and save as astropy table."),
51
+ )
52
+ config.parser.add_argument(
53
+ "--telescope_type",
54
+ help="Type of telescope (e.g., LST, MST, SST).",
55
+ type=str,
56
+ default="LST",
57
+ )
58
+ config.parser.add_argument(
59
+ "--n_telescopes",
60
+ help="Number of telescopes in the array.",
61
+ type=int,
62
+ default=4,
63
+ )
64
+ config.parser.add_argument(
65
+ "--telescope_distance",
66
+ help="Distance between telescopes in the array (in meters).",
67
+ type=float,
68
+ default=50.0,
69
+ )
70
+ config.parser.add_argument(
71
+ "--array_shape",
72
+ help="Shape of the array (e.g., 'square', 'star').",
73
+ type=str,
74
+ default="square",
75
+ choices=["square", "star"],
52
76
  )
53
77
  return config.initialize(
54
78
  db_config=False, simulation_model=["site", "model_version"], output=True
@@ -56,61 +80,44 @@ def _parse():
56
80
 
57
81
 
58
82
  def main():
59
- """Create layout array files (ecsv) of regular arrays."""
83
+ """Create layout array files of regular arrays."""
60
84
  app_context = startup_application(_parse)
61
85
 
62
- if app_context.args["site"] == "South":
63
- array_list = ["1SST", "4SST", "1MST", "4MST", "1LST", "4LST"]
64
- else:
65
- array_list = ["1MST", "4MST", "1LST", "4LST"]
66
-
67
- for array_name in array_list:
68
- app_context.logger.info(f"Processing array {array_name}")
69
-
70
- tel_name, pos_x, pos_y, pos_z = [], [], [], []
71
- tel_size = array_name[1:4]
72
-
73
- # Single telescope at the center
74
- if array_name[0] == "1":
75
- tel_name.append(
76
- names.generate_array_element_name_from_type_site_id(
77
- tel_size, app_context.args["site"], "01"
78
- )
79
- )
80
- pos_x.append(0 * u.m)
81
- pos_y.append(0 * u.m)
82
- pos_z.append(0 * u.m)
83
- # 4 telescopes in a regular square grid
84
- else:
85
- for i in range(1, 5):
86
- tel_name.append(
87
- names.generate_array_element_name_from_type_site_id(
88
- tel_size, app_context.args["site"], f"0{i}"
89
- )
90
- )
91
- pos_x.append(telescope_distance[tel_size] * (-1) ** (i // 2))
92
- pos_y.append(telescope_distance[tel_size] * (-1) ** (i % 2))
93
- pos_z.append(0 * u.m)
94
-
95
- table = QTable(meta={"array_name": array_name, "site": app_context.args["site"]})
96
- table["telescope_name"] = tel_name
97
- table["position_x"] = pos_x
98
- table["position_y"] = pos_y
99
- table["position_z"] = pos_z
100
- table.sort("telescope_name")
101
- table.pprint()
102
-
103
- output_file = app_context.args.get("output_file")
104
- if output_file:
105
- output_path = Path(output_file)
106
- output_file = output_path.with_name(
107
- f"{output_path.stem}-{app_context.args['site']}-{array_name}{output_path.suffix}"
108
- )
109
- writer.ModelDataWriter.dump(
110
- args_dict=app_context.args,
86
+ n_tel = app_context.args["n_telescopes"]
87
+ tel_type = app_context.args["telescope_type"]
88
+ tel_dist = app_context.args["telescope_distance"] * u.m
89
+ shape = app_context.args["array_shape"]
90
+
91
+ array_name = f"{n_tel}{tel_type}-{shape}"
92
+ app_context.logger.info(f"Processing array {array_name}")
93
+
94
+ array_table = create_regular_array(
95
+ array_name,
96
+ app_context.args["site"],
97
+ n_telescopes=n_tel,
98
+ telescope_type=tel_type,
99
+ telescope_distance=tel_dist,
100
+ shape=shape,
101
+ )
102
+
103
+ output_file = app_context.args.get("output_file")
104
+ if output_file:
105
+ output_path = Path(output_file)
106
+ output_file = output_path.with_name(
107
+ f"{output_path.stem}-{app_context.args['site']}-{array_name}{output_path.suffix}"
108
+ )
109
+
110
+ data_writer = writer.ModelDataWriter(
111
111
  output_file=output_file,
112
- metadata=None,
113
- product_data=table,
112
+ output_file_format=app_context.args.get("output_file_format", "ascii.ecsv"),
113
+ )
114
+ data_writer.write(metadata=None, product_data=array_table)
115
+
116
+ write_array_elements_info_yaml(
117
+ array_table,
118
+ app_context.args["site"],
119
+ app_context.args["model_version"],
120
+ Path(data_writer.output_file).with_suffix(".info.yml"),
114
121
  )
115
122
 
116
123
 
@@ -130,7 +130,7 @@ from simtools.application_control import get_application_label, startup_applicat
130
130
  from simtools.configuration import configurator
131
131
  from simtools.data_model.metadata_collector import MetadataCollector
132
132
  from simtools.io import io_handler, table_handler
133
- from simtools.simtel.simtel_io_event_writer import SimtelIOEventDataWriter
133
+ from simtools.sim_events.writer import EventDataWriter
134
134
 
135
135
 
136
136
  def _parse():
@@ -173,7 +173,7 @@ def main():
173
173
  return
174
174
 
175
175
  output_filepath = io_handler.IOHandler().get_output_file(app_context.args["output_file"])
176
- generator = SimtelIOEventDataWriter(files, app_context.args["max_files"])
176
+ generator = EventDataWriter(files, app_context.args["max_files"])
177
177
  tables = generator.process_files()
178
178
  table_handler.write_tables(tables, output_filepath, overwrite_existing=True)
179
179
  MetadataCollector.dump(
@@ -28,8 +28,8 @@ The following example applies a patch update with changes defined in a YAML file
28
28
 
29
29
  .. code-block:: console
30
30
 
31
- simtools-maintain-simulation-model-add-new-production \\
32
- --model_path ../simulation-models-dev/simulation-models/ \\
31
+ simtools-maintain-simulation-model-add-production \\
32
+ --model_path ../simulation-models-dev \\
33
33
  --model_version 6.0.2
34
34
 
35
35
  """
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/python3
2
+ """
3
+ Read array element positions from file and write model parameter files for each element.
4
+
5
+ This is an application for experts and should not be used by the general user.
6
+ Reading of input is fine-tuned to the array element files as provided by CTAO.
7
+
8
+ Writes one model parameter file per array element into a directory structure compatible
9
+ with the simtools model parameter repository.
10
+
11
+ Command line arguments
12
+
13
+ input : str
14
+ File containing a table of array element positions.
15
+ repository_path : str
16
+ Path of local copy of model parameter repository.
17
+ parameter_version : str
18
+ Parameter version.
19
+ coordinate_system : str
20
+ Coordinate system of array element positions (ground or utm).
21
+
22
+ Examples
23
+ --------
24
+ Add array element positions to repository (ground coordinates):
25
+
26
+ .. code-block:: console
27
+
28
+ simtools-maintain-simulation-model-write-array-element-positions \
29
+ --input tests/resources/telescope_positions-North-ground.ecsv \
30
+ --output_path /path/to/repository \
31
+ --parameter_version 0.1.0 \
32
+ --coordinate_system ground
33
+
34
+ Add array element positions to repository (utm coordinates):
35
+
36
+ .. code-block:: console
37
+
38
+ simtools-maintain-simulation-model-write-array-element-positions \
39
+ --input tests/resources/telescope_positions-North-utm.ecsv \
40
+ --output_path /path/to/repository \
41
+ --parameter_version 0.1.0 \
42
+ --coordinate_system utm
43
+
44
+ """
45
+
46
+ from simtools.application_control import get_application_label, startup_application
47
+ from simtools.configuration import configurator
48
+ from simtools.layout.array_layout_utils import write_array_elements_from_file_to_repository
49
+
50
+
51
+ def _parse():
52
+ """Parse command line configuration."""
53
+ config = configurator.Configurator(
54
+ label=get_application_label(__file__),
55
+ description="Add array element positions to model parameter repository",
56
+ )
57
+ config.parser.add_argument(
58
+ "--input",
59
+ help="File containing a table of array element positions.",
60
+ required=False,
61
+ )
62
+ config.parser.add_argument(
63
+ "--coordinate_system",
64
+ help="Coordinate system of array element positions (utm or ground).",
65
+ default="ground",
66
+ required=False,
67
+ type=str,
68
+ choices=["ground", "utm"],
69
+ )
70
+
71
+ return config.initialize(db_config=True, output=True, simulation_model=["parameter_version"])
72
+
73
+
74
+ def main():
75
+ """Application main."""
76
+ app_context = startup_application(_parse)
77
+
78
+ write_array_elements_from_file_to_repository(
79
+ coordinate_system=app_context.args["coordinate_system"],
80
+ input_file=app_context.args["input"],
81
+ repository_path=app_context.args["output_path"],
82
+ parameter_version=app_context.args["parameter_version"],
83
+ )
84
+
85
+
86
+ if __name__ == "__main__":
87
+ main()