00001
00002
00003
00004
00005
00013
00014
00015
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
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,
00066 AXIS_CHARGED_AVERAGE = 1,
00067 AXIS_CHARGED_AVERAGE_NOLEPTON = 2,
00068 AXIS_CHARGED_SUM = 3,
00069 AXIS_CHARGED_SUM_NOLEPTON = 4
00070 };
00071
00072 using namespace std;
00073 using namespace edm;
00074 using namespace reco;
00075 using namespace ROOT::Math::VectorUtil;
00076
00077
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,
00081 0.0, 0.0015 * 0.0015,
00082 0.0, 0.0, 15. * 15. ) ),
00083 1, 1, 0 );
00084
00085
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
00100 SoftLepton::~SoftLepton(void) {
00101 }
00102
00103
00104 void
00105 SoftLepton::produce(edm::Event & event, const edm::EventSetup & setup) {
00106
00107
00108 edm::ESHandle<TransientTrackBuilder> builder;
00109 setup.get<TransientTrackRecord>().get( "TransientTrackBuilder", builder );
00110 m_transientTrackBuilder = builder.product();
00111
00112
00113
00114
00115 ProductID jets_id;
00116 std::vector<edm::RefToBase<reco::Jet> > jets;
00117 std::vector<reco::TrackRefVector> tracks;
00118 do { {
00119
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 } {
00133
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 } {
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
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
00164 vertex = s_nominalBeamSpot;
00165 }
00166 }
00167
00168
00169 ProductID leptons_id;
00170 std::vector<edm::RefToBase<reco::Track> > leptons;
00171
00172 do { {
00173
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 } {
00182
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 } {
00191
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 } {
00205
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 } {
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
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
00227 void
00228 SoftLepton::beginJob(const edm::EventSetup & setup) {
00229 }
00230
00231
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
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
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
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.)
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
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
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.)
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
00357 double SoftLepton::boostedPPar(const math::XYZVector& vector, const math::XYZVector& axis) {
00358 static const double lepton_mass = 0.00;
00359 static const double jet_mass = 5.279;
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 }