LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
lar_content::ShowerStartFinderTool Class Reference

#include "ShowerStartFinderTool.h"

Inheritance diagram for lar_content::ShowerStartFinderTool:

Public Member Functions

 ShowerStartFinderTool ()
 Default constructor. More...
 
pandora::StatusCode Run (const pandora::ParticleFlowObject *const pShowerPfo, const pandora::CartesianVector &peakDirection, const pandora::HitType hitType, const pandora::CaloHitList &showerSpineHitList, pandora::CartesianVector &showerStartPosition, pandora::CartesianVector &showerStartDirection)
 
template<typename T >
int FindShowerStartLongitudinalCoordinate (const ParticleFlowObject *const pShowerPfo, const HitType hitType, const TwoDSlidingFitResult &spineTwoDSlidingFit, const EnergySpectrumMap &energySpectrumMap, const CaloHitList &showerSpineHitList, const bool isEndDownstream, const T startIter, const T endIter) const
 

Private Types

typedef std::map< const pandora::CaloHit *, float > LongitudinalPositionMap
 
typedef std::map< int, float > EnergySpectrumMap
 
typedef std::map< int, pandora::CaloHitList > LayerToHitMap
 

Private Member Functions

pandora::StatusCode ReadSettings (const pandora::TiXmlHandle xmlHandle)
 
void ObtainLongitudinalDecomposition (const TwoDSlidingFitResult &spineTwoDSlidingFit, const pandora::CaloHitList &showerSpineHitList, LongitudinalPositionMap &longitudinalPositionMap) const
 Create the [shower spine hit -> shower spine fit longitudinal projection] map. More...
 
void GetEnergyDistribution (const pandora::CaloHitList &showerSpineHitList, const LongitudinalPositionMap &longitudinalPositionMap, EnergySpectrumMap &energySpectrumMap) const
 Create the longituidnal energy distribution. More...
 
void FindShowerStartAndDirection (const pandora::ParticleFlowObject *const pShowerPfo, const pandora::HitType hitType, const TwoDSlidingFitResult &spineTwoDSlidingFit, const EnergySpectrumMap &energySpectrumMap, const pandora::CaloHitList &showerSpineHitList, const bool isEndDownstream, pandora::CartesianVector &showerStartPosition, pandora::CartesianVector &showerStartDirection) const
 Find the position at which the shower cascade looks to originate, and its initial direction. More...
 
template<typename T >
int FindShowerStartLongitudinalCoordinate (const pandora::ParticleFlowObject *const pShowerPfo, const pandora::HitType hitType, const TwoDSlidingFitResult &spineTwoDSlidingFit, const EnergySpectrumMap &energySpectrumMap, const pandora::CaloHitList &showerSpineHitList, const bool isEndDownstream, const T startIter, const T endIter) const
 Find the longitudinal bin which corresponds to the start position of the shower cascade. More...
 
void CharacteriseInitialEnergy (const EnergySpectrumMap &energySpectrumMap, const bool isEndDownstream, float &meanEnergy, float &energySigma) const
 Find the mean and standard deviation of the energy depositions in the initial region. More...
 
bool IsShowerTopology (const pandora::ParticleFlowObject *const pShowerPfo, const pandora::HitType hitType, const TwoDSlidingFitResult &spineTwoDSlidingFit, const float longitudinalDistance, const pandora::CaloHitList &showerSpineHitList, const bool isEndDownstream) const
 Whether a sensible shower cascade looks to originate at a given position. More...
 
void ConvertLongitudinalProjectionToGlobal (const TwoDSlidingFitResult &spineTwoDSlidingFit, const float longitudinalDistance, pandora::CartesianVector &globalPosition, pandora::CartesianVector &globalDirection) const
 Determine the (X,Y,Z) position and direction at a given longitudinal distance along the spine. More...
 
pandora::StatusCode BuildShowerRegion (const pandora::ParticleFlowObject *const pShowerPfo, const pandora::HitType hitType, const pandora::CaloHitList &showerSpineHitList, const pandora::CartesianVector &showerStartPosition, const pandora::CartesianVector &showerStartDirection, const bool isEndDownstream, pandora::CartesianPointVector &showerRegionPositionVector) const
 Build the downstream 'shower region' at a given longitudinal distance along the spine. More...
 
pandora::StatusCode CharacteriseShowerTopology (const pandora::CartesianPointVector &showerRegionPositionVector, const pandora::CartesianVector &showerStartPosition, const pandora::HitType hitType, const bool isEndDownstream, const pandora::CartesianVector &showerStartDirection, pandora::CartesianVector &positiveEdgeStart, pandora::CartesianVector &positiveEdgeEnd, pandora::CartesianVector &negativeEdgeStart, pandora::CartesianVector &negativeEdgeEnd, bool &isBetween) const
 Parameterise the topological structure of the shower region. More...
 
bool IsClockwiseRotation (const pandora::CartesianVector &showerStartDirection, const pandora::CartesianVector &displacementVector) const
 Determine whether a point lies on the RHS or LHS (wrt +ve Z) of the shower core. More...
 
pandora::StatusCode GetBoundaryExtremalPoints (const TwoDSlidingShowerFitResult &showerTwoDSlidingFit, const LayerFitResultMap &layerFitResultMap, const pandora::CartesianVector &showerStartPosition, const int showerStartLayer, const int showerEndLayer, pandora::CartesianVector &boundaryEdgeStart, pandora::CartesianVector &boundaryEdgeEnd) const
 Determine the start and end positions of a shower boundary. More...
 

Private Attributes

unsigned int m_spineSlidingFitWindow
 The sliding window used to fit the shower spine. More...
 
float m_longitudinalCoordinateBinSize
 The longitudinal coordinate bin size. More...
 
unsigned int m_nInitialEnergyBins
 The number of longitudinal bins that define the initial region. More...
 
float m_minSigmaDeviation
 The min. average energy deviation of a candidate shower start. More...
 
float m_maxEdgeGap
 The max. allowed layer gap in a shower boundary. More...
 
float m_longitudinalShowerFraction
 The shower region fraction considered. More...
 
float m_minShowerOpeningAngle
 The min. opening angle of a sensible shower. More...
 
float m_molliereRadius
 The max. distance from the shower core of a collected shower region hit. More...
 
unsigned int m_showerSlidingFitWindow
 The sliding window used to fit the shower region. More...
 
int m_maxLayerSeparation
 The max. allowed separation between the shower start and boundary start layers. More...
 

Detailed Description

Definition at line 20 of file ShowerStartFinderTool.h.

Member Typedef Documentation

typedef std::map<int, float> lar_content::ShowerStartFinderTool::EnergySpectrumMap
private

Definition at line 34 of file ShowerStartFinderTool.h.

typedef std::map<int, pandora::CaloHitList> lar_content::ShowerStartFinderTool::LayerToHitMap
private

Definition at line 35 of file ShowerStartFinderTool.h.

typedef std::map<const pandora::CaloHit *, float> lar_content::ShowerStartFinderTool::LongitudinalPositionMap
private

Definition at line 33 of file ShowerStartFinderTool.h.

Constructor & Destructor Documentation

lar_content::ShowerStartFinderTool::ShowerStartFinderTool ( )

Default constructor.

Definition at line 26 of file ShowerStartFinderTool.cc.

26  :
31  m_maxEdgeGap(3.f),
34  m_molliereRadius(4.5f),
37 {
38 }
float m_longitudinalShowerFraction
The shower region fraction considered.
float m_minShowerOpeningAngle
The min. opening angle of a sensible shower.
float m_longitudinalCoordinateBinSize
The longitudinal coordinate bin size.
int m_maxLayerSeparation
The max. allowed separation between the shower start and boundary start layers.
unsigned int m_showerSlidingFitWindow
The sliding window used to fit the shower region.
TFile f
Definition: plotHisto.C:6
unsigned int m_nInitialEnergyBins
The number of longitudinal bins that define the initial region.
float m_maxEdgeGap
The max. allowed layer gap in a shower boundary.
float m_molliereRadius
The max. distance from the shower core of a collected shower region hit.
float m_minSigmaDeviation
The min. average energy deviation of a candidate shower start.
unsigned int m_spineSlidingFitWindow
The sliding window used to fit the shower spine.

Member Function Documentation

StatusCode lar_content::ShowerStartFinderTool::BuildShowerRegion ( const pandora::ParticleFlowObject *const  pShowerPfo,
const pandora::HitType  hitType,
const pandora::CaloHitList &  showerSpineHitList,
const pandora::CartesianVector &  showerStartPosition,
const pandora::CartesianVector &  showerStartDirection,
const bool  isEndDownstream,
pandora::CartesianPointVector &  showerRegionPositionVector 
) const
private

Build the downstream 'shower region' at a given longitudinal distance along the spine.

Parameters
pShowerPfothe shower pfo
hitTypethe 2D view
showerSpineHitListthe shower spine hit list
showerStartPositionthe candidate shower start position
showerStartDirectionthe candidate shower start direction
isEndDownstreamwhether the shower direction is downstream (in Z) of the neutrino vertex
showerRegionPositionVectorthe ouput vector of shower region hit positions
Returns
whether the 'shower region finder' mechanics could proceed

Definition at line 347 of file ShowerStartFinderTool.cc.

References f, lar_content::LArPfoHelper::GetCaloHits(), lar_content::TwoDSlidingFitResult::GetGlobalPosition(), lar_content::TwoDSlidingFitResult::GetLayer(), lar_content::TwoDSlidingFitResult::GetLayerFitResultMap(), lar_content::TwoDSlidingFitResult::GetLocalPosition(), lar_content::TwoDSlidingShowerFitResult::GetNegativeEdgeFitResult(), lar_content::TwoDSlidingShowerFitResult::GetPositiveEdgeFitResult(), lar_content::TwoDSlidingShowerFitResult::GetShowerFitResult(), lar_content::LArGeometryHelper::GetWirePitch(), m_longitudinalShowerFraction, m_maxEdgeGap, m_molliereRadius, and m_showerSlidingFitWindow.

Referenced by IsShowerTopology().

350 {
351  CaloHitList viewShowerHitList;
352  LArPfoHelper::GetCaloHits(pShowerPfo, hitType, viewShowerHitList);
353 
354  // Find shower region hits
355  CaloHitList showerRegionHitList;
356 
357  for (const CaloHit *const pCaloHit : viewShowerHitList)
358  {
359  if (std::find(showerSpineHitList.begin(), showerSpineHitList.end(), pCaloHit) != showerSpineHitList.end())
360  continue;
361 
362  const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
363  float l(showerStartDirection.GetDotProduct(hitPosition - showerStartPosition));
364 
365  l *= isEndDownstream ? 1.f : -1.f;
366 
367  if (l < 0.f)
368  continue;
369 
370  if (showerStartDirection.GetCrossProduct(hitPosition - showerStartPosition).GetMagnitude() > m_molliereRadius)
371  continue;
372 
373  showerRegionPositionVector.push_back(pCaloHit->GetPositionVector());
374  showerRegionHitList.push_back(pCaloHit);
375  }
376 
377  // Searching for a continuous shower, so truncate at first gap
378  CartesianPointVector coordinateListP, coordinateListN;
379  try
380  {
381  // Perform shower sliding fit
382  const TwoDSlidingShowerFitResult twoDShowerSlidingFit(
383  &showerRegionPositionVector, m_showerSlidingFitWindow, LArGeometryHelper::GetWirePitch(this->GetPandora(), hitType));
384  const LayerFitResultMap &layerFitResultMapS(twoDShowerSlidingFit.GetShowerFitResult().GetLayerFitResultMap());
385  const LayerFitResultMap &layerFitResultMapP(twoDShowerSlidingFit.GetPositiveEdgeFitResult().GetLayerFitResultMap());
386  const LayerFitResultMap &layerFitResultMapN(twoDShowerSlidingFit.GetNegativeEdgeFitResult().GetLayerFitResultMap());
387 
388  float showerStartL(0.f), showerStartT(0.f);
389  twoDShowerSlidingFit.GetShowerFitResult().GetLocalPosition(showerStartPosition, showerStartL, showerStartT);
390 
391  const int startLayer(twoDShowerSlidingFit.GetShowerFitResult().GetLayer(showerStartL));
392 
393  // Check for gaps in the shower
394  for (LayerFitResultMap::const_iterator iterS = layerFitResultMapS.begin(); iterS != layerFitResultMapS.end(); ++iterS)
395  {
396  const int layer(iterS->first);
397 
398  if (isEndDownstream && (layer < startLayer))
399  continue;
400 
401  if (!isEndDownstream && (layer > startLayer))
402  continue;
403 
404  LayerFitResultMap::const_iterator iterP = layerFitResultMapP.find(layer);
405  LayerFitResultMap::const_iterator iterN = layerFitResultMapN.find(layer);
406 
407  if (layerFitResultMapP.end() != iterP)
408  {
409  CartesianVector positiveEdgePosition(0.f, 0.f, 0.f);
410  twoDShowerSlidingFit.GetShowerFitResult().GetGlobalPosition(iterP->second.GetL(), iterP->second.GetFitT(), positiveEdgePosition);
411  coordinateListP.push_back(positiveEdgePosition);
412  }
413 
414  if (layerFitResultMapN.end() != iterN)
415  {
416  CartesianVector negativeEdgePosition(0.f, 0.f, 0.f);
417  twoDShowerSlidingFit.GetShowerFitResult().GetGlobalPosition(iterN->second.GetL(), iterN->second.GetFitT(), negativeEdgePosition);
418  coordinateListN.push_back(negativeEdgePosition);
419  }
420  }
421 
422  if ((coordinateListP.size() == 0) || (coordinateListN.size() == 0))
423  return STATUS_CODE_FAILURE;
424 
425  std::sort(coordinateListP.begin(), coordinateListP.end(), LArConnectionPathwayHelper::SortByDistanceToPoint(showerStartPosition));
426  std::sort(coordinateListN.begin(), coordinateListN.end(), LArConnectionPathwayHelper::SortByDistanceToPoint(showerStartPosition));
427 
428  float pMaximumL(std::numeric_limits<float>::max());
429  CartesianVector previousCoordinateP(coordinateListP.front());
430 
431  for (auto iterP = std::next(coordinateListP.begin()); iterP != coordinateListP.end(); ++iterP)
432  {
433  const CartesianVector &coordinateP(*iterP);
434  const float separationSquared((coordinateP - previousCoordinateP).GetMagnitudeSquared());
435 
436  if (separationSquared > (m_maxEdgeGap * m_maxEdgeGap))
437  break;
438 
439  float thisT(0.f);
440  twoDShowerSlidingFit.GetShowerFitResult().GetLocalPosition(coordinateP, pMaximumL, thisT);
441 
442  previousCoordinateP = coordinateP;
443  }
444 
445  float nMaximumL(std::numeric_limits<float>::max());
446  CartesianVector previousCoordinateN(coordinateListN.front());
447 
448  for (auto iterN = std::next(coordinateListN.begin()); iterN != coordinateListN.end(); ++iterN)
449  {
450  const CartesianVector &coordinateN(*iterN);
451  const float separationSquared((coordinateN - previousCoordinateN).GetMagnitudeSquared());
452 
453  if (separationSquared > (m_maxEdgeGap * m_maxEdgeGap))
454  break;
455 
456  float thisT(0.f);
457  twoDShowerSlidingFit.GetShowerFitResult().GetLocalPosition(coordinateN, nMaximumL, thisT);
458 
459  previousCoordinateN = coordinateN;
460  }
461 
462  // Now truncate the halo hit position vector
463  showerRegionPositionVector.clear();
464 
465  for (const CaloHit *const pCaloHit : showerRegionHitList)
466  {
467  float thisL(0.f), thisT(0.f);
468  const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
469 
470  twoDShowerSlidingFit.GetShowerFitResult().GetLocalPosition(hitPosition, thisL, thisT);
471 
472  // because the end of showers can get really narrow and thus fail the opening angle check
473  if (isEndDownstream && (thisL > (m_longitudinalShowerFraction * std::max(pMaximumL, nMaximumL))))
474  continue;
475 
476  if (!isEndDownstream && (thisL < (m_longitudinalShowerFraction * std::min(pMaximumL, nMaximumL))))
477  continue;
478 
479  showerRegionPositionVector.push_back(pCaloHit->GetPositionVector());
480  }
481  }
482  catch (const StatusCodeException &)
483  {
484  return STATUS_CODE_FAILURE;
485  }
486 
487  return STATUS_CODE_SUCCESS;
488 }
float m_longitudinalShowerFraction
The shower region fraction considered.
unsigned int m_showerSlidingFitWindow
The sliding window used to fit the shower region.
intermediate_table::const_iterator const_iterator
TFile f
Definition: plotHisto.C:6
float m_maxEdgeGap
The max. allowed layer gap in a shower boundary.
float m_molliereRadius
The max. distance from the shower core of a collected shower region hit.
std::map< int, LayerFitResult > LayerFitResultMap
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static void GetCaloHits(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::CaloHitList &caloHitList)
Get a list of calo hits of a particular hit type from a list of pfos.
void lar_content::ShowerStartFinderTool::CharacteriseInitialEnergy ( const EnergySpectrumMap energySpectrumMap,
const bool  isEndDownstream,
float &  meanEnergy,
float &  energySigma 
) const
private

Find the mean and standard deviation of the energy depositions in the initial region.

Parameters
energySpectrumMapthe [longitudial projection bin -> contained energy] map
isEndDownstreamwhether the shower direction is downstream (in Z) of the neutrino vertex
meanEnergythe output mean energy
energySigmathe output standard deviation

Definition at line 243 of file ShowerStartFinderTool.cc.

References m_nInitialEnergyBins.

Referenced by FindShowerStartLongitudinalCoordinate().

245 {
246  auto energySpectrumIter(isEndDownstream ? energySpectrumMap.begin() : std::prev(energySpectrumMap.end()));
247 
248  for (unsigned int i = 0; i < m_nInitialEnergyBins; ++i)
249  {
250  meanEnergy += energySpectrumIter->second;
251  isEndDownstream ? ++energySpectrumIter : --energySpectrumIter;
252  }
253 
254  meanEnergy /= static_cast<float>(m_nInitialEnergyBins);
255 
256  energySpectrumIter = isEndDownstream ? energySpectrumMap.begin() : std::prev(energySpectrumMap.end());
257 
258  for (unsigned int i = 0; i < m_nInitialEnergyBins; ++i)
259  {
260  energySigma += std::pow(energySpectrumIter->second - meanEnergy, 2);
261  isEndDownstream ? ++energySpectrumIter : --energySpectrumIter;
262  }
263 
264  energySigma = std::sqrt(energySigma / m_nInitialEnergyBins);
265 }
unsigned int m_nInitialEnergyBins
The number of longitudinal bins that define the initial region.
StatusCode lar_content::ShowerStartFinderTool::CharacteriseShowerTopology ( const pandora::CartesianPointVector &  showerRegionPositionVector,
const pandora::CartesianVector &  showerStartPosition,
const pandora::HitType  hitType,
const bool  isEndDownstream,
const pandora::CartesianVector &  showerStartDirection,
pandora::CartesianVector &  positiveEdgeStart,
pandora::CartesianVector &  positiveEdgeEnd,
pandora::CartesianVector &  negativeEdgeStart,
pandora::CartesianVector &  negativeEdgeEnd,
bool &  isBetween 
) const
private

Parameterise the topological structure of the shower region.

Parameters
showerRegionPositionVectorthe vector of shower region hit positions
showerStartPositionthe shower start position
hitTypethe 2D view
isEndDownstreamwhether the shower direction is downstream (in Z) of the neutrino vertex
showerStartDirectionthe shower start direction
positiveEdgeStartthe start position of one shower boundary
positiveEdgeEndthe end position of one shower boundary
negativeEdgeStartthe start position of the other shower boundary
negativeEdgeEndthe end position of the other shower boundary
isBetweenif the shower core is between either the start or end boundary positions
Returns
whether the 'shower characterisation' mechanics could proceed

Definition at line 492 of file ShowerStartFinderTool.cc.

References f, GetBoundaryExtremalPoints(), lar_content::TwoDSlidingFitResult::GetGlobalPosition(), lar_content::TwoDSlidingFitResult::GetLayer(), lar_content::TwoDSlidingFitResult::GetLayerFitResultMap(), lar_content::TwoDSlidingFitResult::GetLocalPosition(), lar_content::TwoDSlidingFitResult::GetMaxLayer(), lar_content::TwoDSlidingShowerFitResult::GetNegativeEdgeFitResult(), lar_content::TwoDSlidingShowerFitResult::GetPositiveEdgeFitResult(), lar_content::TwoDSlidingShowerFitResult::GetShowerFitResult(), lar_content::LArGeometryHelper::GetWirePitch(), IsClockwiseRotation(), and m_showerSlidingFitWindow.

Referenced by IsShowerTopology().

495 {
496  try
497  {
498  // Perform shower sliding fit
499  const TwoDSlidingShowerFitResult twoDShowerSlidingFit(
500  &showerRegionPositionVector, m_showerSlidingFitWindow, LArGeometryHelper::GetWirePitch(this->GetPandora(), hitType));
501  const LayerFitResultMap &layerFitResultMapS(twoDShowerSlidingFit.GetShowerFitResult().GetLayerFitResultMap());
502  const LayerFitResultMap &layerFitResultMapP(twoDShowerSlidingFit.GetPositiveEdgeFitResult().GetLayerFitResultMap());
503  const LayerFitResultMap &layerFitResultMapN(twoDShowerSlidingFit.GetNegativeEdgeFitResult().GetLayerFitResultMap());
504 
505  float showerStartL(0.f), showerStartT(0.f);
506  twoDShowerSlidingFit.GetShowerFitResult().GetLocalPosition(showerStartPosition, showerStartL, showerStartT);
507 
508  const int startLayer(twoDShowerSlidingFit.GetShowerFitResult().GetLayer(showerStartL));
509  const int endLayer(twoDShowerSlidingFit.GetShowerFitResult().GetMaxLayer());
510 
511  // Does the shower look to originate from the shower start position
512  int layerCount(0);
513  bool isFirstBetween(false), isLastBetween(false);
514  CartesianPointVector coordinateListP, coordinateListN;
515 
516  for (LayerFitResultMap::const_iterator iterS = layerFitResultMapS.begin(); iterS != layerFitResultMapS.end(); ++iterS)
517  {
518  int layer(iterS->first);
519 
520  if (isEndDownstream && (layer < startLayer))
521  continue;
522 
523  if (!isEndDownstream && (layer > startLayer))
524  continue;
525 
526  LayerFitResultMap::const_iterator iterP = layerFitResultMapP.find(layer);
527  LayerFitResultMap::const_iterator iterN = layerFitResultMapN.find(layer);
528 
529  CartesianVector positiveEdgePosition(0.f, 0.f, 0.f), negativeEdgePosition(0.f, 0.f, 0.f);
530  if (layerFitResultMapP.end() != iterP)
531  {
532  twoDShowerSlidingFit.GetShowerFitResult().GetGlobalPosition(iterP->second.GetL(), iterP->second.GetFitT(), positiveEdgePosition);
533  coordinateListP.push_back(positiveEdgePosition);
534  }
535 
536  if (layerFitResultMapN.end() != iterN)
537  {
538  twoDShowerSlidingFit.GetShowerFitResult().GetGlobalPosition(iterN->second.GetL(), iterN->second.GetFitT(), negativeEdgePosition);
539  coordinateListN.push_back(negativeEdgePosition);
540  }
541 
542  if ((layerFitResultMapP.end() != iterP) && (layerFitResultMapN.end() != iterN))
543  {
544  const CartesianVector positiveDisplacement((positiveEdgePosition - showerStartPosition).GetUnitVector());
545  const bool isPositiveClockwise(this->IsClockwiseRotation(showerStartDirection, positiveDisplacement));
546 
547  const CartesianVector negativeDisplacement((negativeEdgePosition - showerStartPosition).GetUnitVector());
548  const bool isNegativeClockwise(this->IsClockwiseRotation(showerStartDirection, negativeDisplacement));
549 
550  ++layerCount;
551 
552  if (layerCount == 1)
553  isFirstBetween = (isPositiveClockwise != isNegativeClockwise);
554 
555  isLastBetween = (isPositiveClockwise != isNegativeClockwise);
556  }
557  }
558 
559  isBetween = (isFirstBetween || isLastBetween);
560 
561  // Find the extremal points of the shower
562  if (this->GetBoundaryExtremalPoints(twoDShowerSlidingFit, layerFitResultMapP, showerStartPosition, startLayer, endLayer,
563  positiveEdgeStart, positiveEdgeEnd) != STATUS_CODE_SUCCESS)
564  {
565  return STATUS_CODE_FAILURE;
566  }
567 
568  if (this->GetBoundaryExtremalPoints(twoDShowerSlidingFit, layerFitResultMapN, showerStartPosition, startLayer, endLayer,
569  negativeEdgeStart, negativeEdgeEnd) != STATUS_CODE_SUCCESS)
570  {
571  return STATUS_CODE_FAILURE;
572  }
573  }
574  catch (const StatusCodeException &)
575  {
576  return STATUS_CODE_FAILURE;
577  }
578 
579  return STATUS_CODE_SUCCESS;
580 }
unsigned int m_showerSlidingFitWindow
The sliding window used to fit the shower region.
intermediate_table::const_iterator const_iterator
TFile f
Definition: plotHisto.C:6
std::map< int, LayerFitResult > LayerFitResultMap
pandora::StatusCode GetBoundaryExtremalPoints(const TwoDSlidingShowerFitResult &showerTwoDSlidingFit, const LayerFitResultMap &layerFitResultMap, const pandora::CartesianVector &showerStartPosition, const int showerStartLayer, const int showerEndLayer, pandora::CartesianVector &boundaryEdgeStart, pandora::CartesianVector &boundaryEdgeEnd) const
Determine the start and end positions of a shower boundary.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
bool IsClockwiseRotation(const pandora::CartesianVector &showerStartDirection, const pandora::CartesianVector &displacementVector) const
Determine whether a point lies on the RHS or LHS (wrt +ve Z) of the shower core.
void lar_content::ShowerStartFinderTool::ConvertLongitudinalProjectionToGlobal ( const TwoDSlidingFitResult spineTwoDSlidingFit,
const float  longitudinalDistance,
pandora::CartesianVector &  globalPosition,
pandora::CartesianVector &  globalDirection 
) const
private

Determine the (X,Y,Z) position and direction at a given longitudinal distance along the spine.

Parameters
spineTwoDSlidingFitthe shower spine fit
longitudinalDistancethe input longitudinal distance
globalPositionthe output (X,Y,Z) position
globalDirectionthe output (X,Y,Z) direction

Definition at line 312 of file ShowerStartFinderTool.cc.

References f, lar_content::TwoDSlidingFitResult::GetGlobalDirection(), lar_content::TwoDSlidingFitResult::GetGlobalPosition(), and lar_content::TwoDSlidingFitResult::GetLayerFitResultMap().

Referenced by FindShowerStartAndDirection(), and IsShowerTopology().

314 {
315  const LayerFitResultMap &layerFitResultMap(spineTwoDSlidingFit.GetLayerFitResultMap());
316 
317  float runningDistance(0.f);
318  int showerStartLayer(0);
319  CartesianVector previousLayerPosition(0.f, 0.f, 0.f);
320  spineTwoDSlidingFit.GetGlobalPosition(layerFitResultMap.begin()->second.GetL(), layerFitResultMap.begin()->second.GetFitT(), previousLayerPosition);
321 
322  for (auto iter = std::next(layerFitResultMap.begin()); iter != layerFitResultMap.end(); ++iter)
323  {
324  const int layer(iter->first);
325  showerStartLayer = layer;
326 
327  CartesianVector layerPosition(0.f, 0.f, 0.f);
328  spineTwoDSlidingFit.GetGlobalPosition(layerFitResultMap.at(layer).GetL(), layerFitResultMap.at(layer).GetFitT(), layerPosition);
329 
330  runningDistance += (layerPosition - previousLayerPosition).GetMagnitude();
331 
332  if (runningDistance > longitudinalDistance)
333  break;
334 
335  previousLayerPosition = layerPosition;
336  }
337 
338  const float lCoordinate(layerFitResultMap.at(showerStartLayer).GetL()), tCoordinate(layerFitResultMap.at(showerStartLayer).GetFitT());
339  const float localGradient(layerFitResultMap.at(showerStartLayer).GetGradient());
340 
341  spineTwoDSlidingFit.GetGlobalPosition(lCoordinate, tCoordinate, globalPosition);
342  spineTwoDSlidingFit.GetGlobalDirection(localGradient, globalDirection);
343 }
TFile f
Definition: plotHisto.C:6
std::map< int, LayerFitResult > LayerFitResultMap
void lar_content::ShowerStartFinderTool::FindShowerStartAndDirection ( const pandora::ParticleFlowObject *const  pShowerPfo,
const pandora::HitType  hitType,
const TwoDSlidingFitResult spineTwoDSlidingFit,
const EnergySpectrumMap energySpectrumMap,
const pandora::CaloHitList &  showerSpineHitList,
const bool  isEndDownstream,
pandora::CartesianVector &  showerStartPosition,
pandora::CartesianVector &  showerStartDirection 
) const
private

Find the position at which the shower cascade looks to originate, and its initial direction.

Parameters
pShowerPfothe shower pfo
hitTypethe 2D view
spineTwoDSlidingFitthe shower spine fit
energySpectrumMapthe [longitudial projection bin -> contained energy] map
showerSpineHitListthe shower spine hit list
isEndDownstreamwhether the shower direction is downstream (in Z) of the neutrino vertex
showerStartPositionthe position at which the shower cascade looks to originate
showerStartDirectionthe initial direction of the shower cascade

Definition at line 182 of file ShowerStartFinderTool.cc.

References ConvertLongitudinalProjectionToGlobal(), FindShowerStartLongitudinalCoordinate(), and m_longitudinalCoordinateBinSize.

Referenced by Run().

185 {
186  // Search for shower start at significant energy deviations
187  int longitudinalStartBin(0);
188 
189  if (isEndDownstream)
190  {
191  longitudinalStartBin = this->FindShowerStartLongitudinalCoordinate(pShowerPfo, hitType, spineTwoDSlidingFit, energySpectrumMap,
192  showerSpineHitList, isEndDownstream, energySpectrumMap.begin(), std::prev(energySpectrumMap.end()));
193  }
194  else
195  {
196  longitudinalStartBin = this->FindShowerStartLongitudinalCoordinate(pShowerPfo, hitType, spineTwoDSlidingFit, energySpectrumMap,
197  showerSpineHitList, isEndDownstream, energySpectrumMap.rbegin(), std::prev(energySpectrumMap.rend()));
198  }
199 
200  const float longitudinalStartCoordinate(longitudinalStartBin * m_longitudinalCoordinateBinSize);
201 
202  this->ConvertLongitudinalProjectionToGlobal(spineTwoDSlidingFit, longitudinalStartCoordinate, showerStartPosition, showerStartDirection);
203 
204  showerStartDirection = isEndDownstream ? showerStartDirection : showerStartDirection * (-1.f);
205 }
float m_longitudinalCoordinateBinSize
The longitudinal coordinate bin size.
void ConvertLongitudinalProjectionToGlobal(const TwoDSlidingFitResult &spineTwoDSlidingFit, const float longitudinalDistance, pandora::CartesianVector &globalPosition, pandora::CartesianVector &globalDirection) const
Determine the (X,Y,Z) position and direction at a given longitudinal distance along the spine...
int FindShowerStartLongitudinalCoordinate(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::HitType hitType, const TwoDSlidingFitResult &spineTwoDSlidingFit, const EnergySpectrumMap &energySpectrumMap, const pandora::CaloHitList &showerSpineHitList, const bool isEndDownstream, const T startIter, const T endIter) const
Find the longitudinal bin which corresponds to the start position of the shower cascade.
template<typename T >
int lar_content::ShowerStartFinderTool::FindShowerStartLongitudinalCoordinate ( const pandora::ParticleFlowObject *const  pShowerPfo,
const pandora::HitType  hitType,
const TwoDSlidingFitResult spineTwoDSlidingFit,
const EnergySpectrumMap energySpectrumMap,
const pandora::CaloHitList &  showerSpineHitList,
const bool  isEndDownstream,
const T  startIter,
const T  endIter 
) const
private

Find the longitudinal bin which corresponds to the start position of the shower cascade.

Parameters
pShowerPfothe shower pfo
hitTypethe 2D view
spineTwoDSlidingFitthe shower spine fit
energySpectrumMapthe [longitudial projection bin -> contained energy] map
showerSpineHitListthe shower spine hit list
isEndDownstreamwhether the shower direction is downstream (in Z) of the neutrino vertex
startIterthe start iterator of energySpectrumMap
endIterthe end iterator of energySpectrumMap

Referenced by FindShowerStartAndDirection().

template<typename T >
int lar_content::ShowerStartFinderTool::FindShowerStartLongitudinalCoordinate ( const ParticleFlowObject *const  pShowerPfo,
const HitType  hitType,
const TwoDSlidingFitResult spineTwoDSlidingFit,
const EnergySpectrumMap energySpectrumMap,
const CaloHitList &  showerSpineHitList,
const bool  isEndDownstream,
const T  startIter,
const T  endIter 
) const

Definition at line 210 of file ShowerStartFinderTool.cc.

References CharacteriseInitialEnergy(), f, IsShowerTopology(), m_longitudinalCoordinateBinSize, m_minSigmaDeviation, and m_nInitialEnergyBins.

213 {
214  // Characterise initial energy
215  float meanEnergy(0.f), energySigma(0.f);
216 
217  if (energySpectrumMap.size() > m_nInitialEnergyBins)
218  this->CharacteriseInitialEnergy(energySpectrumMap, isEndDownstream, meanEnergy, energySigma);
219 
220  // Now loop through energySpectrumMap
221  T iter(startIter);
222 
223  std::advance(iter, (energySpectrumMap.size() > m_nInitialEnergyBins) ? m_nInitialEnergyBins : (energySpectrumMap.size() - 1));
224 
225  for (; iter != endIter; iter++)
226  {
227  const float longitudinalCoordinate(iter->first * m_longitudinalCoordinateBinSize);
228  const float energyDeviation((iter->second - meanEnergy) / energySigma);
229 
230  // Use energy and local topology to assess whether we are at the shower start
231  if ((energyDeviation > m_minSigmaDeviation) &&
232  this->IsShowerTopology(pShowerPfo, hitType, spineTwoDSlidingFit, longitudinalCoordinate, showerSpineHitList, isEndDownstream))
233  {
234  break;
235  }
236  }
237 
238  return iter->first;
239 }
void CharacteriseInitialEnergy(const EnergySpectrumMap &energySpectrumMap, const bool isEndDownstream, float &meanEnergy, float &energySigma) const
Find the mean and standard deviation of the energy depositions in the initial region.
float m_longitudinalCoordinateBinSize
The longitudinal coordinate bin size.
TFile f
Definition: plotHisto.C:6
unsigned int m_nInitialEnergyBins
The number of longitudinal bins that define the initial region.
bool IsShowerTopology(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::HitType hitType, const TwoDSlidingFitResult &spineTwoDSlidingFit, const float longitudinalDistance, const pandora::CaloHitList &showerSpineHitList, const bool isEndDownstream) const
Whether a sensible shower cascade looks to originate at a given position.
float m_minSigmaDeviation
The min. average energy deviation of a candidate shower start.
StatusCode lar_content::ShowerStartFinderTool::GetBoundaryExtremalPoints ( const TwoDSlidingShowerFitResult showerTwoDSlidingFit,
const LayerFitResultMap layerFitResultMap,
const pandora::CartesianVector &  showerStartPosition,
const int  showerStartLayer,
const int  showerEndLayer,
pandora::CartesianVector &  boundaryEdgeStart,
pandora::CartesianVector &  boundaryEdgeEnd 
) const
private

Determine the start and end positions of a shower boundary.

Parameters
showerTwoDSlidingFitthe shower fit
layerFitResultMapthe layer fit result map of the shower boundary fit
showerStartPositionthe shower start position
showerStartLayerthe shower start layer wrt the shower region fit
showerEndLayerthe shower end layer wrt the shower region fit
boundaryEdgeStartthe output boundary start position
boundaryEdgeEndthe output boundary end position
Returns
whether suitable positions could be found

Definition at line 606 of file ShowerStartFinderTool.cc.

References util::abs(), lar_content::TwoDSlidingFitResult::GetGlobalPosition(), lar_content::TwoDSlidingShowerFitResult::GetShowerFitResult(), and m_maxLayerSeparation.

Referenced by CharacteriseShowerTopology().

609 {
610  int boundaryStartLayer(std::numeric_limits<int>::max());
611  int boundaryEndLayer(std::numeric_limits<int>::max());
612 
613  for (auto &entry : layerFitResultMap)
614  {
615  const int bestStartSeparation(std::abs(showerStartLayer - boundaryStartLayer));
616  const int thisStartSeparation(std::abs(showerStartLayer - entry.first));
617 
618  if (((bestStartSeparation - thisStartSeparation) > 0) && (thisStartSeparation < bestStartSeparation))
619  boundaryStartLayer = entry.first;
620 
621  const int bestEndSeparation(std::abs(showerEndLayer - boundaryEndLayer));
622  const int thisEndSeparation(std::abs(showerEndLayer - entry.first));
623 
624  if (((bestEndSeparation - thisEndSeparation) > 0) && (thisEndSeparation < bestEndSeparation))
625  boundaryEndLayer = entry.first;
626  }
627 
628  if (std::abs(showerStartLayer - boundaryStartLayer) > m_maxLayerSeparation)
629  return STATUS_CODE_FAILURE;
630 
631  const float showerStartBoundaryLocalL(layerFitResultMap.at(boundaryStartLayer).GetL()),
632  showerStartBoundaryLocalT(layerFitResultMap.at(boundaryStartLayer).GetFitT());
633  const float showerEndBoundaryLocalL(layerFitResultMap.at(boundaryEndLayer).GetL()),
634  showerEndBoundaryLocalT(layerFitResultMap.at(boundaryEndLayer).GetFitT());
635 
636  showerTwoDSlidingFit.GetShowerFitResult().GetGlobalPosition(showerStartBoundaryLocalL, showerStartBoundaryLocalT, boundaryEdgeStart);
637  showerTwoDSlidingFit.GetShowerFitResult().GetGlobalPosition(showerEndBoundaryLocalL, showerEndBoundaryLocalT, boundaryEdgeEnd);
638 
639  // Swap start and end if needs be
640  if ((showerStartPosition - boundaryEdgeEnd).GetMagnitudeSquared() < (showerStartPosition - boundaryEdgeStart).GetMagnitude())
641  {
642  const CartesianVector startTemp(boundaryEdgeStart), endTemp(boundaryEdgeEnd);
643 
644  boundaryEdgeStart = endTemp;
645  boundaryEdgeEnd = startTemp;
646  }
647 
648  return STATUS_CODE_SUCCESS;
649 }
int m_maxLayerSeparation
The max. allowed separation between the shower start and boundary start layers.
constexpr auto abs(T v)
Returns the absolute value of the argument.
void lar_content::ShowerStartFinderTool::GetEnergyDistribution ( const pandora::CaloHitList &  showerSpineHitList,
const LongitudinalPositionMap longitudinalPositionMap,
EnergySpectrumMap energySpectrumMap 
) const
private

Create the longituidnal energy distribution.

Parameters
showerSpineHitListthe shower spine hit list
longitudinalPositionMapthe shower spine longitudinal projection map
energySpectrumMapthe output [longitudial projection bin -> contained energy] map

Definition at line 159 of file ShowerStartFinderTool.cc.

References f, and m_longitudinalCoordinateBinSize.

Referenced by Run().

161 {
162  float e0(0.f);
163 
164  for (const CaloHit *pCaloHit : showerSpineHitList)
165  e0 += pCaloHit->GetElectromagneticEnergy();
166 
167  for (const CaloHit *pCaloHit : showerSpineHitList)
168  {
169  const float fractionalEnergy(pCaloHit->GetElectromagneticEnergy() / e0);
170  const float projection(longitudinalPositionMap.at(pCaloHit));
171  const int longitudinalIndex = std::floor(projection / m_longitudinalCoordinateBinSize);
172 
173  if (energySpectrumMap.find(longitudinalIndex) == energySpectrumMap.end())
174  energySpectrumMap[longitudinalIndex] = fractionalEnergy;
175  else
176  energySpectrumMap[longitudinalIndex] += fractionalEnergy;
177  }
178 }
float m_longitudinalCoordinateBinSize
The longitudinal coordinate bin size.
TFile f
Definition: plotHisto.C:6
bool lar_content::ShowerStartFinderTool::IsClockwiseRotation ( const pandora::CartesianVector &  showerStartDirection,
const pandora::CartesianVector &  displacementVector 
) const
private

Determine whether a point lies on the RHS or LHS (wrt +ve Z) of the shower core.

Parameters
showerStartDirectionthe shower start direction
displacementVectorthe input position wrt the shower start position
Returns
whether a point lies on the RHS or LHS (wrt +ve Z) of the shower core

Definition at line 584 of file ShowerStartFinderTool.cc.

References f.

Referenced by CharacteriseShowerTopology().

585 {
586  // Clockwise with respect to +ve Z
587  const float openingAngleFromCore(showerStartDirection.GetOpeningAngle(displacementVector));
588 
589  const CartesianVector clockwiseRotation(
590  displacementVector.GetZ() * std::sin(openingAngleFromCore) + displacementVector.GetX() * std::cos(openingAngleFromCore), 0.f,
591  displacementVector.GetZ() * std::cos(openingAngleFromCore) - displacementVector.GetX() * std::sin(openingAngleFromCore));
592 
593  const CartesianVector anticlockwiseRotation(
594  displacementVector.GetZ() * std::sin(-1.f * openingAngleFromCore) + displacementVector.GetX() * std::cos(-1.f * openingAngleFromCore), 0.f,
595  displacementVector.GetZ() * std::cos(-1.f * openingAngleFromCore) - displacementVector.GetX() * std::sin(-1.f * openingAngleFromCore));
596 
597  const float clockwiseT((clockwiseRotation - showerStartDirection).GetMagnitude());
598  const float anticlockwiseT((anticlockwiseRotation - showerStartDirection).GetMagnitude());
599  const bool isClockwise(clockwiseT < anticlockwiseT);
600 
601  return isClockwise;
602 }
TFile f
Definition: plotHisto.C:6
bool lar_content::ShowerStartFinderTool::IsShowerTopology ( const pandora::ParticleFlowObject *const  pShowerPfo,
const pandora::HitType  hitType,
const TwoDSlidingFitResult spineTwoDSlidingFit,
const float  longitudinalDistance,
const pandora::CaloHitList &  showerSpineHitList,
const bool  isEndDownstream 
) const
private

Whether a sensible shower cascade looks to originate at a given position.

Parameters
pShowerPfothe shower pfo
hitTypethe 2D view
spineTwoDSlidingFitthe shower spine fit
longitudinalDistancethe longitudinal projection of the candidate shower start position
showerSpineHitListthe shower spine hit list
isEndDownstreamwhether the shower direction is downstream (in Z) of the neutrino vertex
Returns
whether a sensible shower cascade looks to originate at the given position

Definition at line 269 of file ShowerStartFinderTool.cc.

References BuildShowerRegion(), CharacteriseShowerTopology(), ConvertLongitudinalProjectionToGlobal(), f, and m_minShowerOpeningAngle.

Referenced by FindShowerStartLongitudinalCoordinate().

271 {
272  CartesianVector showerStartPosition(0.f, 0.f, 0.f), showerStartDirection(0.f, 0.f, 0.f);
273  this->ConvertLongitudinalProjectionToGlobal(spineTwoDSlidingFit, longitudinalDistance, showerStartPosition, showerStartDirection);
274 
275  // Build shower
276  CartesianPointVector showerRegionPositionVector;
277  if (this->BuildShowerRegion(pShowerPfo, hitType, showerSpineHitList, showerStartPosition, showerStartDirection, isEndDownstream,
278  showerRegionPositionVector) != STATUS_CODE_SUCCESS)
279  {
280  return false;
281  }
282 
283  // Characterise the shower
284  bool isBetween(false);
285  CartesianVector positiveEdgeStart(0.f, 0.f, 0.f), positiveEdgeEnd(0.f, 0.f, 0.f), positiveEdgeDirection(0.f, 0.f, 0.f);
286  CartesianVector negativeEdgeStart(0.f, 0.f, 0.f), negativeEdgeEnd(0.f, 0.f, 0.f), negativeEdgeDirection(0.f, 0.f, 0.f);
287 
288  if (this->CharacteriseShowerTopology(showerRegionPositionVector, showerStartPosition, hitType, isEndDownstream, showerStartDirection,
289  positiveEdgeStart, positiveEdgeEnd, negativeEdgeStart, negativeEdgeEnd, isBetween) != STATUS_CODE_SUCCESS)
290  {
291  return false;
292  }
293 
294  if (!isBetween)
295  return false;
296 
297  positiveEdgeStart = showerStartPosition;
298  negativeEdgeStart = showerStartPosition;
299  positiveEdgeDirection = positiveEdgeEnd - positiveEdgeStart;
300  negativeEdgeDirection = negativeEdgeEnd - negativeEdgeStart;
301 
302  const float showerOpeningAngle(positiveEdgeDirection.GetOpeningAngle(negativeEdgeDirection) * 180.f / 3.14);
303 
304  if (showerOpeningAngle < m_minShowerOpeningAngle)
305  return false;
306 
307  return true;
308 }
float m_minShowerOpeningAngle
The min. opening angle of a sensible shower.
pandora::StatusCode BuildShowerRegion(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::HitType hitType, const pandora::CaloHitList &showerSpineHitList, const pandora::CartesianVector &showerStartPosition, const pandora::CartesianVector &showerStartDirection, const bool isEndDownstream, pandora::CartesianPointVector &showerRegionPositionVector) const
Build the downstream &#39;shower region&#39; at a given longitudinal distance along the spine.
TFile f
Definition: plotHisto.C:6
pandora::StatusCode CharacteriseShowerTopology(const pandora::CartesianPointVector &showerRegionPositionVector, const pandora::CartesianVector &showerStartPosition, const pandora::HitType hitType, const bool isEndDownstream, const pandora::CartesianVector &showerStartDirection, pandora::CartesianVector &positiveEdgeStart, pandora::CartesianVector &positiveEdgeEnd, pandora::CartesianVector &negativeEdgeStart, pandora::CartesianVector &negativeEdgeEnd, bool &isBetween) const
Parameterise the topological structure of the shower region.
void ConvertLongitudinalProjectionToGlobal(const TwoDSlidingFitResult &spineTwoDSlidingFit, const float longitudinalDistance, pandora::CartesianVector &globalPosition, pandora::CartesianVector &globalDirection) const
Determine the (X,Y,Z) position and direction at a given longitudinal distance along the spine...
void lar_content::ShowerStartFinderTool::ObtainLongitudinalDecomposition ( const TwoDSlidingFitResult spineTwoDSlidingFit,
const pandora::CaloHitList &  showerSpineHitList,
LongitudinalPositionMap longitudinalPositionMap 
) const
private

Create the [shower spine hit -> shower spine fit longitudinal projection] map.

Parameters
spineTwoDSlidingFitthe shower spine fit
showerSpineHitListthe shower spine hit list
longitudinalPositionMapthe output shower spine longitudinal projection map

Definition at line 79 of file ShowerStartFinderTool.cc.

References f, lar_content::TwoDSlidingFitResult::GetGlobalPosition(), lar_content::TwoDSlidingFitResult::GetLayer(), lar_content::TwoDSlidingFitResult::GetLayerFitResultMap(), and lar_content::TwoDSlidingFitResult::GetLocalPosition().

Referenced by Run().

81 {
82  // Find hits in each layer
83  LayerToHitMap layerToHitMap;
84 
85  for (const CaloHit *const pCaloHit : showerSpineHitList)
86  {
87  float hitL(0.f), hitT(0.f);
88  const CartesianVector hitPosition(pCaloHit->GetPositionVector());
89 
90  spineTwoDSlidingFit.GetLocalPosition(hitPosition, hitL, hitT);
91  layerToHitMap[spineTwoDSlidingFit.GetLayer(hitL)].push_back(pCaloHit);
92  }
93 
94  // Walk through layers and store the longitudinal distance of each hit
95  // IMPORTANT: layer positions correspond to the middle of the layer
96  // IMPORTANT: the longitudinal distance is measured relative to the first layer position (where l = 0)
97  // IMPORTANT: at any point, the running distance is that at the lowest neighbour central position
98  float runningDistance(0);
99  const LayerFitResultMap &layerFitResultMap(spineTwoDSlidingFit.GetLayerFitResultMap());
100 
101  for (auto iter = layerToHitMap.begin(); iter != layerToHitMap.end(); ++iter)
102  {
103  const int layer(iter->first);
104  const float layerL(layerFitResultMap.at(layer).GetL());
105 
106  // Get global positions of layer and its neighbours
107  const int higherLayer(std::next(iter) == layerToHitMap.end() ? layer : std::next(iter)->first);
108  const int middleLayer(layer);
109  const int lowerLayer(iter == layerToHitMap.begin() ? layer : std::prev(iter)->first);
110  CartesianVector lowerLayerPosition(0.f, 0.f, 0.f), middleLayerPosition(0.f, 0.f, 0.f), higherLayerPosition(0.f, 0.f, 0.f);
111 
112  spineTwoDSlidingFit.GetGlobalPosition(layerFitResultMap.at(lowerLayer).GetL(), layerFitResultMap.at(lowerLayer).GetFitT(), lowerLayerPosition);
113  spineTwoDSlidingFit.GetGlobalPosition(layerFitResultMap.at(middleLayer).GetL(), layerFitResultMap.at(middleLayer).GetFitT(), middleLayerPosition);
114  spineTwoDSlidingFit.GetGlobalPosition(layerFitResultMap.at(higherLayer).GetL(), layerFitResultMap.at(higherLayer).GetFitT(), higherLayerPosition);
115 
116  const float layerLength = std::next(iter) == layerToHitMap.end() ? 0.f
117  : iter == layerToHitMap.begin() ? 0.f
118  : (middleLayerPosition - lowerLayerPosition).GetMagnitude();
119 
120  for (const CaloHit *const pCaloHit : iter->second)
121  {
122  const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
123 
124  float hitL(0.f), hitT(0.f);
125  spineTwoDSlidingFit.GetLocalPosition(hitPosition, hitL, hitT);
126 
127  // Is the hit below or above the middle of the layer?
128  // Therefore, determine which layer positions the hit is between
129  CartesianVector localLowerLayerPosition(0.f, 0.f, 0.f), localHigherLayerPosition(0.f, 0.f, 0.f);
130 
131  if (hitL < layerL)
132  {
133  localLowerLayerPosition = lowerLayerPosition;
134  localHigherLayerPosition = iter == layerToHitMap.begin() ? higherLayerPosition : middleLayerPosition;
135  }
136  else
137  {
138  localLowerLayerPosition = std::next(iter) == layerToHitMap.end() ? lowerLayerPosition : middleLayerPosition;
139  localHigherLayerPosition = higherLayerPosition;
140  }
141 
142  // Determine the axis to project onto
143  // Calculate the distance of axis between its two nearest neighbours
144  const CartesianVector displacement((higherLayerPosition - lowerLayerPosition).GetUnitVector());
145  float longitudinalDisplacement = (displacement.GetDotProduct(hitPosition - lowerLayerPosition) + runningDistance);
146 
147  // If we've passed the central position, we need to add on the layer length
148  longitudinalDisplacement += (hitL > layerL ? layerLength : 0.f);
149 
150  longitudinalPositionMap[pCaloHit] = longitudinalDisplacement;
151  }
152 
153  runningDistance += layerLength;
154  }
155 }
std::map< int, pandora::CaloHitList > LayerToHitMap
TFile f
Definition: plotHisto.C:6
std::map< int, LayerFitResult > LayerFitResultMap
StatusCode lar_content::ShowerStartFinderTool::ReadSettings ( const pandora::TiXmlHandle  xmlHandle)
private

Definition at line 653 of file ShowerStartFinderTool.cc.

References m_longitudinalCoordinateBinSize, m_longitudinalShowerFraction, m_maxEdgeGap, m_maxLayerSeparation, m_minShowerOpeningAngle, m_minSigmaDeviation, m_molliereRadius, m_nInitialEnergyBins, m_showerSlidingFitWindow, and m_spineSlidingFitWindow.

