SVertex.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Rivet.hh"
00003 #include "Rivet/Projections/SVertex.hh"
00004 #include "HepMC/GenVertex.h"
00005 #include "HepMC/GenParticle.h"
00006 #include "HepMC/GenEvent.h"
00007 #include "HepMC/SimpleVector.h"
00008 #include "Rivet/Cmp.hh"
00009 
00010 namespace Rivet {
00011 
00012 
00013   // Return distance of closest approach from track to given (primary) vertex position.
00014   inline double get2dClosestApproach(const HepMC::GenParticle& track, const Vector3& vtx3pos) {
00015     /// @todo Whoa! - implicit constructors from hell!
00016     HepMC::FourVector trkvec = track;
00017     HepMC::ThreeVector trk3vec = trkvec;
00018     HepMC::ThreeVector trk3pos = track.production_vertex()->position();
00019 
00020     Vector3 diff(vtx3pos.x()-trk3pos.x(), vtx3pos.y()-trk3pos.y(), vtx3pos.z()-trk3pos.z());
00021 
00022     // Impact parameter in the transverse plane
00023     const double d = fabs( trk3vec.x()*diff.y() - trk3vec.y()*diff.x() )
00024       / sqrt( sqr(trk3vec.x()) + sqr(trk3vec.y()) );
00025     return d;
00026   }
00027 
00028 
00029   // Return distance of closest approach from track to given (primary) vertex position.
00030   inline double get3dClosestApproach(const HepMC::GenParticle& track, const Vector3& vtx3pos) {
00031     HepMC::FourVector trkvec = track;
00032     HepMC::ThreeVector trk3vec = trkvec;
00033     HepMC::FourVector trkpos = track.production_vertex()->position();
00034     HepMC::ThreeVector trk3pos = trkpos;
00035     Vector3 diff(vtx3pos.x()-trk3pos.x(), vtx3pos.y()-trk3pos.y(), vtx3pos.z()-trk3pos.z());
00036 
00037     // Impact parameter in 3 dimensions
00038     const double mag = sqrt( sqr(trk3vec.x()) + sqr(trk3vec.y()) + sqr(trk3vec.z()) );
00039     const double d = sqrt( sqr(trk3vec.y()*diff.z()-trk3vec.z()*diff.y()) -
00040                            sqr(trk3vec.x()*diff.z()-trk3vec.z()*diff.x()) +
00041                            sqr(trk3vec.x()*diff.y()-trk3vec.y()*diff.x()) ) / mag;
00042     return d;
00043   }
00044 
00045 
00046   /// Return Decay Length Significance between two vertices in transverse plane
00047   inline double get2dDecayLength(const Vector3& vtx1, const Vector3& vtx2, const FourMomentum& jetaxis) {
00048     Vector3 diff = vtx1 - vtx2;
00049     const double l = (jetaxis.px()*diff.x() + jetaxis.py()*diff.y() )
00050       / sqrt(sqr(jetaxis.px())+sqr(jetaxis.py()));
00051     return l;
00052   }
00053 
00054 
00055 
00056   /// Return 3 dimensional Decay Length Significance between vertices
00057   inline double get3dDecayLength(const Vector3& vtx1, const Vector3& vtx2, const FourMomentum& jetaxis) {
00058     Vector3 diff = vtx1 - vtx2;
00059     const double l = (jetaxis.px()*diff.x() +jetaxis.py()*diff.y() +jetaxis.pz()*diff.z())
00060       / sqrt(sqr(jetaxis.px())+sqr(jetaxis.py())+sqr(jetaxis.pz()));
00061     return l;
00062   }
00063 
00064 
00065 
00066   int SVertex::compare(const Projection& p) const {
00067     const PCmp fscmp = mkNamedPCmp(p, "PV");
00068     if (fscmp != EQUIVALENT) return fscmp;
00069     const SVertex& other = pcast<SVertex>(p);
00070     return \
00071       cmp(_detEta, other._detEta) ||
00072       cmp(_IPres, other._IPres) ||
00073       cmp(_DLS, other._DLS) ||
00074       cmp(_DLSres, _DLSres);
00075   }
00076 
00077 
00078 
00079   void SVertex::project(const Event& e) {
00080     const PVertex& pvtx = applyProjection<PVertex>(e, "PV");
00081     const Vector3 pvpos = pvtx.position();
00082     const ChargedFinalState& chfs = applyProjection<ChargedFinalState>(e, "FS");
00083 
00084     // Produce vector of vertices, each containing a vector of all charged
00085     // final state particles belonging to this vertex
00086     typedef map<GenVertex*,ParticleVector> VtxPartsMap;
00087     VtxPartsMap vtxparts;
00088     foreach (const Particle& p, chfs.particles()) {
00089       // Consider only charged particles in tracker geometrical acceptance
00090       /// @todo Use acceptance from the FinalState instead
00091       if (fabs(p.momentum().pseudorapidity()) > _detEta) continue;
00092       HepMC::GenVertex* pvtx = p.genParticle().production_vertex();
00093       vtxparts[pvtx].push_back(p);
00094     }
00095 
00096     // Check if jets are tagged, by means of selected vertices fulfilling track criteria
00097     _taggedjets.clear();
00098     for (VtxPartsMap::const_iterator vp = vtxparts.begin(); vp != vtxparts.end(); ++vp) {
00099       FourMomentum vtxVisMom;
00100       if (! _applyVtxTrackCuts(vp->second, pvpos, vtxVisMom) ) break;
00101       for (vector<FourMomentum>::const_iterator jaxis = _jetaxes.begin(); jaxis != _jetaxes.end(); ++jaxis) {
00102         // Delta{R} requirement between jet and visible vector sum of vertex tracks
00103         if (deltaR(*jaxis, vtxVisMom) < _deltaR) {
00104           const double dls = get2dDecayLength(vp->first->position(), pvpos, *jaxis) / _DLSres;
00105           if (dls > _DLS) _taggedjets.push_back(*jaxis);
00106         }
00107       }
00108     }
00109 
00110   }
00111 
00112 
00113 
00114   /// Analysis dependent cuts on vertex tracks in SVertex projection
00115   /// Since the analysis specific cuts are very complex, they are not
00116   /// implemented in the projection and are instead passed via a function (object).
00117   /// SVertex member function implementation below
00118   /// in: reference to instance of SVertex projection, ParticleVector of
00119   ///     vertex to be analyzed, primary (Gen)Vertex
00120   /// out: FourMomentum = visible Momentum of vertex (selected tracks),
00121   /// return bool: cuts passed? 1 : 0
00122   /// @todo Move this into the projection concrete class.
00123   bool SVertex::_applyVtxTrackCuts(const ParticleVector& vtxparts,
00124                                    const Vector3& pvtxpos,
00125                                    FourMomentum vtxVisMom)
00126   {
00127     // Check vertex final state charged particles, if fulfilling track criteria
00128     size_t pass1trk1pTdcaSig25(0), pass1trk05pTdcaSig25(0),
00129       pass2trk15pTdcaSig3(0), pass2trk1pTdcaSig3(0);
00130 
00131     foreach (const Particle& vp, vtxparts) {
00132       const double IPsig = get2dClosestApproach(vp.genParticle(), pvtxpos) / _IPres;
00133 
00134       // Update "visible momentum" vector (returned by reference).
00135       if (vp.momentum().pT() > 0.5) {
00136         vtxVisMom += vp.momentum();
00137       }
00138       // 1st pass
00139       if (vtxparts.size() >= 3 && IPsig > 2.5) {
00140         if (vp.momentum().pT() > 1.0) pass1trk1pTdcaSig25++;
00141         else if (vp.momentum().pT() > 0.5) pass1trk05pTdcaSig25++;
00142       }
00143       // 2nd pass
00144       if (vtxparts.size() >= 2 && IPsig > 3.) {
00145         if (vp.momentum().pT() > 1.5) pass2trk15pTdcaSig3++;
00146         else if (vp.momentum().pT() > 1.0) pass2trk1pTdcaSig3++;
00147       }
00148     }
00149 
00150     // Combine info from passes to make yes/no decision about whether this is significant:
00151     if (pass1trk1pTdcaSig25 >= 1 && pass1trk1pTdcaSig25 + pass1trk05pTdcaSig25>=3) return true;
00152     if (pass2trk15pTdcaSig3 >= 1 && pass2trk15pTdcaSig3 + pass2trk1pTdcaSig3>=2) return true;
00153     return false;
00154   }
00155 
00156 
00157 
00158 }