LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
lar_cluster3d::ClusterParamsBuilder Class Reference

ClusterParamsBuilder class definiton. More...

#include "ClusterParamsBuilder.h"

Public Member Functions

 ClusterParamsBuilder (fhicl::ParameterSet const &pset)
 Constructor. More...
 
virtual ~ClusterParamsBuilder ()
 Destructor. More...
 
void configure (const fhicl::ParameterSet &)
 
void BuildClusterInfo (reco::ClusterParametersList &clusterParametersList) const
 Given the results of running DBScan, format the clusters so that they can be easily transferred back to the larsoft world. More...
 
void FillClusterParams (reco::ClusterParameters &, reco::Hit2DToClusterMap &, double minUniqueFrac=0., double maxLostFrac=1.) const
 Fill the cluster parameters (expose to outside world for case of splitting/merging clusters) More...
 

Private Member Functions

void removeUsedHitsFromMap (reco::ClusterParameters &, reco::HitPairListPtr &, reco::Hit2DToClusterMap &) const
 

Private Attributes

size_t m_clusterMinHits
 Data members to follow. More...
 
double m_clusterMinUniqueFraction
 
double m_clusterMaxLostFraction
 
PrincipalComponentsAlg m_pcaAlg
 

Detailed Description

ClusterParamsBuilder class definiton.

Definition at line 34 of file ClusterParamsBuilder.h.

Constructor & Destructor Documentation

lar_cluster3d::ClusterParamsBuilder::ClusterParamsBuilder ( fhicl::ParameterSet const &  pset)

Constructor.

Parameters
pset

Definition at line 30 of file ClusterParamsBuilder.cxx.

References configure().

30  :
31  m_pcaAlg(pset.get<fhicl::ParameterSet>("PrincipalComponentsAlg"))
32 {
33  this->configure(pset);
34 }
void configure(const fhicl::ParameterSet &)
lar_cluster3d::ClusterParamsBuilder::~ClusterParamsBuilder ( )
virtual

Destructor.

Definition at line 38 of file ClusterParamsBuilder.cxx.

39 {
40 }

Member Function Documentation

void lar_cluster3d::ClusterParamsBuilder::BuildClusterInfo ( reco::ClusterParametersList clusterParametersList) const

Given the results of running DBScan, format the clusters so that they can be easily transferred back to the larsoft world.

Parameters
hitPairClusterMapmap between view and a list of 3D hits
clusterParametersLista container for our candidate 3D clusters
rejectionFractionUsed for determine "hit purity" when rejecting clusters
                          The last two parameters are passed through to the FillClusterParams method

Given a list of a list of candidate cluster hits, build these out into the intermediate 3D cluster objects to pass to the final stage

Note that this routine will also reject unworthy clusters, in particular those that share too many hits with other clusters. The criteria is that a larger cluster (more hits) will be superior to a smaller one, if the smaller one shares too many hits with the larger it is zapped. *** THIS IS AN AREA FOR CONTINUED STUDY ***

Definition at line 53 of file ClusterParamsBuilder.cxx.

References FillClusterParams(), reco::ClusterParameters::getClusterParams(), reco::ClusterParameters::getFullPCA(), reco::PrincipalComponents::getSvdOK(), m_clusterMaxLostFraction, m_clusterMinHits, and m_clusterMinUniqueFraction.

Referenced by lar_cluster3d::DBScanAlg::Cluster3DHits(), and lar_cluster3d::MinSpanTreeAlg::Cluster3DHits().

