98 #include "fastjet/JetDefinition.hh"
99 #include "fastjet/ClusterSequence.hh"
100 #include "fastjet/Selector.hh"
101 #include "fastjet/PseudoJet.hh"
107 typedef boost::shared_ptr<fastjet::JetDefinition>
JetDefPtr;
112 class GhostInfo :
public fastjet::PseudoJet::UserInfoBase{
122 if( isHadron )
m_type |= ( 1 << 0 );
123 if( isbHadron )
m_type |= ( 1 << 1 );
124 if( isParton )
m_type |= ( 1 << 2 );
125 if( isLepton )
m_type |= ( 1 << 3 );
157 const double ghostRescaling,
158 const bool isHadron,
const bool isbHadron,
const bool isParton,
const bool isLepton,
159 std::vector<fastjet::PseudoJet>& constituents);
162 const std::vector<fastjet::PseudoJet>& matchedJets,
163 std::vector<int>& matchedIndices);
166 std::vector<int>& matchedIndices);
167 void matchSubjets(
const std::vector<int>& groomedIndices,
170 std::vector<std::vector<int> >& matchedIndices);
180 const std::vector<int>& subjetIndices,
181 std::vector<reco::GenParticleRefVector>& assignedParticles);
214 jetsToken_(consumes<edm::
View<
reco::
Jet> >( iConfig.getParameter<edm::
InputTag>(
"jets")) ),
215 groomedJetsToken_(mayConsume<edm::
View<
reco::
Jet> >( iConfig.exists(
"groomedJets") ? iConfig.getParameter<edm::
InputTag>(
"groomedJets") : edm::
InputTag() )),
216 subjetsToken_(mayConsume<edm::
View<
reco::
Jet> >( iConfig.exists(
"subjets") ? iConfig.getParameter<edm::
InputTag>(
"subjets") : edm::
InputTag() )),
221 jetAlgorithm_(iConfig.getParameter<std::
string>(
"jetAlgorithm")),
222 rParam_(iConfig.getParameter<double>(
"rParam")),
224 ghostRescaling_(iConfig.exists(
"ghostRescaling") ? iConfig.getParameter<double>(
"ghostRescaling") : 1
e-18),
225 relPtTolerance_(iConfig.exists(
"relPtTolerance") ? iConfig.getParameter<double>(
"relPtTolerance") : 1
e-03),
226 hadronFlavourHasPriority_(iConfig.getParameter<bool>(
"hadronFlavourHasPriority")),
227 useSubjets_(iConfig.exists(
"groomedJets") && iConfig.exists(
"subjets")),
228 useLeptons_(iConfig.exists(
"leptons"))
232 produces<reco::JetFlavourInfoMatchingCollection>();
234 produces<reco::JetFlavourInfoMatchingCollection>(
"SubJets");
244 throw cms::Exception(
"InvalidJetAlgorithm") <<
"Jet clustering algorithm is invalid: " <<
jetAlgorithm_ <<
", use CambridgeAachen | Kt | AntiKt" << std::endl;
290 std::auto_ptr<reco::JetFlavourInfoMatchingCollection> subjetFlavourInfos;
295 std::vector<fastjet::PseudoJet> fjInputs;
299 std::vector<edm::Ptr<reco::Candidate> > constituents = it->getJetConstituents();
300 std::vector<edm::Ptr<reco::Candidate> >::const_iterator
m;
301 for( m = constituents.begin(); m != constituents.end(); ++
m )
304 if(constit->pt() == 0)
306 edm::LogWarning(
"NullTransverseMomentum") <<
"dropping input candidate with pt=0";
309 fjInputs.push_back(fastjet::PseudoJet(constit->px(),constit->py(),constit->pz(),constit->energy()));
325 std::vector<fastjet::PseudoJet> inclusiveJets = fastjet::sorted_by_pt(
fjClusterSeq_->inclusive_jets(
jetPtMin_) );
327 if( inclusiveJets.size() < jets->size() )
328 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.";
331 std::vector<int> reclusteredIndices;
335 std::vector<int> groomedIndices;
338 if( groomedJets->size() > jets->size() )
339 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.";
345 std::vector<std::vector<int> > subjetIndices;
348 matchSubjets(groomedIndices,groomedJets,subjets,subjetIndices);
352 for(
size_t i=0;
i<jets->size(); ++
i)
360 if( reclusteredIndices.at(
i) < 0 )
363 (*jetFlavourInfos)[jets->refAt(
i)] =
reco::JetFlavourInfo(clusteredbHadrons, clusteredcHadrons, clusteredPartons, clusteredLeptons, 0, 0);
365 else if( jets->at(
i).pt() == 0 )
367 edm::LogWarning(
"NullTransverseMomentum") <<
"The original jet " <<
i <<
" has Pt=0. This is not expected so the jet will be skipped.";
370 (*jetFlavourInfos)[jets->refAt(
i)] =
reco::JetFlavourInfo(clusteredbHadrons, clusteredcHadrons, clusteredPartons, clusteredLeptons, 0, 0);
376 for(
size_t sj=0; sj<subjetIndices.at(
i).size(); ++sj)
388 if( jets->at(
i).pt() < 10. )
389 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"
390 <<
"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"
391 <<
"Since the mismatch is at low Pt (Pt<10 GeV), it is ignored and only a warning is issued.\n"
392 <<
"\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.";
394 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"
395 <<
"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"
396 <<
"\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.";
400 std::vector<fastjet::PseudoJet> constituents = fastjet::sorted_by_pt( inclusiveJets.at(reclusteredIndices.at(
i)).constituents() );
403 for(std::vector<fastjet::PseudoJet>::const_iterator it = constituents.begin(); it != constituents.end(); ++it)
405 if( !it->has_user_info() )
continue;
425 int hadronFlavour = 0;
426 int partonFlavour = 0;
429 setFlavours(clusteredbHadrons, clusteredcHadrons, clusteredPartons, hadronFlavour, partonFlavour);
432 (*jetFlavourInfos)[jets->refAt(
i)] =
reco::JetFlavourInfo(clusteredbHadrons, clusteredcHadrons, clusteredPartons, clusteredLeptons, hadronFlavour, partonFlavour);
438 if( subjetIndices.at(
i).size()==0 )
continue;
447 assignToSubjets(clusteredbHadrons, subjets, subjetIndices.at(
i), assignedbHadrons);
449 assignToSubjets(clusteredcHadrons, subjets, subjetIndices.at(
i), assignedcHadrons);
451 assignToSubjets(clusteredPartons, subjets, subjetIndices.at(
i), assignedPartons);
454 assignToSubjets(clusteredLeptons, subjets, subjetIndices.at(
i), assignedLeptons);
457 for(
size_t sj=0; sj<subjetIndices.at(
i).size(); ++sj)
459 int subjetHadronFlavour = 0;
460 int subjetPartonFlavour = 0;
463 setFlavours(assignedbHadrons.at(sj), assignedcHadrons.at(sj), assignedPartons.at(sj), subjetHadronFlavour, subjetPartonFlavour);
466 (*subjetFlavourInfos)[subjets->refAt(subjetIndices.at(
i).at(sj))] =
reco::JetFlavourInfo(assignedbHadrons.at(sj), assignedcHadrons.at(sj), assignedPartons.at(sj), assignedLeptons.at(sj), subjetHadronFlavour, subjetPartonFlavour);
472 iEvent.
put( jetFlavourInfos );
475 iEvent.
put( subjetFlavourInfos,
"SubJets" );
481 const double ghostRescaling,
482 const bool isHadron,
const bool isbHadron,
const bool isParton,
const bool isLepton,
483 std::vector<fastjet::PseudoJet>& constituents)
490 edm::LogInfo(
"NullTransverseMomentum") <<
"dropping input ghost candidate with pt=0";
493 fastjet::PseudoJet
p((*it)->px(),(*it)->py(),(*it)->pz(),(*it)->energy());
495 p.set_user_info(
new GhostInfo(isHadron, isbHadron, isParton, isLepton, *it));
496 constituents.push_back(p);
503 const std::vector<fastjet::PseudoJet>& reclusteredJets,
504 std::vector<int>& matchedIndices)
506 std::vector<bool> matchedLocks(reclusteredJets.size(),
false);
508 for(
size_t j=0;
j<
jets->size(); ++
j)
510 double matchedDR2 = 1e9;
513 for(
size_t rj=0; rj<reclusteredJets.size(); ++rj)
515 if( matchedLocks.at(rj) )
continue;
517 double tempDR2 =
reco::deltaR2(
jets->at(
j).rapidity(),
jets->at(
j).phi(), reclusteredJets.at(rj).rapidity(), reclusteredJets.at(rj).phi_std() );
518 if( tempDR2 < matchedDR2 )
520 matchedDR2 = tempDR2;
529 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"
530 <<
"This is not expected so please check that the jet algorithm and jet size match those used for the original jet collection.";
533 matchedLocks.at(matchedIdx) =
true;
536 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.";
538 matchedIndices.push_back(matchedIdx);
546 std::vector<int>& matchedIndices)
548 std::vector<bool> jetLocks(
jets->size(),
false);
549 std::vector<int> jetIndices;
551 for(
size_t gj=0; gj<groomedJets->size(); ++gj)
553 double matchedDR2 = 1e9;
556 if( groomedJets->at(gj).pt()>0. )
558 for(
size_t j=0;
j<
jets->size(); ++
j)
560 if( jetLocks.at(
j) )
continue;
562 double tempDR2 =
reco::deltaR2(
jets->at(
j).rapidity(),
jets->at(
j).phi(), groomedJets->at(gj).rapidity(), groomedJets->at(gj).phi() );
563 if( tempDR2 < matchedDR2 )
565 matchedDR2 = tempDR2;
575 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"
576 <<
"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.";
580 jetLocks.at(matchedIdx) =
true;
582 jetIndices.push_back(matchedIdx);
585 for(
size_t j=0;
j<
jets->size(); ++
j)
587 std::vector<int>::iterator matchedIndex =
std::find( jetIndices.begin(), jetIndices.end(),
j );
589 matchedIndices.push_back( matchedIndex != jetIndices.end() ?
std::distance(jetIndices.begin(),matchedIndex) : -1 );
598 std::vector<std::vector<int> >& matchedIndices)
600 for(
size_t g=0;
g<groomedIndices.size(); ++
g)
602 std::vector<int> subjetIndices;
604 if( groomedIndices.at(
g)>=0 )
606 for(
size_t s=0;
s<groomedJets->at(groomedIndices.at(
g)).numberOfDaughters(); ++
s)
610 for(
size_t sj=0; sj<subjets->size(); ++sj)
614 subjetIndices.push_back(sj);
620 if( subjetIndices.size() == 0 )
621 edm::LogError(
"SubjetMatchingFailed") <<
"Matching subjets to original jets failed. Please check that the groomed jet and subjet collections belong to each other.";
623 matchedIndices.push_back(subjetIndices);
626 matchedIndices.push_back(subjetIndices);
646 if( hardestParton.
isNull() )
647 hardestParton = (*it);
649 if( hardestLightParton.
isNull() )
652 hardestLightParton = (*it);
655 if( flavourParton.
isNull() && (
std::abs( (*it)->pdgId() ) == 4 ) )
656 flavourParton = (*it);
658 if(
std::abs( (*it)->pdgId() ) == 5 )
660 if( flavourParton.
isNull() )
661 flavourParton = (*it);
662 else if(
std::abs( flavourParton->pdgId() ) != 5 )
663 flavourParton = (*it);
668 if( clusteredbHadrons.
size()>0 )
670 else if( clusteredcHadrons.
size()>0 && clusteredbHadrons.
size()==0 )
673 if( flavourParton.
isNull() )
675 if( hardestParton.
isNonnull() ) partonFlavour = hardestParton->pdgId();
678 partonFlavour = flavourParton->pdgId();
683 if( hadronFlavour==0 && (
std::abs(partonFlavour)==4 ||
std::abs(partonFlavour)==5) )
684 partonFlavour = ( hardestLightParton.
isNonnull() ? hardestLightParton->pdgId() : 0 );
685 else if( hadronFlavour!=0 &&
std::abs(partonFlavour)!=hadronFlavour )
686 partonFlavour = hadronFlavour;
694 const std::vector<int>& subjetIndices,
695 std::vector<reco::GenParticleRefVector>& assignedParticles)
700 std::vector<double> dR2toSubjets;
702 for(
size_t sj=0; sj<subjetIndices.size(); ++sj)
703 dR2toSubjets.push_back(
reco::deltaR2( (*it)->rapidity(), (*it)->phi(), subjets->at(subjetIndices.at(sj)).rapidity(), subjets->at(subjetIndices.at(sj)).
phi() ) );
706 int closestSubjetIdx =
std::distance( dR2toSubjets.begin(), std::min_element(dR2toSubjets.begin(), dR2toSubjets.end()) );
708 assignedParticles.at(closestSubjetIdx).push_back( *it );
const reco::GenParticleRef & particleRef() const
bool isLightParton(const reco::Candidate &c)
boost::shared_ptr< fastjet::JetDefinition > JetDefPtr
virtual void produce(edm::Event &, const edm::EventSetup &)
virtual void endLuminosityBlock(edm::LuminosityBlock &, edm::EventSetup const &)
bool isNonnull() const
Checks for non-null.
void assignToSubjets(const reco::GenParticleRefVector &clusteredParticles, const edm::Handle< edm::View< reco::Jet > > &subjets, const std::vector< int > &subjetIndices, std::vector< reco::GenParticleRefVector > &assignedParticles)
Clusters hadrons, partons, and jet contituents to determine the jet flavour.
const bool hadronFlavourHasPriority_
bool getByToken(EDGetToken token, Handle< PROD > &result) const
boost::shared_ptr< fastjet::ClusterSequence > ClusterSequencePtr
#define DEFINE_FWK_MODULE(type)
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)
GhostInfo(const bool &isHadron, const bool &isbHadron, const bool &isParton, const bool &isLepton, const reco::GenParticleRef &particleRef)
const reco::GenParticleRef m_particleRef
void setFlavours(const reco::GenParticleRefVector &clusteredbHadrons, const reco::GenParticleRefVector &clusteredcHadrons, const reco::GenParticleRefVector &clusteredPartons, int &hadronFlavour, int &partonFlavour)
const edm::EDGetTokenT< reco::GenParticleRefVector > bHadronsToken_
bool isLepton(const Candidate &part)
void matchGroomedJets(const edm::Handle< edm::View< reco::Jet > > &jets, const edm::Handle< edm::View< reco::Jet > > &matchedJets, std::vector< int > &matchedIndices)
const_iterator end() const
Termination of iteration.
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
const double ghostRescaling_
const edm::EDGetTokenT< reco::GenParticleRefVector > partonsToken_
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
const bool isParton() const
const_iterator begin() const
Initialize an iterator over the RefVector.
JetDefPtr fjJetDefinition_
const bool isLepton() const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const edm::EDGetTokenT< reco::GenParticleRefVector > cHadronsToken_
void addDefault(ParameterSetDescription const &psetDescription)
virtual void beginRun(edm::Run &, edm::EventSetup const &)
OrphanHandle< PROD > put(std::auto_ptr< PROD > product)
Put a new product.
Class storing the jet flavour information.
Abs< T >::type abs(const T &t)
double deltaR2(const T1 &t1, const T2 &t2)
virtual void endRun(edm::Run &, edm::EventSetup const &)
JetFlavourClustering(const edm::ParameterSet &)
bool isNull() const
Checks for null.
void matchReclusteredJets(const edm::Handle< edm::View< reco::Jet > > &jets, const std::vector< fastjet::PseudoJet > &matchedJets, std::vector< int > &matchedIndices)
const std::string jetAlgorithm_
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_
bool isParton(const reco::Candidate &c)
const double relPtTolerance_
boost::indirect_iterator< typename seq_t::const_iterator > const_iterator
const bool isbHadron() const
virtual void beginLuminosityBlock(edm::LuminosityBlock &, edm::EventSetup const &)
const bool isHadron() const
void push_back(value_type const &ref)
Add a Ref<C, T> to the RefVector.
size_type size() const
Size of the RefVector.
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_