Skip to content

Commit 4fdd013

Browse files
committed
big remake
1 parent 79adb2b commit 4fdd013

1 file changed

Lines changed: 85 additions & 112 deletions

File tree

src/graphnet/data/extractors/icecube/i3calorimetry.py

Lines changed: 85 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Extract all the visible particles entering the volume."""
22

3-
from typing import Dict, Any, TYPE_CHECKING, Tuple
3+
from typing import Dict, Any, TYPE_CHECKING, Tuple, Union, List
44

55
from .utilities.gcd_hull import GCD_hull
66
from .i3extractor import I3Extractor
@@ -45,6 +45,8 @@ def __init__(
4545
extractor_name: Name of the extractor.
4646
daughters: If True, only consider particles that are
4747
daughters of the primary.
48+
highest_energy_primary: If True, only consider particles that are
49+
daughters of the highest energy primary.
4850
"""
4951
# Member variable(s)
5052
self.hull = hull
@@ -62,12 +64,6 @@ def __call__(self, frame: "icetray.I3Frame") -> Dict[str, Any]:
6264
tree_copy = deepcopy(frame[self.mctree])
6365
if self.frame_contains_info(frame):
6466

65-
e_entrance_track, e_deposited_track = self.total_track_energy(
66-
frame
67-
)
68-
69-
e_deposited_cascade = self.total_cascade_energy(frame)
70-
7167
primary_energy = sum(
7268
[
7369
p.energy
@@ -81,8 +77,32 @@ def __call__(self, frame: "icetray.I3Frame") -> Dict[str, Any]:
8177
)
8278
]
8379
)
80+
81+
e_entrance_track, e_deposited_track = self.total_track_energy(
82+
frame
83+
)
84+
85+
e_deposited_cascade = self.total_cascade_energy(frame)
86+
8487
e_total = e_entrance_track + e_deposited_cascade
8588

