NNClusters.h
Go to the documentation of this file.
1 #ifndef NNClusters_h
2 #define NNClusters_h 1
3 
4 /** File with various classes for a generic nearest neighbour type clustering.
5 */
6 
7 #include <list>
8 #include <vector>
9 #include <algorithm>
10 
11 #include "CLHEP/Vector/ThreeVector.h"
12 
13 #include "RecoAlg/ClusterShapes.h"
14 
15 namespace gar{
16  namespace rec{
17  namespace alg{
18 
19  // forward declarations:
20 
21  template <class U>
23 
24 
25  /** Simple nearest neighbour (NN) clustering algorithm. Users have to provide an input iterator of
26  * GenericHit objects and an output iterator for the clusters found. The predicate has to have
27  * a method with the following signature: bool mergeHits( GenericHit<T>*, GenericHit<T>*) where
28  * T is the original (LCIO) type of the hit objects. All pairs of hits for which this method returns
29  * 'true' will be merged into one output cluster - all other pairs of hits will be in distinct
30  * clusters.
31  *
32  * $see GenericCluster
33  * @see GenericHit
34  * @see NNDistance
35  *
36  * @author F.Gaede (DESY)
37  * @version $Id: NNClusters.h,v 1.5 2007-06-05 15:35:49 engels Exp $
38  */
39 
40  template <class In, class Out, class Pred >
41  void cluster( In first, In last, Out result, Pred* pred ) {
42 
43  //unused clang caught it: typedef typename In::value_type GenericHitPtr ;
44  typedef typename Pred::hit_type HitType ;
45 
46  typedef std::vector< GenericCluster<HitType >* > ClusterList ;
47 
48  ClusterList tmp ;
49  tmp.reserve( 1024 ) ;
50 
51  // int i(0),j(0) ;
52 
53  while( first != last ) {
54 
55  // j=i+1 ;
56 
57  for( In other = first+1 ; other != last ; other ++ ) {
58 
59  // std::cout << " in nested loop " << i << " , " << j << std::endl ;
60 
61  if( pred->mergeHits( (*first) , (*other) ) ) {
62 
63  if( (*first)->second == 0 && (*other)->second == 0 ) { // no cluster exists
64 
66 
67  cl->addHit( (*other) ) ;
68 
69  tmp.push_back( cl ) ;
70 
71  }
72  else if( (*first)->second != 0 && (*other)->second != 0 ) { // two clusters
73 
74  // if( (*first)->second == (*other)->second )
75  // std::cout << " Merging identical clusters !? " << std::endl ;
76 
77  if( (*first)->second != (*other)->second ) // this is a bug fix for old gcc 3.2 compiler !
78  (*first)->second->mergeClusters( (*other)->second ) ;
79 
80  } else { // one cluster exists
81 
82  if( (*first)->second != 0 ) {
83 
84  (*first)->second->addHit( (*other) ) ;
85 
86  } else {
87 
88  (*other)->second->addHit( (*first) ) ;
89  }
90  }
91 
92  } // dCut
93  // ++j ;
94  }
95  // ++i ;
96  ++first ;
97  }
98 
99  // remove empty clusters
100  // std::remove_copy_if( tmp.begin() , tmp.end() , result , &empty_list< GenericCluster<HitType > > ) ;
101 
102  for( typename ClusterList::iterator i = tmp.begin(); i != tmp.end() ; i++ ){
103 
104  if( (*i)->size() > 0 ) {
105 
106  result++ = *i ;
107  }
108  else { delete *i ; }
109  }
110  }
111 
112  /** Templated class for generic hit type objects that are to be clustered with
113  * an NN-like clustering algorithm. Holds a pointer to a generalized cluster
114  * object that is templated with the same type.
115  *
116  * @see GenericCluster
117  * @author F.Gaede (DESY)
118  * @version $Id: NNClusters.h,v 1.5 2007-06-05 15:35:49 engels Exp $
119  */
120  template <class T>
121  class GenericHit : public std::pair< T*, GenericCluster<T>* >{
122 
123  typedef T value_type ;
124  typedef std::pair< T*, GenericCluster<T>* > Pair ;
125 
126  public:
127 
128  /** Default c'tor takes a pointer to the original hit type object. The optioal index can be used to
129  * code nearest neighbour bins, e.g. in z-coordinate to speed up the clustering process.
130  */
131  GenericHit(T* hit, int index0 = 0 ) : Index0( index0 ) {
132  Pair::first = hit ;
133  Pair::second = 0 ;
134  }
135 
136  /** C'tor that also takes a pointer to the cluster this hit belongs to - in case seed hits/clusters are used.
137  */
138  GenericHit(T* hit , GenericCluster<T>* cl , int index0 = 0) : Index0( index0 ) {
139  Pair::first = hit ;
140  Pair::second = cl ;
141  }
142 
143  /** Index that can be used to code nearest neighbour bins, e.g. in z-coordinate
144  * to speed up the clustering process.
145  */
146  int Index0 ;
147 
148  protected:
149  /** Don't allow default c'tor w/o hit */
150  GenericHit() ;
151  } ;
152 
153 
154  /** Templated class for generic clusters of GenericHits that are clustered with
155  * an NN-like clustering algorithm. Effectively this is just a list of hits.
156  *
157  * @see GenericHit
158  * @author F.Gaede (DESY)
159  * @version $Id: NNClusters.h,v 1.5 2007-06-05 15:35:49 engels Exp $
160  */
161  template <class T >
162  class GenericCluster : public std::list< GenericHit<T> * > {
163 
164  public :
165 
166  /** C'tor that takes the first hit */
168  addHit( hit ) ;
169  }
170 
171  /** Add a hit to this cluster - updates the hit's pointer to cluster */
173 
174  hit->second = this ;
175  this->push_back( hit ) ;
176 
177  }
178 
179  /** Merges all hits from the other cluster cl into this cluster */
181 
182  for( typename GenericCluster<T>::iterator it = cl->begin() ; it != cl->end() ; it++ ){
183  (*it)->second = this ;
184  }
185  this->merge( *cl ) ;
186  }
187  } ;
188 
189 
190  /** Helper vector of GenericHit<T> taking care of memory management, i.e. deletes all
191  * GenericHit<T> objects when it goes out of scope.
192  */
193  template <class T>
194  class GenericHitVec : public std::vector< GenericHit<T>* > {
195  typedef std::vector< GenericHit<T>* > Vector ;
196  public:
198  for( typename GenericHitVec::iterator i = Vector::begin() ; i != Vector::end() ; i++) delete *i ;
199  }
200  };
201 
202 
203  /** Helper method that copies all hit pointers from an LCIO collection that fullfill the predicate to
204  * a GenericHitVec. The predicate can either be a bool funtion or functor that takes a T*, e.g.
205  * @see EnergyCut
206  */
207  template <class T, class Pred>
209 
210  for( unsigned int i=0 ; i < vec.size() ; i++ ){
211 
212  T* hit = dynamic_cast<T*>( vec.at(i) ) ;
213 
214  if( pred( hit ) ){
215 
216  v.push_back( new GenericHit<T>( hit ) ) ;
217  }
218  }
219  }
220 
221  /** Same as addToGenericHitVec(GenericHitVec<T>& v, CaloHitList vec, Pred pred ) except that an additional
222  * order function/functor can be given that defines the index of the hit, e.g.
223  * @see ZIndex.
224  */
225  template <class T, class Pred, class Order>
226  void addToGenericHitVec(GenericHitVec<T>& v, CaloHitVec vec, Pred pred , Order order ){
227 
228  for( unsigned int i=0 ; i < vec.size() ; i++ ){
229 
230  T* hit = dynamic_cast<T*>( vec.at(i) ) ;
231 
232  if( pred( hit ) ){
233 
234  v.push_back( new GenericHit<T>( hit , order(hit) ) ) ;
235  }
236  }
237  }
238 
239  /** Helper vector of GenericCluster<T> taking care of memory management.
240  */
241  template <class T>
242  class GenericClusterVec : public std::list< GenericCluster<T>* > {
243  typedef std::list< GenericCluster<T>* > List ;
244  public:
246  for( typename GenericClusterVec::iterator i = List::begin() ; i != List::end() ; i++) delete *i ;
247  }
248  };
249 
250 
251  /** Simple predicate class for NN clustering. Requires
252  * PosType* HitClass::Position(), e.g for CalorimeterHits use: <br>
253  * NNDistance<CaloHit,float> dist( myDistCut ) ;
254  */
255  template <class HitClass, typename PosType >
256  class NNDistance{
257  public:
258 
259  /** Required typedef for cluster algorithm
260  */
261  typedef HitClass hit_type ;
262 
263  /** C'tor takes merge distance */
264  NNDistance(float dCut) : _dCutSquared( dCut*dCut ) , _dCut(dCut) {}
265 
266 
267  /** Merge condition: true if distance is less than dCut given in the C'tor.*/
269 
270  if( std::abs( h0->Index0 - h1->Index0 ) > 1 ) return false ;
271 
272  const PosType* pos0 = h0->first->Position() ;
273  const PosType* pos1 = h1->first->Position() ;
274 
275  return
276  ( pos0[0] - pos1[0] ) * ( pos0[0] - pos1[0] ) +
277  ( pos0[1] - pos1[1] ) * ( pos0[1] - pos1[1] ) +
278  ( pos0[2] - pos1[2] ) * ( pos0[2] - pos1[2] )
279  < _dCutSquared ;
280  }
281 
282  protected:
283  NNDistance() ;
284  float _dCutSquared ;
285  float _dCut ;
286  } ;
287 
288 
289  /** Simple predicate class for applying an energy cut to the objects of type T.
290  * Requires float/double T::Energy().
291  */
292  template <class T>
293  class EnergyCut{
294  public:
295  EnergyCut( double eCut ) : _eCut( eCut ) {}
296 
297  inline bool operator() (T* hit) { return hit->Energy() > _eCut ; }
298 
299  protected:
300 
301  EnergyCut() {} ;
302  double _eCut ;
303  } ;
304 
305 
306  /** Simple predicate class for computing an index from N bins of the x-coordinate of Objects
307  * that have a float/double* Position() method.
308  */
309 
310  template <class T, int N>
311  class XIndex{
312  public:
313  /** C'tor takes xmin and xmax - NB index can be negative and larger than N */
314  XIndex( float xmin , float xmax ) : _xmin( xmin ), _xmax( xmax ) {}
315 
316  inline int operator() (T* hit) {
317 
318  return (int) std::floor( ( hit->Position()[0] - _xmin ) / ( _xmax - _xmin ) * N ) ;
319  }
320 
321  protected:
322 
323  XIndex() {} ;
324  float _xmin ;
325  float _xmax ;
326  } ;
327 
328 
329  /** Helper class that creates an gar::rec::Cluster from a generic cluster with hit types that have a
330  * Position() and a Energy() method.
331  */
332  template <class T>
333  class AlgCluster{
334 
335  public:
336  // C'tor
337  AlgCluster(float xendcap ) : _xendcap( xendcap ) {}
338 
339  inline gar::rec::Cluster* operator() (GenericCluster<T>* c) {
340 
342 
343  unsigned n = c->size() ;
344  unsigned i = 0 ;
345  float rmin = 9999.;
346  float rmax = 0.;
347  std::vector<float> tmin;
348  std::vector<float> tmax;
349 
350  std::vector<float> a, t, x, y, z;
351  a.resize(n);
352  t.resize(n);
353  x.resize(n);
354  y.resize(n);
355  z.resize(n);
356 
357  for( typename GenericCluster<T>::iterator hi = c->begin(); hi != c->end() ; hi++) {
358 
359  T* hit = (*hi)->first ;
360 
361  a[i] = hit->Energy() ;
362  t[i] = hit->Time().first ;
363  x[i] = hit->Position()[0] ;
364  y[i] = hit->Position()[1] ;
365  z[i] = hit->Position()[2] ;
366 
367  clu->addHit( hit , a[i] ) ;
368 
369  //get time of first layer and last layer to compute the difference
370  float r = std::sqrt(y[i]*y[i] + z[i]*z[i]);
371  if( std::fabs(x[i]) < _xendcap ){
372  //case in barrel
373  if(rmin >= r)
374  {
375  rmin = r;
376  tmin.push_back(t[i]);
377  }
378  if(rmax <= r)
379  {
380  rmax = r;
381  tmax.push_back(t[i]);
382  }
383  }
384  else{
385  //case endcap
386  if( rmin >= std::fabs(x[i]) )
387  {
388  rmin = std::fabs(x[i]);
389  tmin.push_back(t[i]);
390  }
391  if( rmax <= std::fabs(x[i]) )
392  {
393  rmax = std::fabs(x[i]);
394  tmax.push_back(t[i]);
395  }
396  }
397 
398  ++i ;
399  }
400 
401  //get minimum time of the first layer
402  auto time_first = std::min_element( tmin.begin(), tmin.end() );
403  assert(time_first != tmin.end());
404  //get minimum time of the last layer
405  auto time_last = std::min_element( tmax.begin(), tmax.end() );
406  assert(time_last != tmax.end());
407 
408  util::ClusterShapes cs(n, a, t, x, y, z) ;
409 
410  clu->setEnergy( cs.getTotalAmplitude() ) ;
411  clu->setTime( cs.getAverageTime(), *time_first - *time_last ) ;
412  clu->setPosition( cs.getCenterOfGravity() ) ;
413 
414  // direction of cluster's PCA
415  float* d = cs.getEigenVecInertia() ;
416  clu->setEigenVectors( d );
417 
418  //Main eigenvector
419  CLHEP::Hep3Vector v( d[0], d[1], d[2] ) ;
420 
421  clu->setITheta( v.theta() ) ;
422  clu->setIPhi( v.phi() ) ;
423 
424  float param[6] ;
425 
426  // param[0] = cs.getElipsoid_r1() ;
427  param[0] = cs.getElipsoid_r_forw();
428  param[1] = cs.getElipsoid_r_back();
429  param[2] = cs.getElipsoid_r2() ;
430  param[3] = cs.getElipsoid_r3() ;
431  param[4] = cs.getElipsoid_vol() ;
432  param[5] = cs.getWidth() ;
433 
434  clu->setShape( param ) ;
435 
436  return clu;
437  }
438 
439  protected:
440  AlgCluster() {} ;
441  float _xendcap ;
442  };
443 
444  }//end namespace alg
445  }//end namespace rec
446 }//end namespace gar
447 
448 #endif
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
intermediate_table::iterator iterator
rec
Definition: tracks.py:88
AlgCluster(float xendcap)
Definition: NNClusters.h:337
void cluster(In first, In last, Out result, Pred *pred)
Definition: NNClusters.h:41
GenericHit(T *hit, GenericCluster< T > *cl, int index0=0)
Definition: NNClusters.h:138
static QCString result
enum cvn::HType HitType
void setShape(const float *shape)
Definition: Cluster.cxx:54
std::vector< gar::rec::CaloHit * > CaloHitVec
Definition: KNNClusterAlg.h:36
struct vector vector
std::list< GenericCluster< T > * > List
Definition: NNClusters.h:243
void addToGenericHitVec(GenericHitVec< T > &v, CaloHitVec vec, Pred pred)
Definition: NNClusters.h:208
void addHit(GenericHit< T > *hit)
Definition: NNClusters.h:172
QAsciiDict< Entry > cl
void setEigenVectors(const float *eigenvectors)
Definition: Cluster.cxx:49
bool mergeHits(GenericHit< HitClass > *h0, GenericHit< HitClass > *h1)
Definition: NNClusters.h:268
T abs(T value)
GenericCluster(GenericHit< T > *hit)
Definition: NNClusters.h:167
fInnerVessel push_back(Point(-578.400000, 0.000000, 0.000000))
void setEnergy(float energy)
Definition: Cluster.cxx:18
std::pair< T *, GenericCluster< T > * > Pair
Definition: NNClusters.h:124
std::void_t< T > n
void setPosition(const float *position)
Definition: Cluster.cxx:34
const double a
EnergyCut(double eCut)
Definition: NNClusters.h:295
string tmp
Definition: languages.py:63
Detector simulation of raw signals on wires.
void addHit(gar::rec::CaloHit *hit, float contribution)
Definition: Cluster.cxx:64
void mergeClusters(GenericCluster< T > *cl)
Definition: NNClusters.h:180
General GArSoft Utilities.
void setIPhi(float phi)
Definition: Cluster.cxx:44
void setITheta(float theta)
Definition: Cluster.cxx:39
list x
Definition: train.py:276
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
const char * cs
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:85
XIndex(float xmin, float xmax)
Definition: NNClusters.h:314
GenericHit(T *hit, int index0=0)
Definition: NNClusters.h:131
std::vector< GenericHit< T > * > Vector
Definition: NNClusters.h:195
void setTime(float time, float time_diff)
Definition: Cluster.cxx:28