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
@@ -3,13 +3,13 @@ import os
3
3
  from copy import copy
4
4
  from pathlib import Path
5
5
 
6
- from simtools import io_handler
7
6
  from simtools.corsika.corsika_config import (
8
7
  CorsikaConfig,
9
8
  MissingRequiredInputInCorsikaConfigData,
10
9
  )
10
+ from simtools.io_operations import io_handler
11
11
  from simtools.utils import names
12
- from simtools.utils.general import collect_data_from_yaml_or_dict
12
+ from simtools.utils.general import collect_data_from_file_or_dict
13
13
 
14
14
  __all__ = ["CorsikaRunner", "MissingRequiredEntryInCorsikaConfig"]
15
15
 
@@ -96,7 +96,7 @@ class CorsikaRunner:
96
96
 
97
97
  self.label = label
98
98
  self.site = names.validate_site_name(site)
99
- self.layout_name = names.validate_layout_array_name(layout_name)
99
+ self.layout_name = names.validate_array_layout_name(layout_name)
100
100
 
101
101
  self._keep_seeds = keep_seeds
102
102
 
@@ -106,7 +106,8 @@ class CorsikaRunner:
106
106
  self._output_directory = self.io_handler.get_output_directory(self.label, _runner_directory)
107
107
  self._logger.debug(f"Creating output dir {self._output_directory}, if needed,")
108
108
 
109
- corsika_config_data = collect_data_from_yaml_or_dict(
109
+ self._corsika_parameters_file = corsika_parameters_file
110
+ corsika_config_data = collect_data_from_file_or_dict(
110
111
  corsika_config_file, corsika_config_data
111
112
  )
112
113
  self._load_corsika_config_data(corsika_config_data)
@@ -151,6 +152,7 @@ class CorsikaRunner:
151
152
  layout_name=self.layout_name,
152
153
  corsika_config_data=self._corsika_config_data,
153
154
  simtel_source_path=self._simtel_source_path,
155
+ corsika_parameters_file=self._corsika_parameters_file,
154
156
  )
155
157
  # CORSIKA input file used as template for all runs
156
158
  self._corsika_input_file = self.corsika_config.get_input_file(use_multipipe)
@@ -239,6 +241,8 @@ class CorsikaRunner:
239
241
  if use_pfp:
240
242
  file.write("\n# Running pfp\n")
241
243
  file.write(pfp_command)
244
+ file.write("\n# Replacing the XXXXXX placeholder with the run number\n")
245
+ file.write(f"sed -i 's/XXXXXX/{run_number:06}/g' {corsika_input_tmp_file}\n")
242
246
  else:
243
247
  file.write("\n# Copying CORSIKA input file to run location\n")
244
248
  file.write(f"cp {self._corsika_input_file} {corsika_input_tmp_file}")
@@ -90,7 +90,7 @@ class CorsikaSimtelRunner(CorsikaRunner, SimtelRunnerArray):
90
90
  run_number=run_number,
91
91
  input_file="-", # Tell sim_telarray to take the input from standard output
92
92
  )
