CMS 3D CMS Logo

MuonMETAlgo.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: METAlgorithms
4 // Class: MuonMETAlgo
5 //
6 // Original Authors: Michael Schmitt, Richard Cavanaugh The University of Florida
7 // Created: August 30, 2007
8 //
9 
10 //____________________________________________________________________________||
11 #include <cmath>
12 #include <vector>
18 
19 #include "TMath.h"
20 
21 using namespace std;
22 using namespace reco;
23 
26 
27 //____________________________________________________________________________||
29  double fSumEt,
30  const std::vector<CorrMETData>& fCorrections,
31  const MET::LorentzVector& fP4) {
32  return CaloMET(fMet.getSpecific(), fSumEt, fCorrections, fP4, fMet.vertex());
33 }
34 
35 //____________________________________________________________________________||
36 MET MuonMETAlgo::makeMET(const MET& fMet,
37  double fSumEt,
38  const std::vector<CorrMETData>& fCorrections,
39  const MET::LorentzVector& fP4) {
40  return MET(fSumEt, fCorrections, fP4, fMet.vertex());
41 }
42 
43 //____________________________________________________________________________||
44 template <class T>
46  const edm::ValueMap<reco::MuonMETCorrectionData>& vm_muCorrData,
47  const edm::View<T>& v_uncorMET,
48  std::vector<T>* v_corMET) {
49  const T& uncorMETObj = v_uncorMET.front();
50 
51  double corMETX = uncorMETObj.px();
52  double corMETY = uncorMETObj.py();
53 
54  double sumMuPx = 0.;
55  double sumMuPy = 0.;
56  double sumMuPt = 0.;
57  double sumMuDepEx = 0.;
58  double sumMuDepEy = 0.;
59  double sumMuDepEt = 0.;
60 
61  for (unsigned int i = 0; i < inputMuons.size(); ++i) {
62  reco::MuonMETCorrectionData muCorrData = vm_muCorrData[inputMuons.refAt(i)];
63 
64  if (muCorrData.type() == 0)
65  continue;
66 
67  float deltax = muCorrData.corrX();
68  float deltay = muCorrData.corrY();
69 
70  const reco::Muon* mu = &inputMuons[i];
71  const LorentzVector& mup4 = mu->p4();
72 
73  sumMuPx += mup4.px();
74  sumMuPy += mup4.py();
75  sumMuPt += mup4.pt();
76  sumMuDepEx += deltax;
77  sumMuDepEy += deltay;
78  sumMuDepEt += sqrt(deltax * deltax + deltay * deltay);
79  corMETX = corMETX - mup4.px() + deltax;
80  corMETY = corMETY - mup4.py() + deltay;
81  }
82 
84  delta.mex = sumMuDepEx - sumMuPx;
85  delta.mey = sumMuDepEy - sumMuPy;
86  delta.sumet = sumMuPt - sumMuDepEt;
87  MET::LorentzVector correctedMET4vector(corMETX, corMETY, 0., sqrt(corMETX * corMETX + corMETY * corMETY));
88  std::vector<CorrMETData> corrections = uncorMETObj.mEtCorr();
89  corrections.push_back(delta);
90 
91  T result = makeMET(uncorMETObj, uncorMETObj.sumEt() + delta.sumet, corrections, correctedMET4vector);
92  v_corMET->push_back(result);
93 }
94 
95 //____________________________________________________________________________||
99  bool useRecHits,
100  bool useHO,
101  double towerEtThreshold,
102  double& deltax,
103  double& deltay,
104  double Bfield) {
105  bool useAverage = false;
106  //decide whether or not we want to correct on average based
107  //on isolation information from the muon
108  double sumPt = inputMuon->isIsolationValid() ? inputMuon->isolationR03().sumPt : 0.0;
109  double sumEtEcal = inputMuon->isIsolationValid() ? inputMuon->isolationR03().emEt : 0.0;
110  double sumEtHcal = inputMuon->isIsolationValid() ? inputMuon->isolationR03().hadEt : 0.0;
111 
112  if (sumPt > 3 || sumEtEcal + sumEtHcal > 5)
113  useAverage = true;
114 
115  //get the energy using TrackAssociator if
116  //the muon turns out to be isolated
117  MuonMETInfo muMETInfo;
118  muMETInfo.useAverage = useAverage;
120  muMETInfo.useHO = useHO;
121 
122  TrackRef mu_track;
123  if (inputMuon->isGlobalMuon()) {
124  mu_track = inputMuon->globalTrack();
125  } else if (inputMuon->isTrackerMuon() || inputMuon->isRPCMuon() || inputMuon->isGEMMuon() || inputMuon->isME0Muon()) {
126  mu_track = inputMuon->innerTrack();
127  } else
128  mu_track = inputMuon->outerTrack();
129 
131  muMETInfo.ecalPos = info.trkGlobPosAtEcal;
132  muMETInfo.hcalPos = info.trkGlobPosAtHcal;
133  muMETInfo.hoPos = info.trkGlobPosAtHO;
134  }
135 
136  if (!useAverage) {
137  if (useRecHits) {
138  muMETInfo.ecalE = inputMuon->calEnergy().emS9;
139  muMETInfo.hcalE = inputMuon->calEnergy().hadS9;
140  if (useHO) //muMETInfo.hoE is 0 by default
141  muMETInfo.hoE = inputMuon->calEnergy().hoS9;
142  } else { // use Towers (this is the default)
143  //only include towers whose Et > 0.5 since
144  //by default the MET only includes towers with Et > 0.5
145  std::vector<const CaloTower*> towers = info.crossedTowers;
146  for (vector<const CaloTower*>::const_iterator it = towers.begin(); it != towers.end(); it++) {
147  if ((*it)->et() < towerEtThreshold)
148  continue;
149  muMETInfo.ecalE += (*it)->emEnergy();
150  muMETInfo.hcalE += (*it)->hadEnergy();
151  if (useHO)
152  muMETInfo.hoE += (*it)->outerEnergy();
153  }
154  } //use Towers
155  }
156 
157  //This needs to be fixed!!!!!
158  //The tracker has better resolution for pt < 200 GeV
160  if (inputMuon->isGlobalMuon()) {
161  if (inputMuon->globalTrack()->pt() < 200) {
162  mup4 = LorentzVector(inputMuon->innerTrack()->px(),
163  inputMuon->innerTrack()->py(),
164  inputMuon->innerTrack()->pz(),
165  inputMuon->innerTrack()->p());
166  } else {
167  mup4 = LorentzVector(inputMuon->globalTrack()->px(),
168  inputMuon->globalTrack()->py(),
169  inputMuon->globalTrack()->pz(),
170  inputMuon->globalTrack()->p());
171  }
172  } else if (inputMuon->isTrackerMuon() || inputMuon->isRPCMuon() || inputMuon->isGEMMuon() || inputMuon->isME0Muon()) {
173  mup4 = LorentzVector(inputMuon->innerTrack()->px(),
174  inputMuon->innerTrack()->py(),
175  inputMuon->innerTrack()->pz(),
176  inputMuon->innerTrack()->p());
177  } else
178  mup4 = LorentzVector(inputMuon->outerTrack()->px(),
179  inputMuon->outerTrack()->py(),
180  inputMuon->outerTrack()->pz(),
181  inputMuon->outerTrack()->p());
182 
183  //call function that does the work
184  correctMETforMuon(deltax, deltay, Bfield, inputMuon->charge(), mup4, inputMuon->vertex(), muMETInfo);
185 }
186 
187 //____________________________________________________________________________||
188 void MuonMETAlgo::correctMETforMuon(double& deltax,
189  double& deltay,
190  double bfield,
191  int muonCharge,
192  const math::XYZTLorentzVector& muonP4,
193  const math::XYZPoint& muonVertex,
194  MuonMETInfo& muonMETInfo) {
195  double mu_p = muonP4.P();
196  double mu_pt = muonP4.Pt();
197  double mu_phi = muonP4.Phi();
198  double mu_eta = muonP4.Eta();
199  double mu_vz = muonVertex.z() / 100.;
200  double mu_pz = muonP4.Pz();
201 
202  double ecalPhi, ecalTheta;
203  double hcalPhi, hcalTheta;
204  double hoPhi, hoTheta;
205 
206  //should always be false for FWLite
207  //unless you want to supply co-ordinates at
208  //the calorimeter sub-detectors yourself
209  if (muonMETInfo.useTkAssociatorPositions) {
210  ecalPhi = muonMETInfo.ecalPos.Phi();
211  ecalTheta = muonMETInfo.ecalPos.Theta();
212  hcalPhi = muonMETInfo.hcalPos.Phi();
213  hcalTheta = muonMETInfo.hcalPos.Theta();
214  hoPhi = muonMETInfo.hoPos.Phi();
215  hoTheta = muonMETInfo.hoPos.Theta();
216  } else {
217  /*
218  use the analytical solution for the
219  intersection of a helix with a cylinder
220  to find the positions of the muon
221  at the various calo surfaces
222  */
223 
224  //radii of subdetectors in meters
225  double rEcal = 1.290;
226  double rHcal = 1.9;
227  double rHo = 3.82;
228  if (abs(mu_eta) > 0.3)
229  rHo = 4.07;
230  //distance from the center of detector to face of Ecal
231  double zFaceEcal = 3.209;
232  if (mu_eta < 0)
233  zFaceEcal = -1 * zFaceEcal;
234  //distance from the center of detector to face of Hcal
235  double zFaceHcal = 3.88;
236  if (mu_eta < 0)
237  zFaceHcal = -1 * zFaceHcal;
238 
239  //now we have to get Phi
240  //bending radius of the muon (units are meters)
241  double bendr = mu_pt * 1000 / (300 * bfield);
242 
243  double tb_ecal = TMath::ACos(1 - rEcal * rEcal / (2 * bendr * bendr)); //helix time interval parameter
244  double tb_hcal = TMath::ACos(1 - rHcal * rHcal / (2 * bendr * bendr)); //helix time interval parameter
245  double tb_ho = TMath::ACos(1 - rHo * rHo / (2 * bendr * bendr)); //helix time interval parameter
246  double xEcal, yEcal, zEcal;
247  double xHcal, yHcal, zHcal;
248  double xHo, yHo, zHo;
249  //Ecal
250  //in the barrel and if not a looper
251  if (fabs(mu_pz * bendr * tb_ecal / mu_pt + mu_vz) < fabs(zFaceEcal) && rEcal < 2 * bendr) {
252  xEcal = bendr * (TMath::Sin(tb_ecal + mu_phi) - TMath::Sin(mu_phi));
253  yEcal = bendr * (-TMath::Cos(tb_ecal + mu_phi) + TMath::Cos(mu_phi));
254  zEcal = bendr * tb_ecal * mu_pz / mu_pt + mu_vz;
255  } else { //endcap
256  if (mu_pz > 0) {
257  double te_ecal = (fabs(zFaceEcal) - mu_vz) * mu_pt / (bendr * mu_pz);
258  xEcal = bendr * (TMath::Sin(te_ecal + mu_phi) - TMath::Sin(mu_phi));
259  yEcal = bendr * (-TMath::Cos(te_ecal + mu_phi) + TMath::Cos(mu_phi));
260  zEcal = fabs(zFaceEcal);
261  } else {
262  double te_ecal = -(fabs(zFaceEcal) + mu_vz) * mu_pt / (bendr * mu_pz);
263  xEcal = bendr * (TMath::Sin(te_ecal + mu_phi) - TMath::Sin(mu_phi));
264  yEcal = bendr * (-TMath::Cos(te_ecal + mu_phi) + TMath::Cos(mu_phi));
265  zEcal = -fabs(zFaceEcal);
266  }
267  }
268 
269  //Hcal
270  if (fabs(mu_pz * bendr * tb_hcal / mu_pt + mu_vz) < fabs(zFaceHcal) && rEcal < 2 * bendr) { //in the barrel
271  xHcal = bendr * (TMath::Sin(tb_hcal + mu_phi) - TMath::Sin(mu_phi));
272  yHcal = bendr * (-TMath::Cos(tb_hcal + mu_phi) + TMath::Cos(mu_phi));
273  zHcal = bendr * tb_hcal * mu_pz / mu_pt + mu_vz;
274  } else { //endcap
275  if (mu_pz > 0) {
276  double te_hcal = (fabs(zFaceHcal) - mu_vz) * mu_pt / (bendr * mu_pz);
277  xHcal = bendr * (TMath::Sin(te_hcal + mu_phi) - TMath::Sin(mu_phi));
278  yHcal = bendr * (-TMath::Cos(te_hcal + mu_phi) + TMath::Cos(mu_phi));
279  zHcal = fabs(zFaceHcal);
280  } else {
281  double te_hcal = -(fabs(zFaceHcal) + mu_vz) * mu_pt / (bendr * mu_pz);
282  xHcal = bendr * (TMath::Sin(te_hcal + mu_phi) - TMath::Sin(mu_phi));
283  yHcal = bendr * (-TMath::Cos(te_hcal + mu_phi) + TMath::Cos(mu_phi));
284  zHcal = -fabs(zFaceHcal);
285  }
286  }
287 
288  //Ho - just the barrel
289  xHo = bendr * (TMath::Sin(tb_ho + mu_phi) - TMath::Sin(mu_phi));
290  yHo = bendr * (-TMath::Cos(tb_ho + mu_phi) + TMath::Cos(mu_phi));
291  zHo = bendr * tb_ho * mu_pz / mu_pt + mu_vz;
292 
293  ecalTheta = TMath::ACos(zEcal / sqrt(pow(xEcal, 2) + pow(yEcal, 2) + pow(zEcal, 2)));
294  ecalPhi = atan2(yEcal, xEcal);
295  hcalTheta = TMath::ACos(zHcal / sqrt(pow(xHcal, 2) + pow(yHcal, 2) + pow(zHcal, 2)));
296  hcalPhi = atan2(yHcal, xHcal);
297  hoTheta = TMath::ACos(zHo / sqrt(pow(xHo, 2) + pow(yHo, 2) + pow(zHo, 2)));
298  hoPhi = atan2(yHo, xHo);
299 
300  /*
301  the above prescription is for right handed helicies only
302  Positively charged muons trace a left handed helix
303  so we correct for that
304  */
305  if (muonCharge > 0) {
306  //Ecal
307  double dphi = mu_phi - ecalPhi;
308  if (fabs(dphi) > TMath::Pi())
309  dphi = 2 * TMath::Pi() - fabs(dphi);
310  ecalPhi = mu_phi - fabs(dphi);
311  if (fabs(ecalPhi) > TMath::Pi()) {
312  double temp = 2 * TMath::Pi() - fabs(ecalPhi);
313  ecalPhi = -1 * temp * ecalPhi / fabs(ecalPhi);
314  }
315 
316  //Hcal
317  dphi = mu_phi - hcalPhi;
318  if (fabs(dphi) > TMath::Pi())
319  dphi = 2 * TMath::Pi() - fabs(dphi);
320  hcalPhi = mu_phi - fabs(dphi);
321  if (fabs(hcalPhi) > TMath::Pi()) {
322  double temp = 2 * TMath::Pi() - fabs(hcalPhi);
323  hcalPhi = -1 * temp * hcalPhi / fabs(hcalPhi);
324  }
325 
326  //Ho
327  dphi = mu_phi - hoPhi;
328  if (fabs(dphi) > TMath::Pi())
329  dphi = 2 * TMath::Pi() - fabs(dphi);
330  hoPhi = mu_phi - fabs(dphi);
331  if (fabs(hoPhi) > TMath::Pi()) {
332  double temp = 2 * TMath::Pi() - fabs(hoPhi);
333  hoPhi = -1 * temp * hoPhi / fabs(hoPhi);
334  }
335  }
336  }
337 
338  //for isolated muons
339  if (!muonMETInfo.useAverage) {
340  double mu_Ex = muonMETInfo.ecalE * sin(ecalTheta) * cos(ecalPhi) +
341  muonMETInfo.hcalE * sin(hcalTheta) * cos(hcalPhi) + muonMETInfo.hoE * sin(hoTheta) * cos(hoPhi);
342  double mu_Ey = muonMETInfo.ecalE * sin(ecalTheta) * sin(ecalPhi) +
343  muonMETInfo.hcalE * sin(hcalTheta) * sin(hcalPhi) + muonMETInfo.hoE * sin(hoTheta) * sin(hoPhi);
344 
345  deltax += mu_Ex;
346  deltay += mu_Ey;
347 
348  } else { //non-isolated muons - derive the correction
349 
350  //dE/dx in matter for iron:
351  //-(11.4 + 0.96*fabs(log(p0*2.8)) + 0.033*p0*(1.0 - pow(p0, -0.33)) )*1e-3
352  //from http://cmslxr.fnal.gov/lxr/source/TrackPropagation/SteppingHelixPropagator/src/SteppingHelixPropagator.ccyes,
353  //line ~1100
354  //normalisation is at 50 GeV
355  double dEdx_normalization = -(11.4 + 0.96 * fabs(log(50 * 2.8)) + 0.033 * 50 * (1.0 - pow(50, -0.33))) * 1e-3;
356  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;
357 
358  double temp = 0.0;
359 
360  if (muonMETInfo.useHO) {
361  //for the Towers, with HO
362  if (fabs(mu_eta) < 0.2)
363  temp = 2.75 * (1 - 0.00003 * mu_p);
364  if (fabs(mu_eta) > 0.2 && fabs(mu_eta) < 1.0)
365  temp = (2.38 + 0.0144 * fabs(mu_eta)) * (1 - 0.0003 * mu_p);
366  if (fabs(mu_eta) > 1.0 && fabs(mu_eta) < 1.3)
367  temp = 7.413 - 5.12 * fabs(mu_eta);
368  if (fabs(mu_eta) > 1.3)
369  temp = 2.084 - 0.743 * fabs(mu_eta);
370  } else {
371  if (fabs(mu_eta) < 1.0)
372  temp = 2.33 * (1 - 0.0004 * mu_p);
373  if (fabs(mu_eta) > 1.0 && fabs(mu_eta) < 1.3)
374  temp = (7.413 - 5.12 * fabs(mu_eta)) * (1 - 0.0003 * mu_p);
375  if (fabs(mu_eta) > 1.3)
376  temp = 2.084 - 0.743 * fabs(mu_eta);
377  }
378 
379  double dep = temp * dEdx_normalization / dEdx_numerator;
380  if (dep < 0.5)
381  dep = 0;
382  //use the average phi of the 3 subdetectors
383  if (fabs(mu_eta) < 1.3) {
384  deltax += dep * cos((ecalPhi + hcalPhi + hoPhi) / 3);
385  deltay += dep * sin((ecalPhi + hcalPhi + hoPhi) / 3);
386  } else {
387  deltax += dep * cos((ecalPhi + hcalPhi) / 2);
388  deltay += dep * cos((ecalPhi + hcalPhi) / 2);
389  }
390  }
391 }
392 
393 //____________________________________________________________________________||
395  const edm::ValueMap<reco::MuonMETCorrectionData>& vm_muCorrData,
396  const edm::View<reco::MET>& uncorMET,
397  METCollection* corMET) {
398  MuonMETAlgo_run(inputMuons, vm_muCorrData, uncorMET, corMET);
399 }
400 
401 //____________________________________________________________________________||
403  const edm::ValueMap<reco::MuonMETCorrectionData>& vm_muCorrData,
404  const edm::View<reco::CaloMET>& uncorMET,
405  CaloMETCollection* corMET) {
406  MuonMETAlgo_run(inputMuons, vm_muCorrData, uncorMET, corMET);
407 }
408 
409 //____________________________________________________________________________||
const double Pi
float hadEt
hcal sum-Et
Definition: MuonIsolation.h:8
const MuonIsolation & isolationR03() const
Definition: Muon.h:166
static const TGPicture * info(bool iBackgroundIsBlack)
math::XYZPoint hcalPos
Definition: MuonMETInfo.h:11
float sumPt
sum-pt of tracks
Definition: MuonIsolation.h:6
virtual TrackRef globalTrack() const
reference to Track reconstructed in both tracked and muon detector
Definition: Muon.h:51
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
float emS9
energy deposited in 3x3 ECAL crystal shape around central crystal
Definition: MuonEnergy.h:28
constexpr int pow(int x)
Definition: conifer.h:24
const Point & vertex() const override
vertex position (overwritten by PF...)
float hcalE
Definition: MuonMETInfo.h:8
virtual TrackRef outerTrack() const
reference to Track reconstructed in the muon detector only
Definition: Muon.h:48
SpecificCaloMETData getSpecific() const
Definition: CaloMET.h:77
bool isTrackerMuon() const override
Definition: Muon.h:304
Collection of Calo MET.
void MuonMETAlgo_run(const edm::View< reco::Muon > &inputMuons, const edm::ValueMap< reco::MuonMETCorrectionData > &vm_muCorrData, const edm::View< T > &v_uncorMET, std::vector< T > *v_corMET)
Definition: MuonMETAlgo.cc:45
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
void GetMuDepDeltas(const reco::Muon *inputMuon, TrackDetMatchInfo &info, bool useTrackAssociatorPositions, bool useRecHits, bool useHO, double towerEtThreshold, double &deltax, double &deltay, double Bfield)
Definition: MuonMETAlgo.cc:96
bool isME0Muon() const
Definition: Muon.h:310
Definition: MET.h:41
T sqrt(T t)
Definition: SSEVec.h:19
float emEt
ecal sum-Et
Definition: MuonIsolation.h:7
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
constexpr float Bfield
Definition: Config.h:53
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
math::XYZTLorentzVector LorentzVector
float hoS9
energy deposited in 3x3 HO tower shape around central tower
Definition: MuonEnergy.h:44
MuonEnergy calEnergy() const
get energy deposition information
Definition: Muon.h:106
virtual TrackRef innerTrack() const
Definition: Muon.h:45
Collection of MET.
math::XYZPoint hoPos
Definition: MuonMETInfo.h:12
bool isRPCMuon() const
Definition: Muon.h:308
bool useTkAssociatorPositions
Definition: MuonMETInfo.h:15
float ecalE
Definition: MuonMETInfo.h:7
bool isGEMMuon() const
Definition: Muon.h:309
bool isIsolationValid() const
Definition: Muon.h:177
bool useAverage
Definition: MuonMETInfo.h:13
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
a MET correction term
Definition: CorrMETData.h:14
math::XYZTLorentzVector LorentzVector
Definition: MuonMETAlgo.cc:24
fixed size matrix
static void correctMETforMuon(double &deltax, double &deltay, double bfield, int muonCharge, const math::XYZTLorentzVector &muonP4, const math::XYZPoint &muonVertex, MuonMETInfo &)
Definition: MuonMETAlgo.cc:188
math::XYZPoint ecalPos
Definition: MuonMETInfo.h:10
math::XYZPoint Point
Definition: MuonMETAlgo.cc:25
virtual void run(const edm::View< reco::Muon > &inputMuons, const edm::ValueMap< reco::MuonMETCorrectionData > &vm_muCorrData, const edm::View< reco::MET > &uncorMET, reco::METCollection *corMET)
long double T
reco::CaloMET makeMET(const reco::CaloMET &fMet, double fSumEt, const std::vector< CorrMETData > &fCorrections, const reco::MET::LorentzVector &)
bool isGlobalMuon() const override
Definition: Muon.h:303
float hadS9
energy deposited in 3x3 HCAL tower shape around central tower
Definition: MuonEnergy.h:38
int charge() const final
electric charge
double ecalPhi(const MagneticField &magField, const math::XYZVector &momentum, const math::XYZPoint &vertex, const int charge)
float hoE
Definition: MuonMETInfo.h:9