CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
List of all members | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes
JetFlavourClustering Class Reference

Clusters hadrons, partons, and jet contituents to determine the jet flavour. More...

#include <PhysicsTools/JetMCAlgos/plugins/JetFlavourClustering.cc>

Inheritance diagram for JetFlavourClustering:
edm::stream::EDProducer<> edm::stream::EDProducerBase edm::ProducerBase edm::EDConsumerBase edm::ProductRegistryHelper

Public Member Functions

 JetFlavourClustering (const edm::ParameterSet &)
 
 ~JetFlavourClustering ()
 
- Public Member Functions inherited from edm::stream::EDProducer<>
 EDProducer ()=default
 
- Public Member Functions inherited from edm::stream::EDProducerBase
 EDProducerBase ()
 
ModuleDescription const & moduleDescription () const
 
virtual ~EDProducerBase ()
 
- Public Member Functions inherited from edm::ProducerBase
void callWhenNewProductsRegistered (std::function< void(BranchDescription const &)> const &func)
 
 ProducerBase ()
 
void registerProducts (ProducerBase *, ProductRegistry *, ModuleDescription const &)
 
std::function< void(BranchDescription
const &)> 
registrationCallback () const
 used by the fwk to register list of products More...
 
virtual ~ProducerBase ()
 
- Public Member Functions inherited from edm::EDConsumerBase
std::vector< ConsumesInfoconsumesInfo () const
 
 EDConsumerBase ()
 
ProductHolderIndexAndSkipBit indexFrom (EDGetToken, BranchType, TypeID const &) const
 
void itemsMayGet (BranchType, std::vector< ProductHolderIndexAndSkipBit > &) const
 
void itemsToGet (BranchType, std::vector< ProductHolderIndexAndSkipBit > &) const
 
std::vector
< ProductHolderIndexAndSkipBit >
const & 
itemsToGetFromEvent () const
 
void labelsForToken (EDGetToken iToken, Labels &oLabels) const
 
void modulesDependentUpon (const std::string &iProcessName, std::vector< const char * > &oModuleLabels) const
 
void modulesWhoseProductsAreConsumed (std::vector< ModuleDescription const * > &modules, ProductRegistry const &preg, std::map< std::string, ModuleDescription const * > const &labelsToDesc, std::string const &processName) const
 
bool registeredToConsume (ProductHolderIndex, bool, BranchType) const
 
bool registeredToConsumeMany (TypeID const &, BranchType) const
 
void updateLookup (BranchType iBranchType, ProductHolderIndexHelper const &)
 
virtual ~EDConsumerBase ()
 

Static Public Member Functions

static void fillDescriptions (edm::ConfigurationDescriptions &descriptions)
 
- Static Public Member Functions inherited from edm::stream::EDProducerBase
static const std::string & baseType ()
 
static void fillDescriptions (ConfigurationDescriptions &descriptions)
 
static void prevalidate (ConfigurationDescriptions &descriptions)
 

Private Member Functions

void assignToSubjets (const reco::GenParticleRefVector &clusteredParticles, const edm::Handle< edm::View< reco::Jet > > &subjets, const std::vector< int > &subjetIndices, std::vector< reco::GenParticleRefVector > &assignedParticles)
 
void insertGhosts (const edm::Handle< reco::GenParticleRefVector > &particles, const double ghostRescaling, const bool isHadron, const bool isbHadron, const bool isParton, const bool isLepton, std::vector< fastjet::PseudoJet > &constituents)
 
void matchGroomedJets (const edm::Handle< edm::View< reco::Jet > > &jets, const edm::Handle< edm::View< reco::Jet > > &matchedJets, std::vector< int > &matchedIndices)
 
void matchReclusteredJets (const edm::Handle< edm::View< reco::Jet > > &jets, const std::vector< fastjet::PseudoJet > &matchedJets, std::vector< int > &matchedIndices)
 
void matchSubjets (const std::vector< int > &groomedIndices, const edm::Handle< edm::View< reco::Jet > > &groomedJets, const edm::Handle< edm::View< reco::Jet > > &subjets, std::vector< std::vector< int > > &matchedIndices)
 
virtual void produce (edm::Event &, const edm::EventSetup &)
 
void setFlavours (const reco::GenParticleRefVector &clusteredbHadrons, const reco::GenParticleRefVector &clusteredcHadrons, const reco::GenParticleRefVector &clusteredPartons, int &hadronFlavour, int &partonFlavour)
 

Private Attributes

const edm::EDGetTokenT
< reco::GenParticleRefVector
bHadronsToken_
 
const edm::EDGetTokenT
< reco::GenParticleRefVector
cHadronsToken_
 
ClusterSequencePtr fjClusterSeq_
 
JetDefPtr fjJetDefinition_
 
const double ghostRescaling_
 
const edm::EDGetTokenT
< edm::View< reco::Jet > > 
groomedJetsToken_
 
const bool hadronFlavourHasPriority_
 
const std::string jetAlgorithm_
 
const double jetPtMin_
 
const edm::EDGetTokenT
< edm::View< reco::Jet > > 
jetsToken_
 
const edm::EDGetTokenT
< reco::GenParticleRefVector
leptonsToken_
 
const edm::EDGetTokenT
< reco::GenParticleRefVector
partonsToken_
 
const double relPtTolerance_
 
const double rParam_
 
const edm::EDGetTokenT
< edm::View< reco::Jet > > 
subjetsToken_
 
const bool useLeptons_
 
const bool useSubjets_
 

Additional Inherited Members

- Public Types inherited from edm::stream::EDProducer<>
typedef CacheContexts< T...> CacheTypes
 
typedef CacheTypes::GlobalCache GlobalCache
 
typedef AbilityChecker< T...> HasAbility
 
typedef
CacheTypes::LuminosityBlockCache 
LuminosityBlockCache
 
typedef
LuminosityBlockContextT
< LuminosityBlockCache,
RunCache, GlobalCache
LuminosityBlockContext
 
