gammasimtools 0.16.0__py3-none-any.whl → 0.18.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 (85) hide show
  1. {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/METADATA +5 -2
  2. {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/RECORD +82 -74
  3. {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/WHEEL +1 -1
  4. {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/entry_points.txt +4 -1
  5. simtools/_version.py +2 -2
  6. simtools/applications/db_add_simulation_model_from_repository_to_db.py +10 -1
  7. simtools/applications/derive_ctao_array_layouts.py +5 -5
  8. simtools/applications/derive_mirror_rnda.py +1 -1
  9. simtools/applications/generate_simtel_event_data.py +128 -46
  10. simtools/applications/merge_tables.py +102 -0
  11. simtools/applications/plot_array_layout.py +145 -258
  12. simtools/applications/plot_tabular_data.py +12 -1
  13. simtools/applications/plot_tabular_data_for_model_parameter.py +103 -0
  14. simtools/applications/production_derive_corsika_limits.py +78 -225
  15. simtools/applications/production_derive_statistics.py +77 -43
  16. simtools/applications/simulate_light_emission.py +1 -0
  17. simtools/applications/simulate_prod.py +30 -18
  18. simtools/applications/simulate_prod_htcondor_generator.py +0 -1
  19. simtools/applications/submit_array_layouts.py +93 -0
  20. simtools/applications/verify_simulation_model_production_tables.py +52 -0
  21. simtools/camera/camera_efficiency.py +3 -3
  22. simtools/configuration/commandline_parser.py +30 -35
  23. simtools/configuration/configurator.py +0 -4
  24. simtools/constants.py +2 -0
  25. simtools/corsika/corsika_config.py +17 -12
  26. simtools/corsika/primary_particle.py +46 -13
  27. simtools/data_model/metadata_collector.py +7 -3
  28. simtools/data_model/schema.py +15 -1
  29. simtools/db/db_handler.py +16 -11
  30. simtools/db/db_model_upload.py +2 -2
  31. simtools/io_operations/io_handler.py +2 -2
  32. simtools/io_operations/io_table_handler.py +345 -0
  33. simtools/job_execution/htcondor_script_generator.py +2 -2
  34. simtools/job_execution/job_manager.py +7 -121
  35. simtools/layout/array_layout_utils.py +389 -0
  36. simtools/model/array_model.py +10 -1
  37. simtools/model/model_repository.py +134 -0
  38. simtools/production_configuration/{calculate_statistical_errors_grid_point.py → calculate_statistical_uncertainties_grid_point.py} +101 -112
  39. simtools/production_configuration/derive_corsika_limits.py +239 -111
  40. simtools/production_configuration/derive_corsika_limits_grid.py +232 -0
  41. simtools/production_configuration/derive_production_statistics.py +57 -26
  42. simtools/production_configuration/derive_production_statistics_handler.py +70 -37
  43. simtools/production_configuration/interpolation_handler.py +296 -94
  44. simtools/ray_tracing/ray_tracing.py +7 -6
  45. simtools/reporting/docs_read_parameters.py +104 -62
  46. simtools/resources/array-element-ids.json +126 -0
  47. simtools/runners/corsika_simtel_runner.py +4 -1
  48. simtools/runners/runner_services.py +5 -4
  49. simtools/schemas/model_parameter_and_data_schema.metaschema.yml +5 -1
  50. simtools/schemas/model_parameters/atmospheric_profile.schema.yml +41 -0
  51. simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +43 -0
  52. simtools/schemas/model_parameters/camera_filter.schema.yml +10 -0
  53. simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +10 -0
  54. simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +31 -0
  55. simtools/schemas/model_parameters/dsum_threshold.schema.yml +41 -0
  56. simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +12 -0
  57. simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +10 -0
  58. simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +10 -0
  59. simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +12 -0
  60. simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +19 -0
  61. simtools/schemas/model_parameters/quantum_efficiency.schema.yml +10 -0
  62. simtools/schemas/plot_configuration.metaschema.yml +46 -57
  63. simtools/schemas/production_configuration_metrics.schema.yml +2 -2
  64. simtools/simtel/simtel_config_writer.py +34 -14
  65. simtools/simtel/simtel_io_event_reader.py +301 -194
  66. simtools/simtel/simtel_io_event_writer.py +237 -221
  67. simtools/simtel/simtel_io_file_info.py +9 -4
  68. simtools/simtel/simtel_io_metadata.py +119 -8
  69. simtools/simtel/simulator_array.py +2 -2
  70. simtools/simtel/simulator_light_emission.py +79 -34
  71. simtools/simtel/simulator_ray_tracing.py +2 -2
  72. simtools/simulator.py +101 -68
  73. simtools/testing/validate_output.py +4 -1
  74. simtools/utils/general.py +1 -3
  75. simtools/utils/names.py +76 -7
  76. simtools/visualization/plot_array_layout.py +242 -0
  77. simtools/visualization/plot_pixels.py +680 -0
  78. simtools/visualization/plot_tables.py +81 -2
  79. simtools/visualization/visualize.py +3 -219
  80. simtools/applications/production_generate_simulation_config.py +0 -152
  81. simtools/layout/ctao_array_layouts.py +0 -172
  82. simtools/production_configuration/generate_simulation_config.py +0 -158
  83. {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/licenses/LICENSE +0 -0
  84. {gammasimtools-0.16.0.dist-info → gammasimtools-0.18.0.dist-info}/top_level.txt +0 -0
  85. /simtools/{schemas → resources}/array_elements.yml +0 -0
@@ -1,21 +1,31 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  """
4
- Plot array elements (array layout).
4
+ Plot array elements (array layouts).
5
5
 
6
- Plot an array layout and save it to file (e.g., pdf). Layouts are defined in the database,
7
- or given as command line arguments (explicit listing or telescope list file). A list of input
8
- files is also accepted.
9
- Layouts can be plotted in ground or UTM coordinate systems.
6
+ Plot array layouts in ground or UTM coordinate systems from multiple sources.
10
7
 
11
- Listing of array elements follows this logic:
8
+ For the following options, array element positions are retrieved from the model parameter database:
12
9
 
13
- * explicit listing: e.g., ``-array_element_list MSTN-01, MSTN05``
14
- * listing of types: e.g, ``-array_element_list MSTN`` plots all telescopes of type MSTN.
10
+ * from the model parameter database using the layout name (e.g., ``-array_layout_name alpha``)
15
11
 
16
- A rotation angle in degrees allows to rotate the array before plotting.
17
- The typical image formats (e.g., pdf, png, jpg) are allowed for the output figures.
18
- If no ``figure_name`` is given as output, layouts are plotted in pdf and png format.
12
+ * from the model parameter data, retrieving all layouts for the given site and model version
13
+ (``--plot_all_layouts``)
14
+
15
+ * from a model parameter file
16
+ (e.g., ``-array_layout_parameter_file tests/resources/model_parameters/array_layouts-2.0.1.json``)
17
+
18
+ * from a list of array elements (e.g., ``-array_element_list MSTN-01, MSTN-02``).
19
+ Positions are retrieved from the database.
20
+ * explicit listing: e.g., ``-array_element_list MSTN-01, MSTN05``
21
+ * listing of types: e.g, ``-array_element_list MSTN`` plots all telescopes of type MSTN.
22
+
23
+ For this option, array element positions are retrieved from the input file:
24
+
25
+ * from a file containing an astropy table with a list of array elements and their positions
26
+ (e.g., ``-array_layout_file tests/resources/telescope_positions-North-ground.ecsv``)
27
+
28
+ Plots are saved as pdf and png files in the output directory.
19
29
 
20
30
  Example of a layout plot:
21
31
 
@@ -31,12 +41,15 @@ array_layout_file : str
31
41
  File (astropy table compatible) with a list of array elements.
32
42
  array_layout_name : str
33
43
  Name of the layout array (e.g., test_layout, alpha, 4mst, etc.).
44
+ Use 'plot_all' to plot all layouts from the database for the given site and model version.
45
+ array_layout_parameter_file : str, optional
46
+ File with array layouts similar in the model parameter file format (typically JSON).
47
+ array_layout_name_background: str, optional
48
+ Name of the background layout array (e.g., test_layout, alpha, 4mst, etc.).
34
49
  array_element_list : list
35
50
  List of array elements (e.g., telescopes) to plot (e.g., ``LSTN-01 LSTN-02 MSTN``).
36
51
  coordinate_system : str, optional
37
52
  Coordinate system for the array layout (ground or utm).
38
- rotate_angle : float, optional
39
- Angle to rotate the array before plotting (in degrees).
40
53
  show_labels : bool, optional
41
54
  Shows the telescope labels in the plot.
42
55
  axes_range : float, optional
@@ -46,26 +59,44 @@ marker_scaling : float, optional.
46
59
 
47
60
  Examples
48
61
  --------
49
- Plot layout with the name "test_layout":
62
+ Plot "alpha" layout for the North site with model version 6.0.0:
63
+
64
+ .. code-block:: console
65
+
66
+ simtools-plot-array-layout --site North
67
+ --array_layout_name alpha
68
+ --model_version=6.0.0
69
+
70
+ Plot layout with 2 LSTs on top of north alpha layout:
50
71
 
51
72
  .. code-block:: console
52
73
 
53
- simtools-plot-layout-array --figure_name northern_array_alpha
54
- --array_layout_name test_layout
74
+ simtools-plot-array-layout --site North
75
+ --array_element_list LSTN-01,LSTN-02
76
+ --model_version=6.0.0
77
+ --array_layout_name_background alpha
78
+
79
+ Plot layout from a file with a list of telescopes:
80
+
81
+ .. code-block:: console
55
82
 
83
+ simtools-plot-array-layout
84
+ --array_layout_file tests/resources/telescope_positions-North-ground.ecsv
56
85
 
57
- Plot layout with 2 LSTs and all northern MSTs in UTM coordinates:
86
+ Plot layout from a parameter file with a list of telescopes:
58
87
 
59
88
  .. code-block:: console
60
89
 
61
- simtools-plot-layout-array --array_element_list LSTN-01 LSTN-02 MSTN
62
- --coordinate_system utm
90
+ simtools-plot-array-layout
91
+ --array_layout_parameter_file tests/resources/model_parameters/array_layouts-2.0.1.json
92
+ --model_version 6.0.0
63
93
 
64
- Plot layout from a file with the list of telescopes:
94
+
95
+ Plot all layouts for the North site and model version 6.0.0:
65
96
 
66
97
  .. code-block:: console
67
98
 
68
- simtools-plot-layout-array --array_element_list telescope_positions-test_layout.ecsv
99
+ simtools-plot-array-layout --site North --plot_all_layouts --model_version=6.0.0
69
100
  """
70
101
 
71
102
  import logging
@@ -73,17 +104,16 @@ from pathlib import Path
73
104
 
74
105
  import matplotlib as mpl
75
106
  import matplotlib.pyplot as plt
76
- from astropy import units as u
77
107
 
108
+ import simtools.layout.array_layout_utils as layout_utils
78
109
  import simtools.utils.general as gen
79
110
  from simtools.configuration import configurator
80
111
  from simtools.io_operations import io_handler
81
- from simtools.model.array_model import ArrayModel
82
- from simtools.utils import names
83
- from simtools.visualization.visualize import plot_array
112
+ from simtools.visualization import visualize
113
+ from simtools.visualization.plot_array_layout import plot_array_layout
84
114
 
85
115
 
86
- def _parse(label, description, usage):
116
+ def _parse(label, description, usage=None):
87
117
  """
88
118
  Parse command line configuration.
89
119
 
@@ -110,13 +140,6 @@ def _parse(label, description, usage):
110
140
  required=False,
111
141
  default=None,
112
142
  )
113
- config.parser.add_argument(
114
- "--rotate_angle",
115
- help="Angle to rotate the array (in degrees).",
116
- type=str,
117
- required=False,
118
- default=None,
119
- )
120
143
  config.parser.add_argument(
121
144
  "--show_labels",
122
145
  help="Plot array element labels.",
@@ -146,227 +169,81 @@ def _parse(label, description, usage):
146
169
  required=False,
147
170
  default=None,
148
171
  )
149
- return config.initialize(
150
- db_config=True, simulation_model=["site", "model_version", "layout", "layout_file"]
172
+ config.parser.add_argument(
173
+ "--array_layout_name_background",
174
+ help="Name of the background layout array (e.g., test_layout, alpha, 4mst, etc.).",
175
+ type=str,
176
+ required=False,
177
+ default=None,
151
178
  )
152
-
153
-
154
- def _get_site_from_telescope_list_name(telescope_list_file):
155
- """
156
- Get the site name from the telescope list file name.
157
-
158
- Parameters
159
- ----------
160
- telescope_list_file : str
161
- Telescope list file name.
162
-
163
- Returns
164
- -------
165
- str
166
- Site name.
167
- """
168
- for _site in names.site_names():
169
- if _site in str(telescope_list_file):
170
- return _site
171
- return None
172
-
173
-
174
- def _get_list_of_plot_files(plot_file_name, output_dir):
175
- """
176
- Get list of output file names for plotting.
177
-
178
- Parameters
179
- ----------
180
- plot_file_name : str
181
- Name of the plot file.
182
- output_dir : str
183
- Output directory.
184
-
185
- Returns
186
- -------
187
- list
188
- List of output file names.
189
-
190
- Raises
191
- ------
192
- NameError
193
- If the file extension is not valid.
194
- """
195
- plot_file = output_dir.joinpath(plot_file_name)
196
-
197
- if len(plot_file.suffix) == 0:
198
- return [plot_file.with_suffix(f".{ext}") for ext in ["pdf", "png"]]
199
-
200
- allowed_extensions = [".jpeg", ".jpg", ".png", ".tiff", ".ps", ".pdf", ".bmp"]
201
- if plot_file.suffix in allowed_extensions:
202
- return [plot_file]
203
- msg = f"Extension in {plot_file} is not valid. Valid extensions are: {allowed_extensions}."
204
- raise NameError(msg)
205
-
206
-
207
- def _get_plot_file_name(figure_name, layout_name, site, coordinate_system, rotate_angle):
208
- """
209
- Generate and return the file name for plots.
210
-
211
- Parameters
212
- ----------
213
- figure_name : str
214
- Figure name given through command line.
215
- layout_name : str
216
- Name of the layout.
217
- site : str
218
- Site name.
219
- coordinate_system : str
220
- Coordinate system for the array layout.
221
- rotate_angle : float
222
- Angle to rotate the array before plotting.
223
-
224
- Returns
225
- -------
226
- str
227
- Plot file name.
228
- """
229
- if figure_name is not None:
230
- return figure_name
231
-
232
- return (
233
- f"array_layout_{layout_name}_{site}_{coordinate_system}_"
234
- f"{round(rotate_angle.to(u.deg).value)!s}deg"
179
+ return config.initialize(
180
+ db_config=True,
181
+ simulation_model=[
182
+ "site",
183
+ "model_version",
184
+ "layout",
185
+ "layout_file",
186
+ "plot_all_layouts",
187
+ "layout_parameter_file",
188
+ ],
235
189
  )
236
190
 
237
191
 
238
- def _layouts_from_array_layout_file(args_dict, db_config, rotate_angle):
192
+ def read_layouts(args_dict, db_config, logger):
239
193
  """
240
- Read array layout positions from file(s) and return a list of layouts.
194
+ Read array layouts from the database or parameter file.
241
195
 
242
196
  Parameters
243
197
  ----------
244
198
  args_dict : dict
245
- Dictionary with the command line arguments.
199
+ Dictionary with command line arguments.
246
200
  db_config : dict
247
201
  Database configuration.
248
- rotate_angle : float
249
- Angle to rotate the array before plotting (in degrees).
202
+ logger : logging.Logger
203
+ Logger instance.
250
204
 
251
205
  Returns
252
206
  -------
253
207
  list
254
208
  List of array layouts.
255
209
  """
256
- layouts = []
257
- telescope_files = args_dict["array_layout_file"]
258
- for one_file in telescope_files:
259
- site = (
260
- _get_site_from_telescope_list_name(one_file)
261
- if args_dict["site"] is None
262
- else args_dict["site"]
263
- )
264
- array_model = ArrayModel(
265
- mongo_db_config=db_config,
266
- model_version=args_dict["model_version"],
267
- site=site,
268
- array_elements=one_file,
210
+ if args_dict["array_layout_name"] is not None or args_dict["plot_all_layouts"]:
211
+ logger.info("Plotting array from DB using layout array name(s).")
212
+ layouts = layout_utils.get_array_layouts_from_db(
213
+ args_dict["array_layout_name"],
214
+ args_dict["site"],
215
+ args_dict["model_version"],
216
+ db_config,
217
+ args_dict["coordinate_system"],
269
218
  )
270
- layouts.append(
271
- {
272
- "array_elements": array_model.export_array_elements_as_table(),
273
- "plot_file_name": _get_plot_file_name(
274
- args_dict["figure_name"],
275
- (Path(one_file).name).split(".")[0],
276
- site,
277
- args_dict["coordinate_system"],
278
- rotate_angle,
279
- ),
280
- }
219
+ if isinstance(layouts, list):
220
+ return layouts
221
+ return [layouts]
222
+
223
+ if args_dict["array_layout_parameter_file"] is not None:
224
+ logger.info("Plotting array from parameter file(s).")
225
+ return layout_utils.get_array_layouts_from_parameter_file(
226
+ args_dict["array_layout_parameter_file"],
227
+ args_dict["model_version"],
228
+ db_config,
229
+ args_dict["coordinate_system"],
281
230
  )
282
- return layouts
283
231
 
232
+ if args_dict["array_layout_file"] is not None:
233
+ logger.info("Plotting array from telescope table file(s).")
234
+ return layout_utils.get_array_layouts_from_file(args_dict["array_layout_file"])
284
235
 
285
- def _layouts_from_list(args_dict, db_config, rotate_angle):
286
- """
287
- Read positions for a list of array elements from the database and return a list of layouts.
288
-
289
- Parameters
290
- ----------
291
- args_dict : dict
292
- Dictionary with the command line arguments.
293
- db_config : dict
294
- Database configuration.
295
- rotate_angle : float
296
- Angle to rotate the array before plotting (in degrees).
297
-
298
- Returns
299
- -------
300
- list
301
- List of array layouts.
302
- """
303
- site = (
304
- names.get_site_from_array_element_name(args_dict["array_element_list"][0])
305
- if args_dict["site"] is None
306
- else args_dict["site"]
307
- )
308
- array_model = ArrayModel(
309
- mongo_db_config=db_config,
310
- model_version=args_dict["model_version"],
311
- site=site,
312
- array_elements=args_dict["array_element_list"],
313
- )
314
- return [
315
- {
316
- "array_elements": array_model.export_array_elements_as_table(
317
- coordinate_system=args_dict["coordinate_system"]
318
- ),
319
- "plot_file_name": _get_plot_file_name(
320
- args_dict["figure_name"],
321
- "list",
322
- site,
323
- args_dict["coordinate_system"],
324
- rotate_angle,
325
- ),
326
- }
327
- ]
328
-
329
-
330
- def _layouts_from_db(args_dict, db_config, rotate_angle):
331
- """
332
- Read array elements and their positions from data base using the layout name.
236
+ if args_dict["array_element_list"] is not None:
237
+ logger.info("Plotting array from list of array elements.")
238
+ return layout_utils.get_array_layouts_using_telescope_lists_from_db(
239
+ [args_dict["array_element_list"]],
240
+ args_dict["site"],
241
+ args_dict["model_version"],
242
+ db_config,
243
+ args_dict["coordinate_system"],
244
+ )
333
245
 
334
- Parameters
335
- ----------
336
- args_dict : dict
337
- Dictionary with the command line arguments.
338
- db_config : dict
339
- Database configuration.
340
- rotate_angle : float
341
- Angle to rotate the array before plotting (in degrees).
342
-
343
- Returns
344
- -------
345
- list
346
- List of array layouts.
347
- """
348
- layouts = []
349
- array_model = ArrayModel(
350
- mongo_db_config=db_config,
351
- model_version=args_dict["model_version"],
352
- site=args_dict["site"],
353
- layout_name=args_dict["array_layout_name"],
354
- )
355
- layouts.append(
356
- {
357
- "array_elements": array_model.export_array_elements_as_table(
358
- coordinate_system=args_dict["coordinate_system"]
359
- ),
360
- "plot_file_name": _get_plot_file_name(
361
- figure_name=args_dict["figure_name"],
362
- layout_name=args_dict["array_layout_name"],
363
- site=args_dict["site"],
364
- coordinate_system=args_dict["coordinate_system"],
365
- rotate_angle=rotate_angle,
366
- ),
367
- }
368
- )
369
- return layouts
246
+ return []
370
247
 
371
248
 
372
249
  def main():
@@ -374,48 +251,58 @@ def main():
374
251
  label = Path(__file__).stem
375
252
  args_dict, db_config = _parse(
376
253
  label,
377
- "Plots array layout.",
378
- "python applications/plot_array_layout.py --array_layout_name test_layout",
254
+ (
255
+ "Plots array layout."
256
+ "Use '--array_layout_name plot_all' to plot all layouts for the given site "
257
+ "and model version."
258
+ ),
379
259
  )
380
260
  logger = logging.getLogger()
381
261
  logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
382
262
  io_handler_instance = io_handler.IOHandler()
383
263
 
384
- rotate_angle = (
385
- 0.0 * u.deg
386
- if args_dict["rotate_angle"] is None
387
- else float(args_dict["rotate_angle"]) * u.deg
388
- )
264
+ layouts = read_layouts(args_dict, db_config, logger)
389
265
 
390
- layouts = []
391
- if args_dict["array_layout_name"] is not None:
392
- logger.info("Plotting array from layout array name.")
393
- layouts = _layouts_from_db(args_dict, db_config, rotate_angle)
394
- elif args_dict["array_layout_file"] is not None:
395
- logger.info("Plotting array from telescope list file.")
396
- layouts = _layouts_from_array_layout_file(args_dict, db_config, rotate_angle)
397
- elif args_dict["array_element_list"] is not None:
398
- logger.info("Plotting array from list of array elements.")
399
- layouts = _layouts_from_list(args_dict, db_config, rotate_angle)
266
+ if args_dict.get("array_layout_name_background"):
267
+ background_layout = layout_utils.get_array_layouts_from_db(
268
+ args_dict["array_layout_name_background"],
269
+ args_dict["site"],
270
+ args_dict["model_version"],
271
+ db_config,
272
+ args_dict["coordinate_system"],
273
+ )["array_elements"]
274
+ else:
275
+ background_layout = None
400
276
 
401
277
  mpl.use("Agg")
402
278
  for layout in layouts:
403
- fig_out = plot_array(
279
+ fig_out = plot_array_layout(
404
280
  telescopes=layout["array_elements"],
405
- rotate_angle=rotate_angle,
406
281
  show_tel_label=args_dict["show_labels"],
407
282
  axes_range=args_dict["axes_range"],
408
283
  marker_scaling=args_dict["marker_scaling"],
284
+ background_telescopes=background_layout,
409
285
  )
410
- _plot_files = _get_list_of_plot_files(
411
- layout["plot_file_name"],
412
- io_handler_instance.get_output_directory(label, sub_dir="application-plots"),
286
+ site_string = ""
287
+ if layout.get("site") is not None:
288
+ site_string = f"_{layout['site']}"
289
+ elif args_dict["site"] is not None:
290
+ site_string = f"_{args_dict['site']}"
291
+ coordinate_system_string = (
292
+ f"_{args_dict['coordinate_system']}"
293
+ if args_dict["coordinate_system"] not in layout["name"]
294
+ else ""
295
+ )
296
+ plot_file_name = args_dict["figure_name"] or (
297
+ f"array_layout_{layout['name']}{site_string}{coordinate_system_string}"
413
298
  )
414
299
 
415
- for file in _plot_files:
416
- logger.info(f"Saving figure as {file}")
417
- plt.savefig(file, bbox_inches="tight", dpi=400)
418
- fig_out.clf()
300
+ visualize.save_figure(
301
+ fig_out,
302
+ io_handler_instance.get_output_directory(label, sub_dir="application-plots")
303
+ / plot_file_name,
304
+ dpi=400,
305
+ )
419
306
  plt.close()
420
307
 
421
308
 
@@ -9,6 +9,17 @@ Command line arguments
9
9
  ----------------------
10
10
  config_file (str, required)
11
11
  Configuration file name for plotting.
12
+ output_file (str, required)
13
+ Output file name (without suffix).
14
+
15
+ Example
16
+ -------
17
+
18
+ Plot tabular data using a configuration file.
19
+
20
+ .. code-block:: console
21
+
22
+ simtools-plot-tabular-data --plot_config config_file_name --output_file output_file_name
12
23
 
13
24
  """
14
25
 
@@ -80,7 +91,7 @@ def main():
80
91
  )
81
92
 
82
93
  plot_tables.plot(
83
- config=plot_config["cta_simpipe"]["plot"],
94
+ config=plot_config["plot"],
84
95
  output_file=io_handler_instance.get_output_file(args_dict["output_file"]),
85
96
  db_config=db_config_,
86
97
  )
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/python3
2
+ r"""
3
+ Plot tabular data for a single model parameter using default plotting configurations.
4
+
5
+ Uses plotting configurations as defined in the model parameters schema files.
6
+
7
+ Command line arguments
8
+ ----------------------
9
+ parameter (str, required)
10
+ Model parameter to plot (e.g., 'atmospheric_profile').
11
+ parameter_version (str, required)
12
+ Version of the model parameter to plot (e.g., '1.0.0').
13
+ site (str, required)
14
+ Site for which the model parameter is defined (e.g., 'North').
15
+ telescope (str, optional)
16
+ Telescope for which the model parameter is defined (e.g., 'LSTN-01').
17
+ output_file (str, required)
18
+ Output file name (without suffix).
19
+ plot_type (str, optional)
20
+ Type of plot as defined in the schema file.
21
+ Use '--plot_type all' to plot all types defined in the schema.
22
+
23
+ Example
24
+ -------
25
+
26
+ Plot tabular data for a specific type defined in the schema file:
27
+
28
+ .. code-block:: console
29
+
30
+ simtools-plot-tabular-data-for-model-parameter \\
31
+ --parameter atmospheric_profile \\
32
+ --parameter_version 1.0.0 \\
33
+ --site North \\
34
+ --plot_type refractive_index_vs_altitude
35
+
36
+ Plot tabular data for all types defined in the schema file:
37
+
38
+ .. code-block:: console
39
+
40
+ simtools-plot-tabular-data-for-model-parameter \\
41
+ --parameter fadc_pulse_shape
42
+ --parameter_version 1.0.0 \\
43
+ --site North \\
44
+ --telescope LSTN-01 \\
45
+ --plot_type all
46
+
47
+ """
48
+
49
+ import logging
50
+ from pathlib import Path
51
+
52
+ import simtools.utils.general as gen
53
+ from simtools.configuration import configurator
54
+ from simtools.data_model.metadata_collector import MetadataCollector
55
+ from simtools.io_operations import io_handler
56
+ from simtools.visualization import plot_tables
57
+
58
+
59
+ def _parse(label, description):
60
+ """Parse command line configuration."""
61
+ config = configurator.Configurator(label=label, description=description)
62
+
63
+ config.parser.add_argument("--parameter", type=str, required=True, help="Parameter name.")
64
+ config.parser.add_argument(
65
+ "--plot_type",
66
+ help="Plot type as defined in the schema file.",
67
+ type=str,
68
+ required=True,
69
+ default=None,
70
+ )
71
+ return config.initialize(db_config=True, simulation_model=["telescope", "parameter_version"])
72
+
73
+
74
+ def main():
75
+ """Plot tabular data."""
76
+ args_dict, db_config = _parse(
77
+ label=Path(__file__).stem,
78
+ description="Plots tabular data for a model parameter.",
79
+ )
80
+ logger = logging.getLogger()
81
+ logger.setLevel(gen.get_log_level_from_user(args_dict.get("log_level", "INFO")))
82
+ io_handler_instance = io_handler.IOHandler()
83
+
84
+ plot_configs, output_files = plot_tables.generate_plot_configurations(
85
+ parameter=args_dict["parameter"],
86
+ parameter_version=args_dict["parameter_version"],
87
+ site=args_dict["site"],
88
+ telescope=args_dict.get("telescope"),
89
+ output_path=io_handler_instance.get_output_directory(),
90
+ plot_type=args_dict["plot_type"],
91
+ )
92
+
93
+ for plot_config, output_file in zip(plot_configs, output_files):
94
+ plot_tables.plot(
95
+ config=plot_config,
96
+ output_file=output_file,
97
+ db_config=db_config,
98
+ )
99
+ MetadataCollector.dump(args_dict, output_file=output_file, add_activity_name=True)
100
+
101
+
102
+ if __name__ == "__main__":
103
+ main()