9 #include "Pandora/AlgorithmHeaders.h" 
   25 StitchingCosmicRayMergingTool::StitchingCosmicRayMergingTool() :
 
   26     m_useXcoordinate(
false),
 
   27     m_alwaysApplyT0Calculation(
true),
 
   28     m_halfWindowLayers(30),
 
   29     m_minLengthSquared(50.f),
 
   30     m_minCosRelativeAngle(0.966),
 
   31     m_relaxMinLongitudinalDisplacement(-5.f),
 
   32     m_maxLongitudinalDisplacementX(15.f),
 
   33     m_maxTransverseDisplacement(5.f),
 
   34     m_relaxCosRelativeAngle(0.906),
 
   35     m_relaxTransverseDisplacement(2.5f),
 
   37     m_maxX0FractionalDeviation(0.3f),
 
   38     m_boundaryToleranceWidth(10.f)
 
   45     if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
 
   46         std::cout << 
"----> Running Algorithm Tool: " << this->GetInstanceName() << 
", " << this->GetType() << std::endl;
 
   48     if (this->GetPandora().GetGeometry()->GetLArTPCMap().
size() < 2)
 
   51     if (pfoToLArTPCMap.empty())
 
   52         throw StatusCodeException(STATUS_CODE_NOT_FOUND);
 
   61     this->
BuildTPCMaps(primaryPfos, pfoToLArTPCMap, larTPCToPfoMap);
 
   64     this->
CreatePfoMatches(larTPCToPfoMap, pointingClusterMap, pfoAssociationMatrix);
 
   73     this->
OrderPfoMerges(pfoToLArTPCMap, pointingClusterMap, pfoSelectedMerges, pfoOrderedMerges);
 
   75     this->
StitchPfos(pAlgorithm, pointingClusterMap, pfoOrderedMerges, pfoToLArTPCMap, stitchedPfosToX0Map);
 
   82     for (
const ParticleFlowObject *
const pPfo : *pInputPfoList)
 
   87         if (!pfoToLArTPCMap.count(pPfo))
 
   90         outputPfoList.push_back(pPfo);
 
  101     for (
const ParticleFlowObject *
const pPfo : inputPfoList)
 
  105             PfoToLArTPCMap::const_iterator tpcIter(pfoToLArTPCMap.find(pPfo));
 
  107             if (pfoToLArTPCMap.end() == tpcIter)
 
  108                 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
 
  110             const float slidingFitPitch(tpcIter->second->GetWirePitchW());
 
  112             ClusterList clusterList;
 
  115             if (1 != clusterList.size())
 
  116                 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
 
  119             (
void)pointingClusterMap.insert(ThreeDPointingClusterMap::value_type(pPfo, 
LArPointingCluster(slidingFitResult)));
 
  121         catch (
const StatusCodeException &)
 
  131     for (
const ParticleFlowObject *
const pPfo : inputPfoList)
 
  133         PfoToLArTPCMap::const_iterator iter(pfoToLArTPCMap.find(pPfo));
 
  135         if (pfoToLArTPCMap.end() != iter)
 
  136             larTPCToPfoMap[iter->second].push_back(pPfo);
 
  145     LArTPCVector larTPCVector;
 
  146     for (
const auto &mapEntry : larTPCToPfoMap)
 
  147         larTPCVector.push_back(mapEntry.first);
 
  150     for (LArTPCVector::const_iterator tpcIter1 = larTPCVector.begin(), tpcIterEnd = larTPCVector.end(); tpcIter1 != tpcIterEnd; ++tpcIter1)
 
  152         const LArTPC *
const pLArTPC1(*tpcIter1);
 
  153         const PfoList &pfoList1(larTPCToPfoMap.at(pLArTPC1));
 
  155         for (LArTPCVector::const_iterator tpcIter2 = tpcIter1; tpcIter2 != tpcIterEnd; ++tpcIter2)
 
  157             const LArTPC *
const pLArTPC2(*tpcIter2);
 
  158             const PfoList &pfoList2(larTPCToPfoMap.at(pLArTPC2));
 
  163             for (
const ParticleFlowObject *
const pPfo1 : pfoList1)
 
  165                 for (
const ParticleFlowObject *
const pPfo2 : pfoList2)
 
  166                     this->