typedef
CacheTypes::LuminosityBlockSummaryCache 
LuminosityBlockSummaryCache
 
typedef CacheTypes::RunCache RunCache
 
typedef RunContextT< RunCache,
GlobalCache
RunContext
 
typedef CacheTypes::RunSummaryCache RunSummaryCache
 
- Public Types inherited from edm::stream::EDProducerBase
typedef EDProducerAdaptorBase ModuleType
 
- Public Types inherited from edm::ProducerBase
typedef
ProductRegistryHelper::TypeLabelList 
TypeLabelList
 
- Public Types inherited from edm::EDConsumerBase
typedef ProductLabels Labels
 
- Protected Member Functions inherited from edm::EDConsumerBase
template<typename ProductType , BranchType B = InEvent>
EDGetTokenT< ProductType > consumes (edm::InputTag const &tag)
 
EDGetToken consumes (const TypeToGet &id, edm::InputTag const &tag)
 
template<BranchType B>
EDGetToken consumes (TypeToGet const &id, edm::InputTag const &tag)
 
ConsumesCollector consumesCollector ()
 Use a ConsumesCollector to gather consumes information from helper functions. More...
 
template<typename ProductType , BranchType B = InEvent>
void consumesMany ()
 
void consumesMany (const TypeToGet &id)
 
template<BranchType B>
void consumesMany (const TypeToGet &id)
 
template<typename ProductType , BranchType B = InEvent>
EDGetTokenT< ProductType > mayConsume (edm::InputTag const &tag)
 
EDGetToken mayConsume (const TypeToGet &id, edm::InputTag const &tag)
 
template<BranchType B>
EDGetToken mayConsume (const TypeToGet &id, edm::InputTag const &tag)
 

Detailed Description

Clusters hadrons, partons, and jet contituents to determine the jet flavour.

This producer clusters hadrons, partons and jet contituents to determine the jet flavour. The jet flavour information is stored in the event as an AssociationVector which associates an object of type JetFlavorInfo to each of the jets.

The producer takes as input jets and hadron and partons selected by the HadronAndPartonSelector producer. The hadron and parton four-momenta are rescaled by a very small number (default rescale factor is 10e-18) which turns them into the so-called "ghosts". The "ghost" hadrons and partons are clustered together with all of the jet constituents. It is important to use the same clustering algorithm and jet size as for the original input jet collection. Since the "ghost" hadrons and partons are extremely soft, the resulting jet collection will be practically identical to the original one but now with "ghost" hadrons and partons clustered inside jets. The jet flavour is determined based on the "ghost" hadrons clustered inside a jet:

To further assign a more specific flavour to light-flavour jets, "ghost" partons are used:

In rare instances a conflict between the hadron- and parton-based flavours can occur. In such cases it is possible to keep both flavours or to give priority to the hadron-based flavour. This is controlled by the 'hadronFlavourHasPriority' switch which is enabled by default. The priority is given to the hadron-based flavour as follows:

The producer is also capable of assigning the flavor to subjets of fat jets, in which case it produces an additional AssociationVector providing the flavour information for subjets. In order to assign the flavor to subjets, three input jet collections are required:

The "ghost" hadrons and partons clustered inside a fat jet are assigned to the closest subjet in the rapidity-phi space. Once hadrons and partons have been assigned to subjets, the subjet flavor is determined in the same way as for jets. The reason for requiring three jet collections as input in order to determine the subjet flavour is to avoid possible inconsistencies between the fat jet and subjet flavours (such as a non-b fat jet having a b subjet and vice versa) as well as the fact that reclustering the constituents of groomed fat jets will generally result in a jet collection different from the input groomed fat jets.

In addition, "ghost" leptons can also be clustered inside jets but they are not used in any way to determine the jet flavor. This functionality is disabled by default.

For more details, please refer to https://twiki.cern.ch/twiki/bin/view/CMSPublic/SWGuideBTagMCTools

Definition at line 139 of file JetFlavourClustering.cc.

Constructor & Destructor Documentation

JetFlavourClustering::JetFlavourClustering ( const edm::ParameterSet iConfig)
explicit

Definition at line 205 of file JetFlavourClustering.cc.

References Exception, fjJetDefinition_, jetAlgorithm_, rParam_, and useSubjets_.

205  :
206 
208  groomedJetsToken_(mayConsume<edm::View<reco::Jet> >( iConfig.exists("groomedJets") ? iConfig.getParameter<edm::InputTag>("groomedJets") : edm::InputTag() )),
209  subjetsToken_(mayConsume<edm::View<reco::Jet> >( iConfig.exists("subjets") ? iConfig.getParameter<edm::InputTag>("subjets") : edm::InputTag() )),
210  bHadronsToken_(consumes<reco::GenParticleRefVector>( iConfig.getParameter<edm::InputTag>("bHadrons") )),
211  cHadronsToken_(consumes<reco::GenParticleRefVector>( iConfig.getParameter<edm::InputTag>("cHadrons") )),
212  partonsToken_(consumes<reco::GenParticleRefVector>( iConfig.getParameter<edm::InputTag>("partons") )),
213  leptonsToken_(mayConsume<reco::GenParticleRefVector>( iConfig.exists("leptons") ? iConfig.getParameter<edm::InputTag>("leptons") : edm::InputTag() )),
214  jetAlgorithm_(iConfig.getParameter<std::string>("jetAlgorithm")),
215  rParam_(iConfig.getParameter<double>("rParam")),
216  jetPtMin_(0.), // hardcoded to 0. since we simply want to recluster all input jets which already had some PtMin applied
217  ghostRescaling_(iConfig.exists("ghostRescaling") ? iConfig.getParameter<double>("ghostRescaling") : 1e-18),
218  relPtTolerance_(iConfig.exists("relPtTolerance") ? iConfig.getParameter<double>("relPtTolerance") : 1e-03), // 0.1% relative difference in Pt should be sufficient to detect possible misconfigurations
219  hadronFlavourHasPriority_(iConfig.getParameter<bool>("hadronFlavourHasPriority")),
220  useSubjets_(iConfig.exists("groomedJets") && iConfig.exists("subjets")),
221  useLeptons_(iConfig.exists("leptons"))
222 
223 {
224  // register your products
225  produces<reco::JetFlavourInfoMatchingCollection>();
226  if( useSubjets_ )
227  produces<reco::JetFlavourInfoMatchingCollection>("SubJets");
228 
229  // set jet algorithm
230  if (jetAlgorithm_=="Kt")
231  fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(fastjet::kt_algorithm, rParam_) );
232  else if (jetAlgorithm_=="CambridgeAachen")
233  fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(fastjet::cambridge_algorithm, rParam_) );
234  else if (jetAlgorithm_=="AntiKt")
235  fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(fastjet::antikt_algorithm, rParam_) );
236  else
237  throw cms::Exception("InvalidJetAlgorithm") << "Jet clustering algorithm is invalid: " << jetAlgorithm_ << ", use CambridgeAachen | Kt | AntiKt" << std::endl;
238 }
T getParameter(std::string const &) const
boost::shared_ptr< fastjet::JetDefinition > JetDefPtr
bool exists(std::string const &parameterName) const
checks if a parameter exists
const edm::EDGetTokenT< reco::GenParticleRefVector > bHadronsToken_
const edm::EDGetTokenT< reco::GenParticleRefVector > partonsToken_
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
const edm::EDGetTokenT< reco::GenParticleRefVector > cHadronsToken_
const std::string jetAlgorithm_
const edm::EDGetTokenT< edm::View< reco::Jet > > groomedJetsToken_
const edm::EDGetTokenT< edm::View< reco::Jet > > jetsToken_
const edm::EDGetTokenT< reco::GenParticleRefVector > leptonsToken_
EDGetTokenT< ProductType > mayConsume(edm::InputTag const &tag)
const edm::EDGetTokenT< edm::View< reco::Jet > > subjetsToken_
JetFlavourClustering::~JetFlavourClustering ( )

Definition at line 241 of file JetFlavourClustering.cc.

242 {
243 
244  // do anything here that needs to be done at desctruction time
245  // (e.g. close files, deallocate resources etc.)
246 
247 }

Member Function Documentation

void JetFlavourClustering::assignToSubjets ( const reco::GenParticleRefVector clusteredParticles,
const edm::Handle< edm::View< reco::Jet > > &  subjets,
const std::vector< int > &  subjetIndices,
std::vector< reco::GenParticleRefVector > &  assignedParticles 
)
private

Definition at line 685 of file JetFlavourClustering.cc.

References edm::RefVector< C, T, F >::begin(), reco::deltaR2(), HLT_25ns14e33_v1_cff::distance, edm::RefVector< C, T, F >::end(), and phi.

Referenced by produce().

689 {
690  // loop over clustered particles and assign them to different subjets based on smallest dR
691  for(reco::GenParticleRefVector::const_iterator it = clusteredParticles.begin(); it != clusteredParticles.end(); ++it)
692  {
693  std::vector<double> dR2toSubjets;
694 
695  for(size_t sj=0; sj<subjetIndices.size(); ++sj)
696  dR2toSubjets.push_back( reco::deltaR2( (*it)->rapidity(), (*it)->phi(), subjets->at(subjetIndices.at(sj)).rapidity(), subjets->at(subjetIndices.at(sj)).phi() ) );
697 
698  // find the closest subjet
699  int closestSubjetIdx = std::distance( dR2toSubjets.begin(), std::min_element(dR2toSubjets.begin(), dR2toSubjets.end()) );
700 
701  assignedParticles.at(closestSubjetIdx).push_back( *it );
702  }
703 }
const_iterator end() const
Termination of iteration.
Definition: RefVector.h:255
const_iterator begin() const
Initialize an iterator over the RefVector.
Definition: RefVector.h:250
double deltaR2(const T1 &t1, const T2 &t2)
Definition: deltaR.h:36
const_reference at(size_type pos) const
void JetFlavourClustering::fillDescriptions ( edm::ConfigurationDescriptions descriptions)
static

Definition at line 707 of file JetFlavourClustering.cc.

References edm::ConfigurationDescriptions::addDefault(), and edm::ParameterSetDescription::setUnknown().

707  {
708  //The following says we do not know what parameters are allowed so do no validation
709  // Please change this to state exactly what you do use, even if it is no parameters
711  desc.setUnknown();
712  descriptions.addDefault(desc);
713 }
void addDefault(ParameterSetDescription const &psetDescription)
void JetFlavourClustering::insertGhosts ( const edm::Handle< reco::GenParticleRefVector > &  particles,
const double  ghostRescaling,
const bool  isHadron,
const bool  isbHadron,
const bool  isParton,
const bool  isLepton,
std::vector< fastjet::PseudoJet > &  constituents 
)
private

Definition at line 473 of file JetFlavourClustering.cc.

References AlCaHLTBitMon_ParallelJobs::p.

Referenced by produce().

477 {
478  // insert "ghost" particles in the vector of jet constituents
479  for(reco::GenParticleRefVector::const_iterator it = particles->begin(); it != particles->end(); ++it)
480  {
481  if((*it)->pt() == 0)
482  {
483  edm::LogInfo("NullTransverseMomentum") << "dropping input ghost candidate with pt=0";
484  continue;
485  }
486  fastjet::PseudoJet p((*it)->px(),(*it)->py(),(*it)->pz(),(*it)->energy());
487  p*=ghostRescaling; // rescale particle momentum
488  p.set_user_info(new GhostInfo(isHadron, isbHadron, isParton, isLepton, *it));
489  constituents.push_back(p);
490  }
491 }
bool isLepton(const Candidate &part)
Definition: pdgIdUtils.h:19
bool isParton(const reco::Candidate &c)
Definition: CandMCTag.cc:48
void JetFlavourClustering::matchGroomedJets ( const edm::Handle< edm::View< reco::Jet > > &  jets,
const edm::Handle< edm::View< reco::Jet > > &  matchedJets,
std::vector< int > &  matchedIndices 
)
private

Definition at line 537 of file JetFlavourClustering.cc.

References reco::deltaR2(), HLT_25ns14e33_v1_cff::distance, spr::find(), j, fwrapper::jets, rParam_, and mathSSE::sqrt().

Referenced by produce().

540 {
541  std::vector<bool> jetLocks(jets->size(),false);
542  std::vector<int> jetIndices;
543 
544  for(size_t gj=0; gj<groomedJets->size(); ++gj)
545  {
546  double matchedDR2 = 1e9;
547  int matchedIdx = -1;
548 
549  if( groomedJets->at(gj).pt()>0. ) // skip pathological cases of groomed jets with Pt=0
550  {
551  for(size_t j=0; j<jets->size(); ++j)
552  {
553  if( jetLocks.at(j) ) continue; // skip jets that have already been matched
554 
555  double tempDR2 = reco::deltaR2( jets->at(j).rapidity(), jets->at(j).phi(), groomedJets->at(gj).rapidity(), groomedJets->at(gj).phi() );
556  if( tempDR2 < matchedDR2 )
557  {
558  matchedDR2 = tempDR2;
559  matchedIdx = j;
560  }
561  }
562  }
563 
564  if( matchedIdx>=0 )
565  {
566  if ( matchedDR2 > rParam_*rParam_ )
567  {
568  edm::LogWarning("MatchedJetsFarApart") << "Matched groomed jet " << gj << " and original jet " << matchedIdx <<" are separated by dR=" << sqrt(matchedDR2) << " which is greater than the jet size R=" << rParam_ << ".\n"
569  << "This is not expected so the matching of these two jets has been discarded. Please check that the two jet collections belong to each other.";
570  matchedIdx = -1;
571  }
572  else
573  jetLocks.at(matchedIdx) = true;
574  }
575  jetIndices.push_back(matchedIdx);
576  }
577 
578  for(size_t j=0; j<jets->size(); ++j)
579  {
580  std::vector<int>::iterator matchedIndex = std::find( jetIndices.begin(), jetIndices.end(), j );
581 
582  matchedIndices.push_back( matchedIndex != jetIndices.end() ? std::distance(jetIndices.begin(),matchedIndex) : -1 );
583  }
584 }
size_type size() const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
T sqrt(T t)
Definition: SSEVec.h:48
int j
Definition: DBlmapReader.cc:9
double deltaR2(const T1 &t1, const T2 &t2)
Definition: deltaR.h:36
const_reference at(size_type pos) const
void JetFlavourClustering::matchReclusteredJets ( const edm::Handle< edm::View< reco::Jet > > &  jets,
const std::vector< fastjet::PseudoJet > &  matchedJets,
std::vector< int > &  matchedIndices 
)
private

Definition at line 495 of file JetFlavourClustering.cc.

References reco::deltaR2(), j, fwrapper::jets, rParam_, and mathSSE::sqrt().

Referenced by produce().

498 {
499  std::vector<bool> matchedLocks(reclusteredJets.size(),false);
500 
501  for(size_t j=0; j<jets->size(); ++j)
502  {
503  double matchedDR2 = 1e9;
504  int matchedIdx = -1;
505 
506  for(size_t rj=0; rj<reclusteredJets.size(); ++rj)
507  {
508  if( matchedLocks.at(rj) ) continue; // skip jets that have already been matched
509 
510  double tempDR2 = reco::deltaR2( jets->at(j).rapidity(), jets->at(j).phi(), reclusteredJets.at(rj).rapidity(), reclusteredJets.at(rj).phi_std() );
511  if( tempDR2 < matchedDR2 )
512  {
513  matchedDR2 = tempDR2;
514  matchedIdx = rj;
515  }
516  }
517 
518  if( matchedIdx>=0 )
519  {
520  if ( matchedDR2 > rParam_*rParam_ )
521  {
522  edm::LogError("JetMatchingFailed") << "Matched reclustered jet " << matchedIdx << " and original jet " << j <<" are separated by dR=" << sqrt(matchedDR2) << " which is greater than the jet size R=" << rParam_ << ".\n"
523  << "This is not expected so please check that the jet algorithm and jet size match those used for the original jet collection.";
524  }
525  else
526  matchedLocks.at(matchedIdx) = true;
527  }
528  else
529  edm::LogError("JetMatchingFailed") << "Matching reclustered to original jets failed. Please check that the jet algorithm and jet size match those used for the original jet collection.";
530 
531  matchedIndices.push_back(matchedIdx);
532  }
533 }
size_type size() const
T sqrt(T t)
Definition: SSEVec.h:48
int j
Definition: DBlmapReader.cc:9
double deltaR2(const T1 &t1, const T2 &t2)
Definition: deltaR.h:36
const_reference at(size_type pos) const
void JetFlavourClustering::matchSubjets ( const std::vector< int > &  groomedIndices,
const edm::Handle< edm::View< reco::Jet > > &  groomedJets,
const edm::Handle< edm::View< reco::Jet > > &  subjets,
std::vector< std::vector< int > > &  matchedIndices 
)
private

Definition at line 588 of file JetFlavourClustering.cc.

References g, and alignCSCRings::s.

Referenced by produce().

