CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
EcalClusterTools.cc
Go to the documentation of this file.
2 
7 
9 
10 
11 #include "CLHEP/Geometry/Transform3D.h"
12 
17 
18 std::pair<DetId, float> EcalClusterTools::getMaximum( const std::vector< std::pair<DetId, float> > &v_id, const EcalRecHitCollection *recHits)
19 {
20  float max = 0;
21  DetId id(0);
22  for ( size_t i = 0; i < v_id.size(); ++i ) {
23  float energy = recHitEnergy( v_id[i].first, recHits ) * v_id[i].second;
24  if ( energy > max ) {
25  max = energy;
26  id = v_id[i].first;
27  }
28  }
29  return std::pair<DetId, float>(id, max);
30 }
31 
32 
33 
34 std::pair<DetId, float> EcalClusterTools::getMaximum( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits)
35 {
36  return getMaximum( cluster.hitsAndFractions(), recHits );
37 }
38 
39 
40 
42 {
43  if ( id == DetId(0) ) {
44  return 0;
45  } else {
46  EcalRecHitCollection::const_iterator it = recHits->find( id );
47  if ( it != recHits->end() ) {
48  return (*it).energy();
49  } else {
50  //throw cms::Exception("EcalRecHitNotFound") << "The recHit corresponding to the DetId" << id.rawId() << " not found in the EcalRecHitCollection";
51  // the recHit is not in the collection (hopefully zero suppressed)
52  return 0;
53  }
54  }
55  return 0;
56 }
57 
58 
59 // Returns the energy in a rectangle of crystals
60 // specified in eta by ixMin and ixMax
61 // and in phi by iyMin and iyMax
62 //
63 // Reference picture (X=seed crystal)
64 // iy ___________
65 // 2 |_|_|_|_|_|
66 // 1 |_|_|_|_|_|
67 // 0 |_|_|X|_|_|
68 // -1 |_|_|_|_|_|
69 // -2 |_|_|_|_|_|
70 // -2 -1 0 1 2 ix
71 float EcalClusterTools::matrixEnergy( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology, DetId id, int ixMin, int ixMax, int iyMin, int iyMax )
72 {
73  // fast version
75  float energy = 0;
76  for ( int i = ixMin; i <= ixMax; ++i ) {
77  for ( int j = iyMin; j <= iyMax; ++j ) {
78  cursor.home();
79  cursor.offsetBy( i, j );
80  energy += recHitEnergy( *cursor, recHits );
81  }
82  }
83  // slow elegant version
84  //float energy = 0;
85  //std::vector<DetId> v_id = matrixDetId( topology, id, ixMin, ixMax, iyMin, iyMax );
86  //for ( std::vector<DetId>::const_iterator it = v_id.begin(); it != v_id.end(); ++it ) {
87  // energy += recHitEnergy( *it, recHits );
88  //}
89  return energy;
90 }
91 
92 
93 
94 std::vector<DetId> EcalClusterTools::matrixDetId( const CaloTopology* topology, DetId id, int ixMin, int ixMax, int iyMin, int iyMax )
95 {
97  std::vector<DetId> v;
98  for ( int i = ixMin; i <= ixMax; ++i ) {
99  for ( int j = iyMin; j <= iyMax; ++j ) {
100  cursor.home();
101  cursor.offsetBy( i, j );
102  if ( *cursor != DetId(0) ) v.push_back( *cursor );
103  }
104  }
105  return v;
106 }
107 
108 
109 
110 float EcalClusterTools::e2x2( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
111 {
112  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
113  std::list<float> energies;
114  energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 0, -1, 0 ) );
115  energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 0, 0, 1 ) );
116  energies.push_back( matrixEnergy( cluster, recHits, topology, id, 0, 1, 0, 1 ) );
117  energies.push_back( matrixEnergy( cluster, recHits, topology, id, 0, 1, -1, 0 ) );
118 
119 
120  return *std::max_element(energies.begin(),energies.end());
121 
122 }
123 
124 
125 
126 float EcalClusterTools::e3x2( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
127 {
128  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
129  std::list<float> energies;
130  energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 1, -1, 0 ) );
131  energies.push_back( matrixEnergy( cluster, recHits, topology, id, 0, 1, -1, 1 ) );
132  energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 1, 0, 1 ) );
133  energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 0, -1, 1 ) );
134  return *std::max_element(energies.begin(),energies.end());
135 }
136 
137 
138 
139 float EcalClusterTools::e3x3( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
140 {
141  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
142  return matrixEnergy( cluster, recHits, topology, id, -1, 1, -1, 1 );
143 }
144 
145 
146 
147 float EcalClusterTools::e4x4( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
148 {
149  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
150  std::list<float> energies;
151  energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 2, -2, 1 ) );
152  energies.push_back( matrixEnergy( cluster, recHits, topology, id, -2, 1, -2, 1 ) );
153  energies.push_back( matrixEnergy( cluster, recHits, topology, id, -2, 1, -1, 2 ) );
154  energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 2, -1, 2 ) );
155  return *std::max_element(energies.begin(),energies.end());
156 }
157 
158 
159 
160 float EcalClusterTools::e5x5( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
161 {
162  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
163  return matrixEnergy( cluster, recHits, topology, id, -2, 2, -2, 2 );
164 }
165 
166 
167 
168 float EcalClusterTools::eMax( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits )
169 {
170  return getMaximum( cluster.hitsAndFractions(), recHits ).second;
171 }
172 
173 
174 
175 float EcalClusterTools::e2nd( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits )
176 {
177  std::list<float> energies;
178  std::vector< std::pair<DetId, float> > v_id = cluster.hitsAndFractions();
179  if ( v_id.size() < 2 ) return 0;
180  for ( size_t i = 0; i < v_id.size(); ++i ) {
181  energies.push_back( recHitEnergy( v_id[i].first, recHits ) * v_id[i].second );
182  }
183  energies.sort();
184  return *--(--energies.end());
185 
186 
187 }
188 
189 
190 
191 float EcalClusterTools::e2x5Right( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
192 {
193  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
194  return matrixEnergy( cluster, recHits, topology, id, 1, 2, -2, 2 );
195 }
196 
197 
198 
199 float EcalClusterTools::e2x5Left( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
200 {
201  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
202  return matrixEnergy( cluster, recHits, topology, id, -2, -1, -2, 2 );
203 }
204 
205 
206 //
207 float EcalClusterTools::e2x5Top( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
208 {
209  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
210  return matrixEnergy( cluster, recHits, topology, id, -2, 2, 1, 2 );
211 }
212 
213 
214 
215 float EcalClusterTools::e2x5Bottom( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
216 {
217  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
218  return matrixEnergy( cluster, recHits, topology, id, -2, 2, -2, -1 );
219 }
220 
221 // Energy in 2x5 strip containing the max crystal.
222 // Adapted from code by Sam Harper
223 float EcalClusterTools::e2x5Max( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
224 {
225  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
226 
227  // 1x5 strip left of seed
228  float left = matrixEnergy( cluster, recHits, topology, id, -1, -1, -2, 2 );
229  // 1x5 strip right of seed
230  float right = matrixEnergy( cluster, recHits, topology, id, 1, 1, -2, 2 );
231  // 1x5 strip containing seed
232  float centre = matrixEnergy( cluster, recHits, topology, id, 0, 0, -2, 2 );
233 
234  // Return the maximum of (left+center) or (right+center) strip
235  return left > right ? left+centre : right+centre;
236 }
237 
238 
239 float EcalClusterTools::e1x5( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
240 {
241  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
242  return matrixEnergy( cluster, recHits, topology, id, 0, 0, -2, 2 );
243 }
244 
245 
246 
247 float EcalClusterTools::e5x1( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
248 {
249  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
250  return matrixEnergy( cluster, recHits, topology, id, -2, 2, 0, 0 );
251 }
252 
253 
254 
255 float EcalClusterTools::e1x3( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
256 {
257  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
258  return matrixEnergy( cluster, recHits, topology, id, 0, 0, -1, 1 );
259 }
260 
261 
262 
263 float EcalClusterTools::e3x1( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
264 {
265  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
266  return matrixEnergy( cluster, recHits, topology, id, -1, 1, 0, 0 );
267 }
268 
269 
270 
271 float EcalClusterTools::eLeft( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
272 {
273  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
274  return matrixEnergy( cluster, recHits, topology, id, -1, -1, 0, 0 );
275 }
276 
277 
278 
279 float EcalClusterTools::eRight( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
280 {
281  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
282  return matrixEnergy( cluster, recHits, topology, id, 1, 1, 0, 0 );
283 }
284 
285 
286 
287 float EcalClusterTools::eTop( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
288 {
289  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
290  return matrixEnergy( cluster, recHits, topology, id, 0, 0, 1, 1 );
291 }
292 
293 
294 
295 float EcalClusterTools::eBottom( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
296 {
297  DetId id = getMaximum( cluster.hitsAndFractions(), recHits ).first;
298  return matrixEnergy( cluster, recHits, topology, id, 0, 0, -1, -1 );
299 }
300 
301 
302 
303 std::vector<float> EcalClusterTools::energyBasketFractionEta( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits )
304 {
305  std::vector<float> basketFraction( 2 * EBDetId::kModulesPerSM );
306  float clusterEnergy = cluster.energy();
307  std::vector< std::pair<DetId, float> > v_id = cluster.hitsAndFractions();
308  if ( v_id[0].first.subdetId() != EcalBarrel ) {
309  edm::LogWarning("EcalClusterTools::energyBasketFractionEta") << "Trying to get basket fraction for endcap basic-clusters. Basket fractions can be obtained ONLY for barrel basic-clusters. Returning empty vector.";
310  return basketFraction;
311  }
312  for ( size_t i = 0; i < v_id.size(); ++i ) {
313  basketFraction[ EBDetId(v_id[i].first).im()-1 + EBDetId(v_id[i].first).positiveZ()*EBDetId::kModulesPerSM ] += recHitEnergy( v_id[i].first, recHits ) * v_id[i].second / clusterEnergy;
314  }
315  std::sort( basketFraction.rbegin(), basketFraction.rend() );
316  return basketFraction;
317 }
318 
319 
320 
321 std::vector<float> EcalClusterTools::energyBasketFractionPhi( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits )
322 {
323  std::vector<float> basketFraction( 2 * (EBDetId::MAX_IPHI / EBDetId::kCrystalsInPhi) );
324  float clusterEnergy = cluster.energy();
325  std::vector< std::pair<DetId, float> > v_id = cluster.hitsAndFractions();
326  if ( v_id[0].first.subdetId() != EcalBarrel ) {
327  edm::LogWarning("EcalClusterTools::energyBasketFractionPhi") << "Trying to get basket fraction for endcap basic-clusters. Basket fractions can be obtained ONLY for barrel basic-clusters. Returning empty vector.";
328  return basketFraction;
329  }
330  for ( size_t i = 0; i < v_id.size(); ++i ) {
331  basketFraction[ (EBDetId(v_id[i].first).iphi()-1)/EBDetId::kCrystalsInPhi + EBDetId(v_id[i].first).positiveZ()*EBDetId::kTowersInPhi] += recHitEnergy( v_id[i].first, recHits ) * v_id[i].second / clusterEnergy;
332  }
333  std::sort( basketFraction.rbegin(), basketFraction.rend() );
334  return basketFraction;
335 }
336 
337 
338 
339 std::vector<EcalClusterTools::EcalClusterEnergyDeposition> EcalClusterTools::getEnergyDepTopology( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, bool logW, float w0 )
340 {
341  std::vector<EcalClusterTools::EcalClusterEnergyDeposition> energyDistribution;
342  // init a map of the energy deposition centered on the
343  // cluster centroid. This is for momenta calculation only.
344  CLHEP::Hep3Vector clVect(cluster.position().x(), cluster.position().y(), cluster.position().z());
345  CLHEP::Hep3Vector clDir(clVect);
346  clDir*=1.0/clDir.mag();
347  // in the transverse plane, axis perpendicular to clusterDir
348  CLHEP::Hep3Vector theta_axis(clDir.y(),-clDir.x(),0.0);
349  theta_axis *= 1.0/theta_axis.mag();
350  CLHEP::Hep3Vector phi_axis = theta_axis.cross(clDir);
351 
352  std::vector< std::pair<DetId, float> > clusterDetIds = cluster.hitsAndFractions();
353 
355  EcalRecHit testEcalRecHit;
356  std::vector< std::pair<DetId, float> >::iterator posCurrent;
357  // loop over crystals
358  for(posCurrent=clusterDetIds.begin(); posCurrent!=clusterDetIds.end(); ++posCurrent) {
359  EcalRecHitCollection::const_iterator itt = recHits->find( (*posCurrent).first );
360  testEcalRecHit=*itt;
361 
362  if(( (*posCurrent).first != DetId(0)) && (recHits->find( (*posCurrent).first ) != recHits->end())) {
363  clEdep.deposited_energy = testEcalRecHit.energy() * (*posCurrent).second;
364  // if logarithmic weight is requested, apply cut on minimum energy of the recHit
365  if(logW) {
366  //double w0 = parameterMap_.find("W0")->second;
367 
368  double weight = std::max(0.0, w0 + log(fabs(clEdep.deposited_energy)/cluster.energy()) );
369  if(weight==0) {
370  LogDebug("ClusterShapeAlgo") << "Crystal has insufficient energy: E = "
371  << clEdep.deposited_energy << " GeV; skipping... ";
372  continue;
373  }
374  else LogDebug("ClusterShapeAlgo") << "===> got crystal. Energy = " << clEdep.deposited_energy << " GeV. ";
375  }
376  DetId id_ = (*posCurrent).first;
377  const CaloCellGeometry *this_cell = geometry->getSubdetectorGeometry(id_)->getGeometry(id_);
378  GlobalPoint cellPos = this_cell->getPosition();
379  CLHEP::Hep3Vector gblPos (cellPos.x(),cellPos.y(),cellPos.z()); //surface position?
380  // Evaluate the distance from the cluster centroid
381  CLHEP::Hep3Vector diff = gblPos - clVect;
382  // Important: for the moment calculation, only the "lateral distance" is important
383  // "lateral distance" r_i = distance of the digi position from the axis Origin-Cluster Center
384  // ---> subtract the projection on clDir
385  CLHEP::Hep3Vector DigiVect = diff - diff.dot(clDir)*clDir;
386  clEdep.r = DigiVect.mag();
387  LogDebug("ClusterShapeAlgo") << "E = " << clEdep.deposited_energy
388  << "\tdiff = " << diff.mag()
389  << "\tr = " << clEdep.r;
390  clEdep.phi = DigiVect.angle(theta_axis);
391  if(DigiVect.dot(phi_axis)<0) clEdep.phi = 2 * M_PI - clEdep.phi;
392  energyDistribution.push_back(clEdep);
393  }
394  }
395  return energyDistribution;
396 }
397 
398 
399 
400 std::vector<float> EcalClusterTools::lat( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, bool logW, float w0 )
401 {
402  std::vector<EcalClusterTools::EcalClusterEnergyDeposition> energyDistribution = getEnergyDepTopology( cluster, recHits, geometry, logW, w0 );
403 
404  std::vector<float> lat;
405  double r, redmoment=0;
406  double phiRedmoment = 0 ;
407  double etaRedmoment = 0 ;
408  int n,n1,n2,tmp;
409  int clusterSize=energyDistribution.size();
410  float etaLat_, phiLat_, lat_;
411  if (clusterSize<3) {
412  etaLat_ = 0.0 ;
413  lat_ = 0.0;
414  lat.push_back(0.);
415  lat.push_back(0.);
416  lat.push_back(0.);
417  return lat;
418  }
419 
420  n1=0; n2=1;
421  if (energyDistribution[1].deposited_energy >
422  energyDistribution[0].deposited_energy)
423  {
424  tmp=n2; n2=n1; n1=tmp;
425  }
426  for (int i=2; i<clusterSize; i++) {
427  n=i;
428  if (energyDistribution[i].deposited_energy >
429  energyDistribution[n1].deposited_energy)
430  {
431  tmp = n2;
432  n2 = n1; n1 = i; n=tmp;
433  } else {
434  if (energyDistribution[i].deposited_energy >
435  energyDistribution[n2].deposited_energy)
436  {
437  tmp=n2; n2=i; n=tmp;
438  }
439  }
440 
441  r = energyDistribution[n].r;
442  redmoment += r*r* energyDistribution[n].deposited_energy;
443  double rphi = r * cos (energyDistribution[n].phi) ;
444  phiRedmoment += rphi * rphi * energyDistribution[n].deposited_energy;
445  double reta = r * sin (energyDistribution[n].phi) ;
446  etaRedmoment += reta * reta * energyDistribution[n].deposited_energy;
447  }
448  double e1 = energyDistribution[n1].deposited_energy;
449  double e2 = energyDistribution[n2].deposited_energy;
450 
451  lat_ = redmoment/(redmoment+2.19*2.19*(e1+e2));
452  phiLat_ = phiRedmoment/(phiRedmoment+2.19*2.19*(e1+e2));
453  etaLat_ = etaRedmoment/(etaRedmoment+2.19*2.19*(e1+e2));
454 
455  lat.push_back(etaLat_);
456  lat.push_back(phiLat_);
457  lat.push_back(lat_);
458  return lat;
459 }
460 
461 
462 
464 {
465  // find mean energy position of a 5x5 cluster around the maximum
466  math::XYZVector meanPosition(0.0, 0.0, 0.0);
467  std::vector<DetId> v_id = matrixDetId( topology, getMaximum( cluster, recHits ).first, -2, 2, -2, 2 );
468  for ( std::vector<DetId>::const_iterator it = v_id.begin(); it != v_id.end(); ++it ) {
469  GlobalPoint positionGP = geometry->getSubdetectorGeometry( *it )->getGeometry( *it )->getPosition();
470  math::XYZVector position(positionGP.x(),positionGP.y(),positionGP.z());
471  meanPosition = meanPosition + recHitEnergy( *it, recHits ) * position;
472  }
473  return meanPosition / e5x5( cluster, recHits, topology );
474 }
475 
476 
477 
478 //returns mean energy weighted eta/phi in crystals from the seed
479 //iPhi is not defined for endcap and is returned as zero
480 //return <eta,phi>
481 //we have an issue in working out what to do for negative energies
482 //I (Sam Harper) think it makes sense to ignore crystals with E<0 in the calculation as they are ignored
483 //in the sigmaIEtaIEta calculation (well they arent fully ignored, they do still contribute to the e5x5 sum
484 //in the sigmaIEtaIEta calculation but not here)
485 std::pair<float,float> EcalClusterTools::mean5x5PositionInLocalCrysCoord(const reco::BasicCluster &cluster, const EcalRecHitCollection* recHits,const CaloTopology *topology)
486 {
487  DetId seedId = getMaximum( cluster, recHits ).first;
488  float meanDEta=0.;
489  float meanDPhi=0.;
490  float energySum=0.;
491 
492  std::vector<DetId> v_id = matrixDetId( topology,seedId, -2, 2, -2, 2 );
493  for ( std::vector<DetId>::const_iterator it = v_id.begin(); it != v_id.end(); ++it ) {
494  float energy = recHitEnergy(*it,recHits);
495  if(energy<0.) continue;//skipping negative energy crystals
496  meanDEta += energy * getNrCrysDiffInEta(*it,seedId);
497  meanDPhi += energy * getNrCrysDiffInPhi(*it,seedId);
498  energySum +=energy;
499  }
500  meanDEta /=energySum;
501  meanDPhi /=energySum;
502  return std::pair<float,float>(meanDEta,meanDPhi);
503 }
504 
505 //returns mean energy weighted x/y in normalised crystal coordinates
506 //only valid for endcap, returns 0,0 for barrel
507 //we have an issue in working out what to do for negative energies
508 //I (Sam Harper) think it makes sense to ignore crystals with E<0 in the calculation as they are ignored
509 //in the sigmaIEtaIEta calculation (well they arent fully ignored, they do still contribute to the e5x5 sum
510 //in the sigmaIEtaIEta calculation but not here)
511 std::pair<float,float> EcalClusterTools::mean5x5PositionInXY(const reco::BasicCluster &cluster, const EcalRecHitCollection* recHits,const CaloTopology *topology)
512 {
513  DetId seedId = getMaximum( cluster, recHits ).first;
514 
515  std::pair<float,float> meanXY(0.,0.);
516  if(seedId.subdetId()==EcalBarrel) return meanXY;
517 
518  float energySum=0.;
519 
520  std::vector<DetId> v_id = matrixDetId( topology,seedId, -2, 2, -2, 2 );
521  for ( std::vector<DetId>::const_iterator it = v_id.begin(); it != v_id.end(); ++it ) {
522  float energy = recHitEnergy(*it,recHits);
523  if(energy<0.) continue;//skipping negative energy crystals
524  meanXY.first += energy * getNormedIX(*it);
525  meanXY.second += energy * getNormedIY(*it);
526  energySum +=energy;
527  }
528  meanXY.first/=energySum;
529  meanXY.second/=energySum;
530  return meanXY;
531 }
532 
533 
534 std::vector<float> EcalClusterTools::covariances(const reco::BasicCluster &cluster, const EcalRecHitCollection* recHits, const CaloTopology *topology, const CaloGeometry* geometry, float w0)
535 {
536  float e_5x5 = e5x5( cluster, recHits, topology );
537  float covEtaEta, covEtaPhi, covPhiPhi;
538  if (e_5x5 >= 0.) {
539  //double w0_ = parameterMap_.find("W0")->second;
540  std::vector< std::pair<DetId, float> > v_id = cluster.hitsAndFractions();
541  math::XYZVector meanPosition = meanClusterPosition( cluster, recHits, topology, geometry );
542 
543  // now we can calculate the covariances
544  double numeratorEtaEta = 0;
545  double numeratorEtaPhi = 0;
546  double numeratorPhiPhi = 0;
547  double denominator = 0;
548 
549  DetId id = getMaximum( v_id, recHits ).first;
551  for ( int i = -2; i <= 2; ++i ) {
552  for ( int j = -2; j <= 2; ++j ) {
553  cursor.home();
554  cursor.offsetBy( i, j );
555  float energy = recHitEnergy( *cursor, recHits );
556 
557  if ( energy <= 0 ) continue;
558 
559  GlobalPoint position = geometry->getSubdetectorGeometry(*cursor)->getGeometry(*cursor)->getPosition();
560 
561  double dPhi = position.phi() - meanPosition.phi();
562  if (dPhi > + Geom::pi()) { dPhi = Geom::twoPi() - dPhi; }
563  if (dPhi < - Geom::pi()) { dPhi = Geom::twoPi() + dPhi; }
564 
565  double dEta = position.eta() - meanPosition.eta();
566  double w = 0.;
567  w = std::max(0.0, w0 + log( energy / e_5x5 ));
568 
569  denominator += w;
570  numeratorEtaEta += w * dEta * dEta;
571  numeratorEtaPhi += w * dEta * dPhi;
572  numeratorPhiPhi += w * dPhi * dPhi;
573  }
574  }
575 
576  if (denominator != 0.0) {
577  covEtaEta = numeratorEtaEta / denominator;
578  covEtaPhi = numeratorEtaPhi / denominator;
579  covPhiPhi = numeratorPhiPhi / denominator;
580  } else {
581  covEtaEta = 999.9;
582  covEtaPhi = 999.9;
583  covPhiPhi = 999.9;
584  }
585 
586  } else {
587  // Warn the user if there was no energy in the cells and return zeroes.
588  // std::cout << "\ClusterShapeAlgo::Calculate_Covariances: no energy in supplied cells.\n";
589  covEtaEta = 0;
590  covEtaPhi = 0;
591  covPhiPhi = 0;
592  }
593  std::vector<float> v;
594  v.push_back( covEtaEta );
595  v.push_back( covEtaPhi );
596  v.push_back( covPhiPhi );
597  return v;
598 }
599 
600 
601 
602 
603 
604 
605 //for covIEtaIEta,covIEtaIPhi and covIPhiIPhi are defined but only covIEtaIEta has been actively studied
606 //instead of using absolute eta/phi it counts crystals normalised so that it gives identical results to normal covariances except near the cracks where of course its better
607 //it also does not require any eta correction function in the endcap
608 //it is multipled by an approprate crystal size to ensure it gives similar values to covariances(...)
609 std::vector<float> EcalClusterTools::localCovariances(const reco::BasicCluster &cluster, const EcalRecHitCollection* recHits,const CaloTopology *topology,float w0)
610 {
611 
612  float e_5x5 = e5x5( cluster, recHits, topology );
613  float covEtaEta, covEtaPhi, covPhiPhi;
614 
615  if (e_5x5 >= 0.) {
616  //double w0_ = parameterMap_.find("W0")->second;
617  std::vector< std::pair<DetId, float> > v_id = cluster.hitsAndFractions();
618  std::pair<float,float> mean5x5PosInNrCrysFromSeed = mean5x5PositionInLocalCrysCoord( cluster, recHits, topology );
619  std::pair<float,float> mean5x5XYPos = mean5x5PositionInXY(cluster,recHits,topology);
620 
621  // now we can calculate the covariances
622  double numeratorEtaEta = 0;
623  double numeratorEtaPhi = 0;
624  double numeratorPhiPhi = 0;
625  double denominator = 0;
626 
627  //these allow us to scale the localCov by the crystal size
628  //so that the localCovs have the same average value as the normal covs
629  const double barrelCrysSize = 0.01745; //approximate size of crystal in eta,phi in barrel
630  const double endcapCrysSize = 0.0447; //the approximate crystal size sigmaEtaEta was corrected to in the endcap
631 
632  DetId seedId = getMaximum( v_id, recHits ).first;
633 
634  bool isBarrel=seedId.subdetId()==EcalBarrel;
635  const double crysSize = isBarrel ? barrelCrysSize : endcapCrysSize;
636 
637  CaloNavigator<DetId> cursor = CaloNavigator<DetId>( seedId, topology->getSubdetectorTopology( seedId ) );
638 
639  for ( int eastNr = -2; eastNr <= 2; ++eastNr ) { //east is eta in barrel
640  for ( int northNr = -2; northNr <= 2; ++northNr ) { //north is phi in barrel
641  cursor.home();
642  cursor.offsetBy( eastNr, northNr);
643  float energy = recHitEnergy( *cursor, recHits );
644  if ( energy <= 0 ) continue;
645 
646  float dEta = getNrCrysDiffInEta(*cursor,seedId) - mean5x5PosInNrCrysFromSeed.first;
647  float dPhi = 0;
648 
649  if(isBarrel) dPhi = getNrCrysDiffInPhi(*cursor,seedId) - mean5x5PosInNrCrysFromSeed.second;
650  else dPhi = getDPhiEndcap(*cursor,mean5x5XYPos.first,mean5x5XYPos.second);
651 
652 
653  double w = std::max(0.0, w0 + log( energy / e_5x5 ));
654 
655  denominator += w;
656  numeratorEtaEta += w * dEta * dEta;
657  numeratorEtaPhi += w * dEta * dPhi;
658  numeratorPhiPhi += w * dPhi * dPhi;
659  } //end east loop
660  }//end north loop
661 
662 
663  //multiplying by crysSize to make the values compariable to normal covariances
664  if (denominator != 0.0) {
665  covEtaEta = crysSize*crysSize* numeratorEtaEta / denominator;
666  covEtaPhi = crysSize*crysSize* numeratorEtaPhi / denominator;
667  covPhiPhi = crysSize*crysSize* numeratorPhiPhi / denominator;
668  } else {
669  covEtaEta = 999.9;
670  covEtaPhi = 999.9;
671  covPhiPhi = 999.9;
672  }
673 
674 
675  } else {
676  // Warn the user if there was no energy in the cells and return zeroes.
677  // std::cout << "\ClusterShapeAlgo::Calculate_Covariances: no energy in supplied cells.\n";
678  covEtaEta = 0;
679  covEtaPhi = 0;
680  covPhiPhi = 0;
681  }
682  std::vector<float> v;
683  v.push_back( covEtaEta );
684  v.push_back( covEtaPhi );
685  v.push_back( covPhiPhi );
686  return v;
687 }
688 
689 
690 
691 
692 double EcalClusterTools::zernike20( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, double R0, bool logW, float w0 )
693 {
694  return absZernikeMoment( cluster, recHits, geometry, 2, 0, R0, logW, w0 );
695 }
696 
697 
698 
699 double EcalClusterTools::zernike42( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, double R0, bool logW, float w0 )
700 {
701  return absZernikeMoment( cluster, recHits, geometry, 4, 2, R0, logW, w0 );
702 }
703 
704 
705 
706 double EcalClusterTools::absZernikeMoment( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, int n, int m, double R0, bool logW, float w0 )
707 {
708  // 1. Check if n,m are correctly
709  if ((m>n) || ((n-m)%2 != 0) || (n<0) || (m<0)) return -1;
710 
711  // 2. Check if n,R0 are within validity Range :
712  // n>20 or R0<2.19cm just makes no sense !
713  if ((n>20) || (R0<=2.19)) return -1;
714  if (n<=5) return fast_AbsZernikeMoment(cluster, recHits, geometry, n, m, R0, logW, w0 );
715  else return calc_AbsZernikeMoment(cluster, recHits, geometry, n, m, R0, logW, w0 );
716 }
717 
718 
719 double EcalClusterTools::fast_AbsZernikeMoment(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, int n, int m, double R0, bool logW, float w0 )
720 {
721  double r,ph,e,Re=0,Im=0;
722  double TotalEnergy = cluster.energy();
723  int index = (n/2)*(n/2)+(n/2)+m;
724  std::vector<EcalClusterEnergyDeposition> energyDistribution = getEnergyDepTopology( cluster, recHits, geometry, logW, w0 );
725  int clusterSize = energyDistribution.size();
726  if(clusterSize < 3) return 0.0;
727 
728  for (int i=0; i<clusterSize; i++)
729  {
730  r = energyDistribution[i].r / R0;
731  if (r<1) {
732  std::vector<double> pol;
733  pol.push_back( f00(r) );
734  pol.push_back( f11(r) );
735  pol.push_back( f20(r) );
736  pol.push_back( f22(r) );
737  pol.push_back( f31(r) );
738  pol.push_back( f33(r) );
739  pol.push_back( f40(r) );
740  pol.push_back( f42(r) );
741  pol.push_back( f44(r) );
742  pol.push_back( f51(r) );
743  pol.push_back( f53(r) );
744  pol.push_back( f55(r) );
745  ph = (energyDistribution[i]).phi;
746  e = energyDistribution[i].deposited_energy;
747  Re = Re + e/TotalEnergy * pol[index] * cos( (double) m * ph);
748  Im = Im - e/TotalEnergy * pol[index] * sin( (double) m * ph);
749  }
750  }
751  return sqrt(Re*Re+Im*Im);
752 }
753 
754 
755 
756 double EcalClusterTools::calc_AbsZernikeMoment(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, int n, int m, double R0, bool logW, float w0 )
757 {
758  double r, ph, e, Re=0, Im=0, f_nm;
759  double TotalEnergy = cluster.energy();
760  std::vector<EcalClusterEnergyDeposition> energyDistribution = getEnergyDepTopology( cluster, recHits, geometry, logW, w0 );
761  int clusterSize=energyDistribution.size();
762  if(clusterSize<3) return 0.0;
763 
764  for (int i = 0; i < clusterSize; ++i)
765  {
766  r = energyDistribution[i].r / R0;
767  if (r < 1) {
768  ph = energyDistribution[i].phi;
769  e = energyDistribution[i].deposited_energy;
770  f_nm = 0;
771  for (int s=0; s<=(n-m)/2; s++) {
772  if (s%2==0) {
773  f_nm = f_nm + factorial(n-s)*pow(r,(double) (n-2*s))/(factorial(s)*factorial((n+m)/2-s)*factorial((n-m)/2-s));
774  } else {
775  f_nm = f_nm - factorial(n-s)*pow(r,(double) (n-2*s))/(factorial(s)*factorial((n+m)/2-s)*factorial((n-m)/2-s));
776  }
777  }
778  Re = Re + e/TotalEnergy * f_nm * cos( (double) m*ph);
779  Im = Im - e/TotalEnergy * f_nm * sin( (double) m*ph);
780  }
781  }
782  return sqrt(Re*Re+Im*Im);
783 }
784 
785 //returns the crystal 'eta' from the det id
786 //it is defined as the number of crystals from the centre in the eta direction
787 //for the barrel with its eta/phi geometry it is always integer
788 //for the endcap it is fractional due to the x/y geometry
790 {
791  if(id.det()==DetId::Ecal){
792  if(id.subdetId()==EcalBarrel){
793  EBDetId ebId(id);
794  return ebId.ieta();
795  }else if(id.subdetId()==EcalEndcap){
796  float iXNorm = getNormedIX(id);
797  float iYNorm = getNormedIY(id);
798 
799  return std::sqrt(iXNorm*iXNorm+iYNorm*iYNorm);
800  }
801  }
802  return 0.;
803 }
804 
805 
806 //returns the crystal 'phi' from the det id
807 //it is defined as the number of crystals from the centre in the phi direction
808 //for the barrel with its eta/phi geometry it is always integer
809 //for the endcap it is not defined
811 {
812  if(id.det()==DetId::Ecal){
813  if(id.subdetId()==EcalBarrel){
814  EBDetId ebId(id);
815  return ebId.iphi();
816  }
817  }
818  return 0.;
819 }
820 
821 //want to map 1=-50,50=-1,51=1 and 100 to 50 so sub off one if zero or neg
823 {
824  if(id.det()==DetId::Ecal && id.subdetId()==EcalEndcap){
825  EEDetId eeId(id);
826  int iXNorm = eeId.ix()-50;
827  if(iXNorm<=0) iXNorm--;
828  return iXNorm;
829  }
830  return 0;
831 }
832 
833 //want to map 1=-50,50=-1,51=1 and 100 to 50 so sub off one if zero or neg
835 {
836  if(id.det()==DetId::Ecal && id.subdetId()==EcalEndcap){
837  EEDetId eeId(id);
838  int iYNorm = eeId.iy()-50;
839  if(iYNorm<=0) iYNorm--;
840  return iYNorm;
841  }
842  return 0;
843 }
844 
845 //nr crystals crysId is away from orgin id in eta
846 float EcalClusterTools::getNrCrysDiffInEta(const DetId& crysId,const DetId& orginId)
847 {
848  float crysIEta = getIEta(crysId);
849  float orginIEta = getIEta(orginId);
850  bool isBarrel = orginId.subdetId()==EcalBarrel;
851 
852  float nrCrysDiff = crysIEta-orginIEta;
853 
854  //no iEta=0 in barrel, so if go from positive to negative
855  //need to reduce abs(detEta) by 1
856  if(isBarrel){
857  if(crysIEta*orginIEta<0){ // -1 to 1 transition
858  if(crysIEta>0) nrCrysDiff--;
859  else nrCrysDiff++;
860  }
861  }
862  return nrCrysDiff;
863 }
864 
865 //nr crystals crysId is away from orgin id in phi
866 float EcalClusterTools::getNrCrysDiffInPhi(const DetId& crysId,const DetId& orginId)
867 {
868  float crysIPhi = getIPhi(crysId);
869  float orginIPhi = getIPhi(orginId);
870  bool isBarrel = orginId.subdetId()==EcalBarrel;
871 
872  float nrCrysDiff = crysIPhi-orginIPhi;
873 
874  if(isBarrel){ //if barrel, need to map into 0-180
875  if (nrCrysDiff > + 180) { nrCrysDiff = nrCrysDiff - 360; }
876  if (nrCrysDiff < - 180) { nrCrysDiff = nrCrysDiff + 360; }
877  }
878  return nrCrysDiff;
879 }
880 
881 //nr crystals crysId is away from mean phi in 5x5 in phi
882 float EcalClusterTools::getDPhiEndcap(const DetId& crysId,float meanX,float meanY)
883 {
884  float iXNorm = getNormedIX(crysId);
885  float iYNorm = getNormedIY(crysId);
886 
887  float hitLocalR2 = (iXNorm-meanX)*(iXNorm-meanX)+(iYNorm-meanY)*(iYNorm-meanY);
888  float hitR2 = iXNorm*iXNorm+iYNorm*iYNorm;
889  float meanR2 = meanX*meanX+meanY*meanY;
890  float hitR = sqrt(hitR2);
891  float meanR = sqrt(meanR2);
892 
893  float phi = acos((hitR2+meanR2-hitLocalR2)/(2*hitR*meanR));
894  float dPhi = hitR*phi;
895 
896  return dPhi;
897 }
898 
899 std::vector<float> EcalClusterTools::scLocalCovariances(const reco::SuperCluster &cluster, const EcalRecHitCollection* recHits,const CaloTopology *topology, float w0)
900 {
901  const reco::BasicCluster bcluster = *(cluster.seed());
902 
903  float e_5x5 = e5x5(bcluster, recHits, topology);
904  float covEtaEta, covEtaPhi, covPhiPhi;
905 
906  if (e_5x5 >= 0.) {
907  std::vector<std::pair<DetId, float> > v_id = cluster.hitsAndFractions();
908  std::pair<float,float> mean5x5PosInNrCrysFromSeed = mean5x5PositionInLocalCrysCoord(bcluster, recHits, topology);
909  std::pair<float,float> mean5x5XYPos = mean5x5PositionInXY(cluster,recHits,topology);
910  // now we can calculate the covariances
911  double numeratorEtaEta = 0;
912  double numeratorEtaPhi = 0;
913  double numeratorPhiPhi = 0;
914  double denominator = 0;
915 
916  const double barrelCrysSize = 0.01745; //approximate size of crystal in eta,phi in barrel
917  const double endcapCrysSize = 0.0447; //the approximate crystal size sigmaEtaEta was corrected to in the endcap
918 
919  DetId seedId = getMaximum(v_id, recHits).first;
920  bool isBarrel=seedId.subdetId()==EcalBarrel;
921 
922  const double crysSize = isBarrel ? barrelCrysSize : endcapCrysSize;
923 
924  for (size_t i = 0; i < v_id.size(); ++i) {
925  CaloNavigator<DetId> cursor = CaloNavigator<DetId>(v_id[i].first, topology->getSubdetectorTopology(v_id[i].first));
926  float energy = recHitEnergy(*cursor, recHits);
927 
928  if (energy <= 0) continue;
929 
930  float dEta = getNrCrysDiffInEta(*cursor,seedId) - mean5x5PosInNrCrysFromSeed.first;
931  float dPhi = 0;
932  if(isBarrel) dPhi = getNrCrysDiffInPhi(*cursor,seedId) - mean5x5PosInNrCrysFromSeed.second;
933  else dPhi = getDPhiEndcap(*cursor,mean5x5XYPos.first,mean5x5XYPos.second);
934 
935 
936 
937  double w = 0.;
938  w = std::max(0.0, w0 + log( energy / e_5x5 ));
939 
940  denominator += w;
941  numeratorEtaEta += w * dEta * dEta;
942  numeratorEtaPhi += w * dEta * dPhi;
943  numeratorPhiPhi += w * dPhi * dPhi;
944  }
945 
946  //multiplying by crysSize to make the values compariable to normal covariances
947  if (denominator != 0.0) {
948  covEtaEta = crysSize*crysSize* numeratorEtaEta / denominator;
949  covEtaPhi = crysSize*crysSize* numeratorEtaPhi / denominator;
950  covPhiPhi = crysSize*crysSize* numeratorPhiPhi / denominator;
951  } else {
952  covEtaEta = 999.9;
953  covEtaPhi = 999.9;
954  covPhiPhi = 999.9;
955  }
956 
957  } else {
958  // Warn the user if there was no energy in the cells and return zeroes.
959  // std::cout << "\ClusterShapeAlgo::Calculate_Covariances: no energy in supplied cells.\n";
960  covEtaEta = 0;
961  covEtaPhi = 0;
962  covPhiPhi = 0;
963  }
964 
965  std::vector<float> v;
966  v.push_back( covEtaEta );
967  v.push_back( covEtaPhi );
968  v.push_back( covPhiPhi );
969 
970  return v;
971 }
972 
973 
974 // compute cluster second moments with respect to principal axes (eigenvectors of sEtaEta, sPhiPhi, sEtaPhi matrix)
975 // store also angle alpha between major axis and phi.
976 // takes into account shower elongation in phi direction due to magnetic field effect:
977 // default value of 0.8 ensures sMaj = sMin for unconverted photons
978 // (if phiCorrectionFactor=1 sMaj > sMin and alpha=0 also for unconverted photons)
979 
980 Cluster2ndMoments EcalClusterTools::cluster2ndMoments( const reco::BasicCluster &basicCluster, const EcalRecHitCollection &recHits, double phiCorrectionFactor, double w0, bool useLogWeights) {
981 
982  Cluster2ndMoments returnMoments;
983  returnMoments.sMaj = -1.;
984  returnMoments.sMin = -1.;
985  returnMoments.alpha = 0.;
986 
987  // for now implemented only for EB:
988  if( fabs( basicCluster.eta() ) < 1.479 ) {
989 
990  std::vector<const EcalRecHit*> RH_ptrs;
991 
992  std::vector< std::pair<DetId, float> > myHitsPair = basicCluster.hitsAndFractions();
993  std::vector<DetId> usedCrystals;
994  for(unsigned int i=0; i< myHitsPair.size(); i++){
995  usedCrystals.push_back(myHitsPair[i].first);
996  }
997 
998  for(unsigned int i=0; i<usedCrystals.size(); i++){
999  //get pointer to recHit object
1000  EcalRecHitCollection::const_iterator myRH = recHits.find(usedCrystals[i]);
1001  RH_ptrs.push_back( &(*myRH) );
1002  }
1003 
1004  returnMoments = EcalClusterTools::cluster2ndMoments(RH_ptrs, phiCorrectionFactor, w0, useLogWeights);
1005 
1006  }
1007 
1008  return returnMoments;
1009 
1010 }
1011 
1012 
1013 Cluster2ndMoments EcalClusterTools::cluster2ndMoments( const reco::SuperCluster &superCluster, const EcalRecHitCollection &recHits, double phiCorrectionFactor, double w0, bool useLogWeights) {
1014 
1015  // for now returns second moments of supercluster seed cluster:
1016  Cluster2ndMoments returnMoments;
1017  returnMoments.sMaj = -1.;
1018  returnMoments.sMin = -1.;
1019  returnMoments.alpha = 0.;
1020 
1021  // for now implemented only for EB:
1022  if( fabs( superCluster.eta() ) < 1.479 ) {
1023  returnMoments = EcalClusterTools::cluster2ndMoments( *(superCluster.seed()), recHits, phiCorrectionFactor, w0, useLogWeights);
1024  }
1025 
1026  return returnMoments;
1027 
1028 }
1029 
1030 
1031 Cluster2ndMoments EcalClusterTools::cluster2ndMoments( std::vector<const EcalRecHit*> RH_ptrs, double phiCorrectionFactor, double w0, bool useLogWeights) {
1032 
1033  double mid_eta,mid_phi;
1034  mid_eta=mid_phi=0.;
1035 
1036  double Etot = EcalClusterTools::getSumEnergy( RH_ptrs );
1037 
1038  double max_phi=-10.;
1039  double min_phi=100.;
1040 
1041  std::vector<double> etaDetId;
1042  std::vector<double> phiDetId;
1043  std::vector<double> wiDetId;
1044 
1045  int nCry=0;
1046  double denominator=0.;
1047 
1048 
1049  // loop over rechits and compute weights:
1050  for(std::vector<const EcalRecHit*>::const_iterator rh_ptr = RH_ptrs.begin(); rh_ptr != RH_ptrs.end(); rh_ptr++){
1051 
1052  //get iEta, iPhi
1053  EBDetId temp_EBDetId( (*rh_ptr)->detid() );
1054  double temp_eta=(temp_EBDetId.ieta() > 0. ? temp_EBDetId.ieta() + 84.5 : temp_EBDetId.ieta() + 85.5);
1055  double temp_phi=temp_EBDetId.iphi() - 0.5;
1056  double temp_ene=(*rh_ptr)->energy();
1057 
1058  double temp_wi=((useLogWeights) ?
1059  std::max(0., w0 + log( fabs(temp_ene)/Etot ))
1060  : temp_ene);
1061 
1062  if(temp_phi>max_phi) max_phi=temp_phi;
1063  if(temp_phi<min_phi) min_phi=temp_phi;
1064  etaDetId.push_back(temp_eta);
1065  phiDetId.push_back(temp_phi);
1066  wiDetId.push_back(temp_wi);
1067  denominator+=temp_wi;
1068  nCry++;
1069  }
1070 
1071 
1072  // correct phi wrap-around:
1073  if(max_phi==359.5 && min_phi==0.5){
1074  for(int i=0; i<nCry; i++){
1075  if(phiDetId[i] - 179. > 0.) phiDetId[i]-=360.;
1076  mid_phi+=phiDetId[i]*wiDetId[i];
1077  mid_eta+=etaDetId[i]*wiDetId[i];
1078  }
1079  }
1080 
1081  else{
1082  for(int i=0; i<nCry; i++){
1083  mid_phi+=phiDetId[i]*wiDetId[i];
1084  mid_eta+=etaDetId[i]*wiDetId[i];
1085  }
1086  }
1087 
1088  mid_eta/=denominator;
1089  mid_phi/=denominator;
1090 
1091  // See = sigma eta eta
1092  // Spp = (B field corrected) sigma phi phi
1093  // See = (B field corrected) sigma eta phi
1094  double See=0.;
1095  double Spp=0.;
1096  double Sep=0.;
1097 
1098  // compute (phi-corrected) covariance matrix:
1099  for(int i=0; i<nCry; i++) {
1100  See += (wiDetId[i]*(etaDetId[i]-mid_eta)*(etaDetId[i]-mid_eta)) / denominator;
1101  Spp += phiCorrectionFactor*(wiDetId[i]*(phiDetId[i]-mid_phi)*(phiDetId[i]-mid_phi)) / denominator;
1102  Sep += sqrt(phiCorrectionFactor)*(wiDetId[i]*(etaDetId[i]-mid_eta)*(phiDetId[i]-mid_phi)) / denominator;
1103  }
1104 
1105  Cluster2ndMoments returnMoments;
1106 
1107  // compute matrix eigenvalues:
1108  returnMoments.sMaj = ((See + Spp) + sqrt((See - Spp)*(See - Spp) + 4.*Sep*Sep)) / 2.;
1109  returnMoments.sMin = ((See + Spp) - sqrt((See - Spp)*(See - Spp) + 4.*Sep*Sep)) / 2.;
1110 
1111  returnMoments.alpha = atan( (See - Spp + sqrt( (Spp - See)*(Spp - See) + 4.*Sep*Sep )) / (2.*Sep));
1112 
1113  return returnMoments;
1114 
1115 }
1116 
1117 
1118 
1119 //compute shower shapes: roundness and angle in a vector. Roundness is 0th element, Angle is 1st element.
1120 //description: uses classical mechanics inertia tensor.
1121 // roundness is smaller_eValue/larger_eValue
1122 // angle is the angle from the iEta axis to the smallest eVector (a.k.a. the shower's elongated axis)
1123 // this function uses only recHits belonging to a SC above energyThreshold (default 0)
1124 // you can select linear weighting = energy_recHit/total_energy (weightedPositionMethod=0) default
1125 // or log weighting = max( 0.0, 4.2 + log(energy_recHit/total_energy) ) (weightedPositionMethod=1)
1126 std::vector<float> EcalClusterTools::roundnessBarrelSuperClusters( const reco::SuperCluster &superCluster ,const EcalRecHitCollection &recHits, int weightedPositionMethod, float energyThreshold){//int positionWeightingMethod=0){
1127  std::vector<const EcalRecHit*>RH_ptrs;
1128  std::vector< std::pair<DetId, float> > myHitsPair = superCluster.hitsAndFractions();
1129  std::vector<DetId> usedCrystals;
1130  for(unsigned int i=0; i< myHitsPair.size(); i++){
1131  usedCrystals.push_back(myHitsPair[i].first);
1132  }
1133  for(unsigned int i=0; i<usedCrystals.size(); i++){
1134  //get pointer to recHit object
1135  EcalRecHitCollection::const_iterator myRH = recHits.find(usedCrystals[i]);
1136  if( myRH != recHits.end() && myRH->energy() > energyThreshold){ //require rec hit to have positive energy
1137  RH_ptrs.push_back( &(*myRH) );
1138  }
1139  }
1140  std::vector<float> temp = EcalClusterTools::roundnessSelectedBarrelRecHits(RH_ptrs,weightedPositionMethod);
1141  return temp;
1142 }
1143 
1144 // this function uses all recHits within specified window ( with default values ieta_delta=2, iphi_delta=5) around SC's highest recHit.
1145 // recHits must pass an energy threshold "energyRHThresh" (default 0)
1146 // you can select linear weighting = energy_recHit/total_energy (weightedPositionMethod=0)
1147 // or log weighting = max( 0.0, 4.2 + log(energy_recHit/total_energy) ) (weightedPositionMethod=1)
1148 
1149 std::vector<float> EcalClusterTools::roundnessBarrelSuperClustersUserExtended( const reco::SuperCluster &superCluster ,const EcalRecHitCollection &recHits, int ieta_delta, int iphi_delta, float energyRHThresh, int weightedPositionMethod){
1150 
1151  std::vector<const EcalRecHit*>RH_ptrs;
1152  std::vector< std::pair<DetId, float> > myHitsPair = superCluster.hitsAndFractions();
1153  std::vector<DetId> usedCrystals;
1154  for(unsigned int i=0; i< myHitsPair.size(); i++){
1155  usedCrystals.push_back(myHitsPair[i].first);
1156  }
1157 
1158  for(unsigned int i=0; i<usedCrystals.size(); i++){
1159  //get pointer to recHit object
1160  EcalRecHitCollection::const_iterator myRH = recHits.find(usedCrystals[i]);
1161  if(myRH != recHits.end() && myRH->energy() > energyRHThresh)
1162  RH_ptrs.push_back( &(*myRH) );
1163  }
1164 
1165 
1166  std::vector<int> seedPosition = EcalClusterTools::getSeedPosition( RH_ptrs );
1167 
1168  for(EcalRecHitCollection::const_iterator rh = recHits.begin(); rh != recHits.end(); rh++){
1169  EBDetId EBdetIdi( rh->detid() );
1170  //if(rh != recHits.end())
1171  bool inEtaWindow = ( abs( deltaIEta(seedPosition[0],EBdetIdi.ieta()) ) <= ieta_delta );
1172  bool inPhiWindow = ( abs( deltaIPhi(seedPosition[1],EBdetIdi.iphi()) ) <= iphi_delta );
1173  bool passEThresh = ( rh->energy() > energyRHThresh );
1174  bool alreadyCounted = false;
1175 
1176  // figure out if the rechit considered now is already inside the SC
1177  bool is_SCrh_inside_recHits = false;
1178  for(unsigned int i=0; i<usedCrystals.size(); i++){
1179  EcalRecHitCollection::const_iterator SCrh = recHits.find(usedCrystals[i]);
1180  if(SCrh != recHits.end()){
1181  is_SCrh_inside_recHits = true;
1182  if( rh->detid() == SCrh->detid() ) alreadyCounted = true;
1183  }
1184  }//for loop over SC's recHits
1185 
1186  if( is_SCrh_inside_recHits && !alreadyCounted && passEThresh && inEtaWindow && inPhiWindow){
1187  RH_ptrs.push_back( &(*rh) );
1188  }
1189 
1190  }//for loop over rh
1191  return EcalClusterTools::roundnessSelectedBarrelRecHits(RH_ptrs,weightedPositionMethod);
1192 }
1193 
1194 // this function computes the roundness and angle variables for vector of pointers to recHits you pass it
1195 // you can select linear weighting = energy_recHit/total_energy (weightedPositionMethod=0)
1196 // or log weighting = max( 0.0, 4.2 + log(energy_recHit/total_energy) ) (weightedPositionMethod=1)
1197 std::vector<float> EcalClusterTools::roundnessSelectedBarrelRecHits( std::vector<const EcalRecHit*> RH_ptrs, int weightedPositionMethod){//int weightedPositionMethod = 0){
1198  //positionWeightingMethod = 0 linear weighting, 1 log energy weighting
1199 
1200  std::vector<float> shapes; // this is the returning vector
1201 
1202  //make sure photon has more than one crystal; else roundness and angle suck
1203  if(RH_ptrs.size()<2){
1204  shapes.push_back( -3 );
1205  shapes.push_back( -3 );
1206  return shapes;
1207  }
1208 
1209  //Find highest E RH (Seed) and save info, compute sum total energy used
1210  std::vector<int> seedPosition = EcalClusterTools::getSeedPosition( RH_ptrs );// *recHits);
1211  int tempInt = seedPosition[0];
1212  if(tempInt <0) tempInt++;
1213  float energyTotal = EcalClusterTools::getSumEnergy( RH_ptrs );
1214 
1215  //1st loop over rechits: compute new weighted center position in coordinates centered on seed
1216  float centerIEta = 0.;
1217  float centerIPhi = 0.;
1218  float denominator = 0.;
1219 
1220  for(std::vector<const EcalRecHit*>::const_iterator rh_ptr = RH_ptrs.begin(); rh_ptr != RH_ptrs.end(); rh_ptr++){
1221  //get iEta, iPhi
1222  EBDetId EBdetIdi( (*rh_ptr)->detid() );
1223  if(fabs(energyTotal) < 0.0001){
1224  // don't /0, bad!
1225  shapes.push_back( -2 );
1226  shapes.push_back( -2 );
1227  return shapes;
1228  }
1229  float weight = 0;
1230  if(fabs(weightedPositionMethod)<0.0001){ //linear
1231  weight = (*rh_ptr)->energy()/energyTotal;
1232  }else{ //logrithmic
1233  weight = std::max(0.0, 4.2 + log((*rh_ptr)->energy()/energyTotal));
1234  }
1235  denominator += weight;
1236  centerIEta += weight*deltaIEta(seedPosition[0],EBdetIdi.ieta());
1237  centerIPhi += weight*deltaIPhi(seedPosition[1],EBdetIdi.iphi());
1238  }
1239  if(fabs(denominator) < 0.0001){
1240  // don't /0, bad!
1241  shapes.push_back( -2 );
1242  shapes.push_back( -2 );
1243  return shapes;
1244  }
1245  centerIEta = centerIEta / denominator;
1246  centerIPhi = centerIPhi / denominator;
1247 
1248 
1249  //2nd loop over rechits: compute inertia tensor
1250  TMatrixDSym inertia(2); //initialize 2d inertia tensor
1251  double inertia00 = 0.;
1252  double inertia01 = 0.;// = inertia10 b/c matrix should be symmetric
1253  double inertia11 = 0.;
1254  int i = 0;
1255  for(std::vector<const EcalRecHit*>::const_iterator rh_ptr = RH_ptrs.begin(); rh_ptr != RH_ptrs.end(); rh_ptr++){
1256  //get iEta, iPhi
1257  EBDetId EBdetIdi( (*rh_ptr)->detid() );
1258 
1259  if(fabs(energyTotal) < 0.0001){
1260  // don't /0, bad!
1261  shapes.push_back( -2 );
1262  shapes.push_back( -2 );
1263  return shapes;
1264  }
1265  float weight = 0;
1266  if(fabs(weightedPositionMethod) < 0.0001){ //linear
1267  weight = (*rh_ptr)->energy()/energyTotal;
1268  }else{ //logrithmic
1269  weight = std::max(0.0, 4.2 + log((*rh_ptr)->energy()/energyTotal));
1270  }
1271 
1272  float ieta_rh_to_center = deltaIEta(seedPosition[0],EBdetIdi.ieta()) - centerIEta;
1273  float iphi_rh_to_center = deltaIPhi(seedPosition[1],EBdetIdi.iphi()) - centerIPhi;
1274 
1275  inertia00 += weight*iphi_rh_to_center*iphi_rh_to_center;
1276  inertia01 -= weight*iphi_rh_to_center*ieta_rh_to_center;
1277  inertia11 += weight*ieta_rh_to_center*ieta_rh_to_center;
1278  i++;
1279  }
1280 
1281  inertia[0][0] = inertia00;
1282  inertia[0][1] = inertia01; // use same number here
1283  inertia[1][0] = inertia01; // and here to insure symmetry
1284  inertia[1][1] = inertia11;
1285 
1286 
1287  //step 1 find principal axes of inertia
1288  TMatrixD eVectors(2,2);
1289  TVectorD eValues(2);
1290  //std::cout<<"EcalClusterTools::showerRoundness- about to compute eVectors"<<std::endl;
1291  eVectors=inertia.EigenVectors(eValues); //ordered highest eV to lowest eV (I checked!)
1292  //and eVectors are in columns of matrix! I checked!
1293  //and they are normalized to 1
1294 
1295 
1296 
1297  //step 2 select eta component of smaller eVal's eVector
1298  TVectorD smallerAxis(2);//easiest to spin SC on this axis (smallest eVal)
1299  smallerAxis[0]=eVectors[0][1];//row,col //eta component
1300  smallerAxis[1]=eVectors[1][1]; //phi component
1301 
1302  //step 3 compute interesting quatities
1303  Double_t temp = fabs(smallerAxis[0]);// closer to 1 ->beamhalo, closer to 0 something else
1304  if(fabs(eValues[0]) < 0.0001){
1305  // don't /0, bad!
1306  shapes.push_back( -2 );
1307  shapes.push_back( -2 );
1308  return shapes;
1309  }
1310 
1311  float Roundness = eValues[1]/eValues[0];
1312  float Angle=acos(temp);
1313 
1314  if( -0.00001 < Roundness && Roundness < 0) Roundness = 0.;
1315  if( -0.00001 < Angle && Angle < 0 ) Angle = 0.;
1316 
1317  shapes.push_back( Roundness );
1318  shapes.push_back( Angle );
1319  return shapes;
1320 
1321 }
1322 //private functions useful for roundnessBarrelSuperClusters etc.
1323 //compute delta iphi between a seed and a particular recHit
1324 //iphi [1,360]
1325 //safe gaurds are put in to ensure the difference is between [-180,180]
1326 int EcalClusterTools::deltaIPhi(int seed_iphi, int rh_iphi){
1327  int rel_iphi = rh_iphi - seed_iphi;
1328  // take care of cyclic variable iphi [1,360]
1329  if(rel_iphi > 180) rel_iphi = rel_iphi - 360;
1330  if(rel_iphi < -180) rel_iphi = rel_iphi + 360;
1331  return rel_iphi;
1332 }
1333 
1334 //compute delta ieta between a seed and a particular recHit
1335 //ieta [-85,-1] and [1,85]
1336 //safe gaurds are put in to shift the negative ieta +1 to make an ieta=0 so differences are computed correctly
1337 int EcalClusterTools::deltaIEta(int seed_ieta, int rh_ieta){
1338  // get rid of the fact that there is no ieta=0
1339  if(seed_ieta < 0) seed_ieta++;
1340  if(rh_ieta < 0) rh_ieta++;
1341  int rel_ieta = rh_ieta - seed_ieta;
1342  return rel_ieta;
1343 }
1344 
1345 //return (ieta,iphi) of highest energy recHit of the recHits passed to this function
1346 std::vector<int> EcalClusterTools::getSeedPosition(std::vector<const EcalRecHit*> RH_ptrs){
1347  std::vector<int> seedPosition;
1348  float eSeedRH = 0;
1349  int iEtaSeedRH = 0;
1350  int iPhiSeedRH = 0;
1351 
1352  for(std::vector<const EcalRecHit*>::const_iterator rh_ptr = RH_ptrs.begin(); rh_ptr != RH_ptrs.end(); rh_ptr++){
1353 
1354  //get iEta, iPhi
1355  EBDetId EBdetIdi( (*rh_ptr)->detid() );
1356 
1357  if(eSeedRH < (*rh_ptr)->energy()){
1358  eSeedRH = (*rh_ptr)->energy();
1359  iEtaSeedRH = EBdetIdi.ieta();
1360  iPhiSeedRH = EBdetIdi.iphi();
1361  }
1362 
1363  }// for loop
1364 
1365  seedPosition.push_back(iEtaSeedRH);
1366  seedPosition.push_back(iPhiSeedRH);
1367  return seedPosition;
1368 }
1369 
1370 // return the total energy of the recHits passed to this function
1371 float EcalClusterTools::getSumEnergy(std::vector<const EcalRecHit*> RH_ptrs){
1372 
1373  float sumE = 0.;
1374 
1375  for(std::vector<const EcalRecHit*>::const_iterator rh_ptr = RH_ptrs.begin(); rh_ptr != RH_ptrs.end(); rh_ptr++){
1376  sumE += (*rh_ptr)->energy();
1377  }// for loop
1378 
1379  return sumE;
1380 }
#define LogDebug(id)
static float eBottom(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
const CaloSubdetectorGeometry * getSubdetectorGeometry(const DetId &id) const
access the subdetector geometry for the given subdetector directly
Definition: CaloGeometry.cc:43
int i
Definition: DBlmapReader.cc:9
static double zernike42(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, double R0=6.6, bool logW=true, float w0=4.7)
static double f42(double r)
static float getNormedIX(const DetId &id)
int ix() const
Definition: EEDetId.h:71
static double f53(double r)
static std::vector< float > roundnessBarrelSuperClusters(const reco::SuperCluster &superCluster, const EcalRecHitCollection &recHits, int weightedPositionMethod=0, float energyThreshold=0.0)
static float e5x1(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static float recHitEnergy(DetId id, const EcalRecHitCollection *recHits)
void home() const
move the navigator back to the starting point
static std::vector< float > energyBasketFractionEta(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits)
static double fast_AbsZernikeMoment(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, int n, int m, double R0, bool logW, float w0)
static float e3x1(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static float matrixEnergy(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology, DetId id, int ixMin, int ixMax, int iyMin, int iyMax)
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
static std::vector< DetId > matrixDetId(const CaloTopology *topology, DetId id, int ixMin, int ixMax, int iyMin, int iyMax)
static std::vector< int > getSeedPosition(std::vector< const EcalRecHit * >RH_ptrs)
Geom::Phi< T > phi() const
Definition: PV3DBase.h:63
std::vector< T >::const_iterator const_iterator
T y() const
Definition: PV3DBase.h:57
#define abs(x)
Definition: mlp_lapack.h:159
static double calc_AbsZernikeMoment(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, int n, int m, double R0, bool logW, float w0)
const std::vector< std::pair< DetId, float > > & hitsAndFractions() const
Definition: CaloCluster.h:178
static const int kTowersInPhi
Definition: EBDetId.h:125
static double f51(double r)
static float e2nd(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits)
static int position[TOTALCHAMBERS][3]
Definition: ReadPGInfo.cc:509
double eta() const
pseudorapidity of cluster centroid
Definition: CaloCluster.h:149
static int deltaIEta(int seed_ieta, int rh_ieta)
static std::vector< EcalClusterEnergyDeposition > getEnergyDepTopology(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, bool logW, float w0)
static std::pair< float, float > mean5x5PositionInLocalCrysCoord(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static float e3x2(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
virtual const CaloCellGeometry * getGeometry(const DetId &id) const
Get the cell geometry of a given detector id. Should return false if not found.
static std::vector< float > covariances(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology, const CaloGeometry *geometry, float w0=4.7)
int iphi() const
get the crystal iphi
Definition: EBDetId.h:46
U second(std::pair< T, U > const &p)
int im() const
get the number of module inside the SM (1-4)
Definition: EBDetId.cc:85
static const int kCrystalsInPhi
Definition: EBDetId.h:128
static float e2x5Left(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static std::vector< float > localCovariances(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology, float w0=4.7)
static double zernike20(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, double R0=6.6, bool logW=true, float w0=4.7)
static std::vector< float > energyBasketFractionPhi(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits)
double dPhi(double phi1, double phi2)
Definition: JetUtil.h:30
const T & max(const T &a, const T &b)
static double f00(double r)
static float getNormedIY(const DetId &id)
static float getSumEnergy(std::vector< const EcalRecHit * >RH_ptrs)
float energy() const
Definition: CaloRecHit.h:19
T sqrt(T t)
Definition: SSEVec.h:28
static std::vector< float > roundnessBarrelSuperClustersUserExtended(const reco::SuperCluster &superCluster, const EcalRecHitCollection &recHits, int ieta_delta=0, int iphi_delta=0, float energyRHThresh=0.00000, int weightedPositionMethod=0)
static float getIPhi(const DetId &id)
virtual T offsetBy(int deltaX, int deltaY) const
Free movement of arbitray steps.
T z() const
Definition: PV3DBase.h:58
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
static std::pair< float, float > mean5x5PositionInXY(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static double absZernikeMoment(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, int n, int m, double R0, bool logW, float w0)
static Cluster2ndMoments cluster2ndMoments(const reco::BasicCluster &basicCluster, const EcalRecHitCollection &recHits, double phiCorrectionFactor=0.8, double w0=4.7, bool useLogWeights=true)
static float e3x3(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static const int kModulesPerSM
Definition: EBDetId.h:126
static int deltaIPhi(int seed_iphi, int rh_iphi)
int j
Definition: DBlmapReader.cc:9
static std::vector< float > roundnessSelectedBarrelRecHits(std::vector< const EcalRecHit * >rhVector, int weightedPositionMethod=0)
static float e4x4(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static float getNrCrysDiffInPhi(const DetId &crysId, const DetId &orginId)
int iy() const
Definition: EEDetId.h:77
int ieta() const
get the crystal ieta
Definition: EBDetId.h:44
static double f44(double r)
static float getDPhiEndcap(const DetId &crysId, float meanX, float meanY)
static double f55(double r)
bool first
Definition: L1TdeRCT.cc:79
int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:39
static float getIEta(const DetId &id)
static double f40(double r)
const_iterator end() const
Definition: DetId.h:20
#define M_PI
Definition: BFit3D.cc:3
static float eRight(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static float eTop(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
bool positiveZ() const
Definition: EBDetId.h:65
static double factorial(int n)
Log< T >::type log(const T &t)
Definition: Log.h:22
static double f31(double r)
static const int MAX_IPHI
Definition: EBDetId.h:123
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
static float eMax(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits)
static std::vector< float > lat(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, bool logW=true, float w0=4.7)
static float getNrCrysDiffInEta(const DetId &crysId, const DetId &orginId)
const CaloSubdetectorTopology * getSubdetectorTopology(const DetId &id) const
access the subdetector Topology for the given subdetector directly
Definition: CaloTopology.cc:26
static float e2x5Bottom(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
T eta() const
Definition: PV3DBase.h:70
static std::vector< float > scLocalCovariances(const reco::SuperCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology, float w0=4.7)
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
Definition: Angle.h:17
ESHandle< TrackerGeometry > geometry
iterator find(key_type k)
double pi()
Definition: Pi.h:31
double twoPi()
Definition: Pi.h:32
static std::pair< DetId, float > getMaximum(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits)
static float e2x5Max(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static float e1x3(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static float e5x5(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static float e1x5(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static double f20(double r)
static double f33(double r)
const CaloClusterPtr & seed() const
seed BasicCluster
Definition: SuperCluster.h:61
string s
Definition: asciidump.py:422
double energySum(const DataFrame &df, int fs, int ls)
static float eLeft(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
const GlobalPoint & getPosition() const
T x() const
Definition: PV3DBase.h:56
static double f22(double r)
static float e2x5Right(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static double f11(double r)
mathSSE::Vec4< T > v
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
const_iterator begin() const
static math::XYZVector meanClusterPosition(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology, const CaloGeometry *geometry)
Definition: DDAxes.h:10
static float e2x2(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)
static float e2x5Top(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology)