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
00018
00019 #include "CommonTools/Utils/interface/normalizedPhi.h"
00020
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
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 if (fixVxy && fixVz) {
00223
00224
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 }