CMS 3D CMS Logo

DisappearingMuonsSkimming.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: MuMu/DisappearingMuonsSkimming
4 // Class: DisappearingMuonsSkimming
5 //
13 //
14 // Original Author: Michael Revering
15 // Created: Mon, 18 Jun 2018 21:22:23 GMT
16 //
17 //
18 // system include files
19 #include <memory>
20 #include "Math/VectorUtil.h"
21 
22 // user include files
35 
37  : recoMuonToken_(consumes<reco::MuonCollection>(iConfig.getParameter<edm::InputTag>("recoMuons"))),
38  standaloneMuonToken_(consumes<reco::TrackCollection>(iConfig.getParameter<edm::InputTag>("StandaloneTracks"))),
39  trackCollectionToken_(consumes<reco::TrackCollection>(iConfig.getParameter<edm::InputTag>("tracks"))),
40  primaryVerticesToken_(consumes<reco::VertexCollection>(iConfig.getParameter<edm::InputTag>("primaryVertices"))),
41  reducedEndcapRecHitCollectionToken_(
42  consumes<EcalRecHitCollection>(iConfig.getParameter<edm::InputTag>("EERecHits"))),
43  reducedBarrelRecHitCollectionToken_(
44  consumes<EcalRecHitCollection>(iConfig.getParameter<edm::InputTag>("EBRecHits"))),
45  trigResultsToken_(consumes<edm::TriggerResults>(iConfig.getParameter<edm::InputTag>("TriggerResultsTag"))),
46  transientTrackToken_(
47  esConsumes<TransientTrackBuilder, TransientTrackRecord>(edm::ESInputTag("", "TransientTrackBuilder"))),
49  muonPathsToPass_(iConfig.getParameter<std::vector<std::string>>("muonPathsToPass")),
50  minMuPt_(iConfig.getParameter<double>("minMuPt")),
51  maxMuEta_(iConfig.getParameter<double>("maxMuEta")),
52  minTrackEta_(iConfig.getParameter<double>("minTrackEta")),
53  maxTrackEta_(iConfig.getParameter<double>("maxTrackEta")),
54  minTrackPt_(iConfig.getParameter<double>("minTrackPt")),
55  maxTransDCA_(iConfig.getParameter<double>("maxTransDCA")),
56  maxLongDCA_(iConfig.getParameter<double>("maxLongDCA")),
57  maxVtxChi_(iConfig.getParameter<double>("maxVtxChi")),
58  minInvMass_(iConfig.getParameter<double>("minInvMass")),
59  maxInvMass_(iConfig.getParameter<double>("maxInvMass")),
60  trackIsoConesize_(iConfig.getParameter<double>("trackIsoConesize")),
61  trackIsoInnerCone_(iConfig.getParameter<double>("trackIsoInnerCone")),
62  ecalIsoConesize_(iConfig.getParameter<double>("ecalIsoConesize")),
63  minEcalHitE_(iConfig.getParameter<double>("minEcalHitE")),
64  maxTrackIso_(iConfig.getParameter<double>("maxTrackIso")),
65  maxEcalIso_(iConfig.getParameter<double>("maxEcalIso")),
66  minSigInvMass_(iConfig.getParameter<double>("minSigInvMass")),
67  maxSigInvMass_(iConfig.getParameter<double>("maxSigInvMass")),
68  minStandaloneDr_(iConfig.getParameter<double>("minStandaloneDr")),
69  maxStandaloneDE_(iConfig.getParameter<double>("maxStandaloneDE")),
70  keepOffPeak_(iConfig.getParameter<bool>("keepOffPeak")),
71  keepSameSign_(iConfig.getParameter<bool>("keepSameSign")),
72  keepTotalRegion_(iConfig.getParameter<bool>("keepTotalRegion")),
73  keepPartialRegion_(iConfig.getParameter<bool>("keepPartialRegion")) {}
74 
75 //
76 // member functions
77 //
78 
79 // ------------ method called for each event ------------
81  using namespace edm;
82  using namespace std;
83  using namespace reco;
84 
85  bool totalRegion = false;
86  bool sameSign = false;
87  bool offPeak = false;
88  bool partialRegion = false;
89 
90  const auto& staTracks = iEvent.get(standaloneMuonToken_);
91  const auto& vertices = iEvent.get(primaryVerticesToken_);
92  const auto& recoMuons = iEvent.get(recoMuonToken_);
93  const auto& thePATTracks = iEvent.get(trackCollectionToken_);
94  const auto& triggerResults = iEvent.get(trigResultsToken_);
95 
96  // this wraps tracks with additional methods that are used in vertex-calculation
97  const TransientTrackBuilder* transientTrackBuilder = &iSetup.getData(transientTrackToken_);
98 
100  return false;
101 
102  int nMuonTrackCand = 0;
103  float MuonTrackMass = 0.;
104 
105  //Looping over the reconstructed Muons
106  for (const auto& iMuon : recoMuons) {
107  if (!(iMuon.isPFMuon() && iMuon.isGlobalMuon()))
108  continue;
109  if (!(iMuon.passed(reco::Muon::CutBasedIdTight)))
110  continue;
111  if (!(iMuon.passed(reco::Muon::PFIsoTight)))
112  continue;
113  if (iMuon.pt() < minMuPt_ || std::abs(iMuon.eta()) > maxMuEta_)
114  continue;
115 
116  //Looping over tracks for any good muon
117  int indx(0);
118  for (const auto& iTrack : thePATTracks) {
119  reco::TrackRef trackRef = reco::TrackRef(&thePATTracks, indx);
120  indx++;
121 
122  if (!iTrack.quality(reco::Track::qualityByName("highPurity")))
123  continue;
124  if (std::abs(iTrack.eta()) > maxTrackEta_ || std::abs(iTrack.eta()) < minTrackEta_)
125  continue;
126  if (iTrack.pt() < minTrackPt_)
127  continue;
128  //Check if the track belongs to a primary vertex for isolation calculation
129 
130  unsigned int vtxIndex;
131  unsigned int tkIndex;
132  bool foundtrack = this->findTrackInVertices(trackRef, vertices, vtxIndex, tkIndex);
133 
134  if (!foundtrack)
135  continue;
136 
137  reco::VertexRef vtx(&vertices, vtxIndex);
138  GlobalPoint tkVtx = GlobalPoint(vtx->x(), vtx->y(), vtx->z());
139 
140  reco::TransientTrack tk = transientTrackBuilder->build(iTrack);
141  TrajectoryStateClosestToPoint traj = tk.trajectoryStateClosestToPoint(tkVtx);
142  double transDCA = traj.perigeeParameters().transverseImpactParameter();
143  double longDCA = traj.perigeeParameters().longitudinalImpactParameter();
144  if (std::abs(longDCA) > maxLongDCA_)
145  continue;
146  if (std::abs(transDCA) > maxTransDCA_)
147  continue;
148  // make a pair of TransientTracks to feed the vertexer
149  std::vector<reco::TransientTrack> tracksToVertex;
150  tracksToVertex.push_back(tk);
151  tracksToVertex.push_back(transientTrackBuilder->build(iMuon.globalTrack()));
152  // try to fit these two tracks to a common vertex
154  CachingVertex<5> fittedVertex = vertexFitter.vertex(tracksToVertex);
155  double vtxChi = 0;
156  // some poor fits will simply fail to find a common vertex
157  if (fittedVertex.isValid() && fittedVertex.totalChiSquared() >= 0. && fittedVertex.degreesOfFreedom() > 0) {
158  // others we can exclude by their poor fit
159  vtxChi = fittedVertex.totalChiSquared() / fittedVertex.degreesOfFreedom();
160 
161  if (vtxChi < maxVtxChi_) {
162  // important! evaluate momentum vectors AT THE VERTEX
164  tracksToVertex[0].trajectoryStateClosestToPoint(fittedVertex.position());
166  tracksToVertex[1].trajectoryStateClosestToPoint(fittedVertex.position());
167  GlobalVector one_momentum = one_TSCP.momentum();
168  GlobalVector two_momentum = two_TSCP.momentum();
169 
170  double total_energy = sqrt(one_momentum.mag2() + 0.106 * 0.106) + sqrt(two_momentum.mag2() + 0.106 * 0.106);
171  double total_px = one_momentum.x() + two_momentum.x();
172  double total_py = one_momentum.y() + two_momentum.y();
173  double total_pz = one_momentum.z() + two_momentum.z();
174  MuonTrackMass = sqrt(pow(total_energy, 2) - pow(total_px, 2) - pow(total_py, 2) - pow(total_pz, 2));
175  } else {
176  continue;
177  }
178  } else {
179  continue;
180  }
181  if (MuonTrackMass < minInvMass_ || MuonTrackMass > maxInvMass_)
182  continue;
183 
184  double trackIso = getTrackIsolation(trackRef, vertices);
185  //Track iso returns -1 when it fails to find the vertex containing the track (already checked in track selection, but might as well make sure)
186  if (trackIso < 0)
187  continue;
188  double ecalIso = getECALIsolation(iEvent, iSetup, transientTrackBuilder->build(iTrack));
189  if (trackIso > maxTrackIso_ || ecalIso > maxEcalIso_)
190  continue;
191 
192  //A good tag/probe pair has been selected, now check for control or signal regions
193  if (iMuon.charge() == iTrack.charge()) {
194  sameSign = true;
195  }
196 
197  //If not same sign CR, need to check standalone muons for signal regions
198  double staMinDr2 = 1000;
199  double staMinDEoverE = -10;
200  if (!staTracks.empty()) {
201  for (const auto& staTrack : staTracks) {
202  reco::TransientTrack track = transientTrackBuilder->build(staTrack);
203  double dR2 = deltaR2(track.impactPointTSCP().momentum().eta(),
204  track.impactPointTSCP().momentum().phi(),
205  iTrack.eta(),
206  iTrack.phi());
207  double staDE = (std::sqrt(track.impactPointTSCP().momentum().mag2()) - iTrack.p()) / iTrack.p();
208  if (dR2 < staMinDr2) {
209  staMinDr2 = dR2;
210  }
211  //Pick the largest standalone muon within the cone
212  if (dR2 < minStandaloneDr_ * minStandaloneDr_ && staDE > staMinDEoverE) {
213  staMinDEoverE = staDE;
214  }
215  }
216  }
217  if (staMinDr2 > minStandaloneDr_ * minStandaloneDr_) {
218  if (MuonTrackMass < minSigInvMass_ || MuonTrackMass > maxSigInvMass_) {
219  offPeak = true;
220  } else {
221  totalRegion = true;
222  }
223  } else {
224  if (staMinDEoverE < maxStandaloneDE_) {
225  if (MuonTrackMass < minSigInvMass_ || MuonTrackMass > maxSigInvMass_) {
226  offPeak = true;
227  } else {
228  partialRegion = true;
229  }
230  }
231  }
232  nMuonTrackCand++;
233  }
234  }
235 
236  if (nMuonTrackCand == 0)
237  return false;
238  bool passes = false;
239  //Pass all same sign CR events
240  if (sameSign && keepSameSign_) {
241  passes = true;
242  }
243  //Pass all total disappearance events
244  else if (totalRegion && keepTotalRegion_) {
245  passes = true;
246  }
247  //Pass all partial disappearkance off-peak events
248  else if (offPeak && keepOffPeak_) {
249  passes = true;
250  }
251  //Pass partial region events that pass minimum standalone muon DE/E.
252  else if (partialRegion && keepPartialRegion_) {
253  passes = true;
254  }
255  return passes;
256 }
257 
260  const std::vector<std::string>& m_muonPathsToPass) {
261  bool passTriggers = false;
262  const edm::TriggerNames& trigNames = iEvent.triggerNames(triggerResults);
263  for (size_t i = 0; i < trigNames.size(); ++i) {
264  const std::string& name = trigNames.triggerName(i);
265  for (auto& pathName : m_muonPathsToPass) {
266  if ((name.find(pathName) != std::string::npos)) {
267  if (triggerResults.accept(i)) {
268  passTriggers = true;
269  break;
270  }
271  }
272  }
273  }
274  return passTriggers;
275 }
276 
279  unsigned int& vtxIndex,
280  unsigned int& trackIndex) {
281  // initialize indices
282  vtxIndex = -1;
283  trackIndex = -1;
284 
285  bool foundtrack{false};
286  unsigned int idx = 0;
287  for (const auto& vtx : vertices) {
288  if (!vtx.isValid()) {
289  idx++;
290  continue;
291  }
292 
293  const auto& thePVtracks{vtx.tracks()};
294  std::vector<unsigned int> thePVkeys;
295  thePVkeys.reserve(thePVtracks.size());
296  for (const auto& tv : thePVtracks) {
297  thePVkeys.push_back(tv.key());
298  }
299 
300  auto result = std::find_if(
301  thePVkeys.begin(), thePVkeys.end(), [tkToMatch](const auto& tkRef) { return tkRef == tkToMatch.key(); });
302  if (result != thePVkeys.end()) {
303  foundtrack = true;
304  trackIndex = std::distance(thePVkeys.begin(), result);
305  vtxIndex = idx;
306  }
307  if (foundtrack)
308  break;
309 
310  idx++;
311  }
312  return foundtrack;
313 }
314 
317  unsigned int vtxindex;
318  unsigned int trackIndex;
319  bool foundtrack = this->findTrackInVertices(tkToMatch, vertices, vtxindex, trackIndex);
320 
321  LogDebug("DisappearingMuonsSkimming") << "getTrackIsolation vtx Index: " << vtxindex
322  << " track Index: " << trackIndex;
323 
324  if (!foundtrack) {
325  return -1.;
326  }
327 
328  reco::VertexRef primaryVtx(&vertices, vtxindex);
329 
330  double Isolation = 0;
331  for (unsigned int i = 0; i < primaryVtx->tracksSize(); i++) {
332  if (i == trackIndex)
333  continue;
334  reco::TrackBaseRef secondarytrack = primaryVtx->trackRefAt(i);
335  if (deltaR2(tkToMatch.get()->eta(), tkToMatch.get()->phi(), secondarytrack->eta(), secondarytrack->phi()) >
337  deltaR2(tkToMatch.get()->eta(), tkToMatch.get()->phi(), secondarytrack->eta(), secondarytrack->phi()) <
339  continue;
340  Isolation += secondarytrack->pt();
341  }
342 
343  return Isolation / tkToMatch.get()->pt();
344 }
345 
347  const edm::EventSetup& iSetup,
348  const reco::TransientTrack& track) {
350  iEvent.getByToken(reducedEndcapRecHitCollectionToken_, rechitsEE);
351 
353  iEvent.getByToken(reducedBarrelRecHitCollectionToken_, rechitsEB);
354 
355  const CaloGeometry& caloGeom = iSetup.getData(geometryToken_);
356  TrajectoryStateClosestToPoint t0 = track.impactPointTSCP();
357  double eDR = 0;
358 
359  for (EcalRecHitCollection::const_iterator hit = rechitsEE->begin(); hit != rechitsEE->end(); hit++) {
360  const DetId id = (*hit).detid();
361  const GlobalPoint hitPos = caloGeom.getSubdetectorGeometry(id)->getGeometry(id)->getPosition();
362  //Check if hit and track trajectory ar in the same endcap (transient track projects both ways)
363  if ((hitPos.eta() * t0.momentum().eta()) < 0) {
364  continue;
365  }
366  TrajectoryStateClosestToPoint traj = track.trajectoryStateClosestToPoint(hitPos);
367  math::XYZVector idPositionRoot(hitPos.x(), hitPos.y(), hitPos.z());
368  math::XYZVector trajRoot(traj.position().x(), traj.position().y(), traj.position().z());
369  if (deltaR2(idPositionRoot, trajRoot) < ecalIsoConesize_ * ecalIsoConesize_ && (*hit).energy() > minEcalHitE_) {
370  eDR += (*hit).energy();
371  }
372  }
373  for (EcalRecHitCollection::const_iterator hit = rechitsEB->begin(); hit != rechitsEB->end(); hit++) {
374  const DetId id = (*hit).detid();
375  const GlobalPoint hitPos = caloGeom.getSubdetectorGeometry(id)->getGeometry(id)->getPosition();
376  if ((hitPos.eta() * t0.momentum().eta()) < 0) {
377  continue;
378  }
379  TrajectoryStateClosestToPoint traj = track.trajectoryStateClosestToPoint(hitPos);
380  math::XYZVector idPositionRoot(hitPos.x(), hitPos.y(), hitPos.z());
381  math::XYZVector trajRoot(traj.position().x(), traj.position().y(), traj.position().z());
382  if (deltaR2(idPositionRoot, trajRoot) < ecalIsoConesize_ * ecalIsoConesize_ && (*hit).energy() > minEcalHitE_) {
383  eDR += (*hit).energy();
384  }
385  }
386 
387  return eDR;
388 }
389 
392 
393  desc.add<edm::InputTag>("recoMuons", edm::InputTag("muons"));
394  desc.add<edm::InputTag>("tracks", edm::InputTag("generalTracks"));
395  desc.add<edm::InputTag>("StandaloneTracks", edm::InputTag("standAloneMuons"));
396  desc.add<edm::InputTag>("primaryVertices", edm::InputTag("offlinePrimaryVertices"));
397  desc.add<edm::InputTag>("EERecHits", edm::InputTag("reducedEcalRecHitsEE"));
398  desc.add<edm::InputTag>("EBRecHits", edm::InputTag("reducedEcalRecHitsEB"));
399  desc.add<edm::InputTag>("TriggerResultsTag", edm::InputTag("TriggerResults", "", "HLT"));
400  desc.add<std::vector<std::string>>("muonPathsToPass",
401  {
402  "HLT_IsoMu24_v",
403  "HLT_IsoMu27_v",
404  });
405  desc.add<double>("minMuPt", 26);
406  desc.add<double>("maxMuEta", 2.4);
407  desc.add<double>("minTrackEta", 0);
408  desc.add<double>("maxTrackEta", 2.4);
409  desc.add<double>("minTrackPt", 20);
410  desc.add<double>("maxTransDCA", 0.005);
411  desc.add<double>("maxLongDCA", 0.05);
412  desc.add<double>("maxVtxChi", 3.0);
413  desc.add<double>("minInvMass", 50);
414  desc.add<double>("maxInvMass", 150);
415  desc.add<double>("trackIsoConesize", 0.3);
416  desc.add<double>("trackIsoInnerCone", 0.01);
417  desc.add<double>("ecalIsoConesize", 0.4);
418  desc.add<double>("minEcalHitE", 0.3);
419  desc.add<double>("maxTrackIso", 0.05);
420  desc.add<double>("maxEcalIso", 10);
421  desc.add<double>("minSigInvMass", 76);
422  desc.add<double>("maxSigInvMass", 106);
423  desc.add<double>("minStandaloneDr", 1.0);
424  desc.add<double>("maxStandaloneDE", -0.5);
425  desc.add<bool>("keepOffPeak", true);
426  desc.add<bool>("keepSameSign", true);
427  desc.add<bool>("keepTotalRegion", true);
428  desc.add<bool>("keepPartialRegion", true);
429  descriptions.addWithDefaultLabel(desc);
430 }
431 
432 //define this as a plug-in
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
const std::vector< std::string > muonPathsToPass_
T z() const
Definition: PV3DBase.h:61
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const edm::EDGetTokenT< edm::TriggerResults > trigResultsToken_
T eta() const
Definition: PV3DBase.h:73
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
std::vector< Track > TrackCollection
collection of Tracks
Definition: TrackFwd.h:14
std::vector< EcalRecHit >::const_iterator const_iterator
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
constexpr int pow(int x)
Definition: conifer.h:24
T mag2() const
Definition: PV3DBase.h:63
const edm::EDGetTokenT< reco::VertexCollection > primaryVerticesToken_
std::vector< Vertex > VertexCollection
Definition: Vertex.h:31
key_type key() const
Accessor for product key.
Definition: Ref.h:250
std::vector< Muon > MuonCollection
collection of Muon objects
Definition: MuonFwd.h:9
float totalChiSquared() const
reco::TransientTrack build(const reco::Track *p) const
double pt() const
track transverse momentum
Definition: TrackBase.h:637
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
int iEvent
Definition: GenABIO.cc:224
const edm::ESGetToken< TransientTrackBuilder, TransientTrackRecord > transientTrackToken_
T sqrt(T t)
Definition: SSEVec.h:19
const edm::EDGetTokenT< EcalRecHitCollection > reducedEndcapRecHitCollectionToken_
bool passTriggers(const edm::Event &iEvent, const edm::TriggerResults &results, const std::vector< std::string > &m_muonPathsToPass)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double phi() const
azimuthal angle of momentum vector
Definition: TrackBase.h:649
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
const edm::EDGetTokenT< reco::MuonCollection > recoMuonToken_
double getECALIsolation(const edm::Event &, const edm::EventSetup &, const reco::TransientTrack &track)
const_iterator begin() const
static std::string const triggerResults
Definition: EdmProvDump.cc:47
double getTrackIsolation(const reco::TrackRef &tkToMatch, const reco::VertexCollection &vertices)
bool findTrackInVertices(const reco::TrackRef &tkToMatch, const reco::VertexCollection &vertices, unsigned int &vtxIndex, unsigned int &trackIndex)
const PerigeeTrajectoryParameters & perigeeParameters() const
bool filter(edm::Event &, const edm::EventSetup &) override
virtual std::shared_ptr< const CaloCellGeometry > getGeometry(const DetId &id) const
Get the cell geometry of a given detector id. Should return false if not found.
const_iterator end() const
static const char *const trigNames[]
Definition: EcalDumpRaw.cc:57
double eta() const
pseudorapidity of momentum vector
Definition: TrackBase.h:652
Definition: DetId.h:17
static TrackQuality qualityByName(const std::string &name)
Definition: TrackBase.cc:126
bool isValid() const
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
edm::Ref< TrackCollection > TrackRef
persistent reference to a Track
Definition: TrackFwd.h:20
const edm::ESGetToken< CaloGeometry, CaloGeometryRecord > geometryToken_
const edm::EDGetTokenT< reco::TrackCollection > standaloneMuonToken_
fixed size matrix
HLT enums.
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:232
float degreesOfFreedom() const
const edm::EDGetTokenT< EcalRecHitCollection > reducedBarrelRecHitCollectionToken_
const edm::EDGetTokenT< reco::TrackCollection > trackCollectionToken_
GlobalPoint position() const
DisappearingMuonsSkimming(const edm::ParameterSet &)
const CaloSubdetectorGeometry * getSubdetectorGeometry(const DetId &id) const
access the subdetector geometry for the given subdetector directly
Definition: CaloGeometry.cc:34
#define LogDebug(id)