9 #include "Pandora/AlgorithmHeaders.h" 
   20 TrackClusterCreationAlgorithm::TrackClusterCreationAlgorithm() :
 
   21     m_mergeBackFilteredHits(
true),
 
   23     m_maxCaloHitSeparationSquared(1.3f * 1.3f),
 
   24     m_minCaloHitSeparationSquared(0.4f * 0.4f),
 
   25     m_closeSeparationSquared(0.9f * 0.9f)
 
   33     const CaloHitList *pCaloHitList = NULL;
 
   34     PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pCaloHitList));
 
   36     OrderedCaloHitList selectedCaloHitList, rejectedCaloHitList;
 
   37     PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->
FilterCaloHits(pCaloHitList, selectedCaloHitList, rejectedCaloHitList));
 
   45     this->
IdentifyJoins(selectedCaloHitList, forwardHitAssociationMap, backwardHitAssociationMap, hitJoinMap);
 
   46     this->
CreateClusters(selectedCaloHitList, hitJoinMap, hitToClusterMap);
 
   49         this->
CreateClusters(rejectedCaloHitList, hitJoinMap, hitToClusterMap);
 
   51     PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->
AddFilteredCaloHits(selectedCaloHitList, rejectedCaloHitList, hitToClusterMap));
 
   53     return STATUS_CODE_SUCCESS;
 
   59     const CaloHitList *
const pCaloHitList, OrderedCaloHitList &selectedCaloHitList, OrderedCaloHitList &rejectedCaloHitList)
 const 
   61     CaloHitList availableHitList;
 
   63     for (
const CaloHit *
const pCaloHit : *pCaloHitList)
 
   65         if (PandoraContentApi::IsAvailable(*
this, pCaloHit))
 
   66             availableHitList.push_back(pCaloHit);
 
   69     if (availableHitList.empty())
 
   70         return STATUS_CODE_SUCCESS;
 
   72     PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, selectedCaloHitList.Add(availableHitList));
 
   74     for (OrderedCaloHitList::const_iterator iter = selectedCaloHitList.begin(), iterEnd = selectedCaloHitList.end(); iter != iterEnd; ++iter)
 
   76         CaloHitVector caloHits(iter->second->begin(), iter->second->end());
 
   79         for (
const CaloHit *
const pCaloHitI : caloHits)
 
   81             bool useCaloHit(
true);
 
   83             for (
const CaloHit *
const pCaloHitJ : caloHits)
 
   85                 if (pCaloHitI == pCaloHitJ)
 
   88                 if ((pCaloHitI->GetMipEquivalentEnergy() < pCaloHitJ->GetMipEquivalentEnergy()) &&
 
   97                 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, rejectedCaloHitList.Add(pCaloHitI));
 
  101     PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, selectedCaloHitList.Remove(rejectedCaloHitList));
 
  102     return STATUS_CODE_SUCCESS;
 
  108     const OrderedCaloHitList &selectedCaloHitList, 
const OrderedCaloHitList &rejectedCaloHitList, 
HitToClusterMap &hitToClusterMap)
 const 
  110     for (OrderedCaloHitList::const_iterator iter = rejectedCaloHitList.begin(), iterEnd = rejectedCaloHitList.end(); iter != iterEnd; ++iter)
 
  112         CaloHitList *pCaloHitList = NULL;
 
  113         PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, selectedCaloHitList.GetCaloHitsInPseudoLayer(iter->first, pCaloHitList));
 
  115         CaloHitSet unavailableHits;
 
  117         CaloHitVector inputAvailableHits(iter->second->begin(), iter->second->end());
 
  120         CaloHitVector clusteredHits(pCaloHitList->begin(), pCaloHitList->end());
 
  128             CaloHitVector newClusteredHits;
 
  130             for (
const CaloHit *
const pCaloHitI : inputAvailableHits)
 
  132                 if (unavailableHits.count(pCaloHitI))
 
  135                 if (hitToClusterMap.end() != hitToClusterMap.find(pCaloHitI))
 
  138                 const CaloHit *pClosestHit = NULL;
 
  141                 for (
const CaloHit *
const pCaloHitJ : clusteredHits)
 
  143                     if (pCaloHitI->GetMipEquivalentEnergy() > pCaloHitJ->GetMipEquivalentEnergy())
 
  146                     const float separationSquared((pCaloHitI->GetPositionVector() - pCaloHitJ->GetPositionVector()).GetMagnitudeSquared());
 
  148                     if (separationSquared < closestSeparationSquared)
 
  150                         closestSeparationSquared = separationSquared;
 
  151                         pClosestHit = pCaloHitJ;
 
  158                 HitToClusterMap::const_iterator mapIter = hitToClusterMap.find(pClosestHit);
 
  160                 if (hitToClusterMap.end() == mapIter)
 
  161                     throw StatusCodeException(STATUS_CODE_FAILURE);
 
  163                 const Cluster *
const pCluster = mapIter->second;
 
  164                 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pCluster, pCaloHitI));
 
  165                 (
void)hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHitI, pCluster));
 
  167                 newClusteredHits.push_back(pCaloHitI);
 
  171             for (
const CaloHit *
const pCaloHit : newClusteredHits)
 
  173                 clusteredHits.push_back(pCaloHit);
 
  174                 unavailableHits.insert(pCaloHit);
 
  179     return STATUS_CODE_SUCCESS;
 
  187     for (OrderedCaloHitList::const_iterator iterI = orderedCaloHitList.begin(), iterIEnd = orderedCaloHitList.end(); iterI != iterIEnd; ++iterI)
 
  189         unsigned int nLayersConsidered(0);
 
  191         CaloHitVector caloHitsI(iterI->second->begin(), iterI->second->end());
 
  194         for (OrderedCaloHitList::const_iterator iterJ = iterI, iterJEnd = orderedCaloHitList.end();
 
  195              (nLayersConsidered++ <= 
m_maxGapLayers + 1) && (iterJ != iterJEnd); ++iterJ)
 
  197             if (iterJ->first == iterI->first || iterJ->first > iterI->first + 
m_maxGapLayers + 1)
 
  200             CaloHitVector caloHitsJ(iterJ->second->begin(), iterJ->second->end());
 
  203             for (
const CaloHit *
const pCaloHitI : caloHitsI)
 
  205                 for (
const CaloHit *
const pCaloHitJ : caloHitsJ)
 
  217     for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
 
  219         CaloHitVector caloHits(iter->second->begin(), iter->second->end());
 
  222         for (
const CaloHit *
const pCaloHit : caloHits)
 
  224             HitAssociationMap::const_iterator fwdIter = forwardHitAssociationMap.find(pCaloHit);
 
  225             const CaloHit *
const pForwardHit((forwardHitAssociationMap.end() == fwdIter) ? NULL : fwdIter->second.GetPrimaryTarget());
 
  227             HitAssociationMap::const_iterator fwdCheckIter = backwardHitAssociationMap.find(pForwardHit);
 
  228             const CaloHit *
const pForwardHitCheck((backwardHitAssociationMap.end() == fwdCheckIter) ? NULL : fwdCheckIter->second.GetPrimaryTarget());
 
  230             if ((NULL != pForwardHit) && (pForwardHitCheck != pCaloHit))
 
  233             HitAssociationMap::const_iterator bwdIter = backwardHitAssociationMap.find(pCaloHit);
 
  234             const CaloHit *
const pBackwardHit((backwardHitAssociationMap.end() == bwdIter) ? NULL : bwdIter->second.GetPrimaryTarget());
 
  236             HitAssociationMap::const_iterator bwdCheckIter = forwardHitAssociationMap.find(pBackwardHit);
 
  237             const CaloHit *
const pBackwardHitCheck((forwardHitAssociationMap.end() == bwdCheckIter) ? NULL : bwdCheckIter->second.GetPrimaryTarget());
 
  239             if ((NULL != pBackwardHit) && (pBackwardHitCheck != pCaloHit))
 
  250     for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
 
  252         CaloHitVector caloHits(iter->second->begin(), iter->second->end());
 
  255         for (
const CaloHit *
const pCaloHit : caloHits)
 
  257             const CaloHit *
const pForwardJoinHit = this->
GetJoinHit(pCaloHit, forwardHitAssociationMap, backwardHitAssociationMap);
 
  258             const CaloHit *
const pBackwardJoinHit = this->
GetJoinHit(pForwardJoinHit, backwardHitAssociationMap, forwardHitAssociationMap);
 
  260             if ((NULL == pForwardJoinHit) || (NULL == pBackwardJoinHit) || (pBackwardJoinHit != pCaloHit))
 
  263             HitJoinMap::const_iterator joinIter = hitJoinMap.find(pCaloHit);
 
  265             if (hitJoinMap.end() == joinIter)
 
  266                 hitJoinMap.insert(HitJoinMap::value_type(pCaloHit, pForwardJoinHit));
 
  268             if ((hitJoinMap.end() != joinIter) && (joinIter->second != pForwardJoinHit))
 
  269                 throw StatusCodeException(STATUS_CODE_FAILURE);
 
  279     for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
 
  281         CaloHitVector caloHits(iter->second->begin(), iter->second->end());
 
  284         for (
const CaloHit *
const pCaloHit : caloHits)
 
  286             const Cluster *pCluster = NULL;
 
  288             HitToClusterMap::const_iterator mapIter = hitToClusterMap.find(pCaloHit);
 
  290             if (hitToClusterMap.end() == mapIter)
 
  293                 parameters.m_caloHitList.push_back(pCaloHit);
 
  294                 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, parameters, pCluster));
 
  295                 hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
 
  299                 pCluster = mapIter->second;
 
  302             HitJoinMap::const_iterator joinIter = hitJoinMap.find(pCaloHit);
 
  304             if (hitJoinMap.end() == joinIter)
 
  307             if (hitToClusterMap.end() != hitToClusterMap.find(joinIter->second))
 
  308                 throw StatusCodeException(STATUS_CODE_FAILURE);
 
  310             PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pCluster, joinIter->second));
 
  311             hitToClusterMap.insert(HitToClusterMap::value_type(joinIter->second, pCluster));
 
  321     const float distanceSquared((pCaloHitJ->GetPositionVector() - pCaloHitI->GetPositionVector()).GetMagnitudeSquared());
 
  326     HitAssociationMap::iterator forwardIter = forwardHitAssociationMap.find(pCaloHitI);
 
  328     if (forwardHitAssociationMap.end() == forwardIter)
 
  330         forwardHitAssociationMap.insert(HitAssociationMap::value_type(pCaloHitI, 
HitAssociation(pCaloHitJ, distanceSquared)));
 
  332     else if (distanceSquared < forwardIter->
second.GetPrimaryDistanceSquared())
 
  337     HitAssociationMap::iterator backwardIter = backwardHitAssociationMap.find(pCaloHitJ);
 
  339     if (backwardHitAssociationMap.end() == backwardIter)
 
  341         backwardHitAssociationMap.insert(HitAssociationMap::value_type(pCaloHitJ, 
HitAssociation(pCaloHitI, distanceSquared)));
 
  343     else if (distanceSquared < backwardIter->
second.GetPrimaryDistanceSquared())
 
  345         backwardIter->second = 
HitAssociation(pCaloHitI, distanceSquared);
 
  354     HitAssociationMap::iterator forwardIter = forwardHitAssociationMap.find(pCaloHitI);
 
  355     HitAssociationMap::iterator backwardIter = backwardHitAssociationMap.find(pCaloHitJ);
 
  357     if ((forwardHitAssociationMap.end() == forwardIter) || (backwardHitAssociationMap.end() == backwardIter))
 
  387     HitAssociationMap::const_iterator iterI = hitAssociationMapI.find(pCaloHit);
 
  389     if (hitAssociationMapI.end() == iterI)
 
  392     const CaloHit *
const pPrimaryTarget = iterI->second.GetPrimaryTarget();
 
  393     const CaloHit *
const pSecondaryTarget = iterI->second.GetSecondaryTarget();
 
  395     if (NULL == pSecondaryTarget)
 
  396         return pPrimaryTarget;
 
  398     unsigned int primaryNSteps(0), secondaryNSteps(0);
 
  399     const CaloHit *
const pPrimaryTrace = this->
TraceHitAssociation(pPrimaryTarget, hitAssociationMapI, hitAssociationMapJ, primaryNSteps);
 
  400     const CaloHit *
const pSecondaryTrace = this->
TraceHitAssociation(pSecondaryTarget, hitAssociationMapI, hitAssociationMapJ, secondaryNSteps);
 
  402     if ((pPrimaryTrace == pSecondaryTrace) || (secondaryNSteps < 5))
 
  403         return pPrimaryTarget;
 
  414     const CaloHit *pThisHit = pCaloHit;
 
  415     const CaloHit *pLastHit = pCaloHit;
 
  421         HitAssociationMap::const_iterator iterI = hitAssociationMapI.find(pThisHit);
 
  423         if (hitAssociationMapI.end() == iterI)
 
  426         pLastHit = iterI->second.GetPrimaryTarget();
 
  427         HitAssociationMap::const_iterator iterJ = hitAssociationMapJ.find(pLastHit);
 
  429         if (hitAssociationMapJ.end() == iterJ)
 
  432         if (iterJ->second.GetPrimaryTarget() != pThisHit)
 
  443     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  444         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MergeBackFilteredHits", 