CreatePfoMatches(*pLArTPC1, *pLArTPC2, pPfo1, pPfo2, pointingClusterMap, pfoAssociationMatrix);
 
  175     const ParticleFlowObject *
const pPfo2, 
const ThreeDPointingClusterMap &pointingClusterMap, PfoAssociationMatrix &pfoAssociationMatrix)
 const 
  183     ThreeDPointingClusterMap::const_iterator iter1 = pointingClusterMap.find(pPfo1);
 
  184     ThreeDPointingClusterMap::const_iterator iter2 = pointingClusterMap.find(pPfo2);
 
  186     if (pointingClusterMap.end() == iter1 || pointingClusterMap.end() == iter2)
 
  197     CaloHitList caloHitList3D1;
 
  200     CaloHitList caloHitList3D2;
 
  214     catch (
const pandora::StatusCodeException &)
 
  226     const float pX1(std::fabs(pointingVertex1.
GetDirection().GetX()));
 
  227     const float pX2(std::fabs(pointingVertex2.
GetDirection().GetX()));
 
  229     if (pX1 < std::numeric_limits<float>::epsilon() || pX2 < std::numeric_limits<float>::epsilon())
 
  233     const float intersectX(0.5 * (pointingVertex1.
GetPosition().GetX() + pointingVertex2.
GetPosition().GetX()));
 
  235     if (std::fabs(intersectX - boundaryCenterX) > maxLongitudinalDisplacementX)
 
  239     float rT1(0.f), rL1(0.f), rT2(0.f), rL2(0.f);
 
  254     catch (
const pandora::StatusCodeException &)
 
  263     const float dXdL1(
m_useXcoordinate ? pX1 : (1.f - pX1 * pX1 > std::numeric_limits<float>::epsilon()) ? pX1 / std::sqrt(1.f - pX1 * pX1) : minL);
 
  264     const float dXdL2(
m_useXcoordinate ? pX2 : (1.f - pX2 * pX2 > std::numeric_limits<float>::epsilon()) ? pX2 / std::sqrt(1.f - pX2 * pX2) : minL);
 
  265     const float maxL1(maxLongitudinalDisplacementX / dXdL1);
 
  266     const float maxL2(maxLongitudinalDisplacementX / dXdL2);
 
  268     if (rL1 < minL || rL1 > maxL1 || rL2 < minL || rL2 > maxL2)
 
  275     if (!minPass && !maxPass)
 
  282     const float particleLength1(pointingCluster1.GetLengthSquared());
 
  283     const float particleLength2(pointingCluster2.GetLengthSquared());
 
  285     pfoAssociationMatrix[pPfo1].insert(PfoAssociationMap::value_type(pPfo2, PfoAssociation(vertexType1, vertexType2, particleLength2)));
 
  286     pfoAssociationMatrix[pPfo2].insert(PfoAssociationMap::value_type(pPfo1, PfoAssociation(vertexType2, vertexType1, particleLength1)));
 
  297     PfoVector pfoVector1;
 
  298     for (
const auto &mapEntry : pfoAssociationMatrix)
 
  299         pfoVector1.push_back(mapEntry.first);
 
  302     for (
const ParticleFlowObject *
const pPfo1 : pfoVector1)
 
  306         const ParticleFlowObject *pBestPfoInner(
nullptr);
 
  309         const ParticleFlowObject *pBestPfoOuter(
nullptr);
 
  312         PfoVector pfoVector2;
 
  313         for (
const auto &mapEntry : pfoAssociationMap)
 
  314             pfoVector2.push_back(mapEntry.first);
 
  317         for (
const ParticleFlowObject *
const pPfo2 : pfoVector2)
 
  319             const PfoAssociation &pfoAssociation(pfoAssociationMap.at(pPfo2));
 
  324                 if (pfoAssociation.GetFigureOfMerit() > bestAssociationInner.
GetFigureOfMerit())
 
  326                     bestAssociationInner = pfoAssociation;
 
  327                     pBestPfoInner = pPfo2;
 
  334                 if (pfoAssociation.GetFigureOfMerit() > bestAssociationOuter.
GetFigureOfMerit())
 
  336                     bestAssociationOuter = pfoAssociation;
 
  337                     pBestPfoOuter = pPfo2;
 
  343             (
void)bestAssociationMatrix[pPfo1].insert(PfoAssociationMap::value_type(pBestPfoInner, bestAssociationInner));
 
  346             (
void)bestAssociationMatrix[pPfo1].insert(PfoAssociationMap::value_type(pBestPfoOuter, bestAssociationOuter));
 
  351     PfoVector pfoVector3;
 
  352     for (
const auto &mapEntry : bestAssociationMatrix)
 
  353         pfoVector3.push_back(mapEntry.first);
 
  356     for (
const ParticleFlowObject *
const pParentPfo : pfoVector3)
 
  358         const PfoAssociationMap &parentAssociationMap(bestAssociationMatrix.at(pParentPfo));
 
  360         PfoVector pfoVector4;
 
  361         for (
const auto &mapEntry : parentAssociationMap)
 
  362             pfoVector4.push_back(mapEntry.first);
 
  365         for (
const ParticleFlowObject *
const pDaughterPfo : pfoVector4)
 
  367             const PfoAssociation &parentToDaughterAssociation(parentAssociationMap.at(pDaughterPfo));
 
  368             PfoAssociationMatrix::const_iterator iter5 = bestAssociationMatrix.find(pDaughterPfo);
 
  370             if (bestAssociationMatrix.end() == iter5)
 
  375             PfoAssociationMap::const_iterator iter6 = daughterAssociationMap.find(pParentPfo);
 
  376             if (daughterAssociationMap.end() == iter6)
 
  381             if (parentToDaughterAssociation.GetParent() == daughterToParentAssociation.
GetDaughter() &&
 
  382                 parentToDaughterAssociation.GetDaughter() == daughterToParentAssociation.
GetParent())
 
  384                 pfoMatches[pParentPfo].push_back(pDaughterPfo);
 
  396     PfoVector inputPfoVector;
 
  397     for (
const auto &mapEntry : pfoMatches)
 
  398         inputPfoVector.push_back(mapEntry.first);
 
  401     for (
const ParticleFlowObject *
const pInputPfo : inputPfoVector)
 
  403         const PfoList &pfoList(pfoMatches.at(pInputPfo));
 
  405         for (
const ParticleFlowObject *
const pSeedPfo : pfoList)
 
  407             if (vetoSet.count(pSeedPfo))
 
  413             vetoSet.insert(pSeedPfo);
 
  414             PfoList &selectedPfoList(pfoMerges[pSeedPfo]);
 
  415             selectedPfoList.push_back(pSeedPfo);
 
  417             for (
const ParticleFlowObject *
const pAssociatedPfo : mergeList)
 
  420                 if (vetoSet.count(pAssociatedPfo) || (selectedPfoList.end() != std::find(selectedPfoList.begin(), selectedPfoList.end(), pAssociatedPfo)))
 
  421                     throw StatusCodeException(STATUS_CODE_FAILURE);
 
  423                 vetoSet.insert(pAssociatedPfo);
 
  424                 selectedPfoList.push_back(pAssociatedPfo);
 
  433     const ParticleFlowObject *
const pCurrentPfo, 
const PfoMergeMap &pfoMergeMap, 
const PfoSet &vetoSet, PfoList &associatedList)
 const 
  435     if (vetoSet.count(pCurrentPfo))
 
  438     PfoMergeMap::const_iterator iter1 = pfoMergeMap.find(pCurrentPfo);
 
  440     if (pfoMergeMap.end() == iter1)
 
  443     for (PfoList::const_iterator iter2 = iter1->second.begin(), iterEnd2 = iter1->second.end(); iter2 != iterEnd2; ++iter2)
 
  445         const ParticleFlowObject *
const pAssociatedPfo = *iter2;
 
  447         if (pAssociatedPfo == pSeedPfo)
 
  450         if (associatedList.end() != std::find(associatedList.begin(), associatedList.end(), pAssociatedPfo))
 
  453         associatedList.push_back(pAssociatedPfo);
 
  464     PfoVector inputPfoVector;
 
  465     for (
const auto &mapEntry : inputPfoMerges)
 
  466         inputPfoVector.push_back(mapEntry.first);
 
  469     for (
const ParticleFlowObject *
const pInputPfo : inputPfoVector)
 
  471         const PfoList &pfoList(inputPfoMerges.at(pInputPfo));
 
  473         float bestLength(0.f);
 
  474         const ParticleFlowObject *pVertexPfo = 
