00001
00002
00003
00004
00005
00006
00007 #include <math.h>
00008 #include <vector>
00009 #include "RecoMET/METAlgorithms/interface/MuonMETAlgo.h"
00010 #include "DataFormats/METReco/interface/CaloMET.h"
00011 #include "DataFormats/METReco/interface/SpecificCaloMETData.h"
00012 #include "DataFormats/JetReco/interface/CaloJet.h"
00013 #include "DataFormats/TrackReco/interface/Track.h"
00014 #include "DataFormats/CaloTowers/interface/CaloTower.h"
00015 #include "FWCore/Framework/interface/ESHandle.h"
00016 #include "Geometry/Records/interface/IdealGeometryRecord.h"
00017 #include "MagneticField/Engine/interface/MagneticField.h"
00018 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00019 #include "DataFormats/Math/interface/Point3D.h"
00020 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00021 #include "TMath.h"
00022
00023
00024 using namespace std;
00025 using namespace reco;
00026
00027 typedef math::XYZTLorentzVector LorentzVector;
00028 typedef math::XYZPoint Point;
00029
00030 CaloMET MuonMETAlgo::makeMET (const CaloMET& fMet,
00031 double fSumEt,
00032 const std::vector<CorrMETData>& fCorrections,
00033 const MET::LorentzVector& fP4) {
00034 return CaloMET (fMet.getSpecific (), fSumEt, fCorrections, fP4, fMet.vertex ());
00035 }
00036
00037
00038
00039 MET MuonMETAlgo::makeMET (const MET& fMet,
00040 double fSumEt,
00041 const std::vector<CorrMETData>& fCorrections,
00042 const MET::LorentzVector& fP4) {
00043 return MET (fSumEt, fCorrections, fP4, fMet.vertex ());
00044 }
00045
00046
00047
00048 template <class T> void MuonMETAlgo::MuonMETAlgo_run(const edm::View<reco::Muon>& inputMuons,
00049 const edm::ValueMap<reco::MuonMETCorrectionData>& vm_muCorrData,
00050 const edm::View<T>& v_uncorMET,
00051 std::vector<T>* v_corMET) {
00052 T uncorMETObj = v_uncorMET.front();
00053
00054 double uncorMETX = uncorMETObj.px();
00055 double uncorMETY = uncorMETObj.py();
00056
00057 double corMETX = uncorMETX;
00058 double corMETY = uncorMETY;
00059
00060 CorrMETData delta;
00061 double sumMuPx = 0.;
00062 double sumMuPy = 0.;
00063 double sumMuDepEx = 0.;
00064 double sumMuDepEy = 0.;
00065
00066 unsigned int nMuons = inputMuons.size();
00067 for(unsigned int iMu = 0; iMu<nMuons; iMu++) {
00068 const reco::Muon *mu = &inputMuons[iMu];
00069 reco::MuonMETCorrectionData muCorrData = (vm_muCorrData)[inputMuons.refAt(iMu)];
00070 int flag = muCorrData.type();
00071 float deltax = muCorrData.corrX();
00072 float deltay = muCorrData.corrY();
00073
00074
00075 LorentzVector mup4;
00076 if (flag == 0)
00077 continue;
00078
00079
00080 mup4 = mu->p4();
00081
00082 sumMuPx += mup4.px();
00083 sumMuPy += mup4.py();
00084 sumMuDepEx += deltax;
00085 sumMuDepEy += deltay;
00086 corMETX = corMETX - mup4.px() + deltax;
00087 corMETY = corMETY - mup4.py() + deltay;
00088
00089 }
00090 delta.mex = sumMuDepEx - sumMuPx;
00091 delta.mey = sumMuDepEy - sumMuPy;
00092 delta.sumet = sqrt(sumMuPx*sumMuPx + sumMuPy*sumMuPy) - sqrt(sumMuDepEx*sumMuDepEx + sumMuDepEy*sumMuDepEy);
00093 MET::LorentzVector correctedMET4vector( corMETX, corMETY, 0., sqrt(corMETX*corMETX + corMETY*corMETY));
00094 std::vector<CorrMETData> corrections = uncorMETObj.mEtCorr();
00095 corrections.push_back(delta);
00096
00097 T result = makeMET(uncorMETObj, uncorMETObj.sumEt()+delta.sumet, corrections, correctedMET4vector);
00098 v_corMET->push_back(result);
00099
00100 }
00101
00102 void MuonMETAlgo::GetMuDepDeltas(const reco::Muon* inputMuon,
00103 TrackDetMatchInfo& info,
00104 bool useTrackAssociatorPositions,
00105 bool useRecHits,
00106 bool useHO,
00107 double towerEtThreshold,
00108 double& deltax, double& deltay,
00109 double Bfield) {
00110
00111
00112 bool useAverage = false;
00113
00114
00115 double sumPt = inputMuon->isIsolationValid()? inputMuon->isolationR03().sumPt : 0.0;
00116 double sumEtEcal = inputMuon->isIsolationValid() ? inputMuon->isolationR03().emEt : 0.0;
00117 double sumEtHcal = inputMuon->isIsolationValid() ? inputMuon->isolationR03().hadEt : 0.0;
00118
00119 if(sumPt > 3 || sumEtEcal + sumEtHcal > 5) useAverage = true;
00120
00121
00122
00123 MuonMETInfo muMETInfo;
00124 muMETInfo.useAverage = useAverage;
00125 muMETInfo.useTkAssociatorPositions = useTrackAssociatorPositions;
00126 muMETInfo.useHO = useHO;
00127
00128
00129 TrackRef mu_track;
00130 if(inputMuon->isGlobalMuon()) {
00131 mu_track = inputMuon->globalTrack();
00132 } else if(inputMuon->isTrackerMuon()) {
00133 mu_track = inputMuon->innerTrack();
00134 } else
00135 mu_track = inputMuon->outerTrack();
00136
00137 if(useTrackAssociatorPositions) {
00138 muMETInfo.ecalPos = info.trkGlobPosAtEcal;
00139 muMETInfo.hcalPos = info.trkGlobPosAtHcal;
00140 muMETInfo.hoPos = info.trkGlobPosAtHO;
00141 }
00142
00143 if(!useAverage) {
00144
00145 if(useRecHits) {
00146 muMETInfo.ecalE = inputMuon->calEnergy().emS9;
00147 muMETInfo.hcalE = inputMuon->calEnergy().hadS9;
00148 if(useHO)
00149 muMETInfo.hoE = inputMuon->calEnergy().hoS9;
00150 } else {
00151
00152
00153 std::vector<const CaloTower*> towers = info.crossedTowers;
00154 for(vector<const CaloTower*>::const_iterator it = towers.begin();
00155 it != towers.end(); it++) {
00156 if((*it)->et() < towerEtThreshold) continue;
00157 muMETInfo.ecalE += (*it)->emEnergy();
00158 muMETInfo.hcalE += (*it)->hadEnergy();
00159 if(useHO)
00160 muMETInfo.hoE +=(*it)->outerEnergy();
00161 }
00162 }
00163 }
00164
00165
00166
00167
00168
00169 math::XYZTLorentzVector mup4;
00170 if(inputMuon->isGlobalMuon()) {
00171 if(inputMuon->globalTrack()->pt() < 200) {
00172 mup4 = LorentzVector(inputMuon->innerTrack()->px(), inputMuon->innerTrack()->py(),
00173 inputMuon->innerTrack()->pz(), inputMuon->innerTrack()->p());
00174 } else {
00175 mup4 = LorentzVector(inputMuon->globalTrack()->px(), inputMuon->globalTrack()->py(),
00176 inputMuon->globalTrack()->pz(), inputMuon->globalTrack()->p());
00177 }
00178 } else if(inputMuon->isTrackerMuon()) {
00179 mup4 = LorentzVector(inputMuon->innerTrack()->px(), inputMuon->innerTrack()->py(),
00180 inputMuon->innerTrack()->pz(), inputMuon->innerTrack()->p());
00181 } else
00182 mup4 = LorentzVector(inputMuon->outerTrack()->px(), inputMuon->outerTrack()->py(),
00183 inputMuon->outerTrack()->pz(), inputMuon->outerTrack()->p());
00184
00185
00186
00187 correctMETforMuon(deltax, deltay, Bfield, inputMuon->charge(),
00188 mup4, inputMuon->vertex(),
00189 muMETInfo);
00190 }
00191
00192
00193
00194 void MuonMETAlgo::correctMETforMuon(double& deltax, double& deltay, double bfield, int muonCharge,
00195 math::XYZTLorentzVector muonP4,math::XYZPoint muonVertex,
00196 MuonMETInfo& muonMETInfo) {
00197
00198 double mu_p = muonP4.P();
00199 double mu_pt = muonP4.Pt();
00200 double mu_phi = muonP4.Phi();
00201 double mu_eta = muonP4.Eta();
00202 double mu_vz = muonVertex.z()/100.;
00203 double mu_pz = muonP4.Pz();
00204
00205 double ecalPhi, ecalTheta;
00206 double hcalPhi, hcalTheta;
00207 double hoPhi, hoTheta;
00208
00209
00210
00211
00212
00213 if(muonMETInfo.useTkAssociatorPositions) {
00214 ecalPhi = muonMETInfo.ecalPos.Phi();
00215 ecalTheta = muonMETInfo.ecalPos.Theta();
00216 hcalPhi = muonMETInfo.hcalPos.Phi();
00217 hcalTheta = muonMETInfo.hcalPos.Theta();
00218 hoPhi = muonMETInfo.hoPos.Phi();
00219 hoTheta = muonMETInfo.hoPos.Theta();
00220 } else {
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 double rEcal = 1.290;
00231 double rHcal = 1.9;
00232 double rHo = 3.82;
00233 if(abs(mu_eta) > 0.3) rHo = 4.07;
00234
00235 double zFaceEcal = 3.209;
00236 if(mu_eta < 0 ) zFaceEcal = -1*zFaceEcal;
00237
00238 double zFaceHcal = 3.88;
00239 if(mu_eta < 0 ) zFaceHcal = -1*zFaceHcal;
00240
00241
00242
00243 double bendr = mu_pt*1000/(300*bfield);
00244
00245 double tb_ecal = TMath::ACos(1-rEcal*rEcal/(2*bendr*bendr));
00246 double tb_hcal = TMath::ACos(1-rHcal*rHcal/(2*bendr*bendr));
00247 double tb_ho = TMath::ACos(1-rHo*rHo/(2*bendr*bendr));
00248 double xEcal,yEcal,zEcal;
00249 double xHcal,yHcal,zHcal;
00250 double xHo, yHo,zHo;
00251
00252
00253 if(fabs(mu_pz*bendr*tb_ecal/mu_pt+mu_vz) < fabs(zFaceEcal) && rEcal < 2*bendr) {
00254 xEcal = bendr*(TMath::Sin(tb_ecal+mu_phi)-TMath::Sin(mu_phi));
00255 yEcal = bendr*(-TMath::Cos(tb_ecal+mu_phi)+TMath::Cos(mu_phi));
00256 zEcal = bendr*tb_ecal*mu_pz/mu_pt + mu_vz;
00257 } else {
00258 if(mu_pz > 0) {
00259 double te_ecal = (fabs(zFaceEcal) - mu_vz)*mu_pt/(bendr*mu_pz);
00260 xEcal = bendr*(TMath::Sin(te_ecal+mu_phi) - TMath::Sin(mu_phi));
00261 yEcal = bendr*(-TMath::Cos(te_ecal+mu_phi) + TMath::Cos(mu_phi));
00262 zEcal = fabs(zFaceEcal);
00263 } else {
00264 double te_ecal = -(fabs(zFaceEcal) + mu_vz)*mu_pt/(bendr*mu_pz);
00265 xEcal = bendr*(TMath::Sin(te_ecal+mu_phi) - TMath::Sin(mu_phi));
00266 yEcal = bendr*(-TMath::Cos(te_ecal+mu_phi) + TMath::Cos(mu_phi));
00267 zEcal = -fabs(zFaceEcal);
00268 }
00269 }
00270
00271
00272 if(fabs(mu_pz*bendr*tb_hcal/mu_pt+mu_vz) < fabs(zFaceHcal) && rEcal < 2*bendr) {
00273 xHcal = bendr*(TMath::Sin(tb_hcal+mu_phi)-TMath::Sin(mu_phi));
00274 yHcal = bendr*(-TMath::Cos(tb_hcal+mu_phi)+TMath::Cos(mu_phi));
00275 zHcal = bendr*tb_hcal*mu_pz/mu_pt + mu_vz;
00276 } else {
00277 if(mu_pz > 0) {
00278 double te_hcal = (fabs(zFaceHcal) - mu_vz)*mu_pt/(bendr*mu_pz);
00279 xHcal = bendr*(TMath::Sin(te_hcal+mu_phi) - TMath::Sin(mu_phi));
00280 yHcal = bendr*(-TMath::Cos(te_hcal+mu_phi) + TMath::Cos(mu_phi));
00281 zHcal = fabs(zFaceHcal);
00282 } else {
00283 double te_hcal = -(fabs(zFaceHcal) + mu_vz)*mu_pt/(bendr*mu_pz);
00284 xHcal = bendr*(TMath::Sin(te_hcal+mu_phi) - TMath::Sin(mu_phi));
00285 yHcal = bendr*(-TMath::Cos(te_hcal+mu_phi) + TMath::Cos(mu_phi));
00286 zHcal = -fabs(zFaceHcal);
00287 }
00288 }
00289
00290
00291 xHo = bendr*(TMath::Sin(tb_ho+mu_phi)-TMath::Sin(mu_phi));
00292 yHo = bendr*(-TMath::Cos(tb_ho+mu_phi)+TMath::Cos(mu_phi));
00293 zHo = bendr*tb_ho*mu_pz/mu_pt + mu_vz;
00294
00295 ecalTheta = TMath::ACos(zEcal/sqrt(pow(xEcal,2) + pow(yEcal,2)+pow(zEcal,2)));
00296 ecalPhi = atan2(yEcal,xEcal);
00297 hcalTheta = TMath::ACos(zHcal/sqrt(pow(xHcal,2) + pow(yHcal,2)+pow(zHcal,2)));
00298 hcalPhi = atan2(yHcal,xHcal);
00299 hoTheta = TMath::ACos(zHo/sqrt(pow(xHo,2) + pow(yHo,2)+pow(zHo,2)));
00300 hoPhi = atan2(yHo,xHo);
00301
00302
00303 double r2dEcal = sqrt(pow(xEcal,2)+pow(yEcal,2));
00304 double r2dHcal = sqrt(pow(xHcal,2)+pow(yHcal,2));
00305 double r2dHo = sqrt(pow(xHo,2) +pow(yHo,2));
00306
00307
00308
00309
00310
00311
00312 if(muonCharge > 0) {
00313
00314
00315 double dphi = mu_phi - ecalPhi;
00316 if(fabs(dphi) > TMath::Pi())
00317 dphi = 2*TMath::Pi() - fabs(dphi);
00318 ecalPhi = mu_phi - fabs(dphi);
00319 if(fabs(ecalPhi) > TMath::Pi()) {
00320 double temp = 2*TMath::Pi() - fabs(ecalPhi);
00321 ecalPhi = -1*temp*ecalPhi/fabs(ecalPhi);
00322 }
00323 xEcal = r2dEcal*TMath::Cos(ecalPhi);
00324 yEcal = r2dEcal*TMath::Sin(ecalPhi);
00325
00326
00327 dphi = mu_phi - hcalPhi;
00328 if(fabs(dphi) > TMath::Pi())
00329 dphi = 2*TMath::Pi() - fabs(dphi);
00330 hcalPhi = mu_phi - fabs(dphi);
00331 if(fabs(hcalPhi) > TMath::Pi()) {
00332 double temp = 2*TMath::Pi() - fabs(hcalPhi);
00333 hcalPhi = -1*temp*hcalPhi/fabs(hcalPhi);
00334 }
00335 xHcal = r2dHcal*TMath::Cos(hcalPhi);
00336 yHcal = r2dHcal*TMath::Sin(hcalPhi);
00337
00338
00339
00340 dphi = mu_phi - hoPhi;
00341 if(fabs(dphi) > TMath::Pi())
00342 dphi = 2*TMath::Pi() - fabs(dphi);
00343 hoPhi = mu_phi - fabs(dphi);
00344 if(fabs(hoPhi) > TMath::Pi()) {
00345 double temp = 2*TMath::Pi() - fabs(hoPhi);
00346 hoPhi = -1*temp*hoPhi/fabs(hoPhi);
00347 }
00348 xHo = r2dHo*TMath::Cos(hoPhi);
00349 yHo = r2dHo*TMath::Sin(hoPhi);
00350
00351 }
00352 }
00353
00354
00355 if(!muonMETInfo.useAverage) {
00356
00357 double mu_Ex = muonMETInfo.ecalE*sin(ecalTheta)*cos(ecalPhi)
00358 + muonMETInfo.hcalE*sin(hcalTheta)*cos(hcalPhi)
00359 + muonMETInfo.hoE*sin(hoTheta)*cos(hoPhi);
00360 double mu_Ey = muonMETInfo.ecalE*sin(ecalTheta)*sin(ecalPhi)
00361 + muonMETInfo.hcalE*sin(hcalTheta)*sin(hcalPhi)
00362 + muonMETInfo.hoE*sin(hoTheta)*sin(hoPhi);
00363
00364 deltax += mu_Ex;
00365 deltay += mu_Ey;
00366
00367 } else {
00368
00369
00370
00371
00372
00373
00374 double dEdx_normalization = -(11.4 + 0.96*fabs(log(50*2.8)) + 0.033*50*(1.0 - pow(50, -0.33)) )*1e-3;
00375 double dEdx_numerator = -(11.4 + 0.96*fabs(log(mu_p*2.8)) + 0.033*mu_p*(1.0 - pow(mu_p, -0.33)) )*1e-3;
00376
00377 double temp = 0.0;
00378
00379 if(muonMETInfo.useHO) {
00380
00381 if(fabs(mu_eta) < 0.2)
00382 temp = 2.75*(1-0.00003*mu_p);
00383 if(fabs(mu_eta) > 0.2 && fabs(mu_eta) < 1.0)
00384 temp = (2.38+0.0144*fabs(mu_eta))*(1-0.0003*mu_p);
00385 if(fabs(mu_eta) > 1.0 && fabs(mu_eta) < 1.3)
00386 temp = 7.413-5.12*fabs(mu_eta);
00387 if(fabs(mu_eta) > 1.3)
00388 temp = 2.084-0.743*fabs(mu_eta);
00389 } else {
00390 if(fabs(mu_eta) < 1.0)
00391 temp = 2.33*(1-0.0004*mu_p);
00392 if(fabs(mu_eta) > 1.0 && fabs(mu_eta) < 1.3)
00393 temp = (7.413-5.12*fabs(mu_eta))*(1-0.0003*mu_p);
00394 if(fabs(mu_eta) > 1.3)
00395 temp = 2.084-0.743*fabs(mu_eta);
00396 }
00397
00398 double dep = temp*dEdx_normalization/dEdx_numerator;
00399 if(dep < 0.5) dep = 0;
00400
00401 if(fabs(mu_eta) < 1.3) {
00402 deltax += dep*cos((ecalPhi+hcalPhi+hoPhi)/3);
00403 deltay += dep*sin((ecalPhi+hcalPhi+hoPhi)/3);
00404 } else {
00405 deltax += dep*cos( (ecalPhi+hcalPhi)/2);
00406 deltay += dep*cos( (ecalPhi+hcalPhi)/2);
00407 }
00408 }
00409
00410
00411 }
00412
00413 void MuonMETAlgo::run(const edm::View<reco::Muon>& inputMuons,
00414 const edm::ValueMap<reco::MuonMETCorrectionData>& vm_muCorrData,
00415 const edm::View<reco::MET>& uncorMET,
00416 METCollection *corMET) {
00417
00418 MuonMETAlgo_run(inputMuons, vm_muCorrData, uncorMET, corMET);
00419 }
00420
00421
00422 void MuonMETAlgo::run(const edm::View<reco::Muon>& inputMuons,
00423 const edm::ValueMap<reco::MuonMETCorrectionData>& vm_muCorrData,
00424 const edm::View<reco::CaloMET>& uncorMET,
00425 CaloMETCollection *corMET) {
00426
00427 MuonMETAlgo_run(inputMuons, vm_muCorrData, uncorMET, corMET);
00428
00429 }
00430
00431
00432
00433 MuonMETAlgo::MuonMETAlgo() {}
00434
00435
00436
00437 MuonMETAlgo::~MuonMETAlgo() {}
00438
00439
00440
00441