9 #include "Pandora/AlgorithmHeaders.h"
22 TracksCrossingGapsTool::TracksCrossingGapsTool() :
23 m_minMatchedFraction(0.5f),
24 m_minMatchedSamplingPoints(10),
25 m_minXOverlapFraction(0.9f),
26 m_minMatchedSamplingPointRatio(2),
27 m_maxGapTolerance(2.f),
28 m_sampleStepSize(0.5f),
37 if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
38 std::cout <<
"----> Running Algorithm Tool: " << this->GetInstanceName() <<
", " << this->GetType() << std::endl;
40 if (PandoraContentApi::GetGeometry(*pAlgorithm)->GetDetectorGapList().empty())
44 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);
72 for (IteratorList::const_iterator iIter = iteratorList.begin(), iIterEnd = iteratorList.end(); iIter != iIterEnd; ++iIter)
81 protoParticle.
m_clusterList.push_back((*iIter)->GetClusterU());
82 protoParticle.
m_clusterList.push_back((*iIter)->GetClusterV());
83 protoParticle.
m_clusterList.push_back((*iIter)->GetClusterW());
84 protoParticleVector.push_back(protoParticle);
86 usedClusters.insert((*iIter)->GetClusterU());
87 usedClusters.insert((*iIter)->GetClusterV());
88 usedClusters.insert((*iIter)->GetClusterW());
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 const TensorType::Element &
element,
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);
138 const float minCommonX(std::max(xMinEffU, std::max(xMinEffV, xMinEffW)));
139 const float maxCommonX(std::min(xMaxEffU, std::min(xMaxEffV, xMaxEffW)));
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 const TensorType::Element &
element,
float &xMinEffU,
float &xMaxEffU,
float &xMinEffV,
float &xMaxEffV,
float &xMinEffW,
float &xMaxEffW)
const
153 const float xMinAll(std::min(xMinEffU, std::min(xMinEffV, xMinEffW)));
154 const float xMaxAll(std::max(xMaxEffU, std::max(xMaxEffV, xMaxEffW)));
155 const float minCommonX(std::max(xMinEffU, std::max(xMinEffV, xMinEffW)));
156 const float maxCommonX(std::min(xMaxEffU, std::min(xMaxEffV, xMaxEffW)));
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);
168 const float xSample(std::max(xMinAll, minCommonX - static_cast<float>(iSample) *
m_sampleStepSize));
170 if (!this->
PassesGapChecks(pAlgorithm, element, xSample, gapInU, gapInV, gapInW))
174 dxUmin = xMinEffU - xSample;
176 dxVmin = xMinEffV - xSample;
178 dxWmin = xMinEffW - xSample;
181 for (
int iSample = 1; iSample <= nSamplingPointsRight; ++iSample)
183 bool gapInU(
false), gapInV(
false), gapInW(
false);
184 const float xSample(std::min(xMaxAll, maxCommonX + static_cast<float>(iSample) *
m_sampleStepSize));
186 if (!this->
PassesGapChecks(pAlgorithm, element, xSample, gapInU, gapInV, gapInW))
190 dxUmax = xSample - xMaxEffU;
192 dxVmax = xSample - xMaxEffV;
194 dxWmax = xSample - xMaxEffW;
208 const float xSample,
bool &gapInU,
bool &gapInV,
bool &gapInW)
const
215 CartesianVector fitUPosition(0.f, 0.f, 0.f), fitVPosition(0.f, 0.f, 0.f), fitWPosition(0.f, 0.f, 0.f);
220 if ((STATUS_CODE_SUCCESS == statusCodeU) && (STATUS_CODE_SUCCESS == statusCodeV) && (STATUS_CODE_SUCCESS == statusCodeW))
226 if ((STATUS_CODE_SUCCESS != statusCodeU) && (!this->
IsEndOfCluster(xSample, slidingFitResultU)))
227 return this->
CheckXPositionInGap(xSample, slidingFitResultU, slidingFitResultV, slidingFitResultW, gapInU, gapInV, gapInW);
229 if ((STATUS_CODE_SUCCESS != statusCodeV) && (!this->
IsEndOfCluster(xSample, slidingFitResultV)))
230 return this->
CheckXPositionInGap(xSample, slidingFitResultV, slidingFitResultU, slidingFitResultW, gapInV, gapInU, gapInW);
232 if ((STATUS_CODE_SUCCESS != statusCodeW) && (!this->
IsEndOfCluster(xSample, slidingFitResultW)))
233 return this->
CheckXPositionInGap(xSample, slidingFitResultW, slidingFitResultU, slidingFitResultV, gapInW, gapInU, gapInV);
235 catch (
const StatusCodeException &statusCodeException)
247 CartesianVector fitPosition2(0.f, 0.f, 0.f), fitPosition3(0.f, 0.f, 0.f);
258 const CartesianVector samplingPoint(xSample, 0.f, zSample);
272 const bool endIn2(this->
IsEndOfCluster(xSample, slidingFitResult2));
273 const bool endIn3(this->
IsEndOfCluster(xSample, slidingFitResult3));
281 return ((gapIn2 && endIn3) || (gapIn3 && endIn2) || (endIn2 && endIn3));
288 return (gapIn2 || this->
IsEndOfCluster(xSample, slidingFitResult2));
293 return (gapIn3 || this->
IsEndOfCluster(xSample, slidingFitResult3));
309 PANDORA_RETURN_RESULT_IF_AND_IF(
310 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinMatchedFraction",
m_minMatchedFraction));
312 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
315 PANDORA_RETURN_RESULT_IF_AND_IF(
316 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinXOverlapFraction",
m_minXOverlapFraction));
318 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
321 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxGapTolerance",
m_maxGapTolerance));
323 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SampleStepSize",
m_sampleStepSize));
328 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
331 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxAngleRatio",
m_maxAngleRatio));
333 return STATUS_CODE_SUCCESS;
unsigned int m_minMatchedSamplingPoints
The min number of matched sampling points for particle creation.
std::vector< ProtoParticle > ProtoParticleVector
void CalculateEffectiveOverlapSpan(ThreeViewTransverseTracksAlgorithm *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.
void CalculateEffectiveOverlapFractions(ThreeViewTransverseTracksAlgorithm *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...
float m_maxGapTolerance
The max gap tolerance.
std::vector< TensorType::ElementList::const_iterator > IteratorList
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...
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
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 FindTracks(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ProtoParticleVector &protoParticleVector) const
Find tracks crossing gaps, with unambiguous connection but poor overlap due to gaps.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
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.
void SelectElements(ThreeViewTransverseTracksAlgorithm *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...
Header file for the geometry helper class.
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.
bool Run(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
pandora::ClusterList m_clusterList
List of 2D 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::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)
bool PassesGapChecks(ThreeViewTransverseTracksAlgorithm *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.
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 ...
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
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.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
virtual bool CreateThreeDParticles(const ProtoParticleVector &protoParticleVector)
Create particles using findings from recent algorithm processing.
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.
float m_sampleStepSize
The sampling step size used in association checks, units cm.
ThreeViewTransverseTracksAlgorithm class.
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
TwoDSlidingFitResult class.
BEGIN_PROLOG could also be cout
TheTensor::const_iterator const_iterator