54 {
64  // This is a remote possibility but why not check?
65  if (!clusterParametersList.empty())
66  {
67  // We want to order our clusters on by largest (most number hits) to smallest. So, we'll loop through the clusters,
68  // weeding out the unwanted ones and keep track of things in a set of "good" clusters which we'll order
69  // by cluster size.
70  clusterParametersList.sort();
71 
72  // The smallest clusters are now at the end, drop those off the back that are less than the mininum necessary
73  while(!clusterParametersList.empty() && clusterParametersList.back().getHitPairListPtr().size() < m_clusterMinHits) clusterParametersList.pop_back();
74 
75  // The next step is to build out a mapping of all 2D hits to clusters
76  // Keep track of where the hits get distributed...
77  reco::Hit2DToClusterMap hit2DToClusterMap;
78 
79  reco::ClusterParametersList::iterator clusterItr = clusterParametersList.begin();
80 
81  for(auto& clusterParams : clusterParametersList)
82  {
83  for(const auto& hit3D : clusterParams.getHitPairListPtr())
84  {
85  for(const auto& hit2D : hit3D->getHits())
86  {
87  if (!hit2D) continue;
88 
89  hit2DToClusterMap[hit2D][&clusterParams].insert(hit3D);
90  }
91  }
92  }
93 
94  // Ok, spin through again to remove ambiguous hits
95  // for(auto& clusterParams : clusterParametersList) PruneAmbiguousHits(clusterParams,hit2DToClusterMap);
96 
97  // What remains is an order set of clusters, largest first
98  // Now go through and obtain cluster parameters
99  clusterItr = clusterParametersList.begin();
100 
101  while(clusterItr != clusterParametersList.end())
102  {
103  // Dereference for ease...
104  reco::ClusterParameters& clusterParams = *clusterItr;
105 
106  // Do the actual work of filling the parameters
107  FillClusterParams(clusterParams, hit2DToClusterMap, m_clusterMinUniqueFraction, m_clusterMaxLostFraction);
108 
109  // If this cluster is rejected then the parameters will be empty
110  if (clusterParams.getClusterParams().empty() || !clusterParams.getFullPCA().getSvdOK())
111  {
112  clusterItr = clusterParametersList.erase(clusterItr);
113  }
114  else clusterItr++;
115  }
116  }
117 
118  return;
119 }
bool getSvdOK() const
Definition: Cluster3D.h:224
intermediate_table::iterator iterator
reco::PlaneToClusterParamsMap & getClusterParams()
Definition: Cluster3D.h:402
void FillClusterParams(reco::ClusterParameters &, reco::Hit2DToClusterMap &, double minUniqueFrac=0., double maxLostFrac=1.) const
Fill the cluster parameters (expose to outside world for case of splitting/merging clusters) ...
size_t m_clusterMinHits
Data members to follow.
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:405
std::unordered_map< const reco::ClusterHit2D *, ClusterToHitPairSetMap > Hit2DToClusterMap
Definition: Cluster3D.h:437
void lar_cluster3d::ClusterParamsBuilder::configure ( const fhicl::ParameterSet )

Definition at line 44 of file ClusterParamsBuilder.cxx.

References fhicl::ParameterSet::get(), m_clusterMaxLostFraction, m_clusterMinHits, and m_clusterMinUniqueFraction.

Referenced by ClusterParamsBuilder().

45 {
46  m_clusterMinHits = pset.get<size_t>("ClusterMinHits", 3 );
47  m_clusterMinUniqueFraction = pset.get<double>("ClusterMinUniqueFraction", 0.5 );
48  m_clusterMaxLostFraction = pset.get<double>("ClusterMaxLostFraction", 0.5 );
49 
50  return;
51 }
size_t m_clusterMinHits
Data members to follow.
void lar_cluster3d::ClusterParamsBuilder::FillClusterParams ( reco::ClusterParameters clusterParams,
reco::Hit2DToClusterMap hit2DToClusterMap,
double  minUniqueFrac = 0.,
double  maxLostFrac = 1. 
) const

Fill the cluster parameters (expose to outside world for case of splitting/merging clusters)

Parameters
ClusterParametersThe cluster parameters container to be modified
Hit2DToClusterMapMap to keep track of 2D hit to cluster association
doubleminimum fraction of unique hits
doublemaximum fraction of "lost" hits

Given a list of hits fill out the remaining parameters for this cluster and evaluate the candidate's worthiness to achieve stardom in the event display