654 {
655  PANDORA_RETURN_RESULT_IF_AND_IF(
656  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SpineSlidingFitWindow", m_spineSlidingFitWindow));
657 
658  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
659  XmlHelper::ReadValue(xmlHandle, "LongitudinalCoordinateBinSize", m_longitudinalCoordinateBinSize));
660 
661  PANDORA_RETURN_RESULT_IF_AND_IF(
662  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "nInitialEnergyBins", m_nInitialEnergyBins));
663 
664  PANDORA_RETURN_RESULT_IF_AND_IF(
665  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinSigmaDeviation", m_minSigmaDeviation));
666 
667  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxEdgeGap", m_maxEdgeGap));
668 
669  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
670  XmlHelper::ReadValue(xmlHandle, "LongitudinalShowerFraction", m_longitudinalShowerFraction));
671 
672  PANDORA_RETURN_RESULT_IF_AND_IF(
673  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinShowerOpeningAngle", m_minShowerOpeningAngle));
674 
675  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MolliereRadius", m_molliereRadius));
676 
677  PANDORA_RETURN_RESULT_IF_AND_IF(
678  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ShowerSlidingFitWindow", m_showerSlidingFitWindow));
679 
680  PANDORA_RETURN_RESULT_IF_AND_IF(
681  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxLayerSeparation", m_maxLayerSeparation));
682 
683  return STATUS_CODE_SUCCESS;
684 }
float m_longitudinalShowerFraction
The shower region fraction considered.
float m_minShowerOpeningAngle
The min. opening angle of a sensible shower.
float m_longitudinalCoordinateBinSize
The longitudinal coordinate bin size.
int m_maxLayerSeparation
The max. allowed separation between the shower start and boundary start layers.
unsigned int m_showerSlidingFitWindow
The sliding window used to fit the shower region.
unsigned int m_nInitialEnergyBins
The number of longitudinal bins that define the initial region.
float m_maxEdgeGap
The max. allowed layer gap in a shower boundary.
float m_molliereRadius
The max. distance from the shower core of a collected shower region hit.
float m_minSigmaDeviation
The min. average energy deviation of a candidate shower start.
unsigned int m_spineSlidingFitWindow
The sliding window used to fit the shower spine.
StatusCode lar_content::ShowerStartFinderTool::Run ( const pandora::ParticleFlowObject *const  pShowerPfo,
const pandora::CartesianVector &  peakDirection,
const pandora::HitType  hitType,
const pandora::CaloHitList &  showerSpineHitList,
pandora::CartesianVector &  showerStartPosition,
pandora::CartesianVector &  showerStartDirection 
)

Definition at line 42 of file ShowerStartFinderTool.cc.

References FindShowerStartAndDirection(), GetEnergyDistribution(), lar_content::LArGeometryHelper::GetWirePitch(), m_spineSlidingFitWindow, and ObtainLongitudinalDecomposition().

Referenced by lar_content::ElectronInitialRegionRefinementAlgorithm::BuildViewProtoShowers().

44 {
45  try
46  {
47  // Fit the shower spine
48  CartesianPointVector hitPositions;
49  for (const CaloHit *const pCaloHit : showerSpineHitList)
50  hitPositions.push_back(pCaloHit->GetPositionVector());
51 
52  const TwoDSlidingFitResult spineTwoDSlidingFit(
53  &hitPositions, m_spineSlidingFitWindow, LArGeometryHelper::GetWirePitch(this->GetPandora(), hitType));
54 
55  // First obtain the longitudinal position of spine hits
56  LongitudinalPositionMap longitudinalPositionMap;
57  this->ObtainLongitudinalDecomposition(spineTwoDSlidingFit, showerSpineHitList, longitudinalPositionMap);
58 
59  // Obtain spine energy profile
60  EnergySpectrumMap energySpectrumMap;
61  this->GetEnergyDistribution(showerSpineHitList, longitudinalPositionMap, energySpectrumMap);
62 
63  // Now find the shower start position/direction
64  const bool isEndDownstream(peakDirection.GetZ() > 0.f);
65 
66  this->FindShowerStartAndDirection(pShowerPfo, hitType, spineTwoDSlidingFit, energySpectrumMap, showerSpineHitList, isEndDownstream,
67  showerStartPosition, showerStartDirection);
68  }
69  catch (...)
70  {
71  return STATUS_CODE_FAILURE;
72  }
73 
74  return STATUS_CODE_SUCCESS;
75 }
void ObtainLongitudinalDecomposition(const TwoDSlidingFitResult &spineTwoDSlidingFit, const pandora::CaloHitList &showerSpineHitList, LongitudinalPositionMap &longitudinalPositionMap) const
Create the [shower spine hit -> shower spine fit longitudinal projection] map.
std::map< const pandora::CaloHit *, float > LongitudinalPositionMap
void GetEnergyDistribution(const pandora::CaloHitList &showerSpineHitList, const LongitudinalPositionMap &longitudinalPositionMap, EnergySpectrumMap &energySpectrumMap) const
Create the longituidnal energy distribution.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
unsigned int m_spineSlidingFitWindow
The sliding window used to fit the shower spine.
void FindShowerStartAndDirection(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::HitType hitType, const TwoDSlidingFitResult &spineTwoDSlidingFit, const EnergySpectrumMap &energySpectrumMap, const pandora::CaloHitList &showerSpineHitList, const bool isEndDownstream, pandora::CartesianVector &showerStartPosition, pandora::CartesianVector &showerStartDirection) const
Find the position at which the shower cascade looks to originate, and its initial direction...

Member Data Documentation

float lar_content::ShowerStartFinderTool::m_longitudinalCoordinateBinSize
private

The longitudinal coordinate bin size.

Definition at line 195 of file ShowerStartFinderTool.h.

Referenced by FindShowerStartAndDirection(), FindShowerStartLongitudinalCoordinate(), GetEnergyDistribution(), and ReadSettings().

float lar_content::ShowerStartFinderTool::m_longitudinalShowerFraction
private

The shower region fraction considered.

Definition at line 199 of file ShowerStartFinderTool.h.

Referenced by BuildShowerRegion(), and ReadSettings().

float lar_content::ShowerStartFinderTool::m_maxEdgeGap
private

The max. allowed layer gap in a shower boundary.

Definition at line 198 of file ShowerStartFinderTool.h.

Referenced by BuildShowerRegion(), and ReadSettings().

int lar_content::ShowerStartFinderTool::m_maxLayerSeparation
private

The max. allowed separation between the shower start and boundary start layers.

Definition at line 203 of file ShowerStartFinderTool.h.

Referenced by GetBoundaryExtremalPoints(), and ReadSettings().

float lar_content::ShowerStartFinderTool::m_minShowerOpeningAngle
private

The min. opening angle of a sensible shower.

Definition at line 200 of file ShowerStartFinderTool.h.

Referenced by IsShowerTopology(), and ReadSettings().

float lar_content::ShowerStartFinderTool::m_minSigmaDeviation
private

The min. average energy deviation of a candidate shower start.

Definition at line 197 of file ShowerStartFinderTool.h.

Referenced by FindShowerStartLongitudinalCoordinate(), and ReadSettings().

float lar_content::ShowerStartFinderTool::m_molliereRadius
private

The max. distance from the shower core of a collected shower region hit.

Definition at line 201 of file ShowerStartFinderTool.h.

Referenced by BuildShowerRegion(), and ReadSettings().

unsigned int lar_content::ShowerStartFinderTool::m_nInitialEnergyBins
private

The number of longitudinal bins that define the initial region.

Definition at line 196 of file ShowerStartFinderTool.h.

Referenced by CharacteriseInitialEnergy(), FindShowerStartLongitudinalCoordinate(), and ReadSettings().

unsigned int lar_content::ShowerStartFinderTool::m_showerSlidingFitWindow
private

The sliding window used to fit the shower region.

Definition at line 202 of file ShowerStartFinderTool.h.

Referenced by BuildShowerRegion(), CharacteriseShowerTopology(), and ReadSettings().

unsigned int lar_content::ShowerStartFinderTool::m_spineSlidingFitWindow
private

The sliding window used to fit the shower spine.

Definition at line 194 of file ShowerStartFinderTool.h.

Referenced by ReadSettings(), and Run().


The documentation for this class was generated from the following files: