9 #include "Pandora/AlgorithmHeaders.h" 23 TracksCrossingGapsTool::TracksCrossingGapsTool() :
24 m_minMatchedFraction(0.5
f),
25 m_minMatchedSamplingPoints(10),
26 m_minXOverlapFraction(0.9
f),
27 m_minMatchedSamplingPointRatio(2),
28 m_maxGapTolerance(2.
f),
29 m_sampleStepSize(0.5
f),
38 if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
39 std::cout <<
"----> Running Algorithm Tool: " << this->GetInstanceName() <<
", " << this->GetType() << std::endl;
41 if (PandoraContentApi::GetGeometry(*pAlgorithm)->GetDetectorGapList().empty())
45 this->
FindTracks(pAlgorithm, overlapTensor, protoParticleVector);
55 ClusterSet usedClusters;
59 for (
const Cluster *
const pKeyCluster : sortedKeyClusters)
61 if (!pKeyCluster->IsAvailable())
64 unsigned int nU(0), nV(0), nW(0);
69 this->
SelectElements(pAlgorithm, elementList, usedClusters, iteratorList);
84 protoParticleVector.push_back(protoParticle);
86 usedClusters.insert((*iIter)->GetClusterU());
87 usedClusters.insert((*iIter)->GetClusterV());
88 usedClusters.insert((*iIter)->GetClusterW());
96 const pandora::ClusterSet &usedClusters,
IteratorList &iteratorList)
const 100 if (usedClusters.count(eIter->GetClusterU()) || usedClusters.count(eIter->GetClusterV()) || usedClusters.count(eIter->GetClusterW()))
109 const XOverlap &xOverlap(eIter->GetOverlapResult().GetXOverlap());
111 if (xOverlap.GetXOverlapSpan() < std::numeric_limits<float>::epsilon())
115 float xOverlapFractionU(0.
f), xOverlapFractionV(0.
f), xOverlapFractionW(0.
f);
118 if ((xOverlap.GetXSpanU() > std::numeric_limits<float>::epsilon()) && (xOverlapFractionU >
m_minXOverlapFraction) &&
119 (xOverlap.GetXSpanV() > std::numeric_limits<float>::epsilon()) && (xOverlapFractionV >
m_minXOverlapFraction) &&
120 (xOverlap.GetXSpanW() > std::numeric_limits<float>::epsilon()) && (xOverlapFractionW >
m_minXOverlapFraction))
122 iteratorList.push_back(eIter);
130 float &xOverlapFractionU,
float &xOverlapFractionV,
float &xOverlapFractionW)
const 132 float xMinEffU(element.GetOverlapResult().GetXOverlap().GetUMinX()), xMaxEffU(element.GetOverlapResult().GetXOverlap().GetUMaxX());
133 float xMinEffV(element.GetOverlapResult().GetXOverlap().GetVMinX()), xMaxEffV(element.GetOverlapResult().GetXOverlap().GetVMaxX());
134 float xMinEffW(element.GetOverlapResult().GetXOverlap().GetWMinX()), xMaxEffW(element.GetOverlapResult().GetXOverlap().GetWMaxX());
137 const float effectiveXSpanU(xMaxEffU - xMinEffU), effectiveXSpanV(xMaxEffV - xMinEffV), effectiveXSpanW(xMaxEffW - xMinEffW);
140 const float effectiveXOverlapSpan(maxCommonX - minCommonX);
143 xOverlapFractionU = effectiveXSpanU > 0.f ?
std::min(1.
f, (effectiveXOverlapSpan / effectiveXSpanU)) : 0.f;
144 xOverlapFractionV = effectiveXSpanV > 0.f ?
std::min(1.
f, (effectiveXOverlapSpan / effectiveXSpanV)) : 0.f;
145 xOverlapFractionW = effectiveXSpanW > 0.f ?
std::min(1.
f, (effectiveXOverlapSpan / effectiveXSpanW)) : 0.f;
151 float &xMinEffU,
float &xMaxEffU,
float &xMinEffV,
float &xMaxEffV,
float &xMinEffW,
float &xMaxEffW)
const 158 float dxUmin(0.
f), dxVmin(0.
f), dxWmin(0.
f);
159 float dxUmax(0.
f), dxVmax(0.
f), dxWmax(0.
f);
162 const int nSamplingPointsLeft(1 + static_cast<int>((minCommonX - xMinAll) /
m_sampleStepSize));
163 const int nSamplingPointsRight(1 + static_cast<int>((xMaxAll - maxCommonX) /
m_sampleStepSize));
165 for (
int iSample = 1; iSample <= nSamplingPointsLeft; ++iSample)
167 bool gapInU(
false), gapInV(
false), gapInW(
false);
170 if (!this->
PassesGapChecks(pAlgorithm, element, xSample, gapInU, gapInV, gapInW))
173 if (gapInU) dxUmin = xMinEffU - xSample;
174 if (gapInV) dxVmin = xMinEffV - xSample;
175 if (gapInW) dxWmin = xMinEffW - xSample;
178 for (
int iSample = 1; iSample <= nSamplingPointsRight; ++iSample)
180 bool gapInU(
false), gapInV(
false), gapInW(
false);
183 if (!this->
PassesGapChecks(pAlgorithm, element, xSample, gapInU, gapInV, gapInW))
186 if (gapInU) dxUmax = xSample - xMaxEffU;
187 if (gapInV) dxVmax = xSample - xMaxEffV;
188 if (gapInW) dxWmax = xSample - xMaxEffW;
202 bool &gapInU,
bool &gapInV,
bool &gapInW)
const 209 CartesianVector fitUPosition(0.
f, 0.
f, 0.
f), fitVPosition(0.
f, 0.
f, 0.
f), fitWPosition(0.
f, 0.
f, 0.
f);
214 if ((STATUS_CODE_SUCCESS == statusCodeU) && (STATUS_CODE_SUCCESS == statusCodeV) && (STATUS_CODE_SUCCESS == statusCodeW))
218 if ((STATUS_CODE_SUCCESS != statusCodeU) && (!this->
IsEndOfCluster(xSample, slidingFitResultU)))
219 return this->
CheckXPositionInGap(xSample, slidingFitResultU, slidingFitResultV, slidingFitResultW, gapInU, gapInV, gapInW);
221 if ((STATUS_CODE_SUCCESS != statusCodeV) && (!this->
IsEndOfCluster(xSample, slidingFitResultV)))
222 return this->
CheckXPositionInGap(xSample, slidingFitResultV, slidingFitResultU, slidingFitResultW, gapInV, gapInU, gapInW);
224 if ((STATUS_CODE_SUCCESS != statusCodeW) && (!this->
IsEndOfCluster(xSample, slidingFitResultW)))
225 return this->
CheckXPositionInGap(xSample, slidingFitResultW, slidingFitResultU, slidingFitResultV, gapInW, gapInU, gapInV);
235 CartesianVector fitPosition2(0.
f, 0.
f, 0.
f), fitPosition3(0.
f, 0.
f, 0.
f);
246 const CartesianVector samplingPoint(xSample, 0.
f, zSample);
260 const bool endIn2(this->
IsEndOfCluster(xSample, slidingFitResult2));
261 const bool endIn3(this->
IsEndOfCluster(xSample, slidingFitResult3));
269 return ((gapIn2 && endIn3) || (gapIn3 && endIn2) || (endIn2 && endIn3));
276 return (gapIn2 || this->
IsEndOfCluster(xSample, slidingFitResult2));
281 return (gapIn3 || this->
IsEndOfCluster(xSample, slidingFitResult3));
297 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
300 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
303 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
306 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
309 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
312 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
317 std::cout <<
"TracksCrossingGapsTool: Invalid value for SampleStepSize " <<
m_sampleStepSize << std::endl;
318 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
321 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
324 return STATUS_CODE_SUCCESS;
void SelectElements(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const TensorType::ElementList &elementList, const pandora::ClusterSet &usedClusters, IteratorList &iteratorList) const
Select a list of track-like elements crossing a gap in one or more views from a set of connected tens...
unsigned int m_minMatchedSamplingPoints
The min number of matched sampling points for particle creation.
std::vector< ProtoParticle > ProtoParticleVector
float m_maxGapTolerance
The max gap tolerance.
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...
float m_minXOverlapFraction
The min x overlap fraction (in each view) for particle creation.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
void CalculateEffectiveOverlapFractions(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const TensorType::Element &element, float &xOverlapFractionU, float &xOverlapFractionV, float &xOverlapFractionW) const
Calculate the effective overlap fractions given a set of clusters, taking gaps into account...
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 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.
Header file for the geometry helper class.
pandora::ClusterList m_clusterListW
List of 2D W clusters in a 3D proto particle.
unsigned int m_minMatchedSamplingPointRatio
The min ratio between 1st and 2nd highest msps for simple ambiguity resolution.
bool CheckXPositionInGap(const float xSample, const TwoDSlidingFitResult &slidingFitResult1, const TwoDSlidingFitResult &slidingFitResult2, const TwoDSlidingFitResult &slidingFitResult3, bool &gapIn1, bool &gapIn2, bool &gapIn3) const
Check individually each cluster where a gap might be present.
bool IsEndOfCluster(const float xSample, const TwoDSlidingFitResult &slidingFitResult) const
Check whether a x position is at the end of the cluster.
std::vector< Element > ElementList
Header file for the cluster helper class.
float m_minMatchedFraction
The min matched sampling point fraction for particle creation.
pandora::ClusterList m_clusterListV
List of 2D V clusters in a 3D proto particle.
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 GetLayerPitch() const
Get the layer pitch, units cm.
pandora::ClusterList m_clusterListU
List of 2D U clusters in a 3D proto particle.
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
void GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (U clusters with current implementation)
static bool IsXSamplingPointInGap(const pandora::Pandora &pandora, const float xSample, const TwoDSlidingFitResult &slidingFitResult, const float gapTolerance=0.f)
Whether there is a gap in a cluster (described via its sliding fit result) at a specified x sampling ...
std::vector< art::Ptr< recob::Cluster > > ClusterVector
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
bool Run(ThreeDTransverseTracksAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
unsigned int m_maxAngleRatio
The max ratio allowed in the angle.
pandora::StatusCode GetGlobalFitPositionAtX(const float x, pandora::CartesianVector &position) const
Get global fit position for a given input x coordinate.
bool PassesGapChecks(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const TensorType::Element &element, const float xSample, bool &gapInU, bool &gapInV, bool &gapInW) const
Check whether there is any gap in the three U-V-W clusters combination.
void FindTracks(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ProtoParticleVector &protoParticleVector) const
Find tracks crossing gaps, with unambiguous connection but poor overlap due to gaps.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static bool HasLongDirectConnections(IteratorList::const_iterator iIter, const IteratorList &iteratorList)
Whether a long element shares clusters with any other long elements.
float m_sampleStepSize
The sampling step size used in association checks, units cm.
void CalculateEffectiveOverlapSpan(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const TensorType::Element &element, float &xMinEffU, float &xMaxEffU, float &xMinEffV, float &xMaxEffV, float &xMinEffW, float &xMaxEffW) const
Calculate the effective overlap span given a set of clusters, taking gaps into account.
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
TwoDSlidingFitResult class.
ThreeDTransverseTracksAlgorithm class.
TheTensor::const_iterator const_iterator