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.
- {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/METADATA +80 -28
- gammasimtools-0.6.1.dist-info/RECORD +91 -0
- {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/WHEEL +1 -1
- {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/entry_points.txt +4 -2
- simtools/_version.py +14 -2
- simtools/applications/add_file_to_db.py +2 -1
- simtools/applications/compare_cumulative_psf.py +10 -15
- simtools/applications/db_development_tools/add_new_parameter_to_db.py +12 -6
- simtools/applications/derive_mirror_rnda.py +95 -71
- simtools/applications/generate_corsika_histograms.py +216 -131
- simtools/applications/generate_default_metadata.py +110 -0
- simtools/applications/generate_simtel_array_histograms.py +192 -0
- simtools/applications/get_file_from_db.py +1 -1
- simtools/applications/get_parameter.py +3 -3
- simtools/applications/make_regular_arrays.py +89 -93
- simtools/applications/{plot_layout_array.py → plot_array_layout.py} +15 -14
- simtools/applications/print_array_elements.py +81 -34
- simtools/applications/produce_array_config.py +2 -2
- simtools/applications/production.py +39 -5
- simtools/applications/sim_showers_for_trigger_rates.py +26 -30
- simtools/applications/simulate_prod.py +49 -107
- simtools/applications/submit_data_from_external.py +8 -10
- simtools/applications/tune_psf.py +16 -18
- simtools/applications/validate_camera_efficiency.py +63 -9
- simtools/applications/validate_camera_fov.py +9 -13
- simtools/applications/validate_file_using_schema.py +127 -0
- simtools/applications/validate_optics.py +13 -15
- simtools/camera_efficiency.py +73 -80
- simtools/configuration/commandline_parser.py +52 -22
- simtools/configuration/configurator.py +98 -33
- simtools/constants.py +9 -0
- simtools/corsika/corsika_config.py +28 -22
- simtools/corsika/corsika_default_config.py +282 -0
- simtools/corsika/corsika_histograms.py +328 -282
- simtools/corsika/corsika_histograms_visualize.py +162 -163
- simtools/corsika/corsika_runner.py +8 -4
- simtools/corsika_simtel/corsika_simtel_runner.py +18 -23
- simtools/data_model/data_reader.py +129 -0
- simtools/data_model/metadata_collector.py +346 -118
- simtools/data_model/metadata_model.py +123 -218
- simtools/data_model/model_data_writer.py +79 -22
- simtools/data_model/validate_data.py +96 -46
- simtools/db_handler.py +67 -42
- simtools/io_operations/__init__.py +0 -0
- simtools/io_operations/hdf5_handler.py +112 -0
- simtools/{io_handler.py → io_operations/io_handler.py} +51 -22
- simtools/job_execution/job_manager.py +1 -1
- simtools/layout/{layout_array.py → array_layout.py} +168 -199
- simtools/layout/geo_coordinates.py +196 -0
- simtools/layout/telescope_position.py +12 -12
- simtools/model/array_model.py +16 -14
- simtools/model/camera.py +5 -8
- simtools/model/mirrors.py +136 -73
- simtools/model/model_utils.py +1 -69
- simtools/model/telescope_model.py +32 -25
- simtools/psf_analysis.py +26 -19
- simtools/ray_tracing.py +54 -26
- simtools/schemas/data.metaschema.yml +400 -0
- simtools/schemas/metadata.metaschema.yml +566 -0
- simtools/simtel/simtel_config_writer.py +14 -5
- simtools/simtel/simtel_histograms.py +266 -83
- simtools/simtel/simtel_runner.py +8 -7
- simtools/simtel/simtel_runner_array.py +7 -8
- simtools/simtel/simtel_runner_camera_efficiency.py +48 -2
- simtools/simtel/simtel_runner_ray_tracing.py +61 -25
- simtools/simulator.py +43 -50
- simtools/utils/general.py +232 -286
- simtools/utils/geometry.py +163 -0
- simtools/utils/names.py +294 -142
- simtools/visualization/legend_handlers.py +115 -9
- simtools/visualization/visualize.py +13 -13
- gammasimtools-0.5.1.dist-info/RECORD +0 -83
- simtools/applications/plot_simtel_histograms.py +0 -120
- simtools/applications/validate_schema_files.py +0 -135
- simtools/corsika/corsika_output_visualize.py +0 -345
- simtools/data_model/validate_schema.py +0 -285
- {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/LICENSE +0 -0
- {gammasimtools-0.5.1.dist-info → gammasimtools-0.6.1.dist-info}/top_level.txt +0 -0
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import logging
|
|
3
3
|
import operator
|
|
4
|
+
import re
|
|
4
5
|
import time
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
|
|
7
8
|
import boost_histogram as bh
|
|
8
9
|
import numpy as np
|
|
9
10
|
from astropy import units as u
|
|
10
|
-
from astropy.
|
|
11
|
+
from astropy.io.misc import yaml
|
|
11
12
|
from astropy.units import cds
|
|
12
13
|
from corsikaio.subblocks import event_header, get_units_from_fields, run_header
|
|
14
|
+
from ctapipe.io import write_table
|
|
13
15
|
from eventio import IACTFile
|
|
14
16
|
|
|
15
|
-
from simtools import
|
|
16
|
-
from simtools.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
)
|
|
17
|
+
from simtools import version
|
|
18
|
+
from simtools.io_operations import io_handler
|
|
19
|
+
from simtools.io_operations.hdf5_handler import fill_hdf5_table
|
|
20
|
+
from simtools.utils.general import collect_data_from_file_or_dict
|
|
21
|
+
from simtools.utils.geometry import convert_2d_to_radial_distr, rotate
|
|
22
|
+
from simtools.utils.names import sanitize_name
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class HistogramNotCreated(Exception):
|
|
@@ -37,6 +38,8 @@ class CorsikaHistograms:
|
|
|
37
38
|
Instance label.
|
|
38
39
|
output_path: str
|
|
39
40
|
Path where to save the output of the class methods.
|
|
41
|
+
hdf5_file_name: str
|
|
42
|
+
HDF5 file name for histogram storage.
|
|
40
43
|
|
|
41
44
|
Raises
|
|
42
45
|
------
|
|
@@ -44,7 +47,7 @@ class CorsikaHistograms:
|
|
|
44
47
|
if the input file given does not exist.
|
|
45
48
|
"""
|
|
46
49
|
|
|
47
|
-
def __init__(self, input_file, label=None, output_path=None):
|
|
50
|
+
def __init__(self, input_file, label=None, output_path=None, hdf5_file_name=None):
|
|
48
51
|
self.label = label
|
|
49
52
|
self._logger = logging.getLogger(__name__)
|
|
50
53
|
self._logger.debug("Init CorsikaHistograms")
|
|
@@ -58,18 +61,17 @@ class CorsikaHistograms:
|
|
|
58
61
|
|
|
59
62
|
self.io_handler = io_handler.IOHandler()
|
|
60
63
|
_default_output_path = self.io_handler.get_output_directory(self.label, "corsika")
|
|
64
|
+
|
|
61
65
|
if output_path is None:
|
|
62
66
|
self.output_path = _default_output_path
|
|
63
67
|
else:
|
|
64
68
|
self.output_path = Path(output_path)
|
|
65
|
-
self._initialize_attributes()
|
|
66
|
-
self.read_event_information()
|
|
67
|
-
self._initialize_header()
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
if hdf5_file_name is None:
|
|
71
|
+
self.hdf5_file_name = re.split(r"\.", self.input_file.name)[0] + ".hdf5"
|
|
72
|
+
else:
|
|
73
|
+
self.hdf5_file_name = hdf5_file_name
|
|
74
|
+
|
|
73
75
|
self._telescope_indices = None
|
|
74
76
|
self._telescope_positions = None
|
|
75
77
|
self.num_events = None
|
|
@@ -79,8 +81,8 @@ class CorsikaHistograms:
|
|
|
79
81
|
self._num_photons_per_event = None
|
|
80
82
|
self._num_photons_per_telescope = None
|
|
81
83
|
self.__meta_dict = None
|
|
82
|
-
self.
|
|
83
|
-
self.
|
|
84
|
+
self._dict_2d_distributions = None
|
|
85
|
+
self._dict_1d_distributions = None
|
|
84
86
|
self._event_azimuth_angles = None
|
|
85
87
|
self._event_zenith_angles = None
|
|
86
88
|
self._hist_config = None
|
|
@@ -93,9 +95,36 @@ class CorsikaHistograms:
|
|
|
93
95
|
self.event_information = None
|
|
94
96
|
self._individual_telescopes = None
|
|
95
97
|
self._allowed_histograms = {"hist_position", "hist_direction", "hist_time_altitude"}
|
|
96
|
-
self.
|
|
97
|
-
self.
|
|
98
|
+
self._allowed_1d_labels = {"wavelength", "time", "altitude"}
|
|
99
|
+
self._allowed_2d_labels = {"counts", "density", "direction", "time_altitude"}
|
|
98
100
|
self._header = None
|
|
101
|
+
self.hist_position = None
|
|
102
|
+
self.hist_direction = None
|
|
103
|
+
self.hist_time_altitude = None
|
|
104
|
+
|
|
105
|
+
self.read_event_information()
|
|
106
|
+
self._initialize_header()
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def hdf5_file_name(self):
|
|
110
|
+
"""
|
|
111
|
+
Property for the hdf5 file name.
|
|
112
|
+
The idea of this property is to allow setting (or changing) the name of the hdf5 file
|
|
113
|
+
even after creating the class instance.
|
|
114
|
+
"""
|
|
115
|
+
return self._hdf5_file_name
|
|
116
|
+
|
|
117
|
+
@hdf5_file_name.setter
|
|
118
|
+
def hdf5_file_name(self, hdf5_file_name):
|
|
119
|
+
"""
|
|
120
|
+
Sets the hdf5_file_name to the argument passed.
|
|
121
|
+
|
|
122
|
+
Parameters
|
|
123
|
+
----------
|
|
124
|
+
hdf5_file_name: str
|
|
125
|
+
The name of hdf5 file to be set.
|
|
126
|
+
"""
|
|
127
|
+
self._hdf5_file_name = Path(self.output_path).joinpath(hdf5_file_name).absolute().as_posix()
|
|
99
128
|
|
|
100
129
|
@property
|
|
101
130
|
def corsika_version(self):
|
|
@@ -193,7 +222,7 @@ class CorsikaHistograms:
|
|
|
193
222
|
self.all_event_keys, all_event_units
|
|
194
223
|
)
|
|
195
224
|
|
|
196
|
-
# Add the
|
|
225
|
+
# Add the units to dictionary with the parameters and turn it into
|
|
197
226
|
# astropy.Quantities.
|
|
198
227
|
for i_key, key in enumerate(self.all_event_keys[1:]): # starting at the second
|
|
199
228
|
# element to avoid the non-numeric (e.g. 'EVTH') key.
|
|
@@ -315,7 +344,7 @@ class CorsikaHistograms:
|
|
|
315
344
|
input_dict = input_config
|
|
316
345
|
else:
|
|
317
346
|
input_yaml = input_config
|
|
318
|
-
self._hist_config =
|
|
347
|
+
self._hist_config = collect_data_from_file_or_dict(input_yaml, input_dict, allow_empty=True)
|
|
319
348
|
|
|
320
349
|
def hist_config_to_yaml(self, file_name=None):
|
|
321
350
|
"""
|
|
@@ -331,8 +360,9 @@ class CorsikaHistograms:
|
|
|
331
360
|
if file_name is None:
|
|
332
361
|
file_name = "hist_config"
|
|
333
362
|
file_name = Path(file_name).with_suffix(".yml")
|
|
334
|
-
|
|
335
|
-
|
|
363
|
+
output_config_file_name = Path(self.output_path).joinpath(file_name)
|
|
364
|
+
with open(output_config_file_name, "w", encoding="utf-8") as file:
|
|
365
|
+
yaml.dump(self.hist_config, file)
|
|
336
366
|
|
|
337
367
|
def _create_histogram_default_config(self):
|
|
338
368
|
"""
|
|
@@ -510,9 +540,9 @@ class CorsikaHistograms:
|
|
|
510
540
|
of the Cherenkov photons on the ground are saved:
|
|
511
541
|
x: x position on the ground (CORSIKA coordinate system),
|
|
512
542
|
y: y position on the ground (CORSIKA coordinate system),
|
|
513
|
-
cx: direction
|
|
543
|
+
cx: direction cosine in the x direction, i.e., the cosine of the angle between the
|
|
514
544
|
incoming direction and the x axis,
|
|
515
|
-
cy: direction
|
|
545
|
+
cy: direction cosine in the y direction, i.e., the cosine of the angle between the
|
|
516
546
|
incoming direction and the y axis,
|
|
517
547
|
time: time of arrival of the photon in ns. The clock starts when the particle crosses
|
|
518
548
|
the top of the atmosphere (CORSIKA-defined) if `self.event_first_interaction_heights`
|
|
@@ -605,7 +635,7 @@ class CorsikaHistograms:
|
|
|
605
635
|
|
|
606
636
|
num_photons_per_event_per_telescope_to_set = []
|
|
607
637
|
start_time = time.time()
|
|
608
|
-
self._logger.debug("Starting reading the file at {}."
|
|
638
|
+
self._logger.debug(f"Starting reading the file at {start_time}.")
|
|
609
639
|
with IACTFile(self.input_file) as f:
|
|
610
640
|
event_counter = 0
|
|
611
641
|
for event in f:
|
|
@@ -667,7 +697,7 @@ class CorsikaHistograms:
|
|
|
667
697
|
"""
|
|
668
698
|
|
|
669
699
|
for histogram in self._allowed_histograms:
|
|
670
|
-
if not hasattr(self, histogram):
|
|
700
|
+
if not hasattr(self, histogram) or getattr(self, histogram) is None:
|
|
671
701
|
msg = (
|
|
672
702
|
"The histograms were not created. Please, use `create_histograms` to create "
|
|
673
703
|
"histograms from the CORSIKA output file."
|
|
@@ -675,7 +705,7 @@ class CorsikaHistograms:
|
|
|
675
705
|
self._logger.error(msg)
|
|
676
706
|
raise HistogramNotCreated
|
|
677
707
|
|
|
678
|
-
def
|
|
708
|
+
def _get_hist_2d_projection(self, label):
|
|
679
709
|
"""
|
|
680
710
|
Helper function to get 2D distributions.
|
|
681
711
|
|
|
@@ -689,9 +719,9 @@ class CorsikaHistograms:
|
|
|
689
719
|
numpy.ndarray
|
|
690
720
|
The counts of the histogram.
|
|
691
721
|
numpy.array
|
|
692
|
-
The x edges of the histograms.
|
|
722
|
+
The x bin edges of the histograms.
|
|
693
723
|
numpy.array
|
|
694
|
-
The y edges of the histograms.
|
|
724
|
+
The y bin edges of the histograms.
|
|
695
725
|
|
|
696
726
|
Raises
|
|
697
727
|
------
|
|
@@ -699,8 +729,8 @@ class CorsikaHistograms:
|
|
|
699
729
|
if label is not valid.
|
|
700
730
|
"""
|
|
701
731
|
|
|
702
|
-
if label not in self.
|
|
703
|
-
msg = f"label is not valid. Valid entries are {self.
|
|
732
|
+
if label not in self._allowed_2d_labels:
|
|
733
|
+
msg = f"label is not valid. Valid entries are {self._allowed_2d_labels}"
|
|
704
734
|
self._logger.error(msg)
|
|
705
735
|
raise ValueError
|
|
706
736
|
self._raise_if_no_histogram()
|
|
@@ -709,7 +739,7 @@ class CorsikaHistograms:
|
|
|
709
739
|
len(self.telescope_indices) if self.individual_telescopes is True else 1
|
|
710
740
|
)
|
|
711
741
|
|
|
712
|
-
|
|
742
|
+
x_bin_edges, y_bin_edges, hist_values = [], [], []
|
|
713
743
|
for i_telescope in range(num_telescopes_to_fill):
|
|
714
744
|
if label == "counts":
|
|
715
745
|
mini_hist = self.hist_position[i_telescope][:, :, sum]
|
|
@@ -724,12 +754,12 @@ class CorsikaHistograms:
|
|
|
724
754
|
elif label == "time_altitude":
|
|
725
755
|
mini_hist = self.hist_time_altitude[i_telescope]
|
|
726
756
|
hist_values.append(self.hist_time_altitude[i_telescope].view().T)
|
|
727
|
-
|
|
728
|
-
|
|
757
|
+
x_bin_edges.append(mini_hist.axes.edges[0].flatten())
|
|
758
|
+
y_bin_edges.append(mini_hist.axes.edges[1].flatten())
|
|
729
759
|
|
|
730
|
-
return np.array(hist_values), np.array(
|
|
760
|
+
return np.array(hist_values), np.array(x_bin_edges), np.array(y_bin_edges)
|
|
731
761
|
|
|
732
|
-
def
|
|
762
|
+
def get_2d_photon_position_distr(self):
|
|
733
763
|
"""
|
|
734
764
|
Get 2D histograms of position of the Cherenkov photons on the ground.
|
|
735
765
|
|
|
@@ -738,13 +768,13 @@ class CorsikaHistograms:
|
|
|
738
768
|
numpy.ndarray
|
|
739
769
|
The counts of the histogram.
|
|
740
770
|
numpy.array
|
|
741
|
-
The x edges of the count histograms in x, usually in meters.
|
|
771
|
+
The x bin edges of the count histograms in x, usually in meters.
|
|
742
772
|
numpy.array
|
|
743
|
-
The y edges of the count histograms in y, usually in meters.
|
|
773
|
+
The y bin edges of the count histograms in y, usually in meters.
|
|
744
774
|
"""
|
|
745
|
-
return self.
|
|
775
|
+
return self._get_hist_2d_projection("counts")
|
|
746
776
|
|
|
747
|
-
def
|
|
777
|
+
def get_2d_photon_density_distr(self):
|
|
748
778
|
"""
|
|
749
779
|
Get 2D histograms of position of the Cherenkov photons on the ground. It returns the photon
|
|
750
780
|
density per square meter.
|
|
@@ -754,13 +784,13 @@ class CorsikaHistograms:
|
|
|
754
784
|
numpy.ndarray
|
|
755
785
|
The values of the histogram, usually in $m^{-2}$
|
|
756
786
|
numpy.array
|
|
757
|
-
The x edges of the density/count histograms in x, usually in meters.
|
|
787
|
+
The x bin edges of the density/count histograms in x, usually in meters.
|
|
758
788
|
numpy.array
|
|
759
|
-
The y edges of the density/count histograms in y, usually in meters.
|
|
789
|
+
The y bin edges of the density/count histograms in y, usually in meters.
|
|
760
790
|
"""
|
|
761
|
-
return self.
|
|
791
|
+
return self._get_hist_2d_projection("density")
|
|
762
792
|
|
|
763
|
-
def
|
|
793
|
+
def get_2d_photon_direction_distr(self):
|
|
764
794
|
"""
|
|
765
795
|
Get 2D histograms of incoming direction of the Cherenkov photons on the ground.
|
|
766
796
|
|
|
@@ -769,13 +799,13 @@ class CorsikaHistograms:
|
|
|
769
799
|
numpy.ndarray
|
|
770
800
|
The counts of the histogram.
|
|
771
801
|
numpy.array
|
|
772
|
-
The x edges of the direction histograms in cos(x).
|
|
802
|
+
The x bin edges of the direction histograms in cos(x).
|
|
773
803
|
numpy.array
|
|
774
|
-
The y edges of the direction histograms in cos(y)
|
|
804
|
+
The y bin edges of the direction histograms in cos(y)
|
|
775
805
|
"""
|
|
776
|
-
return self.
|
|
806
|
+
return self._get_hist_2d_projection("direction")
|
|
777
807
|
|
|
778
|
-
def
|
|
808
|
+
def get_2d_photon_time_altitude_distr(self):
|
|
779
809
|
"""
|
|
780
810
|
Get 2D histograms of the time and altitude of the photon production.
|
|
781
811
|
|
|
@@ -784,13 +814,13 @@ class CorsikaHistograms:
|
|
|
784
814
|
numpy.ndarray
|
|
785
815
|
The counts of the histogram.
|
|
786
816
|
numpy.array
|
|
787
|
-
The x edges of the time_altitude histograms, usually in ns.
|
|
817
|
+
The x bin edges of the time_altitude histograms, usually in ns.
|
|
788
818
|
numpy.array
|
|
789
|
-
The y edges of the time_altitude histograms, usually in km.
|
|
819
|
+
The y bin edges of the time_altitude histograms, usually in km.
|
|
790
820
|
"""
|
|
791
|
-
return self.
|
|
821
|
+
return self._get_hist_2d_projection("time_altitude")
|
|
792
822
|
|
|
793
|
-
def
|
|
823
|
+
def get_2d_num_photons_distr(self):
|
|
794
824
|
"""
|
|
795
825
|
Get the distribution of Cherenkov photons per event per telescope. It returns the 2D array
|
|
796
826
|
accounting for the events from the telescopes given by `self.telescope_indices`.
|
|
@@ -810,11 +840,11 @@ class CorsikaHistograms:
|
|
|
810
840
|
telescope_counter = np.arange(len(self.telescope_indices) + 1).reshape(
|
|
811
841
|
1, len(self.telescope_indices) + 1
|
|
812
842
|
)
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
return (
|
|
843
|
+
hist_2d = np.array(self.num_photons_per_event_per_telescope)
|
|
844
|
+
hist_2d = hist_2d.reshape((1, len(self.telescope_indices), self.num_events))
|
|
845
|
+
return (hist_2d, num_events_array, telescope_counter)
|
|
816
846
|
|
|
817
|
-
def
|
|
847
|
+
def _get_hist_1d_projection(self, label):
|
|
818
848
|
"""
|
|
819
849
|
Helper function to get 1D distributions.
|
|
820
850
|
|
|
@@ -828,7 +858,7 @@ class CorsikaHistograms:
|
|
|
828
858
|
numpy.ndarray
|
|
829
859
|
The counts of the histogram.
|
|
830
860
|
numpy.array
|
|
831
|
-
The edges of the histogram.
|
|
861
|
+
The bin edges of the histogram.
|
|
832
862
|
|
|
833
863
|
Raises
|
|
834
864
|
------
|
|
@@ -836,13 +866,13 @@ class CorsikaHistograms:
|
|
|
836
866
|
if label is not valid.
|
|
837
867
|
"""
|
|
838
868
|
|
|
839
|
-
if label not in self.
|
|
840
|
-
msg = f"{label} is not valid. Valid entries are {self.
|
|
869
|
+
if label not in self._allowed_1d_labels:
|
|
870
|
+
msg = f"{label} is not valid. Valid entries are {self._allowed_1d_labels}"
|
|
841
871
|
self._logger.error(msg)
|
|
842
872
|
raise ValueError
|
|
843
873
|
self._raise_if_no_histogram()
|
|
844
874
|
|
|
845
|
-
|
|
875
|
+
x_bin_edges_list, hist_1d_list = [], []
|
|
846
876
|
for i_hist, _ in enumerate(self.hist_position):
|
|
847
877
|
if label == "wavelength":
|
|
848
878
|
mini_hist = self.hist_position[i_hist][sum, sum, :]
|
|
@@ -851,9 +881,9 @@ class CorsikaHistograms:
|
|
|
851
881
|
elif label == "altitude":
|
|
852
882
|
mini_hist = self.hist_time_altitude[i_hist][sum, :]
|
|
853
883
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
return np.array(
|
|
884
|
+
x_bin_edges_list.append(mini_hist.axes.edges.T.flatten()[0])
|
|
885
|
+
hist_1d_list.append(mini_hist.view().T)
|
|
886
|
+
return np.array(hist_1d_list), np.array(x_bin_edges_list)
|
|
857
887
|
|
|
858
888
|
def _get_bins_max_dist(self, bins=None, max_dist=None):
|
|
859
889
|
"""Auxiliary function to get the number of bins and the max distance to generate the
|
|
@@ -905,26 +935,26 @@ class CorsikaHistograms:
|
|
|
905
935
|
np.array
|
|
906
936
|
The counts of the 1D histogram with size = int(max_dist/bin_size).
|
|
907
937
|
np.array
|
|
908
|
-
The edges of the 1D histogram in meters with size = int(max_dist/bin_size) + 1,
|
|
938
|
+
The bin edges of the 1D histogram in meters with size = int(max_dist/bin_size) + 1,
|
|
909
939
|
usually in meter.
|
|
910
940
|
"""
|
|
911
941
|
|
|
912
942
|
bins, max_dist = self._get_bins_max_dist(bins=bins, max_dist=max_dist)
|
|
913
|
-
|
|
943
|
+
bin_edges_1d_list, hist_1d_list = [], []
|
|
914
944
|
|
|
915
|
-
|
|
945
|
+
hist_2d_values_list, x_position_list, y_position_list = self.get_2d_photon_position_distr()
|
|
916
946
|
|
|
917
947
|
for i_hist, _ in enumerate(x_position_list):
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
x_position_list[i_hist],
|
|
948
|
+
hist_1d, bin_edges_1d = convert_2d_to_radial_distr(
|
|
949
|
+
hist_2d_values_list[i_hist],
|
|
950
|
+
x_position_list[i_hist], # pylint: disable=unnecessary-list-index-lookup
|
|
921
951
|
y_position_list[i_hist],
|
|
922
952
|
bins=bins,
|
|
923
953
|
max_dist=max_dist,
|
|
924
954
|
)
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
return np.array(
|
|
955
|
+
bin_edges_1d_list.append(bin_edges_1d)
|
|
956
|
+
hist_1d_list.append(hist_1d)
|
|
957
|
+
return np.array(hist_1d_list), np.array(bin_edges_1d_list)
|
|
928
958
|
|
|
929
959
|
def get_photon_density_distr(self, bins=None, max_dist=None):
|
|
930
960
|
"""
|
|
@@ -944,25 +974,25 @@ class CorsikaHistograms:
|
|
|
944
974
|
The density distribution of the 1D histogram with size = int(max_dist/bin_size),
|
|
945
975
|
usually in $m^{-2}$.
|
|
946
976
|
np.array
|
|
947
|
-
The edges of the 1D histogram in meters with size = int(max_dist/bin_size) + 1,
|
|
977
|
+
The bin edges of the 1D histogram in meters with size = int(max_dist/bin_size) + 1,
|
|
948
978
|
usually in meter.
|
|
949
979
|
"""
|
|
950
980
|
bins, max_dist = self._get_bins_max_dist(bins=bins, max_dist=max_dist)
|
|
951
|
-
|
|
981
|
+
bin_edges_1d_list, hist_1d_list = [], []
|
|
952
982
|
|
|
953
|
-
|
|
983
|
+
hist_2d_values_list, x_position_list, y_position_list = self.get_2d_photon_density_distr()
|
|
954
984
|
|
|
955
985
|
for i_hist, _ in enumerate(x_position_list):
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
x_position_list[i_hist],
|
|
986
|
+
hist_1d, bin_edges_1d = convert_2d_to_radial_distr(
|
|
987
|
+
hist_2d_values_list[i_hist],
|
|
988
|
+
x_position_list[i_hist], # pylint: disable=unnecessary-list-index-lookup
|
|
959
989
|
y_position_list[i_hist],
|
|
960
990
|
bins=bins,
|
|
961
991
|
max_dist=max_dist,
|
|
962
992
|
)
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
return np.array(
|
|
993
|
+
bin_edges_1d_list.append(bin_edges_1d)
|
|
994
|
+
hist_1d_list.append(hist_1d)
|
|
995
|
+
return np.array(hist_1d_list), np.array(bin_edges_1d_list)
|
|
966
996
|
|
|
967
997
|
def get_photon_wavelength_distr(self):
|
|
968
998
|
"""
|
|
@@ -973,10 +1003,10 @@ class CorsikaHistograms:
|
|
|
973
1003
|
np.array
|
|
974
1004
|
The counts of the wavelength histogram.
|
|
975
1005
|
np.array
|
|
976
|
-
The edges of the wavelength histogram in nanometers.
|
|
1006
|
+
The bin edges of the wavelength histogram in nanometers.
|
|
977
1007
|
|
|
978
1008
|
"""
|
|
979
|
-
return self.
|
|
1009
|
+
return self._get_hist_1d_projection("wavelength")
|
|
980
1010
|
|
|
981
1011
|
def get_photon_time_of_emission_distr(self):
|
|
982
1012
|
"""
|
|
@@ -989,10 +1019,10 @@ class CorsikaHistograms:
|
|
|
989
1019
|
numpy.ndarray
|
|
990
1020
|
The counts of the histogram.
|
|
991
1021
|
numpy.array
|
|
992
|
-
The edges of the time histograms in ns.
|
|
1022
|
+
The bin edges of the time histograms in ns.
|
|
993
1023
|
|
|
994
1024
|
"""
|
|
995
|
-
return self.
|
|
1025
|
+
return self._get_hist_1d_projection("time")
|
|
996
1026
|
|
|
997
1027
|
def get_photon_altitude_distr(self):
|
|
998
1028
|
"""
|
|
@@ -1003,10 +1033,10 @@ class CorsikaHistograms:
|
|
|
1003
1033
|
numpy.ndarray
|
|
1004
1034
|
The counts of the histogram.
|
|
1005
1035
|
numpy.array
|
|
1006
|
-
The edges of the photon altitude histograms in km.
|
|
1036
|
+
The bin edges of the photon altitude histograms in km.
|
|
1007
1037
|
|
|
1008
1038
|
"""
|
|
1009
|
-
return self.
|
|
1039
|
+
return self._get_hist_1d_projection("altitude")
|
|
1010
1040
|
|
|
1011
1041
|
@property
|
|
1012
1042
|
def num_photons_per_event_per_telescope(self):
|
|
@@ -1058,8 +1088,8 @@ class CorsikaHistograms:
|
|
|
1058
1088
|
numpy.array
|
|
1059
1089
|
Number of photons per event.
|
|
1060
1090
|
"""
|
|
1061
|
-
hist,
|
|
1062
|
-
return hist.reshape(1, bins),
|
|
1091
|
+
hist, bin_edges = np.histogram(self.num_photons_per_event, bins=bins, range=hist_range)
|
|
1092
|
+
return hist.reshape(1, bins), bin_edges.reshape(1, bins + 1)
|
|
1063
1093
|
|
|
1064
1094
|
def get_num_photons_per_telescope_distr(self, bins=50, hist_range=None):
|
|
1065
1095
|
"""
|
|
@@ -1080,15 +1110,20 @@ class CorsikaHistograms:
|
|
|
1080
1110
|
Number of photons per telescope.
|
|
1081
1111
|
"""
|
|
1082
1112
|
|
|
1083
|
-
hist,
|
|
1084
|
-
return hist.reshape(1, bins),
|
|
1113
|
+
hist, bin_edges = np.histogram(self.num_photons_per_telescope, bins=bins, range=hist_range)
|
|
1114
|
+
return hist.reshape(1, bins), bin_edges.reshape(1, bins + 1)
|
|
1085
1115
|
|
|
1086
|
-
def export_histograms(self):
|
|
1116
|
+
def export_histograms(self, overwrite=False):
|
|
1087
1117
|
"""
|
|
1088
|
-
Export the histograms to
|
|
1118
|
+
Export the histograms to hdf5 files.
|
|
1119
|
+
|
|
1120
|
+
Parameters
|
|
1121
|
+
----------
|
|
1122
|
+
overwrite: bool
|
|
1123
|
+
If True overwrites the histograms already saved in the hdf5 file.
|
|
1089
1124
|
"""
|
|
1090
|
-
self.
|
|
1091
|
-
self.
|
|
1125
|
+
self._export_1d_histograms(overwrite=overwrite)
|
|
1126
|
+
self._export_2d_histograms(overwrite=False)
|
|
1092
1127
|
|
|
1093
1128
|
@property
|
|
1094
1129
|
def _meta_dict(self):
|
|
@@ -1098,22 +1133,22 @@ class CorsikaHistograms:
|
|
|
1098
1133
|
Returns
|
|
1099
1134
|
-------
|
|
1100
1135
|
dict
|
|
1101
|
-
Meta dictionary for the
|
|
1136
|
+
Meta dictionary for the hdf5 files with the histograms.
|
|
1102
1137
|
"""
|
|
1103
1138
|
|
|
1104
1139
|
if self.__meta_dict is None:
|
|
1105
1140
|
self.__meta_dict = {
|
|
1106
|
-
"
|
|
1107
|
-
"
|
|
1108
|
-
"
|
|
1141
|
+
"corsika_version": self.corsika_version,
|
|
1142
|
+
"simtools_version": version.__version__,
|
|
1143
|
+
"iact_file": self.input_file.name,
|
|
1109
1144
|
"telescope_indices": list(self.telescope_indices),
|
|
1110
1145
|
"individual_telescopes": self.individual_telescopes,
|
|
1111
|
-
"
|
|
1146
|
+
"note": "Only lower bin edges are given.",
|
|
1112
1147
|
}
|
|
1113
1148
|
return self.__meta_dict
|
|
1114
1149
|
|
|
1115
1150
|
@property
|
|
1116
|
-
def
|
|
1151
|
+
def dict_1d_distributions(self):
|
|
1117
1152
|
"""
|
|
1118
1153
|
Dictionary to label the 1D distributions according to the class methods.
|
|
1119
1154
|
|
|
@@ -1122,96 +1157,111 @@ class CorsikaHistograms:
|
|
|
1122
1157
|
dict:
|
|
1123
1158
|
The dictionary with information about the 1D distributions.
|
|
1124
1159
|
"""
|
|
1125
|
-
self.
|
|
1160
|
+
self._dict_1d_distributions = {
|
|
1126
1161
|
"wavelength": {
|
|
1127
1162
|
"function": "get_photon_wavelength_distr",
|
|
1128
|
-
"file name": "
|
|
1163
|
+
"file name": "hist_1d_photon_wavelength_distr",
|
|
1129
1164
|
"title": "Photon wavelength distribution",
|
|
1130
|
-
"edges": "wavelength",
|
|
1131
|
-
"
|
|
1165
|
+
"bin edges": "wavelength",
|
|
1166
|
+
"axis unit": self.hist_config["hist_position"]["z axis"]["start"].unit,
|
|
1132
1167
|
},
|
|
1133
1168
|
"counts": {
|
|
1134
1169
|
"function": "get_photon_radial_distr",
|
|
1135
|
-
"file name": "
|
|
1170
|
+
"file name": "hist_1d_photon_radial_distr",
|
|
1136
1171
|
"title": "Radial photon distribution on the ground",
|
|
1137
|
-
"edges": "Distance to center",
|
|
1138
|
-
"
|
|
1172
|
+
"bin edges": "Distance to center",
|
|
1173
|
+
"axis unit": self.hist_config["hist_position"]["x axis"]["start"].unit,
|
|
1139
1174
|
},
|
|
1140
1175
|
"density": {
|
|
1141
1176
|
"function": "get_photon_density_distr",
|
|
1142
|
-
"file name": "
|
|
1177
|
+
"file name": "hist_1d_photon_density_distr",
|
|
1143
1178
|
"title": "Photon density distribution on the ground",
|
|
1144
|
-
"edges": "Distance to center",
|
|
1145
|
-
"
|
|
1179
|
+
"bin edges": "Distance to center",
|
|
1180
|
+
"axis unit": self.hist_config["hist_position"]["x axis"]["start"].unit,
|
|
1146
1181
|
},
|
|
1147
1182
|
"time": {
|
|
1148
1183
|
"function": "get_photon_time_of_emission_distr",
|
|
1149
|
-
"file name": "
|
|
1184
|
+
"file name": "hist_1d_photon_time_distr",
|
|
1150
1185
|
"title": "Photon time of arrival distribution",
|
|
1151
|
-
"edges": "Time of arrival",
|
|
1152
|
-
"
|
|
1186
|
+
"bin edges": "Time of arrival",
|
|
1187
|
+
"axis unit": self.hist_config["hist_time_altitude"]["x axis"]["start"].unit,
|
|
1153
1188
|
},
|
|
1154
1189
|
"altitude": {
|
|
1155
1190
|
"function": "get_photon_altitude_distr",
|
|
1156
|
-
"file name": "
|
|
1191
|
+
"file name": "hist_1d_photon_altitude_distr",
|
|
1157
1192
|
"title": "Photon altitude of emission distribution",
|
|
1158
|
-
"edges": "Altitude of emission",
|
|
1159
|
-
"
|
|
1193
|
+
"bin edges": "Altitude of emission",
|
|
1194
|
+
"axis unit": self.hist_config["hist_time_altitude"]["y axis"]["start"].unit,
|
|
1160
1195
|
},
|
|
1161
1196
|
"num_photons_per_event": {
|
|
1162
1197
|
"function": "get_num_photons_per_event_distr",
|
|
1163
|
-
"file name": "
|
|
1198
|
+
"file name": "hist_1d_photon_per_event_distr",
|
|
1164
1199
|
"title": "Photons per event distribution",
|
|
1165
|
-
"edges": "Event counter",
|
|
1166
|
-
"
|
|
1200
|
+
"bin edges": "Event counter",
|
|
1201
|
+
"axis unit": u.dimensionless_unscaled,
|
|
1167
1202
|
},
|
|
1168
1203
|
"num_photons_per_telescope": {
|
|
1169
1204
|
"function": "get_num_photons_per_telescope_distr",
|
|
1170
|
-
"file name": "
|
|
1205
|
+
"file name": "hist_1d_photon_per_telescope_distr",
|
|
1171
1206
|
"title": "Photons per telescope distribution",
|
|
1172
|
-
"edges": "Telescope counter",
|
|
1173
|
-
"
|
|
1207
|
+
"bin edges": "Telescope counter",
|
|
1208
|
+
"axis unit": u.dimensionless_unscaled,
|
|
1174
1209
|
},
|
|
1175
1210
|
}
|
|
1176
|
-
return self.
|
|
1211
|
+
return self._dict_1d_distributions
|
|
1177
1212
|
|
|
1178
|
-
def
|
|
1213
|
+
def _export_1d_histograms(self, overwrite=False):
|
|
1179
1214
|
"""
|
|
1180
1215
|
Auxiliary function to export only the 1D histograms.
|
|
1216
|
+
|
|
1217
|
+
Parameters
|
|
1218
|
+
----------
|
|
1219
|
+
overwrite: bool
|
|
1220
|
+
If True overwrites the histograms already saved in the hdf5 file.
|
|
1181
1221
|
"""
|
|
1182
1222
|
|
|
1183
|
-
for _, function_dict in self.
|
|
1184
|
-
self._meta_dict["Title"] = function_dict["title"]
|
|
1223
|
+
for _, function_dict in self.dict_1d_distributions.items():
|
|
1224
|
+
self._meta_dict["Title"] = sanitize_name(function_dict["title"])
|
|
1185
1225
|
function = getattr(self, function_dict["function"])
|
|
1186
|
-
|
|
1187
|
-
|
|
1226
|
+
hist_1d_list, x_bin_edges_list = function()
|
|
1227
|
+
x_bin_edges_list = x_bin_edges_list * function_dict["axis unit"]
|
|
1188
1228
|
if function_dict["function"] == "get_photon_density_distr":
|
|
1189
|
-
histogram_value_unit = 1 / (function_dict["
|
|
1229
|
+
histogram_value_unit = 1 / (function_dict["axis unit"] ** 2)
|
|
1190
1230
|
else:
|
|
1191
1231
|
histogram_value_unit = u.dimensionless_unscaled
|
|
1192
|
-
|
|
1193
|
-
for i_histogram, _ in enumerate(
|
|
1232
|
+
hist_1d_list = hist_1d_list * histogram_value_unit
|
|
1233
|
+
for i_histogram, _ in enumerate(x_bin_edges_list):
|
|
1194
1234
|
if self.individual_telescopes:
|
|
1195
|
-
|
|
1196
|
-
f"{function_dict['file name']}_"
|
|
1197
|
-
f"tel_index_{self.telescope_indices[i_histogram]}
|
|
1235
|
+
hdf5_table_name = (
|
|
1236
|
+
f"/{function_dict['file name']}_"
|
|
1237
|
+
f"tel_index_{self.telescope_indices[i_histogram]}"
|
|
1198
1238
|
)
|
|
1199
1239
|
else:
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
table =
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
None,
|
|
1206
|
-
function_dict["edges"],
|
|
1207
|
-
None,
|
|
1240
|
+
hdf5_table_name = f"/{function_dict['file name']}_all_tels"
|
|
1241
|
+
|
|
1242
|
+
table = fill_hdf5_table(
|
|
1243
|
+
hist=hist_1d_list[i_histogram],
|
|
1244
|
+
x_bin_edges=x_bin_edges_list[i_histogram],
|
|
1245
|
+
y_bin_edges=None,
|
|
1246
|
+
x_label=function_dict["bin edges"],
|
|
1247
|
+
y_label=None,
|
|
1248
|
+
meta_data=self._meta_dict,
|
|
1249
|
+
)
|
|
1250
|
+
self._logger.info(
|
|
1251
|
+
f"Writing 1D histogram with name {hdf5_table_name} to "
|
|
1252
|
+
f"{self.hdf5_file_name}."
|
|
1253
|
+
)
|
|
1254
|
+
# overwrite takes precedence over append
|
|
1255
|
+
if overwrite is True:
|
|
1256
|
+
append = False
|
|
1257
|
+
else:
|
|
1258
|
+
append = True
|
|
1259
|
+
write_table(
|
|
1260
|
+
table, self.hdf5_file_name, hdf5_table_name, append=append, overwrite=overwrite
|
|
1208
1261
|
)
|
|
1209
|
-
ecsv_file = Path(self.output_path).joinpath(ecsv_file)
|
|
1210
|
-
self._logger.info(f"Exporting histogram to {ecsv_file}.")
|
|
1211
|
-
table.write(ecsv_file, format="ascii.ecsv", overwrite=True)
|
|
1212
1262
|
|
|
1213
1263
|
@property
|
|
1214
|
-
def
|
|
1264
|
+
def dict_2d_distributions(self):
|
|
1215
1265
|
"""
|
|
1216
1266
|
Dictionary to label the 2D distributions according to the class methods.
|
|
1217
1267
|
|
|
@@ -1220,150 +1270,118 @@ class CorsikaHistograms:
|
|
|
1220
1270
|
dict:
|
|
1221
1271
|
The dictionary with information about the 2D distributions.
|
|
1222
1272
|
"""
|
|
1223
|
-
if self.
|
|
1224
|
-
self.
|
|
1273
|
+
if self._dict_2d_distributions is None:
|
|
1274
|
+
self._dict_2d_distributions = {
|
|
1225
1275
|
"counts": {
|
|
1226
|
-
"function": "
|
|
1227
|
-
"file name": "
|
|
1276
|
+
"function": "get_2d_photon_position_distr",
|
|
1277
|
+
"file name": "hist_2d_photon_count_distr",
|
|
1228
1278
|
"title": "Photon count distribution on the ground",
|
|
1229
|
-
"x edges": "x position on the ground",
|
|
1230
|
-
"x
|
|
1231
|
-
"y edges": "y position on the ground",
|
|
1232
|
-
"y
|
|
1279
|
+
"x bin edges": "x position on the ground",
|
|
1280
|
+
"x axis unit": self.hist_config["hist_position"]["x axis"]["start"].unit,
|
|
1281
|
+
"y bin edges": "y position on the ground",
|
|
1282
|
+
"y axis unit": self.hist_config["hist_position"]["y axis"]["start"].unit,
|
|
1233
1283
|
},
|
|
1234
1284
|
"density": {
|
|
1235
|
-
"function": "
|
|
1236
|
-
"file name": "
|
|
1285
|
+
"function": "get_2d_photon_density_distr",
|
|
1286
|
+
"file name": "hist_2d_photon_density_distr",
|
|
1237
1287
|
"title": "Photon density distribution on the ground",
|
|
1238
|
-
"x edges": "x position on the ground",
|
|
1239
|
-
"x
|
|
1240
|
-
"y edges": "y position on the ground",
|
|
1241
|
-
"y
|
|
1288
|
+
"x bin edges": "x position on the ground",
|
|
1289
|
+
"x axis unit": self.hist_config["hist_position"]["x axis"]["start"].unit,
|
|
1290
|
+
"y bin edges": "y position on the ground",
|
|
1291
|
+
"y axis unit": self.hist_config["hist_position"]["y axis"]["start"].unit,
|
|
1242
1292
|
},
|
|
1243
1293
|
"direction": {
|
|
1244
|
-
"function": "
|
|
1245
|
-
"file name": "
|
|
1294
|
+
"function": "get_2d_photon_direction_distr",
|
|
1295
|
+
"file name": "hist_2d_photon_direction_distr",
|
|
1246
1296
|
"title": "Photon arrival direction",
|
|
1247
|
-
"x edges": "x direction cosine",
|
|
1248
|
-
"x
|
|
1249
|
-
"y edges": "y direction cosine",
|
|
1250
|
-
"y
|
|
1297
|
+
"x bin edges": "x direction cosine",
|
|
1298
|
+
"x axis unit": u.dimensionless_unscaled,
|
|
1299
|
+
"y bin edges": "y direction cosine",
|
|
1300
|
+
"y axis unit": u.dimensionless_unscaled,
|
|
1251
1301
|
},
|
|
1252
1302
|
"time_altitude": {
|
|
1253
|
-
"function": "
|
|
1254
|
-
"file name": "
|
|
1303
|
+
"function": "get_2d_photon_time_altitude_distr",
|
|
1304
|
+
"file name": "hist_2d_photon_time_altitude_distr",
|
|
1255
1305
|
"title": "Time of arrival vs altitude of emission",
|
|
1256
|
-
"x edges": "Time of arrival",
|
|
1257
|
-
"x
|
|
1258
|
-
"y edges": "Altitude of emission",
|
|
1259
|
-
"y
|
|
1306
|
+
"x bin edges": "Time of arrival",
|
|
1307
|
+
"x axis unit": self.hist_config["hist_time_altitude"]["x axis"]["start"].unit,
|
|
1308
|
+
"y bin edges": "Altitude of emission",
|
|
1309
|
+
"y axis unit": self.hist_config["hist_time_altitude"]["y axis"]["start"].unit,
|
|
1260
1310
|
},
|
|
1261
1311
|
"num_photons_per_telescope": {
|
|
1262
|
-
"function": "
|
|
1263
|
-
"file name": "
|
|
1312
|
+
"function": "get_2d_num_photons_distr",
|
|
1313
|
+
"file name": "hist_2d_photon_telescope_event_distr",
|
|
1264
1314
|
"title": "Number of photons per telescope and per event",
|
|
1265
|
-
"x edges": "Telescope counter",
|
|
1266
|
-
"x
|
|
1267
|
-
"y edges": "Event counter",
|
|
1268
|
-
"y
|
|
1315
|
+
"x bin edges": "Telescope counter",
|
|
1316
|
+
"x axis unit": u.dimensionless_unscaled,
|
|
1317
|
+
"y bin edges": "Event counter",
|
|
1318
|
+
"y axis unit": u.dimensionless_unscaled,
|
|
1269
1319
|
},
|
|
1270
1320
|
}
|
|
1271
|
-
return self.
|
|
1321
|
+
return self._dict_2d_distributions
|
|
1272
1322
|
|
|
1273
|
-
def
|
|
1323
|
+
def _export_2d_histograms(self, overwrite):
|
|
1274
1324
|
"""
|
|
1275
1325
|
Auxiliary function to export only the 2D histograms.
|
|
1276
|
-
"""
|
|
1277
1326
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1327
|
+
Parameters
|
|
1328
|
+
----------
|
|
1329
|
+
overwrite: bool
|
|
1330
|
+
If True overwrites the histograms already saved in the hdf5 file.
|
|
1331
|
+
"""
|
|
1332
|
+
for property_name, function_dict in self.dict_2d_distributions.items():
|
|
1333
|
+
self._meta_dict["Title"] = sanitize_name(function_dict["title"])
|
|
1280
1334
|
function = getattr(self, function_dict["function"])
|
|
1281
1335
|
|
|
1282
|
-
|
|
1283
|
-
if function_dict["function"] == "
|
|
1336
|
+
hist_2d_list, x_bin_edges_list, y_bin_edges_list = function()
|
|
1337
|
+
if function_dict["function"] == "get_2d_photon_density_distr":
|
|
1284
1338
|
histogram_value_unit = 1 / (
|
|
1285
|
-
self.
|
|
1286
|
-
* self.
|
|
1339
|
+
self.dict_2d_distributions[property_name]["x axis unit"]
|
|
1340
|
+
* self.dict_2d_distributions[property_name]["y axis unit"]
|
|
1287
1341
|
)
|
|
1288
1342
|
else:
|
|
1289
1343
|
histogram_value_unit = u.dimensionless_unscaled
|
|
1290
1344
|
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1345
|
+
hist_2d_list, x_bin_edges_list, y_bin_edges_list = (
|
|
1346
|
+
hist_2d_list * histogram_value_unit,
|
|
1347
|
+
x_bin_edges_list * self.dict_2d_distributions[property_name]["x axis unit"],
|
|
1348
|
+
y_bin_edges_list * self.dict_2d_distributions[property_name]["y axis unit"],
|
|
1295
1349
|
)
|
|
1296
1350
|
|
|
1297
|
-
for i_histogram, _ in enumerate(
|
|
1351
|
+
for i_histogram, _ in enumerate(x_bin_edges_list):
|
|
1298
1352
|
if self.individual_telescopes:
|
|
1299
|
-
|
|
1300
|
-
f"{self.
|
|
1301
|
-
f"_tel_index_{self.telescope_indices[i_histogram]}
|
|
1353
|
+
hdf5_table_name = (
|
|
1354
|
+
f"/{self.dict_2d_distributions[property_name]['file name']}"
|
|
1355
|
+
f"_tel_index_{self.telescope_indices[i_histogram]}"
|
|
1302
1356
|
)
|
|
1303
1357
|
else:
|
|
1304
|
-
|
|
1305
|
-
f"{self.
|
|
1358
|
+
hdf5_table_name = (
|
|
1359
|
+
f"/{self.dict_2d_distributions[property_name]['file name']}" f"_all_tels"
|
|
1306
1360
|
)
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
function_dict["
|
|
1313
|
-
|
|
1361
|
+
table = fill_hdf5_table(
|
|
1362
|
+
hist=hist_2d_list[i_histogram],
|
|
1363
|
+
x_bin_edges=x_bin_edges_list[i_histogram],
|
|
1364
|
+
y_bin_edges=y_bin_edges_list[i_histogram],
|
|
1365
|
+
x_label=function_dict["x bin edges"],
|
|
1366
|
+
y_label=function_dict["y bin edges"],
|
|
1367
|
+
meta_data=self._meta_dict,
|
|
1314
1368
|
)
|
|
1315
|
-
ecsv_file = Path(self.output_path).joinpath(ecsv_file)
|
|
1316
|
-
self._logger.info(f"Exporting histogram to {ecsv_file}.")
|
|
1317
|
-
table.write(ecsv_file, format="ascii.ecsv", overwrite=True)
|
|
1318
1369
|
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
x_edges: numpy.array
|
|
1329
|
-
The x edges of the histograms.
|
|
1330
|
-
y_edges: numpy.array
|
|
1331
|
-
The y edges of the histograms.
|
|
1332
|
-
x_label: str
|
|
1333
|
-
X edges label.
|
|
1334
|
-
y_label: str
|
|
1335
|
-
Y edges label.
|
|
1336
|
-
"""
|
|
1337
|
-
try:
|
|
1338
|
-
x_edges_2D, y_edges_2D = np.meshgrid(x_edges[:-1], y_edges[:-1])
|
|
1339
|
-
x_edges_2D_flattened, y_edges_2D_flattened, hist_2D_flattened = (
|
|
1340
|
-
x_edges_2D.flatten(),
|
|
1341
|
-
y_edges_2D.flatten(),
|
|
1342
|
-
hist.flatten(),
|
|
1343
|
-
)
|
|
1344
|
-
table = QTable(
|
|
1345
|
-
[
|
|
1346
|
-
x_edges_2D_flattened,
|
|
1347
|
-
y_edges_2D_flattened,
|
|
1348
|
-
hist_2D_flattened,
|
|
1349
|
-
],
|
|
1350
|
-
names=(x_label, y_label, "Values"),
|
|
1351
|
-
meta=self._meta_dict,
|
|
1352
|
-
)
|
|
1353
|
-
except TypeError:
|
|
1354
|
-
table = QTable(
|
|
1355
|
-
[
|
|
1356
|
-
x_edges[:-1],
|
|
1357
|
-
hist,
|
|
1358
|
-
],
|
|
1359
|
-
names=(x_label, "Values"),
|
|
1360
|
-
meta=self._meta_dict,
|
|
1361
|
-
)
|
|
1362
|
-
return table
|
|
1370
|
+
self._logger.info(
|
|
1371
|
+
f"Writing 2D histogram with name {hdf5_table_name} to "
|
|
1372
|
+
f"{self.hdf5_file_name}."
|
|
1373
|
+
)
|
|
1374
|
+
# Always appending to table due to the file previously created
|
|
1375
|
+
# by self._export_1d_histograms.
|
|
1376
|
+
write_table(
|
|
1377
|
+
table, self.hdf5_file_name, hdf5_table_name, append=True, overwrite=overwrite
|
|
1378
|
+
)
|
|
1363
1379
|
|
|
1364
|
-
def
|
|
1380
|
+
def export_event_header_1d_histogram(
|
|
1381
|
+
self, event_header_element, bins=50, hist_range=None, overwrite=False
|
|
1382
|
+
):
|
|
1365
1383
|
"""
|
|
1366
|
-
Export to a
|
|
1384
|
+
Export to a hdf5 file the 1D histogram for the key `event_header_element` from the CORSIKA
|
|
1367
1385
|
event header.
|
|
1368
1386
|
|
|
1369
1387
|
Parameters
|
|
@@ -1375,28 +1393,44 @@ class CorsikaHistograms:
|
|
|
1375
1393
|
Number of bins for the histogram.
|
|
1376
1394
|
hist_range: 2-tuple
|
|
1377
1395
|
Tuple to define the range of the histogram.
|
|
1396
|
+
overwrite: bool
|
|
1397
|
+
If True overwrites the histograms already saved in the hdf5 file.
|
|
1378
1398
|
"""
|
|
1379
1399
|
|
|
1380
|
-
hist,
|
|
1400
|
+
hist, bin_edges = self.event_1d_histogram(
|
|
1381
1401
|
event_header_element, bins=bins, hist_range=hist_range
|
|
1382
1402
|
)
|
|
1383
|
-
|
|
1384
|
-
table =
|
|
1385
|
-
|
|
1386
|
-
|
|
1403
|
+
bin_edges *= self.event_information[event_header_element].unit
|
|
1404
|
+
table = fill_hdf5_table(
|
|
1405
|
+
hist=hist,
|
|
1406
|
+
x_bin_edges=bin_edges,
|
|
1407
|
+
y_bin_edges=None,
|
|
1408
|
+
x_label=event_header_element,
|
|
1409
|
+
y_label=None,
|
|
1410
|
+
meta_data=self._meta_dict,
|
|
1387
1411
|
)
|
|
1388
|
-
|
|
1389
|
-
table.write(ecsv_file, format="ascii.ecsv", overwrite=True)
|
|
1412
|
+
hdf5_table_name = f"/event_2d_histograms_{event_header_element}"
|
|
1390
1413
|
|
|
1391
|
-
|
|
1414
|
+
self._logger.info(
|
|
1415
|
+
f"Exporting histogram with name {hdf5_table_name} to {self.hdf5_file_name}."
|
|
1416
|
+
)
|
|
1417
|
+
# overwrite takes precedence over append
|
|
1418
|
+
if overwrite is True:
|
|
1419
|
+
append = False
|
|
1420
|
+
else:
|
|
1421
|
+
append = True
|
|
1422
|
+
write_table(table, self.hdf5_file_name, hdf5_table_name, append=append, overwrite=overwrite)
|
|
1423
|
+
|
|
1424
|
+
def export_event_header_2d_histogram(
|
|
1392
1425
|
self,
|
|
1393
1426
|
event_header_element_1,
|
|
1394
1427
|
event_header_element_2,
|
|
1395
1428
|
bins=50,
|
|
1396
1429
|
hist_range=None,
|
|
1430
|
+
overwrite=False,
|
|
1397
1431
|
):
|
|
1398
1432
|
"""
|
|
1399
|
-
Export to a
|
|
1433
|
+
Export to a hdf5 file the 2D histogram for the key `event_header_element_1` and
|
|
1400
1434
|
`event_header_element_2`from the CORSIKA event header.
|
|
1401
1435
|
|
|
1402
1436
|
Parameters
|
|
@@ -1411,23 +1445,35 @@ class CorsikaHistograms:
|
|
|
1411
1445
|
Number of bins for the histogram.
|
|
1412
1446
|
hist_range: 2-tuple
|
|
1413
1447
|
Tuple to define the range of the histogram.
|
|
1448
|
+
overwrite: bool
|
|
1449
|
+
If True overwrites the histograms already saved in the hdf5 file.
|
|
1414
1450
|
"""
|
|
1415
|
-
hist,
|
|
1451
|
+
hist, x_bin_edges, y_bin_edges = self.event_2d_histogram(
|
|
1416
1452
|
event_header_element_1, event_header_element_2, bins=bins, hist_range=hist_range
|
|
1417
1453
|
)
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
table =
|
|
1422
|
-
hist,
|
|
1454
|
+
x_bin_edges *= self.event_information[event_header_element_1].unit
|
|
1455
|
+
y_bin_edges *= self.event_information[event_header_element_2].unit
|
|
1456
|
+
|
|
1457
|
+
table = fill_hdf5_table(
|
|
1458
|
+
hist=hist,
|
|
1459
|
+
x_bin_edges=x_bin_edges,
|
|
1460
|
+
y_bin_edges=y_bin_edges,
|
|
1461
|
+
x_label=event_header_element_1,
|
|
1462
|
+
y_label=event_header_element_2,
|
|
1463
|
+
meta_data=self._meta_dict,
|
|
1423
1464
|
)
|
|
1424
1465
|
|
|
1425
|
-
|
|
1426
|
-
f"event_2D_histograms_{event_header_element_1}" f"_{event_header_element_2}.ecsv"
|
|
1427
|
-
)
|
|
1466
|
+
hdf5_table_name = f"/event_2d_histograms_{event_header_element_1}_{event_header_element_2}"
|
|
1428
1467
|
|
|
1429
|
-
self._logger.info(
|
|
1430
|
-
|
|
1468
|
+
self._logger.info(
|
|
1469
|
+
f"Exporting histogram with name {hdf5_table_name} to {self.hdf5_file_name}."
|
|
1470
|
+
)
|
|
1471
|
+
# overwrite takes precedence over append
|
|
1472
|
+
if overwrite is True:
|
|
1473
|
+
append = False
|
|
1474
|
+
else:
|
|
1475
|
+
append = True
|
|
1476
|
+
write_table(table, self.hdf5_file_name, hdf5_table_name, append=append, overwrite=overwrite)
|
|
1431
1477
|
|
|
1432
1478
|
@property
|
|
1433
1479
|
def num_photons_per_telescope(self):
|
|
@@ -1632,7 +1678,7 @@ class CorsikaHistograms:
|
|
|
1632
1678
|
raise KeyError
|
|
1633
1679
|
return self.header[parameter]
|
|
1634
1680
|
|
|
1635
|
-
def
|
|
1681
|
+
def event_1d_histogram(self, key, bins=50, hist_range=None):
|
|
1636
1682
|
"""
|
|
1637
1683
|
Create a histogram for the all events using `key` as parameter.
|
|
1638
1684
|
Valid keys are stored in `self.all_event_keys` (CORSIKA defined).
|
|
@@ -1664,14 +1710,14 @@ class CorsikaHistograms:
|
|
|
1664
1710
|
msg = f"`key` is not valid. Valid entries are {self.all_event_keys}"
|
|
1665
1711
|
self._logger.error(msg)
|
|
1666
1712
|
raise KeyError
|
|
1667
|
-
hist,
|
|
1713
|
+
hist, bin_edges = np.histogram(
|
|
1668
1714
|
self.event_information[key].value,
|
|
1669
1715
|
bins=bins,
|
|
1670
1716
|
range=hist_range,
|
|
1671
1717
|
)
|
|
1672
|
-
return hist,
|
|
1718
|
+
return hist, bin_edges
|
|
1673
1719
|
|
|
1674
|
-
def
|
|
1720
|
+
def event_2d_histogram(self, key_1, key_2, bins=50, hist_range=None):
|
|
1675
1721
|
"""
|
|
1676
1722
|
Create a 2D histogram for the all events using `key_1` and `key_2` as parameters.
|
|
1677
1723
|
Valid keys are stored in `self.all_event_keys` (CORSIKA defined).
|
|
@@ -1712,10 +1758,10 @@ class CorsikaHistograms:
|
|
|
1712
1758
|
)
|
|
1713
1759
|
self._logger.error(msg)
|
|
1714
1760
|
raise KeyError
|
|
1715
|
-
hist,
|
|
1761
|
+
hist, x_bin_edges, y_bin_edges = np.histogram2d(
|
|
1716
1762
|
self.event_information[key_1].value,
|
|
1717
1763
|
self.event_information[key_2].value,
|
|
1718
1764
|
bins=bins,
|
|
1719
1765
|
range=hist_range,
|
|
1720
1766
|
)
|
|
1721
|
-
return hist,
|
|
1767
|
+
return hist, x_bin_edges, y_bin_edges
|