592 {
593  for(size_t g=0; g<groomedIndices.size(); ++g)
594  {
595  std::vector<int> subjetIndices;
596 
597  if( groomedIndices.at(g)>=0 )
598  {
599  for(size_t s=0; s<groomedJets->at(groomedIndices.at(g)).numberOfDaughters(); ++s)
600  {
601  const edm::Ptr<reco::Candidate> & subjet = groomedJets->at(groomedIndices.at(g)).daughterPtr(s);
602 
603  for(size_t sj=0; sj<subjets->size(); ++sj)
604  {
605  if( subjet == edm::Ptr<reco::Candidate>(subjets->ptrAt(sj)) )
606  {
607  subjetIndices.push_back(sj);
608  break;
609  }
610  }
611  }
612 
613  if( subjetIndices.size() == 0 )
614  edm::LogError("SubjetMatchingFailed") << "Matching subjets to original jets failed. Please check that the groomed jet and subjet collections belong to each other.";
615 
616  matchedIndices.push_back(subjetIndices);
617  }
618  else
619  matchedIndices.push_back(subjetIndices);
620  }
621 }
Ptr< value_type > ptrAt(size_type i) const
size_type size() const
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
const_reference at(size_type pos) const
void JetFlavourClustering::produce ( edm::Event iEvent,
const edm::EventSetup iSetup 
)
privatevirtual

Implements edm::stream::EDProducerBase.

Definition at line 256 of file JetFlavourClustering.cc.

References funct::abs(), assignToSubjets(), bHadronsToken_, cHadronsToken_, fjClusterSeq_, fjJetDefinition_, edm::Event::getByToken(), ghostRescaling_, groomedJetsToken_, i, insertGhosts(), GhostInfo::isbHadron(), GhostInfo::isHadron(), GhostInfo::isLepton(), GhostInfo::isParton(), jetPtMin_, fwrapper::jets, jetsToken_, HLT_25ns14e33_v1_cff::leptons, leptonsToken_, visualization-live-secondInstance_cfg::m, matchGroomedJets(), matchReclusteredJets(), matchSubjets(), GhostInfo::particleRef(), partonsToken_, EnergyCorrector::pt, edm::RefVector< C, T, F >::push_back(), edm::Event::put(), relPtTolerance_, setFlavours(), subjetsToken_, useLeptons_, and useSubjets_.

257 {
259  iEvent.getByToken(jetsToken_, jets);
260 
261  edm::Handle<edm::View<reco::Jet> > groomedJets;
263  if( useSubjets_ )
264  {
265  iEvent.getByToken(groomedJetsToken_, groomedJets);
266  iEvent.getByToken(subjetsToken_, subjets);
267  }
268 
270  iEvent.getByToken(bHadronsToken_, bHadrons);
271 
273  iEvent.getByToken(cHadronsToken_, cHadrons);
274 
276  iEvent.getByToken(partonsToken_, partons);
277 
279  if( useLeptons_ )
280  iEvent.getByToken(leptonsToken_, leptons);
281 
282  std::auto_ptr<reco::JetFlavourInfoMatchingCollection> jetFlavourInfos( new reco::JetFlavourInfoMatchingCollection(reco::JetRefBaseProd(jets)) );
283  std::auto_ptr<reco::JetFlavourInfoMatchingCollection> subjetFlavourInfos;
284  if( useSubjets_ )
285  subjetFlavourInfos = std::auto_ptr<reco::JetFlavourInfoMatchingCollection>( new reco::JetFlavourInfoMatchingCollection(reco::JetRefBaseProd(subjets)) );
286 
287  // vector of constituents for reclustering jets and "ghosts"
288  std::vector<fastjet::PseudoJet> fjInputs;
289  // loop over all input jets and collect all their constituents
290  for(edm::View<reco::Jet>::const_iterator it = jets->begin(); it != jets->end(); ++it)
291  {
292  std::vector<edm::Ptr<reco::Candidate> > constituents = it->getJetConstituents();
293  std::vector<edm::Ptr<reco::Candidate> >::const_iterator m;
294  for( m = constituents.begin(); m != constituents.end(); ++m )
295  {
296  reco::CandidatePtr constit = *m;
297  if(constit->pt() == 0)
298  {
299  edm::LogWarning("NullTransverseMomentum") << "dropping input candidate with pt=0";
300  continue;
301  }
302  fjInputs.push_back(fastjet::PseudoJet(constit->px(),constit->py(),constit->pz(),constit->energy()));
303  }
304  }
305  // insert "ghost" b hadrons in the vector of constituents
306  insertGhosts(bHadrons, ghostRescaling_, true, true, false, false, fjInputs);
307  // insert "ghost" c hadrons in the vector of constituents
308  insertGhosts(cHadrons, ghostRescaling_, true, false, false, false, fjInputs);
309  // insert "ghost" partons in the vector of constituents
310  insertGhosts(partons, ghostRescaling_, false, false, true, false, fjInputs);
311  // if used, insert "ghost" leptons in the vector of constituents
312  if( useLeptons_ )
313  insertGhosts(leptons, ghostRescaling_, false, false, false, true, fjInputs);
314 
315  // define jet clustering sequence
316  fjClusterSeq_ = ClusterSequencePtr( new fastjet::ClusterSequence( fjInputs, *fjJetDefinition_ ) );
317  // recluster jet constituents and inserted "ghosts"
318  std::vector<fastjet::PseudoJet> inclusiveJets = fastjet::sorted_by_pt( fjClusterSeq_->inclusive_jets(jetPtMin_) );
319 
320  if( inclusiveJets.size() < jets->size() )
321  edm::LogError("TooFewReclusteredJets") << "There are fewer reclustered (" << inclusiveJets.size() << ") than original jets (" << jets->size() << "). Please check that the jet algorithm and jet size match those used for the original jet collection.";
322 
323  // match reclustered and original jets
324  std::vector<int> reclusteredIndices;
325  matchReclusteredJets(jets,inclusiveJets,reclusteredIndices);
326 
327  // match groomed and original jets
328  std::vector<int> groomedIndices;
329  if( useSubjets_ )
330  {
331  if( groomedJets->size() > jets->size() )
332  edm::LogError("TooManyGroomedJets") << "There are more groomed (" << groomedJets->size() << ") than original jets (" << jets->size() << "). Please check that the two jet collections belong to each other.";
333 
334  matchGroomedJets(jets,groomedJets,groomedIndices);
335  }
336 
337  // match subjets and original jets
338  std::vector<std::vector<int> > subjetIndices;
339  if( useSubjets_ )
340  {
341  matchSubjets(groomedIndices,groomedJets,subjets,subjetIndices);
342  }
343 
344  // determine jet flavour
345  for(size_t i=0; i<jets->size(); ++i)
346  {
347  reco::GenParticleRefVector clusteredbHadrons;
348  reco::GenParticleRefVector clusteredcHadrons;
349  reco::GenParticleRefVector clusteredPartons;
350  reco::GenParticleRefVector clusteredLeptons;
351 
352  // if matching reclustered to original jets failed
353  if( reclusteredIndices.at(i) < 0 )
354  {
355  // set an empty JetFlavourInfo for this jet
356  (*jetFlavourInfos)[jets->refAt(i)] = reco::JetFlavourInfo(clusteredbHadrons, clusteredcHadrons, clusteredPartons, clusteredLeptons, 0, 0);
357  }
358  else if( jets->at(i).pt() == 0 )
359  {
360  edm::LogWarning("NullTransverseMomentum") << "The original jet " << i << " has Pt=0. This is not expected so the jet will be skipped.";
361 
362  // set an empty JetFlavourInfo for this jet
363  (*jetFlavourInfos)[jets->refAt(i)] = reco::JetFlavourInfo(clusteredbHadrons, clusteredcHadrons, clusteredPartons, clusteredLeptons, 0, 0);
364 
365  // if subjets are used
366  if( useSubjets_ && subjetIndices.at(i).size()>0 )
367  {
368  // loop over subjets
369  for(size_t sj=0; sj<subjetIndices.at(i).size(); ++sj)
370  {
371  // set an empty JetFlavourInfo for this subjet
372  (*subjetFlavourInfos)[subjets->refAt(subjetIndices.at(i).at(sj))] = reco::JetFlavourInfo(reco::GenParticleRefVector(), reco::GenParticleRefVector(), reco::GenParticleRefVector(), reco::GenParticleRefVector(), 0, 0);
373  }
374  }
375  }
376  else
377  {
378  // since the "ghosts" are extremely soft, the configuration and ordering of the reclustered and original jets should in principle stay the same
379  if( ( std::abs( inclusiveJets.at(reclusteredIndices.at(i)).pt() - jets->at(i).pt() ) / jets->at(i).pt() ) > relPtTolerance_ )
380  {
381  if( jets->at(i).pt() < 10. ) // special handling for low-Pt jets (Pt<10 GeV)
382  edm::LogWarning("JetPtMismatchAtLowPt") << "The reclustered and original jet " << i << " have different Pt's (" << inclusiveJets.at(reclusteredIndices.at(i)).pt() << " vs " << jets->at(i).pt() << " GeV, respectively).\n"
383  << "Please check that the jet algorithm and jet size match those used for the original jet collection and also make sure the original jets are uncorrected. In addition, make sure you are not using CaloJets which are presently not supported.\n"
384  << "Since the mismatch is at low Pt (Pt<10 GeV), it is ignored and only a warning is issued.\n"
385  << "\nIn extremely rare instances the mismatch could be caused by a difference in the machine precision in which case make sure the original jet collection is produced and reclustering is performed in the same job.";
386  else
387  edm::LogError("JetPtMismatch") << "The reclustered and original jet " << i << " have different Pt's (" << inclusiveJets.at(reclusteredIndices.at(i)).pt() << " vs " << jets->at(i).pt() << " GeV, respectively).\n"
388  << "Please check that the jet algorithm and jet size match those used for the original jet collection and also make sure the original jets are uncorrected. In addition, make sure you are not using CaloJets which are presently not supported.\n"
389  << "\nIn extremely rare instances the mismatch could be caused by a difference in the machine precision in which case make sure the original jet collection is produced and reclustering is performed in the same job.";
390  }
391 
392  // get jet constituents (sorted by Pt)
393  std::vector<fastjet::PseudoJet> constituents = fastjet::sorted_by_pt( inclusiveJets.at(reclusteredIndices.at(i)).constituents() );
394 
395  // loop over jet constituents and try to find "ghosts"
396  for(std::vector<fastjet::PseudoJet>::const_iterator it = constituents.begin(); it != constituents.end(); ++it)
397  {
398  if( !it->has_user_info() ) continue; // skip if not a "ghost"
399 
400  // "ghost" hadron
401  if( it->user_info<GhostInfo>().isHadron() )
402  {
403  // "ghost" b hadron
404  if( it->user_info<GhostInfo>().isbHadron() )
405  clusteredbHadrons.push_back(it->user_info<GhostInfo>().particleRef());
406  // "ghost" c hadron
407  else
408  clusteredcHadrons.push_back(it->user_info<GhostInfo>().particleRef());
409  }
410  // "ghost" parton
411  else if( it->user_info<GhostInfo>().isParton() )
412  clusteredPartons.push_back(it->user_info<GhostInfo>().particleRef());
413  // "ghost" lepton
414  else if( it->user_info<GhostInfo>().isLepton() )
415  clusteredLeptons.push_back(it->user_info<GhostInfo>().particleRef());
416  }
417 
418  int hadronFlavour = 0; // default hadron flavour set to 0 (= undefined)
419  int partonFlavour = 0; // default parton flavour set to 0 (= undefined)
420 
421  // set hadron- and parton-based flavours
422  setFlavours(clusteredbHadrons, clusteredcHadrons, clusteredPartons, hadronFlavour, partonFlavour);
423 
424  // set the JetFlavourInfo for this jet
425  (*jetFlavourInfos)[jets->refAt(i)] = reco::JetFlavourInfo(clusteredbHadrons, clusteredcHadrons, clusteredPartons, clusteredLeptons, hadronFlavour, partonFlavour);
426  }
427 
428  // if subjets are used, determine their flavour
429  if( useSubjets_ )
430  {
431  if( subjetIndices.at(i).size()==0 ) continue; // continue if the original jet does not have subjets assigned
432 
433  // define vectors of GenParticleRefVectors for hadrons and partons assigned to different subjets
434  std::vector<reco::GenParticleRefVector> assignedbHadrons(subjetIndices.at(i).size(),reco::GenParticleRefVector());
435  std::vector<reco::GenParticleRefVector> assignedcHadrons(subjetIndices.at(i).size(),reco::GenParticleRefVector());
436  std::vector<reco::GenParticleRefVector> assignedPartons(subjetIndices.at(i).size(),reco::GenParticleRefVector());
437  std::vector<reco::GenParticleRefVector> assignedLeptons(subjetIndices.at(i).size(),reco::GenParticleRefVector());
438 
439  // loop over clustered b hadrons and assign them to different subjets based on smallest dR
440  assignToSubjets(clusteredbHadrons, subjets, subjetIndices.at(i), assignedbHadrons);
441  // loop over clustered c hadrons and assign them to different subjets based on smallest dR
442  assignToSubjets(clusteredcHadrons, subjets, subjetIndices.at(i), assignedcHadrons);
443  // loop over clustered partons and assign them to different subjets based on smallest dR
444  assignToSubjets(clusteredPartons, subjets, subjetIndices.at(i), assignedPartons);
445  // if used, loop over clustered leptons and assign them to different subjets based on smallest dR
446  if( useLeptons_ )
447  assignToSubjets(clusteredLeptons, subjets, subjetIndices.at(i), assignedLeptons);
448 
449  // loop over subjets and determine their flavour
450  for(size_t sj=0; sj<subjetIndices.at(i).size(); ++sj)
451  {
452  int subjetHadronFlavour = 0; // default hadron flavour set to 0 (= undefined)
453  int subjetPartonFlavour = 0; // default parton flavour set to 0 (= undefined)
454 
455  // set hadron- and parton-based flavours
456  setFlavours(assignedbHadrons.at(sj), assignedcHadrons.at(sj), assignedPartons.at(sj), subjetHadronFlavour, subjetPartonFlavour);
457 
458  // set the JetFlavourInfo for this subjet
459  (*subjetFlavourInfos)[subjets->refAt(subjetIndices.at(i).at(sj))] = reco::JetFlavourInfo(assignedbHadrons.at(sj), assignedcHadrons.at(sj), assignedPartons.at(sj), assignedLeptons.at(sj), subjetHadronFlavour, subjetPartonFlavour);
460  }
461  }
462  }
463 
464  // put jet flavour infos in the event
465  iEvent.put( jetFlavourInfos );
466  // put subjet flavour infos in the event
467  if( useSubjets_ )
468  iEvent.put( subjetFlavourInfos, "SubJets" );
469 }
const reco::GenParticleRef & particleRef() const
int i
Definition: DBlmapReader.cc:9
void assignToSubjets(const reco::GenParticleRefVector &clusteredParticles, const edm::Handle< edm::View< reco::Jet > > &subjets, const std::vector< int > &subjetIndices, std::vector< reco::GenParticleRefVector > &assignedParticles)
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:457
boost::shared_ptr< fastjet::ClusterSequence > ClusterSequencePtr
void insertGhosts(const edm::Handle< reco::GenParticleRefVector > &particles, const double ghostRescaling, const bool isHadron, const bool isbHadron, const bool isParton, const bool isLepton, std::vector< fastjet::PseudoJet > &constituents)
void setFlavours(const reco::GenParticleRefVector &clusteredbHadrons, const reco::GenParticleRefVector &clusteredcHadrons, const reco::GenParticleRefVector &clusteredPartons, int &hadronFlavour, int &partonFlavour)
const edm::EDGetTokenT< reco::GenParticleRefVector > bHadronsToken_
void matchGroomedJets(const edm::Handle< edm::View< reco::Jet > > &jets, const edm::Handle< edm::View< reco::Jet > > &matchedJets, std::vector< int > &matchedIndices)
const edm::EDGetTokenT< reco::GenParticleRefVector > partonsToken_
const bool isParton() const
const bool isLepton() const
const edm::EDGetTokenT< reco::GenParticleRefVector > cHadronsToken_
OrphanHandle< PROD > put(std::auto_ptr< PROD > product)
Put a new product.
Definition: Event.h:115
vector< PseudoJet > jets
Class storing the jet flavour information.
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void matchReclusteredJets(const edm::Handle< edm::View< reco::Jet > > &jets, const std::vector< fastjet::PseudoJet > &matchedJets, std::vector< int > &matchedIndices)
const edm::EDGetTokenT< edm::View< reco::Jet > > groomedJetsToken_
edm::RefVector< GenParticleCollection > GenParticleRefVector
vector of reference to GenParticle in the same collection
const edm::EDGetTokenT< edm::View< reco::Jet > > jetsToken_
boost::indirect_iterator< typename seq_t::const_iterator > const_iterator
Definition: View.h:85
const bool isbHadron() const
const bool isHadron() const
void push_back(value_type const &ref)
Add a Ref&lt;C, T&gt; to the RefVector.
Definition: RefVector.h:62
const edm::EDGetTokenT< reco::GenParticleRefVector > leptonsToken_
void matchSubjets(const std::vector< int > &groomedIndices, const edm::Handle< edm::View< reco::Jet > > &groomedJets, const edm::Handle< edm::View< reco::Jet > > &subjets, std::vector< std::vector< int > > &matchedIndices)
ClusterSequencePtr fjClusterSeq_
const edm::EDGetTokenT< edm::View< reco::Jet > > subjetsToken_
void JetFlavourClustering::setFlavours ( const reco::GenParticleRefVector clusteredbHadrons,
const reco::GenParticleRefVector clusteredcHadrons,
const reco::GenParticleRefVector clusteredPartons,
int &  hadronFlavour,
int &  partonFlavour 
)
private

