CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/src/RecoMuon/MuonIsolation/plugins/CaloExtractor.cc

Go to the documentation of this file.
00001 #include "CaloExtractor.h"
00002 
00003 #include "DataFormats/Common/interface/Handle.h"
00004 #include "FWCore/Framework/interface/ESHandle.h"
00005 #include "DataFormats/TrackReco/interface/Track.h"
00006 #include "DataFormats/TrackReco/interface/TrackFwd.h"
00007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00008 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00009 
00010 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00011 #include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
00012 
00013 #include "MagneticField/Engine/interface/MagneticField.h"
00014 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00015 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00016 #include "DataFormats/Math/interface/deltaR.h"
00017 //#include "CommonTools/Utils/interface/deltaR.h"
00018 //#include "PhysicsTools/Utilities/interface/deltaR.h"
00019 #include "CommonTools/Utils/interface/normalizedPhi.h"
00020 //#include "PhysicsTools/Utilities/interface/normalizedPhi.h"
00021 
00022 using namespace edm;
00023 using namespace std;
00024 using namespace reco;
00025 using namespace muonisolation;
00026 using reco::isodeposit::Direction;
00027 
00028 CaloExtractor::CaloExtractor(const ParameterSet& par) :
00029   theCaloTowerCollectionLabel(par.getParameter<edm::InputTag>("CaloTowerCollectionLabel")),
00030   theDepositLabel(par.getUntrackedParameter<string>("DepositLabel")),
00031   theWeight_E(par.getParameter<double>("Weight_E")),
00032   theWeight_H(par.getParameter<double>("Weight_H")),
00033   theThreshold_E(par.getParameter<double>("Threshold_E")),
00034   theThreshold_H(par.getParameter<double>("Threshold_H")),
00035   theDR_Veto_E(par.getParameter<double>("DR_Veto_E")),
00036   theDR_Veto_H(par.getParameter<double>("DR_Veto_H")),
00037   theDR_Max(par.getParameter<double>("DR_Max")),
00038   vertexConstraintFlag_XY(par.getParameter<bool>("Vertex_Constraint_XY")),
00039   vertexConstraintFlag_Z(par.getParameter<bool>("Vertex_Constraint_Z"))
00040 {
00041 }
00042 
00043 void CaloExtractor::fillVetos(const edm::Event& event, const edm::EventSetup& eventSetup, const TrackCollection& muons)
00044 {
00045   theVetoCollection.clear();
00046 
00047   Handle<CaloTowerCollection> towers;
00048   event.getByLabel(theCaloTowerCollectionLabel,towers);
00049 
00050   edm::ESHandle<CaloGeometry> caloGeom;
00051   eventSetup.get<CaloGeometryRecord>().get(caloGeom);
00052 
00053   edm::ESHandle<MagneticField> bField;
00054   eventSetup.get<IdealMagneticFieldRecord>().get(bField);
00055   double bz = bField->inInverseGeV(GlobalPoint(0.,0.,0.)).z();
00056 
00057   TrackCollection::const_iterator mu;
00058   TrackCollection::const_iterator muEnd(muons.end());
00059   
00060   CaloTowerCollection::const_iterator cal;
00061   CaloTowerCollection::const_iterator calEnd(towers->end());
00062   
00063   for ( mu = muons.begin(); mu != muEnd; ++mu ) {
00064     for ( cal = towers->begin(); cal != calEnd; ++cal ) {
00066       double dEta = fabs(mu->eta()-cal->eta());
00067       if (fabs(dEta) > theDR_Max) continue;
00068 
00069             double deltar0 = reco::deltaR(*mu,*cal);
00070             if (deltar0>theDR_Max) continue;
00071 
00072             double etecal = cal->emEt();
00073             double eecal = cal->emEnergy();
00074             bool doEcal = theWeight_E>0 && etecal>theThreshold_E && eecal>3*noiseEcal(*cal);
00075             double ethcal = cal->hadEt();
00076             double ehcal = cal->hadEnergy();
00077             bool doHcal = theWeight_H>0 && ethcal>theThreshold_H && ehcal>3*noiseHcal(*cal);
00078             if ((!doEcal) && (!doHcal)) continue;
00079 
00080             DetId calId = cal->id();
00081             GlobalPoint endpos = caloGeom->getPosition(calId);
00082             GlobalPoint muatcal = MuonAtCaloPosition(*mu,bz,endpos, vertexConstraintFlag_XY, vertexConstraintFlag_Z);
00083             double deltar = reco::deltaR(muatcal,endpos);
00084 
00085             if (doEcal) {
00086                   if (deltar<theDR_Veto_E) theVetoCollection.push_back(calId);
00087             } else {
00088                   if (deltar<theDR_Veto_H) theVetoCollection.push_back(calId);
00089             }
00090       }
00091   }
00092      
00093 }
00094 
00095 IsoDeposit CaloExtractor::deposit( const Event & event, const EventSetup& eventSetup, const Track & muon) const
00096 {
00097   IsoDeposit dep(muon.eta(), muon.phi() );
00098   LogDebug("Muon|RecoMuon|L2MuonIsolationProducer")
00099           << " >>> Muon: pt " << muon.pt()
00100           << " eta " << muon.eta()
00101           << " phi " << muon.phi();
00102 
00103   Handle<CaloTowerCollection> towers;
00104   event.getByLabel(theCaloTowerCollectionLabel,towers);
00105 
00106   edm::ESHandle<CaloGeometry> caloGeom;
00107   eventSetup.get<CaloGeometryRecord>().get(caloGeom);
00108 
00109   edm::ESHandle<MagneticField> bField;
00110   eventSetup.get<IdealMagneticFieldRecord>().get(bField);
00111   double bz = bField->inInverseGeV(GlobalPoint(0.,0.,0.)).z();
00112 
00113   CaloTowerCollection::const_iterator cal;
00114   CaloTowerCollection::const_iterator calEnd(towers->end());
00115   for ( cal = towers->begin(); cal != calEnd; ++cal ) {
00117       double dEta = fabs(muon.eta()-cal->eta());
00118       if (fabs(dEta) > theDR_Max) continue;
00119     
00120       double deltar0 = reco::deltaR(muon,*cal);
00121       if (deltar0>theDR_Max) continue;
00122 
00123       double etecal = cal->emEt();
00124       double eecal = cal->emEnergy();
00125       bool doEcal = theWeight_E>0 && etecal>theThreshold_E && eecal>3*noiseEcal(*cal);
00126       double ethcal = cal->hadEt();
00127       double ehcal = cal->hadEnergy();
00128       bool doHcal = theWeight_H>0 && ethcal>theThreshold_H && ehcal>3*noiseHcal(*cal);
00129       if ((!doEcal) && (!doHcal)) continue;
00130 
00131       DetId calId = cal->id();
00132       GlobalPoint endpos = caloGeom->getPosition(calId);
00133       GlobalPoint muatcal = MuonAtCaloPosition(muon,bz,endpos,vertexConstraintFlag_XY, vertexConstraintFlag_Z);
00134       double deltar = reco::deltaR(muatcal,endpos);
00135 
00136       if (deltar<theDR_Veto_H) {
00137               dep.setVeto(IsoDeposit::Veto(reco::isodeposit::Direction(muatcal.eta(), muatcal.phi()), theDR_Veto_H));
00138       }
00139 
00140       if (doEcal) {
00141             if (deltar<theDR_Veto_E) { 
00142                   double calodep = theWeight_E*etecal;
00143                   if (doHcal) calodep += theWeight_H*ethcal;
00144                   dep.addCandEnergy(calodep);
00145                     LogDebug("Muon|RecoMuon|L2MuonIsolationProducer")
00146                     << " >>> Calo deposit inside veto (with ECAL): deltar " << deltar
00147                     << " calodep " << calodep
00148                     << " ecaldep " << etecal
00149                     << " hcaldep " << ethcal
00150                     << " eta " << cal->eta()
00151                     << " phi " << cal->phi();
00152                   continue;
00153             }
00154       } else {
00155             if (deltar<theDR_Veto_H) { 
00156                   dep.addCandEnergy(theWeight_H*ethcal);
00157                     LogDebug("Muon|RecoMuon|L2MuonIsolationProducer")
00158                     << " >>> Calo deposit inside veto (no ECAL): deltar " << deltar
00159                     << " calodep " << theWeight_H*ethcal
00160                     << " eta " << cal->eta()
00161                     << " phi " << cal->phi();
00162                   continue;
00163             }
00164       }
00165 
00166       if (std::find(theVetoCollection.begin(), theVetoCollection.end()
00167                   , calId)!=theVetoCollection.end()) {
00168             LogDebug("Muon|RecoMuon|L2MuonIsolationProducer")
00169             << " >>> Deposits belongs to other track: deltar, etecal, ethcal= " 
00170             << deltar << ", " << etecal << ", " << ethcal;
00171             continue;
00172       }
00173 
00174       if (doEcal) {
00175             if (deltar>theDR_Veto_E) { 
00176                   double calodep = theWeight_E*etecal;
00177                   if (doHcal) calodep += theWeight_H*ethcal;
00178                   dep.addDeposit(reco::isodeposit::Direction(endpos.eta(), endpos.phi()),calodep);
00179                     LogDebug("Muon|RecoMuon|L2MuonIsolationProducer")
00180                     << " >>> Calo deposit (with ECAL): deltar " << deltar
00181                     << " calodep " << calodep
00182                     << " ecaldep " << etecal
00183                     << " hcaldep " << ethcal
00184                     << " eta " << cal->eta()
00185                     << " phi " << cal->phi();
00186             }
00187       } else {
00188             if (deltar>theDR_Veto_H) { 
00189                     dep.addDeposit(reco::isodeposit::Direction(endpos.eta(), endpos.phi()),theWeight_H*ethcal);
00190                     LogDebug("Muon|RecoMuon|L2MuonIsolationProducer")
00191                     << " >>> Calo deposit (no ECAL): deltar " << deltar
00192                     << " calodep " << theWeight_H*ethcal
00193                     << " eta " << cal->eta()
00194                     << " phi " << cal->phi();
00195             }
00196       }
00197   }
00198 
00199   return dep;
00200 
00201 }
00202 
00203 GlobalPoint CaloExtractor::MuonAtCaloPosition(const Track& muon, const double bz, const GlobalPoint& endpos, bool fixVxy, bool fixVz) {
00204       double qoverp= muon.qoverp();
00205       double cur = bz*muon.charge()/muon.pt();
00206       double phi0 = muon.phi();
00207       double dca = muon.dxy();
00208       double theta = muon.theta();
00209       double dz = muon.dz();
00210 
00211       //LogDebug("Muon|RecoMuon|L2MuonIsolationProducer")
00212           //<< " Pt(GeV): " <<  muon.pt()
00213           //<< ", phi0 " <<  muon.phi0()
00214              //<< ", eta " <<  muon.eta();
00215       //LogDebug("Muon|RecoMuon|L2MuonIsolationProducer")
00216           //<< " d0 " <<  muon.d0()
00217           //<< ", dz " <<  muon.dz();
00218       //LogDebug("Muon|RecoMuon|L2MuonIsolationProducer")
00219           //<< " rhocal " <<  endpos.perp()
00220           //<< ", zcal " <<  endpos.z();
00221 
00222       if (fixVxy && fixVz) {
00223             // Note that here we assume no correlation between XY and Z projections
00224             // This should be a reasonable approximation for our purposes
00225             double errd02 = muon.covariance(muon.i_dxy,muon.i_dxy);
00226             if (pow(muon.dxy(),2)<4*errd02) {
00227                   phi0 -= muon.dxy()*muon.covariance(muon.i_dxy,muon.i_phi)
00228                                      /errd02;
00229                   cur -= muon.dxy()*muon.covariance(muon.i_dxy,muon.i_qoverp)
00230                                      /errd02 * (cur/qoverp);
00231                   dca = 0;
00232             } 
00233             double errdsz2 = muon.covariance(muon.i_dsz,muon.i_dsz);
00234             if (pow(muon.dsz(),2)<4*errdsz2) {
00235                   theta += muon.dsz()*muon.covariance(muon.i_dsz,muon.i_lambda)
00236                                      /errdsz2;
00237                   dz = 0;
00238             } 
00239       } else if (fixVxy) {
00240             double errd02 = muon.covariance(muon.i_dxy,muon.i_dxy);
00241             if (pow(muon.dxy(),2)<4*errd02) {
00242                   phi0  -= muon.dxy()*muon.covariance(muon.i_dxy,muon.i_phi)
00243                                      /errd02;
00244                   cur -= muon.dxy()*muon.covariance(muon.i_dxy,muon.i_qoverp)
00245                                      /errd02 * (cur/qoverp);
00246                   theta += muon.dxy()*muon.covariance(muon.i_dxy,muon.i_lambda)
00247                                      /errd02;
00248                   dz    -= muon.dxy()*muon.covariance(muon.i_dxy,muon.i_dsz)
00249                                      /errd02 * muon.p()/muon.pt();
00250                   dca = 0;
00251             } 
00252       } else if (fixVz) {
00253             double errdsz2 = muon.covariance(muon.i_dsz,muon.i_dsz);
00254             if (pow(muon.dsz(),2)<4*errdsz2) {
00255                   theta += muon.dsz()*muon.covariance(muon.i_dsz,muon.i_lambda)
00256                                      /errdsz2;
00257                   phi0  -= muon.dsz()*muon.covariance(muon.i_dsz,muon.i_phi)
00258                                      /errdsz2;
00259                   cur -= muon.dsz()*muon.covariance(muon.i_dsz,muon.i_qoverp)
00260                                      /errdsz2 * (cur/qoverp);
00261                   dca   -= muon.dsz()*muon.covariance(muon.i_dsz,muon.i_dxy)
00262                                      /errdsz2;
00263                   dz = 0;
00264             } 
00265       }
00266 
00267       double sphi0 = sin(phi0);
00268       double cphi0 = cos(phi0);
00269 
00270       double xsin =  endpos.x()*sphi0 - endpos.y()*cphi0;
00271       double xcos =  endpos.x()*cphi0 + endpos.y()*sphi0;
00272       double fcdca = fabs(1-cur*dca);
00273       double phif = atan2( fcdca*sphi0-cur*endpos.x()
00274                          , fcdca*cphi0+cur*endpos.y());
00275       double tphif2 = tan(0.5*(phif-phi0));
00276       double dcaf = dca + xsin + xcos*tphif2;
00277 
00278       double x = endpos.x() - dcaf*sin(phif);
00279       double y = endpos.y() + dcaf*cos(phif);
00280 
00281       double deltas =  (x-muon.vx())*cphi0 + (y-muon.vy())*sphi0;
00282       double deltaphi = normalizedPhi(phif-phi0);
00283       if (deltaphi!=0) deltas = deltas*deltaphi/sin(deltaphi);
00284 
00285       double z =dz;
00286       double tantheta = tan(theta);
00287       if (tantheta!=0) {
00288             z += deltas/tan(theta);
00289       } else {
00290             z = endpos.z();
00291       }
00292 
00293       return GlobalPoint(x,y,z);
00294 }
00295 
00296 double CaloExtractor::noiseEcal(const CaloTower& tower) const {
00297       double noise = 0.04;
00298       double eta = tower.eta();
00299       if (fabs(eta)>1.479) noise = 0.15;
00300       return noise;
00301 }
00302 
00303 double CaloExtractor::noiseHcal(const CaloTower& tower) const {
00304       double noise = 0.2;
00305       return noise;
00306 }