nullptr;
 
  476         for (PfoList::const_iterator iter1 = pfoList.begin(), iterEnd = pfoList.end(); iter1 != iterEnd; ++iter1)
 
  478             const ParticleFlowObject *
const pPfo1(*iter1);
 
  479             PfoToLArTPCMap::const_iterator tpcIter1 = pfoToLArTPCMap.find(pPfo1);
 
  480             ThreeDPointingClusterMap::const_iterator pointingIter1 = pointingClusterMap.find(pPfo1);
 
  482             if (pfoToLArTPCMap.end() == tpcIter1 || pointingClusterMap.end() == pointingIter1)
 
  483                 throw StatusCodeException(STATUS_CODE_FAILURE);
 
  485             const LArTPC *
const pLArTPC1(tpcIter1->second);
 
  488             for (PfoList::const_iterator iter2 = iter1; iter2 != iterEnd; ++iter2)
 
  490                 const ParticleFlowObject *
const pPfo2(*iter2);
 
  491                 PfoToLArTPCMap::const_iterator tpcIter2 = pfoToLArTPCMap.find(pPfo2);
 
  492                 ThreeDPointingClusterMap::const_iterator pointingIter2 = pointingClusterMap.find(pPfo2);
 
  494                 if (pfoToLArTPCMap.end() == tpcIter2 || pointingClusterMap.end() == pointingIter2)
 
  495                     throw StatusCodeException(STATUS_CODE_FAILURE);
 
  497                 const LArTPC *
const pLArTPC2(tpcIter2->second);
 
  500                 if (pLArTPC1 == pLArTPC2)
 
  505                 if (thisLength < bestLength)
 
  508                 bestLength = thisLength;
 
  512                     pVertexPfo = 
nullptr;
 
  521                     const float deltaY(farVertex1.GetPosition().GetY() - farVertex2.GetPosition().GetY());
 
  523                     if (std::fabs(deltaY) < std::numeric_limits<float>::epsilon())
 
  524                         throw StatusCodeException(STATUS_CODE_NOT_FOUND);
 
  526                     pVertexPfo = ((deltaY > 0.f) ? pPfo1 : pPfo2);
 
  528                 catch (
const pandora::StatusCodeException &)
 
  535             outputPfoMerges[pVertexPfo].insert(outputPfoMerges[pVertexPfo].
begin(), pfoList.begin(), pfoList.end());
 
  544     PfoVector pfoVectorToEnlarge;
 
  545     for (
const auto &mapEntry : pfoMerges)
 
  546         pfoVectorToEnlarge.push_back(mapEntry.first);
 
  549     for (
const ParticleFlowObject *
const pPfoToEnlarge : pfoVectorToEnlarge)
 
  551         const PfoList &pfoList(pfoMerges.at(pPfoToEnlarge));
 
  552         const PfoVector pfoVector(pfoList.begin(), pfoList.end());
 
  561                 if (!this->
CalculateX0(pfoToLArTPCMap, pointingClusterMap, pfoVector, x0, pfoToPointingVertexMatrix))
 
  564             catch (
const pandora::StatusCodeException &)
 
  572         for (PfoVector::const_iterator iterI = pfoVector.begin(); iterI != pfoVector.end(); ++iterI)
 
  574             const ParticleFlowObject *
const pPfoI(*iterI);
 
  575             const LArTPC *
const pLArTPCI(pfoToLArTPCMap.at(pPfoI));
 
  577             for (PfoVector::const_iterator iterJ = std::next(iterI); iterJ != pfoVector.end(); ++iterJ)
 
  579                 const ParticleFlowObject *
const pPfoJ(*iterJ);
 
  580                 const LArTPC *
const pLArTPCJ(pfoToLArTPCMap.at(pPfoJ));
 
  585                 if (std::find(shiftedPfos.begin(), shiftedPfos.end(), pPfoI) == shiftedPfos.end())
 
  588                         this->
ShiftPfo(pAlgorithm, pPfoI, pPfoJ, x0, pfoToLArTPCMap, pfoToPointingVertexMatrix);
 
  590                     shiftedPfos.insert(pPfoI);
 
  593                 if (std::find(shiftedPfos.begin(), shiftedPfos.end(), pPfoJ) == shiftedPfos.end())
 
  596                         this->
