CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/HLTrigger/Muon/src/HLTMuonTrackMassFilter.cc

Go to the documentation of this file.
00001 #include "HLTrigger/Muon/interface/HLTMuonTrackMassFilter.h"
00002 
00003 #include "FWCore/Framework/interface/Frameworkfwd.h"
00004 
00005 #include "FWCore/Framework/interface/Event.h"
00006 #include "FWCore/Framework/interface/MakerMacros.h"
00007 #include "DataFormats/Common/interface/Handle.h"
00008 
00009 #include "DataFormats/HLTReco/interface/TriggerFilterObjectWithRefs.h"
00010 #include "DataFormats/HLTReco/interface/TriggerRefsCollections.h"
00011 
00012 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00013 #include "FWCore/MessageLogger/interface/MessageDrop.h"
00014 
00015 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00016 #include "DataFormats/RecoCandidate/interface/RecoChargedCandidate.h"
00017 #include "DataFormats/RecoCandidate/interface/RecoChargedCandidateFwd.h"
00018 #include "DataFormats/TrackReco/interface/Track.h"
00019 
00020 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00021 
00022 #include "DataFormats/Math/interface/deltaR.h"
00023 
00024 #include <memory>
00025 #include <iostream>
00026 #include <sstream>
00027 
00028 
00029 HLTMuonTrackMassFilter::HLTMuonTrackMassFilter(const edm::ParameterSet& iConfig) :
00030   beamspotTag_(iConfig.getParameter<edm::InputTag>("BeamSpotTag")),
00031   muonTag_(iConfig.getParameter<edm::InputTag>("CandTag")),
00032   trackTag_(iConfig.getParameter<edm::InputTag>("TrackTag")),
00033   prevCandTag_(iConfig.getParameter<edm::InputTag>("PreviousCandTag")),
00034   saveTag_(iConfig.getUntrackedParameter<bool>("SaveTag",false)),
00035   minMasses_(iConfig.getParameter< std::vector<double> >("MinMasses")),
00036   maxMasses_(iConfig.getParameter< std::vector<double> >("MaxMasses")),
00037   checkCharge_(iConfig.getParameter<bool>("checkCharge")),
00038   minTrackPt_(iConfig.getParameter<double>("MinTrackPt")),
00039   minTrackP_(iConfig.getParameter<double>("MinTrackP")),
00040   maxTrackEta_(iConfig.getParameter<double>("MaxTrackEta")),
00041   maxTrackDxy_(iConfig.getParameter<double>("MaxTrackDxy")),
00042   maxTrackDz_(iConfig.getParameter<double>("MaxTrackDz")),
00043   minTrackHits_(iConfig.getParameter<int>("MinTrackHits")),
00044   maxTrackNormChi2_(iConfig.getParameter<double>("MaxTrackNormChi2")),
00045   maxDzMuonTrack_(iConfig.getParameter<double>("MaxDzMuonTrack")),
00046   cutCowboys_(iConfig.getParameter<bool>("CutCowboys"))
00047 {
00048   //register your products
00049   produces<trigger::TriggerFilterObjectWithRefs>();
00050   //
00051   // verify mass windows
00052   //
00053   bool massesValid = minMasses_.size()==maxMasses_.size();
00054   if ( massesValid ) {
00055     for ( unsigned int i=0; i<minMasses_.size(); ++i ) {
00056       if ( minMasses_[i]<0 || maxMasses_[i]<0 || 
00057            minMasses_[i]>maxMasses_[i] )  massesValid = false;
00058     }
00059   }
00060   if ( !massesValid ) {
00061     edm::LogError("HLTMuonTrackMassFilter") << "Inconsistency in definition of mass windows, "
00062                                                 << "no event will pass the filter";
00063     minMasses_.clear();
00064     maxMasses_.clear();
00065   }
00066 
00067   std::ostringstream stream;
00068   stream << "instantiated with parameters\n";
00069   stream << "  beamspot = " << beamspotTag_ << "\n";
00070   stream << "  muonCandidates = " << muonTag_ << "\n";
00071   stream << "  trackCandidates = " << trackTag_ << "\n";
00072   stream << "  previousCandidates = " << prevCandTag_ << "\n";
00073   stream << "  saveTag = " << saveTag_ << "\n";
00074   stream << "  mass windows =";
00075   for ( size_t i=0; i<minMasses_.size(); ++i )  
00076     stream << " (" << minMasses_[i] << "," << maxMasses_[i] << ")";
00077   stream << "\n";
00078   stream << "  checkCharge = " << checkCharge_ << "\n";
00079   stream << "  MinTrackPt = " << minTrackPt_ << "\n";
00080   stream << "  MinTrackP = " << minTrackP_ << "\n";
00081   stream << "  MaxTrackEta = " << maxTrackEta_ << "\n";
00082   stream << "  MaxTrackDxy = " << maxTrackDxy_ << "\n";
00083   stream << "  MaxTrackDz = " << maxTrackDz_ << "\n";
00084   stream << "  MinTrackHits = " << minTrackHits_ << "\n";
00085   stream << "  MaxTrackNormChi2 = " << maxTrackNormChi2_ << "\n";
00086   stream << "  MaxDzMuonTrack = " << maxDzMuonTrack_ << "\n";
00087   LogDebug("HLTMuonTrackMassFilter") << stream.str();
00088 
00089 }
00090 
00091 bool
00092 HLTMuonTrackMassFilter::filter(edm::Event& iEvent, const edm::EventSetup& iSetup)
00093 {
00094  // The filter object
00095   std::auto_ptr<trigger::TriggerFilterObjectWithRefs>
00096     filterproduct (new trigger::TriggerFilterObjectWithRefs(path(),module()));
00097   if ( saveTag_ ) {
00098     filterproduct->addCollectionTag(muonTag_);
00099     filterproduct->addCollectionTag(trackTag_);
00100   }
00101   //
00102   // Beamspot
00103   //
00104   edm::Handle<reco::BeamSpot> beamspotHandle;
00105   iEvent.getByLabel(beamspotTag_,beamspotHandle);
00106   reco::BeamSpot::Point beamspot(beamspotHandle->position());
00107   //
00108   // Muons
00109   //
00110   edm::Handle<reco::RecoChargedCandidateCollection> muonHandle;
00111   iEvent.getByLabel(muonTag_,muonHandle);
00112   //
00113   // Tracks
00114   //
00115   edm::Handle<reco::RecoChargedCandidateCollection> trackHandle;
00116   iEvent.getByLabel(trackTag_,trackHandle);
00117   //
00118   // Muons from previous filter
00119   //
00120   edm::Handle<trigger::TriggerFilterObjectWithRefs> prevCandHandle;
00121   iEvent.getByLabel(prevCandTag_,prevCandHandle);
00122   std::vector<reco::RecoChargedCandidateRef> prevMuonRefs;
00123   prevCandHandle->getObjects(trigger::TriggerMuon,prevMuonRefs);
00124   std::vector<reco::RecoChargedCandidateRef> prevTrackRefs;
00125   prevCandHandle->getObjects(trigger::TriggerTrack,prevTrackRefs);
00126   bool checkPrevTracks = prevTrackRefs.size()==prevMuonRefs.size();
00127 //   LogDebug("HLTMuonTrackMassFilter") << "#previous track refs = " << prevTrackRefs.size();
00128   //
00129   // access to muons and selection according to configuration
00130   //   if the previous candidates are taken from a muon+track
00131   //   quarkonia filter we rely on the fact that only the muons 
00132   //   are flagged as TriggerMuon 
00133   //
00134   std::vector<reco::RecoChargedCandidateRef> selectedMuonRefs;
00135   selectedMuonRefs.reserve(muonHandle->size());
00136 //   std::vector<size_t> prevMuonIndices;
00137 //   std::ostringstream stream1;
00138   for ( unsigned int i=0; i<muonHandle->size(); ++i ) {
00139     // Ref
00140     reco::RecoChargedCandidateRef muonRef(muonHandle,i);
00141 //     stream1 << "Checking muon with q / pt / p / eta = "
00142 //          << muonRef->charge() << " " << muonRef->pt() << " "
00143 //          << muonRef->p() << " " << muonRef->eta() << "\n";
00144     // passed previous filter?
00145     if ( find(prevMuonRefs.begin(),prevMuonRefs.end(),muonRef)==
00146          prevMuonRefs.end() )  continue;
00147 //     prevMuonIndices.push_back(find(prevMuonRefs.begin(),prevMuonRefs.end(),muonRef)-
00148 //                            prevMuonRefs.begin());
00149     // keep muon
00150 //     stream1 << "... accepted as #" << selectedMuonRefs.size() << "\n";
00151     selectedMuonRefs.push_back(muonRef);
00152   }
00153 //   LogDebug("HLTMuonTrackMassFilter") << stream1.str();
00154   //
00155   // access to tracks and selection according to configuration
00156   //
00157   std::vector<reco::RecoChargedCandidateRef> selectedTrackRefs;
00158   selectedTrackRefs.reserve(trackHandle->size());
00159 //   std::ostringstream stream2;
00160   for ( unsigned int i=0; i<trackHandle->size(); ++i ) {
00161     // validity of REF
00162     reco::RecoChargedCandidateRef trackRef(trackHandle,i);
00163     const reco::RecoChargedCandidate& trackCand = *trackRef;
00164 //     stream2 << "Checking track with q / pt / p / eta = "
00165 //          << trackCand.charge() << " " << trackCand.pt() << " "
00166 //          << trackCand.p() << " " << trackCand.eta() << "\n";
00167     // cuts on the momentum
00168     if ( trackCand.pt()<minTrackPt_ || trackCand.p()<minTrackP_ ||
00169          fabs(trackCand.eta())>maxTrackEta_ )  continue;
00170     if ( trackCand.track().isNull() )  continue;
00171     // cuts on track quality
00172     const reco::Track& track = *trackCand.track();
00173 //     stream2 << "... with dxy / dz / #hits / chi2 = "
00174 //          << track.dxy(beamspot) << " "
00175 //          << track.dz(beamspot) << " "
00176 //          << track.numberOfValidHits() << " "
00177 //          << track.normalizedChi2();
00178     if ( fabs(track.dxy(beamspot))>maxTrackDxy_ ||
00179          fabs(track.dz(beamspot))>maxTrackDz_ ||
00180          track.numberOfValidHits()<minTrackHits_ ||
00181          track.normalizedChi2()>maxTrackNormChi2_ )  continue;
00182     // keep track
00183 //     stream2 << "... accepted as #" << selectedTrackRefs.size() << "\n";
00184     selectedTrackRefs.push_back(trackRef);
00185   }
00186 //   LogDebug("HLTMuonTrackMassFilter") << stream2.str();
00187   //
00188   // combinations
00189   //
00190   unsigned int nDz(0);
00191   unsigned int nQ(0);
00192   unsigned int nCowboy(0);
00193   unsigned int nComb(0);
00194   reco::Particle::LorentzVector p4Muon;
00195   reco::Particle::LorentzVector p4JPsi;
00196 //   std::ostringstream stream3;
00197   for ( unsigned int im=0; im<selectedMuonRefs.size(); ++im ) {
00198     const reco::RecoChargedCandidate& muon = *selectedMuonRefs[im];
00199     int qMuon = muon.charge();
00200     p4Muon = muon.p4();
00201     for ( unsigned int it=0; it<selectedTrackRefs.size(); ++it ) {
00202       const reco::RecoChargedCandidate& track = *selectedTrackRefs[it];
00203 //       stream3 << "Combination " << im << " / " << it << " with dz / q / mass = "
00204 //            << muon.track()->dz(beamspot)-track.track()->dz(beamspot) << " "
00205 //            << track.charge()+qMuon << " "
00206 //            << (p4Muon+track.p4()).mass() << "\n";
00207       if ( fabs(muon.track()->dz(beamspot)-track.track()->dz(beamspot))>
00208            maxDzMuonTrack_ )  continue;
00209       ++nDz;
00210       if ( checkCharge_ && track.charge()!=-qMuon )  continue;
00211       ++nQ;
00212 
00213       // if cutting on cowboys reject muons that bend towards each other
00214       if(cutCowboys_ && (qMuon*deltaPhi(p4Muon.phi(), track.phi()) > 0.)) continue;
00215       ++nCowboy;
00216 
00217       if ( checkPrevTracks ) {
00218         if ( !pairMatched(prevMuonRefs,prevTrackRefs,
00219                           selectedMuonRefs[im],
00220                           selectedTrackRefs[it]) ) continue;
00221       }
00222       double mass = (p4Muon+track.p4()).mass();
00223       for ( unsigned int j=0; j<minMasses_.size(); ++j ) {
00224         if ( mass>minMasses_[j] && mass<maxMasses_[j] ) {
00225           ++nComb;
00226           filterproduct->addObject(trigger::TriggerMuon,selectedMuonRefs[im]);
00227           filterproduct->addObject(trigger::TriggerTrack,selectedTrackRefs[it]);
00228 //        stream3 << "... accepted\n";
00229           break;
00230         }
00231       }
00232     }
00233   }
00234 //   LogDebug("HLTMuonTrackMassFilter") << stream3.str();
00235 
00236 
00237   if ( edm::isDebugEnabled() ) {
00238     std::ostringstream stream;
00239     stream << "Total number of combinations = " 
00240            << selectedMuonRefs.size()*selectedTrackRefs.size() << " , after dz " << nDz
00241            << " , after charge " << nQ << " , after cutCowboy " << nCowboy << " , after mass " << nComb << std::endl;
00242     stream << "Found " << nComb << " jpsi candidates with # / mass / q / pt / eta" << std::endl;
00243     std::vector<reco::RecoChargedCandidateRef> muRefs;
00244     std::vector<reco::RecoChargedCandidateRef> tkRefs;
00245     filterproduct->getObjects(trigger::TriggerMuon,muRefs);
00246     filterproduct->getObjects(trigger::TriggerTrack,tkRefs);
00247     reco::Particle::LorentzVector p4Mu;
00248     reco::Particle::LorentzVector p4Tk;
00249     reco::Particle::LorentzVector p4JPsi;
00250     if ( muRefs.size()==tkRefs.size() ) {
00251       for ( unsigned int i=0; i<muRefs.size(); ++i ) {
00252         p4Mu = muRefs[i]->p4();
00253         p4Tk = tkRefs[i]->p4();
00254         p4JPsi = p4Mu + p4Tk;
00255         stream << "  " << i << " " 
00256                << p4JPsi.M() << " "
00257                << muRefs[i]->charge()+tkRefs[i]->charge() << " "
00258                << p4JPsi.P() << " "
00259                << p4JPsi.Eta() << "\n";
00260       }
00261       LogDebug("HLTMuonTrackMassFilter") << stream.str();
00262     }
00263     else {
00264       LogDebug("HLTMuonTrackMassFilter") << "different sizes for muon and track containers!!!";
00265     }
00266   }
00267 
00268   iEvent.put(filterproduct);
00269 
00270   return nComb>0;
00271 }
00272 
00273 bool
00274 HLTMuonTrackMassFilter::pairMatched (std::vector<reco::RecoChargedCandidateRef>& prevMuonRefs,
00275                                          std::vector<reco::RecoChargedCandidateRef>& prevTrackRefs,
00276                                          const reco::RecoChargedCandidateRef& muonRef,
00277                                          const reco::RecoChargedCandidateRef& trackRef) const
00278 {
00279   //
00280   // check only if references to tracks are available
00281   //
00282   if ( prevTrackRefs.empty() )  return true;
00283   //
00284   // validity
00285   //
00286   if ( prevMuonRefs.size()!=prevTrackRefs.size() )  return false;
00287   edm::RefToBase<TrajectorySeed> seedRef = trackRef->track()->seedRef();
00288   if ( seedRef.isNull() )  return false;
00289   //
00290   // comparison by hits of TrajectorySeed of the new track
00291   // with the previous candidate
00292   //
00293   TrajectorySeed::range seedHits = seedRef->recHits();
00294   trackingRecHit_iterator prevTrackHitEnd;
00295   trackingRecHit_iterator iprev;
00296   TrajectorySeed::const_iterator iseed;
00297   for ( size_t i=0; i<prevMuonRefs.size(); ++i ) {
00298     // identity of muon
00299     if ( prevMuonRefs[i]!=muonRef )  continue;
00300     // validity of Ref to previous track candidate
00301     reco::TrackRef prevTrackRef = prevTrackRefs[i]->track();
00302     if ( prevTrackRef.isNull() )  continue;
00303     // if the references are the same then found and return true otherwise compare by hits
00304     if (prevTrackRef==trackRef->track()) return true;
00305     // same #hits
00306     if ( seedRef->nHits()!=prevTrackRef->recHitsSize() )  continue;
00307     // hit-by-hit comparison based on the sharesInput method
00308     iseed = seedHits.first;
00309     iprev = prevTrackRef->recHitsBegin();
00310     prevTrackHitEnd = prevTrackRef->recHitsEnd();
00311     bool identical(true);
00312     for ( ; iseed!=seedHits.second&&iprev!=prevTrackHitEnd; ++iseed,++iprev ) {
00313       if ( (*iseed).isValid()!=(**iprev).isValid() ||
00314            !(*iseed).sharesInput(&**iprev,TrackingRecHit::all) ) {
00315         // terminate loop over hits on first mismatch
00316         identical = false;
00317         break;
00318       }
00319     }
00320     // if seed and previous track candidates are identical : return success
00321     if ( identical )  return true;
00322   }
00323   // no match found
00324   return false;
00325 }
00326 
00327                                        
00328 
00329 
00330 
00331 //define this as a plug-in
00332 DEFINE_FWK_MODULE(HLTMuonTrackMassFilter);