CMS 3D CMS Logo

HLTMuonDimuonL3Filter.cc
Go to the documentation of this file.
1 
14 #include "HLTMuonDimuonL3Filter.h"
23 
24 using namespace edm;
25 using namespace std;
26 using namespace reco;
27 using namespace trigger;
28 
29 //
30 // constructors and destructor
31 //
32 namespace {
33  struct Out {
34  Out(std::vector<double> const& v): v_(v) {}
35 
36  std::vector<double> const& v_;
37  };
38 
39 #if defined(EDM_ML_DEBUG)
40  std::ostream& operator<<(std::ostream& iS, Out const& iO) {
41  iS<<"[";
42  for( double v: iO.v_) {
43  iS<<v<<" ";
44  }
45  iS<<"]";
46  return iS;
47  }
48 #endif
49 }
50 
52  beamspotTag_ (iConfig.getParameter< edm::InputTag > ("BeamSpotTag")),
53  beamspotToken_ (consumes<reco::BeamSpot>(beamspotTag_)),
54  candTag_ (iConfig.getParameter< edm::InputTag > ("CandTag")),
55  candToken_ (consumes<reco::RecoChargedCandidateCollection>(candTag_)),
56  previousCandTag_ (iConfig.getParameter<InputTag > ("PreviousCandTag")),
57  previousCandToken_ (consumes<trigger::TriggerFilterObjectWithRefs>(previousCandTag_)),
58  l1CandTag_ (iConfig.getParameter<InputTag > ("L1CandTag")),
59  l1CandToken_ (consumes<trigger::TriggerFilterObjectWithRefs>(l1CandTag_)),
60  recoMuTag_ (iConfig.getParameter<InputTag > ("inputMuonCollection")),
61  recoMuToken_ (consumes<reco::MuonCollection>(recoMuTag_)),
62  previousCandIsL2_(iConfig.getParameter<bool> ("PreviousCandIsL2")),
63  fast_Accept_ (iConfig.getParameter<bool> ("FastAccept")),
64  min_N_ (iConfig.getParameter<int> ("MinN")),
65  max_Eta_ (iConfig.getParameter<double> ("MaxEta")),
66  min_Nhits_ (iConfig.getParameter<int> ("MinNhits")),
67  max_Dr_ (iConfig.getParameter<double> ("MaxDr")),
68  max_Dz_ (iConfig.getParameter<double> ("MaxDz")),
69  chargeOpt_ (iConfig.getParameter<int> ("ChargeOpt")),
70  min_PtPair_ (iConfig.getParameter< vector<double> > ("MinPtPair")),
71  max_PtPair_ (iConfig.getParameter< vector<double> > ("MaxPtPair")),
72  min_PtMax_ (iConfig.getParameter< vector<double> > ("MinPtMax")),
73  min_PtMin_ (iConfig.getParameter< vector<double> > ("MinPtMin")),
74  max_PtMin_ (iConfig.getParameter< vector<double> > ("MaxPtMin")),
75  min_InvMass_ (iConfig.getParameter< vector<double> > ("MinInvMass")),
76  max_InvMass_ (iConfig.getParameter< vector<double> > ("MaxInvMass")),
77  min_Acop_ (iConfig.getParameter<double> ("MinAcop")),
78  max_Acop_ (iConfig.getParameter<double> ("MaxAcop")),
79  min_PtBalance_ (iConfig.getParameter<double> ("MinPtBalance")),
80  max_PtBalance_ (iConfig.getParameter<double> ("MaxPtBalance")),
81  nsigma_Pt_ (iConfig.getParameter<double> ("NSigmaPt")),
82  max_DCAMuMu_ (iConfig.getParameter<double>("MaxDCAMuMu")),
83  max_YPair_ (iConfig.getParameter<double>("MaxRapidityPair")),
84  cutCowboys_(iConfig.getParameter<bool>("CutCowboys")),
85  theL3LinksLabel (iConfig.getParameter<InputTag>("InputLinks")),
86  linkToken_ (consumes<reco::MuonTrackLinksCollection>(theL3LinksLabel)),
87  L1MatchingdR_ (iConfig.getParameter<double> ("L1MatchingdR")),
88  matchPreviousCand_ (iConfig.getParameter<bool>("MatchToPreviousCand") ),
89  MuMass2_(0.106*0.106)
90 {
91 
92  LogDebug("HLTMuonDimuonL3Filter")
93  << " CandTag/MinN/MaxEta/MinNhits/MaxDr/MaxDz/MinPt1/MinPt2/MinInvMass/MaxInvMass/MinAcop/MaxAcop/MinPtBalance/MaxPtBalance/NSigmaPt/MaxDzMuMu/MaxRapidityPair : "
94  << candTag_.encode()
95  << " " << fast_Accept_
96  << " " << min_N_
97  << " " << max_Eta_
98  << " " << min_Nhits_
99  << " " << max_Dr_
100  << " " << max_Dz_
101  << " " << chargeOpt_ << " " << Out(min_PtPair_)
102  << " " << Out(min_PtMax_) << " " << Out(min_PtMin_)
103  << " " << Out(min_InvMass_) << " " << Out(max_InvMass_)
104  << " " << min_Acop_ << " " << max_Acop_
105  << " " << min_PtBalance_ << " " << max_PtBalance_
106  << " " << nsigma_Pt_
107  << " " << max_DCAMuMu_
108  << " " << max_YPair_;
109 }
110 
112 
113 void
117  desc.add<edm::InputTag>("BeamSpotTag",edm::InputTag("hltOfflineBeamSpot"));
118  desc.add<edm::InputTag>("CandTag",edm::InputTag("hltL3MuonCandidates"));
119  // desc.add<edm::InputTag>("PreviousCandTag",edm::InputTag("hltDiMuonL2PreFiltered0"));
120  desc.add<edm::InputTag>("PreviousCandTag",edm::InputTag(""));
121  desc.add<edm::InputTag>("L1CandTag",edm::InputTag(""));
122  desc.add<edm::InputTag>("inputMuonCollection",edm::InputTag(""));
123  desc.add<bool>("PreviousCandIsL2",true);
124  desc.add<bool>("FastAccept",false);
125  desc.add<int>("MinN",1);
126  desc.add<double>("MaxEta",2.5);
127  desc.add<int>("MinNhits",0);
128  desc.add<double>("MaxDr",2.0);
129  desc.add<double>("MaxDz",9999.0);
130  desc.add<int>("ChargeOpt",0);
131  vector<double> v1; v1.push_back(0.0);
132  vector<double> v2; v2.push_back(1e125);
133  vector<double> v3; v3.push_back(3.0);
134  vector<double> v4; v4.push_back(3.0);
135  vector<double> v5; v5.push_back(1e125);
136  vector<double> v6; v6.push_back(2.8);
137  vector<double> v7; v7.push_back(3.4);
138  desc.add<vector<double> >("MinPtPair",v1);
139  desc.add<vector<double> >("MaxPtPair",v2);
140  desc.add<vector<double> >("MinPtMax",v3);
141  desc.add<vector<double> >("MinPtMin",v4);
142  desc.add<vector<double> >("MaxPtMin",v5);
143  desc.add<vector<double> >("MinInvMass",v6);
144  desc.add<vector<double> >("MaxInvMass",v7);
145  desc.add<double>("MinAcop",-1.0);
146  desc.add<double>("MaxAcop",3.15);
147  desc.add<double>("MinPtBalance",-1.0);
148  desc.add<double>("MaxPtBalance",999999.0);
149  desc.add<double>("NSigmaPt",0.0);
150  desc.add<double>("MaxDCAMuMu",99999.9);
151  desc.add<double>("MaxRapidityPair",999999.0);
152  desc.add<bool>("CutCowboys",false);
153  desc.add<edm::InputTag>("InputLinks",edm::InputTag(""));
154  desc.add<double>("L1MatchingdR",0.3);
155  desc.add<bool>("MatchToPreviousCand", true);
156  descriptions.add("hltMuonDimuonL3Filter",desc);
157 }
158 
159 //
160 // member functions
161 //
162 
163 // ------------ method called to produce the data ------------
164 bool
166 {
167 
168  if (min_InvMass_.size() != min_PtPair_.size()) {cout << "ERROR!!! Vector sizes don't match!" << endl; return false;}
169  if (min_InvMass_.size() != max_PtPair_.size()) {cout << "ERROR!!! Vector sizes don't match!" << endl; return false;}
170  if (min_InvMass_.size() != min_PtMax_.size()) {cout << "ERROR!!! Vector sizes don't match!" << endl; return false;}
171  if (min_InvMass_.size() != min_PtMin_.size()) {cout << "ERROR!!! Vector sizes don't match!" << endl; return false;}
172  if (min_InvMass_.size() != max_PtMin_.size()) {cout << "ERROR!!! Vector sizes don't match!" << endl; return false;}
173  if (min_InvMass_.size() != max_InvMass_.size()) {cout << "ERROR!!! Vector sizes don't match!" << endl; return false;}
174 
175  // All HLT filters must create and fill an HLT filter object,
176  // recording any reconstructed physics objects satisfying (or not)
177  // this HLT filter, and place it in the Event.
178 
179  // Read RecoChargedCandidates from L3MuonCandidateProducer:
181  if (saveTags()) filterproduct.addCollectionTag(candTag_); //?
182  iEvent.getByToken(candToken_,mucands);
183 
184  // Read L2 triggered objects:
185  Handle<TriggerFilterObjectWithRefs> previousLevelCands;
186  iEvent.getByToken(previousCandToken_,previousLevelCands);
187  vector<RecoChargedCandidateRef> vl2cands;
188  previousLevelCands->getObjects(TriggerMuon,vl2cands);
189 
190  // Read BeamSpot information:
191  Handle<BeamSpot> recoBeamSpotHandle;
192  iEvent.getByToken(beamspotToken_,recoBeamSpotHandle);
193  const BeamSpot& beamSpot = *recoBeamSpotHandle;
194 
195  // sort them by L2Track
196  std::map<reco::TrackRef, std::vector<RecoChargedCandidateRef> > L2toL3s;
197  // map the L3 cands matched to a L1 to their position in the recoMuon collection
198  std::map<unsigned int, RecoChargedCandidateRef > MuonToL3s;
199 
200  // Test to see if we can use L3MuonTrajectorySeeds:
201  if (mucands->empty()) return false;
202  auto const &tk = (*mucands)[0].track();
203  bool useL3MTS=false;
204 
205  if (tk->seedRef().isNonnull()){
206  auto a = dynamic_cast<const L3MuonTrajectorySeed*>(tk->seedRef().get());
207  useL3MTS = a != nullptr;
208  }
209 
210  // If we can use L3MuonTrajectory seeds run the older code:
211  if (useL3MTS){
212  unsigned int maxI = mucands->size();
213  for (unsigned int i=0;i!=maxI;i++){
214  const TrackRef &tk = (*mucands)[i].track();
215  if (previousCandIsL2_) {
217  TrackRef staTrack = l3seedRef->l2Track();
218  L2toL3s[staTrack].push_back(RecoChargedCandidateRef(mucands,i));
219  } else {
220  L2toL3s[tk].push_back(RecoChargedCandidateRef(mucands,i));
221  }
222  }
223  }
224  // Using normal TrajectorySeeds:
225  else{
226  // Read Links collection:
228  iEvent.getByToken(linkToken_, links);
229 
231  std::vector<l1t::MuonRef> vl1cands;
232 
233  bool check_l1match = true;
234 
235  // Loop over RecoChargedCandidates:
236  for(unsigned int i(0); i < mucands->size(); ++i){
237  RecoChargedCandidateRef cand(mucands,i);
238  TrackRef tk = cand->track(); // is inner track
239 
240  if (!matchPreviousCand_){
241  MuonToL3s[i] = RecoChargedCandidateRef(cand);
242  }
243  else{
244 
245  check_l1match = true;
246  for(auto const & link : *links){
247 
248  // Using the same method that was used to create the links between L3 and L2
249  // ToDo: there should be a better way than dR,dPt matching
250  const reco::Track& trackerTrack = *link.trackerTrack();
251  if (tk->pt()==0 or trackerTrack.pt()==0) continue;
252 
253  float dR2 = deltaR2(tk->eta(),tk->phi(),trackerTrack.eta(),trackerTrack.phi());
254  float dPt = std::abs(tk->pt() - trackerTrack.pt())/tk->pt();
255 
256  if (dR2 < 0.02*0.02 and dPt < 0.001) {
257  const TrackRef staTrack = link.standAloneTrack();
258  L2toL3s[staTrack].push_back(RecoChargedCandidateRef(cand));
259  check_l1match = false;
260  }
261  } //MTL loop
262 
263  if (not l1CandTag_.label().empty() and check_l1match){
264  iEvent.getByToken(l1CandToken_,level1Cands);
265  level1Cands->getObjects(trigger::TriggerL1Mu,vl1cands);
266  const unsigned int nL1Muons(vl1cands.size());
267  for (unsigned int il1=0; il1!=nL1Muons; ++il1) {
268  if (deltaR(cand->eta(), cand->phi(), vl1cands[il1]->eta(), vl1cands[il1]->phi()) < L1MatchingdR_) { //was muon, non cand
269  MuonToL3s[i] = RecoChargedCandidateRef(cand);
270  }
271  }
272  }
273  }
274  } //RCC loop
275  } //end of using normal TrajectorySeeds
276 
277  // Needed for DCA calculation
278  ESHandle<MagneticField> bFieldHandle;
279  iSetup.get<IdealMagneticFieldRecord>().get(bFieldHandle);
280 
281  // look at all mucands, check cuts and add to filter object
282  int n = 0;
283 
284  // look at all mucands, check cuts and add to filter object
285  auto L2toL3s_it1 = L2toL3s.begin();
286  auto L2toL3s_end = L2toL3s.end();
287  bool atLeastOnePair=false;
288  for (; L2toL3s_it1!=L2toL3s_end; ++L2toL3s_it1){
289 
290  if (!triggeredByLevel2(L2toL3s_it1->first,vl2cands)) continue;
291 
292  //loop over the L3Tk reconstructed for this L2.
293  unsigned int iTk1=0;
294  unsigned int maxItk1=L2toL3s_it1->second.size();
295  for (; iTk1!=maxItk1; iTk1++){
296  bool thisL3Index1isDone=false;
297  RecoChargedCandidateRef & cand1=L2toL3s_it1->second[iTk1];
298  TrackRef tk1 = cand1->get<TrackRef>();
299 
300  LogDebug("HLTMuonDimuonL3Filter") << " 1st muon in loop: q*pt= " << tk1->charge()*tk1->pt()
301  << " (" << cand1->charge()*cand1->pt()<< ") " << ", eta= " << tk1->eta()
302  << " (" << cand1->eta() << ") " << ", hits= " << tk1->numberOfValidHits();
303 
304  // Run muon selection on first muon:
305  if (!applyMuonSelection(cand1, beamSpot)) continue;
306 
307  // Pt threshold cut
308  // Don't convert to 90% efficiency threshold
309  LogDebug("HLTMuonDimuonL3Filter") << " ... 1st muon in loop, pt1= " << cand1->pt();
310 
311  // Loop on 2nd muon cand
312  auto L2toL3s_it2 = L2toL3s_it1;
313  L2toL3s_it2++;
314  for (; L2toL3s_it2!=L2toL3s_end; ++L2toL3s_it2){
315  if (!triggeredByLevel2(L2toL3s_it2->first,vl2cands)) continue;
316 
317  //loop over the L3Tk reconstructed for this L2.
318  unsigned int iTk2=0;
319  unsigned int maxItk2=L2toL3s_it2->second.size();
320  for (; iTk2!=maxItk2; iTk2++){
321  RecoChargedCandidateRef & cand2=L2toL3s_it2->second[iTk2];
322  TrackRef tk2 = cand2->get<TrackRef>();
323 
324  LogDebug("HLTMuonDimuonL3Filter") << " 2nd muon in loop: q*pt= " << tk2->charge()*tk2->pt()
325  << " (" << cand2->charge()*cand2->pt() << ") " << ", eta= " << tk2->eta()
326  << " (" << cand2->eta() << ") " << ", hits= " << tk2->numberOfValidHits() << ", d0= " << tk2->d0() ;
327 
328  // Run muon selection on second muon:
329  if (!applyMuonSelection(cand2, beamSpot)) continue;
330 
331  // Pt threshold cut
332  // Don't convert to 90% efficiency threshold
333  LogDebug("HLTMuonDimuonL3Filter") << " ... 2nd muon in loop, pt2= " << cand2->pt();
334 
335  // Run dimuon selection:
336  if (!applyDiMuonSelection(cand1, cand2, beamSpot, bFieldHandle)) continue;
337 
338  // Add this pair
339  n++;
340  LogDebug("HLTMuonDimuonL3Filter") << " Track1 passing filter: pt= " << cand1->pt() << ", eta: " << cand1->eta();
341  LogDebug("HLTMuonDimuonL3Filter") << " Track2 passing filter: pt= " << cand2->pt() << ", eta: " << cand2->eta();
342 
343  bool i1done = false;
344  bool i2done = false;
345  vector<RecoChargedCandidateRef> vref;
346  filterproduct.getObjects(TriggerMuon,vref);
347  for (auto & i : vref) {
349  TrackRef tktmp = candref->get<TrackRef>();
350  if (tktmp==tk1) i1done = true;
351  else if (tktmp==tk2) i2done = true; //why is this an elif?
352  if (i1done && i2done) break;
353  }
354  if (!i1done) filterproduct.addObject(TriggerMuon,cand1);
355  if (!i2done) filterproduct.addObject(TriggerMuon,cand2);
356 
357  //break anyway since a L3 track pair has been found matching the criteria
358  thisL3Index1isDone=true;
359  atLeastOnePair=true;
360  break;
361  }//loop on the track of the second L2
362  //break the loop if fast accept.
363  if (atLeastOnePair && fast_Accept_) break;
364  }//loop on the second L2
365  //break the loop if fast accept.
366  if (atLeastOnePair && fast_Accept_) break;
367  if (thisL3Index1isDone) break;
368 
369  //Loop over L3FromL1 collection see if we get a pair that way
370  auto MuonToL3s_it1 = MuonToL3s.begin();
371  auto MuonToL3s_end = MuonToL3s.end();
372  for (; MuonToL3s_it1!=MuonToL3s_end; ++MuonToL3s_it1){
373  const RecoChargedCandidateRef& cand2=MuonToL3s_it1->second;
374  if (!applyMuonSelection(cand2, beamSpot)) continue;
375  TrackRef tk2 = cand2->get<TrackRef>();
376 
377  // Run dimuon selection:
378  if (!applyDiMuonSelection(cand1, cand2, beamSpot, bFieldHandle)) continue;
379  n++;
380  LogDebug("HLTMuonDimuonL3Filter") << " L3FromL2 Track1 passing filter: pt= " << cand1->pt() << ", eta: " << cand1->eta();
381  LogDebug("HLTMuonDimuonL3Filter") << " L3FromL1 Track2 passing filter: pt= " << cand2->pt() << ", eta: " << cand2->eta();
382 
383  bool i1done = false;
384  bool i2done = false;
385  vector<RecoChargedCandidateRef> vref;
386  filterproduct.getObjects(TriggerMuon,vref);
387  for (auto & i : vref) {
389  TrackRef tktmp = candref->get<TrackRef>();
390  if (tktmp==tk1) i1done = true;
391  else if (tktmp==tk2) i2done = true; //why is this an elif?
392  if (i1done && i2done) break;
393  }
394  if (!i1done) filterproduct.addObject(TriggerMuon,cand1);
395  if (!i2done) filterproduct.addObject(TriggerMuon,cand2);
396 
397  //break anyway since a L3 track pair has been found matching the criteria
398  thisL3Index1isDone=true;
399  atLeastOnePair=true;
400  break;
401  }//L3FromL1 loop
402  //break the loop if fast accept.
403  if (atLeastOnePair && fast_Accept_) break;
404  if (thisL3Index1isDone) break;
405 
406  }//loop on tracks for first L2
407  //break the loop if fast accept.
408  if (atLeastOnePair && fast_Accept_) break;
409  }//loop on the first L2
410 
411 
412  // now loop on 1st L3 from L1
413  auto MuonToL3s_it1 = MuonToL3s.begin();
414  auto MuonToL3s_end = MuonToL3s.end();
415  for (; MuonToL3s_it1!=MuonToL3s_end; ++MuonToL3s_it1){
416  bool thisL3Index1isDone=false;
417  const RecoChargedCandidateRef& cand1=MuonToL3s_it1->second;
418  if (!applyMuonSelection(cand1, beamSpot)) continue;
419  TrackRef tk1 = cand1->get<TrackRef>();
420 
421  // Loop on 2nd L3 from L1
422  auto MuonToL3s_it2 = MuonToL3s_it1;
423  for (; MuonToL3s_it2!=MuonToL3s_end; ++MuonToL3s_it2){
424  const RecoChargedCandidateRef& cand2=MuonToL3s_it2->second;
425  if (!applyMuonSelection(cand2, beamSpot)) continue;
426  TrackRef tk2 = cand2->get<TrackRef>();
427 
428  // Run dimuon selection:
429  if (!applyDiMuonSelection(cand1, cand2, beamSpot, bFieldHandle)) continue;
430 
431  n++;
432  LogDebug("HLTMuonDimuonL3Filter") << " L3FromL1 Track1 passing filter: pt= " << cand1->pt() << ", eta: " << cand1->eta();
433  LogDebug("HLTMuonDimuonL3Filter") << " L3FromL1 Track2 passing filter: pt= " << cand2->pt() << ", eta: " << cand2->eta();
434 
435  bool i1done = false;
436  bool i2done = false;
437  vector<RecoChargedCandidateRef> vref;
438  filterproduct.getObjects(TriggerMuon,vref);
439  for (auto & i : vref) {
441  TrackRef tktmp = candref->get<TrackRef>();
442  if (tktmp==tk1) i1done = true;
443  else if (tktmp==tk2) i2done = true; //why is this an elif?
444  if (i1done && i2done) break;
445  }
446  if (!i1done) filterproduct.addObject(TriggerMuon,cand1);
447  if (!i2done) filterproduct.addObject(TriggerMuon,cand2);
448 
449  //break anyway since a L3 track pair has been found matching the criteria
450  thisL3Index1isDone=true;
451  atLeastOnePair=true;
452  break;
453  } //loop on 2nd muon
454 
455  //break the loop if fast accept
456  if (atLeastOnePair && fast_Accept_) break;
457  if (thisL3Index1isDone) break;
458  } //loop on 1st muon
459 
460 
461  // filter decision
462  const bool accept (n >= min_N_);
463 
464  LogDebug("HLTMuonDimuonL3Filter") << " >>>>> Result of HLTMuonDimuonL3Filter is "<< accept << ", number of muon pairs passing thresholds= " << n;
465 
466  return accept;
467 }
468 
469 
470 bool HLTMuonDimuonL3Filter::triggeredByLevel2(TrackRef const & staTrack,vector<RecoChargedCandidateRef> const & vcands){
471  bool ok=false;
472  for (auto const & vcand : vcands) {
473  if ( vcand->get<TrackRef>() == staTrack ) {
474  ok=true;
475  LogDebug("HLTMuonL3PreFilter") << "The L2 track triggered";
476  break;
477  }
478  }
479  return ok;
480 }
481 
483  // eta cut
484  if (std::abs(cand->eta())>max_Eta_) return false;
485 
486  // cut on number of hits
487  TrackRef tk = cand->track();
488  if (tk->numberOfValidHits()<min_Nhits_) return false;
489 
490  //dr cut
491  if (std::abs( (- (cand->vx()-beamSpot.x0()) * cand->py() + (cand->vy()-beamSpot.y0()) * cand->px() ) / cand->pt() ) >max_Dr_) return false;
492 
493  //dz cut
494  if (std::abs((cand->vz()-beamSpot.z0()) - ((cand->vx()-beamSpot.x0())*cand->px()+(cand->vy()-beamSpot.y0())*cand->py())/cand->pt() * cand->pz()/cand->pt())>max_Dz_) return false;
495 
496  return true;
497 }
498 
499 
501  // Opposite Charge
502  if (chargeOpt_<0 and (cand1->charge()*cand2->charge()>0)) return false;
503  else if (chargeOpt_>0 and (cand1->charge()*cand2->charge()<0)) return false;
504 
505  // Acoplanarity
506  double acop = std::abs(cand1->phi()-cand2->phi());
507  if (acop>M_PI) acop = 2*M_PI - acop;
508  acop = M_PI - acop;
509  LogDebug("HLTMuonDimuonL3Filter") << " ... 1-2 acop= " << acop;
510  if (acop<min_Acop_) return false;
511  if (acop>max_Acop_) return false;
512 
513  // Pt balance
514  double ptbalance = std::abs(cand1->pt()-cand2->pt());
515  if (ptbalance<min_PtBalance_) return false;
516  if (ptbalance>max_PtBalance_) return false;
517 
518  // Combined dimuon syste
519  double e1,e2;
521  e1 = sqrt(cand1->momentum().Mag2()+MuMass2_);
522  e2 = sqrt(cand2->momentum().Mag2()+MuMass2_);
523  p1 = Particle::LorentzVector(cand1->px(),cand1->py(),cand1->pz(),e1);
524  p2 = Particle::LorentzVector(cand2->px(),cand2->py(),cand2->pz(),e2);
525  p = p1+p2;
526 
527  double pt12 = p.pt();
528  LogDebug("HLTMuonDimuonL3Filter") << " ... 1-2 pt12= " << pt12;
529 
530  double ptLx1 = cand1->pt();
531  double ptLx2 = cand2->pt();
532  double invmass = abs(p.mass());
533  // if (invmass>0) invmass = sqrt(invmass); else invmass = 0;
534  LogDebug("HLTMuonDimuonL3Filter") << " ... 1-2 invmass= " << invmass;
535  bool proceed=false;
536  for (unsigned int iv=0 ; iv<min_InvMass_.size(); iv++) {
537  if (invmass<min_InvMass_[iv]) return false;
538  if (invmass>max_InvMass_[iv]) return false;
539  if (ptLx1>ptLx2) {
540  if (ptLx1<min_PtMax_[iv]) return false;
541  if (ptLx2<min_PtMin_[iv]) return false;
542  if (ptLx2>max_PtMin_[iv]) return false;
543  } else {
544  if (ptLx2<min_PtMax_[iv]) return false;
545  if (ptLx1<min_PtMin_[iv]) return false;
546  if (ptLx1>max_PtMin_[iv]) return false;
547  }
548  if (pt12<min_PtPair_[iv]) return false;
549  if (pt12>max_PtPair_[iv]) return false;
550  proceed=true;
551  break;
552  }
553  if (!proceed) return false;
554 
555  // Delta Z between the two muons
556  //double DeltaZMuMu = std::abs(tk2->dz(beamSpot.position())-tk1->dz(beamSpot.position()));
557  //if ( DeltaZMuMu > max_DzMuMu_) return false;
558 
559  // DCA between the two muons
560  TrackRef tk1 = cand1->track();
561  TrackRef tk2 = cand2->track();
562  TransientTrack mu1TT(*tk1, &(*bFieldHandle));
563  TransientTrack mu2TT(*tk2, &(*bFieldHandle));
566  if (mu1TS.isValid() && mu2TS.isValid()) {
568  cApp.calculate(mu1TS.theState(), mu2TS.theState());
569  if (!cApp.status()
570  || cApp.distance() > max_DCAMuMu_) return false;
571  }
572 
573  // Max dimuon |rapidity|
574  double rapidity = std::abs(p.Rapidity());
575  if ( rapidity > max_YPair_) return false;
576 
577  // if cutting on cowboys reject muons that bend towards each other
578  if(cutCowboys_ && (cand1->charge()*deltaPhi(cand1->phi(), cand2->phi()) > 0.)) return false;
579  return true;
580 }
581 
582 // declare this class as a framework plugin
#define LogDebug(id)
bool applyDiMuonSelection(const reco::RecoChargedCandidateRef &, const reco::RecoChargedCandidateRef &, const reco::BeamSpot &, const edm::ESHandle< MagneticField > &) const
std::vector< double > max_PtPair_
double z0() const
z coordinate
Definition: BeamSpot.h:68
float distance() const override
void getObjects(Vids &ids, VRphoton &refs) const
various physics-level getters:
const edm::EDGetTokenT< trigger::TriggerFilterObjectWithRefs > previousCandToken_
std::vector< double > max_PtMin_
std::vector< double > max_InvMass_
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
enum start value shifted to 81 so as to avoid clashes with PDG codes
TrajectoryStateClosestToPoint impactPointTSCP() const
const FreeTrajectoryState & theState() const
std::vector< double > min_InvMass_
edm::Ref< RecoChargedCandidateCollection > RecoChargedCandidateRef
reference to an object in a collection of RecoChargedCandidate objects
double phi() const
azimuthal angle of momentum vector
Definition: TrackBase.h:684
bool applyMuonSelection(const reco::RecoChargedCandidateRef &, const reco::BeamSpot &) const
std::vector< double > min_PtPair_
~HLTMuonDimuonL3Filter() override
bool accept(const edm::Event &event, const edm::TriggerResults &triggerTable, const std::string &triggerPath)
Definition: TopDQMHelpers.h:30
std::string encode() const
Definition: InputTag.cc:159
std::vector< Muon > MuonCollection
collection of Muon objects
Definition: MuonFwd.h:9
std::vector< MuonTrackLinks > MuonTrackLinksCollection
collection of MuonTrackLinks
Definition: MuonFwd.h:22
const edm::InputTag l1CandTag_
void addObject(int id, const reco::RecoEcalCandidateRef &ref)
setters for L3 collections: (id=physics type, and Ref<C>)
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
bool status() const override
const edm::EDGetTokenT< trigger::TriggerFilterObjectWithRefs > l1CandToken_
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
bool calculate(const TrajectoryStateOnSurface &sta, const TrajectoryStateOnSurface &stb) override
T sqrt(T t)
Definition: SSEVec.h:18
double pt() const
track transverse momentum
Definition: TrackBase.h:660
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:243
std::vector< double > min_PtMin_
ParameterDescriptionBase * add(U const &iLabel, T const &value)
double p2[4]
Definition: TauolaWrapper.h:90
std::vector< double > min_PtMax_
#define M_PI
std::vector< RecoChargedCandidate > RecoChargedCandidateCollection
collectin of RecoChargedCandidate objects
const edm::EDGetTokenT< reco::BeamSpot > beamspotToken_
constexpr auto deltaR2(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:16
static void makeHLTFilterDescription(edm::ParameterSetDescription &desc)
Definition: HLTFilter.cc:29
bool hltFilter(edm::Event &, const edm::EventSetup &, trigger::TriggerFilterObjectWithRefs &filterproduct) const override
void addCollectionTag(const edm::InputTag &collectionTag)
collectionTags
void add(std::string const &label, ParameterSetDescription const &psetDescription)
std::string const & label() const
Definition: InputTag.h:36
const edm::EDGetTokenT< reco::RecoChargedCandidateCollection > candToken_
fixed size matrix
bool saveTags() const
Definition: HLTFilter.h:45
HLT enums.
double p1[4]
Definition: TauolaWrapper.h:89
double a
Definition: hdecay.h:121
T get() const
Definition: EventSetup.h:71
double y0() const
y coordinate
Definition: BeamSpot.h:66
HLTMuonDimuonL3Filter(const edm::ParameterSet &)
const edm::EDGetTokenT< reco::MuonTrackLinksCollection > linkToken_
bool cutCowboys_
if true, reject muon-track pairs that bend towards each other
std::ostream & operator<<(std::ostream &ost, const HLTGlobalStatus &hlt)
Formatted printout of trigger tbale.
static bool triggeredByLevel2(reco::TrackRef const &track, std::vector< reco::RecoChargedCandidateRef > const &vcands)
const edm::InputTag candTag_
math::PtEtaPhiELorentzVectorF LorentzVector
double x0() const
x coordinate
Definition: BeamSpot.h:64