gammasimtools 0.24.0__py3-none-any.whl → 0.25.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 (59) hide show
  1. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/METADATA +1 -1
  2. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/RECORD +58 -55
  3. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/entry_points.txt +1 -0
  4. simtools/_version.py +2 -2
  5. simtools/application_control.py +50 -0
  6. simtools/applications/derive_psf_parameters.py +5 -0
  7. simtools/applications/derive_pulse_shape_parameters.py +195 -0
  8. simtools/applications/plot_array_layout.py +63 -1
  9. simtools/applications/simulate_flasher.py +3 -2
  10. simtools/applications/simulate_pedestals.py +1 -1
  11. simtools/applications/simulate_prod.py +8 -23
  12. simtools/applications/simulate_prod_htcondor_generator.py +7 -0
  13. simtools/applications/submit_array_layouts.py +5 -3
  14. simtools/applications/validate_file_using_schema.py +49 -123
  15. simtools/configuration/commandline_parser.py +8 -6
  16. simtools/corsika/corsika_config.py +197 -87
  17. simtools/data_model/model_data_writer.py +14 -2
  18. simtools/data_model/schema.py +112 -5
  19. simtools/data_model/validate_data.py +82 -48
  20. simtools/db/db_model_upload.py +2 -1
  21. simtools/db/mongo_db.py +133 -42
  22. simtools/dependencies.py +5 -9
  23. simtools/io/eventio_handler.py +128 -0
  24. simtools/job_execution/htcondor_script_generator.py +0 -2
  25. simtools/layout/array_layout_utils.py +1 -1
  26. simtools/model/array_model.py +36 -5
  27. simtools/model/model_parameter.py +0 -1
  28. simtools/model/model_repository.py +18 -5
  29. simtools/ray_tracing/psf_analysis.py +11 -8
  30. simtools/ray_tracing/psf_parameter_optimisation.py +822 -679
  31. simtools/reporting/docs_read_parameters.py +69 -9
  32. simtools/runners/corsika_runner.py +12 -3
  33. simtools/runners/corsika_simtel_runner.py +6 -0
  34. simtools/runners/runner_services.py +17 -7
  35. simtools/runners/simtel_runner.py +12 -54
  36. simtools/schemas/model_parameters/flasher_pulse_exp_decay.schema.yml +2 -0
  37. simtools/schemas/model_parameters/flasher_pulse_shape.schema.yml +50 -0
  38. simtools/schemas/model_parameters/flasher_pulse_width.schema.yml +2 -0
  39. simtools/schemas/simulation_models_info.schema.yml +2 -0
  40. simtools/simtel/pulse_shapes.py +268 -0
  41. simtools/simtel/simtel_config_writer.py +82 -1
  42. simtools/simtel/simtel_io_event_writer.py +2 -2
  43. simtools/simtel/simulator_array.py +58 -12
  44. simtools/simtel/simulator_light_emission.py +45 -8
  45. simtools/simulator.py +361 -347
  46. simtools/testing/assertions.py +62 -6
  47. simtools/testing/configuration.py +1 -1
  48. simtools/testing/log_inspector.py +4 -1
  49. simtools/testing/sim_telarray_metadata.py +1 -1
  50. simtools/testing/validate_output.py +44 -9
  51. simtools/utils/names.py +2 -4
  52. simtools/version.py +37 -0
  53. simtools/visualization/legend_handlers.py +14 -4
  54. simtools/visualization/plot_array_layout.py +229 -33
  55. simtools/visualization/plot_mirrors.py +837 -0
  56. simtools/simtel/simtel_io_file_info.py +0 -62
  57. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/WHEEL +0 -0
  58. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/licenses/LICENSE +0 -0
  59. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/top_level.txt +0 -0
@@ -69,7 +69,7 @@ def _parse():
69
69
  help="Calibration run mode",
70
70
  type=str,
71
71
  required=True,
72
- choices=["pedestals", "dark_pedestals", "nsb_only_pedestals"],
72
+ choices=["pedestals", "pedestals_dark", "pedestals_nsb_only"],
73
73
  )
