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
@@ -0,0 +1,282 @@
1
+ from collections import defaultdict
2
+
3
+ import astropy.units as u
4
+ from scipy.interpolate import interp1d
5
+
6
+
7
+ class CorsikaDefaultConfig:
8
+ """
9
+ This class contains the default configuration for CORSIKA parameters for
10
+ the various primary particles. It includes all basic dependencies on zenith angles, etc.
11
+ The default values defined in this class assume the full CTAO arrays are simulated,
12
+ including full CTAO energy range and number of events optimized to run for roughly 24 hours
13
+ on a single node on the grid.
14
+ """
15
+
16
+ def __init__(self, primary=None, zenith_angle=None):
17
+ """
18
+ Initialize CorsikaDefaultConfig.
19
+ """
20
+ self.primary = primary
21
+ self.zenith_angle = zenith_angle
22
+ self._energy_slope = -2.0
23
+ self.energy_ranges = self._define_hardcoded_energy_ranges()
24
+ self.number_of_showers = self._define_hardcoded_number_of_showers()
25
+
26
+ @property
27
+ def primary(self):
28
+ """
29
+ Primary particle.
30
+
31
+ Returns
32
+ -------
33
+ primary: str
34
+ """
35
+ return self._primary
36
+
37
+ @primary.setter
38
+ def primary(self, primary):
39
+ """
40
+ Set primary particle.
41
+
42
+ Parameters
43
+ ----------
44
+ primary: str
45
+ Which primary to simulate.
46
+ """
47
+ supported_primaries = [
48
+ "gamma",
49
+ "gamma_diffuse",
50
+ "electron",
51
+ "proton",
52
+ "muon",
53
+ "helium",
54
+ "nitrogen",
55
+ "silicon",
56
+ "iron",
57
+ ]
58
+ if primary not in supported_primaries:
59
+ raise ValueError(
60
+ f"Invalid primary particle: {primary}. Must be one of {supported_primaries}"
61
+ )
62
+ self._primary = primary
63
+
64
+ @property
65
+ def zenith_angle(self):
66
+ """
67
+ Zenith angle.
68
+
69
+ Returns
70
+ -------
71
+ zenith_angle: astropy.units.Quantity
72
+ """
73
+ return self._zenith_angle
74
+
75
+ @zenith_angle.setter
76
+ @u.quantity_input(zenith_angle=u.deg)
77
+ def zenith_angle(self, zenith_angle):
78
+ """
79
+ Set zenith angle.
80
+
81
+ Parameters
82
+ ----------
83
+ zenith_angle: astropy.units.Quantity
84
+ Which zenith angle to simulate (in degrees).
85
+ """
86
+ allowed_zenith_angle_interval = [20.0, 60.0] * u.deg
87
+ if (
88
+ zenith_angle < allowed_zenith_angle_interval[0]
89
+ or zenith_angle > allowed_zenith_angle_interval[1]
90
+ ):
91
+ raise ValueError(
92
+ f"The zenith angle, {zenith_angle:.1f}, "
93
+ f"is outside of the allowed interval, {allowed_zenith_angle_interval}."
94
+ "This interval is enforced because values can only be interpolated "
95
+ "between zenith angles that were manually optimized."
96
+ )
97
+
98
+ self._zenith_angle = zenith_angle
99
+
100
+ @property
101
+ def energy_slope(self):
102
+ """
103
+ Energy slope.
104
+
105
+ Returns
106
+ -------
107
+ energy_slope: float
108
+ """
109
+ return self._energy_slope
110
+
111
+ def _define_hardcoded_energy_ranges(self):
112
+ """
113
+ Define the hardcoded energy ranges for the various primaries.
114
+ These energy ranges are for the full CTAO energy range (for both sites).
115
+
116
+ Returns
117
+ -------
118
+ energy_ranges: dict
119
+ Dictionary with the default energy ranges for the various primaries.
120
+ """
121
+
122
+ energy_ranges = defaultdict(dict)
123
+ energy_ranges["gamma"][20] = [3 * u.GeV, 330 * u.TeV]
124
+ energy_ranges["gamma"][40] = [6 * u.GeV, 660 * u.TeV]
125
+ energy_ranges["gamma"][60] = [12 * u.GeV, 990 * u.TeV]
126
+
127
+ for zenith_angle in energy_ranges["gamma"]:
128
+ energy_ranges["gamma_diffuse"][zenith_angle] = energy_ranges["gamma"][zenith_angle]
129
+ energy_ranges["electron"][zenith_angle] = energy_ranges["gamma"][zenith_angle]
130
+
131
+ energy_ranges["proton"][20] = [8 * u.GeV, 600 * u.TeV]
132
+ energy_ranges["proton"][40] = [12 * u.GeV, 800 * u.TeV]
133
+ energy_ranges["proton"][60] = [16 * u.GeV, 1800 * u.TeV]
134
+
135
+ energy_ranges["helium"][20] = [10 * u.GeV, 1200 * u.TeV]
136
+ energy_ranges["helium"][40] = [20 * u.GeV, 2400 * u.TeV]
137
+ energy_ranges["helium"][60] = [40 * u.GeV, 3600 * u.TeV]
138
+
139
+ energy_ranges["nitrogen"][20] = [40 * u.GeV, 4000 * u.TeV]
140
+ energy_ranges["nitrogen"][40] = [80 * u.GeV, 8000 * u.TeV]
141
+ energy_ranges["nitrogen"][60] = [160 * u.GeV, 12000 * u.TeV]
142
+
143
+ energy_ranges["silicon"][20] = [50 * u.GeV, 5000 * u.TeV]
144
+ energy_ranges["silicon"][40] = [100 * u.GeV, 10000 * u.TeV]
145
+ energy_ranges["silicon"][60] = [200 * u.GeV, 15000 * u.TeV]
146
+
147
+ energy_ranges["iron"][20] = [60 * u.GeV, 6000 * u.TeV]
148
+ energy_ranges["iron"][40] = [120 * u.GeV, 12000 * u.TeV]
149
+ energy_ranges["iron"][60] = [240 * u.GeV, 18000 * u.TeV]
150
+
151
+ return energy_ranges
152
+
153
+ def _define_hardcoded_number_of_showers(self):
154
+ """
155
+ Define the hardcoded number of showers for the various primaries.
156
+
157
+ Returns
158
+ -------
159
+ number_of_showers: dict
160
+ Dictionary with the default number of showers for the various primaries.
161
+ """
162
+
163
+ number_of_showers = defaultdict(dict)
164
+ number_of_showers["gamma"][20] = 5000
165
+ number_of_showers["gamma"][40] = 5000
166
+ number_of_showers["gamma"][60] = 2500
167
+
168
+ for zenith_angle in number_of_showers["gamma"]:
169
+ number_of_showers["gamma_diffuse"][zenith_angle] = number_of_showers["gamma"][
170
+ zenith_angle
171
+ ]
172
+ number_of_showers["electron"][zenith_angle] = number_of_showers["gamma"][zenith_angle]
173
+
174
+ number_of_showers["proton"][20] = 15000
175
+ number_of_showers["proton"][40] = 15000
176
+ number_of_showers["proton"][60] = 7500
177
+
178
+ number_of_showers["helium"][20] = 10000
179
+ number_of_showers["helium"][40] = 10000
180
+ number_of_showers["helium"][60] = 5000
181
+
182
+ number_of_showers["nitrogen"][20] = 2000
183
+ number_of_showers["nitrogen"][40] = 2000
184
+ number_of_showers["nitrogen"][60] = 1000
185
+
186
+ number_of_showers["silicon"][20] = 1000
187
+ number_of_showers["silicon"][40] = 1000
188
+ number_of_showers["silicon"][60] = 500
189
+
190
+ return number_of_showers
191
+
192
+ @staticmethod
193
+ @u.quantity_input(zenith_angle=u.deg)
194
+ def interpolate_to_zenith_angle(
195
+ zenith_angle, zenith_angles_to_interpolate, values_to_interpolate
196
+ ):
197
+ """
198
+ Interpolate values like energy range or number of showers to the provided zenith angle.
199
+
200
+ Parameters
201
+ ----------
202
+ zenith_angle: astropy.units.Quantity
203
+ Which zenith angle to interpolate to (in degrees).
204
+ zenith_angles_to_interpolate: list
205
+ List of zenith angles for which we have values to interpolate between.
206
+ values_to_interpolate: list
207
+ List of values to interpolate between.
208
+
209
+ Returns
210
+ -------
211
+ float
212
+ Interpolated value.
213
+ """
214
+ interpolation_function = interp1d(
215
+ zenith_angles_to_interpolate, values_to_interpolate, kind="quadratic"
216
+ )
217
+ return interpolation_function(zenith_angle.to_value(u.deg)).item()
218
+
219
+ def energy_range_for_primary(self):
220
+ """
221
+ Get the energy range for the primary particle for the given zenith angle.
222
+
223
+ Returns
224
+ -------
225
+ energy_range: list
226
+ List with the energy range for the primary particle for the given zenith angle.
227
+ """
228
+
229
+ zenith_angles_to_interpolate = [*self.energy_ranges[self.primary].keys()]
230
+ min_energy_to_interpolate = [
231
+ energy[0].to_value(u.GeV) for energy in self.energy_ranges[self.primary].values()
232
+ ]
233
+ max_energy_to_interpolate = [
234
+ energy[1].to_value(u.GeV) for energy in self.energy_ranges[self.primary].values()
235
+ ]
236
+
237
+ return [
238
+ self.interpolate_to_zenith_angle(
239
+ self.zenith_angle, zenith_angles_to_interpolate, min_energy_to_interpolate
240
+ )
241
+ * u.GeV,
242
+ (
243
+ self.interpolate_to_zenith_angle(
244
+ self.zenith_angle, zenith_angles_to_interpolate, max_energy_to_interpolate
245
+ )
246
+ * u.GeV
247
+ ).to(u.TeV),
248
+ ]
249
+
250
+ def number_of_showers_for_primary(self):
251
+ """
252
+ Get the number of showers for the primary particle for the given zenith angle.
253
+
254
+ Returns
255
+ -------
256
+ number_of_showers: int
257
+ Number of showers for the primary particle for the given zenith angle.
258
+ """
259
+
260
+ zenith_angles_to_interpolate = [*self.energy_ranges[self.primary].keys()]
261
+ number_of_showers = [*self.number_of_showers[self.primary].values()]
262
+
263
+ return self.interpolate_to_zenith_angle(
264
+ self.zenith_angle,
265
+ zenith_angles_to_interpolate,
266
+ number_of_showers,
267
+ )
268
+
269
+ def view_cone_for_primary(self):
270
+ """
271
+ Get the view cone for the primary particle.
272
+ All diffuse primaries have a view cone of 10 deg by default.
273
+
274
+ Returns
275
+ -------
276
+ view_cone: list
277
+ List with the view cone for the primary particle.
278
+ """
279
+ if self.primary == "gamma":
280
+ return [0.0 * u.deg, 0.0 * u.deg]
281
+
282
+ return [0 * u.deg, 10 * u.deg]