gammasimtools 0.5.1__py3-none-any.whl → 0.6.1__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 (78) hide show
  1. {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/METADATA +80 -28
  2. gammasimtools-0.6.1.dist-info/RECORD +91 -0
  3. {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/WHEEL +1 -1
  4. {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/entry_points.txt +4 -2
  5. simtools/_version.py +14 -2
  6. simtools/applications/add_file_to_db.py +2 -1
  7. simtools/applications/compare_cumulative_psf.py +10 -15
  8. simtools/applications/db_development_tools/add_new_parameter_to_db.py +12 -6
  9. simtools/applications/derive_mirror_rnda.py +95 -71
  10. simtools/applications/generate_corsika_histograms.py +216 -131
  11. simtools/applications/generate_default_metadata.py +110 -0
  12. simtools/applications/generate_simtel_array_histograms.py +192 -0
  13. simtools/applications/get_file_from_db.py +1 -1
  14. simtools/applications/get_parameter.py +3 -3
  15. simtools/applications/make_regular_arrays.py +89 -93
  16. simtools/applications/{plot_layout_array.py → plot_array_layout.py} +15 -14
  17. simtools/applications/print_array_elements.py +81 -34
  18. simtools/applications/produce_array_config.py +2 -2
  19. simtools/applications/production.py +39 -5
  20. simtools/applications/sim_showers_for_trigger_rates.py +26 -30
  21. simtools/applications/simulate_prod.py +49 -107
  22. simtools/applications/submit_data_from_external.py +8 -10
  23. simtools/applications/tune_psf.py +16 -18
  24. simtools/applications/validate_camera_efficiency.py +63 -9
  25. simtools/applications/validate_camera_fov.py +9 -13
  26. simtools/applications/validate_file_using_schema.py +127 -0
  27. simtools/applications/validate_optics.py +13 -15
  28. simtools/camera_efficiency.py +73 -80
  29. simtools/configuration/commandline_parser.py +52 -22
  30. simtools/configuration/configurator.py +98 -33
  31. simtools/constants.py +9 -0
  32. simtools/corsika/corsika_config.py +28 -22
  33. simtools/corsika/corsika_default_config.py +282 -0
  34. simtools/corsika/corsika_histograms.py +328 -282
  35. simtools/corsika/corsika_histograms_visualize.py +162 -163
  36. simtools/corsika/corsika_runner.py +8 -4
  37. simtools/corsika_simtel/corsika_simtel_runner.py +18 -23
  38. simtools/data_model/data_reader.py +129 -0
  39. simtools/data_model/metadata_collector.py +346 -118
  40. simtools/data_model/metadata_model.py +123 -218
  41. simtools/data_model/model_data_writer.py +79 -22
  42. simtools/data_model/validate_data.py +96 -46
  43. simtools/db_handler.py +67 -42
  44. simtools/io_operations/__init__.py +0 -0
  45. simtools/io_operations/hdf5_handler.py +112 -0
  46. simtools/{io_handler.py → io_operations/io_handler.py} +51 -22
  47. simtools/job_execution/job_manager.py +1 -1
  48. simtools/layout/{layout_array.py → array_layout.py} +168 -199
  49. simtools/layout/geo_coordinates.py +196 -0
  50. simtools/layout/telescope_position.py +12 -12
  51. simtools/model/array_model.py +16 -14
  52. simtools/model/camera.py +5 -8
  53. simtools/model/mirrors.py +136 -73
  54. simtools/model/model_utils.py +1 -69
  55. simtools/model/telescope_model.py +32 -25
  56. simtools/psf_analysis.py +26 -19
  57. simtools/ray_tracing.py +54 -26
  58. simtools/schemas/data.metaschema.yml +400 -0
  59. simtools/schemas/metadata.metaschema.yml +566 -0
  60. simtools/simtel/simtel_config_writer.py +14 -5
  61. simtools/simtel/simtel_histograms.py +266 -83
  62. simtools/simtel/simtel_runner.py +8 -7
  63. simtools/simtel/simtel_runner_array.py +7 -8
  64. simtools/simtel/simtel_runner_camera_efficiency.py +48 -2
  65. simtools/simtel/simtel_runner_ray_tracing.py +61 -25
  66. simtools/simulator.py +43 -50
  67. simtools/utils/general.py +232 -286
  68. simtools/utils/geometry.py +163 -0
  69. simtools/utils/names.py +294 -142
  70. simtools/visualization/legend_handlers.py +115 -9
  71. simtools/visualization/visualize.py +13 -13
  72. gammasimtools-0.5.1.dist-info/RECORD +0 -83
  73. simtools/applications/plot_simtel_histograms.py +0 -120
  74. simtools/applications/validate_schema_files.py +0 -135
  75. simtools/corsika/corsika_output_visualize.py +0 -345
  76. simtools/data_model/validate_schema.py +0 -285
  77. {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/LICENSE +0 -0
  78. {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/top_level.txt +0 -0
@@ -2,61 +2,80 @@
2
2
  """
3
3
  Summary
4
4
  -------
5
- Print a list of array element positions in different CTAO coordinate \
6
- systems.
5
+ Convert and print a list of array element positions in different coordinate \
6
+ systems relevant for CTAO.
7
+
8
+ Description
9
+ -----------
10
+
11
+ This application converts a list of array element positions in different CTAO \
12
+ coordinate systems.
7
13
 
8
14
  Available coordinate systems are:
15
+
9
16
  1. UTM system
10
- 2. CORSIKA coordinates
17
+ 2. ground system (similar to sim_telarray system with x-axis pointing toward \
18
+ geographic north and y-axis pointing towards the west)
11
19
  3. Mercator system
12
20
 
13
21
  Command line arguments
14
22
  ----------------------
15
- array_element_list (str)
16
- File name with list of array element positions (ecsv format)
23
+ input (str)
24
+ File name with list of array element positions
17
25
  compact (str)
18
- Compact output (in requested coordinate system; possible are corsika,utm,mercator)
26
+ Compact output in requested coordinate system; possible are corsika,utm,mercator
19
27
  export (str)
20
- Export array element list to file (in requested coordinate system; \
21
- possible are corsika,utm,mercator)
28
+ Export array element list to file in requested coordinate system; \
29
+ possible are ground, utm, mercator
22
30
  use_corsika_telescope_height (bool)
23
- Use CORSIKA coordinates for telescope heights (requires CORSIKA observeration level)
31
+ Use CORSIKA coordinates for telescope heights (requires CORSIKA observation level)
32
+ select_assets (str)
33
+ Select a subset of array elements / telescopes (e.g., MSTN, LSTN)
24
34
 
25
35
 
26
36
  Example
27
37
  -------
28
38
  Print a list of array elements using a list of telescope positions in UTM coordinates.
29
39
 
30
- Example:
31
-
32
- Run the application:
33
-
34
40
  .. code-block:: console
35
41
 
36
- simtools-print-array-elements \
37
- --array_element_list tests/resources/telescope_positions-South-4MST.ecsv \
38
- --compact corsika
42
+ simtools-print-array-elements \\
43
+ --input tests/resources/telescope_positions-South-4MST.ecsv \\
44
+ --compact ground
39
45
 
40
46
  Expected final print-out message:
41
47
 
42
48
  .. code-block:: console
43
49
 
44
- telescope_name pos_x pos_y altitude
45
- MST-01 -0.02 -0.00 2162.00
46
- MST-02 1.43 151.02 2163.00
47
- MST-03 -1.47 -151.02 2169.00
48
- MST-04 150.72 73.57 2159.00
50
+ telescope_name pos_x pos_y altitude
51
+ MST-01 -0.02 -0.00 2162.00
52
+ MST-02 1.43 151.02 2163.00
53
+ MST-03 -1.47 -151.02 2169.00
54
+ MST-04 150.72 73.57 2159.00
49
55
 
56
+ The following example converts a list of telescope positions in UTM coordinates \
57
+ and writes the output to a file in ground (sim_telarray) coordinates. Also selects \
58
+ only a subset of the array elements (telescopes; ignore calibration devices):
50
59
 
60
+ .. code-block:: console
61
+
62
+ simtools-print-array-elements \\
63
+ --input tests/resources/telescope_positions-North-utm.ecsv \\
64
+ --export ground --use_corsika_telescope_height \\
65
+ --select_assets LSTN, MSTN, SSTN
66
+
67
+ Expected output is a ecsv file in the directory printed to the screen.
51
68
 
52
69
  """
53
70
 
54
71
  import logging
55
72
  from pathlib import Path
56
73
 
74
+ import simtools.data_model.model_data_writer as writer
57
75
  import simtools.utils.general as gen
58
76
  from simtools.configuration import configurator
59
- from simtools.layout import layout_array
77
+ from simtools.data_model.metadata_collector import MetadataCollector
78
+ from simtools.layout import array_layout
60
79
 
61
80
 
62
81
  def _parse(label=None, description=None):
@@ -80,9 +99,15 @@ def _parse(label=None, description=None):
80
99
  config = configurator.Configurator(label=label, description=description)
81
100
 
82
101
  config.parser.add_argument(
83
- "--array_element_list",
84
- help="list of array element positions (ecsv format)",
85
- required=True,
102
+ "--input",
103
+ help="list of array element positions",
104
+ required=False,
105
+ )
106
+ config.parser.add_argument(
107
+ "--input_meta",
108
+ help="meta data file associated to input data",
109
+ type=str,
110
+ required=False,
86
111
  )
87
112
  config.parser.add_argument(
88
113
  "--compact",
@@ -90,7 +115,7 @@ def _parse(label=None, description=None):
90
115
  required=False,
91
116
  default="",
92
117
  choices=[
93
- "corsika",
118
+ "ground",
94
119
  "utm",
95
120
  "mercator",
96
121
  ],
@@ -101,14 +126,14 @@ def _parse(label=None, description=None):
101
126
  required=False,
102
127
  default=None,
103
128
  choices=[
104
- "corsika",
129
+ "ground",
105
130
  "utm",
106
131
  "mercator",
107
132
  ],
108
133
  )
109
134
  config.parser.add_argument(
110
135
  "--use_corsika_telescope_height",
111
- help="Use CORSIKA coordinates for telescope heights (requires CORSIKA observeration level)",
136
+ help="Use CORSIKA coordinates for telescope heights (requires CORSIKA observation level)",
112
137
  required=False,
113
138
  default=False,
114
139
  action="store_true",
@@ -120,23 +145,45 @@ def _parse(label=None, description=None):
120
145
  default=None,
121
146
  nargs="+",
122
147
  )
123
- return config.initialize()
148
+ config.parser.add_argument(
149
+ "--skip_input_validation",
150
+ help="skip input data validation against schema",
151
+ default=False,
152
+ required=False,
153
+ action="store_true",
154
+ )
155
+ return config.initialize(output=True, require_command_line=True)
124
156
 
125
157
 
126
158
  def main():
127
159
  label = Path(__file__).stem
128
- args_dict, _ = _parse(label, description="Print a list of array element positions")
160
+ data_model_name = "array_coordinates"
161
+ args_dict, _ = _parse(
162
+ label,
163
+ description=f"Print a list of array element positions ({data_model_name})",
164
+ )
129
165
 
130
166
  _logger = logging.getLogger()
131
167
  _logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
132
168
 
133
- layout = layout_array.LayoutArray(telescope_list_file=args_dict["array_element_list"])
169
+ layout = array_layout.ArrayLayout(
170
+ telescope_list_file=args_dict["input"],
171
+ telescope_list_metadata_file=args_dict["input_meta"],
172
+ validate=not args_dict["skip_input_validation"],
173
+ )
134
174
  layout.select_assets(args_dict["select_assets"])
135
175
  layout.convert_coordinates()
176
+
136
177
  if args_dict["export"] is not None:
137
- layout.export_telescope_list(
138
- crs_name=args_dict["export"],
139
- corsika_z=args_dict["use_corsika_telescope_height"],
178
+ _metadata = MetadataCollector(args_dict=args_dict, data_model_name=data_model_name)
179
+ writer.ModelDataWriter.dump(
180
+ args_dict=args_dict,
181
+ metadata=_metadata.top_level_meta,
182
+ product_data=layout.export_telescope_list_table(
183
+ crs_name=args_dict["export"],
184
+ corsika_z=args_dict["use_corsika_telescope_height"],
185
+ ),
186
+ validate_schema_file=_metadata.get_data_model_schema_file_name(),
140
187
  )
141
188
  else:
142
189
  layout.print_telescope_list(
@@ -65,7 +65,7 @@
65
65
  array_config (str, required)
66
66
  Path to a yaml file with the array config data.
67
67
  verbosity (str, optional)
68
- Log level to print (default=INFO).
68
+ Log level to print.
69
69
 
70
70
  Example
71
71
  -------
@@ -75,7 +75,7 @@
75
75
 
76
76
  .. code-block:: console
77
77
 
78
- python applications/get_file_from_db.py --file_name array_config_test.yml
78
+ simtools-get-file-from-db --file_name array_config_test.yml
79
79
 
80
80
  Run the application. Runtime < 1 min.
81
81
 
@@ -43,9 +43,14 @@
43
43
  If activated, no job will be submitted, but all configuration files \
44
44
  and run scripts will be created.
45
45
  data_directory (str, optional)
46
- The location of the output directories corsika-data and simtel-data
46
+ The location of the output directories corsika-data and simtel-data.
47
+ corsika_files (str, optional)
48
+ The CORSIKA files to pass to simtel_array.
49
+ If it is provided, these CORSIKA files are used and the application does not search for them
50
+ in the data directory.
51
+ This option should only be used in combination with the `showers_only` option.
47
52
  verbosity (str, optional)
48
- Log level to print (default=INFO).
53
+ Log level to print.
49
54
 
50
55
  Example
51
56
  -------
@@ -55,7 +60,7 @@
55
60
 
56
61
  .. code-block:: console
57
62
 
58
- simtools-get-file-from_db --file_name prod_config_test.yml
63
+ simtools-get-file-from-db --file_name prod_config_test.yml
59
64
 
60
65
  Run the application:
61
66
 
@@ -76,6 +81,7 @@
76
81
 
77
82
  import logging
78
83
  from copy import copy
84
+ from pathlib import Path
79
85
 
80
86
  from astropy.io.misc import yaml
81
87
 
@@ -142,6 +148,13 @@ def _parse(description=None):
142
148
  required=False,
143
149
  default="./",
144
150
  )
151
+ config.parser.add_argument(
152
+ "--corsika_files",
153
+ help="The CORSIKA files to pass to simtel_array.",
154
+ type=str,
155
+ required=False,
156
+ default=None,
157
+ )
145
158
  group = config.parser.add_mutually_exclusive_group(required=True)
146
159
  group.add_argument(
147
160
  "--showers_only",
@@ -221,7 +234,6 @@ def _proccess_simulation_config_file(config_file, primary_config, logger):
221
234
  for key, value in this_default.items():
222
235
  config_showers[primary][key] = value
223
236
  config_arrays[primary][key] = value
224
-
225
237
  return label, config_showers, config_arrays
226
238
 
227
239
 
@@ -237,6 +249,11 @@ def main():
237
249
  if args_dict["label"] is None:
238
250
  args_dict["label"] = label
239
251
 
252
+ if args_dict["corsika_files"] is not None and args_dict["array_only"] is False:
253
+ msg = "`--corsika_files` option should be used only with `--array_only` argument."
254
+ logger.error(msg)
255
+ raise ValueError
256
+
240
257
  shower_simulators = {}
241
258
  for primary, config_data in shower_configs.items():
242
259
  if "data_directory" in args_dict:
@@ -270,7 +287,24 @@ def main():
270
287
  mongo_db_config=db_config,
271
288
  )
272
289
  for primary, array in array_simulators.items():
273
- input_list = shower_simulators[primary].get_list_of_output_files()
290
+ if args_dict["corsika_files"] is None:
291
+ input_list = shower_simulators[primary].get_list_of_output_files()
292
+ else:
293
+ if not isinstance(args_dict["corsika_files"], list):
294
+ args_dict["corsika_files"] = [args_dict["corsika_files"]]
295
+ input_list = args_dict["corsika_files"]
296
+
297
+ for corsika_file in input_list:
298
+ if not Path(corsika_file).exists():
299
+ msg = (
300
+ f"CORSIKA file {corsika_file} does not exist. Please run the "
301
+ "production with the `--showers_only` option first or point the "
302
+ "tool to the correct path to the corsika files with "
303
+ "`--corsika_directory`."
304
+ )
305
+ logger.error(msg)
306
+ raise FileNotFoundError
307
+ logger.info(f"Getting CORSIKA files: {input_list}.")
274
308
  _task_function = getattr(array, args_dict["task"])
275
309
  _task_function(input_file_list=input_list)
276
310
 
@@ -25,21 +25,22 @@
25
25
  primary (str, required)
26
26
  Name of the primary particle (proton, helium ...).
27
27
  nruns (int, optional)
28
- Number of runs to be simulated (default=100).
28
+ Number of runs to be simulated.
29
29
  nevents (int, optional)
30
- Number of events simulated per run (default=100000).
30
+ Number of events simulated per run.
31
31
  zenith (float, optional)
32
- Zenith angle in deg (default=20).
32
+ Zenith angle in deg.
33
33
  azimuth (float, optional)
34
- Azimuth angle in deg (default=0).
35
- output (str, optional)
36
- Path of the directory to store the output simulations. By default, \
37
- the standard output directory defined by config will be used.
34
+ Azimuth angle in deg.
35
+ data_directory (str, optional)
36
+ The location of the output directories corsika-data.
37
+ the label is added to the data_directory, such that the output
38
+ will be written to `data_directory/label/corsika-data`.
38
39
  test (activation mode, optional)
39
40
  If activated, no job will be submitted. Instead, an example of the \
40
41
  run script will be printed.
41
42
  verbosity (str, optional)
42
- Log level to print (default=INFO).
43
+ Log level to print.
43
44
 
44
45
  Example
45
46
  -------
@@ -47,7 +48,7 @@
47
48
 
48
49
  .. code-block:: console
49
50
 
50
- simtools-sim-showers-for-trigger_rates --array 4LST --site North --primary \
51
+ simtools-sim-showers-for-trigger-rates --array 4LST --site North --primary \
51
52
  proton --nruns 2 --nevents 10000 --test --submit_command local
52
53
 
53
54
  The output is saved in simtools-output/sim_showers_for_trigger_rates.
@@ -68,8 +69,8 @@ from pathlib import Path
68
69
 
69
70
  import astropy.units as u
70
71
 
71
- from simtools import io_handler
72
72
  from simtools.configuration import configurator
73
+ from simtools.io_operations import io_handler
73
74
  from simtools.simulator import Simulator
74
75
  from simtools.utils import general as gen
75
76
 
@@ -105,24 +106,20 @@ def _parse(label=None, description=None):
105
106
  type=str,
106
107
  required=True,
107
108
  )
109
+ config.parser.add_argument("--nruns", help="Number of runs", type=int, default=100)
110
+ config.parser.add_argument("--nevents", help="Number of events/run", type=int, default=100000)
111
+ config.parser.add_argument("--zenith", help="Zenith angle in deg", type=float, default=20)
112
+ config.parser.add_argument("--azimuth", help="Azimuth angle in deg", type=float, default=0)
108
113
  config.parser.add_argument(
109
- "--nruns", help="Number of runs (default=100)", type=int, default=100
110
- )
111
- config.parser.add_argument(
112
- "--nevents", help="Number of events/run (default=100)", type=int, default=100000
113
- )
114
- config.parser.add_argument(
115
- "--zenith", help="Zenith angle in deg (default=20)", type=float, default=20
116
- )
117
- config.parser.add_argument(
118
- "--azimuth", help="Azimuth angle in deg (default=0)", type=float, default=0
119
- )
120
- # TODO confusing with output_path?
121
- config.parser.add_argument(
122
- "--output",
123
- help="Path of the output directory where the simulations will be saved.",
124
- type=str,
125
- default=None,
114
+ "--data_directory",
115
+ help=(
116
+ "The directory where to save the corsika-data output directories."
117
+ "the label is added to the data_directory, such that the output"
118
+ "will be written to `data_directory/label/corsika-data`."
119
+ ),
120
+ type=str.lower,
121
+ required=False,
122
+ default="./simtools-output/",
126
123
  )
127
124
  return config.initialize(telescope_model=True, job_submission=True, db_config=True)
128
125
 
@@ -138,10 +135,9 @@ def main():
138
135
 
139
136
  # Output directory to save files related directly to this app
140
137
  _io_handler = io_handler.IOHandler()
141
- output_dir = _io_handler.get_output_directory(label, dir_type="application-plots")
142
- print(output_dir)
138
+ output_dir = _io_handler.get_output_directory(label, sub_dir="application-plots")
143
139
  shower_config_data = {
144
- "data_directory": args_dict["output"],
140
+ "data_directory": Path(args_dict["data_directory"]) / label,
145
141
  "site": args_dict["site"],
146
142
  "layout_name": args_dict["array"],
147
143
  "run_range": [1, args_dict["nruns"] + 1],
@@ -10,8 +10,8 @@
10
10
 
11
11
  The entire simulation chain is performed, i.e., shower simulations with CORSIKA
12
12
  which are piped directly to sim_telarray using the sim_telarray multipipe mechanism.
13
- This script assumes that all the necessary configuration files for CORISKA and
14
- sim_telarray are available. FIXME - This is not true at the moment, need to fix I guess.
13
+ This script produces all the necessary configuration files for CORSIKA and
14
+ sim_telarray before running simulation.
15
15
  The multipipe scripts will be produced as part of this script.
16
16
 
17
17
  This script does not provide a mechanism to submit jobs to a batch system like others
@@ -48,9 +48,14 @@
48
48
  run (int, required)
49
49
  Run number (actual run number will be 'start_run' + 'run').
50
50
  data_directory (str, optional)
51
- The location of the output directories corsika-data and simtel-data
51
+ The location of the output directories corsika-data and simtel-data.
52
+ the label is added to the data_directory, such that the output
53
+ will be written to `data_directory/label/simtel-data`.
54
+ pack_for_grid_register (bool, optional)
55
+ Set whether to prepare a tarball for registering the output files on the grid.
56
+ The files are written to the `output_path/directory_for_grid_upload` directory.
52
57
  log_level (str, optional)
53
- Log level to print (default=INFO).
58
+ Log level to print.
54
59
 
55
60
  Example
56
61
  -------
@@ -61,20 +66,23 @@
61
66
  simtools-simulate-prod \
62
67
  --production_config tests/resources/prod_multi_config_test.yml --model_version Prod5 \
63
68
  --site north --primary gamma --azimuth_angle north --zenith_angle 20 \
64
- --start_run 0 --run 1
69
+ --start_run 0 --run 1
65
70
 
66
71
  By default the configuration is saved in simtools-output/test-production
67
- and the output in corsika-data and simtel-data. The location of the latter directories
68
- can be set to a different location via the option --data_directory.
72
+ together with the actual simulation output in corsika-data and simtel-data within.
73
+ The location of the latter directories can be set
74
+ to a different location via the option --data_directory,
75
+ but the label is always added to the data_directory, such that the output
76
+ will be written to `data_directory/label/simtel-data`.
69
77
 
70
78
  Expected final print-out message:
71
79
 
72
80
  .. code-block:: console
73
81
 
74
- INFO::layout_array(l569)::read_telescope_list_file::Reading array elements from ...
82
+ INFO::array_layout(l569)::read_telescope_list_file::Reading array elements from ...
75
83
  WARNING::corsika_runner(l127)::_load_corsika_config_data::data_directory not given
76
84
  in corsika_config - default output directory will be set.
77
- INFO::layout_array(l569)::read_telescope_list_file::Reading array elements from ...
85
+ INFO::array_layout(l569)::read_telescope_list_file::Reading array elements from ...
78
86
  INFO::corsika_config(l493)::_set_output_file_and_directory::Creating directory
79
87
  INFO::simulator(l405)::simulate::Submission command: local
80
88
  INFO::simulator(l410)::simulate::Starting submission for 1 run
@@ -87,8 +95,8 @@
87
95
  """
88
96
 
89
97
  import logging
98
+ import shutil
90
99
  import tarfile
91
- from copy import copy
92
100
  from pathlib import Path
93
101
 
94
102
  from astropy.io.misc import yaml
@@ -184,10 +192,14 @@ def _parse(description=None):
184
192
  )
185
193
  config.parser.add_argument(
186
194
  "--data_directory",
187
- help="The directory where to save the corsika-data and simtel-data output directories.",
195
+ help=(
196
+ "The directory where to save the corsika-data and simtel-data output directories."
197
+ "the label is added to the data_directory, such that the output"
198
+ "will be written to `data_directory/label/simtel-data`."
199
+ ),
188
200
  type=str.lower,
189
201
  required=False,
190
- default="./",
202
+ default="./simtools-output/",
191
203
  )
192
204
  config.parser.add_argument(
193
205
  "--pack_for_grid_register",
@@ -199,112 +211,40 @@ def _parse(description=None):
199
211
  return config.initialize(db_config=True, telescope_model=True)
200
212
 
201
213
 
202
- def _proccess_simulation_config_file(config_file, primary_config, logger):
203
- """
204
- Read the simulation configuration file with all the details
205
- on shower and array simulations.
206
-
207
- Parameters
208
- ----------
209
- config_file: str
210
- Name of simulation configuration file.
211
- primary_config: str
212
- Name of the primary selected from the configuration file.
213
- logger: logging.logger
214
- The logger to use to record log calls.
215
-
216
- Returns
217
- -------
218
- str
219
- Label of simulation configuration.
220
- dict
221
- Configuration of shower simulations.
222
- dict
223
- Configuration of array simulations.
224
-
225
- Raises
226
- ------
227
- FileNotFoundError
228
- """
229
-
230
- try:
231
- with open(config_file, encoding="utf-8") as file:
232
- config_data = yaml.load(file)
233
- except FileNotFoundError:
234
- logger.error(f"Error loading simulation configuration file from {config_file}")
235
- raise
236
-
237
- label = config_data.pop("label", "test_run")
238
- default_data = config_data.pop("default", {})
239
-
240
- for primary, primary_data in config_data.items():
241
- if primary_config is not None and primary != primary_config:
242
- continue
243
-
244
- this_default = copy(default_data)
245
-
246
- config_showers = copy(this_default.pop("showers", {}))
247
- config_arrays = copy(this_default.pop("array", {}))
248
-
249
- # Grabbing common entries for showers and array
250
- for key, value in primary_data.items():
251
- if key in ["showers", "array"]:
252
- continue
253
- config_showers[key] = value
254
- config_arrays[key] = value
255
-
256
- # Grabbing showers entries
257
- for key, value in primary_data.get("showers", {}).items():
258
- config_showers[key] = value
259
- config_showers["primary"] = primary
260
-
261
- # Grabbing array entries
262
- for key, value in primary_data.get("array", {}).items():
263
- config_arrays[key] = value
264
- config_arrays["primary"] = primary
265
-
266
- # Filling in the remaining default keys
267
- for key, value in this_default.items():
268
- config_showers[key] = value
269
- config_arrays[key] = value
270
-
271
- config_arrays["data_directory"] = config_showers["data_directory"]
272
- config_arrays["site"] = config_showers["site"]
273
- config_arrays["layout_name"] = config_showers["layout_name"]
274
-
275
- return label, config_showers, config_arrays
276
-
277
-
278
214
  def main():
279
215
  args_dict, db_config = _parse(description="Run simulations for productions")
280
216
 
281
217
  logger = logging.getLogger()
282
218
  logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
283
219
 
284
- label, shower_configs, array_configs = _proccess_simulation_config_file(
285
- args_dict["production_config"], args_dict["primary"], logger
286
- )
220
+ try:
221
+ with open(args_dict["production_config"], encoding="utf-8") as file:
222
+ config_data = yaml.load(file)
223
+ except FileNotFoundError:
224
+ logger.error(
225
+ f"Error loading simulation configuration file from {args_dict['production_config']}"
226
+ )
227
+ raise
287
228
 
288
229
  # Overwrite default and optional settings
289
- shower_configs["run_list"] = args_dict["run"] + args_dict["start_run"]
290
- array_configs["site"] = shower_configs["site"] = args_dict["site"]
291
- array_configs["zenith"] = shower_configs["zenith"] = args_dict["zenith_angle"]
292
- array_configs["phi"] = shower_configs["phi"] = args_dict["azimuth_angle"]
230
+ config_data["showers"]["run_list"] = args_dict["run"] + args_dict["start_run"]
231
+ config_data["showers"]["primary"] = args_dict["primary"]
232
+ config_data["common"]["site"] = args_dict["site"]
233
+ config_data["common"]["zenith"] = args_dict["zenith_angle"]
234
+ config_data["common"]["phi"] = args_dict["azimuth_angle"]
235
+ label = config_data["common"].pop("label", "test-production")
236
+ config_data["common"]["data_directory"] = Path(args_dict["data_directory"]) / label
293
237
 
294
238
  if args_dict["nshow"] is not None:
295
- shower_configs["nshow"] = args_dict["nshow"]
239
+ config_data["showers"]["nshow"] = args_dict["nshow"]
296
240
  if args_dict["label"] is not None:
297
241
  label = args_dict["label"]
298
- if "data_directory" in args_dict:
299
- array_configs["data_directory"] = shower_configs["data_directory"] = args_dict[
300
- "data_directory"
301
- ]
302
242
 
303
243
  simulator = Simulator(
304
244
  label=label,
305
245
  simulator="corsika_simtel",
306
246
  simulator_source_path=args_dict["simtel_path"],
307
- config_data=shower_configs | array_configs,
247
+ config_data=config_data,
308
248
  submit_command="local",
309
249
  test=args_dict["test"],
310
250
  mongo_db_config=db_config,
@@ -313,10 +253,10 @@ def main():
313
253
  simulator.simulate()
314
254
 
315
255
  logger.info(
316
- f"Production run is complete for primary {shower_configs['primary']} showers "
317
- f"coming from {shower_configs['phi']} azimuth and zenith angle of "
318
- f"{shower_configs['zenith']} at the {args_dict['site']} site, "
319
- f"using the {array_configs['model_version']} telescope model."
256
+ f"Production run is complete for primary {config_data['showers']['primary']} showers "
257
+ f"coming from {config_data['common']['phi']} azimuth and zenith angle of "
258
+ f"{config_data['common']['zenith']} at the {args_dict['site']} site, "
259
+ f"using the {config_data['array']['model_version']} telescope model."
320
260
  )
321
261
 
322
262
  if args_dict["pack_for_grid_register"]:
@@ -329,7 +269,9 @@ def main():
329
269
  files_to_tar = log_files[:1] + histogram_files[:1]
330
270
  for file_to_tar in files_to_tar:
331
271
  tar.add(file_to_tar, arcname=Path(file_to_tar).name)
332
- directory_for_grid_upload = Path("directory_for_grid_upload")
272
+ directory_for_grid_upload = Path(args_dict.get("output_path")).joinpath(
273
+ "directory_for_grid_upload"
274
+ )
333
275
  directory_for_grid_upload.mkdir(parents=True, exist_ok=True)
334
276
  for file_to_move in [*output_files, tar_file_name]:
335
277
  source_file = Path(file_to_move)
@@ -337,7 +279,7 @@ def main():
337
279
  # Note that this will overwrite previous files which exist in the directory
338
280
  # It should be fine for normal production since each run is on a separate node
339
281
  # so no files are expected there.
340
- source_file.replace(destination_file)
282
+ shutil.move(source_file, destination_file)
341
283
  logger.info(f"Output files for the grid placed in {str(directory_for_grid_upload)}")
342
284
 
343
285