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