Definition at line 121 of file ClusterParamsBuilder.cxx.

References reco::ClusterParameters::getClusterParams(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHit2DToHit3DListMap(), reco::ClusterParameters::getHit3DToEdgeMap(), reco::ClusterParameters::getHitPairListPtr(), reco::ClusterParameters::getSkeletonPCA(), reco::PrincipalComponents::getSvdOK(), art::left(), m_pcaAlg, max, min, lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_3D(), reco::ClusterHit3D::REJECTEDHIT, art::right(), reco::ClusterParameters::UpdateParameters(), and reco::ClusterHit2D::USED.

Referenced by BuildClusterInfo(), and lar_cluster3d::Cluster3D::splitClustersWithHough().

125 {
130  // Recover the HitPairListPtr from the input clusterParams (which will be the
131  // only thing that has been provided)
132  reco::HitPairListPtr& hitPairVector = clusterParams.getHitPairListPtr();
133 
134  // To be sure, we should clear the other data members
135  clusterParams.getClusterParams().clear();
136  clusterParams.getFullPCA() = reco::PrincipalComponents();
137 
138  // A test of the emergency broadcast system...
139  // FindBestPathInCluster(clusterParams);
140  // CheckHitSorting(clusterParams);
141 
142  // See if we can avoid duplicates by temporarily transferring to a set
143  std::set<const reco::ClusterHit2D*> hitSet;
144 
145  // Ultimately we want to keep track of the number of unique 2D hits in this cluster
146  // So use a vector (by plane) of sets of hits
147  std::vector<size_t> planeHit2DVec;
148  std::vector<size_t> planeUniqueHit2DVec;
149 
150  planeHit2DVec.resize(3);
151  planeUniqueHit2DVec.resize(3);
152 
153  // Map from 2D hits to associated 3D hits
154  reco::Hit2DToHit3DListMap& hit2DToHit3DListMap = clusterParams.getHit2DToHit3DListMap();
155 
156  // The map from 2D to 3D hits will contain unique entries for 2D hits so we can do some quick accounting here
157  for(const auto& hitMapPair : hit2DToHit3DListMap)
158  {
159  size_t plane = hitMapPair.first->getHit().WireID().Plane;
160 
161  planeHit2DVec[plane] += hitMapPair.second.size();
162  if (!(hitMapPair.first->getStatusBits() & reco::ClusterHit2D::USED)) planeUniqueHit2DVec[plane] += hitMapPair.second.size();
163  }
164 
165  // Get totals
166  int numTotalHits(0);
167  int numUniqueHits(0);
168 
169  // Also consider the number of hits shared on a given view...
170  std::vector<float> uniqueHitFracVec(3,0.);
171  int nPlanesWithHits(0);
172  int nPlanesWithUniqueHits(0);
173  size_t minPlane(0);
174  size_t minPlaneCnt = planeUniqueHit2DVec.at(0);
175 
176  // Loop through the planes
177  for(int idx = 0; idx < 3; idx++)
178  {
179  // numerology
180  numTotalHits += planeHit2DVec.at(idx);
181  numUniqueHits += planeUniqueHit2DVec.at(idx);
182 
183  if (planeHit2DVec.at(idx) > 0) nPlanesWithHits++;
184  if (planeUniqueHit2DVec.at(idx) > 0) nPlanesWithUniqueHits++;
185 
186  // Compute the fraction of unique hits in this plane
187  uniqueHitFracVec[idx] = float(planeUniqueHit2DVec.at(idx)) / std::max(float(planeHit2DVec.at(idx)),float(1.));
188 
189  // Finding the plane with the fewest hits
190  if (planeHit2DVec.at(idx) < minPlaneCnt)
191  {
192  minPlaneCnt = planeHit2DVec.at(idx);
193  minPlane = idx;
194  }
195  }
196 
197  // If we have something left then at this point we make one more check
198  // This check is intended to weed out clusters made from isolated groups of ambiguous hits which
199  // really belong to a larger cluster
200  if (numUniqueHits > 0.25 * numTotalHits && nPlanesWithHits > 1 && nPlanesWithUniqueHits > 1)
201  {
202  // Sorts lowest to highest
203  std::sort(uniqueHitFracVec.begin(),uniqueHitFracVec.end());
204 
205  float acceptRatio = 0.;
206 
207  if(uniqueHitFracVec[0] * uniqueHitFracVec[1] > 0.25) acceptRatio = 1.;
208 
209  float uniqueFraction = uniqueHitFracVec[0] * uniqueHitFracVec[1] * uniqueHitFracVec[2];
210 
211  // Arbitrary rejection criteria... need to understand
212  if (uniqueFraction > 0.6 && acceptRatio > 0.)
213  {
214  // Create a list to hold 3D hits which are already in use (criteria below)
215  reco::HitPairListPtr usedHitPairList;
216 
217 // std::cout << "--------> Starting 3D hit removal, # 2D hits/plane: " << planeHit2DVec[0] << "/" << planeHit2DVec[1] << "/" << planeHit2DVec[2] << std::endl;
218 
219  // Have survived laugh test, do final processing...
220  // In this first loop go through all the 2D hits and identify the 3D hits that are candidates for deletion
221  for(auto& pair : hit2DToHit3DListMap)
222  {
223  // Check to see if this can happen
224  if (pair.second.empty())
225  {
226  std::cout << "<<<<<< no matching 3D hits for reco hit in final hit processing >>>>>>" << std::endl;
227  continue;
228  }
229 
230  // Which plane for this hit?
231  size_t hitPlane = pair.first->getHit().WireID().Plane;
232 
233  // Only reject hits on the planes not the fewest 2D hits and really only do this if more than a couple
234  if (hitPlane != minPlane && pair.second.size() > 2)
235  {
236  // If this hit is associated to a number of 3D hits then do some arbitration
237  // Start by sorting the 3D hits by "significance"
238  // --> Really should do this by the significance of adding the hit we are looking at?
239  //pair.second.sort([hitPlane](const auto& left, const auto& right){return left->getHitDelTSigVec()[hitPlane] < right->getHitDelTSigVec()[hitPlane];});
240  pair.second.sort([](const auto& left, const auto& right){return left->getHitChiSquare() < right->getHitChiSquare();});
241 
243  //std::cout << "~~~~> Checking hit removal, # matches: " << pair.second.size() << ", first params: " << pair.second.front()->getHitChiSquare() << ", last params: "<< pair.second.back()->getHitChiSquare();
244 
245  // From sorted list, determine a rejection value to eliminate bad hits
246  //float cutDeltaTSig = std::min(2.0,std::max(0.5, double((pair.second.front()->getHitDelTSigVec()[hitPlane]))));
247  float cutDeltaTSig = std::min(2.0,std::max(0.5, double(pair.second.front()->getHitChiSquare())));
248 
249  //std::cout << ", cutDeltaTSig: " << cutDeltaTSig;
250 
251  cutDeltaTSig = 10.;
252 
253  // And here go through the process of eliminating it
254  //reco::HitPairListPtr::iterator firstBadHitItr = std::find_if(pair.second.begin(),pair.second.end(),[hitPlane,cutDeltaTSig](const auto& hitPtr){return hitPtr->getHitDelTSigVec()[hitPlane] > cutDeltaTSig;});
255  reco::HitPairListPtr::iterator firstBadHitItr = std::find_if(pair.second.begin(),pair.second.end(),[cutDeltaTSig](const auto& hitPtr){return hitPtr->getHitChiSquare() > cutDeltaTSig;});
256 
257  // We need to worry about cutting too many hits... use this loop to try to expand the range in a reasonable fashion
258 // while(std::distance(pair.second.begin(),firstBadHitItr) < int(pair.second.size()/3) && cutDeltaTSig < 0.5)
259 // {
260 // float candDeltaTSig = (*firstBadHitItr)->getHitDelTSigVec()[hitPlane];
261 //
262 // if (candDeltaTSig > 2. * cutDeltaTSig) break;
263 //
264 // firstBadHitItr++;
265 // cutDeltaTSig = candDeltaTSig;
266 // }
267 
268  reco::HitPairListPtr rejectCandList;
269 
270  std::copy(firstBadHitItr,pair.second.end(),std::back_inserter(rejectCandList));
271 
272  //std::cout << ", bad hits: " << rejectCandList.size() << std::endl;
273 
274  // Remove the 3D hits from all the lists
275  for(const auto& hit3D : rejectCandList)
276  {
277  bool rejectThisHit(true);
278  std::vector<std::pair<reco::HitPairListPtr&,reco::HitPairListPtr::iterator>> deleteVec;
279 
280  for(const auto& hit2D : hit3D->getHits())
281  {
282  // Watch for null hit (dead channels)
283  if (!hit2D) continue;
284 
285  reco::HitPairListPtr& removeHitList = hit2DToHit3DListMap.at(hit2D);
286 
287  // Don't allow all the 3D hits associated to this 2D hit to be rejected?
288  if (removeHitList.size() < 2)
289  {
290  //std::cout << " ---> remove list too small, size: " << removeHitList.size() << " for hit: " << hit2D << ", pair.first: " << pair.first << std::endl;
291  rejectThisHit = false;
292  break;
293  }
294 
295  reco::HitPairListPtr::iterator removeItr = std::find(removeHitList.begin(),removeHitList.end(),hit3D);
296 
297  if (removeItr != removeHitList.end()) deleteVec.emplace_back(removeHitList,removeItr);
298  //else std::cout << "======>> Did not find 3D hit to remove from list for 2D hit! <<+++++++++" << std::endl;
299  }
300 
301  if (rejectThisHit)
302  {
303  for(auto& rejectPair : deleteVec) rejectPair.first.erase(rejectPair.second);
304 
305  usedHitPairList.push_back(hit3D);
306  }
307  }
308  }
309 
310  hitSet.insert(pair.first);
311  }
312 
313  // Now we go through the list of candidates and delete those which are unworthy of being processed...
314  if (!usedHitPairList.empty())
315  {
316  // Loop through the hits watching out for double counting
317  const reco::ClusterHit3D* lastHit3D = 0;
318 
319  for(const auto& hit3D : usedHitPairList)
320  {
321  if (hit3D == lastHit3D) continue;
322 
323  reco::HitPairListPtr::iterator hit3DItr = std::find(hitPairVector.begin(),hitPairVector.end(),hit3D);
324 
325  if (hit3DItr != hitPairVector.end())
326  {
327  // Mark the hit
328  hit3D->setStatusBit(reco::ClusterHit3D::REJECTEDHIT);
329 
330  // Remove from the cluster's hit container
331  hitPairVector.erase(hit3DItr);
332 
333  // If the clustering algorithm includes edges then need to get rid of those as well
334  if (!clusterParams.getHit3DToEdgeMap().empty())
335  {
336  reco::Hit3DToEdgeMap& edgeMap = clusterParams.getHit3DToEdgeMap();
337 
338  edgeMap.erase(edgeMap.find(hit3D));
339  }
340  }
341 
342  lastHit3D = hit3D;
343  }
344 // removeUsedHitsFromMap(clusterParams, usedHitPairList, hit2DToClusterMap);
345  }
346 
347  // First stage of feature extraction runs here
348  m_pcaAlg.PCAAnalysis_3D(hitPairVector, clusterParams.getFullPCA());
349 
350  // Must have a valid pca
351  if (clusterParams.getFullPCA().getSvdOK())
352  {
353  // Set the skeleton PCA to make sure it has some value
354  clusterParams.getSkeletonPCA() = clusterParams.getFullPCA();
355 
356  // Add the "good" hits to our cluster parameters
357  for(const auto& hit2D : hitSet)
358  {
359  hit2D->setStatusBit(reco::ClusterHit2D::USED);
360  clusterParams.UpdateParameters(hit2D);
361  }
362  }
363  }
364  }
365 
366  return;
367 }
bool getSvdOK() const
Definition: Cluster3D.h:224
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
intermediate_table::iterator iterator
reco::PrincipalComponents & getSkeletonPCA()
Definition: Cluster3D.h:406
reco::Hit2DToHit3DListMap & getHit2DToHit3DListMap()
Definition: Cluster3D.h:403
Hit has been rejected for any reason.
Definition: Cluster3D.h:92
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:407
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:404
reco::PlaneToClusterParamsMap & getClusterParams()
Definition: Cluster3D.h:402
Int_t max
Definition: plot.C:27
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:405
std::unordered_map< const reco::ClusterHit2D *, reco::HitPairListPtr > Hit2DToHit3DListMap
Definition: Cluster3D.h:327
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
void UpdateParameters(const reco::ClusterHit2D *hit)
Definition: Cluster3D.h:380
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
Int_t min
Definition: plot.C:26
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:326
void lar_cluster3d::ClusterParamsBuilder::removeUsedHitsFromMap ( reco::ClusterParameters clusterParams,
reco::HitPairListPtr usedHitPairList,
reco::Hit2DToClusterMap hit2DToClusterMap 
) const
private

Definition at line 369 of file ClusterParamsBuilder.cxx.

372 {
373  // Clean up our hit to cluster map
374  for(const auto& hit3D : usedHitPairList)
375  {
376  for(const auto& hit2D : hit3D->getHits())
377  {
378  if (!hit2D) continue;
379 
380  reco::Hit2DToClusterMap::iterator hitToClusMapItr = hit2DToClusterMap.find(hit2D);
381 
382  // I am pretty sure this can't happen but let's check anyway...
383  if (hitToClusMapItr == hit2DToClusterMap.end())
384  {
385  std::cout << "*********** COULD NOT FIND ENTRY FOR 2D HIT! **************" << std::endl;
386  break;
387  }
388 
389  // Ok, the same hit can be shared in the same cluster so must be careful here
390  // First loop over clusters looking for match
391  reco::ClusterToHitPairSetMap::iterator clusToHit3DMapItr = hitToClusMapItr->second.find(&clusterParams);
392 
393  // This also can't happen
394  if (clusToHit3DMapItr == hitToClusMapItr->second.end())
395  {
396  std::cout << "************ DUCK! THE SKY HAS FALLEN!! *********" << std::endl;
397  break;
398  }
399 
400  // If this hit is shared by more than one 3D hit then pick the right one
401  if (clusToHit3DMapItr->second.size() > 1)
402  {
403  reco::HitPairSetPtr::iterator hit3DItr = clusToHit3DMapItr->second.find(hit3D);
404 
405  clusToHit3DMapItr->second.erase(hit3DItr);
406  }
407  else
408  hitToClusMapItr->second.erase(clusToHit3DMapItr);
409 
410  }
411  }
412 
413  return;
414 }
intermediate_table::iterator iterator

Member Data Documentation

double lar_cluster3d::ClusterParamsBuilder::m_clusterMaxLostFraction
private

Definition at line 86 of file ClusterParamsBuilder.h.

Referenced by BuildClusterInfo(), and configure().

size_t lar_cluster3d::ClusterParamsBuilder::m_clusterMinHits
private

Data members to follow.

Definition at line 84 of file ClusterParamsBuilder.h.

Referenced by BuildClusterInfo(), and configure().

double lar_cluster3d::ClusterParamsBuilder::m_clusterMinUniqueFraction
private

Definition at line 85 of file ClusterParamsBuilder.h.

Referenced by BuildClusterInfo(), and configure().

PrincipalComponentsAlg lar_cluster3d::ClusterParamsBuilder::m_pcaAlg
private

Definition at line 88 of file ClusterParamsBuilder.h.

Referenced by FillClusterParams().


The documentation for this class was generated from the following files: