CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
LinkByRecHit.cc
Go to the documentation of this file.
4 #include "TMath.h"
5 
6 // to enable debugs
7 //#define PFLOW_DEBUG
8 
9 double
11  const reco::PFCluster& cluster,
12  bool isBrem,
13  bool debug) {
14 
15 #ifdef PFLOW_DEBUG
16  if( debug )
17  std::cout<<"entering test link by rechit function"<<std::endl;
18 #endif
19 
20  //cluster position
21  double clustereta = cluster.positionREP().Eta();
22  double clusterphi = cluster.positionREP().Phi();
23  //double clusterX = cluster.position().X();
24  //double clusterY = cluster.position().Y();
25  double clusterZ = cluster.position().Z();
26 
27  bool barrel = false;
28  bool hcal = false;
29  // double distance = 999999.9;
30  double horesolscale=1.0;
31 
32  //track extrapolation
33  const reco::PFTrajectoryPoint& atVertex
35  const reco::PFTrajectoryPoint& atECAL
37 
38  //track at calo's
39  double tracketa = 999999.9;
40  double trackphi = 999999.9;
41  double track_X = 999999.9;
42  double track_Y = 999999.9;
43  double track_Z = 999999.9;
44  double dHEta = 0.;
45  double dHPhi = 0.;
46 
47  // Quantities at vertex
48  double trackPt = isBrem ? 999. : sqrt(atVertex.momentum().Vect().Perp2());
49  // double trackEta = isBrem ? 999. : atVertex.momentum().Vect().Eta();
50 
51  switch (cluster.layer()) {
52  case PFLayer::ECAL_BARREL: barrel = true;
54 #ifdef PFLOW_DEBUG
55  if( debug )
56  std::cout << "Fetching Ecal Resolution Maps"
57  << std::endl;
58 #endif
59  // did not reach ecal, cannot be associated with a cluster.
60  if( ! atECAL.isValid() ) return -1.;
61 
62  tracketa = atECAL.positionREP().Eta();
63  trackphi = atECAL.positionREP().Phi();
64  track_X = atECAL.position().X();
65  track_Y = atECAL.position().Y();
66  track_Z = atECAL.position().Z();
67 
68 /* distance
69  = std::sqrt( (track_X-clusterX)*(track_X-clusterX)
70  +(track_Y-clusterY)*(track_Y-clusterY)
71  +(track_Z-clusterZ)*(track_Z-clusterZ)
72  );
73 */
74  break;
75 
76  case PFLayer::HCAL_BARREL1: barrel = true;
78 #ifdef PFLOW_DEBUG
79  if( debug )
80  std::cout << "Fetching Hcal Resolution Maps"
81  << std::endl;
82 #endif
83  if( isBrem ) {
84  return -1.;
85  } else {
86  hcal=true;
87  const reco::PFTrajectoryPoint& atHCAL
89  const reco::PFTrajectoryPoint& atHCALExit
91  // did not reach hcal, cannot be associated with a cluster.
92  if( ! atHCAL.isValid() ) return -1.;
93 
94  // The link is computed between 0 and ~1 interaction length in HCAL
95  dHEta = atHCALExit.positionREP().Eta()-atHCAL.positionREP().Eta();
96  dHPhi = atHCALExit.positionREP().Phi()-atHCAL.positionREP().Phi();
97  if ( dHPhi > M_PI ) dHPhi = dHPhi - 2.*M_PI;
98  else if ( dHPhi < -M_PI ) dHPhi = dHPhi + 2.*M_PI;
99  tracketa = atHCAL.positionREP().Eta() + 0.1*dHEta;
100  trackphi = atHCAL.positionREP().Phi() + 0.1*dHPhi;
101  track_X = atHCAL.position().X();
102  track_Y = atHCAL.position().Y();
103  track_Z = atHCAL.position().Z();
104 /* distance
105  = -std::sqrt( (track_X-clusterX)*(track_X-clusterX)
106  +(track_Y-clusterY)*(track_Y-clusterY)
107  +(track_Z-clusterZ)*(track_Z-clusterZ)
108  );
109 */
110  }
111  break;
112 
113  case PFLayer::HCAL_BARREL2: barrel = true;
114 #ifdef PFLOW_DEBUG
115  if( debug )
116  std::cout << "Fetching HO Resolution Maps"
117  << std::endl;
118 #endif
119  if( isBrem ) {
120  return -1.;
121  } else {
122  hcal=true;
123  horesolscale=1.15;
124  const reco::PFTrajectoryPoint& atHO
126  // did not reach ho, cannot be associated with a cluster.
127  if( ! atHO.isValid() ) return -1.;
128 
129  //
130  tracketa = atHO.positionREP().Eta();
131  trackphi = atHO.positionREP().Phi();
132  track_X = atHO.position().X();
133  track_Y = atHO.position().Y();
134  track_Z = atHO.position().Z();
135 
136  // Is this check really useful ?
137  if ( fabs(track_Z) > 700.25 ) return -1.;
138 
139 
140 /* distance
141  = std::sqrt( (track_X-clusterX)*(track_X-clusterX)
142  +(track_Y-clusterY)*(track_Y-clusterY)
143  +(track_Z-clusterZ)*(track_Z-clusterZ)
144  );
145 */
146 #ifdef PFLOW_DEBUG
147 /* if( debug ) {
148  std::cout <<"dist "<<distance<<" "<<cluster.energy()<<" "<<cluster.layer()<<" "
149  <<track_X<<" "<<clusterX<<" "
150  <<track_Y<<" "<<clusterY<<" "
151  <<track_Z<<" "<<clusterZ<<std::endl;
152  }
153 */
154 #endif
155  }
156  break;
157 
158  case PFLayer::PS1:
159  case PFLayer::PS2:
160  //Note Alex: Nothing implemented for the
161  //PreShower (No resolution maps yet)
162 #ifdef PFLOW_DEBUG
163  if( debug )
164  std::cout << "No link by rechit possible for pre-shower yet!"
165  << std::endl;
166 #endif
167  return -1.;
168  default:
169  return -1.;
170  }
171 
172 
173  // Check that, if the cluster is in the endcap,
174  // 0) the track indeed points to the endcap at vertex (DISABLED)
175  // 1) the track extrapolation is in the endcap too !
176  // 2) the track is in the same end-cap !
177  // PJ - 10-May-09
178  if ( !barrel ) {
179  // if ( fabs(trackEta) < 1.0 ) return -1;
180  if ( !hcal && fabs(track_Z) < 300. ) return -1.;
181  if ( track_Z * clusterZ < 0. ) return -1.;
182  }
183  // Check that, if the cluster is in the barrel,
184  // 1) the track is in the barrel too !
185  if ( barrel ) {
186  if ( !hcal && fabs(track_Z) > 300. ) return -1.;
187  }
188 
189  double dist = LinkByRecHit::computeDist( clustereta, clusterphi,
190  tracketa, trackphi);
191 
192 #ifdef PFLOW_DEBUG
193  if(debug) std::cout<<"test link by rechit "<< dist <<" "<<std::endl;
194  if(debug){
195  std::cout<<" clustereta " << clustereta
196  <<" clusterphi " << clusterphi
197  <<" tracketa " << tracketa
198  <<" trackphi " << trackphi << std::endl;
199  }
200 #endif
201 
202  //Testing if Track can be linked by rechit to a cluster.
203  //A cluster can be linked to a track if the extrapolated position
204  //of the track to the ECAL ShowerMax/HCAL entrance falls within
205  //the boundaries of any cell that belongs to this cluster.
206 
207  const std::vector< reco::PFRecHitFraction >&
208  fracs = cluster.recHitFractions();
209 
210  bool linkedbyrechit = false;
211  //loop rechits
212  for(unsigned int rhit = 0; rhit < fracs.size(); ++rhit){
213 
214  const reco::PFRecHitRef& rh = fracs[rhit].recHitRef();
215  double fraction = fracs[rhit].fraction();
216  if(fraction < 1E-4) continue;
217  if(rh.isNull()) continue;
218 
219  //getting rechit center position
220  const reco::PFRecHit& rechit_cluster = *rh;
221  const math::XYZPoint& posxyz
222  = rechit_cluster.position();
223  const reco::PFRecHit::REPPoint& posrep
224  = rechit_cluster.positionREP();
225 
226  //getting rechit corners
227  const std::vector< math::XYZPoint >&
228  cornersxyz = rechit_cluster.getCornersXYZ();
229  const std::vector<reco::PFRecHit::REPPoint>& corners =
230  rechit_cluster.getCornersREP();
231  assert(corners.size() == 4);
232 
233  if( barrel || hcal ){ // barrel case matching in eta/phi
234  // (and HCAL endcap too!)
235 
236  //rechit size determination
237  // blown up by 50% (HCAL) to 100% (ECAL) to include cracks & gaps
238  // also blown up to account for multiple scattering at low pt.
239  double rhsizeEta
240  = fabs(corners[0].Eta() - corners[2].Eta());
241  double rhsizePhi
242  = fabs(corners[0].Phi() - corners[2].Phi());
243  if ( rhsizePhi > M_PI ) rhsizePhi = 2.*M_PI - rhsizePhi;
244  if ( hcal ) {
245  const double mult = horesolscale * (1.50 + 0.5/fracs.size());
246  rhsizeEta = rhsizeEta * mult + 0.2*fabs(dHEta);
247  rhsizePhi = rhsizePhi * mult + 0.2*fabs(dHPhi);
248 
249  } else {
250  const double mult = 2.00 + 1.0/(fracs.size()*std::min(1.,0.5*trackPt));
251  rhsizeEta *= mult;
252  rhsizePhi *= mult;
253  }
254 
255 #ifdef PFLOW_DEBUG
256  if( debug ) {
257  std::cout << rhit << " Hcal RecHit="
258  << posrep.Eta() << " "
259  << posrep.Phi() << " "
260  << rechit_cluster.energy()
261  << std::endl;
262  for ( unsigned jc=0; jc<4; ++jc )
263  std::cout<<"corners "<<jc<<" "<<corners[jc].Eta()
264  <<" "<<corners[jc].Phi()<<std::endl;
265 
266  std::cout << "RecHit SizeEta=" << rhsizeEta
267  << " SizePhi=" << rhsizePhi << std::endl;
268  }
269 #endif
270 
271  //distance track-rechit center
272  // const math::XYZPoint& posxyz
273  // = rechit_cluster.position();
274  double deta = fabs(posrep.Eta() - tracketa);
275  double dphi = fabs(posrep.Phi() - trackphi);
276  if ( dphi > M_PI ) dphi = 2.*M_PI - dphi;
277 
278 #ifdef PFLOW_DEBUG
279  if( debug ){
280  std::cout << "distance="
281  << deta << " "
282  << dphi << " ";
283  if(deta < (0.5*rhsizeEta) && dphi < (0.5*rhsizePhi))
284  std::cout << " link here !" << std::endl;
285  else std::cout << std::endl;
286  }
287 #endif
288 
289  if(deta < (0.5*rhsizeEta) && dphi < (0.5*rhsizePhi)){
290  linkedbyrechit = true;
291  break;
292  }
293  }
294  else { //ECAL & PS endcap case, matching in X,Y
295 
296 #ifdef PFLOW_DEBUG
297  if( debug ){
298  const math::XYZPoint& posxyz
299  = rechit_cluster.position();
300 
301  std::cout << "RH " << posxyz.X()
302  << " " << posxyz.Y()
303  << std::endl;
304 
305  std::cout << "TRACK " << track_X
306  << " " << track_Y
307  << std::endl;
308  }
309 #endif
310 
311  double x[5];
312  double y[5];
313 
314  for ( unsigned jc=0; jc<4; ++jc ) {
315  const math::XYZPoint& cornerposxyz = cornersxyz[jc];
316  const double mult = (1.00+0.50/(fracs.size()*std::min(1.,0.5*trackPt)));
317  x[jc] = cornerposxyz.X() + (cornerposxyz.X()-posxyz.X()) * mult;
318  y[jc] = cornerposxyz.Y() + (cornerposxyz.Y()-posxyz.Y()) * mult;
319 
320 #ifdef PFLOW_DEBUG
321  if( debug ){
322  std::cout<<"corners "<<jc
323  << " " << cornerposxyz.X()
324  << " " << cornerposxyz.Y()
325  << std::endl;
326  }
327 #endif
328  }//loop corners
329 
330  //need to close the polygon in order to
331  //use the TMath::IsInside fonction from root lib
332  x[4] = x[0];
333  y[4] = y[0];
334 
335  //Check if the extrapolation point of the track falls
336  //within the rechit boundaries
337  bool isinside = TMath::IsInside(track_X,
338  track_Y,
339  5,x,y);
340 
341  if( isinside ){
342  linkedbyrechit = true;
343  break;
344  }
345  }//
346 
347  }//loop rechits
348 
349  if( linkedbyrechit ) {
350 #ifdef PFLOW_DEBUG
351  if( debug )
352  std::cout << "Track and Cluster LINKED BY RECHIT" << std::endl;
353 #endif
354  /*
355  //if ( distance > 40. || distance < -100. )
356  double clusterr = std::sqrt(clusterX*clusterX+clusterY*clusterY);
357  double trackr = std::sqrt(track_X*track_X+track_Y*track_Y);
358  if ( distance > 40. )
359  std::cout << "Distance = " << distance
360  << ", Barrel/Hcal/Brem ? " << barrel << " " << hcal << " " << isBrem << std::endl
361  << " Cluster " << clusterr << " " << clusterZ << " " << clusterphi << " " << clustereta << std::endl
362  << " Track " << trackr << " " << track_Z << " " << trackphi << " " << tracketa << std::endl;
363  if ( !barrel && fabs(trackEta) < 1.0 ) {
364  double clusterr = std::sqrt(clusterX*clusterX+clusterY*clusterY);
365  double trackr = std::sqrt(track_X*track_X+track_Y*track_Y);
366  std::cout << "TrackEta/Pt = " << trackEta << " " << trackPt << ", distance = " << distance << std::endl
367  << ", Barrel/Hcal/Brem ? " << barrel << " " << hcal << " " << isBrem << std::endl
368  << " Cluster " << clusterr << " " << clusterZ << " " << clusterphi << " " << clustereta << std::endl
369  << " Track " << trackr << " " << track_Z << " " << trackphi << " " << tracketa << " " << trackEta << " " << trackPt << std::endl;
370  }
371  */
372  return dist;
373  } else {
374  return -1.;
375  }
376 
377 }
378 
379 
380 
381 double
383  const reco::PFCluster& clusterPS,
384  bool debug) {
385 
386 // 0.19 <-> strip_pitch
387 // 6.1 <-> strip_length
388  static const double resPSpitch = 0.19/sqrt(12.);
389  static const double resPSlength = 6.1/sqrt(12.);
390 
391  // Check that clusterECAL is in ECAL endcap and that clusterPS is a preshower cluster
392  if ( clusterECAL.layer() != PFLayer::ECAL_ENDCAP ||
393  ( clusterPS.layer() != PFLayer::PS1 &&
394  clusterPS.layer() != PFLayer::PS2 ) ) return -1.;
395 
396 #ifdef PFLOW_DEBUG
397  if( debug )
398  std::cout<<"entering test link by rechit function for ECAL and PS"<<std::endl;
399 #endif
400 
401  //ECAL cluster position
402  double zECAL = clusterECAL.position().Z();
403  double xECAL = clusterECAL.position().X();
404  double yECAL = clusterECAL.position().Y();
405 
406  // PS cluster position, extrapolated to ECAL
407  double zPS = clusterPS.position().Z();
408  double xPS = clusterPS.position().X(); //* zECAL/zPS;
409  double yPS = clusterPS.position().Y(); //* zECAL/zPS;
410 // MDN jan09 : check that zEcal and zPs have the same sign
411  if (zECAL*zPS <0.) return -1.;
412  double deltaX = 0.;
413  double deltaY = 0.;
414  double sqr12 = std::sqrt(12.);
415  switch (clusterPS.layer()) {
416  case PFLayer::PS1:
417  // vertical strips, measure x with pitch precision
418  deltaX = resPSpitch * sqr12;
419  deltaY = resPSlength * sqr12;
420  break;
421  case PFLayer::PS2:
422  // horizontal strips, measure y with pitch precision
423  deltaY = resPSpitch * sqr12;
424  deltaX = resPSlength * sqr12;
425  break;
426  default:
427  break;
428  }
429 
430  // Get the rechits
431  const std::vector< reco::PFRecHitFraction >& fracs = clusterECAL.recHitFractions();
432  bool linkedbyrechit = false;
433  //loop rechits
434  for(unsigned int rhit = 0; rhit < fracs.size(); ++rhit){
435 
436  const reco::PFRecHitRef& rh = fracs[rhit].recHitRef();
437  double fraction = fracs[rhit].fraction();
438  if(fraction < 1E-4) continue;
439  if(rh.isNull()) continue;
440 
441  //getting rechit center position
442  const reco::PFRecHit& rechit_cluster = *rh;
443 
444  //getting rechit corners
445  const std::vector< math::XYZPoint >& corners = rechit_cluster.getCornersXYZ();
446  assert(corners.size() == 4);
447 
448  const math::XYZPoint& posxyz = rechit_cluster.position() * zPS/zECAL;
449 #ifdef PFLOW_DEBUG
450  if( debug ){
451  std::cout << "Ecal rechit " << posxyz.X() << " " << posxyz.Y() << std::endl;
452  std::cout << "PS cluster " << xPS << " " << yPS << std::endl;
453  }
454 #endif
455 
456  double x[5];
457  double y[5];
458  for ( unsigned jc=0; jc<4; ++jc ) {
459  // corner position projected onto the preshower
460  math::XYZPoint cornerpos = corners[jc] * zPS/zECAL;
461  // Inflate the size by the size of the PS strips, and by 5% to include ECAL cracks.
462  x[jc] = cornerpos.X() + (cornerpos.X()-posxyz.X()) * (0.05 +1.0/fabs((cornerpos.X()-posxyz.X()))*0.5*deltaX);
463  y[jc] = cornerpos.Y() + (cornerpos.Y()-posxyz.Y()) * (0.05 +1.0/fabs((cornerpos.Y()-posxyz.Y()))*0.5*deltaY);
464 
465 #ifdef PFLOW_DEBUG
466  if( debug ){
467  std::cout<<"corners "<<jc
468  << " " << cornerpos.X() << " " << x[jc]
469  << " " << cornerpos.Y() << " " << y[jc]
470  << std::endl;
471  }
472 #endif
473  }//loop corners
474 
475  //need to close the polygon in order to
476  //use the TMath::IsInside fonction from root lib
477  x[4] = x[0];
478  y[4] = y[0];
479 
480  //Check if the extrapolation point of the track falls
481  //within the rechit boundaries
482  bool isinside = TMath::IsInside(xPS,yPS,5,x,y);
483 
484  if( isinside ){
485  linkedbyrechit = true;
486  break;
487  }
488 
489  }//loop rechits
490 
491  if( linkedbyrechit ) {
492  if( debug ) std::cout << "Cluster PS and Cluster ECAL LINKED BY RECHIT" << std::endl;
493  double dist = computeDist( xECAL/1000.,yECAL/1000.,
494  xPS/1000. ,yPS/1000,
495  false);
496  return dist;
497  } else {
498  return -1.;
499  }
500 
501 }
502 
503 
504 
505 double
507  const reco::PFCluster& clusterHFHAD,
508  bool debug) {
509 
510  math::XYZPoint posxyzEM = clusterHFEM.position();
511  math::XYZPoint posxyzHAD = clusterHFHAD.position();
512 
513  double dX = posxyzEM.X()-posxyzHAD.X();
514  double dY = posxyzEM.Y()-posxyzHAD.Y();
515  double sameZ = posxyzEM.Z()*posxyzHAD.Z();
516 
517  if(sameZ<0) return -1.;
518 
519  double dist2 = dX*dX + dY*dY;
520 
521  if( dist2 < 0.1 ) {
522  // less than one mm
523  double dist = sqrt( dist2 );
524  return dist;;
525  }
526  else
527  return -1.;
528 
529 }
530 
531 double
532 LinkByRecHit::computeDist( double eta1, double phi1,
533  double eta2, double phi2,
534  bool etaPhi ) {
535 
536  const double phicor = etaPhi ? normalizedPhi(phi1 - phi2) : phi1 - phi2;
537  const double etadiff = eta1 - eta2;
538 
539  // double chi2 =
540  // (eta1 - eta2)*(eta1 - eta2) / ( reta1*reta1+ reta2*reta2 ) +
541  // phicor*phicor / ( rphi1*rphi1+ rphi2*rphi2 );
542 
543  return std::sqrt(etadiff*etadiff + phicor*phicor);
544 
545 }
PFLayer::Layer layer() const
cluster layer, see PFLayer.h in this directory
Definition: PFCluster.cc:85
const REPPoint & positionREP() const
trajectory position in (rho, eta, phi) base
const math::XYZPoint & position() const
cluster centroid position
Definition: CaloCluster.h:124
reconstructed track used as an input to particle flow
Definition: PFRecTrack.h:22
static double computeDist(double eta1, double phi1, double eta2, double phi2, bool etaPhi=true)
computes a chisquare
ROOT::Math::PositionVector3D< ROOT::Math::CylindricalEta3D< Double32_t > > REPPoint
Definition: PFRecHit.h:39
Particle flow cluster, see clustering algorithm in PFClusterAlgo.
Definition: PFCluster.h:47
tuple trackPt
Definition: listHistos.py:120
static double testECALAndPSByRecHit(const reco::PFCluster &clusterECAL, const reco::PFCluster &clusterPS, bool debug=false)
const math::XYZPoint & position() const
cartesian position (x, y, z)
const std::vector< math::XYZPoint > & getCornersXYZ() const
rechit corners
Definition: PFRecHit.h:132
bool isNull() const
Checks for null.
Definition: Ref.h:247
Particle flow rechit (rechit + geometry and topology information). See clustering algorithm in PFClus...
Definition: PFRecHit.h:35
Point of closest approach from beam axis (initial point in the case of PFSimParticle) ...
T sqrt(T t)
Definition: SSEVec.h:48
const REPPoint & positionREP() const
cluster position: rho, eta, phi
Definition: PFCluster.h:87
const std::vector< REPPoint > & getCornersREP() const
Definition: PFRecHit.h:135
const reco::PFTrajectoryPoint & extrapolatedPoint(unsigned layerid) const
Definition: PFTrack.cc:76
T min(T a, T b)
Definition: MathUtil.h:58
#define M_PI
const math::XYZPoint & position() const
rechit cell centre x, y, z
Definition: PFRecHit.h:123
const math::XYZTLorentzVector & momentum() const
4-momenta quadrivector
#define debug
Definition: HDRShower.cc:19
bool isValid() const
is this point valid ?
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
static double testHFEMAndHFHADByRecHit(const reco::PFCluster &clusterHFEM, const reco::PFCluster &clusterHFHAD, bool debug=false)
test association between HFEM and HFHAD, by rechit
double energy() const
rechit energy
Definition: PFRecHit.h:107
const std::vector< reco::PFRecHitFraction > & recHitFractions() const
vector of rechit fractions
Definition: PFCluster.h:69
tuple cout
Definition: gather_cfg.py:121
A PFTrack holds several trajectory points, which basically contain the position and momentum of a tra...
const REPPoint & positionREP() const
Definition: PFRecHit.h:125
Definition: DDAxes.h:10
double normalizedPhi(double phi)
Definition: normalizedPhi.cc:5
static double testTrackAndClusterByRecHit(const reco::PFRecTrack &track, const reco::PFCluster &cluster, bool isBrem=false, bool debug=false)
Definition: LinkByRecHit.cc:10