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