CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/HLTrigger/btau/src/HLTmmkFilter.cc

Go to the documentation of this file.
00001 #include <algorithm>
00002 #include <cmath>
00003 #include <vector>
00004 
00005 #include "FWCore/Framework/interface/ESHandle.h"
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 
00008 #include "DataFormats/RecoCandidate/interface/RecoCandidate.h"
00009 #include "DataFormats/RecoCandidate/interface/RecoChargedCandidate.h"
00010 
00011 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00012 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00013  
00014 #include "RecoVertex/KalmanVertexFit/interface/KalmanVertexFitter.h"
00015 #include "RecoVertex/VertexPrimitives/interface/TransientVertex.h"
00016 #include "DataFormats/VertexReco/interface/Vertex.h"
00017 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00018 #include "DataFormats/HLTReco/interface/TriggerFilterObjectWithRefs.h"
00019 
00020 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00021 
00022 #include "DataFormats/Math/interface/deltaPhi.h"
00023 
00024 #include "HLTmmkFilter.h"
00025 
00026 using namespace edm;
00027 using namespace reco;
00028 using namespace std;
00029 using namespace trigger;
00030 
00031 
00032 // ----------------------------------------------------------------------
00033 HLTmmkFilter::HLTmmkFilter(const edm::ParameterSet& iConfig):thirdTrackMass_(iConfig.getParameter<double>("ThirdTrackMass")),
00034                                                              maxEta_(iConfig.getParameter<double>("MaxEta")),
00035                                                              minPt_(iConfig.getParameter<double>("MinPt")),
00036                                                              minInvMass_(iConfig.getParameter<double>("MinInvMass")),
00037                                                              maxInvMass_(iConfig.getParameter<double>("MaxInvMass")),
00038                                                              maxNormalisedChi2_(iConfig.getParameter<double>("MaxNormalisedChi2")),
00039                                                              minLxySignificance_(iConfig.getParameter<double>("MinLxySignificance")),
00040                                                              minCosinePointingAngle_(iConfig.getParameter<double>("MinCosinePointingAngle")),
00041                                                              fastAccept_(iConfig.getParameter<bool>("FastAccept")),
00042                                                              saveTag_ (iConfig.getUntrackedParameter<bool> ("SaveTag",false)),
00043                                                              beamSpotTag_ (iConfig.getParameter<edm::InputTag> ("BeamSpotTag")){
00044 
00045   muCandLabel_   = iConfig.getParameter<edm::InputTag>("MuCand");
00046   trkCandLabel_  = iConfig.getParameter<edm::InputTag>("TrackCand");
00047   
00048   produces<VertexCollection>();
00049   produces<CandidateCollection>();
00050   produces<trigger::TriggerFilterObjectWithRefs>();
00051 
00052 }
00053 
00054 
00055 // ----------------------------------------------------------------------
00056 HLTmmkFilter::~HLTmmkFilter() {
00057 
00058 }
00059 
00060 
00061 // ----------------------------------------------------------------------
00062 void HLTmmkFilter::beginJob() {
00063 
00064 }
00065 
00066 
00067 // ----------------------------------------------------------------------
00068 void HLTmmkFilter::endJob() {
00069         
00070 }
00071 
00072 
00073 // ----------------------------------------------------------------------
00074 bool HLTmmkFilter::filter(edm::Event& iEvent, const edm::EventSetup& iSetup) {
00075 
00076   const double MuMass(0.106);
00077   const double MuMass2(MuMass*MuMass);
00078   
00079   const double thirdTrackMass2(thirdTrackMass_*thirdTrackMass_);
00080   
00081   // The filter object
00082   auto_ptr<TriggerFilterObjectWithRefs> filterobject (new TriggerFilterObjectWithRefs(path(),module()));
00083   
00084   auto_ptr<CandidateCollection> output(new CandidateCollection());    
00085   auto_ptr<VertexCollection> vertexCollection(new VertexCollection());
00086   
00087   //get the transient track builder:
00088   edm::ESHandle<TransientTrackBuilder> theB;
00089   iSetup.get<TransientTrackRecord>().get("TransientTrackBuilder",theB);
00090 
00091   //get the beamspot position
00092   edm::Handle<reco::BeamSpot> recoBeamSpotHandle;
00093   iEvent.getByLabel(beamSpotTag_,recoBeamSpotHandle);
00094   const reco::BeamSpot& vertexBeamSpot = *recoBeamSpotHandle;
00095 
00096   // Ref to Candidate object to be recorded in filter object
00097   RecoChargedCandidateRef refMu1;
00098   RecoChargedCandidateRef refMu2;
00099   RecoChargedCandidateRef refTrk;       
00100         
00101   // get hold of muon trks
00102   Handle<RecoChargedCandidateCollection> mucands;
00103   iEvent.getByLabel (muCandLabel_,mucands);
00104 
00105   // get track candidates around displaced muons
00106   Handle<RecoChargedCandidateCollection> trkcands;
00107   iEvent.getByLabel (trkCandLabel_,trkcands);
00108   
00109   if(saveTag_){
00110     filterobject->addCollectionTag(muCandLabel_);
00111     filterobject->addCollectionTag(trkCandLabel_);
00112   }
00113   
00114   double e1,e2,e3;
00115   Particle::LorentzVector p,p1,p2,p3;
00116   
00117   //TrackRefs to mu cands in trkcand
00118   vector<TrackRef> trkMuCands;
00119   
00120   //Already used mu tracks to avoid double counting candidates
00121   vector<bool> isUsedCand(trkcands->size(),false);
00122   
00123   int counter = 0;
00124   
00125   //run algorithm
00126   for (RecoChargedCandidateCollection::const_iterator mucand1=mucands->begin(), endCand1=mucands->end(); mucand1!=endCand1; ++mucand1) {
00127   
00128         if ( mucands->size()<2) break;
00129         if ( trkcands->size()<3) break;
00130   
00131         TrackRef trk1 = mucand1->get<TrackRef>();
00132         LogDebug("HLTDisplacedMumukFilter") << " 1st muon: q*pt= " << trk1->charge()*trk1->pt() << ", eta= " << trk1->eta() << ", hits= " << trk1->numberOfValidHits();
00133   
00134         // eta cut
00135         if (fabs(trk1->eta()) > maxEta_) continue;
00136         
00137         // Pt threshold cut
00138         if (trk1->pt() < minPt_) continue;
00139 
00140         RecoChargedCandidateCollection::const_iterator mucand2 = mucand1; ++mucand2;
00141         
00142         for (RecoChargedCandidateCollection::const_iterator endCand2=mucands->end(); mucand2!=endCand2; ++mucand2) {
00143   
00144                 TrackRef trk2 = mucand2->get<TrackRef>();
00145 
00146                 LogDebug("HLTDisplacedMumukFilter") << " 2nd muon: q*pt= " << trk2->charge()*trk2->pt() << ", eta= " << trk2->eta() << ", hits= " << trk2->numberOfValidHits();
00147 
00148                 // eta cut
00149                 if (fabs(trk2->eta()) > maxEta_) continue;
00150         
00151                 // Pt threshold cut
00152                 if (trk2->pt() < minPt_) continue;
00153 
00154                 RecoChargedCandidateCollection::const_iterator trkcand, endCandTrk;
00155 
00156                 std::vector<bool>::iterator isUsedIter, endIsUsedCand;
00157 
00158                 //get overlapping muon candidates
00159                 for ( trkcand = trkcands->begin(), endCandTrk=trkcands->end(), isUsedIter = isUsedCand.begin(), endIsUsedCand = isUsedCand.end(); trkcand != endCandTrk && isUsedIter != endIsUsedCand; ++trkcand, ++isUsedIter) {
00160                         TrackRef trk3 = trkcand->get<TrackRef>();
00161                 
00162                         //check for overlapping muon tracks and save TrackRefs
00163                         if (overlap(*mucand1,*trkcand)) {
00164                                 trkMuCands.push_back(trk3);
00165                                 *isUsedIter = true;
00166                                 continue;
00167                         }
00168                         else if (overlap(*mucand2,*trkcand)){
00169                                 trkMuCands.push_back(trk3);
00170                                 *isUsedIter = true;
00171                                 continue;
00172                         }
00173                         
00174                         if(trkMuCands.size()==2) break;
00175                 }
00176 
00177                 //Not all overlapping candidates found, skip event
00178                 if (trkMuCands.size()!=2) continue;
00179 
00180                 //combine muons with all tracks
00181                 for ( trkcand = trkcands->begin(), endCandTrk=trkcands->end(), isUsedIter = isUsedCand.begin(), endIsUsedCand = isUsedCand.end(); trkcand != endCandTrk && isUsedIter != endIsUsedCand; ++trkcand, ++isUsedIter) {
00182  
00183                         TrackRef trk3 = trkcand->get<TrackRef>();
00184 
00185                         LogDebug("HLTDisplacedMumukFilter") << " 3rd track: q*pt= " << trk3->charge()*trk3->pt() << ", eta= " << trk3->eta() << ", hits= " << trk3->numberOfValidHits();
00186  
00187                         //skip overlapping muon candidates
00188                         if(trk3==trkMuCands.at(0) || trk3==trkMuCands.at(1)) continue;
00189 
00190                         //skip already used tracks
00191                         if(*isUsedIter) continue;
00192                                 
00193                         // eta cut
00194                         if (fabs(trk3->eta()) > maxEta_) continue;
00195         
00196                         // Pt threshold cut
00197                         if (trk3->pt() < minPt_) continue;
00198 
00199                         // Combined system
00200                         e1 = sqrt(trk1->momentum().Mag2()+MuMass2);
00201                         e2 = sqrt(trk2->momentum().Mag2()+MuMass2);
00202                         e3 = sqrt(trk3->momentum().Mag2()+thirdTrackMass2);
00203                         
00204                         p1 = Particle::LorentzVector(trk1->px(),trk1->py(),trk1->pz(),e1);
00205                         p2 = Particle::LorentzVector(trk2->px(),trk2->py(),trk2->pz(),e2);
00206                         p3 = Particle::LorentzVector(trk3->px(),trk3->py(),trk3->pz(),e3);
00207                         
00208                         p = p1+p2+p3;
00209                         
00210                         //invariant mass cut
00211                         double invmass = abs(p.mass());
00212                         
00213                         LogDebug("HLTDisplacedMumukFilter") << " Invmass= " << invmass;
00214                         
00215                         if (invmass>maxInvMass_ || invmass<minInvMass_) continue;
00216                         
00217                         // do the vertex fit
00218                         vector<TransientTrack> t_tks;
00219                         t_tks.push_back((*theB).build(&trk1));
00220                         t_tks.push_back((*theB).build(&trk2));
00221                         t_tks.push_back((*theB).build(&trk3));
00222                                                 
00223                         if (t_tks.size()!=3) continue;
00224                         
00225                         KalmanVertexFitter kvf;
00226                         TransientVertex tv = kvf.vertex(t_tks);
00227                                         
00228                         if (!tv.isValid()) continue;
00229                         
00230                         Vertex vertex = tv;
00231                         
00232                         // get vertex position and error to calculate the decay length significance
00233                         GlobalPoint secondaryVertex = tv.position();
00234                         GlobalError err = tv.positionError();
00235 
00236                         //calculate decay length  significance w.r.t. the beamspot
00237                         GlobalPoint displacementFromBeamspot( -1*((vertexBeamSpot.x0() -secondaryVertex.x()) +  (secondaryVertex.z() - vertexBeamSpot.z0()) * vertexBeamSpot.dxdz()), -1*((vertexBeamSpot.y0() - secondaryVertex.y())+ (secondaryVertex.z() -vertexBeamSpot.z0()) * vertexBeamSpot.dydz()), 0);
00238 
00239                         float lxy = displacementFromBeamspot.perp();
00240                         float lxyerr = sqrt(err.rerr(displacementFromBeamspot));
00241 
00242                         // get normalizes chi2
00243                         float normChi2 = tv.normalisedChiSquared();
00244                         
00245                         //calculate the angle between the decay length and the mumu momentum
00246                         Vertex::Point vperp(displacementFromBeamspot.x(),displacementFromBeamspot.y(),0.);
00247                         math::XYZVector pperp(p.x(),p.y(),0.);
00248 
00249                         float cosAlpha = vperp.Dot(pperp)/(vperp.R()*pperp.R());
00250                         
00251                         LogDebug("HLTDisplacedMumukFilter") << " vertex fit normalised chi2: " << normChi2 << ", Lxy significance: " << lxy/lxyerr << ", cosine pointing angle: " << cosAlpha;
00252                         
00253                         // put vertex in the event
00254                         vertexCollection->push_back(vertex);
00255                         
00256                         if (normChi2 > maxNormalisedChi2_) continue;
00257                         if (lxy/lxyerr < minLxySignificance_) continue;
00258                         if(cosAlpha < minCosinePointingAngle_) continue;
00259                         
00260                         LogDebug("HLTDisplacedMumukFilter") << " Event passed!";
00261                         
00262                         //Add event
00263                         ++counter;
00264                         
00265                         //Get refs 
00266                         bool i1done = false;
00267                         bool i2done = false;
00268                         bool i3done = false;
00269                         vector<RecoChargedCandidateRef> vref;
00270                         filterobject->getObjects(TriggerMuon,vref);
00271                         for (unsigned int i=0; i<vref.size(); i++) {
00272                                 RecoChargedCandidateRef candref =  RecoChargedCandidateRef(vref[i]);
00273                                 TrackRef trktmp = candref->get<TrackRef>();
00274                                 if (trktmp==trk1) {
00275                                         i1done = true;
00276                                 } else if (trktmp==trk2) {
00277                                         i2done = true;
00278                                 } else if (trktmp==trk3) {
00279                                     i3done = true;
00280                                 }
00281                                 if (i1done && i2done && i3done) break;
00282                         }
00283                 
00284                         if (!i1done) { 
00285                                 refMu1=RecoChargedCandidateRef( Ref<RecoChargedCandidateCollection> (mucands,distance(mucands->begin(), mucand1)));
00286                                 filterobject->addObject(TriggerMuon,refMu1);
00287                         }
00288                         if (!i2done) { 
00289                                 refMu2=RecoChargedCandidateRef( Ref<RecoChargedCandidateCollection> (mucands,distance(mucands->begin(),mucand2)));
00290                                 filterobject->addObject(TriggerMuon,refMu2);
00291                         }
00292                         if (!i3done) {
00293                             refTrk=RecoChargedCandidateRef( Ref<RecoChargedCandidateCollection> (trkcands,distance(trkcands->begin(),trkcand)));
00294                                 filterobject->addObject(TriggerTrack,refTrk);
00295                         }
00296                         
00297                         if (fastAccept_) break;
00298                 }  
00299                 
00300                 trkMuCands.clear();
00301         } 
00302   }
00303 
00304   // filter decision
00305   const bool accept (counter >= 1);
00306   
00307   LogDebug("HLTDisplacedMumukFilter") << " >>>>> Result of HLTDisplacedMumukFilter is "<< accept << ", number of muon pairs passing thresholds= " << counter; 
00308   
00309   // put filter object into the Event
00310   iEvent.put(filterobject);
00311   iEvent.put(vertexCollection);
00312   
00313   return accept;
00314 }
00315 
00316 // ----------------------------------------------------------------------
00317 int HLTmmkFilter::overlap(const reco::Candidate &a, const reco::Candidate &b) {
00318   
00319   double eps(1.0e-5);
00320 
00321   double dpt = a.pt() - b.pt();
00322   dpt *= dpt;
00323 
00324   double dphi = deltaPhi(a.phi(), b.phi()); 
00325   dphi *= dphi; 
00326 
00327   double deta = a.eta() - b.eta(); 
00328   deta *= deta; 
00329 
00330   if ((dpt + dphi + deta) < eps) {
00331     return 1;
00332   } 
00333 
00334   return 0;
00335 
00336 }
00337