Skip to content

Commit 370b6b9

Browse files
authored
Merge pull request #2082 from cta-observatory/fix_invalid
Fix invalid case in HillasReconstructor and HillasIntersection
2 parents cd944fe + a924066 commit 370b6b9

File tree

5 files changed

+48
-24
lines changed

5 files changed

+48
-24
lines changed

ctapipe/reco/hillas_intersection.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,18 @@ def __call__(self, event):
9696
9797
Parameters
9898
----------
99-
event: `ctapipe.containers.ArrayEventContainer`
100-
The event, needs to have dl1 parameters
99+
event : `~ctapipe.containers.ArrayEventContainer`
100+
The event, needs to have dl1 parameters.
101+
Will be filled with the corresponding dl2 containers,
102+
reconstructed stereo geometry and telescope-wise impact position.
101103
"""
102104

103105
try:
104106
hillas_dict = self._create_hillas_dict(event)
105107
except (TooFewTelescopesException, InvalidWidthException):
106-
return INVALID
108+
event.dl2.stereo.geometry[self.__class__.__name__] = INVALID
109+
self._store_impact_parameter(event)
110+
return
107111

108112
# Due to tracking the pointing of the array will never be a constant
109113
array_pointing = SkyCoord(

ctapipe/reco/hillas_reconstructor.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,23 +133,23 @@ def __init__(self, subarray, **kwargs):
133133

134134
def __call__(self, event):
135135
"""
136-
Perform the full shower geometry reconstruction on the input event.
136+
Perform the full shower geometry reconstruction.
137137
138138
Parameters
139139
----------
140-
event: `ctapipe.containers.ArrayEventContainer`
141-
The event, needs to have dl1 parameters
142-
143-
Returns
144-
-------
145-
ReconstructedGeometryContainer
140+
event : `~ctapipe.containers.ArrayEventContainer`
141+
The event, needs to have dl1 parameters.
142+
Will be filled with the corresponding dl2 containers,
143+
reconstructed stereo geometry and telescope-wise impact position.
146144
"""
147145
warnings.filterwarnings(action="ignore", category=MissingFrameAttributeWarning)
148146

149147
try:
150148
hillas_dict = self._create_hillas_dict(event)
151149
except (TooFewTelescopesException, InvalidWidthException):
152-
return INVALID
150+
event.dl2.stereo.geometry[self.__class__.__name__] = INVALID
151+
self._store_impact_parameter(event)
152+
return
153153

154154
# Here we perform some basic quality checks BEFORE applying reconstruction
155155
# This should be substituted by a DL1 QualityQuery specific to this

ctapipe/reco/reco_algorithms.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from abc import abstractmethod
22

3+
import astropy.units as u
34
import numpy as np
45
from astropy.coordinates import AltAz, SkyCoord
56

@@ -47,18 +48,18 @@ def __init__(self, subarray, **kwargs):
4748

4849
@abstractmethod
4950
def __call__(self, event: ArrayEventContainer):
50-
"""overwrite this method with your favourite direction reconstruction
51-
algorithm
51+
"""
52+
Perform stereo reconstruction on event.
53+
54+
This method must fill the result of the reconstruction into the
55+
dl2 structure of the event.
5256
5357
Parameters
5458
----------
55-
tels_dict : dict
56-
general dictionary containing all triggered telescopes data
57-
Returns
58-
-------
59-
None
60-
Container are directly filled into the event structure
61-
59+
event : `ctapipe.containers.ArrayEventContainer`
60+
The event, needs to have dl1 parameters.
61+
Will be filled with the corresponding dl2 containers,
62+
reconstructed stereo geometry and telescope-wise impact position.
6263
"""
6364

6465
def _create_hillas_dict(self, event):
@@ -97,10 +98,17 @@ def _get_telescope_pointings(event):
9798