74
74
  config.parser.add_argument(
75
75
  "--number_of_events",
@@ -39,10 +39,6 @@ r"""
39
39
  It allows the transformation system to keep using sequential run numbers without repetition.
40
40
  run (int, required)
41
41
  Run number (actual run number will be 'start_run' + 'run').
42
- data_directory (str, optional)
43
- The location of the output directories corsika-data and simtel-data.
44
- the label is added to the data_directory, such that the output
45
- will be written to data_directory/label/simtel-data.
46
42
  pack_for_grid_register (str, optional)
47
43
  Set whether to prepare a tarball for registering the output files on the grid.
48
44
  The files are written to the specified directory.
@@ -58,13 +54,6 @@ r"""
58
54
  simtools-simulate-prod \\
59
55
  --model_version 5.0.0 --site north --primary gamma --azimuth_angle north \\
60
56
  --zenith_angle 20 --start_run 0 --run 1
61
-
62
- By default the configuration is saved in simtools-output/test-production
63
- together with the actual simulation output in corsika-data and simtel-data within.
64
- The location of the latter directories can be set
65
- to a different location via the option --data_directory,
66
- but the label is always added to the data_directory, such that the output
67
- will be written to data_directory/label/simtel-data.
68
57
  """
69
58
 
70
59
  from simtools.application_control import startup_application
@@ -76,15 +65,12 @@ def _parse():
76
65
  """Parse command line configuration."""
77
66
  config = configurator.Configurator(description="Run simulations for productions")
78
67
  config.parser.add_argument(
79
- "--data_directory",
68
+ "--corsika_file",
80
69
  help=(
81
- "The directory where to save the corsika-data and simtel-data output directories."
82
- "the label is added to the data_directory, such that the output"
83
- "will be written to data_directory/label/simtel-data."
70
+ "Path to the CORSIKA input file (only relevant for simulation software 'sim_telarray')."
84
71
  ),
85
- type=str.lower,
72
+ type=str,
86
73
  required=False,
87
- default="./simtools-output/",
88
74
  )
89
75
  config.parser.add_argument(
90
76
  "--pack_for_grid_register",
@@ -150,19 +136,18 @@ def main():
150
136
  simulator.simulate()
151
137
  simulator.validate_metadata()
152
138
 
153
- app_context.logger.info(
154
- f"Production run complete for primary {app_context.args['primary']} showers "
155
- f"from {app_context.args['azimuth_angle']} azimuth and "
156
- f"{app_context.args['zenith_angle']} zenith "
157
- f"at {app_context.args['site']} site, using {app_context.args['model_version']} model."
158
- )
159
139
  if app_context.args["save_reduced_event_lists"]:
160
140
  simulator.save_reduced_event_lists()
141
+
142
+ simulator.verify_simulations()
143
+
161
144
  if app_context.args.get("pack_for_grid_register"):
162
145
  simulator.pack_for_register(app_context.args["pack_for_grid_register"])
163
146
  if app_context.args["save_file_lists"]:
164
147
  simulator.save_file_lists()
165
148
 
149
+ simulator.report()
150
+
166
151
 
167
152
  if __name__ == "__main__":
168
153
  main()
@@ -56,6 +56,13 @@ def _parse():
56
56
  label=get_application_label(__file__),
57
57
  description="Prepare simulations production for HT Condor job submission",
58
58
  )
59
+ config.parser.add_argument(
60
+ "--number_of_runs",
61
+ help="Number of runs to be simulated.",
62
+ type=int,
63
+ required=True,
64
+ default=1,
65
+ )
59
66
  config.parser.add_argument(
60
67
  "--apptainer_image",
61
68
  help="Apptainer image to use for the simulation (full path).",
@@ -1,9 +1,11 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  r"""
4
- Submit array-layouts definition and corresponding metadata and validate list of telescopes.
4
+ Read array layouts from file, validate with telescopes in DB, and prepare for submission.
5
5
 
6
- Includes validation that all defined telescope exists.
6
+ Validates that all telescope defined in the array layouts exist in the database for the
7
+ specified model version. Prepares both JSON-style model parameters and corresponding
8
+ metadata for submission.
7
9
 
8
10
  Command line arguments
9
11
  ----------------------
@@ -19,7 +21,7 @@ r"""
19
21
  Example
20
22
  -------
21
23
 
22
- Submit a new array layout dictionary:
24
+ Submit and validate a new array layout dictionary:
23
25
 
24
26
  .. code-block:: console
25
27
 
@@ -3,26 +3,25 @@ r"""
3
3
  Validate a file or files in a directory using a schema.
4
4
 
5
5
  Input files can be metadata, schema, or data files in yaml, json, or ecsv format.
6
+ For model parameters, the schema files are taken from the simtools model parameter
7
+ schema directory by default.
6
8
 
7
9
  Command line arguments
8
10
  ----------------------
9
11
  file_name (str)
10
12
  input file to be validated
11
- model_parameters_directory (str)
13
+ file_directory (str)
12
14
  directory with json files of model parameters to be validated
13
15
  schema (str)
14
16
  schema file (jsonschema format) used for validation
15
17
  data_type (str)
16
- type of input data (allowed types: metadata, schema, data)
17
-
18
- Raises
19
- ------
20
- FileNotFoundError
21
- if file to be validated is not found
18
+ type of input data (allowed types: metadata, schema, data, model_parameter)
22
19
 
23
20
  Example
24
21
  -------
25
22
 
23
+ Validate metadata of a file:
24
+
26
25
  .. code-block:: console
27
26
 
28
27
  simtools-validate-file-using-schema \\
@@ -30,16 +29,29 @@ r"""
30
29
  --schema simtools/schemas/metadata.metaschema.yml \\
31
30
  --data_type metadata
32
31
 
33
- """
32
+ Validate schema of a file:
33
+
34
+ .. code-block:: console
35
+
36
+ simtools-validate-file-using-schema \\
37
+ --file_name tests/resources/model_parameters/schema-0.3.0/num_gains-1.0.0.json \\
38
+ --schema src/simtools/schemas/model_parameter.metaschema.yml \\
39
+ --data_type schema
34
40
 
35
- import re
36
- from pathlib import Path
41
+ Validate all model parameter files in a directory:
42
+
43
+ .. code-block:: console
44
+
45
+ simtools-validate-file-using-schema \\
46
+ --file_directory tests/resources/model_parameters \\
47
+ --data_type model_parameter
48
+
49
+ """
37
50
 
38
51
  from simtools.application_control import get_application_label, startup_application
39
52
  from simtools.configuration import configurator
40
53
  from simtools.constants import MODEL_PARAMETER_SCHEMA_PATH
41
54
  from simtools.data_model import metadata_collector, schema, validate_data
42
- from simtools.io import ascii_handler
43
55
 
44
56
 
45
57
  def _parse():
@@ -62,7 +74,7 @@ def _parse():
62
74
  f"{MODEL_PARAMETER_SCHEMA_PATH}."
63
75
  ),
64
76
  )
65
- config.parser.add_argument("--schema", help="Json schema file", required=False)
77
+ config.parser.add_argument("--schema", help="Schema file", required=False)
66
78
  config.parser.add_argument(
67
79
  "--data_type",
68
80
  help="Type of input data",
@@ -70,7 +82,7 @@ def _parse():
70
82
  default="data",
71
83
  )
72
84
  config.parser.add_argument(
73
- "--require_exact_data_type",
85
+ "--check_exact_data_type",
74
86
  help="Require exact data type for validation",
75
87
  action="store_true",
76
88
  )
@@ -82,121 +94,35 @@ def _parse():
82
94
  return config.initialize(paths=False)
83
95
 
84
96
 
85
- def _get_schema_file_name(args_dict, data_dict=None):
86
- """
87
- Get schema file name from metadata, data dict, or from command line argument.
88
-
89
- Parameters
90
- ----------
91
- args_dict (dict)
92
- command line arguments
93
- data_dict (dict)
94
- dictionary with metaschema information
95
-
96
- Returns
97
- -------
98
- schema_file: str
99
- schema file name
100
-
101
- """
102
- schema_file = args_dict.get("schema")
103
- if schema_file is None and data_dict is not None:
104
- schema_file = data_dict.get("meta_schema_url")
105
- if schema_file is None:
106
- metadata = metadata_collector.MetadataCollector(
107
- None, metadata_file_name=args_dict["file_name"]
108
- )
109
- schema_file = metadata.get_data_model_schema_file_name()
110
- return schema_file
111
-
112
-
113
- def _get_file_list(file_directory=None, file_name="*.json"):
114
- """Return list of files in a directory."""
115
- file_list = []
116
- if file_directory is not None:
117
- file_list = list(Path(file_directory).rglob(file_name))
118
- if not file_list:
119
- raise FileNotFoundError(f"No files found in {file_directory}")
120
- elif file_name is not None:
121
- file_list = [file_name]
122
-
123
- return file_list
124
-
125
-
126
- def validate_dict_using_schema(args_dict, logger):
127
- """
128
- Validate a schema file (or several files) given in yaml or json format.
129
-
130
- This function validate all documents in a multi-document YAML file.
131
- Schema is either given as command line argument, read from the meta_schema_url or from
132
- the metadata section of the data dictionary.
133
-
134
- """
135
- for file_name in _get_file_list(args_dict.get("file_directory"), args_dict.get("file_name")):
136
- try:
137
- data = ascii_handler.collect_data_from_file(file_name=file_name)
138
- except FileNotFoundError as exc:
139
- raise FileNotFoundError(f"Error reading schema file from {file_name}") from exc
140
- data = data if isinstance(data, list) else [data]
141
- try:
142
- for data_dict in data:
143
- schema.validate_dict_using_schema(
144
- data_dict,
145
- _get_schema_file_name(args_dict, data_dict),
146
- ignore_software_version=args_dict.get("ignore_software_version", False),
147
- )
148
- except Exception as exc:
149
- raise ValueError(f"Validation of file {file_name} failed") from exc
150
- logger.info(f"Successful validation of file {file_name}")
151
-
152
-
153
- def validate_data_files(args_dict, logger):
154
- """Validate data files."""
155
- if args_dict.get("file_directory") is not None:
156
- tmp_args_dict = {}
157
- for file_name in _get_file_list(args_dict.get("file_directory")):
158
- tmp_args_dict["file_name"] = file_name
159
- parameter_name = re.sub(r"-\d+\.\d+\.\d+", "", file_name.stem)
160
- schema_file = schema.get_model_parameter_schema_file(f"{parameter_name}")
161
- tmp_args_dict["schema"] = schema_file
162
- tmp_args_dict["data_type"] = "model_parameter"
163
- tmp_args_dict["require_exact_data_type"] = args_dict["require_exact_data_type"]
164
- validate_data_file(tmp_args_dict, logger)
165
- else:
166
- validate_data_file(args_dict, logger)
167
-
168
-
169
- def validate_data_file(args_dict, logger):
170
- """Validate a data file (e.g., in ecsv, json, yaml format)."""
171
- data_validator = validate_data.DataValidator(
172
- schema_file=_get_schema_file_name(args_dict),
173
- data_file=args_dict["file_name"],
174
- check_exact_data_type=args_dict["require_exact_data_type"],
175
- )
176
- data_validator.validate_and_transform(
177
- is_model_parameter=(args_dict["data_type"].lower() == "model_parameter")
178
- )
179
-
180
- logger.info(f"Successful validation of data file {args_dict['file_name']}")
181
-
182
-
183
- def validate_metadata(args_dict, logger):
184
- """Validate metadata."""
185
- # metadata_collector runs the metadata validation by default, no need to do anything else
186
- metadata_collector.MetadataCollector(None, metadata_file_name=args_dict["file_name"])
187
- logger.info(f"Successful validation of metadata {args_dict['file_name']}")
188
-
189
-
190
97
  def main():
191
98
  """Validate a file or files in a directory using a schema."""
192
99
  app_context = startup_application(_parse)
193
100
 
194
- if app_context.args["data_type"].lower() == "metadata":
195
- validate_metadata(app_context.args, app_context.logger)
196
- elif app_context.args["data_type"].lower() == "schema":
197
- validate_dict_using_schema(app_context.args, app_context.logger)
101
+ file_name = app_context.args.get("file_name")
102
+ file_directory = app_context.args.get("file_directory")
103
+ schema_file = app_context.args.get("schema")
104
+ data_type = app_context.args.get("data_type").lower()
105
+
106
+ if data_type == "metadata":
107
+ # metadata_collector runs the metadata validation by default, no need to do anything else
108
+ metadata_collector.MetadataCollector(None, metadata_file_name=file_name)
109
+ app_context.logger.info(f"Successful validation of metadata {file_name}")
110
+
111
+ elif data_type == "schema":
112
+ schema.validate_schema_from_files(
113
+ file_directory=file_directory,
114
+ file_name=file_name,
115
+ schema_file=schema_file,
116
+ ignore_software_version=app_context.args.get("ignore_software_version", False),
117
+ )
198
118
  else:
199
- validate_data_files(app_context.args, app_context.logger)
119
+ validate_data.DataValidator.validate_data_files(
120
+ file_name=file_name,
121
+ file_directory=file_directory,
122
+ is_model_parameter=(data_type == "model_parameter"),
123
+ check_exact_data_type=app_context.args.get("check_exact_data_type", False),
124
+ schema_file=schema_file,
125
+ )
200
126
 
201
127
 
202
128
  if __name__ == "__main__":
@@ -377,12 +377,6 @@ class CommandLineParser(argparse.ArgumentParser):
377
377
  "required": True,
378
378
  "default": 1,
379
379
  },
380
- "number_of_runs": {
381
- "help": "Number of runs to be simulated.",
382
- "type": int,
383
- "required": True,
384
- "default": 1,
385
- },
386
380
  "event_number_first_shower": {
387
381
  "help": "Event number of first shower",
388
382
  "type": int,
@@ -395,6 +389,14 @@ class CommandLineParser(argparse.ArgumentParser):
395
389
  "required": False,
396
390
  "default": True,
397
391
  },
392
+ "curved_atmosphere_min_zenith_angle": {
393
+ "help": (
394
+ "Minimum zenith angle (deg) for using curved-atmosphere CORSIKA binaries. "
395
+ ),
396
+ "type": CommandLineParser.zenith_angle,
397
+ "required": False,
398
+ "default": 65 * u.deg,
399
+ },
398
400
  }
399
401
 
400
402
  @staticmethod