ShiftPfo(pAlgorithm, pPfoJ, pPfoI, x0, pfoToLArTPCMap, pfoToPointingVertexMatrix);
 
  598                     shiftedPfos.insert(pPfoJ);
 
  604         for (
const ParticleFlowObject *
const pPfoToDelete : shiftedPfos)
 
  606             if (pPfoToDelete == pPfoToEnlarge)
 
  609             pAlgorithm->
StitchPfos(pPfoToEnlarge, pPfoToDelete, pfoToLArTPCMap);
 
  612         stitchedPfosToX0Map.insert(PfoToFloatMap::value_type(pPfoToEnlarge, x0));
 
  619     const ParticleFlowObject *
const pMatchedPfo, 
const float x0, 
const PfoToLArTPCMap &pfoToLArTPCMap,
 
  623     const PfoToPointingVertexMatrix::const_iterator pfoToPointingVertexMatrixIter(pfoToPointingVertexMatrix.find(pPfoToShift));
 
  626     const LArTPC *
const pShiftLArTPC(pfoToLArTPCMap.at(pPfoToShift));
 
  627     const LArTPC *
const pMatchedLArTPC(pfoToLArTPCMap.at(pMatchedPfo));
 
  631     float tpcBoundaryX(0.f);
 
  633     if (pShiftLArTPC->GetCenterX() < tpcBoundaryCenterX)
 
  635         tpcBoundaryX = pShiftLArTPC->GetCenterX() + (pShiftLArTPC->GetWidthX() / 2.f);
 
  639         tpcBoundaryX = pShiftLArTPC->GetCenterX() - (pShiftLArTPC->GetWidthX() / 2.f);
 
  642     const float positionShiftSign = stitchingVertex.GetPosition().GetX() < tpcBoundaryX ? 1.f : -1.f;
 
  645     object_creation::ParticleFlowObject::Metadata metadata;
 
  646     metadata.m_propertiesToAdd[
"X0"] = x0;
 
  649     PfoList downstreamPfoList;
 
  652     for (
const ParticleFlowObject *
const pHierarchyPfo : downstreamPfoList)
 
  653         PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*pAlgorithm, pHierarchyPfo, metadata));
 
  655     const float signedX0(std::fabs(x0) * positionShiftSign);
 
  665     float sumX(0.f), sumN(0.f);
 
  667     for (PfoVector::const_iterator iter1 = pfoVector.begin(), iterEnd = pfoVector.end(); iter1 != iterEnd; ++iter1)
 
  669         const ParticleFlowObject *
const pPfo1(*iter1);
 
  670         PfoToLArTPCMap::const_iterator tpcIter1 = pfoToLArTPCMap.find(pPfo1);
 
  671         ThreeDPointingClusterMap::const_iterator pointingIter1 = pointingClusterMap.find(pPfo1);
 
  673         if (pfoToLArTPCMap.end() == tpcIter1 || pointingClusterMap.end() == pointingIter1)
 
  674             throw StatusCodeException(STATUS_CODE_FAILURE);
 
  676         const LArTPC *
const pLArTPC1(tpcIter1->second);
 
  679         for (PfoVector::const_iterator iter2 = std::next(iter1); iter2 != iterEnd; ++iter2)
 
  681             const ParticleFlowObject *
const pPfo2(*iter2);
 
  682             PfoToLArTPCMap::const_iterator tpcIter2 = pfoToLArTPCMap.find(pPfo2);
 
  683             ThreeDPointingClusterMap::const_iterator pointingIter2 = pointingClusterMap.find(pPfo2);
 
  685             if (pfoToLArTPCMap.end() == tpcIter2 || pointingClusterMap.end() == pointingIter2)
 
  686                 throw StatusCodeException(STATUS_CODE_FAILURE);
 
  688             const LArTPC *
