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 );
150 const double ghostRescaling,
151 const bool isHadron,
const bool isbHadron,
const bool isParton,
const bool isLepton,
152 std::vector<fastjet::PseudoJet>& constituents);
155 const std::vector<fastjet::PseudoJet>& matchedJets,
156 std::vector<int>& matchedIndices);
159 std::vector<int>& matchedIndices);
160 void matchSubjets(
const std::vector<int>& groomedIndices,
163 std::vector<std::vector<int> >& matchedIndices);
173 const std::vector<int>& subjetIndices,
174 std::vector<reco::GenParticleRefVector>& assignedParticles);
207 jetsToken_(consumes<edm::
View<
reco::
Jet> >( iConfig.getParameter<edm::
InputTag>(
"jets")) ),
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() )),
214 jetAlgorithm_(iConfig.getParameter<std::
string>(
"jetAlgorithm")),
215 rParam_(iConfig.getParameter<double>(
"rParam")),
217 ghostRescaling_(iConfig.exists(
"ghostRescaling") ? iConfig.getParameter<double>(
"ghostRescaling") : 1
e-18),
218 relPtTolerance_(iConfig.exists(
"relPtTolerance") ? iConfig.getParameter<double>(
"relPtTolerance") : 1
e-03),
219 hadronFlavourHasPriority_(iConfig.getParameter<bool>(
"hadronFlavourHasPriority")),
220 useSubjets_(iConfig.exists(
"groomedJets") && iConfig.exists(
"subjets")),
221 useLeptons_(iConfig.exists(
"leptons"))
225 produces<reco::JetFlavourInfoMatchingCollection>();
227 produces<reco::JetFlavourInfoMatchingCollection>(
"SubJets");
237 throw cms::Exception(
"InvalidJetAlgorithm") <<
"Jet clustering algorithm is invalid: " <<
jetAlgorithm_ <<
", use CambridgeAachen | Kt | AntiKt" << std::endl;
283 std::auto_ptr<reco::JetFlavourInfoMatchingCollection> subjetFlavourInfos;
288 std::vector<fastjet::PseudoJet> fjInputs;
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 )
297 if(constit->pt() == 0)
299 edm::LogWarning(
"NullTransverseMomentum") <<
"dropping input candidate with pt=0";
302 fjInputs.push_back(fastjet::PseudoJet(constit->px(),constit->py(),constit->pz(),constit->energy()));
318 std::vector<fastjet::PseudoJet> inclusiveJets = fastjet::sorted_by_pt(
fjClusterSeq_->inclusive_jets(
jetPtMin_) );
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.";
324 std::vector<int> reclusteredIndices;
328 std::vector<int> groomedIndices;
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.";
338 std::vector<std::vector<int> > subjetIndices;
341 matchSubjets(groomedIndices,groomedJets,subjets,subjetIndices);
345 for(
size_t i=0;
i<jets->size(); ++
i)
353 if( reclusteredIndices.at(
i) < 0 )
356 (*jetFlavourInfos)[jets->refAt(
i)] =
reco::JetFlavourInfo(clusteredbHadrons, clusteredcHadrons, clusteredPartons, clusteredLeptons, 0, 0);
358 else if( jets->at(
i).pt() == 0 )
360 edm::LogWarning(
"NullTransverseMomentum") <<
"The original jet " <<
i <<
" has Pt=0. This is not expected so the jet will be skipped.";
363 (*jetFlavourInfos)[jets->refAt(
i)] =
reco::JetFlavourInfo(clusteredbHadrons, clusteredcHadrons, clusteredPartons, clusteredLeptons, 0, 0);
369 for(
size_t sj=0; sj<subjetIndices.at(
i).size(); ++sj)
381 if( jets->at(
i).pt() < 10. )
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.";
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.";
393 std::vector<fastjet::PseudoJet> constituents = fastjet::sorted_by_pt( inclusiveJets.at(reclusteredIndices.at(
i)).constituents() );
396 for(std::vector<fastjet::PseudoJet>::const_iterator it = constituents.begin(); it != constituents.end(); ++it)
398 if( !it->has_user_info() )
continue;
418 int hadronFlavour = 0;
419 int partonFlavour = 0;
422 setFlavours(clusteredbHadrons, clusteredcHadrons, clusteredPartons, hadronFlavour, partonFlavour);
425 (*jetFlavourInfos)[jets->refAt(
i)] =
reco::JetFlavourInfo(clusteredbHadrons, clusteredcHadrons, clusteredPartons, clusteredLeptons, hadronFlavour, partonFlavour);
431 if( subjetIndices.at(
i).size()==0 )
continue;
440 assignToSubjets(clusteredbHadrons, subjets, subjetIndices.at(
i), assignedbHadrons);
442 assignToSubjets(clusteredcHadrons, subjets, subjetIndices.at(
i), assignedcHadrons);
444 assignToSubjets(clusteredPartons, subjets, subjetIndices.at(
i), assignedPartons);
447 assignToSubjets(clusteredLeptons, subjets, subjetIndices.at(
i), assignedLeptons);
450 for(
size_t sj=0; sj<subjetIndices.at(
i).size(); ++sj)
452 int subjetHadronFlavour = 0;
453 int subjetPartonFlavour = 0;
456 setFlavours(assignedbHadrons.at(sj), assignedcHadrons.at(sj), assignedPartons.at(sj), subjetHadronFlavour, subjetPartonFlavour);
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);
465 iEvent.
put( jetFlavourInfos );
468 iEvent.
put( subjetFlavourInfos,
"SubJets" );
474 const double ghostRescaling,
475 const bool isHadron,
const bool isbHadron,
const bool isParton,
const bool isLepton,
476 std::vector<fastjet::PseudoJet>& constituents)
483 edm::LogInfo(
"NullTransverseMomentum") <<
"dropping input ghost candidate with pt=0";
486 fastjet::PseudoJet
p((*it)->px(),(*it)->py(),(*it)->pz(),(*it)->energy());
488 p.set_user_info(
new GhostInfo(isHadron, isbHadron, isParton, isLepton, *it));
489 constituents.push_back(p);
496 const std::vector<fastjet::PseudoJet>& reclusteredJets,
497 std::vector<int>& matchedIndices)
499 std::vector<bool> matchedLocks(reclusteredJets.size(),
false);
501 for(
size_t j=0;
j<
jets->size(); ++
j)
503 double matchedDR2 = 1e9;
506 for(
size_t rj=0; rj<reclusteredJets.size(); ++rj)
508 if( matchedLocks.at(rj) )
continue;
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 )
513 matchedDR2 = tempDR2;
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.";
526 matchedLocks.at(matchedIdx) =
true;
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.";
531 matchedIndices.push_back(matchedIdx);
539 std::vector<int>& matchedIndices)
541 std::vector<bool> jetLocks(
jets->size(),
false);
542 std::vector<int> jetIndices;
544 for(
size_t gj=0; gj<groomedJets->size(); ++gj)
546 double matchedDR2 = 1e9;
549 if( groomedJets->at(gj).pt()>0. )
551 for(
size_t j=0;
j<
jets->size(); ++
j)
553 if( jetLocks.at(
j) )
continue;
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 )
558 matchedDR2 = tempDR2;
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.";
573 jetLocks.at(matchedIdx) =
true;
575 jetIndices.push_back(matchedIdx);
578 for(
size_t j=0;
j<
jets->size(); ++
j)
580 std::vector<int>::iterator matchedIndex =
std::find( jetIndices.begin(), jetIndices.end(),
j );
582 matchedIndices.push_back( matchedIndex != jetIndices.end() ?
std::distance(jetIndices.begin(),matchedIndex) : -1 );
591 std::vector<std::vector<int> >& matchedIndices)
593 for(
size_t g=0;
g<groomedIndices.size(); ++
g)
595 std::vector<int> subjetIndices;
597 if( groomedIndices.at(
g)>=0 )
599 for(
size_t s=0;
s<groomedJets->at(groomedIndices.at(
g)).numberOfDaughters(); ++
s)
603 for(
size_t sj=0; sj<subjets->size(); ++sj)
607 subjetIndices.push_back(sj);
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.";
616 matchedIndices.push_back(subjetIndices);
619 matchedIndices.push_back(subjetIndices);
639 if( hardestParton.
isNull() )
640 hardestParton = (*it);
642 if( hardestLightParton.
isNull() )
645 hardestLightParton = (*it);
648 if( flavourParton.
isNull() && (
std::abs( (*it)->pdgId() ) == 4 ) )
649 flavourParton = (*it);
651 if(
std::abs( (*it)->pdgId() ) == 5 )
653 if( flavourParton.
isNull() )
654 flavourParton = (*it);
655 else if(
std::abs( flavourParton->pdgId() ) != 5 )
656 flavourParton = (*it);
661 if( clusteredbHadrons.
size()>0 )
663 else if( clusteredcHadrons.
size()>0 && clusteredbHadrons.
size()==0 )
666 if( flavourParton.
isNull() )
668 if( hardestParton.
isNonnull() ) partonFlavour = hardestParton->pdgId();
671 partonFlavour = flavourParton->pdgId();
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;
687 const std::vector<int>& subjetIndices,
688 std::vector<reco::GenParticleRefVector>& assignedParticles)
693 std::vector<double> dR2toSubjets;
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() ) );
699 int closestSubjetIdx =
std::distance( dR2toSubjets.begin(), std::min_element(dR2toSubjets.begin(), dR2toSubjets.end()) );
701 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 &)
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)
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)
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
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_