gammasimtools 0.11.0__py3-none-any.whl → 0.13.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.
- {gammasimtools-0.11.0.dist-info → gammasimtools-0.13.0.dist-info}/METADATA +1 -1
- {gammasimtools-0.11.0.dist-info → gammasimtools-0.13.0.dist-info}/RECORD +66 -79
- {gammasimtools-0.11.0.dist-info → gammasimtools-0.13.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.11.0.dist-info → gammasimtools-0.13.0.dist-info}/entry_points.txt +2 -1
- simtools/_version.py +2 -2
- simtools/applications/convert_all_model_parameters_from_simtel.py +77 -88
- simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -1
- simtools/applications/db_get_parameter_from_db.py +52 -22
- simtools/applications/derive_photon_electron_spectrum.py +1 -1
- simtools/applications/docs_produce_array_element_report.py +1 -10
- simtools/applications/docs_produce_model_parameter_reports.py +4 -17
- simtools/applications/plot_tabular_data.py +14 -2
- simtools/applications/{production_derive_limits.py → production_derive_corsika_limits.py} +20 -8
- simtools/applications/production_extract_mc_event_data.py +125 -0
- simtools/applications/run_application.py +9 -10
- simtools/applications/submit_data_from_external.py +1 -1
- simtools/applications/submit_model_parameter_from_external.py +2 -1
- simtools/camera/single_photon_electron_spectrum.py +6 -2
- simtools/configuration/commandline_parser.py +1 -1
- simtools/constants.py +7 -0
- simtools/data_model/metadata_collector.py +159 -61
- simtools/data_model/model_data_writer.py +11 -55
- simtools/data_model/schema.py +2 -1
- simtools/data_model/validate_data.py +5 -3
- simtools/db/db_handler.py +119 -33
- simtools/model/model_parameter.py +0 -31
- simtools/production_configuration/derive_corsika_limits.py +260 -0
- simtools/production_configuration/extract_mc_event_data.py +253 -0
- simtools/ray_tracing/mirror_panel_psf.py +1 -1
- simtools/reporting/docs_read_parameters.py +164 -91
- simtools/schemas/metadata.metaschema.yml +7 -6
- simtools/schemas/model_parameter.metaschema.yml +0 -4
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +13 -5
- simtools/schemas/model_parameters/array_coordinates.schema.yml +1 -1
- simtools/schemas/model_parameters/array_layouts.schema.yml +3 -0
- simtools/schemas/model_parameters/asum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/atmospheric_profile.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_file.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_filter.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +3 -3
- simtools/schemas/model_parameters/fadc_max_sum.schema.yml +3 -3
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_skymap.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/plot_configuration.metaschema.yml +162 -0
- simtools/schemas/production_tables.schema.yml +1 -1
- simtools/simtel/simtel_config_reader.py +85 -34
- simtools/simtel/simtel_table_reader.py +4 -0
- simtools/utils/general.py +50 -9
- simtools/utils/names.py +7 -2
- simtools/utils/value_conversion.py +6 -4
- simtools/visualization/plot_tables.py +25 -20
- simtools/visualization/visualize.py +71 -23
- simtools/_dev_version/__init__.py +0 -9
- simtools/applications/__init__.py +0 -0
- simtools/configuration/__init__.py +0 -0
- simtools/corsika/__init__.py +0 -0
- simtools/data_model/__init__.py +0 -0
- simtools/db/__init__.py +0 -0
- simtools/io_operations/__init__.py +0 -0
- simtools/job_execution/__init__.py +0 -0
- simtools/layout/__init__.py +0 -0
- simtools/model/__init__.py +0 -0
- simtools/production_configuration/limits_calculation.py +0 -202
- simtools/ray_tracing/__init__.py +0 -0
- simtools/runners/__init__.py +0 -0
- simtools/simtel/__init__.py +0 -0
- simtools/testing/__init__.py +0 -0
- simtools/utils/__init__.py +0 -0
- simtools/visualization/__init__.py +0 -0
- {gammasimtools-0.11.0.dist-info → gammasimtools-0.13.0.dist-info}/LICENSE +0 -0
- {gammasimtools-0.11.0.dist-info → gammasimtools-0.13.0.dist-info}/top_level.txt +0 -0
|
@@ -144,22 +144,23 @@ def _add_unit(title, array):
|
|
|
144
144
|
str
|
|
145
145
|
Title with units.
|
|
146
146
|
"""
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
_logger.warning(
|
|
157
|
-
"Tried to add a unit from astropy.unit, "
|
|
158
|
-
"but axis already has an explicit unit. Left axis title as is."
|
|
159
|
-
)
|
|
160
|
-
unit = ""
|
|
147
|
+
if title and "[" in title and "]" in title:
|
|
148
|
+
_logger.warning(
|
|
149
|
+
"Tried to add a unit from astropy.unit, "
|
|
150
|
+
"but axis already has an explicit unit. Left axis title as is."
|
|
151
|
+
)
|
|
152
|
+
return title
|
|
153
|
+
|
|
154
|
+
if not isinstance(array, u.Quantity) or not str(array[0].unit):
|
|
155
|
+
return title
|
|
161
156
|
|
|
162
|
-
|
|
157
|
+
unit = str(array[0].unit)
|
|
158
|
+
unit_str = f" [{unit}]"
|
|
159
|
+
if re.search(r"\d", unit_str):
|
|
160
|
+
unit_str = re.sub(r"(\d)", r"^\1", unit_str)
|
|
161
|
+
unit_str = unit_str.replace("[", r"[$").replace("]", r"$]")
|
|
162
|
+
|
|
163
|
+
return f"{title}{unit_str}"
|
|
163
164
|
|
|
164
165
|
|
|
165
166
|
def set_style(palette="default", big_plot=False):
|
|
@@ -418,27 +419,74 @@ def setup_plot(kwargs, plot_ratio, plot_difference):
|
|
|
418
419
|
return fig, ax1, gs
|
|
419
420
|
|
|
420
421
|
|
|
422
|
+
def _plot_error_plots(kwargs, data_now, x_col, y_col, x_err_col, y_err_col, color):
|
|
423
|
+
"""Plot error plots."""
|
|
424
|
+
if kwargs.get("error_type") == "fill_between" and y_err_col:
|
|
425
|
+
plt.fill_between(
|
|
426
|
+
data_now[x_col],
|
|
427
|
+
data_now[y_col] - data_now[y_err_col],
|
|
428
|
+
data_now[y_col] + data_now[y_err_col],
|
|
429
|
+
alpha=0.2,
|
|
430
|
+
color=color,
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
if kwargs.get("error_type") == "errorbar" and (x_err_col or y_err_col):
|
|
434
|
+
plt.errorbar(
|
|
435
|
+
data_now[x_col],
|
|
436
|
+
data_now[y_col],
|
|
437
|
+
xerr=data_now[x_err_col] if x_err_col else None,
|
|
438
|
+
yerr=data_now[y_err_col] if y_err_col else None,
|
|
439
|
+
fmt=".",
|
|
440
|
+
color=color,
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def _get_data_columns(data_now):
|
|
445
|
+
"""Return data columns depending on availability."""
|
|
446
|
+
columns = data_now.dtype.names
|
|
447
|
+
assert len(columns) >= 2, "Input array must have at least two columns with titles."
|
|
448
|
+
x_col, y_col = columns[:2]
|
|
449
|
+
if len(columns) == 3:
|
|
450
|
+
x_err_col = None
|
|
451
|
+
y_err_col = columns[2]
|
|
452
|
+
elif len(columns) == 4:
|
|
453
|
+
x_err_col = columns[2]
|
|
454
|
+
y_err_col = columns[3]
|
|
455
|
+
else:
|
|
456
|
+
x_err_col = None
|
|
457
|
+
y_err_col = None
|
|
458
|
+
return x_col, y_col, x_err_col, y_err_col
|
|
459
|
+
|
|
460
|
+
|
|
421
461
|
def plot_main_data(data_dict, kwargs, plot_args):
|
|
422
462
|
"""Plot the main data."""
|
|
423
463
|
for label, data_now in data_dict.items():
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
x_title = kwargs
|
|
427
|
-
y_title = kwargs
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
464
|
+
x_col, y_col, x_err_col, y_err_col = _get_data_columns(data_now)
|
|
465
|
+
|
|
466
|
+
x_title = kwargs.get("xtitle", x_col)
|
|
467
|
+
y_title = kwargs.get("ytitle", y_col)
|
|
468
|
+
|
|
469
|
+
x_title_unit = _add_unit(x_title, data_now[x_col])
|
|
470
|
+
y_title_unit = _add_unit(y_title, data_now[y_col])
|
|
471
|
+
|
|
472
|
+
(line,) = plt.plot(data_now[x_col], data_now[y_col], label=label, **plot_args)
|
|
473
|
+
color = line.get_color()
|
|
474
|
+
|
|
475
|
+
_plot_error_plots(kwargs, data_now, x_col, y_col, x_err_col, y_err_col, color)
|
|
431
476
|
|
|
432
477
|
plt.xscale(kwargs["xscale"])
|
|
433
478
|
plt.yscale(kwargs["yscale"])
|
|
434
479
|
plt.xlim(kwargs["xlim"])
|
|
435
480
|
plt.ylim(kwargs["ylim"])
|
|
436
481
|
plt.ylabel(y_title_unit)
|
|
482
|
+
|
|
437
483
|
if not (kwargs["plot_ratio"] or kwargs["plot_difference"]):
|
|
438
484
|
plt.xlabel(x_title_unit)
|
|
485
|
+
|
|
439
486
|
if kwargs["title"]:
|
|
440
487
|
plt.title(kwargs["title"], y=1.02)
|
|
441
|
-
|
|
488
|
+
|
|
489
|
+
if "_default" not in data_dict and not kwargs["no_legend"]:
|
|
442
490
|
plt.legend()
|
|
443
491
|
|
|
444
492
|
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# Try to use setuptools_scm to get the current version; this is only used
|
|
2
|
-
# in development installations from the git repository.
|
|
3
|
-
# see src/simtools/version.py for details
|
|
4
|
-
try:
|
|
5
|
-
from setuptools_scm import get_version
|
|
6
|
-
|
|
7
|
-
version = get_version(root="../../..", relative_to=__file__)
|
|
8
|
-
except Exception as e:
|
|
9
|
-
raise ImportError(f"setuptools_scm broken or not installed: {e}")
|
|
File without changes
|
|
File without changes
|
simtools/corsika/__init__.py
DELETED
|
File without changes
|
simtools/data_model/__init__.py
DELETED
|
File without changes
|
simtools/db/__init__.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
simtools/layout/__init__.py
DELETED
|
File without changes
|
simtools/model/__init__.py
DELETED
|
File without changes
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
"""Calculate the thresholds for energy, radial distance, and viewcone."""
|
|
2
|
-
|
|
3
|
-
import astropy.units as u
|
|
4
|
-
import numpy as np
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class LimitCalculator:
|
|
8
|
-
"""
|
|
9
|
-
Compute thresholds/limits for energy, radial distance, and viewcone.
|
|
10
|
-
|
|
11
|
-
Histograms are generated with simtools-generate-simtel-array-histograms with --hdf5 flag.
|
|
12
|
-
|
|
13
|
-
Event data is read from the generated HDF5 file from the following tables:
|
|
14
|
-
- angle_to_observing_position__triggered_showers_ for the viewcone limit.
|
|
15
|
-
- event_weight__ra3d__log10_e__ for the energy and radial distance limit.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Parameters
|
|
19
|
-
----------
|
|
20
|
-
event_data_file : list of astropy.table.Table
|
|
21
|
-
The list of tables containing the event data.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
def __init__(self, event_data_file_tables):
|
|
25
|
-
"""
|
|
26
|
-
Initialize the LimitCalculator with the given event data file.
|
|
27
|
-
|
|
28
|
-
Parameters
|
|
29
|
-
----------
|
|
30
|
-
event_data_file : list of astropy.table.Table
|
|
31
|
-
The list of tables containing the event data.
|
|
32
|
-
"""
|
|
33
|
-
self.angle_to_observing_position__triggered_showers_ = None
|
|
34
|
-
self.event_weight__ra3d__log10_e__ = None
|
|
35
|
-
|
|
36
|
-
for table in event_data_file_tables:
|
|
37
|
-
if (
|
|
38
|
-
"Title" in table.meta
|
|
39
|
-
and table.meta["Title"] == "angle_to_observing_position__triggered_showers_"
|
|
40
|
-
):
|
|
41
|
-
self.angle_to_observing_position__triggered_showers_ = table
|
|
42
|
-
elif "Title" in table.meta and table.meta["Title"] == "event_weight__ra3d__log10_e__":
|
|
43
|
-
self.event_weight__ra3d__log10_e__ = table
|
|
44
|
-
|
|
45
|
-
def _compute_limits(
|
|
46
|
-
self, event_weight_array, bin_edges, loss_fraction, axis=0, limit_type="lower"
|
|
47
|
-
):
|
|
48
|
-
"""
|
|
49
|
-
Compute the limits based on the loss fraction.
|
|
50
|
-
|
|
51
|
-
Parameters
|
|
52
|
-
----------
|
|
53
|
-
event_weight_array : np.ndarray
|
|
54
|
-
Array of event weights.
|
|
55
|
-
bin_edges : np.ndarray
|
|
56
|
-
Array of bin edges.
|
|
57
|
-
loss_fraction : float
|
|
58
|
-
Fraction of events to be lost.
|
|
59
|
-
axis : int, optional
|
|
60
|
-
Axis along which to sum the event weights. Default is 0.
|
|
61
|
-
limit_type : str, optional
|
|
62
|
-
Type of limit ('lower' or 'upper'). Default is 'lower'.
|
|
63
|
-
|
|
64
|
-
Returns
|
|
65
|
-
-------
|
|
66
|
-
int
|
|
67
|
-
Bin index where the threshold is reached.
|
|
68
|
-
float
|
|
69
|
-
Bin edge value corresponding to the threshold.
|
|
70
|
-
"""
|
|
71
|
-
projection = np.sum(event_weight_array, axis=axis)
|
|
72
|
-
bin_edge_value = None
|
|
73
|
-
cumulative_sum = None
|
|
74
|
-
if limit_type == "upper":
|
|
75
|
-
cumulative_sum = np.cumsum(projection)
|
|
76
|
-
|
|
77
|
-
elif limit_type == "lower":
|
|
78
|
-
cumulative_sum = np.cumsum(projection[::-1])
|
|
79
|
-
|
|
80
|
-
total_events = np.sum(projection)
|
|
81
|
-
threshold = (1 - loss_fraction) * total_events
|
|
82
|
-
bin_index = np.searchsorted(cumulative_sum, threshold)
|
|
83
|
-
if limit_type == "upper":
|
|
84
|
-
bin_edge_value = bin_edges[bin_index]
|
|
85
|
-
elif limit_type == "lower":
|
|
86
|
-
bin_edge_value = bin_edges[-bin_index]
|
|
87
|
-
return bin_index, bin_edge_value
|
|
88
|
-
|
|
89
|
-
def get_bin_edges_and_units(self, table, axis="x"):
|
|
90
|
-
"""
|
|
91
|
-
Extract bin edges and units from the table metadata.
|
|
92
|
-
|
|
93
|
-
Parameters
|
|
94
|
-
----------
|
|
95
|
-
table : astropy.table.Table
|
|
96
|
-
Table containing the event data.
|
|
97
|
-
|
|
98
|
-
Returns
|
|
99
|
-
-------
|
|
100
|
-
tuple
|
|
101
|
-
Tuple containing the bin edges and their units.
|
|
102
|
-
"""
|
|
103
|
-
bin_edges = table.meta[f"{axis}_bin_edges"]
|
|
104
|
-
try:
|
|
105
|
-
bin_edges_unit = table.meta[f"{axis}_bin_edges_unit"]
|
|
106
|
-
except KeyError:
|
|
107
|
-
bin_edges_unit = ""
|
|
108
|
-
return bin_edges, bin_edges_unit
|
|
109
|
-
|
|
110
|
-
def compute_lower_energy_limit(self, loss_fraction):
|
|
111
|
-
"""
|
|
112
|
-
Compute the lower energy limit in TeV based on the event loss fraction.
|
|
113
|
-
|
|
114
|
-
Parameters
|
|
115
|
-
----------
|
|
116
|
-
loss_fraction : float
|
|
117
|
-
Fraction of events to be lost.
|
|
118
|
-
|
|
119
|
-
Returns
|
|
120
|
-
-------
|
|
121
|
-
astropy.units.Quantity
|
|
122
|
-
Lower energy limit.
|
|
123
|
-
"""
|
|
124
|
-
event_weight_array = np.column_stack(
|
|
125
|
-
[
|
|
126
|
-
self.event_weight__ra3d__log10_e__[name]
|
|
127
|
-
for name in self.event_weight__ra3d__log10_e__.dtype.names
|
|
128
|
-
]
|
|
129
|
-
)
|
|
130
|
-
bin_edges, bin_edges_unit = self.get_bin_edges_and_units(
|
|
131
|
-
self.event_weight__ra3d__log10_e__, axis="y"
|
|
132
|
-
)
|
|
133
|
-
if bin_edges_unit == "":
|
|
134
|
-
bin_edges_unit = "TeV"
|
|
135
|
-
_, lower_bin_edge_value = self._compute_limits(
|
|
136
|
-
event_weight_array, bin_edges, loss_fraction, axis=0, limit_type="lower"
|
|
137
|
-
)
|
|
138
|
-
return (10**lower_bin_edge_value) * u.Unit(bin_edges_unit)
|
|
139
|
-
|
|
140
|
-
def compute_upper_radial_distance(self, loss_fraction):
|
|
141
|
-
"""
|
|
142
|
-
Compute the upper radial distance based on the event loss fraction.
|
|
143
|
-
|
|
144
|
-
Parameters
|
|
145
|
-
----------
|
|
146
|
-
loss_fraction : float
|
|
147
|
-
Fraction of events to be lost.
|
|
148
|
-
|
|
149
|
-
Returns
|
|
150
|
-
-------
|
|
151
|
-
astropy.units.Quantity
|
|
152
|
-
Upper radial distance in m.
|
|
153
|
-
"""
|
|
154
|
-
event_weight_array = np.column_stack(
|
|
155
|
-
[
|
|
156
|
-
self.event_weight__ra3d__log10_e__[name]
|
|
157
|
-
for name in self.event_weight__ra3d__log10_e__.dtype.names
|
|
158
|
-
]
|
|
159
|
-
)
|
|
160
|
-
bin_edges, bin_edges_unit = self.get_bin_edges_and_units(
|
|
161
|
-
self.event_weight__ra3d__log10_e__, axis="x"
|
|
162
|
-
)
|
|
163
|
-
if bin_edges_unit == "":
|
|
164
|
-
bin_edges_unit = "m"
|
|
165
|
-
_, upper_bin_edge_value = self._compute_limits(
|
|
166
|
-
event_weight_array, bin_edges, loss_fraction, axis=1, limit_type="upper"
|
|
167
|
-
)
|
|
168
|
-
return upper_bin_edge_value * u.Unit(bin_edges_unit)
|
|
169
|
-
|
|
170
|
-
def compute_viewcone(self, loss_fraction):
|
|
171
|
-
"""
|
|
172
|
-
Compute the viewcone based on the event loss fraction.
|
|
173
|
-
|
|
174
|
-
Parameters
|
|
175
|
-
----------
|
|
176
|
-
loss_fraction : float
|
|
177
|
-
Fraction of events to be lost.
|
|
178
|
-
|
|
179
|
-
Returns
|
|
180
|
-
-------
|
|
181
|
-
astropy.units.Quantity
|
|
182
|
-
Viewcone radius in degrees.
|
|
183
|
-
"""
|
|
184
|
-
angle_to_observing_position__triggered_showers = np.column_stack(
|
|
185
|
-
[
|
|
186
|
-
self.angle_to_observing_position__triggered_showers_[name]
|
|
187
|
-
for name in self.angle_to_observing_position__triggered_showers_.dtype.names
|
|
188
|
-
]
|
|
189
|
-
)
|
|
190
|
-
bin_edges, bin_edges_unit = self.get_bin_edges_and_units(
|
|
191
|
-
self.angle_to_observing_position__triggered_showers_, axis="x"
|
|
192
|
-
)
|
|
193
|
-
if bin_edges_unit == "":
|
|
194
|
-
bin_edges_unit = "deg"
|
|
195
|
-
_, upper_bin_edge_value = self._compute_limits(
|
|
196
|
-
angle_to_observing_position__triggered_showers,
|
|
197
|
-
bin_edges,
|
|
198
|
-
loss_fraction,
|
|
199
|
-
axis=0,
|
|
200
|
-
limit_type="upper",
|
|
201
|
-
)
|
|
202
|
-
return upper_bin_edge_value * u.Unit(bin_edges_unit)
|
simtools/ray_tracing/__init__.py
DELETED
|
File without changes
|
simtools/runners/__init__.py
DELETED
|
File without changes
|
simtools/simtel/__init__.py
DELETED
|
File without changes
|
simtools/testing/__init__.py
DELETED
|
File without changes
|
simtools/utils/__init__.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|