const pLArTPC2(tpcIter2->second);
 
  701                 const PfoToPointingVertexMatrix::iterator pfoToPointingVertexMatrixIter1(pfoToPointingVertexMatrix.find(pPfo1));
 
  702                 if (pfoToPointingVertexMatrixIter1 == pfoToPointingVertexMatrix.end())
 
  706                     (
void)pfoToPointingVertexMatrix.insert(PfoToPointingVertexMatrix::value_type(pPfo1, pfoToPointingVertexMap));
 
  712                     const PfoToPointingVertexMap::iterator pfoToPointingVertexMapIter(pfoToPointingVertexMap.find(pPfo2));
 
  713                     if (pfoToPointingVertexMapIter == pfoToPointingVertexMap.end())
 
  715                         (
void)pfoToPointingVertexMap.insert(PfoToPointingVertexMap::value_type(pPfo2, pointingVertex1));
 
  719                         if ((pfoToPointingVertexMapIter->second.GetPosition() - pointingVertex1.
GetPosition()).GetMagnitude() >
 
  720                             std::numeric_limits<float>::epsilon())
 
  721                             throw StatusCodeException(STATUS_CODE_FAILURE);
 
  726                 const PfoToPointingVertexMatrix::iterator pfoToPointingVertexMatrixIter2(pfoToPointingVertexMatrix.find(pPfo2));
 
  727                 if (pfoToPointingVertexMatrixIter2 == pfoToPointingVertexMatrix.end())
 
  731                     (
void)pfoToPointingVertexMatrix.insert(PfoToPointingVertexMatrix::value_type(pPfo2, pfoToPointingVertexMap));
 
  737                     const PfoToPointingVertexMap::iterator pfoToPointingVertexMapIter(pfoToPointingVertexMap.find(pPfo1));
 
  738                     if (pfoToPointingVertexMapIter == pfoToPointingVertexMap.end())
 
  740                         (
void)pfoToPointingVertexMap.insert(PfoToPointingVertexMap::value_type(pPfo1, pointingVertex2));
 
  744                         if ((pfoToPointingVertexMapIter->second.GetPosition() - pointingVertex2.
GetPosition()).GetMagnitude() >
 
  745                             std::numeric_limits<float>::epsilon())
 
  746                             throw StatusCodeException(STATUS_CODE_FAILURE);
 
  751                 const bool isCPAStitch(pLArTPC1->GetCenterX() < tpcBoundaryCenterX ? !pLArTPC1->IsDriftInPositiveX() : !pLArTPC2->IsDriftInPositiveX());
 
  754                 thisX0 *= isCPAStitch ? -1.f : 1.f;
 
  757                 if ((sumN > std::numeric_limits<float>::epsilon()) && (sumX > std::numeric_limits<float>::epsilon()))
 
  759                     const float fractionalDiff(std::fabs((sumX - (thisX0 * sumN)) / sumX));
 
  768             catch (
const pandora::StatusCodeException &statusCodeException)
 
  770                 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
 
  771                     std::cout << 
"StitchingCosmicRayMergingTool: Attempting to stitch a pfo with multiple vertices for the same match" << std::endl;
 
  776     if ((sumN < std::numeric_limits<float>::epsilon()) || (std::fabs(sumX) < std::numeric_limits<float>::epsilon()))
 
  777         throw StatusCodeException(STATUS_CODE_NOT_FOUND);
 
  789     m_daughter(daughter),
 
  820     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  821         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"ThreeDStitchingMode", 
m_useXcoordinate));
 
  823     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
 
  826     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  827         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"HalfWindowLayers", 
m_halfWindowLayers));
 
  830     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MinPfoLength", minLength));
 
  833     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  834         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MinCosRelativeAngle", 
m_minCosRelativeAngle));
 
  836     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
 
  839     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
 
  842     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
 
  845     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
 
  848     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
 
  851     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MinNCaloHits3D", 
m_minNCaloHits3D));
 
  853     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
 
  856     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  857         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"BoundaryToleranceWidth", 
m_boundaryToleranceWidth));
 
  859     return STATUS_CODE_SUCCESS;
 
std::unordered_map< const pandora::ParticleFlowObject *, float > PfoToFloatMap
void SelectPrimaryPfos(const pandora::PfoList *pInputPfoList, const PfoToLArTPCMap &pfoToLArTPCMap, pandora::PfoList &outputPfoList) const 
Select primary Pfos from the input list of Pfos. 
std::unordered_map< const pandora::ParticleFlowObject *, PfoToPointingVertexMap > PfoToPointingVertexMatrix
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits. 
Header file for the pfo helper class. 
static float CalculateX0(const pandora::LArTPC &firstTPC, const pandora::LArTPC &secondTPC, const LArPointingCluster::Vertex &firstVertex, const LArPointingCluster::Vertex &secondVertex)
Calculate X0 for a pair of vertices. 
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
PfoAssociation(const VertexType parent, const VertexType daughter, const float fom)
Constructor. 
void CollectAssociatedPfos(const pandora::ParticleFlowObject *const pSeedPfo, const pandora::ParticleFlowObject *const pCurrentPfo, const PfoMergeMap &pfoMerges, const pandora::PfoSet &vetoSet, pandora::PfoList &associatedList) const 
Collect up associations between Pfos. 
unsigned int m_minNCaloHits3D
static void GetImpactParametersInYZ(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices using yz-coordinates. 
static void GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices. 
std::size_t size(FixedBins< T, C > const &) noexcept
bool CalculateX0(const PfoToLArTPCMap &pfoToLArTPCMap, const ThreeDPointingClusterMap &pointingClusterMap, const pandora::PfoVector &pfoVector, float &x0, PfoToPointingVertexMatrix &pfoToPointingVertexMatrix) const 
Calculate x0 shift for a group of associated Pfos. 
LArPointingCluster class. 
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID. 
float m_relaxCosRelativeAngle
void CreatePfoMatches(const LArTPCToPfoMap &larTPCToPfoMap, const ThreeDPointingClusterMap &pointingClusterMap, PfoAssociationMatrix &pfoAssociationMatrix) const 
Create associations between Pfos using 3D pointing clusters. 
std::unordered_map< const pandora::ParticleFlowObject *, pandora::PfoList > PfoMergeMap
std::unordered_map< const pandora::ParticleFlowObject *, PfoAssociationMap > PfoAssociationMatrix
void BuildTPCMaps(const pandora::PfoList &inputPfoList, const PfoToLArTPCMap &pfoToLArTPCMap, LArTPCToPfoMap &larTPCToPfoMap) const 
Build a list of Pfos for each tpc. 
float m_boundaryToleranceWidth
The distance from the APA/CPA boundary inside which the deviation consideration is ignored...
VertexType
Vertex enumeration. 
VertexType GetDaughter() const 
Get daughter. 
float m_relaxTransverseDisplacement
void OrderPfoMerges(const PfoToLArTPCMap &pfoToLArTPCMap, const ThreeDPointingClusterMap &pointingClusterMap, const PfoMergeMap &inputPfoMerges, PfoMergeMap &outputPfoMerges) const 
Identify the vertex Pfo and then re-order the map of merges so that the vertex Pfo will be enlarged...
static bool IsInGap(const pandora::Pandora &pandora, const pandora::CartesianVector &testPoint2D, const pandora::HitType hitType, const float gapTolerance=0.f)
Whether a 2D test point lies in a registered gap with the associated hit type. 
float m_maxX0FractionalDeviation
The maximum allowed fractional difference of an X0 contribution for matches to be stitched...
bool m_alwaysApplyT0Calculation
void ShiftPfo(const MasterAlgorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pPfoToShift, const pandora::ParticleFlowObject *const pMatchedPfo, const float x0, const PfoToLArTPCMap &pfoToLArTPCMap, const PfoToPointingVertexMatrix &pfoToPointingVertexMatrix) const 
Shift a pfo given its pfo stitching pair. 
Header file for the geometry helper class. 
float m_minCosRelativeAngle
static bool CanTPCsBeStitched(const pandora::LArTPC &firstTPC, const pandora::LArTPC &secondTPC)
Whether particles from a given pair of tpcs can be stitched together. 
const Vertex & GetOuterVertex() const 
Get the outer vertex. 
float m_maxTransverseDisplacement
static float GetTPCDisplacement(const pandora::LArTPC &firstTPC, const pandora::LArTPC &secondTPC)
Calculate distance between central positions of a pair of tpcs. 
static float GetTPCBoundaryCenterX(const pandora::LArTPC &firstTPC, const pandora::LArTPC &secondTPC)
Determine centre in X at the boundary between a pair of tpcs. 
const Vertex & GetInnerVertex() const 
Get the inner vertex. 
void ShiftPfoHierarchy(const pandora::ParticleFlowObject *const pParentPfo, const PfoToLArTPCMap &pfoToLArTPCMap, const float x0) const 
Shift a Pfo hierarchy by a specified x0 value. 
void StitchPfos(const pandora::ParticleFlowObject *const pPfoToEnlarge, const pandora::ParticleFlowObject *const pPfoToDelete, PfoToLArTPCMap &pfoToLArTPCMap) const 
Stitch together a pair of pfos. 
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo. 
static float GetTPCBoundaryWidthX(const pandora::LArTPC &firstTPC, const pandora::LArTPC &secondTPC)
Determine width in X at the boundary between a pair of tpcs. 
void StitchPfos(const MasterAlgorithm *const pAlgorithm, const ThreeDPointingClusterMap &pointingClusterMap, const PfoMergeMap &pfoMerges, PfoToLArTPCMap &pfoToLArTPCMap, PfoToFloatMap &stitchedPfosToX0Map) const 
Apply X0 corrections, and then stitch together Pfos. 
Header file for the lar three dimensional sliding fit result class. 
const pandora::CartesianVector & GetDirection() const 
Get the vertex direction. 
auto begin(FixedBins< T, C > const &) noexcept
void BuildPointingClusterMaps(const pandora::PfoList &inputPfoList, const PfoToLArTPCMap &pfoToLArTPCMap, ThreeDPointingClusterMap &pointingClusterMap) const 
Build a 3D pointing cluster for each Pfo. 
std::unordered_map< const pandora::ParticleFlowObject *, const pandora::LArTPC * > PfoToLArTPCMap
Header file for the helper class for multiple drift volumes. 
float m_maxLongitudinalDisplacementX
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
void SelectPfoMatches(const PfoAssociationMatrix &pfoAssociationMatrix, PfoMergeMap &pfoSelectedMatches) const 
Select the best associations between Pfos; create a mapping between associated Pfos, handling any ambiguities. 
std::unordered_map< const pandora::ParticleFlowObject *, LArPointingCluster::Vertex > PfoToPointingVertexMap
static bool IsFinalState(const pandora::ParticleFlowObject *const pPfo)
Whether a pfo is a primary parent particle. 
std::unordered_map< const pandora::ParticleFlowObject *, PfoAssociation > PfoAssociationMap
ThreeDSlidingFitResult class. 
float m_relaxMinLongitudinalDisplacement
The minimum value of the longitudinal impact parameter for association if both verticies fall in the ...
static void GetAllDownstreamPfos(const pandora::PfoList &inputPfoList, pandora::PfoList &outputPfoList)
Get a flat list of all pfos, recursively, of all daughters associated with those pfos in an input lis...
VertexType GetParent() const 
Get parent. 
void Run(const MasterAlgorithm *const pAlgorithm, const pandora::PfoList *const pMultiPfoList, PfoToLArTPCMap &pfoToLArTPCMap, PfoToFloatMap &stitchedPfosToX0Map)
Run the algorithm tool. 
static bool SortTPCs(const pandora::LArTPC *const pLhs, const pandora::LArTPC *const pRhs)
Sort tpcs by central positions. 
std::unordered_map< const pandora::LArTPC *, pandora::PfoList > LArTPCToPfoMap
bool IsInnerVertex() const 
Is this the inner vertex. 
float GetFigureOfMerit() const 
Get figure of merit. 
void SelectPfoMerges(const PfoMergeMap &pfoMatches, PfoMergeMap &pfoMerges) const 
Create an initial map of Pfo merges to be made. 
static void GetClosestVertices(const pandora::LArTPC &larTPC1, const pandora::LArTPC &larTPC2, const LArPointingCluster &pointingCluster1, const LArPointingCluster &pointingCluster2, LArPointingCluster::Vertex &closestVertex1, LArPointingCluster::Vertex &closestVertex2)
Given a pair of pointing clusters, find the pair of vertices with smallest yz-separation. 
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. 
const pandora::CartesianVector & GetPosition() const 
Get the vertex position. 
BEGIN_PROLOG don t mess with this pandoraTrackGausCryoW true
BEGIN_PROLOG could also be cout
std::unordered_map< const pandora::ParticleFlowObject *, LArPointingCluster > ThreeDPointingClusterMap