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;
50 this->
FindTracks(pAlgorithm, overlapTensor, protoParticleVector, clusterMergeMap);
55 return (particlesMade || mergesMade);
63 ClusterSet usedClusters;
67 for (
const Cluster *
const pKeyCluster : sortedKeyClusters)
69 if (!pKeyCluster->IsAvailable())
72 unsigned int nU(0), nV(0), nW(0);
94 protoParticleVector.push_back(protoParticle);
96 usedClusters.insert((*iIter)->GetClusterU());
97 usedClusters.insert((*iIter)->GetClusterV());
98 usedClusters.insert((*iIter)->GetClusterW());
109 if (usedClusters.count(eIter->GetClusterU()) || usedClusters.count(eIter->GetClusterV()) || usedClusters.count(eIter->GetClusterW()))
118 const XOverlap &xOverlap(eIter->GetOverlapResult().GetXOverlap());
119 const float shortSpan(
std::min(xOverlap.GetXSpanU(),
std::min(xOverlap.GetXSpanV(), xOverlap.GetXSpanW())));
120 const float longSpan1(
std::max(xOverlap.GetXSpanU(),
std::max(xOverlap.GetXSpanV(), xOverlap.GetXSpanW())));
121 const float longSpan2(((xOverlap.GetXSpanU() > shortSpan) && (xOverlap.GetXSpanU() < longSpan1)) ? xOverlap.GetXSpanU() :
122 ((xOverlap.GetXSpanV() > shortSpan) && (xOverlap.GetXSpanV() < longSpan1)) ? xOverlap.GetXSpanV() : xOverlap.GetXSpanW());
124 if ((xOverlap.GetXOverlapSpan() < std::numeric_limits<float>::epsilon()) || (longSpan1 < std::numeric_limits<float>::epsilon()))
130 iteratorList.push_back(eIter);
143 ClusterList candidateClusters;
146 if (candidateClusters.empty())
152 if (slidingFitResultMap.empty())
158 if (segmentOverlapMap.empty())
161 return this->
MakeDecisions(particle, slidingFitResultMap, segmentOverlapMap, usedClusters, clusterMergeMap);
163 catch (StatusCodeException &)
172 ClusterList &candidateClusters)
const 179 const Cluster *
const pCluster(*iter);
187 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 &)
215 (void) slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(pCluster, slidingFitResult));
218 catch (StatusCodeException &)
232 const float nPoints1(std::fabs(static_cast<float>(fitResult1.GetMaxLayer() - fitResult1.GetMinLayer())));
233 const float nPoints2(std::fabs(static_cast<float>(fitResult2.GetMaxLayer() - fitResult2.GetMinLayer())));
235 const unsigned int nPoints(static_cast<unsigned int>(1.
f + (nPoints1 + nPoints2) / 2.
f));
237 ClusterList clusterList;
238 for (
const auto &mapEntry : slidingFitResultMap) clusterList.push_back(mapEntry.first);
241 for (
unsigned n = 0;
n <= nPoints; ++
n)
248 CartesianVector fitVector1(0.
f, 0.
f, 0.
f), fitVector2(0.
f, 0.
f, 0.
f);
250 if ((STATUS_CODE_SUCCESS != fitResult1.GetGlobalFitPositionAtX(x, fitVector1)) ||
251 (STATUS_CODE_SUCCESS != fitResult2.GetGlobalFitPositionAtX(x, fitVector2)))
258 for (
const Cluster *
const pCluster : clusterList)
261 CartesianVector fitVector(0.
f, 0.
f, 0.
f), fitDirection(0.
f, 0.
f, 0.
f);
263 if ((STATUS_CODE_SUCCESS != slidingFitResult.GetGlobalFitPositionAtX(x, fitVector)) ||
264 (STATUS_CODE_SUCCESS != slidingFitResult.GetGlobalFitDirectionAtX(x, fitDirection)))
269 const float delta((prediction - fitVector.GetZ()) * fitDirection.GetX());
270 const float pseudoChi2(delta * delta);
293 bool matchesACluster(
false);
296 for (
const auto &mapEntry : segmentOverlapMap) sortedClusters.push_back(mapEntry.first);
299 for (
const Cluster *
const pCluster : sortedClusters)
301 const SegmentOverlap &segmentOverlap(segmentOverlapMap.at(pCluster));
306 shortMinX =
std::min(segmentOverlap.m_matchedSamplingMinX, shortMinX);
307 shortMaxX =
std::max(segmentOverlap.m_matchedSamplingMaxX, shortMaxX);
308 matchesACluster =
true;
311 if (!usedClusters.insert(pCluster).second || !pCluster->IsAvailable())
314 if (!this->
IsPossibleMerge(pCluster, particle, segmentOverlap, slidingFitResultMap))
317 possibleMerges.push_back(pCluster);
320 if (std::fabs(particle.
m_longMaxX - particle.
m_longMinX) < std::numeric_limits<float>::epsilon())
321 throw StatusCodeException(STATUS_CODE_FAILURE);
323 if (!matchesACluster || possibleMerges.empty())
330 clusterList.insert(clusterList.end(), possibleMerges.begin(), possibleMerges.end());
360 if (slidingFitResultMap.end() == fitIter)
361 throw StatusCodeException(STATUS_CODE_FAILURE);
364 fitIter->second.GetMinAndMaxX(mergeMinX, mergeMaxX);
382 const XOverlap &xOverlap(element.GetOverlapResult().GetXOverlap());
384 m_shortHitType = ((xOverlap.GetXSpanU() < xOverlap.GetXSpanV()) && (xOverlap.GetXSpanU() < xOverlap.GetXSpanW())) ? TPC_VIEW_U :
385 ((xOverlap.GetXSpanV() < xOverlap.GetXSpanU()) && (xOverlap.GetXSpanV() < xOverlap.GetXSpanW())) ? TPC_VIEW_V :
386 ((xOverlap.GetXSpanW() < xOverlap.GetXSpanU()) && (xOverlap.GetXSpanW() < xOverlap.GetXSpanV())) ? TPC_VIEW_W : HIT_CUSTOM;
388 if (HIT_CUSTOM == m_shortHitType)
389 throw StatusCodeException(STATUS_CODE_FAILURE);
391 m_pShortCluster = (TPC_VIEW_U == m_shortHitType) ? element.GetClusterU() : (TPC_VIEW_V == m_shortHitType) ? element.GetClusterV() : element.GetClusterW();
392 m_pCluster1 = (TPC_VIEW_U == m_shortHitType) ? element.GetClusterV() : element.GetClusterU();
393 m_pCluster2 = (TPC_VIEW_W == m_shortHitType) ? element.GetClusterV() : element.GetClusterW();
394 m_shortMinX = (TPC_VIEW_U == m_shortHitType) ? xOverlap.GetUMinX() : (TPC_VIEW_V == m_shortHitType) ? xOverlap.GetVMinX() : xOverlap.GetWMinX();
395 m_shortMaxX = (TPC_VIEW_U == m_shortHitType) ? xOverlap.GetUMaxX() : (TPC_VIEW_V == m_shortHitType) ? xOverlap.GetVMaxX() : xOverlap.GetWMaxX();
396 m_longMinX = (TPC_VIEW_U == m_shortHitType) ?
std::min(xOverlap.GetVMinX(), xOverlap.GetWMinX()) : (TPC_VIEW_V == m_shortHitType) ?
std::min(xOverlap.GetUMinX(), xOverlap.GetWMinX()) :
std::min(xOverlap.GetUMinX(), xOverlap.GetVMinX());
397 m_longMaxX = (TPC_VIEW_U == m_shortHitType) ?
std::max(xOverlap.GetVMaxX(), xOverlap.GetWMaxX()) : (TPC_VIEW_V == m_shortHitType) ?
std::max(xOverlap.GetUMaxX(), xOverlap.GetWMaxX()) :
std::max(xOverlap.GetUMaxX(), xOverlap.GetVMaxX());
408 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
411 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
414 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
417 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
420 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
423 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
426 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
429 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
432 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
435 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
438 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
441 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
444 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
447 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.
void GetSlidingFitResultMap(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const pandora::ClusterList &candidateClusterList, TwoDSlidingFitResultMap &slidingFitResultMap) const
Get a sliding fit result map for the list of candidate clusters.
std::vector< ProtoParticle > ProtoParticleVector
const pandora::ClusterList & GetInputClusterListW() const
Get the input w cluster list.
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
virtual bool CreateThreeDParticles(const ProtoParticleVector &protoParticleVector)
Create particles using findings from recent algorithm processing.
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...
void GetSegmentOverlapMap(ThreeDTransverseTracksAlgorithm *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...
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.
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)
void GetCandidateClusters(ThreeDTransverseTracksAlgorithm *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...
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) ...
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.
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
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.
pandora::ClusterList m_clusterListW
List of 2D W clusters in a 3D proto particle.
unsigned int m_makePfoMinMatchedSamplingPoints
The min number of matched sampling points in order to be able to make pfo.
const pandora::ClusterList & GetInputClusterListV() const
Get the input v cluster list.
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.
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.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
bool Run(ThreeDTransverseTracksAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
const pandora::Cluster * m_pCluster2
Address of long cluster in view 2.
pandora::ClusterList m_clusterListV
List of 2D V clusters in a 3D proto particle.
const pandora::ClusterList & GetInputClusterListU() const
Get the input u cluster list.
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).
pandora::ClusterList m_clusterListU
List of 2D U clusters in a 3D proto particle.
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)
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::vector< art::Ptr< recob::Cluster > > ClusterVector
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.
void FindTracks(ThreeDTransverseTracksAlgorithm *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...
Particle(const TensorType::Element &element)
Constructor.
std::unordered_map< const pandora::Cluster *, SegmentOverlap > SegmentOverlapMap
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.
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.
bool PassesParticleChecks(ThreeDTransverseTracksAlgorithm *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_shortMinX
The min x coordinate of the short cluster.
TwoDSlidingFitResult class.
ThreeDTransverseTracksAlgorithm class.
TheTensor::const_iterator const_iterator
virtual bool MakeClusterMerges(const ClusterMergeMap &clusterMergeMap)
Merge clusters together.
pandora::HitType m_hitType2
The hit type of the long cluster in view 2.
unsigned int GetSlidingFitWindow() const
Get the layer window for the sliding linear fits.