93
- multipipe_file = Path(self.corsika_config._config_file_path.parent).joinpath(
93
+ multipipe_file = Path(self.corsika_config.config_file_path.parent).joinpath(
94
94
  self.corsika_config.get_file_name("multipipe")
95
95
  )
96
96
  with open(multipipe_file, "w", encoding="utf-8") as file:
@@ -107,7 +107,7 @@ class CorsikaSimtelRunner(CorsikaRunner, SimtelRunnerArray):
107
107
  The name of the multipipe file which contains all of the multipipe commands.
108
108
  """
109
109
 
110
- multipipe_executable = Path(self.corsika_config._config_file_path.parent).joinpath(
110
+ multipipe_executable = Path(self.corsika_config.config_file_path.parent).joinpath(
111
111
  "run_cta_multipipe"
112
112
  )
113
113
  with open(multipipe_executable, "w", encoding="utf-8") as file:
@@ -136,34 +136,29 @@ class CorsikaSimtelRunner(CorsikaRunner, SimtelRunnerArray):
136
136
 
137
137
  """
138
138
 
139
- # TODO: These definitions of the files can probably be separated from
140
- # the the run command and put back into the parent class.
141
139
  info_for_file_name = SimtelRunnerArray.get_info_for_file_name(self, kwargs["run_number"])
142
- self._log_file = SimtelRunnerArray.get_file_name(
143
- self, file_type="log", **info_for_file_name
144
- )
145
- histogram_file = SimtelRunnerArray.get_file_name(
146
- self, file_type="histogram", **info_for_file_name
147
- )
148
- output_file = SimtelRunnerArray.get_file_name(
149
- self, file_type="output", **info_for_file_name
150
- )
140
+ weak_pointing = any(pointing in self.label for pointing in ["divergent", "convergent"])
151
141
 
152
- # TODO: Implement the weak pointing for divergent pointing
153
- # TODO: Think how to create multiple run commands for various pipes (e.g., NSB levels)
154
- # Array
155
142
  command = str(self._simtel_source_path.joinpath("sim_telarray/bin/sim_telarray"))
156
143
  command += f" -c {self.array_model.get_config_file()}"
157
144
  command += f" -I{self.array_model.get_config_directory()}"
158
- command += super()._config_option("telescope_theta", self.config.zenith_angle)
159
- command += super()._config_option("telescope_phi", self.config.azimuth_angle)
160
- command += super()._config_option("power_law", "2.5")
161
- command += super()._config_option("histogram_file", histogram_file)
162
- command += super()._config_option("output_file", output_file)
163
- command += super()._config_option("random_state", "auto")
145
+ command += super()._config_option(
146
+ "telescope_theta", self.config.zenith_angle, weak_option=weak_pointing
147
+ )
148
+ command += super()._config_option(
149
+ "telescope_phi", self.config.azimuth_angle, weak_option=weak_pointing
150
+ )
151
+ command += super()._config_option("power_law", abs(self.corsika_config.eslope))
152
+ command += super()._config_option(
153
+ "histogram_file", self.get_file_name("histogram", **info_for_file_name)
154
+ )
155
+ command += super()._config_option(
156
+ "output_file", self.get_file_name("output", **info_for_file_name)
157
+ )
158
+ command += super()._config_option("random_state", "none")
164
159
  command += super()._config_option("show", "all")
165
160
  command += f" {kwargs['input_file']}"
166
- command += f" | gzip > {self._log_file} 2>&1 || exit"
161
+ command += f" | gzip > {self.get_file_name('log', **info_for_file_name)} 2>&1 || exit"
167
162
 
168
163
  return command
169
164
 
@@ -0,0 +1,129 @@
1
+ import logging
2
+
3
+ import astropy.units as u
4
+ from astropy.io.registry.base import IORegistryError
5
+ from astropy.table import QTable
6
+
7
+ import simtools.utils.general as gen
8
+ from simtools.data_model import metadata_model, validate_data
9
+ from simtools.data_model.metadata_collector import MetadataCollector
10
+
11
+ __all__ = ["read_table_from_file", "read_value_from_file"]
12
+
13
+ _logger = logging.getLogger(__name__)
14
+
15
+
16
+ def read_table_from_file(file_name, schema_file=None, validate=False, metadata_file=None):
17
+ """
18
+ Read astropy table from file and validate against schema.
19
+ Metadata is read from metadata file or from the metadata section of the data file.
20
+ Schema for validation can be given as argument, or is determined
21
+ from the metadata associated to the file.
22
+
23
+ Parameters:
24
+ -----------
25
+ file_name: str or Path
26
+ Name of file to be read.
27
+ schema_file: str or Path
28
+ Name of schema file to be used for validation.
29
+ validate: bool
30
+ Validate data against schema (if true).
31
+ metadata_file: str or Path
32
+ Name of metadata file to be read.
33
+
34
+ Returns:
35
+ --------
36
+ astropy Table
37
+ Table read from file.
38
+
39
+ Raises
40
+ ------
41
+ FileNotFoundError
42
+ If file does not exist.
43
+
44
+ """
45
+
46
+ try:
47
+ data_table = QTable.read(file_name)
48
+ except (FileNotFoundError, IORegistryError) as exc:
49
+ _logger.error("Error reading tabled data from %s", file_name)
50
+ raise exc
51
+ _logger.info("Reading table data from %s", file_name)
52
+
53
+ if validate:
54
+ metadata = MetadataCollector(
55
+ args_dict=None,
56
+ metadata_file_name=(metadata_file if metadata_file is not None else file_name),
57
+ data_model_name=None,
58
+ )
59
+
60
+ _validator = validate_data.DataValidator(
61
+ schema_file=(
62
+ schema_file
63
+ if schema_file is not None
64
+ else metadata.get_data_model_schema_file_name()
65
+ ),
66
+ data_table=data_table,
67
+ )
68
+ return _validator.validate_and_transform()
69
+
70
+ return data_table
71
+
72
+
73
+ def read_value_from_file(file_name, schema_file=None, validate=False):
74
+ """
75
+ Read value from file and validate against schema. Expect data to follow the convention for
76
+ how simulation model parameters are stored in the simulation model database: to be a single
77
+ value stored in the 'value' field (with possible units in the 'units' field).
78
+ Metadata is read from metadata file or from the metadata section of the data file.
79
+ Schema for validation can be given as argument, or is determined
80
+ from the metadata associated to the file.
81
+
82
+ Parameters:
83
+ -----------
84
+ file_name: str or Path
85
+ Name of file to be read.
86
+ schema_file: str or Path
87
+ Name of schema file to be used for validation.
88
+ validate: bool
89
+ Validate data against schema (if true).
90
+
91
+ Returns:
92
+ --------
93
+ astro quantity or str
94
+ Value read from file. If units are given, return an astropy quantity, otherwise a string.
95
+ Return None if no value is found in the file.
96
+
97
+ Raises
98
+ ------
99
+ FileNotFoundError
100
+ If file does not exist.
101
+
102
+ """
103
+
104
+ try:
105
+ data = gen.collect_data_from_file_or_dict(file_name=file_name, in_dict=None)
106
+ except FileNotFoundError as exc:
107
+ _logger.error("Error reading data from %s", file_name)
108
+ raise exc
109
+ _logger.info("Reading data from %s", file_name)
110
+
111
+ if validate:
112
+ if schema_file is None and "meta_schema_url" in data:
113
+ schema_file = data["meta_schema_url"]
114
+ _logger.debug(f"Using schema from meta_schema_url: {schema_file}")
115
+ if schema_file is None:
116
+ _collector = MetadataCollector(None, metadata_file_name=file_name)
117
+ schema_file = _collector.get_data_model_schema_file_name()
118
+ _logger.debug(f"Using schema from meta_data_url: {schema_file}")
119
+
120
+ metadata_model.validate_schema(data, schema_file)
121
+ _logger.debug("Successful validation of yaml/json file")
122
+
123
+ if "Value" not in data or data["Value"] is None:
124
+ return None
125
+
126
+ if "units" in data and len(data["units"]) > 0:
127
+ return data["Value"] * u.Unit(data["units"])
128
+
129
+ return data["Value"]