CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/RecoParticleFlow/PFClusterTools/src/LinkByRecHit.cc

Go to the documentation of this file.
00001 #include "RecoParticleFlow/PFClusterTools/interface/LinkByRecHit.h"
00002 #include "DataFormats/Math/interface/normalizedPhi.h"
00003 #include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
00004 #include "TMath.h"
00005 
00006 // to enable debugs
00007 //#define PFLOW_DEBUG
00008 
00009 double 
00010 LinkByRecHit::testTrackAndClusterByRecHit ( const reco::PFRecTrack& track, 
00011                                             const reco::PFCluster&  cluster,
00012                                             bool isBrem,
00013                                             bool debug)  {
00014   
00015 #ifdef PFLOW_DEBUG
00016   if( debug ) 
00017     std::cout<<"entering test link by rechit function"<<std::endl;
00018 #endif
00019   
00020   //cluster position
00021   double clustereta  = cluster.positionREP().Eta();
00022   double clusterphi  = cluster.positionREP().Phi();
00023   double clusterX    = cluster.position().X();
00024   double clusterY    = cluster.position().Y();
00025   double clusterZ    = cluster.position().Z();
00026 
00027   bool barrel = false;
00028   bool hcal = false;
00029   double distance = 999999.9;
00030 
00031   //track extrapolation
00032   const reco::PFTrajectoryPoint& atVertex 
00033     = track.extrapolatedPoint( reco::PFTrajectoryPoint::ClosestApproach );
00034   const reco::PFTrajectoryPoint& atECAL 
00035     = track.extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax );
00036 
00037   //track at calo's
00038   double tracketa = 999999.9;
00039   double trackphi = 999999.9;
00040   double track_X  = 999999.9;
00041   double track_Y  = 999999.9;
00042   double track_Z  = 999999.9;
00043   double dHEta = 0.;
00044   double dHPhi = 0.;
00045 
00046   // Quantities at vertex
00047   double trackPt = isBrem ? 999. : sqrt(atVertex.momentum().Vect().Perp2());
00048   // double trackEta = isBrem ? 999. : atVertex.momentum().Vect().Eta();
00049 
00050 
00051   switch (cluster.layer()) {
00052   case PFLayer::ECAL_BARREL: barrel = true;
00053   case PFLayer::ECAL_ENDCAP:
00054 #ifdef PFLOW_DEBUG
00055     if( debug )
00056       std::cout << "Fetching Ecal Resolution Maps"
00057            << std::endl;
00058 #endif
00059     // did not reach ecal, cannot be associated with a cluster.
00060     if( ! atECAL.isValid() ) return -1.;   
00061     
00062     tracketa = atECAL.positionREP().Eta();
00063     trackphi = atECAL.positionREP().Phi();
00064     track_X  = atECAL.position().X();
00065     track_Y  = atECAL.position().Y();
00066     track_Z  = atECAL.position().Z();
00067 
00068     distance 
00069       = std::sqrt( (track_X-clusterX)*(track_X-clusterX)
00070                   +(track_Y-clusterY)*(track_Y-clusterY)
00071                   +(track_Z-clusterZ)*(track_Z-clusterZ)
00072                    );
00073                                    
00074     break;
00075    
00076   case PFLayer::HCAL_BARREL1: barrel = true; 
00077   case PFLayer::HCAL_ENDCAP:  
00078 #ifdef PFLOW_DEBUG
00079     if( debug )
00080       std::cout << "Fetching Hcal Resolution Maps"
00081            << std::endl;
00082 #endif
00083     if( isBrem ) {  
00084       return  -1.;
00085     } else { 
00086       hcal=true;
00087       const reco::PFTrajectoryPoint& atHCAL 
00088         = track.extrapolatedPoint( reco::PFTrajectoryPoint::HCALEntrance );
00089       const reco::PFTrajectoryPoint& atHCALExit 
00090         = track.extrapolatedPoint( reco::PFTrajectoryPoint::HCALExit );
00091       // did not reach hcal, cannot be associated with a cluster.
00092       if( ! atHCAL.isValid() ) return -1.;   
00093       
00094       // The link is computed between 0 and ~1 interaction length in HCAL
00095       dHEta = atHCALExit.positionREP().Eta()-atHCAL.positionREP().Eta();
00096       dHPhi = atHCALExit.positionREP().Phi()-atHCAL.positionREP().Phi(); 
00097       if ( dHPhi > M_PI ) dHPhi = dHPhi - 2.*M_PI;
00098       else if ( dHPhi < -M_PI ) dHPhi = dHPhi + 2.*M_PI; 
00099       tracketa = atHCAL.positionREP().Eta() + 0.1*dHEta;
00100       trackphi = atHCAL.positionREP().Phi() + 0.1*dHPhi;
00101       track_X  = atHCAL.position().X();
00102       track_Y  = atHCAL.position().Y();
00103       track_Z  = atHCAL.position().Z();
00104       distance 
00105         = -std::sqrt( (track_X-clusterX)*(track_X-clusterX)
00106                      +(track_Y-clusterY)*(track_Y-clusterY)
00107                      +(track_Z-clusterZ)*(track_Z-clusterZ)
00108                      );
00109                                    
00110     }
00111     break;
00112   case PFLayer::PS1:
00113   case PFLayer::PS2:
00114     //Note Alex: Nothing implemented for the
00115     //PreShower (No resolution maps yet)
00116 #ifdef PFLOW_DEBUG
00117     if( debug )
00118       std::cout << "No link by rechit possible for pre-shower yet!"
00119            << std::endl;
00120 #endif
00121     return -1.;
00122   default:
00123     return -1.;
00124   }
00125 
00126 
00127   // Check that, if the cluster is in the endcap, 
00128   // 0) the track indeed points to the endcap at vertex (DISABLED)
00129   // 1) the track extrapolation is in the endcap too !
00130   // 2) the track is in the same end-cap !
00131   // PJ - 10-May-09
00132   if ( !barrel ) { 
00133     // if ( fabs(trackEta) < 1.0 ) return -1; 
00134     if ( !hcal && fabs(track_Z) < 300. ) return -1.;
00135     if ( track_Z * clusterZ < 0. ) return -1.;
00136   }
00137   // Check that, if the cluster is in the barrel, 
00138   // 1) the track is in the barrel too !
00139   if ( barrel ) 
00140     if ( !hcal && fabs(track_Z) > 300. ) return -1.;
00141 
00142   // Finally check that, if the track points to the central barrel (|eta| < 1), 
00143   // it cannot be linked to a cluster in Endcaps (avoid low pt loopers)
00144 
00145 
00146   double dist = LinkByRecHit::computeDist( clustereta, clusterphi, 
00147                                          tracketa, trackphi);
00148   
00149 #ifdef PFLOW_DEBUG
00150   if(debug) std::cout<<"test link by rechit "<< dist <<" "<<std::endl;
00151   if(debug){
00152     std::cout<<" clustereta "  << clustereta 
00153         <<" clusterphi "  << clusterphi 
00154         <<" tracketa " << tracketa
00155         <<" trackphi " << trackphi << std::endl;
00156   }
00157 #endif
00158   
00159   //Testing if Track can be linked by rechit to a cluster.
00160   //A cluster can be linked to a track if the extrapolated position 
00161   //of the track to the ECAL ShowerMax/HCAL entrance falls within 
00162   //the boundaries of any cell that belongs to this cluster.
00163 
00164   const std::vector< reco::PFRecHitFraction >& 
00165     fracs = cluster.recHitFractions();
00166   
00167   bool linkedbyrechit = false;
00168   //loop rechits
00169   for(unsigned int rhit = 0; rhit < fracs.size(); ++rhit){
00170 
00171     const reco::PFRecHitRef& rh = fracs[rhit].recHitRef();
00172     double fraction = fracs[rhit].fraction();
00173     if(fraction < 1E-4) continue;
00174     if(rh.isNull()) continue;
00175     
00176     //getting rechit center position
00177     const reco::PFRecHit& rechit_cluster = *rh;
00178     const math::XYZPoint& posxyz 
00179       = rechit_cluster.position();
00180     const reco::PFRecHit::REPPoint& posrep 
00181       = rechit_cluster.positionREP();
00182     
00183     //getting rechit corners
00184     const std::vector< math::XYZPoint >& 
00185       cornersxyz = rechit_cluster.getCornersXYZ();
00186     const std::vector<reco::PFRecHit::REPPoint>& corners = 
00187       rechit_cluster.getCornersREP();
00188     assert(corners.size() == 4);
00189     
00190     if( barrel || hcal ){ // barrel case matching in eta/phi 
00191                           // (and HCAL endcap too!)
00192       
00193       //rechit size determination 
00194       // blown up by 50% (HCAL) to 100% (ECAL) to include cracks & gaps
00195       // also blown up to account for multiple scattering at low pt.
00196       double rhsizeEta 
00197         = fabs(corners[0].Eta() - corners[2].Eta());
00198       double rhsizePhi 
00199         = fabs(corners[0].Phi() - corners[2].Phi());
00200       if ( rhsizePhi > M_PI ) rhsizePhi = 2.*M_PI - rhsizePhi;
00201       if ( hcal ) { 
00202         rhsizeEta = rhsizeEta * (1.50 + 0.5/fracs.size()) + 0.2*fabs(dHEta);
00203         rhsizePhi = rhsizePhi * (1.50 + 0.5/fracs.size()) + 0.2*fabs(dHPhi); 
00204         
00205       } else { 
00206         rhsizeEta *= 2.00 + 1.0/fracs.size()/std::min(1.,trackPt/2.);
00207         rhsizePhi *= 2.00 + 1.0/fracs.size()/std::min(1.,trackPt/2.); 
00208       }
00209       
00210 #ifdef PFLOW_DEBUG
00211       if( debug ) {
00212         std::cout << rhit         << " Hcal RecHit=" 
00213              << posrep.Eta() << " " 
00214              << posrep.Phi() << " "
00215              << rechit_cluster.energy() 
00216              << std::endl; 
00217         for ( unsigned jc=0; jc<4; ++jc ) 
00218           std::cout<<"corners "<<jc<<" "<<corners[jc].Eta()
00219               <<" "<<corners[jc].Phi()<<std::endl;
00220         
00221         std::cout << "RecHit SizeEta=" << rhsizeEta
00222              << " SizePhi=" << rhsizePhi << std::endl;
00223       }
00224 #endif
00225       
00226       //distance track-rechit center
00227       // const math::XYZPoint& posxyz 
00228       // = rechit_cluster.position();
00229       double deta = fabs(posrep.Eta() - tracketa);
00230       double dphi = fabs(posrep.Phi() - trackphi);
00231       if ( dphi > M_PI ) dphi = 2.*M_PI - dphi;
00232       
00233 #ifdef PFLOW_DEBUG
00234       if( debug ){
00235         std::cout << "distance=" 
00236              << deta << " " 
00237              << dphi << " ";
00238         if(deta < (rhsizeEta/2.) && dphi < (rhsizePhi/2.))
00239           std::cout << " link here !" << std::endl;
00240         else std::cout << std::endl;
00241       }
00242 #endif
00243       
00244       if(deta < (rhsizeEta/2.) && dphi < (rhsizePhi/2.)){ 
00245         linkedbyrechit = true;
00246         break;
00247       }
00248     }
00249     else { //ECAL & PS endcap case, matching in X,Y
00250       
00251 #ifdef PFLOW_DEBUG
00252       if( debug ){
00253         const math::XYZPoint& posxyz 
00254           = rechit_cluster.position();
00255         
00256         std::cout << "RH " << posxyz.X()
00257              << " "   << posxyz.Y()
00258              << std::endl;
00259         
00260         std::cout << "TRACK " << track_X
00261              << " "      << track_Y
00262              << std::endl;
00263       }
00264 #endif
00265       
00266       double x[5];
00267       double y[5];
00268       
00269       for ( unsigned jc=0; jc<4; ++jc ) {
00270         math::XYZPoint cornerposxyz = cornersxyz[jc];
00271         x[jc] = cornerposxyz.X() + (cornerposxyz.X()-posxyz.X())
00272           * (1.00+0.50/fracs.size()/std::min(1.,trackPt/2.));
00273         y[jc] = cornerposxyz.Y() + (cornerposxyz.Y()-posxyz.Y())
00274           * (1.00+0.50/fracs.size()/std::min(1.,trackPt/2.));
00275         
00276 #ifdef PFLOW_DEBUG
00277         if( debug ){
00278           std::cout<<"corners "<<jc
00279               << " " << cornerposxyz.X()
00280               << " " << cornerposxyz.Y()
00281               << std::endl;
00282         }
00283 #endif
00284       }//loop corners
00285       
00286       //need to close the polygon in order to
00287       //use the TMath::IsInside fonction from root lib
00288       x[4] = x[0];
00289       y[4] = y[0];
00290       
00291       //Check if the extrapolation point of the track falls 
00292       //within the rechit boundaries
00293       bool isinside = TMath::IsInside(track_X,
00294                                       track_Y,
00295                                       5,x,y);
00296       
00297       if( isinside ){
00298         linkedbyrechit = true;
00299         break;
00300       }
00301     }//
00302     
00303   }//loop rechits
00304   
00305   if( linkedbyrechit ) {
00306 #ifdef PFLOW_DEBUG
00307     if( debug ) 
00308       std::cout << "Track and Cluster LINKED BY RECHIT" << std::endl;
00309 #endif
00310     /*    
00311     //if ( distance > 40. || distance < -100. ) 
00312     double clusterr = std::sqrt(clusterX*clusterX+clusterY*clusterY);
00313     double trackr = std::sqrt(track_X*track_X+track_Y*track_Y);
00314     if ( distance > 40. ) 
00315     std::cout << "Distance = " << distance 
00316     << ", Barrel/Hcal/Brem ? " << barrel << " " << hcal << " " << isBrem << std::endl
00317     << " Cluster " << clusterr << " " << clusterZ << " " << clusterphi << " " << clustereta << std::endl
00318     << " Track   " << trackr << " " << track_Z << " " << trackphi << " " << tracketa << std::endl;
00319     if ( !barrel && fabs(trackEta) < 1.0 ) { 
00320       double clusterr = std::sqrt(clusterX*clusterX+clusterY*clusterY);
00321       double trackr = std::sqrt(track_X*track_X+track_Y*track_Y);
00322       std::cout << "TrackEta/Pt = " << trackEta << " " << trackPt << ", distance = " << distance << std::endl 
00323                 << ", Barrel/Hcal/Brem ? " << barrel << " " << hcal << " " << isBrem << std::endl
00324                 << " Cluster " << clusterr << " " << clusterZ << " " << clusterphi << " " << clustereta << std::endl
00325                 << " Track   " << trackr << " " << track_Z << " " << trackphi << " " << tracketa << " " << trackEta << " " << trackPt << std::endl;
00326     } 
00327     */
00328     return dist;
00329   } else {
00330     return -1.;
00331   }
00332 
00333 }
00334 
00335 
00336 
00337 double
00338 LinkByRecHit::testECALAndPSByRecHit( const reco::PFCluster& clusterECAL, 
00339                                      const reco::PFCluster& clusterPS,
00340                                      bool debug)  {
00341 
00342 // 0.19 <-> strip_pitch
00343 // 6.1  <-> strip_length
00344   static double resPSpitch = 0.19/sqrt(12.);
00345   static double resPSlength = 6.1/sqrt(12.);
00346 
00347   // Check that clusterECAL is in ECAL endcap and that clusterPS is a preshower cluster
00348   if ( clusterECAL.layer() != PFLayer::ECAL_ENDCAP ||
00349        ( clusterPS.layer() != PFLayer::PS1 && 
00350          clusterPS.layer() != PFLayer::PS2 ) ) return -1.;
00351 
00352 #ifdef PFLOW_DEBUG
00353   if( debug ) 
00354     std::cout<<"entering test link by rechit function for ECAL and PS"<<std::endl;
00355 #endif
00356 
00357   //ECAL cluster position
00358   double zECAL  = clusterECAL.position().Z();
00359   double xECAL  = clusterECAL.position().X();
00360   double yECAL  = clusterECAL.position().Y();
00361 
00362   // PS cluster position, extrapolated to ECAL
00363   double zPS = clusterPS.position().Z();
00364   double xPS = clusterPS.position().X(); //* zECAL/zPS;
00365   double yPS = clusterPS.position().Y(); //* zECAL/zPS;
00366 // MDN jan09 : check that zEcal and zPs have the same sign
00367         if (zECAL*zPS <0.) return -1.;
00368   double deltaX = 0.;
00369   double deltaY = 0.;
00370   double sqr12 = std::sqrt(12.);
00371   switch (clusterPS.layer()) {
00372   case PFLayer::PS1:
00373     // vertical strips, measure x with pitch precision
00374     deltaX = resPSpitch * sqr12;
00375     deltaY = resPSlength * sqr12;
00376     break;
00377   case PFLayer::PS2:
00378     // horizontal strips, measure y with pitch precision
00379     deltaY = resPSpitch * sqr12;
00380     deltaX = resPSlength * sqr12;
00381     break;
00382   default:
00383     break;
00384   }
00385 
00386   // Get the rechits
00387   const std::vector< reco::PFRecHitFraction >&  fracs = clusterECAL.recHitFractions();
00388   bool linkedbyrechit = false;
00389   //loop rechits
00390   for(unsigned int rhit = 0; rhit < fracs.size(); ++rhit){
00391 
00392     const reco::PFRecHitRef& rh = fracs[rhit].recHitRef();
00393     double fraction = fracs[rhit].fraction();
00394     if(fraction < 1E-4) continue;
00395     if(rh.isNull()) continue;
00396 
00397     //getting rechit center position
00398     const reco::PFRecHit& rechit_cluster = *rh;
00399     
00400     //getting rechit corners
00401     const std::vector< math::XYZPoint >&  corners = rechit_cluster.getCornersXYZ();
00402     assert(corners.size() == 4);
00403     
00404     const math::XYZPoint& posxyz = rechit_cluster.position() * zPS/zECAL;
00405 #ifdef PFLOW_DEBUG
00406     if( debug ){
00407       std::cout << "Ecal rechit " << posxyz.X() << " "   << posxyz.Y() << std::endl;
00408       std::cout << "PS cluster  " << xPS << " " << yPS << std::endl;
00409     }
00410 #endif
00411     
00412     double x[5];
00413     double y[5];
00414     for ( unsigned jc=0; jc<4; ++jc ) {
00415       // corner position projected onto the preshower
00416       math::XYZPoint cornerpos = corners[jc] * zPS/zECAL;
00417       // Inflate the size by the size of the PS strips, and by 5% to include ECAL cracks.
00418       x[jc] = cornerpos.X() + (cornerpos.X()-posxyz.X()) * (0.05 +1.0/fabs((cornerpos.X()-posxyz.X()))*deltaX/2.);
00419       y[jc] = cornerpos.Y() + (cornerpos.Y()-posxyz.Y()) * (0.05 +1.0/fabs((cornerpos.Y()-posxyz.Y()))*deltaY/2.);
00420       
00421 #ifdef PFLOW_DEBUG
00422       if( debug ){
00423         std::cout<<"corners "<<jc
00424             << " " << cornerpos.X() << " " << x[jc] 
00425             << " " << cornerpos.Y() << " " << y[jc]
00426             << std::endl;
00427       }
00428 #endif
00429     }//loop corners
00430     
00431     //need to close the polygon in order to
00432     //use the TMath::IsInside fonction from root lib
00433     x[4] = x[0];
00434     y[4] = y[0];
00435     
00436     //Check if the extrapolation point of the track falls 
00437     //within the rechit boundaries
00438     bool isinside = TMath::IsInside(xPS,yPS,5,x,y);
00439       
00440     if( isinside ){
00441       linkedbyrechit = true;
00442       break;
00443     }
00444 
00445   }//loop rechits
00446   
00447   if( linkedbyrechit ) {
00448     if( debug ) std::cout << "Cluster PS and Cluster ECAL LINKED BY RECHIT" << std::endl;
00449     double dist = computeDist( xECAL/1000.,yECAL/1000.,
00450                                xPS/1000.  ,yPS/1000, 
00451                                false);    
00452     return dist;
00453   } else { 
00454     return -1.;
00455   }
00456 
00457 }
00458 
00459 
00460 
00461 double 
00462 LinkByRecHit::testHFEMAndHFHADByRecHit(const reco::PFCluster& clusterHFEM, 
00463                                       const reco::PFCluster& clusterHFHAD,
00464                                       bool debug) {
00465   
00466   math::XYZPoint posxyzEM = clusterHFEM.position();
00467   math::XYZPoint posxyzHAD = clusterHFHAD.position();
00468 
00469   double dX = posxyzEM.X()-posxyzHAD.X();
00470   double dY = posxyzEM.Y()-posxyzHAD.Y();
00471   double sameZ = posxyzEM.Z()*posxyzHAD.Z();
00472 
00473   if(sameZ<0) return -1.;
00474 
00475   double dist2 = dX*dX + dY*dY; 
00476 
00477   if( dist2 < 0.1 ) {
00478     // less than one mm
00479     double dist = sqrt( dist2 );
00480     return dist;;
00481   }
00482   else 
00483     return -1.;
00484 
00485 }
00486 
00487 double
00488 LinkByRecHit::computeDist( double eta1, double phi1, 
00489                            double eta2, double phi2,
00490                            bool etaPhi )  {
00491   
00492   double phicor = etaPhi ? normalizedPhi(phi1 - phi2) : phi1 - phi2;
00493   
00494   // double chi2 =  
00495   //  (eta1 - eta2)*(eta1 - eta2) / ( reta1*reta1+ reta2*reta2 ) +
00496   //  phicor*phicor / ( rphi1*rphi1+ rphi2*rphi2 );
00497 
00498   double dist = std::sqrt( (eta1 - eta2)*(eta1 - eta2) 
00499                           + phicor*phicor);
00500 
00501   return dist;
00502 
00503 }