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(
124 ((xOverlap.GetXSpanU() > shortSpan) && (xOverlap.GetXSpanU() < longSpan1))
125 ? xOverlap.GetXSpanU()
126 : ((xOverlap.GetXSpanV() > shortSpan) && (xOverlap.GetXSpanV() < longSpan1)) ? xOverlap.GetXSpanV() : xOverlap.GetXSpanW());
128 if ((xOverlap.GetXOverlapSpan() < std::numeric_limits<float>::epsilon()) || (longSpan1 < std::numeric_limits<float>::epsilon()))
134 iteratorList.push_back(eIter);
147 ClusterList candidateClusters;
150 if (candidateClusters.empty())
156 if (slidingFitResultMap.empty())
162 if (segmentOverlapMap.empty())
165 return this->
MakeDecisions(particle, slidingFitResultMap, segmentOverlapMap, usedClusters, clusterMergeMap);
167 catch (StatusCodeException &)
182 const Cluster *
const pCluster(*iter);
190 candidateClusters.push_back(pCluster);
201 for (
ClusterList::const_iterator iter = candidateClusterList.begin(), iterEnd = candidateClusterList.end(); iter != iterEnd; ++iter)
203 const Cluster *
const pCluster(*iter);
208 (void)slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(pCluster, slidingFitResult));
211 catch (StatusCodeException &)
218 (void)slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(pCluster, slidingFitResult));
221 catch (StatusCodeException &)
235 const float nPoints1(std::fabs(static_cast<float>(fitResult1.GetMaxLayer() - fitResult1.GetMinLayer())));
236 const float nPoints2(std::fabs(static_cast<float>(fitResult2.GetMaxLayer() - fitResult2.GetMinLayer())));
238 const unsigned int nPoints(static_cast<unsigned int>(1.
f + (nPoints1 + nPoints2) / 2.
f));
240 ClusterList clusterList;
241 for (
const auto &mapEntry : slidingFitResultMap)
242 clusterList.push_back(mapEntry.first);
245 for (
unsigned n = 0;
n <= nPoints; ++
n)
252 CartesianVector fitVector1(0.
f, 0.
f, 0.
f), fitVector2(0.
f, 0.
f, 0.
f);
254 if ((STATUS_CODE_SUCCESS != fitResult1.GetGlobalFitPositionAtX(x, fitVector1)) ||
255 (STATUS_CODE_SUCCESS != fitResult2.GetGlobalFitPositionAtX(x, fitVector2)))
261 this->GetPandora(), particle.
m_hitType1, particle.
m_hitType2, fitVector1.GetZ(), fitVector2.GetZ()));
263 for (
const Cluster *
const pCluster : clusterList)
266 CartesianVector fitVector(0.
f, 0.
f, 0.
f), fitDirection(0.
f, 0.
f, 0.
f);
268 if ((STATUS_CODE_SUCCESS != slidingFitResult.GetGlobalFitPositionAtX(x, fitVector)) ||
269 (STATUS_CODE_SUCCESS != slidingFitResult.GetGlobalFitDirectionAtX(x, fitDirection)))
274 const float delta((prediction - fitVector.GetZ()) * fitDirection.GetX());
275 const float pseudoChi2(delta * delta);
298 bool matchesACluster(
false);
301 for (
const auto &mapEntry : segmentOverlapMap)
302 sortedClusters.push_back(mapEntry.first);
305 for (
const Cluster *
const pCluster : sortedClusters)
307 const SegmentOverlap &segmentOverlap(segmentOverlapMap.at(pCluster));
312 shortMinX =
std::min(segmentOverlap.m_matchedSamplingMinX, shortMinX);
313 shortMaxX =
std::max(segmentOverlap.m_matchedSamplingMaxX, shortMaxX);
314 matchesACluster =
true;
317 if (!usedClusters.insert(pCluster).second || !pCluster->IsAvailable())
320 if (!this->
IsPossibleMerge(pCluster, particle, segmentOverlap, slidingFitResultMap))
323 possibleMerges.push_back(pCluster);
326 if (std::fabs(particle.
m_longMaxX - particle.
m_longMinX) < std::numeric_limits<float>::epsilon())
327 throw StatusCodeException(STATUS_CODE_FAILURE);
329 if (!matchesACluster || possibleMerges.empty())
336 clusterList.insert(clusterList.end(), possibleMerges.begin(), possibleMerges.end());
366 if (slidingFitResultMap.end() == fitIter)
367 throw StatusCodeException(STATUS_CODE_FAILURE);
370 fitIter->second.GetMinAndMaxX(mergeMinX, mergeMaxX);
388 const XOverlap &xOverlap(element.GetOverlapResult().GetXOverlap());
390 m_shortHitType = ((xOverlap.GetXSpanU() < xOverlap.GetXSpanV()) && (xOverlap.GetXSpanU() < xOverlap.GetXSpanW()))
392 : ((xOverlap.GetXSpanV() < xOverlap.GetXSpanU()) && (xOverlap.GetXSpanV() < xOverlap.GetXSpanW()))
394 : ((xOverlap.GetXSpanW() < xOverlap.GetXSpanU()) && (xOverlap.GetXSpanW() < xOverlap.GetXSpanV())) ? TPC_VIEW_W : HIT_CUSTOM;
396 if (HIT_CUSTOM == m_shortHitType)
397 throw StatusCodeException(STATUS_CODE_FAILURE);
399 m_pShortCluster = (TPC_VIEW_U == m_shortHitType) ? element.GetClusterU()
400 : (TPC_VIEW_V == m_shortHitType) ? element.GetClusterV() : element.GetClusterW();
401 m_pCluster1 = (TPC_VIEW_U == m_shortHitType) ? element.GetClusterV() : element.GetClusterU();
402 m_pCluster2 = (TPC_VIEW_W == m_shortHitType) ? element.GetClusterV() : element.GetClusterW();
403 m_shortMinX = (TPC_VIEW_U == m_shortHitType) ? xOverlap.GetUMinX() : (TPC_VIEW_V == m_shortHitType) ? xOverlap.GetVMinX() : xOverlap.GetWMinX();
404 m_shortMaxX = (TPC_VIEW_U == m_shortHitType) ? xOverlap.GetUMaxX() : (TPC_VIEW_V == m_shortHitType) ? xOverlap.GetVMaxX() : xOverlap.GetWMaxX();
405 m_longMinX = (TPC_VIEW_U == m_shortHitType) ?
std::min(xOverlap.GetVMinX(), xOverlap.GetWMinX())
406 : (TPC_VIEW_V == m_shortHitType) ?
std::min(xOverlap.GetUMinX(), xOverlap.GetWMinX())
407 :
std::min(xOverlap.GetUMinX(), xOverlap.GetVMinX());
408 m_longMaxX = (TPC_VIEW_U == m_shortHitType) ?
std::max(xOverlap.GetVMaxX(), xOverlap.GetWMaxX())
409 : (TPC_VIEW_V == m_shortHitType) ?
std::max(xOverlap.GetUMaxX(), xOverlap.GetWMaxX())
410 :
std::max(xOverlap.GetUMaxX(), xOverlap.GetVMaxX());
421 PANDORA_RETURN_RESULT_IF_AND_IF(
422 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinMatchedFraction",
m_minMatchedFraction));
424 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
427 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
430 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
433 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
436 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
439 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"PseudoChi2Cut",
m_pseudoChi2Cut));
441 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
444 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
447 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
450 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
453 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
456 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
459 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...
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
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).
float m_pseudoChi2Sum
The pseudo chi2 sum.
static int max(int a, int b)
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.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
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
QTextStream & endl(QTextStream &s)
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.