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 #include "DataFormats/Common/interface/ValueMap.h"
00034
00035
00036 #include "DataFormats/Math/interface/LorentzVector.h"
00037 #include "DataFormats/Math/interface/Vector3D.h"
00038 #include "Math/GenVector/PxPyPzM4D.h"
00039 #include "Math/GenVector/VectorUtil.h"
00040 #include "Math/GenVector/Boost.h"
00041
00042 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
00043 #include "DataFormats/VertexReco/interface/Vertex.h"
00044 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00045 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00046 #include "DataFormats/TrackReco/interface/Track.h"
00047 #include "DataFormats/MuonReco/interface/Muon.h"
00048 #include "DataFormats/MuonReco/interface/MuonFwd.h"
00049 #include "DataFormats/MuonReco/interface/MuonSelectors.h"
00050 #include "DataFormats/EgammaCandidates/interface/Electron.h"
00051 #include "DataFormats/EgammaCandidates/interface/ElectronFwd.h"
00052 #include "DataFormats/EgammaCandidates/interface/GsfElectron.h"
00053 #include "DataFormats/EgammaCandidates/interface/GsfElectronFwd.h"
00054 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00055 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00056 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateFwd.h"
00057 #include "DataFormats/JetReco/interface/Jet.h"
00058 #include "DataFormats/JetReco/interface/JetTracksAssociation.h"
00059 #include "DataFormats/BTauReco/interface/SoftLeptonTagInfo.h"
00060
00061 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00062 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00063 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00064 #include "TrackingTools/IPTools/interface/IPTools.h"
00065 #include "SoftLepton.h"
00066
00067 enum AxisType {
00068 AXIS_CALORIMETRIC = 0,
00069 AXIS_CHARGED_AVERAGE = 1,
00070 AXIS_CHARGED_AVERAGE_NOLEPTON = 2,
00071 AXIS_CHARGED_SUM = 3,
00072 AXIS_CHARGED_SUM_NOLEPTON = 4,
00073 AXIS_CALORIMETRIC_NOLEPTON = 5
00074 };
00075
00076 using namespace std;
00077 using namespace edm;
00078 using namespace reco;
00079 using namespace ROOT::Math::VectorUtil;
00080
00081 typedef edm::View<reco::GsfElectron> GsfElectronView;
00082 typedef edm::View<reco::Electron> ElectronView;
00083 typedef edm::View<reco::Muon> MuonView;
00084
00085
00086 const reco::Vertex SoftLepton::s_nominalBeamSpot(
00087 reco::Vertex::Point( 0, 0, 0 ),
00088 reco::Vertex::Error( ROOT::Math::SVector<double,6>( 0.0015 * 0.0015,
00089 0.0, 0.0015 * 0.0015,
00090 0.0, 0.0, 15. * 15. ) ),
00091 1, 1, 0 );
00092
00093
00094 SoftLepton::SoftLepton(const edm::ParameterSet & iConfig) :
00095 m_jets( iConfig.getParameter<edm::InputTag>( "jets" ) ),
00096 m_primaryVertex( iConfig.getParameter<edm::InputTag>( "primaryVertex" ) ),
00097 m_leptons( iConfig.getParameter<edm::InputTag>( "leptons" ) ),
00098 m_leptonCands( iConfig.exists("leptonCands") ? iConfig.getParameter<edm::InputTag>( "leptonCands" ) : edm::InputTag() ),
00099 m_leptonId( iConfig.exists("leptonId") ? iConfig.getParameter<edm::InputTag>( "leptonId" ) : edm::InputTag() ),
00100 m_transientTrackBuilder( 0 ),
00101 m_refineJetAxis( iConfig.getParameter<unsigned int>( "refineJetAxis" ) ),
00102 m_deltaRCut( iConfig.getParameter<double>( "leptonDeltaRCut" ) ),
00103 m_chi2Cut( iConfig.getParameter<double>( "leptonChi2Cut" ) ),
00104 m_muonSelection( (muon::SelectionType) iConfig.getParameter<unsigned int>( "muonSelection" ) )
00105 {
00106 produces<reco::SoftLeptonTagInfoCollection>();
00107 }
00108
00109
00110 SoftLepton::~SoftLepton(void) {
00111 }
00112
00113
00114 void
00115 SoftLepton::produce(edm::Event & event, const edm::EventSetup & setup) {
00116
00117
00118 edm::ESHandle<TransientTrackBuilder> builder;
00119 setup.get<TransientTrackRecord>().get( "TransientTrackBuilder", builder );
00120 m_transientTrackBuilder = builder.product();
00121
00122
00123
00124
00125 ProductID jets_id;
00126 std::vector<edm::RefToBase<reco::Jet> > jets;
00127 std::vector<reco::TrackRefVector> tracks;
00128 do { {
00129
00130 edm::Handle<reco::JetTracksAssociationCollection> h_jtas;
00131 event.getByLabel(m_jets, h_jtas);
00132 if (h_jtas.isValid()) {
00133 unsigned int size = h_jtas->size();
00134 jets.resize(size);
00135 tracks.resize(size);
00136 for (unsigned int i = 0; i < size; ++i) {
00137 jets[i] = (*h_jtas)[i].first;
00138 tracks[i] = (*h_jtas)[i].second;
00139 }
00140 break;
00141 }
00142 } {
00143
00144 edm::Handle<edm::View<reco::Jet> > h_jets;
00145 event.getByLabel(m_jets, h_jets);
00146 if (h_jets.isValid()) {
00147 unsigned int size = h_jets->size();
00148 jets.resize(size);
00149 tracks.resize(size);
00150 for (unsigned int i = 0; i < h_jets->size(); i++)
00151 jets[i] = h_jets->refAt(i);
00152 break;
00153 }
00154 } {
00155 throw edm::Exception(edm::errors::NotFound) << "Object " << m_jets << " of type among (\"reco::JetTracksAssociationCollection\", \"edm::View<reco::Jet>\") not found";
00156 } } while (false);
00157
00158
00159 reco::Vertex vertex;
00160 Handle<reco::VertexCollection> h_primaryVertex;
00161 event.getByLabel(m_primaryVertex, h_primaryVertex);
00162 if (h_primaryVertex.isValid() and not h_primaryVertex->empty())
00163 vertex = h_primaryVertex->front();
00164 else
00165
00166 vertex = s_nominalBeamSpot;
00167
00168
00169 Leptons leptons;
00170
00171 Handle< ValueMap<float> > h_leptonCands;
00172 bool haveLeptonCands = !(m_leptonCands == edm::InputTag());
00173 if (haveLeptonCands)
00174 event.getByLabel(m_leptonCands, h_leptonCands);
00175
00176
00177
00178 unsigned int leptonId = SoftLeptonProperties::quality::leptonId;
00179 do { {
00180
00181 Handle<GsfElectronView> h_electrons;
00182 event.getByLabel(m_leptons, h_electrons);
00183
00184 if (h_electrons.isValid()) {
00185 leptonId = SoftLeptonProperties::quality::egammaElectronId;
00186 for (GsfElectronView::const_iterator electron = h_electrons->begin(); electron != h_electrons->end(); ++electron) {
00187 LeptonIds &id = leptons[reco::TrackBaseRef(electron->gsfTrack())];
00188 id[SoftLeptonProperties::quality::pfElectronId] = electron->mva();
00189 if (haveLeptonCands)
00190 id[SoftLeptonProperties::quality::btagElectronCands] = (*h_leptonCands)[h_electrons->refAt(electron - h_electrons->begin())];
00191 }
00192 break;
00193 }
00194 } {
00195
00196
00197 Handle<ElectronView> h_electrons;
00198 event.getByLabel(m_leptons, h_electrons);
00199 if (h_electrons.isValid()) {
00200 leptonId = SoftLeptonProperties::quality::egammaElectronId;
00201 for (ElectronView::const_iterator electron = h_electrons->begin(); electron != h_electrons->end(); ++electron) {
00202 LeptonIds &id = leptons[reco::TrackBaseRef(electron->track())];
00203 if (haveLeptonCands)
00204 id[SoftLeptonProperties::quality::btagElectronCands] = (*h_leptonCands)[h_electrons->refAt(electron - h_electrons->begin())];
00205 }
00206 break;
00207 }
00208 } {
00209
00210
00211 Handle<reco::PFCandidateCollection> h_electrons;
00212 event.getByLabel(m_leptons, h_electrons);
00213 if (h_electrons.isValid()) {
00214 leptonId = SoftLeptonProperties::quality::egammaElectronId;
00215 for (reco::PFCandidateCollection::const_iterator electron = h_electrons->begin(); electron != h_electrons->end(); ++electron) {
00216 LeptonIds *id;
00217 if (electron->gsfTrackRef().isNonnull())
00218 id = &leptons[reco::TrackBaseRef(electron->gsfTrackRef())];
00219 else if (electron->trackRef().isNonnull())
00220 id = &leptons[reco::TrackBaseRef(electron->trackRef())];
00221 else
00222 continue;
00223 (*id)[SoftLeptonProperties::quality::pfElectronId] = electron->mva_e_pi();
00224 if (haveLeptonCands)
00225 (*id)[SoftLeptonProperties::quality::btagElectronCands] = (*h_leptonCands)[reco::PFCandidateRef(h_electrons, electron - h_electrons->begin())];
00226 }
00227 break;
00228 }
00229 } {
00230
00231 Handle<MuonView> h_muons;
00232 event.getByLabel(m_leptons, h_muons);
00233 if (h_muons.isValid()) {
00234 for (MuonView::const_iterator muon = h_muons->begin(); muon != h_muons->end(); ++muon) {
00235
00236 if (muon::isGoodMuon( *muon, m_muonSelection )) {
00237 LeptonIds *id;
00238 if (muon->globalTrack().isNonnull())
00239 id = &leptons[reco::TrackBaseRef(muon->globalTrack())];
00240 else if (muon->innerTrack().isNonnull())
00241 id = &leptons[reco::TrackBaseRef(muon->innerTrack())];
00242 else if (muon->outerTrack().isNonnull())
00243
00244 id = &leptons[reco::TrackBaseRef(muon->outerTrack())];
00245 else
00246 continue;
00247 if (haveLeptonCands)
00248 (*id)[SoftLeptonProperties::quality::btagMuonCands] = (*h_leptonCands)[h_muons->refAt(muon - h_muons->begin())];
00249 }
00250 }
00251 break;
00252 }
00253 } {
00254
00255 Handle<edm::View<reco::Track> > h_tracks;
00256 event.getByLabel(m_leptons, h_tracks);
00257 if (h_tracks.isValid()) {
00258 for (unsigned int i = 0; i < h_tracks->size(); i++) {
00259 LeptonIds &id = leptons[h_tracks->refAt(i)];
00260 if (haveLeptonCands)
00261 id[SoftLeptonProperties::quality::btagLeptonCands] = (*h_leptonCands)[h_tracks->refAt(i)];
00262 }
00263 break;
00264 }
00265 } {
00266 throw edm::Exception(edm::errors::NotFound) << "Object " << m_leptons << " of type among (\"edm::View<reco::GsfElectron>\", \"edm::View<reco::Muon>\", \"edm::View<reco::Track>\") !found";
00267 } } while (false);
00268
00269 if (!(m_leptonId == edm::InputTag())) {
00270 Handle< ValueMap<float> > h_leptonId;
00271 event.getByLabel(m_leptonId, h_leptonId);
00272
00273 for (Leptons::iterator lepton = leptons.begin(); lepton != leptons.end(); ++lepton)
00274 lepton->second[leptonId] = (*h_leptonId)[lepton->first];
00275 }
00276
00277
00278 std::auto_ptr<reco::SoftLeptonTagInfoCollection> outputCollection( new reco::SoftLeptonTagInfoCollection() );
00279 for (unsigned int i = 0; i < jets.size(); ++i) {
00280 reco::SoftLeptonTagInfo result = tag( jets[i], tracks[i], leptons, vertex );
00281 outputCollection->push_back( result );
00282 }
00283 event.put( outputCollection );
00284 }
00285
00286
00287 reco::SoftLeptonTagInfo SoftLepton::tag (
00288 const edm::RefToBase<reco::Jet> & jet,
00289 const reco::TrackRefVector & tracks,
00290 const Leptons & leptons,
00291 const reco::Vertex & primaryVertex
00292 ) const {
00293 reco::SoftLeptonTagInfo info;
00294 info.setJetRef( jet );
00295
00296 for(Leptons::const_iterator lepton = leptons.begin(); lepton != leptons.end(); ++lepton) {
00297 const math::XYZVector & lepton_momentum = lepton->first->momentum();
00298 if (m_chi2Cut > 0.0 && lepton->first->normalizedChi2() > m_chi2Cut)
00299 continue;
00300
00301 const GlobalVector jetAxis = refineJetAxis( jet, tracks, lepton->first );
00302 const math::XYZVector axis( jetAxis.x(), jetAxis.y(), jetAxis.z());
00303 if (DeltaR(lepton_momentum, axis) > m_deltaRCut)
00304 continue;
00305
00306 reco::SoftLeptonProperties properties;
00307
00308 reco::TransientTrack transientTrack = m_transientTrackBuilder->build(*lepton->first);
00309 properties.sip2d = IPTools::signedTransverseImpactParameter( transientTrack, jetAxis, primaryVertex ).second.significance();
00310 properties.sip3d = IPTools::signedImpactParameter3D( transientTrack, jetAxis, primaryVertex ).second.significance();
00311 properties.deltaR = DeltaR( lepton_momentum, axis );
00312 properties.ptRel = Perp( lepton_momentum, axis );
00313 properties.p0Par = boostedPPar( lepton_momentum, axis );
00314 properties.etaRel = relativeEta( lepton_momentum, axis );
00315 properties.ratio = lepton_momentum.R() / axis.R();
00316 properties.ratioRel = lepton_momentum.Dot(axis) / axis.Mag2();
00317
00318 for(LeptonIds::const_iterator iter = lepton->second.begin(); iter != lepton->second.end(); ++iter)
00319 properties.setQuality(static_cast<SoftLeptonProperties::quality::Generic>(iter->first), iter->second);
00320
00321 info.insert( lepton->first, properties );
00322 }
00323
00324 return info;
00325 }
00326
00327
00328
00329 GlobalVector SoftLepton::refineJetAxis (
00330 const edm::RefToBase<reco::Jet> & jet,
00331 const reco::TrackRefVector & tracks,
00332 const reco::TrackBaseRef & exclude
00333 ) const {
00334 math::XYZVector axis = jet->momentum();
00335
00336 if (m_refineJetAxis == AXIS_CHARGED_AVERAGE or
00337 m_refineJetAxis == AXIS_CHARGED_AVERAGE_NOLEPTON) {
00338
00339 double sum_pT = 0.;
00340 double sum_eta_by_pT = 0.;
00341 double sum_phi_by_pT = 0.;
00342
00343 double perp;
00344 double phi_rel;
00345 double eta_rel;
00346
00347
00348 for (reco::TrackRefVector::const_iterator track_it = tracks.begin(); track_it != tracks.end(); ++track_it ) {
00349 const reco::Track & track = **track_it;
00350
00351 perp = track.pt();
00352 eta_rel = (double) track.eta() - axis.eta();
00353 phi_rel = (double) track.phi() - axis.phi();
00354 while (phi_rel < -M_PI) phi_rel += 2*M_PI;
00355 while (phi_rel > M_PI) phi_rel -= 2*M_PI;
00356
00357 sum_pT += perp;
00358 sum_phi_by_pT += perp * phi_rel;
00359 sum_eta_by_pT += perp * eta_rel;
00360 }
00361
00362
00363 if (m_refineJetAxis == AXIS_CHARGED_AVERAGE_NOLEPTON and exclude.isNonnull()) {
00364 const reco::Track & track = *exclude;
00365
00366 perp = track.pt();
00367 eta_rel = (double) track.eta() - axis.eta();
00368 phi_rel = (double) track.phi() - axis.phi();
00369 while (phi_rel < -M_PI) phi_rel += 2*M_PI;
00370 while (phi_rel > M_PI) phi_rel -= 2*M_PI;
00371
00372 sum_pT -= perp;
00373 sum_phi_by_pT -= perp * phi_rel;
00374 sum_eta_by_pT -= perp * eta_rel;
00375 }
00376
00377 if (sum_pT > 1.)
00378 axis = math::RhoEtaPhiVector( axis.rho(), axis.eta() + sum_eta_by_pT / sum_pT, axis.phi() + sum_phi_by_pT / sum_pT);
00379
00380 } else if (m_refineJetAxis == AXIS_CHARGED_SUM or
00381 m_refineJetAxis == AXIS_CHARGED_SUM_NOLEPTON) {
00382 math::XYZVector sum;
00383
00384
00385 for (reco::TrackRefVector::const_iterator track_it = tracks.begin(); track_it != tracks.end(); ++track_it ) {
00386 const reco::Track & track = **track_it;
00387 sum += track.momentum();
00388 }
00389
00390
00391 if (m_refineJetAxis == AXIS_CHARGED_SUM_NOLEPTON and exclude.isNonnull()) {
00392 const reco::Track & track = *exclude;
00393 sum -= track.momentum();
00394 }
00395
00396 if (sum.R() > 1.)
00397 axis = sum;
00398 } else if(m_refineJetAxis == AXIS_CALORIMETRIC_NOLEPTON) {
00399 axis -= exclude->momentum();
00400 }
00401
00402 return GlobalVector(axis.x(), axis.y(), axis.z());
00403 }
00404
00405 double SoftLepton::relativeEta(const math::XYZVector& vector, const math::XYZVector& axis) {
00406 double mag = vector.r() * axis.r();
00407 double dot = vector.Dot(axis);
00408 return -log((mag - dot)/(mag + dot)) / 2;
00409 }
00410
00411
00412 double SoftLepton::boostedPPar(const math::XYZVector& vector, const math::XYZVector& axis) {
00413 static const double lepton_mass = 0.00;
00414 static const double jet_mass = 5.279;
00415 ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> > lepton(vector.Dot(axis) / axis.r(), Perp(vector, axis), 0., lepton_mass);
00416 ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> > jet( axis.r(), 0., 0., jet_mass );
00417 ROOT::Math::BoostX boost( -jet.Beta() );
00418 return boost(lepton).x();
00419 }