9 #include "Pandora/AlgorithmHeaders.h" 25 MissingTrackSegmentTool::MissingTrackSegmentTool() :
26 m_minMatchedFraction(0.9
f),
27 m_minMatchedSamplingPoints(10),
28 m_minMatchedSamplingPointRatio(2),
29 m_minInitialXOverlapFraction(0.75
f),
30 m_minFinalXOverlapFraction(0.75
f),
31 m_minCaloHitsInCandidateCluster(5),
33 m_makePfoMinSamplingPoints(5),
34 m_makePfoMinMatchedSamplingPoints(5),
35 m_makePfoMinMatchedFraction(0.8
f),
36 m_makePfoMaxImpactParameter(3.
f),
37 m_mergeMaxChi2PerSamplingPoint(0.25
f),
38 m_mergeXContainmentTolerance(1.
f)
46 if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
47 std::cout <<
"----> Running Algorithm Tool: " << this->GetInstanceName() <<
", " << this->GetType() << std::endl;
51 this->
FindTracks(pAlgorithm, overlapTensor, protoParticleVector, clusterMergeMap);
56 return (particlesMade || mergesMade);
64 ClusterSet usedClusters;
68 for (
const Cluster *
const pKeyCluster : sortedKeyClusters)
70 if (!pKeyCluster->IsAvailable())
73 unsigned int nU(0), nV(0), nW(0);
92 protoParticle.
m_clusterList.push_back((*iIter)->GetClusterU());
93 protoParticle.
m_clusterList.push_back((*iIter)->GetClusterV());
94 protoParticle.
m_clusterList.push_back((*iIter)->GetClusterW());
95 protoParticleVector.push_back(protoParticle);
97 usedClusters.insert((*iIter)->GetClusterU());
98 usedClusters.insert((*iIter)->GetClusterV());
99 usedClusters.insert((*iIter)->GetClusterW());
111 if (usedClusters.count(eIter->GetClusterU()) || usedClusters.count(eIter->GetClusterV()) || usedClusters.count(eIter->GetClusterW()))
120 const XOverlap &xOverlap(eIter->GetOverlapResult().GetXOverlap());
121 const float shortSpan(std::min(xOverlap.GetXSpanU(), std::min(xOverlap.GetXSpanV(), xOverlap.GetXSpanW())));
122 const float longSpan1(std::max(xOverlap.GetXSpanU(), std::max(xOverlap.GetXSpanV(), xOverlap.GetXSpanW())));
123 const float longSpan2(((xOverlap.GetXSpanU() > shortSpan) && (xOverlap.GetXSpanU() < longSpan1)) ? xOverlap.GetXSpanU()
124 : ((xOverlap.GetXSpanV() > shortSpan) && (xOverlap.GetXSpanV() < longSpan1)) ? xOverlap.GetXSpanV()
125 : xOverlap.GetXSpanW());
127 if ((xOverlap.GetXOverlapSpan() < std::numeric_limits<float>::epsilon()) || (longSpan1 < std::numeric_limits<float>::epsilon()))
133 iteratorList.push_back(eIter);
146 ClusterList candidateClusters;
149 if (candidateClusters.empty())
155 if (slidingFitResultMap.empty())
161 if (segmentOverlapMap.empty())
164 return this->
MakeDecisions(particle, slidingFitResultMap, segmentOverlapMap, usedClusters, clusterMergeMap);
166 catch (StatusCodeException &)
181 const Cluster *
const pCluster(*iter);
189 candidateClusters.push_back(pCluster);
198 for (
ClusterList::const_iterator iter = candidateClusterList.begin(), iterEnd = candidateClusterList.end(); iter != iterEnd; ++iter)
200 const Cluster *
const pCluster(*iter);
205 (void)slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(pCluster, slidingFitResult));
208 catch (StatusCodeException &)
216 (void)slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(pCluster, slidingFitResult));
219 catch (StatusCodeException &)
233 const float nPoints1(std::fabs(static_cast<float>(fitResult1.GetMaxLayer() - fitResult1.GetMinLayer())));
234 const float nPoints2(std::fabs(static_cast<float>(fitResult2.GetMaxLayer() - fitResult2.GetMinLayer())));
236 const unsigned int nPoints(static_cast<unsigned int>(1.
f + (nPoints1 + nPoints2) / 2.
f));
238 ClusterList clusterList;
239 for (
const auto &mapEntry : slidingFitResultMap)
240 clusterList.push_back(mapEntry.first);
243 for (
unsigned n = 0;
n <= nPoints; ++
n)
250 CartesianVector fitVector1(0.
f, 0.
f, 0.
f), fitVector2(0.
f, 0.
f, 0.
f);
252 if ((STATUS_CODE_SUCCESS != fitResult1.GetGlobalFitPositionAtX(x, fitVector1)) ||
253 (STATUS_CODE_SUCCESS != fitResult2.GetGlobalFitPositionAtX(x, fitVector2)))
259 this->GetPandora(), particle.
m_hitType1, particle.
m_hitType2, fitVector1.GetZ(), fitVector2.GetZ()));
261 for (
const Cluster *
const pCluster : clusterList)
264 CartesianVector fitVector(0.
f, 0.
f, 0.
f), fitDirection(0.
f, 0.
f, 0.
f);
266 if ((STATUS_CODE_SUCCESS != slidingFitResult.GetGlobalFitPositionAtX(x, fitVector)) ||
267 (STATUS_CODE_SUCCESS != slidingFitResult.GetGlobalFitDirectionAtX(x, fitDirection)))
272 const float delta((prediction - fitVector.GetZ()) * fitDirection.GetX());
273 const float pseudoChi2(delta * delta);
296 bool matchesACluster(
false);
299 for (
const auto &mapEntry : segmentOverlapMap)
300 sortedClusters.push_back(mapEntry.first);
303 for (
const Cluster *
const pCluster : sortedClusters)
305 const SegmentOverlap &segmentOverlap(segmentOverlapMap.at(pCluster));
310 shortMinX = std::min(segmentOverlap.m_matchedSamplingMinX, shortMinX);
311 shortMaxX = std::max(segmentOverlap.m_matchedSamplingMaxX, shortMaxX);
312 matchesACluster =
true;
315 if (!usedClusters.insert(pCluster).second || !pCluster->IsAvailable())
318 if (!this->
IsPossibleMerge(pCluster, particle, segmentOverlap, slidingFitResultMap))
321 possibleMerges.push_back(pCluster);
324 if (std::fabs(particle.
m_longMaxX - particle.
m_longMinX) < std::numeric_limits<float>::epsilon())
325 throw StatusCodeException(STATUS_CODE_FAILURE);
327 if (!matchesACluster || possibleMerges.empty())
334 clusterList.insert(clusterList.end(), possibleMerges.begin(), possibleMerges.end());
364 if (slidingFitResultMap.end() == fitIter)
365 throw StatusCodeException(STATUS_CODE_FAILURE);
367 float mergeMinX(std::numeric_limits<float>::max()), mergeMaxX(-std::numeric_limits<float>::max());
368 fitIter->second.GetMinAndMaxX(mergeMinX, mergeMaxX);
386 const XOverlap &xOverlap(element.GetOverlapResult().GetXOverlap());
388 m_shortHitType = ((xOverlap.GetXSpanU() < xOverlap.GetXSpanV()) && (xOverlap.GetXSpanU() < xOverlap.GetXSpanW())) ? TPC_VIEW_U
389 : ((xOverlap.GetXSpanV() < xOverlap.GetXSpanU()) && (xOverlap.GetXSpanV() < xOverlap.GetXSpanW())) ? TPC_VIEW_V
390 : ((xOverlap.GetXSpanW() < xOverlap.GetXSpanU()) && (xOverlap.GetXSpanW() < xOverlap.GetXSpanV())) ? TPC_VIEW_W
393 if (HIT_CUSTOM == m_shortHitType)
394 throw StatusCodeException(STATUS_CODE_FAILURE);
396 m_pShortCluster = (TPC_VIEW_U == m_shortHitType) ? element.GetClusterU()
397 : (TPC_VIEW_V == m_shortHitType) ? element.GetClusterV()
398 : element.GetClusterW();
399 m_pCluster1 = (TPC_VIEW_U == m_shortHitType) ? element.GetClusterV() : element.GetClusterU();
400 m_pCluster2 = (TPC_VIEW_W == m_shortHitType) ? element.GetClusterV() : element.GetClusterW();
401 m_shortMinX = (TPC_VIEW_U == m_shortHitType) ? xOverlap.GetUMinX()
402 : (TPC_VIEW_V == m_shortHitType) ? xOverlap.GetVMinX()
403 : xOverlap.GetWMinX();
404 m_shortMaxX = (TPC_VIEW_U == m_shortHitType) ? xOverlap.GetUMaxX()
405 : (TPC_VIEW_V == m_shortHitType) ? xOverlap.GetVMaxX()
406 : xOverlap.GetWMaxX();
407 m_longMinX = (TPC_VIEW_U == m_shortHitType) ? std::min(xOverlap.GetVMinX(), xOverlap.GetWMinX())
408 : (TPC_VIEW_V == m_shortHitType) ? std::min(xOverlap.GetUMinX(), xOverlap.GetWMinX())
409 : std::min(xOverlap.GetUMinX(), xOverlap.GetVMinX());
410 m_longMaxX = (TPC_VIEW_U == m_shortHitType) ? std::max(xOverlap.GetVMaxX(), xOverlap.GetWMaxX())
411 : (TPC_VIEW_V == m_shortHitType) ? std::max(xOverlap.GetUMaxX(), xOverlap.GetWMaxX())
412 : std::max(xOverlap.GetUMaxX(), xOverlap.GetVMaxX());
423 PANDORA_RETURN_RESULT_IF_AND_IF(
424 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinMatchedFraction",
m_minMatchedFraction));
426 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
429 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
432 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
435 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
438 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
441 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"PseudoChi2Cut",
m_pseudoChi2Cut));
443 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
446 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
449 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
452 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
455 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
458 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
461 return STATUS_CODE_SUCCESS;
float m_minMatchedFraction
The min matched sampling point fraction for particle creation.
float m_longMaxX
The max x coordinate of the long clusters.
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
std::vector< ProtoParticle > ProtoParticleVector
unsigned int m_minMatchedSamplingPoints
The min number of matched sampling points for particle creation.
const pandora::Cluster * m_pShortCluster
Address of the short cluster.
Header file for the lar pointing cluster class.
std::vector< TensorType::ElementList::const_iterator > IteratorList
void GetSegmentOverlapMap(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const Particle &particle, const TwoDSlidingFitResultMap &slidingFitResultMap, SegmentOverlapMap &segmentOverlapMap) const
Get a segment overlap map, describing overlap between a provided particle and all clusters in a slidi...
static bool IsLongerThanDirectConnections(IteratorList::const_iterator iIter, const TensorType::ElementList &elementList, const unsigned int minMatchedSamplingPointRatio, const pandora::ClusterSet &usedClusters)
Whether a long element is significantly longer that other elements with which it shares a cluster...
bool IsPossibleMerge(const pandora::Cluster *const pCluster, const Particle &particle, const SegmentOverlap &segmentOverlap, const TwoDSlidingFitResultMap &slidingFitResultMap) const
Whether the cluster could be merged with the candidate particle.
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
float m_matchedSamplingMaxX
The max matched sampling point x coordinate.
float m_minInitialXOverlapFraction
The min x overlap fraction (between long clusters and short cluster vs. shared overlap) ...
bool PassesParticleChecks(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType::Element &element, pandora::ClusterSet &usedClusters, ClusterMergeMap &clusterMergeMap) const
Whether a provided tensor element can be used to construct a pfo.
float m_matchedSamplingMinX
The min matched sampling point x coordinate.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
void GetCandidateClusters(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const Particle &particle, pandora::ClusterList &candidateClusters) const
Get a list of candidate clusters, which may represent missing track segments for a provided particle...
bool Run(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
bool MakeDecisions(const Particle &particle, const TwoDSlidingFitResultMap &slidingFitResultMap, const SegmentOverlapMap &segmentOverlapMap, pandora::ClusterSet &usedClusters, ClusterMergeMap &clusterMergeMap) const
Make decisions about whether to create a pfo for a provided particle and whether to make cluster merg...
Header file for the geometry helper class.
unsigned int m_makePfoMinMatchedSamplingPoints
The min number of matched sampling points in order to be able to make pfo.
std::vector< Element > ElementList
float m_makePfoMaxImpactParameter
The max transverse impact parameter in order to be able to make pfo.
const pandora::Cluster * m_pCluster1
Address of long cluster in view 1.
unsigned int m_minCaloHitsInCandidateCluster
The min no. of calo hits in a candidate cluster, for matching with long clusters. ...
Header file for the cluster helper class.
std::unordered_map< const pandora::Cluster *, SegmentOverlap > SegmentOverlapMap
unsigned int m_nSamplingPoints
The number of sampling points.
void SelectElements(const TensorType::ElementList &elementList, const pandora::ClusterSet &usedClusters, IteratorList &iteratorList) const
Select a list of the relevant elements from a set of connected tensor elements.
void FindTracks(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ProtoParticleVector &protoParticleVector, ClusterMergeMap &clusterMergeMap) const
Find remaining tracks, hidden by missing track segments (and maybe other ambiguities) in the tensor...
pandora::ClusterList m_clusterList
List of 2D clusters in a 3D proto particle.
const pandora::Cluster * m_pCluster2
Address of long cluster in view 2.
const pandora::ClusterList & GetInputClusterList(const pandora::HitType hitType) const
Get the input cluster list corresponding to a specified hit type.
static float MergeTwoPositions(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const float position1, const float position2)
Merge two views (U,V) to give a third view (Z).
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
float m_pseudoChi2Sum
The pseudo chi2 sum.
void GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (U clusters with current implementation)
virtual bool MakeClusterMerges(const ClusterMergeMap &clusterMergeMap)
Merge clusters together.
float m_pseudoChi2Cut
The pseudo chi2 cut to determine whether a sampling point is matched.
pandora::HitType m_hitType1
The hit type of the long cluster in view 1.
unsigned int m_minMatchedSamplingPointRatio
The min ratio between 1st and 2nd highest msps for simple ambiguity resolution.
unsigned int m_makePfoMinSamplingPoints
The min number of sampling points in order to be able to make pfo.
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
float m_minFinalXOverlapFraction
The min x overlap fraction between extended short cluster and the long clusters.
float m_longMinX
The min x coordinate of the long clusters.
float m_mergeXContainmentTolerance
The tolerance in determining whether candidate cluster is contained in x window.
unsigned int m_nMatchedSamplingPoints
The number of matched sampling points.
pandora::HitType m_shortHitType
The hit type of the short cluster.
virtual bool CreateThreeDParticles(const ProtoParticleVector &protoParticleVector)
Create particles using findings from recent algorithm processing.
Particle(const TensorType::Element &element)
Constructor.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
static bool HasLongDirectConnections(IteratorList::const_iterator iIter, const IteratorList &iteratorList)
Whether a long element shares clusters with any other long elements.
bool PassesSamplingCuts(const SegmentOverlap &segmentOverlap) const
Whether the segment overlap object passes cuts on matched sampling points, etc.
float m_makePfoMinMatchedFraction
The min matched sampling point fraction in order to be able to make pfo.
ThreeViewTransverseTracksAlgorithm class.
float m_shortMaxX
The max x coordinate of the short cluster.
float m_mergeMaxChi2PerSamplingPoint
The max value of chi2 per sampling point in order to merge cluster with parent.
float m_shortMinX
The min x coordinate of the short cluster.
TwoDSlidingFitResult class.
unsigned int GetSlidingFitWindow() const
Get the layer window for the sliding linear fits.
TheTensor::const_iterator const_iterator
void GetSlidingFitResultMap(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const pandora::ClusterList &candidateClusterList, TwoDSlidingFitResultMap &slidingFitResultMap) const
Get a sliding fit result map for the list of candidate clusters.
pandora::HitType m_hitType2
The hit type of the long cluster in view 2.