9899
def _store_impact_parameter(self, event):
99100
"""Compute and store the impact parameter for each reconstruction."""
100-
impact_distances = shower_impact_distance(
101-
shower_geom=event.dl2.stereo.geometry[self.__class__.__name__],
102-
subarray=self.subarray,
103-
)
101+
geometry = event.dl2.stereo.geometry[self.__class__.__name__]
102+
103+
if geometry.is_valid:
104+
impact_distances = shower_impact_distance(
105+
shower_geom=geometry,
106+
subarray=self.subarray,
107+
)
108+
else:
109+
n_tels = len(self.subarray)
110+
impact_distances = u.Quantity(np.full(n_tels, np.nan), u.m)
111+
104112
default_prefix = TelescopeImpactParameterContainer.default_prefix
105113
prefix = f"{self.__class__.__name__}_tel_{default_prefix}"
106114
for tel_id in event.trigger.tels_with_trigger:

ctapipe/reco/tests/test_HillasReconstructor.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ def test_invalid_events(subarray_and_event_gamma_off_axis_500_gev):
9090
original_event = deepcopy(event)
9191

9292
hillas_reconstructor(event)
93+
# test the container is actually there and not only created by Map
94+
assert "HillasReconstructor" in event.dl2.stereo.geometry
9395
result = event.dl2.stereo.geometry["HillasReconstructor"]
9496
assert result.is_valid
9597

@@ -101,6 +103,8 @@ def test_invalid_events(subarray_and_event_gamma_off_axis_500_gev):
101103
invalid_event.dl1.tel[tel_id].parameters.hillas = HillasParametersContainer()
102104

103105
hillas_reconstructor(invalid_event)
106+
# test the container is actually there and not only created by Map
107+
assert "HillasReconstructor" in invalid_event.dl2.stereo.geometry
104108
result = invalid_event.dl2.stereo.geometry["HillasReconstructor"]
105109
assert not result.is_valid
106110

@@ -109,13 +113,17 @@ def test_invalid_events(subarray_and_event_gamma_off_axis_500_gev):
109113
invalid_event = deepcopy(original_event)
110114
invalid_event.dl1.tel[tel_id].parameters.hillas.width = 0 * u.m
111115
hillas_reconstructor(invalid_event)
116+
# test the container is actually there and not only created by Map
117+
assert "HillasReconstructor" in invalid_event.dl2.stereo.geometry
112118
result = invalid_event.dl2.stereo.geometry["HillasReconstructor"]
113119
assert not result.is_valid
114120

115121
# Now use the original event, but overwrite the last width to NaN
116122
invalid_event = deepcopy(original_event)
117123
invalid_event.dl1.tel[tel_id].parameters.hillas.width = np.nan * u.m
118124
hillas_reconstructor(invalid_event)
125+
# test the container is actually there and not only created by Map
126+
assert "HillasReconstructor" in invalid_event.dl2.stereo.geometry
119127
result = invalid_event.dl2.stereo.geometry["HillasReconstructor"]
120128
assert not result.is_valid
121129

@@ -140,6 +148,8 @@ def test_reconstruction_against_simulation_telescope_frame(
140148
calib(event)
141149
image_processor(event)
142150
reconstructor(event)
151+
# test the container is actually there and not only created by Map
152+
assert "HillasReconstructor" in event.dl2.stereo.geometry
143153
result = event.dl2.stereo.geometry["HillasReconstructor"]
144154

145155
# get the reconstructed coordinates in the sky

ctapipe/reco/tests/test_reconstruction_methods.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ def test_reconstructors(reconstructors):
4242
reconstructor(event)
4343

4444
name = ReconstructorType.__name__
45+
# test the container is actually there and not only created by Map
46+
assert name in event.dl2.stereo.geometry
4547
assert event.dl2.stereo.geometry[name].alt.unit.is_equivalent(u.deg)
4648
assert event.dl2.stereo.geometry[name].az.unit.is_equivalent(u.deg)
4749
assert event.dl2.stereo.geometry[name].core_x.unit.is_equivalent(u.m)

0 commit comments

Comments
 (0)