9 #include "Pandora/AlgorithmHeaders.h" 21 ThreeViewShowersAlgorithm::ThreeViewShowersAlgorithm() :
22 m_nMaxTensorToolRepeats(1000),
23 m_slidingFitWindow(20),
24 m_ignoreUnavailableClusters(true),
25 m_minClusterCaloHits(5),
26 m_minClusterLengthSquared(3.
f * 3.
f),
27 m_minShowerMatchedFraction(0.2
f),
28 m_minShowerMatchedPoints(20),
40 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
53 catch (StatusCodeException &statusCodeException)
55 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
56 throw statusCodeException;
78 const Cluster *
const pCluster = *iter;
89 selectedClusterList.push_back(pCluster);
93 PANDORA_MONITORING_API(VisualizeClusters(this->GetPandora(), &selectedClusterList,
"Selected Clusters", RED));
94 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
102 for (
ClusterList::iterator iter = preparedClusterList.begin(), iterEnd = preparedClusterList.end(); iter != iterEnd;)
104 const Cluster *
const pCluster(*iter);
111 catch (StatusCodeException &statusCodeException)
113 preparedClusterList.erase(iter++);
115 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
116 throw statusCodeException;
121 PANDORA_MONITORING_API(VisualizeClusters(this->GetPandora(), &preparedClusterList,
"Prepared Clusters", GREEN));
122 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
141 if (!
m_slidingFitResultMap.insert(TwoDSlidingShowerFitResultMap::value_type(pCluster, slidingShowerFitResult)).second)
142 throw StatusCodeException(STATUS_CODE_FAILURE);
160 PANDORA_THROW_RESULT_IF_AND_IF(
161 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, this->
CalculateOverlapResult(pClusterU, pClusterV, pClusterW, overlapResult));
170 const Cluster *
const pClusterU,
const Cluster *
const pClusterV,
const Cluster *
const pClusterW,
ShowerOverlapResult &overlapResult)
178 if (xSampling.m_xOverlapSpan < std::numeric_limits<float>::epsilon())
179 return STATUS_CODE_NOT_FOUND;
182 this->
GetShowerPositionMaps(fitResultU, fitResultV, fitResultW, xSampling, positionMapsU, positionMapsV, positionMapsW);
184 unsigned int nSampledHitsU(0), nMatchedHitsU(0);
187 unsigned int nSampledHitsV(0), nMatchedHitsV(0);
190 unsigned int nSampledHitsW(0), nMatchedHitsW(0);
193 const unsigned int nMatchedHits(nMatchedHitsU + nMatchedHitsV + nMatchedHitsW);
194 const unsigned int nSampledHits(nSampledHitsU + nSampledHitsV + nSampledHitsW);
196 if (0 == nSampledHits)
197 return STATUS_CODE_NOT_FOUND;
199 const XOverlap xOverlapObject(xSampling.m_uMinX, xSampling.m_uMaxX, xSampling.m_vMinX, xSampling.m_vMaxX, xSampling.m_wMinX,
200 xSampling.m_wMaxX, xSampling.m_xOverlapSpan);
204 return STATUS_CODE_NOT_FOUND;
208 ClusterList clusterList{pClusterU, pClusterV, pClusterW};
209 PANDORA_MONITORING_API(VisualizeClusters(this->GetPandora(), &clusterList,
"Overlapping Clusters",
BLUE));
210 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
213 overlapResult = showerOverlapResult;
214 return STATUS_CODE_SUCCESS;
223 const unsigned int nPoints(static_cast<unsigned int>(xSampling.
m_nPoints));
225 for (
unsigned n = 0;
n <= nPoints; ++
n)
227 const float x(xSampling.
m_minX + (xSampling.
m_maxX - xSampling.
m_minX) * static_cast<float>(
n) / static_cast<float>(nPoints));
230 if (STATUS_CODE_SUCCESS != xSampling.
GetBin(x, xBin))
238 std::sort(uValues.begin(), uValues.end());
239 std::sort(vValues.begin(), vValues.end());
240 std::sort(wValues.begin(), wValues.end());
242 if ((uValues.size() > 1) && (vValues.size() > 1))
244 const float uMin(uValues.front()), uMax(uValues.back());
245 const float vMin(vValues.front()), vMax(vValues.back());
250 positionMapsW.first.insert(ShowerPositionMap::value_type(xBin,
ShowerExtent(x, uv2wMinMin, uv2wMaxMax)));
251 positionMapsW.second.insert(ShowerPositionMap::value_type(xBin,
ShowerExtent(x, uv2wMinMax, uv2wMaxMin)));
254 if ((uValues.size() > 1) && (wValues.size() > 1))
256 const float uMin(uValues.front()), uMax(uValues.back());
257 const float wMin(wValues.front()), wMax(wValues.back());
262 positionMapsV.first.insert(ShowerPositionMap::value_type(xBin,
ShowerExtent(x, uw2vMinMin, uw2vMaxMax)));
263 positionMapsV.second.insert(ShowerPositionMap::value_type(xBin,
ShowerExtent(x, uw2vMinMax, uw2vMaxMin)));
266 if ((vValues.size() > 1) && (wValues.size() > 1))
268 const float vMin(vValues.front()), vMax(vValues.back());
269 const float wMin(wValues.front()), wMax(wValues.back());
274 positionMapsU.first.insert(ShowerPositionMap::value_type(xBin,
ShowerExtent(x, vw2uMinMin, vw2uMaxMax)));
275 positionMapsU.second.insert(ShowerPositionMap::value_type(xBin,
ShowerExtent(x, vw2uMinMax, vw2uMaxMin)));
283 const ShowerPositionMapPair &positionMaps,
unsigned int &nSampledHits,
unsigned int &nMatchedHits)
const 285 if ((xSampling.
m_maxX - xSampling.
m_minX) < std::numeric_limits<float>::epsilon())
286 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
290 unsigned int nMatchedHits1(0), nMatchedHits2(0);
291 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
297 const CaloHit *
const pCaloHit = *hIter;
298 const float x(pCaloHit->GetPositionVector().GetX());
299 const float z(pCaloHit->GetPositionVector().GetZ());
302 if (STATUS_CODE_SUCCESS != xSampling.
GetBin(
x, xBin))
310 if ((positionMaps.first.end() != positionIter1) && (
z > positionIter1->second.GetLowEdgeZ()) && (z < positionIter1->
second.GetHighEdgeZ()))
313 if ((positionMaps.second.end() != positionIter2) && (
z > positionIter2->second.GetLowEdgeZ()) && (z < positionIter2->
second.GetHighEdgeZ()))
318 nMatchedHits =
std::max(nMatchedHits1, nMatchedHits2);
325 unsigned int repeatCounter(0);
329 if ((*iter)->Run(
this, this->GetMatchingControl().GetOverlapTensor()))
354 m_xOverlapSpan = (m_maxX - m_minX);
357 if (m_xOverlapSpan > std::numeric_limits<float>::epsilon())
359 const float nPointsU(
360 std::fabs((m_xOverlapSpan / (m_uMaxX - m_uMinX)) * static_cast<float>(fitResultU.
GetMaxLayer() - fitResultU.
GetMinLayer())));
361 const float nPointsV(
362 std::fabs((m_xOverlapSpan / (m_vMaxX - m_vMinX)) * static_cast<float>(fitResultV.
GetMaxLayer() - fitResultV.
GetMinLayer())));
363 const float nPointsW(
364 std::fabs((m_xOverlapSpan / (m_wMaxX - m_wMinX)) * static_cast<float>(fitResultW.
GetMaxLayer() - fitResultW.
GetMinLayer())));
365 m_nPoints = 1.f + ((nPointsU + nPointsV + nPointsW) / 3.
f);
373 if (((x - m_minX) < -std::numeric_limits<float>::epsilon()) || ((x - m_maxX) > +std::numeric_limits<float>::epsilon()))
374 return STATUS_CODE_NOT_FOUND;
376 xBin =
static_cast<int>(0.5f + m_nPoints * (x - m_minX) / (m_maxX - m_minX));
377 return STATUS_CODE_SUCCESS;
385 AlgorithmToolVector algorithmToolVector;
386 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*
this, xmlHandle,
"ShowerTools", algorithmToolVector));
390 ShowerTensorTool *
const pShowerTensorTool(dynamic_cast<ShowerTensorTool *>(*iter));
392 if (!pShowerTensorTool)
393 return STATUS_CODE_INVALID_PARAMETER;
398 PANDORA_RETURN_RESULT_IF_AND_IF(
399 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NMaxTensorToolRepeats",
m_nMaxTensorToolRepeats));
401 PANDORA_RETURN_RESULT_IF_AND_IF(
402 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SlidingFitWindow",
m_slidingFitWindow));
404 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
407 PANDORA_RETURN_RESULT_IF_AND_IF(
408 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinClusterCaloHits",
m_minClusterCaloHits));
411 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinClusterLength", minClusterLength));
414 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
417 PANDORA_RETURN_RESULT_IF_AND_IF(
418 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinShowerMatchedPoints",
m_minShowerMatchedPoints));
420 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"Visualize",
m_visualize));
bool IsInitialized() const
Whether the track overlap result has been initialized.
pandora::StatusCode GetBin(const float x, int &xBin) const
Convert an x position into a sampling bin.
TensorToolVector m_algorithmToolVector
The algorithm tool vector.
void GetMinAndMaxX(float &minX, float &maxX) const
Get the minimum and maximum x coordinates associated with the sliding fit.
TensorType & GetOverlapTensor()
Get the overlap tensor.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
unsigned int m_nMaxTensorToolRepeats
The maximum number of repeat loops over tensor tools.
const TwoDSlidingFitResult & GetShowerFitResult() const
Get the sliding fit result for the full shower cluster.
XSampling(const TwoDSlidingFitResult &fitResultU, const TwoDSlidingFitResult &fitResultV, const TwoDSlidingFitResult &fitResultW)
Constructor.
void RemoveFromSlidingFitCache(const pandora::Cluster *const pCluster)
Remova an existing sliding fit result, for the specified cluster, from the algorithm cache...
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
MatchingType & GetMatchingControl()
Get the matching control.
float m_minX
The min x value of the common x-overlap range.
void AddToSlidingFitCache(const pandora::Cluster *const pCluster)
Add a new sliding fit result, for the specified cluster, to the algorithm cache.
void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
TwoDSlidingShowerFitResult class.
Header file for the geometry helper class.
void UpdateForNewCluster(const pandora::Cluster *const pNewCluster)
void CalculateOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW)
Calculate cluster overlap result and store in container.
std::pair< ShowerPositionMap, ShowerPositionMap > ShowerPositionMapPair
void SelectInputClusters(const pandora::ClusterList *const pInputClusterList, pandora::ClusterList &selectedClusterList) const
Select a subset of input clusters for processing in this algorithm.
void SetOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW, const OverlapResult &overlapResult)
Set overlap result.
ShowerOverlapResult class.
TwoDSlidingShowerFitResultMap m_slidingFitResultMap
The sliding shower fit result map.
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
unsigned int m_minClusterCaloHits
The min number of hits in base cluster selection method.
int GetMinLayer() const
Get the minimum occupied layer in the sliding fit.
unsigned int m_minShowerMatchedPoints
The minimum number of matched shower sampling points to allow shower grouping.
float m_minClusterLengthSquared
The min length (squared) in base cluster selection method.
Header file for the cluster helper class.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void ExamineOverlapContainer()
Examine contents of overlap container, collect together best-matching 2D particles and modify cluster...
void PrepareInputClusters(pandora::ClusterList &preparedClusterList)
Perform any preparatory steps required on the input clusters, e.g. caching expensive fit results...
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).
unsigned int GetNMatchedSamplingPoints() const
Get the number of matched sampling points.
bool m_visualize
Visualize cluster matching procedure.
unsigned int m_slidingFitWindow
The layer window for the sliding linear fits.
static int max(int a, int b)
void GetShowerPositionMaps(const TwoDSlidingShowerFitResult &fitResultU, const TwoDSlidingShowerFitResult &fitResultV, const TwoDSlidingShowerFitResult &fitResultW, const XSampling &xSampling, ShowerPositionMapPair &positionMapsU, ShowerPositionMapPair &positionMapsV, ShowerPositionMapPair &positionMapsW) const
Get the shower position maps.
void UpdateForNewCluster(const pandora::Cluster *const pNewCluster)
Update to reflect addition of a new cluster to the problem space.
bool m_ignoreUnavailableClusters
Whether to ignore (skip-over) unavailable clusters.
void TidyUp()
Tidy member variables in derived class.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
void GetBestHitOverlapFraction(const pandora::Cluster *const pCluster, const XSampling &xSampling, const ShowerPositionMapPair &positionMaps, unsigned int &nSampledHits, unsigned int &nMatchedHits) const
Get the best fraction of hits, in the common x-overlap range, contained within the provided pair of s...
float m_nPoints
The number of sampling points to be used.
float m_minShowerMatchedFraction
The minimum shower matched sampling fraction to allow shower grouping.
float m_maxX
The max x value of the common x-overlap range.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
Dft::FloatVector FloatVector
float GetMatchedFraction() const
Get the fraction of sampling points resulting in a match.
second_as<> second
Type of time stored in seconds, in double precision.
const TwoDSlidingShowerFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding shower fit result from the algorithm cache.
TwoDSlidingFitResult class.
Header file for the three view showers algorithm class.
void GetShowerEdges(const float x, const bool widenIfAmbiguity, pandora::FloatVector &edgePositions) const
Get the most appropriate shower edges at a given x coordinate.
void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.