89+
if all(
90+
(
91+
not self.daughters,
92+
not self.highest_energy_primary,
93+
e_total == 0,
94+
)
95+
):
96+
self.warning(
97+
"No energy deposited in the hull, "
98+
"Think about increasing the padding."
99+
f"\nCurrent padding: {self.hull.padding}"
100+
f"\nTotal energy: {e_total}"
101+
f"\nTrack energy: {e_entrance_track}"
102+
f"\nCascade energy: {e_deposited_cascade}"
103+
f"\nEvent header: {frame['I3EventHeader']}"
104+
)
105+
86106
if self.daughters:
87107
assert e_total <= (
88108
primary_energy * (1 + 1e-6)
@@ -138,7 +158,9 @@ def total_track_energy(
138158
"""Get the total energy of track particles on entrance."""
139159
e_entrance = 0
140160
e_deposited = 0
141-
primaries = self.get_primaries(frame, self.daughters)
161+
primaries = self.get_primaries(
162+
frame, self.daughters, self.highest_energy_primary
163+
)
142164
primaries = self.check_primary_energy(frame, primaries)
143165

144166
MMCTrackList = frame[self.mmctracklist]
@@ -151,13 +173,18 @@ def total_track_energy(
151173
]
152174
MMCTrackList = simclasses.I3MMCTrackList(MMCTrackList)
153175

154-
track_list = MuonGun.Track.harvest(frame[self.mctree], MMCTrackList)
155-
track_ids = np.array([track.id for track in track_list])
176+
track_list = np.array(
177+
MuonGun.Track.harvest(frame[self.mctree], MMCTrackList)
178+
)
156179

157-
total_tracks = len(track_list)
158-
exclude_ids = set()
159180
while len(track_list) > 0:
160181
track = track_list[0]
182+
track_list = track_list[1:]
183+
try:
184+
particle = frame[self.mctree].get_particle(track.id)
185+
except RuntimeError:
186+
# If the particle does not exist in the mctree, that means a partcle further up was processed and therefore it should not be counted
187+
continue
161188

162189
# Find distance to entrance and exit from sampling volume
163190
intersections = self.hull.surface.intersection(
@@ -167,17 +194,8 @@ def total_track_energy(
167194
# Check if the track actually enters the volume
168195
if not (
169196
np.isfinite(intersections.first)
170-
and (
171-
intersections.first
172-
< frame[self.mctree].get_particle(track.id).length
173-
)
197+
and (intersections.first < particle.length)
174198
):
175-
track_list = track_list[1:]
176-
track_ids = track_ids[1:]
177-
frame[self.mctree].erase(track.id)
178-
self._logger.debug(
179-
f"Remaining tracks: {len(track_list)}/{total_tracks}"
180-
)
181199
continue
182200

183201
# Get the corresponding energies
@@ -187,19 +205,10 @@ def total_track_energy(
187205
# Accumulate
188206
e_deposited += e0 - e1
189207
e_entrance += e0
190-
# erase particle and children
191-
exclude_ids.update(
192-
[c.id for c in frame[self.mctree].children(track.id)]
193-
)
194-
exclude_ids.add(track.id)
195-
frame[self.mctree].erase_children(track.id)
208+
# get descendant ids
209+
# erase particle and children from mctree
196210
frame[self.mctree].erase(track.id)
197-
track_mask = [tid not in exclude_ids for tid in track_ids]
198-
track_list = list(np.array(track_list)[track_mask])
199-
track_ids = track_ids[track_mask]
200-
self._logger.debug(
201-
f"Remaining tracks: {len(track_list)}/{total_tracks}"
202-
)
211+
203212
# Sanity check ensuring no double counting
204213
if self.daughters:
205214
assert e_entrance <= sum(
@@ -215,86 +224,50 @@ def total_cascade_energy(
215224
frame: "icetray.I3Frame",
216225
) -> float:
217226
"""Get the total energy of cascade particles on entrance."""
218-
e_deposited = 0
219-
220-
particles = self.get_primaries(frame, self.daughters)
221-
222-
particles = np.array([p for p in particles if (not p.is_track)])
227+
particles = np.array(
228+
self.get_primaries(
229+
frame, self.daughters, self.highest_energy_primary
230+
)
231+
)
223232

224233
if len(particles) == 0:
225-
return e_deposited
226-
227-
pos, direc, length = np.asarray(
228-
[
229-
[
230-
np.array(p.pos),
231-
np.array([p.dir.x, p.dir.y, p.dir.z]),
232-
p.length,
233-
]
234-
for p in particles
235-
],
236-
dtype=object,
237-
).T
234+
return 0.0
235+
236+
pos_list, direc_list, length_list, cascade_bool, energies = (
237+
[],
238+
[],
239+
[],
240+
[],
241+
[],
242+
)
243+
while len(particles) > 0:
244+
p = particles[0]
245+
particles = particles[1:]
246+
p_children = dataclasses.I3MCTree.get_daughters(
247+
frame[self.mctree], p
248+
)
249+
if len(p_children) > 0:
250+
particles = np.concatenate((particles, p_children))
251+
continue
252+
elif (
253+
p.is_track
254+
or p.shape == dataclasses.I3Particle.ParticleShape.Dark
255+
):
256+
continue
238257

239-
length = length.astype(float)
258+
pos_list.append(np.array(p.pos))
259+
direc_list.append(np.array([p.dir.x, p.dir.y, p.dir.z]))
260+
length_list.append(p.length)
261+
cascade_bool.append(p.is_cascade)
262+
energies.append(p.energy)
240263

241-
# replace length nan with 0
264+
length = np.array(length_list).astype(float)
242265
length[np.isnan(length)] = 0
243-
pos = pos + direc * length
244-
pos = np.stack(pos)
245-
246-
in_volume = self.hull.point_in_hull(pos)
247-
particles = particles[in_volume]
248-
249-
for particle in particles:
250-
if particle.is_cascade:
251-
e_deposited += particle.energy
252-
else:
253-
daughters = dataclasses.I3MCTree.get_daughters(
254-
frame[self.mctree], particle
255-
)
256-
257-
pos, direc, length = np.asarray(
258-
[
259-
[
260-
np.array(p.pos),
261-
np.array([p.dir.x, p.dir.y, p.dir.z]),
262-
p.length,
263-
]
264-
for p in daughters
265-
],
266-
dtype=object,
267-
).T
268-
269-
length = length.astype(float)
270-
271-
# replace length nan with 0
272-
length[np.isnan(length)] = 0
273-
pos = pos + direc * length
274-
pos = np.stack(pos)
275-
276-
in_volume = self.hull.point_in_hull(pos)
277-
daughters = np.array(daughters)[in_volume]
278-
279-
while len(daughters) > 0:
280-
daughter = daughters[0]
281-
daughters = daughters[1:]
282-
length = daughter.length
283-
if daughter.is_track:
284-
continue
285-
if length == np.nan:
286-
length = 0
287-
if daughter.is_cascade and (
288-
daughter.shape != dataclasses.I3Particle.ParticleShape.Dark
289-
):
290-
e_deposited += daughter.energy
291-
else:
292-
daughters = np.concatenate(
293-
[
294-
daughters,
295-
dataclasses.I3MCTree.get_daughters(
296-
frame[self.mctree], daughter
297-
),
298-
]
299-
)
300-
return e_deposited
266+
pos = np.array(pos_list)
267+
direc = np.array(direc_list)
268+
cascade_bool = np.array(cascade_bool)
269+
energies = np.array(energies)
270+
pos = (pos.T + direc.T * length).T
271+
in_hull = self.hull.point_in_hull(pos)
272+
273+
return np.sum(energies[cascade_bool & in_hull])

0 commit comments

Comments
 (0)