CMS 3D CMS Logo

SoftLepton.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    SoftLepton
00004 // Class:      SoftLepton
00005 // 
00013 // Original Author:  fwyzard
00014 //         Created:  Wed Oct 18 18:02:07 CEST 2006
00015 // $Id: SoftLepton.cc,v 1.22 2008/10/25 17:33:56 fwyzard Exp $
00016 
00017 
00018 #include <memory>
00019 #include <string>
00020 #include <utility>
00021 #include <cmath>
00022 
00023 #include "FWCore/Framework/interface/Frameworkfwd.h"
00024 #include "FWCore/Framework/interface/EDProducer.h"
00025 #include "FWCore/Framework/interface/Event.h"
00026 #include "FWCore/Framework/interface/MakerMacros.h"
00027 #include "FWCore/Framework/interface/EventSetup.h"
00028 #include "FWCore/Framework/interface/ESHandle.h"
00029 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00030 #include "FWCore/Utilities/interface/EDMException.h"
00031 #include "DataFormats/Provenance/interface/ProductID.h"
00032 #include "DataFormats/Common/interface/RefToBase.h"
00033 
00034 // ROOT::Math vectors (aka math::XYZVector)
00035 #include "DataFormats/Math/interface/LorentzVector.h"
00036 #include "DataFormats/Math/interface/Vector3D.h"
00037 #include "Math/GenVector/PxPyPzM4D.h"
00038 #include "Math/GenVector/VectorUtil.h"
00039 #include "Math/GenVector/Boost.h"
00040 
00041 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
00042 #include "DataFormats/VertexReco/interface/Vertex.h"
00043 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00044 #include "DataFormats/TrackReco/interface/Track.h"
00045 #include "DataFormats/MuonReco/interface/Muon.h"
00046 #include "DataFormats/MuonReco/interface/MuonFwd.h"
00047 #include "DataFormats/EgammaCandidates/interface/Electron.h"
00048 #include "DataFormats/EgammaCandidates/interface/ElectronFwd.h"
00049 #include "DataFormats/EgammaCandidates/interface/GsfElectron.h"
00050 #include "DataFormats/EgammaCandidates/interface/GsfElectronFwd.h"
00051 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00052 #include "DataFormats/JetReco/interface/Jet.h"
00053 #include "DataFormats/JetReco/interface/CaloJet.h"
00054 #include "DataFormats/JetReco/interface/JetTracksAssociation.h"
00055 #include "DataFormats/BTauReco/interface/SoftLeptonTagInfo.h"
00056 
00057 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00058 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00059 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00060 #include "TrackingTools/IPTools/interface/IPTools.h"
00061 #include "RecoVertex/PrimaryVertexProducer/interface/PrimaryVertexSorter.h"
00062 #include "SoftLepton.h"
00063 
00064 enum {
00065   AXIS_CALORIMETRIC             = 0,  // use the calorimietric jet axis
00066   AXIS_CHARGED_AVERAGE          = 1,  // refine jet axis using charged tracks: use a pT-weighted average of (eta, phi)
00067   AXIS_CHARGED_AVERAGE_NOLEPTON = 2,  // as above, without the tagging lepton track
00068   AXIS_CHARGED_SUM              = 3,  // refine jet axis using charged tracks: use the sum of tracks momentum
00069   AXIS_CHARGED_SUM_NOLEPTON     = 4   // as above, without the tagging lepton track
00070 };
00071 
00072 using namespace std;
00073 using namespace edm;
00074 using namespace reco;
00075 using namespace ROOT::Math::VectorUtil;
00076 
00077 // ------------ static copy of the nominal beamspot --------------------------------------
00078 const reco::Vertex SoftLepton::s_nominalBeamSpot(
00079   reco::Vertex::Point( 0, 0, 0 ),
00080   reco::Vertex::Error( ROOT::Math::SVector<double,6>( 0.0015 * 0.0015, //          0.0,        0.0
00081                                                                   0.0, 0.0015 * 0.0015, //     0.0  
00082                                                                   0.0,             0.0, 15. * 15. ) ),
00083   1, 1, 0 );
00084 
00085 // ------------ c'tor --------------------------------------------------------------------
00086 SoftLepton::SoftLepton(const edm::ParameterSet & iConfig) :
00087   m_jets(          iConfig.getParameter<edm::InputTag>( "jets" ) ),
00088   m_primaryVertex( iConfig.getParameter<edm::InputTag>( "primaryVertex" ) ),
00089   m_leptons(       iConfig.getParameter<edm::InputTag>( "leptons" ) ),
00090   m_transientTrackBuilder( NULL ),
00091   m_refineJetAxis( iConfig.getParameter<unsigned int>( "refineJetAxis" ) ),
00092   m_deltaRCut(     iConfig.getParameter<double>( "leptonDeltaRCut" ) ),
00093   m_chi2Cut(       iConfig.getParameter<double>( "leptonChi2Cut" ) ),
00094   m_qualityCut(    iConfig.getParameter<double>( "leptonQualityCut" ) )
00095 {
00096   produces<reco::SoftLeptonTagInfoCollection>();
00097 }
00098 
00099 // ------------ d'tor --------------------------------------------------------------------
00100 SoftLepton::~SoftLepton(void) {
00101 }
00102 
00103 // ------------ method called once per event during the event loop -----------------------
00104 void
00105 SoftLepton::produce(edm::Event & event, const edm::EventSetup & setup) {
00106 
00107   // grab a TransientTrack helper from the Event Setup
00108   edm::ESHandle<TransientTrackBuilder> builder;
00109   setup.get<TransientTrackRecord>().get( "TransientTrackBuilder", builder );
00110   m_transientTrackBuilder = builder.product();
00111 
00112   // input objects
00113 
00114   // input jets (and possibly tracks)
00115   ProductID jets_id;
00116   std::vector<edm::RefToBase<reco::Jet> > jets;
00117   std::vector<reco::TrackRefVector>       tracks;
00118   do { {
00119     // look for a JetTracksAssociationCollection
00120     edm::Handle<reco::JetTracksAssociationCollection> h_jtas;
00121     event.getByLabel(m_jets, h_jtas);
00122     if (h_jtas.isValid()) {
00123       unsigned int size = h_jtas->size();
00124       jets.resize(size);
00125       tracks.resize(size);
00126       for (unsigned int i = 0; i < size; ++i) {
00127         jets[i]   = (*h_jtas)[i].first;
00128         tracks[i] = (*h_jtas)[i].second;
00129       }
00130       break;
00131     }
00132   } { // else...
00133     // look for a View<Jet>
00134     edm::Handle<edm::View<reco::Jet> > h_jets;
00135     event.getByLabel(m_jets, h_jets);
00136     if (h_jets.isValid()) {
00137       unsigned int size = h_jets->size();
00138       jets.resize(size);
00139       tracks.resize(size);
00140       for (unsigned int i = 0; i < h_jets->size(); i++)
00141         jets[i] = h_jets->refAt(i);
00142       break;
00143     }
00144   } { // else...
00145     throw edm::Exception(edm::errors::NotFound) << "Object " << m_jets << " of type among (\"reco::JetTracksAssociationCollection\", \"edm::View<reco::Jet>\") not found";
00146   } } while (false);
00147   
00148   // input primary vetex (optional, can be "nominal" or "beamspot")
00149   reco::Vertex vertex;
00150   Handle<reco::VertexCollection> h_primaryVertex;
00151   if (m_primaryVertex.label() == "nominal") {
00152     vertex = s_nominalBeamSpot;
00153   } else
00154   if (m_primaryVertex.label() == "beamspot") {
00155     edm::Handle<reco::BeamSpot> recoBeamSpotHandle;
00156     event.getByType(recoBeamSpotHandle);
00157     vertex = reco::Vertex(recoBeamSpotHandle->position(), recoBeamSpotHandle->covariance3D(), 1, 1, 0);
00158   } else {
00159     event.getByLabel(m_primaryVertex, h_primaryVertex);
00160     if (h_primaryVertex->size()) {
00161       vertex = h_primaryVertex->front();
00162     } else {
00163       // fall back to nominal beam spot
00164       vertex = s_nominalBeamSpot;
00165     }
00166   }
00167 
00168   // input leptons (can be of different types)
00169   ProductID leptons_id;
00170   std::vector<edm::RefToBase<reco::Track> > leptons;
00171   // try to access the input collection as a collection of Electrons, Muons or Tracks
00172   do { {
00173     // look for vector<Electron>
00174     Handle<reco::ElectronCollection> h_electrons;
00175     event.getByLabel(m_leptons, h_electrons);
00176     if (h_electrons.isValid()) {
00177       for (reco::ElectronCollection::const_iterator electron = h_electrons->begin(); electron != h_electrons->end(); ++electron)
00178         leptons.push_back(edm::RefToBase<reco::Track>( electron->track() ));
00179       break;
00180     }
00181   } { // else
00182     // look for vector<GsfElectron>
00183     Handle<reco::GsfElectronCollection> h_electrons;
00184     event.getByLabel(m_leptons, h_electrons);
00185     if (h_electrons.isValid()) {
00186       for (reco::GsfElectronCollection::const_iterator electron = h_electrons->begin(); electron != h_electrons->end(); ++electron)
00187         leptons.push_back(edm::RefToBase<reco::Track>( electron->gsfTrack() ));
00188       break;
00189     }
00190   } { // else
00191     // look for vetor<Muon>
00192     Handle<reco::MuonCollection> h_muons;
00193     event.getByLabel(m_leptons, h_muons);
00194     if (h_muons.isValid()) {
00195       for (reco::MuonCollection::const_iterator muon = h_muons->begin(); muon != h_muons->end(); ++muon) {
00196         if (muon->isGlobalMuon())
00197           leptons.push_back(edm::RefToBase<reco::Track>( muon->globalTrack() ));
00198         else 
00199         if (muon->isTrackerMuon() and muon->caloCompatibility() > m_qualityCut)
00200           leptons.push_back(edm::RefToBase<reco::Track>( muon->innerTrack() ));
00201       }
00202       break;
00203     }
00204   } { // else
00205     // look for edm::View<Track> 
00206     Handle<edm::View<reco::Track> > h_tracks;
00207     event.getByLabel(m_leptons, h_tracks);
00208     if (h_tracks.isValid()) {
00209       for (unsigned int i = 0; i < h_tracks->size(); i++)
00210         leptons.push_back(h_tracks->refAt(i));
00211       break;
00212     }
00213   } { // else
00214     throw edm::Exception(edm::errors::NotFound) << "Object " << m_leptons << " of type among (\"reco::ElectronCollection\", \"reco::GsfElectronCollection\", \"reco::MuonCollection\", \"edm::View<reco::Track>\") not found";
00215   } } while (false);
00216 
00217   // output collections
00218   std::auto_ptr<reco::SoftLeptonTagInfoCollection> outputCollection(  new reco::SoftLeptonTagInfoCollection() );
00219   for (unsigned int i = 0; i < jets.size(); ++i) {
00220     reco::SoftLeptonTagInfo result = tag( jets[i], tracks[i], leptons, vertex );
00221     outputCollection->push_back( result );
00222   }
00223   event.put( outputCollection );
00224 }
00225 
00226 // ------------ method called once each job just before starting event loop  -------------
00227 void 
00228 SoftLepton::beginJob(const edm::EventSetup & setup) {
00229 }
00230 
00231 // ------------ method called once each job just after ending the event loop  ------------
00232 void 
00233 SoftLepton::endJob(void) {
00234 }
00235 
00236 // ---------------------------------------------------------------------------------------
00237 reco::SoftLeptonTagInfo SoftLepton::tag (
00238     const edm::RefToBase<reco::Jet> & jet,
00239     const reco::TrackRefVector      & tracks,
00240     const std::vector<edm::RefToBase<reco::Track> > & leptons,
00241     const reco::Vertex              & primaryVertex
00242 ) const {
00243   reco::SoftLeptonTagInfo info;
00244   info.setJetRef( jet );
00245 
00246   for (unsigned int i = 0; i < leptons.size(); i++) {
00247     const edm::RefToBase<reco::Track> & lepton = leptons[i];
00248     const math::XYZVector & lepton_momentum = lepton->momentum();
00249     if ((m_chi2Cut > 0.0) and (lepton->normalizedChi2() > m_chi2Cut))
00250       continue;
00251 
00252     const GlobalVector jetAxis = refineJetAxis( jet, tracks, lepton );
00253     const math::XYZVector axis( jetAxis.x(), jetAxis.y(), jetAxis.z());
00254     if (DeltaR(lepton_momentum, axis) > m_deltaRCut)
00255       continue;
00256 
00257     reco::SoftLeptonProperties properties;
00258 
00259     const reco::TransientTrack transientTrack = m_transientTrackBuilder->build(*lepton);
00260     properties.sip2d    = IPTools::signedTransverseImpactParameter( transientTrack, jetAxis, primaryVertex ).second.significance();
00261     properties.sip3d    = IPTools::signedImpactParameter3D( transientTrack, jetAxis, primaryVertex ).second.significance();
00262     properties.deltaR   = DeltaR( lepton_momentum, axis );
00263     properties.ptRel    = Perp( lepton_momentum, axis );
00264     properties.p0Par    = boostedPPar( lepton_momentum, axis );
00265     properties.etaRel   = relativeEta( lepton_momentum, axis );
00266     properties.ratio    = lepton_momentum.R() / axis.R();
00267     properties.ratioRel = lepton_momentum.Dot(axis) / axis.Mag2();
00268     info.insert( lepton, properties );
00269   }
00270 
00271   return info;
00272 }
00273 
00274 
00275 // ---------------------------------------------------------------------------------------
00276 GlobalVector SoftLepton::refineJetAxis (
00277     const edm::RefToBase<reco::Jet>   & jet,
00278     const reco::TrackRefVector        & tracks,
00279     const edm::RefToBase<reco::Track> & exclude /* = edm::RefToBase<reco::Track>() */
00280 ) const {
00281   math::XYZVector axis = jet->momentum();
00282 
00283   if (m_refineJetAxis == AXIS_CHARGED_AVERAGE or
00284       m_refineJetAxis == AXIS_CHARGED_AVERAGE_NOLEPTON) {
00285 
00286     double sum_pT        = 0.;
00287     double sum_eta_by_pT = 0.;
00288     double sum_phi_by_pT = 0.;
00289 
00290     double perp;
00291     double phi_rel;
00292     double eta_rel;
00293 
00294     // refine jet eta and phi with charged tracks measurements, if available
00295     for (reco::TrackRefVector::const_iterator track_it = tracks.begin(); track_it != tracks.end(); ++track_it ) {
00296       const reco::Track & track = **track_it;
00297 
00298       perp = track.pt();
00299       eta_rel = (double) track.eta() - axis.eta();
00300       phi_rel = (double) track.phi() - axis.phi();
00301       while (phi_rel < -M_PI) phi_rel += 2*M_PI;
00302       while (phi_rel >  M_PI) phi_rel -= 2*M_PI;
00303 
00304       sum_pT        += perp;
00305       sum_phi_by_pT += perp * phi_rel;
00306       sum_eta_by_pT += perp * eta_rel;
00307     }
00308 
00309     // "remove" excluded track
00310     if (m_refineJetAxis == AXIS_CHARGED_AVERAGE_NOLEPTON and exclude.isNonnull()) {
00311       const reco::Track & track = *exclude;
00312 
00313       perp = track.pt();
00314       eta_rel = (double) track.eta() - axis.eta();
00315       phi_rel = (double) track.phi() - axis.phi();
00316       while (phi_rel < -M_PI) phi_rel += 2*M_PI;
00317       while (phi_rel >  M_PI) phi_rel -= 2*M_PI;
00318 
00319       sum_pT        -= perp;
00320       sum_phi_by_pT -= perp * phi_rel;
00321       sum_eta_by_pT -= perp * eta_rel;
00322     }
00323 
00324     if (sum_pT > 1.)    // avoid the case of only the lepton-track with small rounding errors
00325       axis = math::RhoEtaPhiVector( axis.rho(), axis.eta() + sum_eta_by_pT / sum_pT, axis.phi() + sum_phi_by_pT / sum_pT);
00326     
00327   } else if (m_refineJetAxis == AXIS_CHARGED_SUM or
00328              m_refineJetAxis == AXIS_CHARGED_SUM_NOLEPTON) {
00329     math::XYZVector sum;
00330 
00331     // recalculate the jet direction as the sum of charget tracks momenta
00332     for (reco::TrackRefVector::const_iterator track_it = tracks.begin(); track_it != tracks.end(); ++track_it ) {
00333       const reco::Track & track = **track_it;
00334       sum += track.momentum();
00335     }
00336 
00337     // "remove" excluded track
00338     if (m_refineJetAxis == AXIS_CHARGED_SUM_NOLEPTON and exclude.isNonnull()) {
00339       const reco::Track & track = *exclude;
00340       sum -= track.momentum();
00341     }
00342 
00343     if (sum.R() > 1.) // avoid the case of only the lepton-track with small rounding errors
00344       axis = sum;
00345   }
00346   
00347   return GlobalVector(axis.x(), axis.y(), axis.z());
00348 }
00349 
00350 double SoftLepton::relativeEta(const math::XYZVector& vector, const math::XYZVector& axis) {
00351   double mag = vector.r() * axis.r();
00352   double dot = vector.Dot(axis); 
00353   return -log((mag - dot)/(mag + dot)) / 2;
00354 }
00355 
00356 // compute the lepton momentum along the jet axis, in the jet rest frame
00357 double SoftLepton::boostedPPar(const math::XYZVector& vector, const math::XYZVector& axis) {
00358   static const double lepton_mass = 0.00;       // assume a massless (ultrarelativistic) lepton
00359   static const double jet_mass    = 5.279;      // use B±/B0 mass as the jet rest mass [PDG 2007 updates]
00360   ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> > lepton(vector.Dot(axis) / axis.r(), Perp(vector, axis), 0., lepton_mass);
00361   ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> > jet( axis.r(), 0., 0., jet_mass );
00362   ROOT::Math::BoostX boost( -jet.Beta() );
00363   return boost(lepton).x();
00364 } 

Generated on Tue Jun 9 17:43:06 2009 for CMSSW by  doxygen 1.5.4