30typedef SlicingAlgorithm::Slice
Slice;
35 m_minHitsPer3DCluster(20),
36 m_min3DHitsToSeedNewSlice(50),
37 m_halfWindowLayers(20),
38 m_usePointingAssociation(true),
39 m_minVertexLongitudinalDistance(-7.5f),
40 m_maxVertexLongitudinalDistance(60.f),
41 m_maxVertexTransverseDistance(10.5f),
42 m_vertexAngularAllowance(9.f),
43 m_maxClosestApproach(15.f),
44 m_maxInterceptDistance(60.f),
45 m_useProximityAssociation(true),
46 m_maxHitSeparationSquared(25.f * 25.f),
47 m_useShowerConeAssociation(true),
50 m_coneLengthMultiplier(7.f),
51 m_maxConeLength(126.f),
52 m_coneTanHalfAngle1(0.5f),
53 m_coneBoundedFraction1(0.5f),
54 m_coneTanHalfAngle2(0.75f),
55 m_coneBoundedFraction2(0.75f),
56 m_use3DProjectionsInHitPickUp(true)
66 std::cout <<
"----> Running Algorithm Tool: " << this->
GetInstanceName() <<
", " << this->
GetType() << std::endl;
79 if (clusterSliceList.size() < 2)
86 this->
CreateSlices(clusterSliceList, sliceList, clusterToSliceIndexMap);
89 this->
CopyPfoHitsToSlices(clusterToSliceIndexMap, clusterToPfoMap, sliceList, assignedClusters);
102 if (!sliceList.empty())
117 if (pCaloHitListU || pCaloHitListV || pCaloHitListW)
119 sliceList.push_back(
Slice());
120 Slice &slice(sliceList.at(0));
136 const PfoList *pPfoList(
nullptr);
139 if (!pPfoList || pPfoList->empty())
142 std::cout <<
"EventSlicingTool: unable to find pfo list " << pfoListName << std::endl;
152 for (
const Cluster *
const pCluster3D : pfoClusters3D)
157 if (!clusterToPfoMap.insert(ClusterToPfoMap::value_type(pCluster3D, pPfo)).second)
160 if (clusters3D.end() != std::find(clusters3D.begin(), clusters3D.end(), pCluster3D))
163 clusters3D.push_back(pCluster3D);
176 for (
const Cluster *
const pCluster3D : trackClusters3D)
180 trackFitResults.insert(
185 std::cout <<
"EventSlicingTool: ThreeDSlidingFitResult failure for track cluster." << std::endl;
191 for (
const Cluster *
const pCluster3D : showerClusters3D)
195 showerConeFitResults.insert(
200 std::cout <<
"EventSlicingTool: ThreeDSlidingConeFitResult failure for shower cluster." << std::endl;
204 ClusterVector sortedClusters3D(trackClusters3D.begin(), trackClusters3D.end());
205 sortedClusters3D.insert(sortedClusters3D.end(), showerClusters3D.begin(), showerClusters3D.end());
210 for (
const Cluster *
const pCluster3D : sortedClusters3D)
212 if (usedClusters.count(pCluster3D))
219 usedClusters.insert(pCluster3D);
222 this->
CollectAssociatedClusters(pCluster3D, sortedClusters3D, trackFitResults, showerConeFitResults, clusterSlice, usedClusters);
234 for (
const Cluster *
const pCandidateCluster : candidateClusters)
236 if (usedClusters.count(pCandidateCluster) || (pClusterInSlice == pCandidateCluster))
242 this->
PassShowerCone(pCandidateCluster, pClusterInSlice, showerConeFitResults))))
244 addedClusters.push_back(pCandidateCluster);
245 (void)usedClusters.insert(pCandidateCluster);
249 clusterSlice.insert(clusterSlice.end(), addedClusters.begin(), addedClusters.end());
251 for (
const Cluster *
const pAddedCluster : addedClusters)
252 this->
CollectAssociatedClusters(pAddedCluster, candidateClusters, trackFitResults, showerConeFitResults, clusterSlice, usedClusters);
260 ThreeDSlidingFitResultMap::const_iterator inSliceIter = trackFitResults.find(pClusterInSlice);
261 ThreeDSlidingFitResultMap::const_iterator candidateIter = trackFitResults.find(pCandidateCluster);
263 if ((trackFitResults.end() == inSliceIter) || (trackFitResults.end() == candidateIter))
270 this->
IsEmission(inSlicePointingCluster, candidatePointingCluster) || this->
IsNode(inSlicePointingCluster, candidatePointingCluster))
284 for (
const CaloHit *
const pCaloHit1 : *(orderedList1.second))
286 const CartesianVector &positionVector1(pCaloHit1->GetPositionVector());
290 for (
const CaloHit *
const pCaloHit2 : *(orderedList2.second))
307 ThreeDSlidingConeFitResultMap::const_iterator fitIter = showerConeFitResults.find(pConeCluster);
309 if (showerConeFitResults.end() == fitIter)
312 float clusterLength(0.f);
327 for (
const SimpleCone &simpleCone : simpleConeList)
358 float displacement1(std::numeric_limits<float>::max()), displacement2(std::numeric_limits<float>::max());
371 const float closestApproach((approach1 - approach2).GetMagnitude());
425 unsigned int index(0);
429 for (
const Cluster *
const pCluster3D : clusterList)
434 if (!clusterToSliceIndexMap.insert(ClusterToSliceIndexMap::value_type(pCluster3D, index)).second)
438 sliceList.push_back(
Slice());
449 for (
const auto &mapEntry : clusterToSliceIndexMap)
450 clusterList.push_back(mapEntry.first);
453 for (
const Cluster *
const pCluster3D : clusterList)
455 const unsigned int index(clusterToSliceIndexMap.at(pCluster3D));
457 const Pfo *
const pPfo(clusterToPfoMap.at(pCluster3D));
458 Slice &slice(sliceList.at(index));
463 for (
const Cluster *
const pCluster2D : clusters2D)
472 pCluster2D->GetOrderedCaloHitList().FillCaloHitList(targetList);
473 targetList.insert(targetList.end(), pCluster2D->GetIsolatedCaloHitList().begin(), pCluster2D->GetIsolatedCaloHitList().end());
475 if (!assignedClusters.insert(pCluster2D).second)
498 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=,
PandoraContentApi::GetList(*pAlgorithm, clusterListName, pClusterList));
500 if (!pClusterList || pClusterList->empty())
503 std::cout <<
"EventSlicingTool: unable to find cluster list " << clusterListName << std::endl;
508 for (
const Cluster *
const pCluster2D : *pClusterList)
515 if (assignedClusters.count(pCluster2D))
518 if (remainingClusters.end() != std::find(remainingClusters.begin(), remainingClusters.end(), pCluster2D))
521 remainingClusters.push_back(pCluster2D);
538 this->
GetKDTreeEntries3D(clusterToSliceIndexMap, pointsU, pointsV, pointsW, pointToSliceIndexMap);
550 kdTreeU.
build(kDNode2DListU, boundingRegionU);
551 kdTreeV.
build(kDNode2DListV, boundingRegionV);
552 kdTreeW.
build(kDNode2DListW, boundingRegionW);
554 ClusterVector sortedRemainingClusters(remainingClusters.begin(), remainingClusters.end());
557 for (
const Cluster *
const pCluster2D : sortedRemainingClusters)
567 if (!pBestResultPoint)
570 Slice &slice(sliceList.at(pointToSliceIndexMap.at(pBestResultPoint->data)));
573 pCluster2D->GetOrderedCaloHitList().FillCaloHitList(targetList);
574 targetList.insert(targetList.end(), pCluster2D->GetIsolatedCaloHitList().begin(), pCluster2D->GetIsolatedCaloHitList().end());
579 std::cout <<
"EventSlicingTool::AssignRemainingHitsToSlices - exception " << std::endl;
580 for (
const auto &pointMap : pointToSliceIndexMap)
581 delete pointMap.first;
585 for (
const auto &pointMap : pointToSliceIndexMap)
586 delete pointMap.first;
594 unsigned int sliceIndex(0);
596 for (
const Slice &slice : sliceList)
598 for (
const CaloHit *
const pCaloHit : slice.m_caloHitListU)
601 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
602 pointsU.push_back(pPoint);
605 for (
const CaloHit *
const pCaloHit : slice.m_caloHitListV)
608 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
609 pointsV.push_back(pPoint);
612 for (
const CaloHit *
const pCaloHit : slice.m_caloHitListW)
615 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
616 pointsW.push_back(pPoint);
629 for (
const auto &mapEntry : clusterToSliceIndexMap)
630 clusterList.push_back(mapEntry.first);
633 for (
const Cluster *
const pCluster3D : clusterList)
635 const unsigned int sliceIndex(clusterToSliceIndexMap.at(pCluster3D));
638 pCluster3D->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
640 for (
const CaloHit *
const pCaloHit3D : caloHitList)
642 if (
TPC_3D != pCaloHit3D->GetHitType())
654 pointsU.push_back(pProjectionU);
655 pointsV.push_back(pProjectionV);
656 pointsW.push_back(pProjectionW);
658 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionU, sliceIndex));
659 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionV, sliceIndex));
660 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionW, sliceIndex));
679 float bestDistance(std::numeric_limits<float>::max());
684 float resultDistance(std::numeric_limits<float>::max());
685 const PointKDNode2D targetPoint(pClusterPoint, pClusterPoint->GetX(), pClusterPoint->GetZ());
688 if (pResultPoint && (resultDistance < bestDistance))
690 pBestResultPoint = pResultPoint;
691 bestDistance = resultDistance;
697 std::cout <<
"EventSlicingTool::MatchClusterToSlice - exception " << std::endl;
706 return pBestResultPoint;
715 if (std::fabs(deltaPosition.
GetZ()) > std::numeric_limits<float>::epsilon())
716 return (deltaPosition.
GetZ() > std::numeric_limits<float>::epsilon());
718 if (std::fabs(deltaPosition.
GetX()) > std::numeric_limits<float>::epsilon())
719 return (deltaPosition.
GetX() > std::numeric_limits<float>::epsilon());
721 return (deltaPosition.
GetY() > std::numeric_limits<float>::epsilon());
796 return STATUS_CODE_SUCCESS;
Header file for the kd tree linker algo template class.
Header file for the cluster helper class.
Header file for the geometry helper class.
Header file for the pfo helper class.
Header file for the lar three dimensional sliding cone fit result class.
Header file for the lar three dimensional sliding fit result class.
#define PANDORA_THROW_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
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.
void GetKDTreeEntries2D(const SlicingAlgorithm::SliceList &sliceList, PointList &pointsU, PointList &pointsV, PointList &pointsW, PointToSliceIndexMap &pointToSliceIndexMap) const
Use projections of 3D hits already assigned to slices to populate kd trees to aid assignment of remai...
std::vector< pandora::ClusterVector > ClusterSliceList
float m_maxClosestApproach
Pointing association: max distance of closest approach between straight line fits.
void GetRemainingClusters(const pandora::Algorithm *const pAlgorithm, const SlicingAlgorithm::HitTypeToNameMap &clusterListNames, const pandora::ClusterSet &assignedClusters, pandora::ClusterList &remainingClusters) const
Get the list of 2D clusters with hits yets to be assigned to slices.
unsigned int m_min3DHitsToSeedNewSlice
The minimum number of hits in a 3D cluster to seed a new slice.
void GetKDTreeEntries3D(const ClusterToSliceIndexMap &clusterToSliceIndexMap, PointList &pointsU, PointList &pointsV, PointList &pointsW, PointToSliceIndexMap &pointToSliceIndexMap) const
Use 2D hits already assigned to slices to populate kd trees to aid assignment of remaining clusters.
const PointKDNode2D * MatchClusterToSlice(const pandora::Cluster *const pCluster2D, PointKDTree2D &kdTree) const
Use the provided kd tree to efficiently identify the most appropriate slice for the provided 2D clust...
void RunSlicing(const pandora::Algorithm *const pAlgorithm, const SlicingAlgorithm::HitTypeToNameMap &caloHitListNames, const SlicingAlgorithm::HitTypeToNameMap &clusterListNames, SlicingAlgorithm::SliceList &sliceList)
Run the slicing tool.
unsigned int m_halfWindowLayers
The number of layers to use for half-window of sliding fit.
void AssignRemainingHitsToSlices(const pandora::ClusterList &remainingClusters, const ClusterToSliceIndexMap &clusterToSliceIndexMap, SlicingAlgorithm::SliceList &sliceList) const
Use the list of remaining 2D clusters to assign all remaining 2D hits to existing slices in the slice...
bool PassShowerCone(const pandora::Cluster *const pConeCluster, const pandora::Cluster *const pNearbyCluster, const ThreeDSlidingConeFitResultMap &showerConeFitResults) const
Compare the provided clusters to assess whether they are associated via cone fits to the shower clust...
std::unordered_map< const pandora::Cluster *, unsigned int > ClusterToSliceIndexMap
void CopyPfoHitsToSlices(const ClusterToSliceIndexMap &clusterToSliceIndexMap, const ClusterToPfoMap &clusterToPfoMap, SlicingAlgorithm::SliceList &sliceList, pandora::ClusterSet &assignedClusters) const
Use 3D clusters in the cluster slice list, find their parent pfos and assign all hits in all 2D clust...
unsigned int m_minHitsPer3DCluster
The minimum number of hits in a 3D cluster to warrant consideration in slicing.
bool IsNode(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
Check whether a pair of pointing clusters are nodally associated.
std::unordered_map< const pandora::CartesianVector *, unsigned int > PointToSliceIndexMap
float m_coneTanHalfAngle1
The cone tan half angle to use when calculating bounded cluster fractions 1.
float m_coneBoundedFraction2
The minimum cluster bounded fraction for association 2.
void CreateSlices(const ClusterSliceList &clusterSliceList, SlicingAlgorithm::SliceList &sliceList, ClusterToSliceIndexMap &clusterToSliceIndexMap) const
Create new slices for each of the groupings of 3D clusters in the provided cluster slice list.
void CopyAllHitsToSingleSlice(const pandora::Algorithm *const pAlgorithm, const SlicingAlgorithm::HitTypeToNameMap &caloHitListNames, SlicingAlgorithm::SliceList &sliceList) const
Copy all the input hits in an event into a single slice.
bool PassProximity(const pandora::Cluster *const pClusterInSlice, const pandora::Cluster *const pCandidateCluster) const
Compare the provided clusters to assess whether they are associated via pointing.
bool m_usePointingAssociation
Whether to use pointing association.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
bool m_useProximityAssociation
Whether to use proximity association.
bool CheckClosestApproach(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
Check closest approach metrics for a pair of pointing clusters.
std::string m_showerPfoListName
The name of the input shower pfo list.
std::list< const pandora::CartesianVector * > PointList
float m_maxHitSeparationSquared
Proximity association: max distance allowed between the closest pair of hits.
float m_coneLengthMultiplier
The cone length multiplier to use when calculating bounded cluster fractions.
void CollectAssociatedClusters(const pandora::Cluster *const pClusterInSlice, const pandora::ClusterVector &candidateClusters, const ThreeDSlidingFitResultMap &trackFitResults, const ThreeDSlidingConeFitResultMap &showerConeFitResults, pandora::ClusterVector &clusterSlice, pandora::ClusterSet &usedClusters) const
Collect all clusters associated with a provided cluster.
float m_vertexAngularAllowance
Pointing association check: pointing angular allowance in degrees.
float m_maxVertexLongitudinalDistance
Pointing association check: max longitudinal distance cut.
float m_maxConeLength
The maximum allowed cone length to use when calculating bounded cluster fractions.
std::unordered_map< const pandora::Cluster *, const pandora::ParticleFlowObject * > ClusterToPfoMap
void GetThreeDClusters(const pandora::Algorithm *const pAlgorithm, const std::string &pfoListName, pandora::ClusterList &clusters3D, ClusterToPfoMap &clusterToPfoMap) const
Get the 3D clusters from a specified list of pfos, storing the 3D clusters in the provided list and p...
unsigned int m_nConeFitLayers
The number of layers over which to sum fitted direction to obtain cone fit.
float m_coneBoundedFraction1
The minimum cluster bounded fraction for association 1.
unsigned int m_nConeFits
The number of cone fits to perform, spread roughly uniformly along the shower length.
float m_coneTanHalfAngle2
The cone tan half angle to use when calculating bounded cluster fractions 2.
std::vector< PointKDNode2D > PointKDNode2DList
float m_minVertexLongitudinalDistance
Pointing association check: min longitudinal distance cut.
bool m_use3DProjectionsInHitPickUp
Whether to include 3D cluster projections when assigning remaining clusters to slices.
bool IsEmission(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
Check whether a pair of pointing clusters are consistent with an emission.
bool m_useShowerConeAssociation
Whether to use shower cone association.
EventSlicingTool()
Default constructor.
float m_maxInterceptDistance
Pointing association: max distance from cluster vertex to point of closest approach.
float m_maxVertexTransverseDistance
Pointing association check: max transverse distance cut.
void GetClusterSliceList(const pandora::ClusterList &trackClusters3D, const pandora::ClusterList &showerClusters3D, ClusterSliceList &clusterSliceList) const
Divide the provided lists of 3D track and shower clusters into slices.
bool PassPointing(const pandora::Cluster *const pClusterInSlice, const pandora::Cluster *const pCandidateCluster, const ThreeDSlidingFitResultMap &trackFitResults) const
Compare the provided clusters to assess whether they are associated via pointing (checks association ...
static bool SortPoints(const pandora::CartesianVector *const pLhs, const pandora::CartesianVector *const pRhs)
Sort points (use Z, followed by X, followed by Y)
std::string m_trackPfoListName
The name of the input track pfo list.
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
Class that implements the KDTree partition of 2D space and a closest point search algorithm.
void build(std::vector< KDTreeNodeInfoT< DATA, DIM > > &eltList, const KDTreeBoxT< DIM > ®ion)
Build the KD tree from the "eltList" in the space define by "region".
void findNearestNeighbour(const KDTreeNodeInfoT< DATA, DIM > &point, const KDTreeNodeInfoT< DATA, DIM > *&result, float &distance)
findNearestNeighbour
Data stored in each KDTree node. The dim1/dim2 fields are usually the duplication of some PFRecHit va...
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 GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
static void GetTwoDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 2D clusters from an input pfo.
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
static bool IsNode(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxTransverseDistance)
Whether pointing vertex is adjacent to a given position.
static bool IsEmission(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxLongitudinalDistance, const float maxTransverseDistance, const float angularAllowance)
Whether pointing vertex is emitted from a given position.
static void GetIntersection(const LArPointingCluster::Vertex &firstVertex, const LArPointingCluster::Vertex &secondVertex, pandora::CartesianVector &intersectPosition, float &firstDisplacement, float &secondDisplacement)
Get intersection of two vertices.
LArPointingCluster class.
const Vertex & GetInnerVertex() const
Get the inner vertex.
const Vertex & GetOuterVertex() const
Get the outer vertex.
pandora::CaloHitList m_caloHitListW
The w calo hit list.
std::map< pandora::HitType, std::string > HitTypeToNameMap
pandora::CaloHitList m_caloHitListU
The u calo hit list.
std::vector< Slice > SliceList
pandora::CaloHitList m_caloHitListV
The v calo hit list.
ThreeDSlidingConeFitResult class.
const ThreeDSlidingFitResult & GetSlidingFitResult() const
Get the sliding fit result for the full cluster.
void GetSimpleConeList(const unsigned int nLayersForConeFit, const unsigned int nCones, const ConeSelection coneSelection, SimpleConeList &simpleConeList) const
Get the list of simple cones fitted to the three dimensional cluster.
ThreeDSlidingFitResult class.
const pandora::CartesianVector & GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
const pandora::CartesianVector & GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
Algorithm class. Algorithm addresses are held only by the algorithm manager. They have a fully define...
float GetX() const
Get the cartesian x coordinate.
float GetZ() const
Get the cartesian z coordinate.
float GetY() const
Get the cartesian y coordinate.
unsigned int GetOuterPseudoLayer() const
Get the outermost pseudo layer in the cluster.
unsigned int GetInnerPseudoLayer() const
Get the innermost pseudo layer in the cluster.
const CartesianVector GetCentroid(const unsigned int pseudoLayer) const
Get unweighted centroid for cluster at a particular pseudo layer, calculated using cached values of h...
const OrderedCaloHitList & GetOrderedCaloHitList() const
Get the ordered calo hit list.
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
ParticleFlowObject class.
const std::string & GetType() const
Get the type.
const Pandora & GetPandora() const
Get the associated pandora instance.
const std::string & GetInstanceName() const
Get the instance name.
StatusCodeException class.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
KDTreeBox fill_and_bound_2d_kd_tree(const MANAGED_CONTAINER< const T * > &points, std::vector< KDTreeNodeInfoT< const T *, 2 > > &nodes)
fill_and_bound_2d_kd_tree
std::unordered_map< const pandora::Cluster *, ThreeDSlidingConeFitResult > ThreeDSlidingConeFitResultMap
SlicingAlgorithm::SliceList SliceList
SlicingAlgorithm::HitTypeToNameMap HitTypeToNameMap
std::vector< SimpleCone > SimpleConeList
SlicingAlgorithm::Slice Slice
std::unordered_map< const pandora::Cluster *, ThreeDSlidingFitResult > ThreeDSlidingFitResultMap
HitType
Calorimeter hit type enum.
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::unordered_set< const Cluster * > ClusterSet
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList