23 m_slidingFitHalfWindow(10),
24 m_maxLongitudinalDisplacement(5.f),
25 m_maxTransverseDisplacement(2.f),
26 m_twoViewChi2Cut(5.f),
27 m_threeViewChi2Cut(5.f)
38 const Vertex *
const pSelectedVertex(
39 (pVertexList && (pVertexList->size() == 1) && (
VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : NULL);
44 std::cout <<
"VertexBasedPfoRecoveryAlgorithm: unable to find vertex in current list " << std::endl;
46 return STATUS_CODE_SUCCESS;
59 this->
SelectVertexClusters(pSelectedVertex, slidingFitResultMap, availableClusters, selectedClusters);
64 this->
MatchThreeViews(pSelectedVertex, slidingFitResultMap, selectedClusters, vetoList, particleList);
65 this->
MatchTwoViews(pSelectedVertex, slidingFitResultMap, selectedClusters, vetoList, particleList);
70 return STATUS_CODE_SUCCESS;
77 for (StringVector::const_iterator iter = inputClusterListNames.begin(), iterEnd = inputClusterListNames.end(); iter != iterEnd; ++iter)
82 if (NULL == pClusterList)
85 std::cout <<
"VertexBasedPfoRecoveryAlgorithm: could not find cluster list " << *iter << std::endl;
89 for (ClusterList::const_iterator cIter = pClusterList->begin(), cIterEnd = pClusterList->end(); cIter != cIterEnd; ++cIter)
91 const Cluster *
const pCluster = *cIter;
102 clusterVector.push_back(pCluster);
108 return STATUS_CODE_SUCCESS;
116 for (ClusterVector::const_iterator iter = clusterVector.begin(), iterEnd = clusterVector.end(); iter != iterEnd; ++iter)
118 if (slidingFitResultMap.end() == slidingFitResultMap.find(*iter))
125 if (pointingCluster.
GetLengthSquared() < std::numeric_limits<float>::epsilon())
128 if (!slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(*iter, slidingFitResult)).second)
133 if (STATUS_CODE_FAILURE == statusCodeException.
GetStatusCode())
134 throw statusCodeException;
149 for (ClusterVector::const_iterator cIter = inputClusters.begin(), cIterEnd = inputClusters.end(); cIter != cIterEnd; ++cIter)
151 const Cluster *
const pCluster = *cIter;
159 TwoDSlidingFitResultMap::const_iterator sIter = slidingFitResultMap.find(pCluster);
160 if (slidingFitResultMap.end() == sIter)
166 for (
unsigned int iVtx = 0; iVtx < 2; ++iVtx)
170 float rL(0.f), rT(0.f);
175 outputClusters.push_back(pCluster);
189 ClusterVector availableClusters, clustersU, clustersV, clustersW;
196 const Cluster *pCluster1(NULL);
197 const Cluster *pCluster2(NULL);
198 const Cluster *pCluster3(NULL);
200 this->
GetBestChi2(pVertex, slidingFitResultMap, clustersU, clustersV, clustersW, pCluster1, pCluster2, pCluster3, chi2);
202 if (NULL == pCluster1 || NULL == pCluster2 || NULL == pCluster3)
209 const Cluster *
const pClusterU(
211 const Cluster *
const pClusterV(
213 const Cluster *
const pClusterW(
216 particleList.push_back(
Particle(pClusterU, pClusterV, pClusterW));
218 vetoList.insert(pCluster1);
219 vetoList.insert(pCluster2);
220 vetoList.insert(pCluster3);
231 ClusterVector availableClusters, clustersU, clustersV, clustersW;
238 const Cluster *pCluster1(NULL);
239 const Cluster *pCluster2(NULL);
241 this->
GetBestChi2(pVertex, slidingFitResultMap, clustersU, clustersV, pCluster1, pCluster2, chi2);
242 this->
GetBestChi2(pVertex, slidingFitResultMap, clustersV, clustersW, pCluster1, pCluster2, chi2);
243 this->
GetBestChi2(pVertex, slidingFitResultMap, clustersW, clustersU, pCluster1, pCluster2, chi2);
245 if (NULL == pCluster1 || NULL == pCluster2)
255 particleList.push_back(
Particle(pClusterU, pClusterV, pClusterW));
257 vetoList.insert(pCluster1);
258 vetoList.insert(pCluster2);
266 const Cluster *&pBestCluster2,
const Cluster *&pBestCluster3,
float &bestChi2)
const
268 if (clusters1.empty() || clusters2.empty() || clusters3.empty())
272 for (ClusterVector::const_iterator cIter1 = clusters1.begin(), cIterEnd1 = clusters1.end(); cIter1 != cIterEnd1; ++cIter1)
274 const Cluster *
const pCluster1 = *cIter1;
276 TwoDSlidingFitResultMap::const_iterator sIter1 = slidingFitResultMap.find(pCluster1);
277 if (slidingFitResultMap.end() == sIter1)
284 for (ClusterVector::const_iterator cIter2 = clusters2.begin(), cIterEnd2 = clusters2.end(); cIter2 != cIterEnd2; ++cIter2)
286 const Cluster *
const pCluster2 = *cIter2;
288 TwoDSlidingFitResultMap::const_iterator sIter2 = slidingFitResultMap.find(pCluster2);
289 if (slidingFitResultMap.end() == sIter2)
296 for (ClusterVector::const_iterator cIter3 = clusters3.begin(), cIterEnd3 = clusters3.end(); cIter3 != cIterEnd3; ++cIter3)
298 const Cluster *
const pCluster3 = *cIter3;
300 TwoDSlidingFitResultMap::const_iterator sIter3 = slidingFitResultMap.find(pCluster3);
301 if (slidingFitResultMap.end() == sIter3)
308 const float thisChi2(this->
GetChi2(pVertex, pointingCluster1, pointingCluster2, pointingCluster3));
310 if (thisChi2 < bestChi2)
313 pBestCluster1 = pCluster1;
314 pBestCluster2 = pCluster2;
315 pBestCluster3 = pCluster3;
327 if (clusters1.empty() || clusters2.empty())
331 for (ClusterVector::const_iterator cIter1 = clusters1.begin(), cIterEnd1 = clusters1.end(); cIter1 != cIterEnd1; ++cIter1)
333 const Cluster *
const pCluster1 = *cIter1;
335 TwoDSlidingFitResultMap::const_iterator sIter1 = slidingFitResultMap.find(pCluster1);
336 if (slidingFitResultMap.end() == sIter1)
343 for (ClusterVector::const_iterator cIter2 = clusters2.begin(), cIterEnd2 = clusters2.end(); cIter2 != cIterEnd2; ++cIter2)
345 const Cluster *
const pCluster2 = *cIter2;
347 TwoDSlidingFitResultMap::const_iterator sIter2 = slidingFitResultMap.find(pCluster2);
348 if (slidingFitResultMap.end() == sIter2)
355 const float thisChi2(this->
GetChi2(pVertex, pointingCluster1, pointingCluster2));
357 if (thisChi2 < bestChi2)
360 pBestCluster1 = pCluster1;
361 pBestCluster2 = pCluster2;
375 if (hitType1 == hitType2)
401 if ((hitType1 == hitType2) || (hitType2 == hitType3) || (hitType3 == hitType1))
424 for (ClusterVector::const_iterator iter = inputVector.begin(), iterEnd = inputVector.end(); iter != iterEnd; ++iter)
426 if (0 == vetoList.count(*iter))
427 outputVector.push_back(*iter);
435 for (ClusterVector::const_iterator iter = inputVector.begin(), iterEnd = inputVector.end(); iter != iterEnd; ++iter)
438 outputVector.push_back(*iter);
446 const float innerDistance((vertex -
cluster.GetInnerVertex().GetPosition()).GetMagnitudeSquared());
447 const float outerDistance((vertex -
cluster.GetOuterVertex().GetPosition()).GetMagnitudeSquared());
449 if (innerDistance < outerDistance)
450 return cluster.GetInnerVertex();
452 return cluster.GetOuterVertex();
462 return cluster.GetOuterVertex();
464 return cluster.GetInnerVertex();
471 if (particleList.empty())
474 const PfoList *pPfoList = NULL;
475 std::string pfoListName;
478 for (ParticleList::const_iterator iter = particleList.begin(), iterEnd = particleList.end(); iter != iterEnd; ++iter)
487 const bool isAvailableU((NULL != pClusterU) ? pClusterU->
IsAvailable() :
true);
488 const bool isAvailableV((NULL != pClusterV) ? pClusterV->
IsAvailable() :
true);
489 const bool isAvailableW((NULL != pClusterW) ? pClusterW->
IsAvailable() :
true);
491 if (!(isAvailableU && isAvailableV && isAvailableW))
495 clusterList.push_back(pClusterU);
497 clusterList.push_back(pClusterV);
499 clusterList.push_back(pClusterW);
502 PandoraContentApi::ParticleFlowObject::Parameters pfoParameters;
503 pfoParameters.m_particleId = MU_MINUS;
506 pfoParameters.m_energy = 0.f;
508 pfoParameters.m_clusterList = clusterList;
511 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*
this, pfoParameters, pPfo));
514 if (!pPfoList->empty())
521 m_pClusterU(pClusterU),
522 m_pClusterV(pClusterV),
523 m_pClusterW(pClusterW)
558 return STATUS_CODE_SUCCESS;
Header file for the cluster helper class.
Header file for the geometry helper class.
#define PANDORA_THROW_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
Header file for the vertex-based particle recovery algorithm.
static pandora::StatusCode ReplaceCurrentList(const pandora::Algorithm &algorithm, const std::string &newListName)
Replace the current list with a pre-saved list; use this new list as a permanent replacement for the ...
static pandora::StatusCode CreateTemporaryListAndSetCurrent(const pandora::Algorithm &algorithm, const T *&pT, std::string &temporaryListName)
Create a temporary list and set it to be the current list, enabling object creation.
static pandora::StatusCode GetCurrentList(const pandora::Algorithm &algorithm, const T *&pT)
Get the current list.
static pandora::StatusCode GetList(const pandora::Algorithm &algorithm, const std::string &listName, const T *&pT)
Get a named list.
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
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,...
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
static void MergeTwoPositions3D(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const pandora::CartesianVector &position1, const pandora::CartesianVector &position2, pandora::CartesianVector &position3D, float &chiSquared)
Merge 2D positions from two views to give unified 3D position.
static void MergeThreePositions3D(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const pandora::HitType view3, const pandora::CartesianVector &position1, const pandora::CartesianVector &position2, const pandora::CartesianVector &position3, pandora::CartesianVector &position3D, float &chiSquared)
Merge 2D positions from three views to give unified 3D position.
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
bool IsInnerVertex() const
Is this the inner vertex.
static void GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices.
LArPointingCluster class.
const Vertex & GetInnerVertex() const
Get the inner vertex.
const pandora::Cluster * GetCluster() const
Get the address of the cluster.
const Vertex & GetOuterVertex() const
Get the outer vertex.
float GetLengthSquared() const
Get length squared of pointing cluster.
TwoDSlidingFitResult class.
const pandora::Cluster * m_pClusterV
Address of cluster in V view.
const pandora::Cluster * m_pClusterU
Address of cluster in U view.
Particle(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW)
Constructor.
const pandora::Cluster * m_pClusterW
Address of cluster in W view.
std::vector< Particle > ParticleList
void MatchThreeViews(const pandora::Vertex *const pVertex, const TwoDSlidingFitResultMap &slidingFitResultMap, const pandora::ClusterVector &selectedClusters, pandora::ClusterSet &vetoList, ParticleList &particleList) const
Match clusters from three views.
void SelectAvailableClusters(const pandora::ClusterSet &vetoList, const pandora::ClusterVector &inputVector, pandora::ClusterVector &outputVector) const
Select cluster which haven't been vetoed.
const LArPointingCluster::Vertex & GetInnerVertex(const pandora::CartesianVector &vertex, const LArPointingCluster &cluster) const
Find nearest end of pointing cluster to a specified position vector.
const LArPointingCluster::Vertex & GetOuterVertex(const pandora::CartesianVector &vertex, const LArPointingCluster &cluster) const
Find furthest end of pointing cluster from a specified position vector.
void SelectVertexClusters(const pandora::Vertex *const pVertex, const TwoDSlidingFitResultMap &slidingFitResultMap, const pandora::ClusterVector &inputClusters, pandora::ClusterVector &outputClusters) const
Select clusters in proximity to reconstructed vertex.
float m_maxLongitudinalDisplacement
std::string m_outputPfoListName
The name of the output pfo list.
void BuildSlidingFitResultMap(const pandora::ClusterVector &clusterVector, TwoDSlidingFitResultMap &slidingFitResultMap) const
Build the map of sliding fit results.
void MatchTwoViews(const pandora::Vertex *const pVertex, const TwoDSlidingFitResultMap &slidingFitResultMap, const pandora::ClusterVector &selectedClusters, pandora::ClusterSet &vetoList, ParticleList &particleList) const
Match clusters from two views.
pandora::StatusCode Run()
Run the algorithm.
void GetBestChi2(const pandora::Vertex *const pVertex, const TwoDSlidingFitResultMap &slidingFitResultMap, const pandora::ClusterVector &clusters1, const pandora::ClusterVector &clusters2, const pandora::ClusterVector &clusters3, const pandora::Cluster *&pBestCluster1, const pandora::Cluster *&pBestCluster2, const pandora::Cluster *&pBestCluster3, float &chi2) const
Get best-matched triplet of clusters from a set of input cluster vectors.
VertexBasedPfoRecoveryAlgorithm()
Default constructor.
float GetChi2(const pandora::Vertex *const pVertex, const LArPointingCluster &pointingCluster1, const LArPointingCluster &pointingCluster2) const
Merge two pointing clusters and return chi-squared metric giving consistency of matching.
float m_maxTransverseDisplacement
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
pandora::StatusCode GetAvailableClusters(const pandora::StringVector inputClusterListName, pandora::ClusterVector &clusterVector) const
Get a vector of available clusters.
void SelectClusters(const pandora::HitType hitType, const pandora::ClusterVector &inputVector, pandora::ClusterVector &outputVector) const
Select clusters of a specified hit type.
pandora::StringVector m_inputClusterListNames
The list of input cluster list names.
unsigned int m_slidingFitHalfWindow
void BuildParticles(const ParticleList &particleList)
Build particle flow objects from matched clusters.
bool IsAvailable() const
Whether the cluster is available to be added to a particle flow object.
unsigned int GetNCaloHits() const
Get the number of calo hits in the cluster.
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
ParticleFlowObject class.
static float GetParticleMass(const int pdgCode)
Get the mass of a particle type.
static int GetParticleCharge(const int pdgCode)
Get the charge of a particle type.
const Pandora & GetPandora() const
Get the associated pandora instance.
StatusCodeException class.
StatusCode GetStatusCode() const
Get status code.
const CartesianVector & GetPosition() const
Get the vertex position.
static StatusCode ReadVectorOfValues(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, std::vector< T > &vector)
Read a vector of values from a (space separated) list in an xml element.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
HitType
Calorimeter hit type enum.
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< std::string > StringVector
std::unordered_set< const Cluster * > ClusterSet
MANAGED_CONTAINER< const Vertex * > VertexList
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList