27 m_spineSlidingFitWindow(10),
28 m_longitudinalCoordinateBinSize(1.f),
29 m_nInitialEnergyBins(5),
30 m_minSigmaDeviation(1.f),
32 m_longitudinalShowerFraction(0.85f),
33 m_minShowerOpeningAngle(2.f),
34 m_molliereRadius(4.5f),
35 m_showerSlidingFitWindow(1000),
36 m_maxLayerSeparation(5)
49 for (
const CaloHit *
const pCaloHit : showerSpineHitList)
50 hitPositions.push_back(pCaloHit->GetPositionVector());
64 const bool isEndDownstream(peakDirection.
GetZ() > 0.f);
67 showerStartPosition, showerStartDirection);
71 return STATUS_CODE_FAILURE;
74 return STATUS_CODE_SUCCESS;
85 for (
const CaloHit *
const pCaloHit : showerSpineHitList)
87 float hitL(0.f), hitT(0.f);
91 layerToHitMap[spineTwoDSlidingFit.
GetLayer(hitL)].push_back(pCaloHit);
98 float runningDistance(0);
101 for (
auto iter = layerToHitMap.begin(); iter != layerToHitMap.end(); ++iter)
103 const int layer(iter->first);
104 const float layerL(layerFitResultMap.at(layer).GetL());
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);
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);
116 const float layerLength = std::next(iter) == layerToHitMap.end()
118 : iter == layerToHitMap.begin() ? 0.f : (middleLayerPosition - lowerLayerPosition).GetMagnitude();
120 for (
const CaloHit *
const pCaloHit : iter->second)
124 float hitL(0.f), hitT(0.f);
129 CartesianVector localLowerLayerPosition(0.f, 0.f, 0.f), localHigherLayerPosition(0.f, 0.f, 0.f);
133 localLowerLayerPosition = lowerLayerPosition;
134 localHigherLayerPosition = iter == layerToHitMap.begin() ? higherLayerPosition : middleLayerPosition;
138 localLowerLayerPosition = std::next(iter) == layerToHitMap.end() ? lowerLayerPosition : middleLayerPosition;
139 localHigherLayerPosition = higherLayerPosition;
144 const CartesianVector displacement((higherLayerPosition - lowerLayerPosition).GetUnitVector());
145 float longitudinalDisplacement = (displacement.
GetDotProduct(hitPosition - lowerLayerPosition) + runningDistance);
148 longitudinalDisplacement += (hitL > layerL ? layerLength : 0.f);
150 longitudinalPositionMap[pCaloHit] = longitudinalDisplacement;
153 runningDistance += layerLength;
164 for (
const CaloHit *pCaloHit : showerSpineHitList)
165 e0 += pCaloHit->GetElectromagneticEnergy();
167 for (
const CaloHit *pCaloHit : showerSpineHitList)
169 const float fractionalEnergy(pCaloHit->GetElectromagneticEnergy() / e0);
170 const float projection(longitudinalPositionMap.at(pCaloHit));
173 if (energySpectrumMap.find(longitudinalIndex) == energySpectrumMap.end())
174 energySpectrumMap[longitudinalIndex] = fractionalEnergy;
176 energySpectrumMap[longitudinalIndex] += fractionalEnergy;
187 int longitudinalStartBin(0);
192 showerSpineHitList, isEndDownstream, energySpectrumMap.begin(), std::prev(energySpectrumMap.end()));
197 showerSpineHitList, isEndDownstream, energySpectrumMap.rbegin(), std::prev(energySpectrumMap.rend()));
204 showerStartDirection = isEndDownstream ? showerStartDirection : showerStartDirection * (-1.f);
212 const bool isEndDownstream,
const T startIter,
const T endIter)
const
215 float meanEnergy(0.f), energySigma(0.f);
225 for (; iter != endIter; iter++)
228 const float energyDeviation((iter->second - meanEnergy) / energySigma);
232 this->
IsShowerTopology(pShowerPfo, hitType, spineTwoDSlidingFit, longitudinalCoordinate, showerSpineHitList, isEndDownstream))
244 const EnergySpectrumMap &energySpectrumMap,
const bool isEndDownstream,
float &meanEnergy,
float &energySigma)
const
246 auto energySpectrumIter(isEndDownstream ? energySpectrumMap.begin() : std::prev(energySpectrumMap.end()));
250 meanEnergy += energySpectrumIter->second;
251 isEndDownstream ? ++energySpectrumIter : --energySpectrumIter;
256 energySpectrumIter = isEndDownstream ? energySpectrumMap.begin() : std::prev(energySpectrumMap.end());
260 energySigma += std::pow(energySpectrumIter->second - meanEnergy, 2);
261 isEndDownstream ? ++energySpectrumIter : --energySpectrumIter;
270 const float longitudinalDistance,
const CaloHitList &showerSpineHitList,
const bool isEndDownstream)
const
272 CartesianVector showerStartPosition(0.f, 0.f, 0.f), showerStartDirection(0.f, 0.f, 0.f);
277 if (this->
BuildShowerRegion(pShowerPfo, hitType, showerSpineHitList, showerStartPosition, showerStartDirection, isEndDownstream,
278 showerRegionPositionVector) != STATUS_CODE_SUCCESS)
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);
288 if (this->
CharacteriseShowerTopology(showerRegionPositionVector, showerStartPosition, hitType, isEndDownstream, showerStartDirection,
289 positiveEdgeStart, positiveEdgeEnd, negativeEdgeStart, negativeEdgeEnd, isBetween) != STATUS_CODE_SUCCESS)
297 positiveEdgeStart = showerStartPosition;
298 negativeEdgeStart = showerStartPosition;
299 positiveEdgeDirection = positiveEdgeEnd - positiveEdgeStart;
300 negativeEdgeDirection = negativeEdgeEnd - negativeEdgeStart;
302 const float showerOpeningAngle(positiveEdgeDirection.
GetOpeningAngle(negativeEdgeDirection) * 180.f / 3.14);
317 float runningDistance(0.f);
318 int showerStartLayer(0);
320 spineTwoDSlidingFit.
GetGlobalPosition(layerFitResultMap.begin()->second.GetL(), layerFitResultMap.begin()->second.GetFitT(), previousLayerPosition);
322 for (
auto iter = std::next(layerFitResultMap.begin()); iter != layerFitResultMap.end(); ++iter)
324 const int layer(iter->first);
325 showerStartLayer = layer;
328 spineTwoDSlidingFit.
GetGlobalPosition(layerFitResultMap.at(layer).GetL(), layerFitResultMap.at(layer).GetFitT(), layerPosition);
330 runningDistance += (layerPosition - previousLayerPosition).GetMagnitude();
332 if (runningDistance > longitudinalDistance)
335 previousLayerPosition = layerPosition;
338 const float lCoordinate(layerFitResultMap.at(showerStartLayer).GetL()), tCoordinate(layerFitResultMap.at(showerStartLayer).GetFitT());
339 const float localGradient(layerFitResultMap.at(showerStartLayer).GetGradient());
357 for (
const CaloHit *
const pCaloHit : viewShowerHitList)
359 if (std::find(showerSpineHitList.begin(), showerSpineHitList.end(), pCaloHit) != showerSpineHitList.end())
363 float l(showerStartDirection.
GetDotProduct(hitPosition - showerStartPosition));
365 l *= isEndDownstream ? 1.f : -1.f;
373 showerRegionPositionVector.push_back(pCaloHit->GetPositionVector());
374 showerRegionHitList.push_back(pCaloHit);
388 float showerStartL(0.f), showerStartT(0.f);
394 for (LayerFitResultMap::const_iterator iterS = layerFitResultMapS.begin(); iterS != layerFitResultMapS.end(); ++iterS)
396 const int layer(iterS->first);
398 if (isEndDownstream && (layer < startLayer))
401 if (!isEndDownstream && (layer > startLayer))
404 LayerFitResultMap::const_iterator iterP = layerFitResultMapP.find(layer);
405 LayerFitResultMap::const_iterator iterN = layerFitResultMapN.find(layer);
407 if (layerFitResultMapP.end() != iterP)
411 coordinateListP.push_back(positiveEdgePosition);
414 if (layerFitResultMapN.end() != iterN)
418 coordinateListN.push_back(negativeEdgePosition);
422 if ((coordinateListP.size() == 0) || (coordinateListN.size() == 0))
423 return STATUS_CODE_FAILURE;
428 float pMaximumL(std::numeric_limits<float>::max());
431 for (
auto iterP = std::next(coordinateListP.begin()); iterP != coordinateListP.end(); ++iterP)
434 const float separationSquared((coordinateP - previousCoordinateP).GetMagnitudeSquared());
442 previousCoordinateP = coordinateP;
445 float nMaximumL(std::numeric_limits<float>::max());
448 for (
auto iterN = std::next(coordinateListN.begin()); iterN != coordinateListN.end(); ++iterN)
451 const float separationSquared((coordinateN - previousCoordinateN).GetMagnitudeSquared());
459 previousCoordinateN = coordinateN;
463 showerRegionPositionVector.clear();
465 for (
const CaloHit *
const pCaloHit : showerRegionHitList)
467 float thisL(0.f), thisT(0.f);
479 showerRegionPositionVector.push_back(pCaloHit->GetPositionVector());
484 return STATUS_CODE_FAILURE;
487 return STATUS_CODE_SUCCESS;
505 float showerStartL(0.f), showerStartT(0.f);
513 bool isFirstBetween(
false), isLastBetween(
false);
516 for (LayerFitResultMap::const_iterator iterS = layerFitResultMapS.begin(); iterS != layerFitResultMapS.end(); ++iterS)
518 int layer(iterS->first);
520 if (isEndDownstream && (layer < startLayer))
523 if (!isEndDownstream && (layer > startLayer))
526 LayerFitResultMap::const_iterator iterP = layerFitResultMapP.find(layer);
527 LayerFitResultMap::const_iterator iterN = layerFitResultMapN.find(layer);
529 CartesianVector positiveEdgePosition(0.f, 0.f, 0.f), negativeEdgePosition(0.f, 0.f, 0.f);
530 if (layerFitResultMapP.end() != iterP)
533 coordinateListP.push_back(positiveEdgePosition);
536 if (layerFitResultMapN.end() != iterN)
539 coordinateListN.push_back(negativeEdgePosition);
542 if ((layerFitResultMapP.end() != iterP) && (layerFitResultMapN.end() != iterN))
544 const CartesianVector positiveDisplacement((positiveEdgePosition - showerStartPosition).GetUnitVector());
545 const bool isPositiveClockwise(this->
IsClockwiseRotation(showerStartDirection, positiveDisplacement));
547 const CartesianVector negativeDisplacement((negativeEdgePosition - showerStartPosition).GetUnitVector());
548 const bool isNegativeClockwise(this->
IsClockwiseRotation(showerStartDirection, negativeDisplacement));
553 isFirstBetween = (isPositiveClockwise != isNegativeClockwise);
555 isLastBetween = (isPositiveClockwise != isNegativeClockwise);
559 isBetween = (isFirstBetween || isLastBetween);
563 positiveEdgeStart, positiveEdgeEnd) != STATUS_CODE_SUCCESS)
565 return STATUS_CODE_FAILURE;
569 negativeEdgeStart, negativeEdgeEnd) != STATUS_CODE_SUCCESS)
571 return STATUS_CODE_FAILURE;
576 return STATUS_CODE_FAILURE;
579 return STATUS_CODE_SUCCESS;
587 const float openingAngleFromCore(showerStartDirection.
GetOpeningAngle(displacementVector));
590 displacementVector.
GetZ() * std::sin(openingAngleFromCore) + displacementVector.
GetX() * std::cos(openingAngleFromCore), 0.f,
591 displacementVector.
GetZ() * std::cos(openingAngleFromCore) - displacementVector.
GetX() * std::sin(openingAngleFromCore));
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));
597 const float clockwiseT((clockwiseRotation - showerStartDirection).GetMagnitude());
598 const float anticlockwiseT((anticlockwiseRotation - showerStartDirection).GetMagnitude());
599 const bool isClockwise(clockwiseT < anticlockwiseT);
610 int boundaryStartLayer(std::numeric_limits<int>::max());
611 int boundaryEndLayer(std::numeric_limits<int>::max());
613 for (
auto &entry : layerFitResultMap)
615 const int bestStartSeparation(std::abs(showerStartLayer - boundaryStartLayer));
616 const int thisStartSeparation(std::abs(showerStartLayer - entry.first));
618 if (((bestStartSeparation - thisStartSeparation) > 0) && (thisStartSeparation < bestStartSeparation))
619 boundaryStartLayer = entry.first;
621 const int bestEndSeparation(std::abs(showerEndLayer - boundaryEndLayer));
622 const int thisEndSeparation(std::abs(showerEndLayer - entry.first));
624 if (((bestEndSeparation - thisEndSeparation) > 0) && (thisEndSeparation < bestEndSeparation))
625 boundaryEndLayer = entry.first;
629 return STATUS_CODE_FAILURE;
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());
640 if ((showerStartPosition - boundaryEdgeEnd).GetMagnitudeSquared() < (showerStartPosition - boundaryEdgeStart).GetMagnitude())
642 const CartesianVector startTemp(boundaryEdgeStart), endTemp(boundaryEdgeEnd);
644 boundaryEdgeStart = endTemp;
645 boundaryEdgeEnd = startTemp;
648 return STATUS_CODE_SUCCESS;
683 return STATUS_CODE_SUCCESS;
Header file for the connection pathway helper class.
Header file for the geometry helper class.
Header file for the pfo helper class.
Header file for the lar two dimensional sliding fit result class.
Header file for the lar two dimensional sliding shower fit result class.
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
SortByDistanceToPoint class.
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.
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.
unsigned int m_spineSlidingFitWindow
The sliding window used to fit the shower spine.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
std::map< int, pandora::CaloHitList > LayerToHitMap
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.
unsigned int m_showerSlidingFitWindow
The sliding window used to fit the shower region.
float m_minShowerOpeningAngle
The min. opening angle of a sensible shower.
void ObtainLongitudinalDecomposition(const TwoDSlidingFitResult &spineTwoDSlidingFit, const pandora::CaloHitList &showerSpineHitList, LongitudinalPositionMap &longitudinalPositionMap) const
Create the [shower spine hit -> shower spine fit longitudinal projection] map.
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.
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.
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)
std::map< const pandora::CaloHit *, float > LongitudinalPositionMap
float m_minSigmaDeviation
The min. average energy deviation of a candidate shower start.
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.
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.
std::map< int, float > EnergySpectrumMap
ShowerStartFinderTool()
Default constructor.
void GetEnergyDistribution(const pandora::CaloHitList &showerSpineHitList, const LongitudinalPositionMap &longitudinalPositionMap, EnergySpectrumMap &energySpectrumMap) const
Create the longituidnal energy distribution.
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.
int m_maxLayerSeparation
The max. allowed separation between the shower start and boundary start layers.
float m_maxEdgeGap
The max. allowed layer gap in a shower boundary.
unsigned int m_nInitialEnergyBins
The number of longitudinal bins that define the initial region.
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.
float m_longitudinalShowerFraction
The shower region fraction considered.
float m_molliereRadius
The max. distance from the shower core of a collected shower region hit.
TwoDSlidingFitResult class.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
const LayerFitResultMap & GetLayerFitResultMap() const
Get the layer fit result map.
void GetGlobalPosition(const float rL, const float rT, pandora::CartesianVector &position) const
Get global coordinates for given sliding linear fit coordinates.
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
int GetLayer(const float rL) const
Get layer number for given sliding linear fit longitudinal coordinate.
void GetGlobalDirection(const float dTdL, pandora::CartesianVector &direction) const
Get global direction coordinates for given sliding linear fit gradient.
TwoDSlidingShowerFitResult class.
const TwoDSlidingFitResult & GetNegativeEdgeFitResult() const
Get the sliding fit result for the negative shower edge.
const TwoDSlidingFitResult & GetShowerFitResult() const
Get the sliding fit result for the full shower cluster.
const TwoDSlidingFitResult & GetPositiveEdgeFitResult() const
Get the sliding fit result for the positive shower edge.
float GetX() const
Get the cartesian x coordinate.
float GetZ() const
Get the cartesian z coordinate.
float GetDotProduct(const CartesianVector &rhs) const
Get the dot product of the cartesian vector with a second cartesian vector.
float GetMagnitude() const
Get the magnitude.
CartesianVector GetCrossProduct(const CartesianVector &rhs) const
Get the cross product of the cartesian vector with a second cartesian vector.
float GetOpeningAngle(const CartesianVector &rhs) const
Get the opening angle of the cartesian vector with respect to a second cartesian vector.
ParticleFlowObject class.
const Pandora & GetPandora() const
Get the associated pandora instance.
StatusCodeException class.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
std::map< int, LayerFitResult > LayerFitResultMap
HitType
Calorimeter hit type enum.
std::vector< CartesianVector > CartesianPointVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.