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"))),
48  geometryToken_(esConsumes<CaloGeometry, CaloGeometryRecord>(edm::ESInputTag{})),
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  std::vector<unsigned int> thePVkeys;
294  thePVkeys.reserve(vtx.tracksSize());
295  for (unsigned int i = 0; i < vtx.tracksSize(); i++) {
296  thePVkeys.push_back(vtx.trackRefAt(i).key());
297  }
298 
299  auto result = std::find_if(
300  thePVkeys.begin(), thePVkeys.end(), [tkToMatch](const auto& tkRef) { return tkRef == tkToMatch.key(); });
301  if (result != thePVkeys.end()) {
302  foundtrack = true;
303  trackIndex = std::distance(thePVkeys.begin(), result);
304  vtxIndex = idx;
305  }
306  if (foundtrack)
307  break;
308  idx++;
309  }
310  return foundtrack;
311 }
312 
315  unsigned int vtxindex;
316  unsigned int trackIndex;
317  bool foundtrack = this->findTrackInVertices(tkToMatch, vertices, vtxindex, trackIndex);
318 
319  LogDebug("DisappearingMuonsSkimming") << "getTrackIsolation vtx Index: " << vtxindex
320  << " track Index: " << trackIndex;
321 
322  if (!foundtrack) {
323  return -1.;
324  }
325 
326  reco::VertexRef primaryVtx(&vertices, vtxindex);
327 
328  double Isolation = 0;
329  for (unsigned int i = 0; i < primaryVtx->tracksSize(); i++) {
330  if (i == trackIndex)
331  continue;
332  reco::TrackBaseRef secondarytrack = primaryVtx->trackRefAt(i);
333  if (deltaR2(tkToMatch.get()->eta(), tkToMatch.get()->phi(), secondarytrack->eta(), secondarytrack->phi()) >
335  deltaR2(tkToMatch.get()->eta(), tkToMatch.get()->phi(), secondarytrack->eta(), secondarytrack->phi()) <
337  continue;
338  Isolation += secondarytrack->pt();
339  }
340 
341  return Isolation / tkToMatch.get()->pt();
342 }
343 
345  const edm::EventSetup& iSetup,
346  const reco::TransientTrack& track) {
349 
352 
353  const CaloGeometry& caloGeom = iSetup.getData(geometryToken_);
355  double eDR = 0;
356 
357  for (EcalRecHitCollection::const_iterator hit = rechitsEE->begin(); hit != rechitsEE->end(); hit++) {
358  const DetId id = (*hit).detid();
359  const GlobalPoint hitPos = caloGeom.getSubdetectorGeometry(id)->getGeometry(id)->getPosition();
360  //Check if hit and track trajectory ar in the same endcap (transient track projects both ways)
361  if ((hitPos.eta() * t0.momentum().eta()) < 0) {
362  continue;
363  }
365  math::XYZVector idPositionRoot(hitPos.x(), hitPos.y(), hitPos.z());
366  math::XYZVector trajRoot(traj.position().x(), traj.position().y(), traj.position().z());
367  if (deltaR2(idPositionRoot, trajRoot) < ecalIsoConesize_ * ecalIsoConesize_ && (*hit).energy() > minEcalHitE_) {
368  eDR += (*hit).energy();
369  }
370  }
371  for (EcalRecHitCollection::const_iterator hit = rechitsEB->begin(); hit != rechitsEB->end(); hit++) {
372  const DetId id = (*hit).detid();
373  const GlobalPoint hitPos = caloGeom.getSubdetectorGeometry(id)->getGeometry(id)->getPosition();
374  if ((hitPos.eta() * t0.momentum().eta()) < 0) {
375  continue;
376  }
378  math::XYZVector idPositionRoot(hitPos.x(), hitPos.y(), hitPos.z());
379  math::XYZVector trajRoot(traj.position().x(), traj.position().y(), traj.position().z());
380  if (deltaR2(idPositionRoot, trajRoot) < ecalIsoConesize_ * ecalIsoConesize_ && (*hit).energy() > minEcalHitE_) {
381  eDR += (*hit).energy();
382  }
383  }
384 
385  return eDR;
386 }
387 
390 
391  desc.add<edm::InputTag>("recoMuons", edm::InputTag("muons"));
392  desc.add<edm::InputTag>("tracks", edm::InputTag("generalTracks"));
393  desc.add<edm::InputTag>("StandaloneTracks", edm::InputTag("standAloneMuons"));
394  desc.add<edm::InputTag>("primaryVertices", edm::InputTag("offlinePrimaryVertices"));
395  desc.add<edm::InputTag>("EERecHits", edm::InputTag("reducedEcalRecHitsEE"));
396  desc.add<edm::InputTag>("EBRecHits", edm::InputTag("reducedEcalRecHitsEB"));
397  desc.add<edm::InputTag>("TriggerResultsTag", edm::InputTag("TriggerResults", "", "HLT"));
398  desc.add<std::vector<std::string>>("muonPathsToPass",
399  {
400  "HLT_IsoMu24_v",
401  "HLT_IsoMu27_v",
402  });
403  desc.add<double>("minMuPt", 26);
404  desc.add<double>("maxMuEta", 2.4);
405  desc.add<double>("minTrackEta", 1.4);
406  desc.add<double>("maxTrackEta", 2.4);
407  desc.add<double>("minTrackPt", 20);
408  desc.add<double>("maxTransDCA", 0.005);
409  desc.add<double>("maxLongDCA", 0.05);
410  desc.add<double>("maxVtxChi", 3.0);
411  desc.add<double>("minInvMass", 50);
412  desc.add<double>("maxInvMass", 150);
413  desc.add<double>("trackIsoConesize", 0.3);
414  desc.add<double>("trackIsoInnerCone", 0.01);
415  desc.add<double>("ecalIsoConesize", 0.4);
416  desc.add<double>("minEcalHitE", 0.3);
417  desc.add<double>("maxTrackIso", 0.05);
418  desc.add<double>("maxEcalIso", 10);
419  desc.add<double>("minSigInvMass", 76);
420  desc.add<double>("maxSigInvMass", 106);
421  desc.add<double>("minStandaloneDr", 1.0);
422  desc.add<double>("maxStandaloneDE", -0.5);
423  desc.add<bool>("keepOffPeak", true);
424  desc.add<bool>("keepSameSign", true);
425  desc.add<bool>("keepTotalRegion", true);
426  desc.add<bool>("keepPartialRegion", true);
427  descriptions.addWithDefaultLabel(desc);
428 }
429 
430 //define this as a plug-in
#define LogDebug(id)
const CaloSubdetectorGeometry * getSubdetectorGeometry(const DetId &id) const
access the subdetector geometry for the given subdetector directly
Definition: CaloGeometry.cc:49
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
T mag2() const
Definition: PV3DBase.h:66
const std::vector< std::string > muonPathsToPass_
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
TrajectoryStateClosestToPoint impactPointTSCP() const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const edm::EDGetTokenT< edm::TriggerResults > trigResultsToken_
bool accept() const
Has at least one path accepted the event?
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
std::vector< Track > TrackCollection
collection of Tracks
Definition: TrackFwd.h:15
std::vector< EcalRecHit >::const_iterator const_iterator
reco::TransientTrack build(const reco::Track *p) const
T y() const
Definition: PV3DBase.h:63
double phi() const
azimuthal angle of momentum vector
Definition: TrackBase.h:684
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
Strings::size_type size() const
Definition: TriggerNames.cc:31
key_type key() const
Accessor for product key.
Definition: Ref.h:263
const edm::EDGetTokenT< reco::VertexCollection > primaryVerticesToken_
std::vector< Muon > MuonCollection
collection of Muon objects
Definition: MuonFwd.h:9
bool getData(T &iHolder) const
Definition: EventSetup.h:111
int iEvent
Definition: GenABIO.cc:224
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
double eta() const
pseudorapidity of momentum vector
Definition: TrackBase.h:690
const PerigeeTrajectoryParameters & perigeeParameters() const
const edm::ESGetToken< TransientTrackBuilder, TransientTrackRecord > transientTrackToken_
T sqrt(T t)
Definition: SSEVec.h:18
double pt() const
track transverse momentum
Definition: TrackBase.h:660
const edm::EDGetTokenT< EcalRecHitCollection > reducedEndcapRecHitCollectionToken_
T z() const
Definition: PV3DBase.h:64
bool passTriggers(const edm::Event &iEvent, const edm::TriggerResults &results, const std::vector< std::string > &m_muonPathsToPass)
float totalChiSquared() const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
CachingVertex< 5 > vertex(const std::vector< reco::TransientTrack > &tracks) const override
bool get(ProductID const &oid, Handle< PROD > &result) const
Definition: Event.h:326
const edm::EDGetTokenT< reco::MuonCollection > recoMuonToken_
double getECALIsolation(const edm::Event &, const edm::EventSetup &, const reco::TransientTrack &track)
float degreesOfFreedom() const
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:243
static std::string const triggerResults
Definition: EdmProvDump.cc:45
ParameterDescriptionBase * add(U const &iLabel, T const &value)
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)
bool filter(edm::Event &, const edm::EventSetup &) override
const_iterator end() const
static const char *const trigNames[]
Definition: EcalDumpRaw.cc:74
Definition: DetId.h:18
constexpr auto deltaR2(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:16
static TrackQuality qualityByName(const std::string &name)
Definition: TrackBase.cc:134
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.
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:30
std::string const & triggerName(unsigned int index) const
Definition: TriggerNames.cc:22
TrajectoryStateClosestToPoint trajectoryStateClosestToPoint(const GlobalPoint &point) const
edm::Ref< TrackCollection > TrackRef
persistent reference to a Track
Definition: TrackFwd.h:21
const edm::ESGetToken< CaloGeometry, CaloGeometryRecord > geometryToken_
GlobalPoint position() const
const edm::EDGetTokenT< reco::TrackCollection > standaloneMuonToken_
T eta() const
Definition: PV3DBase.h:76
fixed size matrix
HLT enums.
bool isValid() const
const edm::EDGetTokenT< EcalRecHitCollection > reducedBarrelRecHitCollectionToken_
const edm::EDGetTokenT< reco::TrackCollection > trackCollectionToken_
T x() const
Definition: PV3DBase.h:62
DisappearingMuonsSkimming(const edm::ParameterSet &)
edm::TriggerNames const & triggerNames(edm::TriggerResults const &triggerResults) const override
Definition: Event.cc:256
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
const_iterator begin() const