Definition at line 625 of file JetFlavourClustering.cc.

References funct::abs(), edm::RefVector< C, T, F >::begin(), edm::RefVector< C, T, F >::end(), hadronFlavourHasPriority_, CandMCTagUtils::isLightParton(), edm::Ref< C, T, F >::isNonnull(), edm::Ref< C, T, F >::isNull(), and edm::RefVector< C, T, F >::size().

Referenced by produce().

630 {
631  reco::GenParticleRef hardestParton;
632  reco::GenParticleRef hardestLightParton;
633  reco::GenParticleRef flavourParton;
634 
635  // loop over clustered partons (already sorted by Pt)
636  for(reco::GenParticleRefVector::const_iterator it = clusteredPartons.begin(); it != clusteredPartons.end(); ++it)
637  {
638  // hardest parton
639  if( hardestParton.isNull() )
640  hardestParton = (*it);
641  // hardest light-flavour parton
642  if( hardestLightParton.isNull() )
643  {
644  if( CandMCTagUtils::isLightParton( *(*it) ) )
645  hardestLightParton = (*it);
646  }
647  // c flavour
648  if( flavourParton.isNull() && ( std::abs( (*it)->pdgId() ) == 4 ) )
649  flavourParton = (*it);
650  // b flavour gets priority
651  if( std::abs( (*it)->pdgId() ) == 5 )
652  {
653  if( flavourParton.isNull() )
654  flavourParton = (*it);
655  else if( std::abs( flavourParton->pdgId() ) != 5 )
656  flavourParton = (*it);
657  }
658  }
659 
660  // set hadron-based flavour
661  if( clusteredbHadrons.size()>0 )
662  hadronFlavour = 5;
663  else if( clusteredcHadrons.size()>0 && clusteredbHadrons.size()==0 )
664  hadronFlavour = 4;
665  // set parton-based flavour
666  if( flavourParton.isNull() )
667  {
668  if( hardestParton.isNonnull() ) partonFlavour = hardestParton->pdgId();
669  }
670  else
671  partonFlavour = flavourParton->pdgId();
672 
673  // if enabled, check for conflicts between hadron- and parton-based flavours and give priority to the hadron-based flavour
675  {
676  if( hadronFlavour==0 && (std::abs(partonFlavour)==4 || std::abs(partonFlavour)==5) )
677  partonFlavour = ( hardestLightParton.isNonnull() ? hardestLightParton->pdgId() : 0 );
678  else if( hadronFlavour!=0 && std::abs(partonFlavour)!=hadronFlavour )
679  partonFlavour = hadronFlavour;
680  }
681 }
bool isLightParton(const reco::Candidate &c)
Definition: CandMCTag.cc:63
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:252
const_iterator end() const
Termination of iteration.
Definition: RefVector.h:255
const_iterator begin() const
Initialize an iterator over the RefVector.
Definition: RefVector.h:250
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool isNull() const
Checks for null.
Definition: Ref.h:249
size_type size() const
Size of the RefVector.
Definition: RefVector.h:99

Member Data Documentation

const edm::EDGetTokenT<reco::GenParticleRefVector> JetFlavourClustering::bHadronsToken_
private

Definition at line 180 of file JetFlavourClustering.cc.

Referenced by produce().

const edm::EDGetTokenT<reco::GenParticleRefVector> JetFlavourClustering::cHadronsToken_
private

Definition at line 181 of file JetFlavourClustering.cc.

Referenced by produce().

ClusterSequencePtr JetFlavourClustering::fjClusterSeq_
private

Definition at line 194 of file JetFlavourClustering.cc.

Referenced by produce().

JetDefPtr JetFlavourClustering::fjJetDefinition_
private

Definition at line 195 of file JetFlavourClustering.cc.

Referenced by JetFlavourClustering(), and produce().

const double JetFlavourClustering::ghostRescaling_
private

Definition at line 188 of file JetFlavourClustering.cc.

Referenced by produce().

const edm::EDGetTokenT<edm::View<reco::Jet> > JetFlavourClustering::groomedJetsToken_
private

Definition at line 178 of file JetFlavourClustering.cc.

Referenced by produce().

const bool JetFlavourClustering::hadronFlavourHasPriority_
private

Definition at line 190 of file JetFlavourClustering.cc.

Referenced by setFlavours().

const std::string JetFlavourClustering::jetAlgorithm_
private

Definition at line 185 of file JetFlavourClustering.cc.

Referenced by JetFlavourClustering().

const double JetFlavourClustering::jetPtMin_
private

Definition at line 187 of file JetFlavourClustering.cc.

Referenced by produce().

const edm::EDGetTokenT<edm::View<reco::Jet> > JetFlavourClustering::jetsToken_
private

Definition at line 177 of file JetFlavourClustering.cc.

Referenced by produce().

const edm::EDGetTokenT<reco::GenParticleRefVector> JetFlavourClustering::leptonsToken_
private

Definition at line 183 of file JetFlavourClustering.cc.

Referenced by produce().

const edm::EDGetTokenT<reco::GenParticleRefVector> JetFlavourClustering::partonsToken_
private

Definition at line 182 of file JetFlavourClustering.cc.

Referenced by produce().

const double JetFlavourClustering::relPtTolerance_
private

Definition at line 189 of file JetFlavourClustering.cc.

Referenced by produce().

const double JetFlavourClustering::rParam_
private
const edm::EDGetTokenT<edm::View<reco::Jet> > JetFlavourClustering::subjetsToken_
private

Definition at line 179 of file JetFlavourClustering.cc.

Referenced by produce().

const bool JetFlavourClustering::useLeptons_
private

Definition at line 192 of file JetFlavourClustering.cc.

Referenced by produce().

const bool JetFlavourClustering::useSubjets_
private

Definition at line 191 of file JetFlavourClustering.cc.

Referenced by JetFlavourClustering(), and produce().