gammasimtools 0.12.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.12.0.dist-info → gammasimtools-0.13.0.dist-info}/METADATA +1 -1
- {gammasimtools-0.12.0.dist-info → gammasimtools-0.13.0.dist-info}/RECORD +64 -77
- {gammasimtools-0.12.0.dist-info → gammasimtools-0.13.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.12.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/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 +115 -31
- 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/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.12.0.dist-info → gammasimtools-0.13.0.dist-info}/LICENSE +0 -0
- {gammasimtools-0.12.0.dist-info → gammasimtools-0.13.0.dist-info}/top_level.txt +0 -0
simtools/utils/general.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import copy
|
|
4
4
|
import datetime
|
|
5
|
+
import glob
|
|
5
6
|
import json
|
|
6
7
|
import logging
|
|
7
8
|
import os
|
|
@@ -455,6 +456,34 @@ def find_file(name, loc):
|
|
|
455
456
|
raise FileNotFoundError(msg)
|
|
456
457
|
|
|
457
458
|
|
|
459
|
+
def resolve_file_patterns(file_names):
|
|
460
|
+
"""
|
|
461
|
+
Return a list of files names from string, list, or wildcard pattern.
|
|
462
|
+
|
|
463
|
+
Parameters
|
|
464
|
+
----------
|
|
465
|
+
file_names: str, list
|
|
466
|
+
File names to be searched for (wildcards allowed).
|
|
467
|
+
|
|
468
|
+
Returns
|
|
469
|
+
-------
|
|
470
|
+
list
|
|
471
|
+
List of file names found.
|
|
472
|
+
"""
|
|
473
|
+
if file_names is None:
|
|
474
|
+
raise ValueError("No file list provided.")
|
|
475
|
+
if not isinstance(file_names, list):
|
|
476
|
+
file_names = [file_names]
|
|
477
|
+
|
|
478
|
+
_files = []
|
|
479
|
+
for file_name in file_names:
|
|
480
|
+
# use glob (and not Path.glob) for easier wildcard handling
|
|
481
|
+
_files.extend(Path(f) for f in glob.glob(str(file_name), recursive=True)) # noqa: PTH207
|
|
482
|
+
if not _files:
|
|
483
|
+
raise FileNotFoundError(f"No files found: {file_names}")
|
|
484
|
+
return _files
|
|
485
|
+
|
|
486
|
+
|
|
458
487
|
def get_log_excerpt(log_file, n_last_lines=30):
|
|
459
488
|
"""
|
|
460
489
|
Get an excerpt from a log file, namely the n_last_lines of the file.
|
|
@@ -696,16 +725,28 @@ def validate_data_type(reference_dtype, value=None, dtype=None, allow_subtypes=T
|
|
|
696
725
|
):
|
|
697
726
|
return True
|
|
698
727
|
|
|
699
|
-
if
|
|
700
|
-
return
|
|
728
|
+
if reference_dtype in ("boolean", "bool"):
|
|
729
|
+
return _is_valid_boolean_type(dtype, value)
|
|
701
730
|
|
|
702
|
-
|
|
703
|
-
np.issubdtype(reference_dtype, np.integer) or np.issubdtype(reference_dtype, np.floating)
|
|
704
|
-
):
|
|
705
|
-
return True
|
|
731
|
+
return _is_valid_numeric_type(dtype, reference_dtype)
|
|
706
732
|
|
|
707
|
-
|
|
733
|
+
|
|
734
|
+
def _is_valid_boolean_type(dtype, value):
|
|
735
|
+
"""Check if dtype or value is a valid boolean type."""
|
|
736
|
+
if value in {0, 1}:
|
|
708
737
|
return True
|
|
738
|
+
return np.issubdtype(dtype, np.bool_)
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
def _is_valid_numeric_type(dtype, reference_dtype):
|
|
742
|
+
"""Check if dtype is a valid numeric type compared to reference_dtype."""
|
|
743
|
+
if np.issubdtype(dtype, np.integer):
|
|
744
|
+
return np.issubdtype(reference_dtype, np.integer) or np.issubdtype(
|
|
745
|
+
reference_dtype, np.floating
|
|
746
|
+
)
|
|
747
|
+
|
|
748
|
+
if np.issubdtype(dtype, np.floating):
|
|
749
|
+
return np.issubdtype(reference_dtype, np.floating)
|
|
709
750
|
|
|
710
751
|
return False
|
|
711
752
|
|
|
@@ -851,8 +892,8 @@ def get_structure_array_from_table(table, column_names):
|
|
|
851
892
|
Structured array containing the table data.
|
|
852
893
|
"""
|
|
853
894
|
return np.array(
|
|
854
|
-
list(zip(*[np.array(table[col]) for col in column_names])),
|
|
855
|
-
dtype=[(col, np.array(table[col]).dtype) for col in column_names],
|
|
895
|
+
list(zip(*[np.array(table[col]) for col in column_names if col in table.colnames])),
|
|
896
|
+
dtype=[(col, np.array(table[col]).dtype) for col in column_names if col in table.colnames],
|
|
856
897
|
)
|
|
857
898
|
|
|
858
899
|
|
simtools/utils/names.py
CHANGED
|
@@ -353,6 +353,8 @@ def get_array_element_type_from_name(array_element_name):
|
|
|
353
353
|
"""
|
|
354
354
|
Get array element type from array element name (e.g "MSTN" from "MSTN-01").
|
|
355
355
|
|
|
356
|
+
For sites, return site name.
|
|
357
|
+
|
|
356
358
|
Parameters
|
|
357
359
|
----------
|
|
358
360
|
array_element_name: str
|
|
@@ -363,7 +365,10 @@ def get_array_element_type_from_name(array_element_name):
|
|
|
363
365
|
str
|
|
364
366
|
Array element type.
|
|
365
367
|
"""
|
|
366
|
-
|
|
368
|
+
try: # e.g. instrument is 'North' as given for the site parameters
|
|
369
|
+
return validate_site_name(array_element_name)
|
|
370
|
+
except ValueError: # any other telescope or calibration device
|
|
371
|
+
return _validate_name(array_element_name.split("-")[0], array_elements())
|
|
367
372
|
|
|
368
373
|
|
|
369
374
|
def get_array_element_id_from_name(array_element_name):
|
|
@@ -460,7 +465,7 @@ def get_collection_name_from_array_element_name(array_element_name, array_elemen
|
|
|
460
465
|
"""
|
|
461
466
|
try:
|
|
462
467
|
return array_elements()[get_array_element_type_from_name(array_element_name)]["collection"]
|
|
463
|
-
except ValueError as exc:
|
|
468
|
+
except (ValueError, KeyError) as exc:
|
|
464
469
|
if array_elements_only:
|
|
465
470
|
raise ValueError(f"Invalid array element name {array_element_name}") from exc
|
|
466
471
|
try:
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"""Plot tabular data."""
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
|
+
from astropy.table import Table
|
|
5
6
|
|
|
6
7
|
import simtools.utils.general as gen
|
|
8
|
+
from simtools.db import db_handler
|
|
7
9
|
from simtools.io_operations import legacy_data_handler
|
|
8
|
-
from simtools.model.site_model import SiteModel
|
|
9
|
-
from simtools.model.telescope_model import TelescopeModel
|
|
10
10
|
from simtools.visualization import visualize
|
|
11
11
|
|
|
12
12
|
|
|
@@ -50,11 +50,15 @@ def read_table_data(config, db_config):
|
|
|
50
50
|
if "parameter" in _config:
|
|
51
51
|
table = _read_table_from_model_database(_config, db_config)
|
|
52
52
|
elif "file_name" in _config:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
if "legacy" in _config.get("type", ""):
|
|
54
|
+
table = legacy_data_handler.read_legacy_data_as_table(
|
|
55
|
+
_config["file_name"], _config["type"]
|
|
56
|
+
)
|
|
57
|
+
else:
|
|
58
|
+
table = Table.read(_config["file_name"], format="ascii.ecsv")
|
|
56
59
|
else:
|
|
57
60
|
raise ValueError("No table data defined in configuration.")
|
|
61
|
+
|
|
58
62
|
if _config.get("normalize_y"):
|
|
59
63
|
table[_config["column_y"]] = (
|
|
60
64
|
table[_config["column_y"]] / table[_config["column_y"]].max()
|
|
@@ -66,7 +70,13 @@ def read_table_data(config, db_config):
|
|
|
66
70
|
_config["select_values"]["value"],
|
|
67
71
|
)
|
|
68
72
|
data[_config["label"]] = gen.get_structure_array_from_table(
|
|
69
|
-
table,
|
|
73
|
+
table,
|
|
74
|
+
[
|
|
75
|
+
_config["column_x"],
|
|
76
|
+
_config["column_y"],
|
|
77
|
+
_config.get("column_x_err"),
|
|
78
|
+
_config.get("column_y_err"),
|
|
79
|
+
],
|
|
70
80
|
)
|
|
71
81
|
return data
|
|
72
82
|
|
|
@@ -85,20 +95,15 @@ def _read_table_from_model_database(table_config, db_config):
|
|
|
85
95
|
Table
|
|
86
96
|
Astropy table.
|
|
87
97
|
"""
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
site=table_config["site"],
|
|
98
|
-
model_version=table_config["model_version"],
|
|
99
|
-
mongo_db_config=db_config,
|
|
100
|
-
)
|
|
101
|
-
return model.get_model_file_as_table(table_config["parameter"])
|
|
98
|
+
db = db_handler.DatabaseHandler(mongo_db_config=db_config)
|
|
99
|
+
return db.export_model_file(
|
|
100
|
+
parameter=table_config["parameter"],
|
|
101
|
+
site=table_config["site"],
|
|
102
|
+
array_element_name=table_config.get("telescope"),
|
|
103
|
+
parameter_version=table_config.get("parameter_version"),
|
|
104
|
+
model_version=table_config.get("model_version"),
|
|
105
|
+
export_file_as_table=True,
|
|
106
|
+
)
|
|
102
107
|
|
|
103
108
|
|
|
104
109
|
def _select_values_from_table(table, column_name, value):
|
|
@@ -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
|