m_mergeBackFilteredHits));
 
  446     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MaxGapLayers", 
m_maxGapLayers));
 
  449     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  450         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MaxCaloHitSeparation", maxCaloHitSeparation));
 
  454     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  455         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MinCaloHitSeparation", minCaloHitSeparation));
 
  459     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"CloseSeparation", closeSeparation));
 
  462     return STATUS_CODE_SUCCESS;
 
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
pandora::StatusCode FilterCaloHits(const pandora::CaloHitList *const pCaloHitList, pandora::OrderedCaloHitList &selectedCaloHitList, pandora::OrderedCaloHitList &rejectedCaloHitList) const 
Filter out low pulse height hits in close proximity to high pulse height hits. 
float m_maxCaloHitSeparationSquared
Square of maximum calo hit separation. 
pandora::StatusCode AddFilteredCaloHits(const pandora::OrderedCaloHitList &selectedCaloHitList, const pandora::OrderedCaloHitList &rejectedCaloHitList, HitToClusterMap &hitToClusterMap) const 
Merge previously filtered hits back into their associated clusters. 
void IdentifyJoins(const pandora::OrderedCaloHitList &orderedCaloHitList, const HitAssociationMap &forwardHitAssociationMap, const HitAssociationMap &backwardHitAssociationMap, HitJoinMap &hitJoinMap) const 
Identify final hit joins for use in cluster formation. 
pandora::StatusCode Run()
float GetSecondaryDistanceSquared() const 
Get the secondary distance squared. 
Header file for the cluster creation algorithm class. 
std::unordered_map< const pandora::CaloHit *, HitAssociation > HitAssociationMap
void MakePrimaryAssociations(const pandora::OrderedCaloHitList &orderedCaloHitList, HitAssociationMap &forwardHitAssociationMap, HitAssociationMap &backwardHitAssociationMap) const 
Control primary association formation. 
static bool SortHitsByPosition(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their position (use Z, followed by X, followed by Y) 
Header file for the cluster helper class. 
const pandora::CaloHit * GetPrimaryTarget() const 
Get the primary target. 
std::unordered_map< const pandora::CaloHit *, const pandora::CaloHit * > HitJoinMap
float GetPrimaryDistanceSquared() const 
Get the primary distance squared. 
void SetSecondaryTarget(const pandora::CaloHit *const pSecondaryTarget, const float secondaryDistanceSquared)
Set secondary target. 
void CreateClusters(const pandora::OrderedCaloHitList &orderedCaloHitList, const HitJoinMap &hitJoinMap, HitToClusterMap &hitToClusterMap) const 
Final cluster formation. 
void CreatePrimaryAssociation(const pandora::CaloHit *const pCaloHitI, const pandora::CaloHit *const pCaloHitJ, HitAssociationMap &forwardHitAssociationMap, HitAssociationMap &backwardHitAssociationMap) const 
Create primary association if appropriate, hitI<->hitJ. 
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
fhicl::Table< sbnd::crt::CRTDetSimParams > Parameters
unsigned int m_maxGapLayers
Maximum number of layers for a gap. 
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
const pandora::CaloHit * GetJoinHit(const pandora::CaloHit *const pCaloHit, const HitAssociationMap &hitAssociationMapI, const HitAssociationMap &hitAssociationMapJ) const 
Get hit to join by tracing associations via map I, checking via map J. 
bool m_mergeBackFilteredHits
Merge rejected hits into their associated clusters. 
void MakeSecondaryAssociations(const pandora::OrderedCaloHitList &orderedCaloHitList, HitAssociationMap &forwardHitAssociationMap, HitAssociationMap &backwardHitAssociationMap) const 
Control secondary association formation. 
void CreateSecondaryAssociation(const pandora::CaloHit *const pCaloHitI, const pandora::CaloHit *const pCaloHitJ, HitAssociationMap &forwardHitAssociationMap, HitAssociationMap &backwardHitAssociationMap) const 
Create secondary association if appropriate, hitI<->hitJ. 
float m_minCaloHitSeparationSquared
Square of minimum calo hit separation. 
BEGIN_PROLOG don t mess with this pandoraTrackGausCryoW true
float m_closeSeparationSquared
Length scale (squared) for close hit separation. 
const pandora::CaloHit * TraceHitAssociation(const pandora::CaloHit *const pCaloHit, const HitAssociationMap &hitAssociationMapI, const HitAssociationMap &hitAssociationMapJ, unsigned int &nSteps) const 
Get last hit obtained by tracing associations via map I, checking via map J.