@@ -279,6 +279,14 @@ def from_particles(cls, particles):
279279@inherit_docstring (RecoBase , InteractionBase )
280280class RecoInteraction (InteractionBase , RecoBase ):
281281 """Reconstructed interaction information."""
282+
283+ leading_shower_vertex_distance : float = - 1.
284+ leading_shower_axial_spread : float = None
285+ leading_shower_directional_spread : float = None
286+ leading_shower_start_dedx : float = None
287+ leading_shower_trunk_straightness : float = None
288+ leading_shower_adjacent_bragg_pearsonr : float = None
289+ leading_shower_split_angle : float = None
282290
283291 # Attributes that must never be stored to file
284292 _skip_attrs = (
@@ -307,7 +315,145 @@ def __str__(self):
307315 Basic information about the interaction properties
308316 """
309317 return 'Reco' + super ().__str__ ()
318+
319+
320+ @property
321+ def leading_shower (self ):
322+ """Leading shower of this interaction
310323
324+ Returns
325+ -------
326+ RecoParticle
327+ Primary shower with the highest reco kinetic energy.
328+ """
329+ showers = [part for part in self .primary_particles if part .shape == 0 ]
330+ if len (showers ) == 0 :
331+ return None
332+ return max (showers , key = lambda x : x .ke )
333+
334+ @leading_shower .setter
335+ def leading_shower (self , leading_shower ):
336+ pass
337+
338+ @property
339+ def leading_shower_start_dedx (self ):
340+ """Leading shower dE/dx
341+
342+ Returns
343+ -------
344+ float
345+ dE/dx of the leading shower
346+ """
347+ leading_shower = self .leading_shower
348+ if leading_shower is None :
349+ return - 1.
350+ return leading_shower .start_dedx
351+
352+ @leading_shower_start_dedx .setter
353+ def leading_shower_start_dedx (self , leading_shower_start_dedx ):
354+ pass
355+
356+ @property
357+ def leading_shower_directional_spread (self ):
358+ """Distance-weighted mean cosine distance from mean direction
359+ of the leading shower.
360+
361+ See ShowerSpreadProcessor under post/reco/shower.py for more details.
362+
363+ Returns
364+ -------
365+ float
366+ Measure of shower directional spread
367+ """
368+ leading_shower = self .leading_shower
369+ if leading_shower is None :
370+ return - 1.
371+ return leading_shower .directional_spread
372+
373+ @leading_shower_directional_spread .setter
374+ def leading_shower_directional_spread (self , leading_shower_directional_spread ):
375+ pass
376+
377+ @property
378+ def leading_shower_axial_spread (self ):
379+ """Pearson R correlation coefficient between the distance from
380+ shower start to a shower point (x) and the perpendicular distance
381+ from the shower point to the shower axis.
382+
383+ Returns
384+ -------
385+ coeff
386+ Measure of shower axial spread
387+ """
388+ leading_shower = self .leading_shower
389+ if leading_shower is None :
390+ return - np .inf
391+ return leading_shower .axial_spread
392+
393+ @leading_shower_axial_spread .setter
394+ def leading_shower_axial_spread (self , leading_shower_axial_spread ):
395+ pass
396+
397+ @property
398+ def leading_shower_trunk_straightness (self ):
399+ """Measure of how straight the trunk of the leading shower is.
400+
401+ Returns
402+ -------
403+ float
404+ Measure of shower trunk straightness (between 0 and 1)
405+ """
406+ leading_shower = self .leading_shower
407+ if leading_shower is None :
408+ return - 1.
409+ return leading_shower .trunk_straightness
410+
411+ @leading_shower_trunk_straightness .setter
412+ def leading_shower_trunk_straightness (self , leading_shower_trunk_straightness ):
413+ pass
414+
415+ @property
416+ def leading_shower_adjacent_bragg_pearsonr (self ):
417+ """Pearson R correlation coefficient between:
418+ x: distance from shower start to a point on a track adjacent to the
419+ shower.
420+ y: the local dedx value at that point.
421+
422+ If this value is strongly negative (close to -1), it suggests that
423+ the shower is likely to be adjacent to a bragg peak.
424+
425+ Returns
426+ -------
427+ float
428+ Measure of how likely the leading shower is adjacent
429+ to a bragg peak (between -1 and 1)
430+ """
431+ leading_shower = self .leading_shower
432+ if leading_shower is None :
433+ return - np .inf
434+ return leading_shower .adjacent_bragg_pearsonr
435+
436+ @leading_shower_adjacent_bragg_pearsonr .setter
437+ def leading_shower_adjacent_bragg_pearsonr (self , leading_shower_adjacent_bragg_pearsonr ):
438+ pass
439+
440+ @property
441+ def leading_shower_split_angle (self ):
442+ """Angle between the two branches of the leading shower.
443+
444+ Returns
445+ -------
446+ float
447+ Angle between the two branches of the leading shower
448+ """
449+ leading_shower = self .leading_shower
450+ if leading_shower is None :
451+ return - 1.
452+ return leading_shower .split_angle
453+
454+ @leading_shower_split_angle .setter
455+ def leading_shower_split_angle (self , leading_shower_split_angle ):
456+ pass
311457
312458@dataclass (eq = False )
313459@inherit_docstring (TruthBase , InteractionBase )
0 commit comments