00001
00002
00003
00004
00005
00006
00008
00009 #include "RecoJets/JetProducers/plugins/VirtualJetProducer.h"
00010 #include "RecoJets/JetProducers/interface/JetSpecific.h"
00011 #include "RecoJets/JetProducers/interface/BackgroundEstimator.h"
00012 #include "RecoJets/JetProducers/interface/VirtualJetProducerHelper.h"
00013
00014 #include "FWCore/Framework/interface/Event.h"
00015 #include "FWCore/Framework/interface/EventSetup.h"
00016 #include "FWCore/Framework/interface/ESHandle.h"
00017 #include "FWCore/Utilities/interface/Exception.h"
00018 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00019 #include "FWCore/Framework/interface/MakerMacros.h"
00020
00021 #include "DataFormats/Common/interface/View.h"
00022 #include "DataFormats/Common/interface/Handle.h"
00023 #include "DataFormats/VertexReco/interface/Vertex.h"
00024 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00025 #include "DataFormats/JetReco/interface/CaloJetCollection.h"
00026 #include "DataFormats/JetReco/interface/GenJetCollection.h"
00027 #include "DataFormats/JetReco/interface/PFJetCollection.h"
00028 #include "DataFormats/JetReco/interface/BasicJetCollection.h"
00029 #include "DataFormats/JetReco/interface/TrackJetCollection.h"
00030 #include "DataFormats/JetReco/interface/PFClusterJetCollection.h"
00031 #include "DataFormats/Candidate/interface/CandidateFwd.h"
00032 #include "DataFormats/Candidate/interface/LeafCandidate.h"
00033 #include "DataFormats/Math/interface/deltaR.h"
00034
00035 #include "fastjet/SISConePlugin.hh"
00036 #include "fastjet/CMSIterativeConePlugin.hh"
00037 #include "fastjet/ATLASConePlugin.hh"
00038 #include "fastjet/CDFMidPointPlugin.hh"
00039
00040 #include <iostream>
00041 #include <memory>
00042 #include <algorithm>
00043 #include <limits>
00044 #include <cmath>
00045
00046
00047 using namespace std;
00048
00049
00050 namespace reco {
00051 namespace helper {
00052 struct GreaterByPtPseudoJet {
00053 bool operator()( const fastjet::PseudoJet & t1, const fastjet::PseudoJet & t2 ) const {
00054 return t1.perp() > t2.perp();
00055 }
00056 };
00057
00058 }
00059 }
00060
00061
00062 const char *VirtualJetProducer::JetType::names[] = {
00063 "BasicJet","GenJet","CaloJet","PFJet","TrackJet","PFClusterJet"
00064 };
00065
00066
00067
00068 VirtualJetProducer::JetType::Type
00069 VirtualJetProducer::JetType::byName(const string &name)
00070 {
00071 const char **pos = std::find(names, names + LastJetType, name);
00072 if (pos == names + LastJetType) {
00073 std::string errorMessage="Requested jetType not supported: "+name+"\n";
00074 throw cms::Exception("Configuration",errorMessage);
00075 }
00076 return (Type)(pos-names);
00077 }
00078
00079
00080 void VirtualJetProducer::makeProduces( std::string alias, std::string tag )
00081 {
00082 if (makeCaloJet(jetTypeE)) {
00083 produces<reco::CaloJetCollection>(tag).setBranchAlias(alias);
00084 }
00085 else if (makePFJet(jetTypeE)) {
00086 produces<reco::PFJetCollection>(tag).setBranchAlias(alias);
00087 }
00088 else if (makeGenJet(jetTypeE)) {
00089 produces<reco::GenJetCollection>(tag).setBranchAlias(alias);
00090 }
00091 else if (makeTrackJet(jetTypeE)) {
00092 produces<reco::TrackJetCollection>(tag).setBranchAlias(alias);
00093 }
00094 else if (makePFClusterJet(jetTypeE)) {
00095 produces<reco::PFClusterJetCollection>(tag).setBranchAlias(alias);
00096 }
00097 else if (makeBasicJet(jetTypeE)) {
00098 produces<reco::BasicJetCollection>(tag).setBranchAlias(alias);
00099 }
00100 }
00101
00103
00105
00106
00107 VirtualJetProducer::VirtualJetProducer(const edm::ParameterSet& iConfig)
00108 : moduleLabel_ (iConfig.getParameter<string> ("@module_label"))
00109 , src_ (iConfig.getParameter<edm::InputTag>("src"))
00110 , srcPVs_ (iConfig.getParameter<edm::InputTag>("srcPVs"))
00111 , jetType_ (iConfig.getParameter<string> ("jetType"))
00112 , jetAlgorithm_ (iConfig.getParameter<string> ("jetAlgorithm"))
00113 , rParam_ (iConfig.getParameter<double> ("rParam"))
00114 , inputEtMin_ (iConfig.getParameter<double> ("inputEtMin"))
00115 , inputEMin_ (iConfig.getParameter<double> ("inputEMin"))
00116 , jetPtMin_ (iConfig.getParameter<double> ("jetPtMin"))
00117 , doPVCorrection_(iConfig.getParameter<bool> ("doPVCorrection"))
00118 , restrictInputs_(false)
00119 , maxInputs_(99999999)
00120 , doAreaFastjet_ (iConfig.getParameter<bool> ("doAreaFastjet"))
00121 , doAreaDiskApprox_ (false)
00122 , doRhoFastjet_ (iConfig.getParameter<bool> ("doRhoFastjet"))
00123 , voronoiRfact_ (-9)
00124 , doPUOffsetCorr_(iConfig.getParameter<bool> ("doPUOffsetCorr"))
00125 , puWidth_(0)
00126 , nExclude_(0)
00127 , jetCollInstanceName_ ("")
00128 {
00129 anomalousTowerDef_ = std::auto_ptr<AnomalousTower>(new AnomalousTower(iConfig));
00130
00131
00132
00133
00134
00135
00136
00137 if (jetAlgorithm_=="SISCone") {
00138 fjPlugin_ = PluginPtr( new fastjet::SISConePlugin(rParam_,0.75,0,0.0,false,
00139 fastjet::SISConePlugin::SM_pttilde) );
00140 fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(&*fjPlugin_) );
00141 }
00142 else if (jetAlgorithm_=="IterativeCone") {
00143 fjPlugin_ = PluginPtr(new fastjet::CMSIterativeConePlugin(rParam_,1.0));
00144 fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(&*fjPlugin_));
00145 }
00146 else if (jetAlgorithm_=="CDFMidPoint") {
00147 fjPlugin_ = PluginPtr(new fastjet::CDFMidPointPlugin(rParam_,0.75));
00148 fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(&*fjPlugin_));
00149 }
00150 else if (jetAlgorithm_=="ATLASCone") {
00151 fjPlugin_ = PluginPtr(new fastjet::ATLASConePlugin(rParam_));
00152 fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(&*fjPlugin_));
00153 }
00154 else if (jetAlgorithm_=="Kt")
00155 fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(fastjet::kt_algorithm,rParam_));
00156 else if (jetAlgorithm_=="CambridgeAachen")
00157 fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(fastjet::cambridge_algorithm,
00158 rParam_) );
00159 else if (jetAlgorithm_=="AntiKt")
00160 fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(fastjet::antikt_algorithm,rParam_) );
00161 else if (jetAlgorithm_=="GeneralizedKt")
00162 fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(fastjet::genkt_algorithm,
00163 rParam_,-2) );
00164 else
00165 throw cms::Exception("Invalid jetAlgorithm")
00166 <<"Jet algorithm for VirtualJetProducer is invalid, Abort!\n";
00167
00168 jetTypeE=JetType::byName(jetType_);
00169
00170 if ( iConfig.exists("jetCollInstanceName") ) {
00171 jetCollInstanceName_ = iConfig.getParameter<string>("jetCollInstanceName");
00172 }
00173
00174 if ( doPUOffsetCorr_ ) {
00175 if ( jetTypeE != JetType::CaloJet ) {
00176 throw cms::Exception("InvalidInput") << "Can only offset correct jets of type CaloJet";
00177 }
00178
00179 if(iConfig.exists("subtractorName")) puSubtractorName_ = iConfig.getParameter<string> ("subtractorName");
00180 else puSubtractorName_ = std::string();
00181
00182 if(puSubtractorName_.empty()){
00183 edm::LogWarning("VirtualJetProducer") << "Pile Up correction on; however, pile up type is not specified. Using default... \n";
00184 subtractor_ = boost::shared_ptr<PileUpSubtractor>(new PileUpSubtractor(iConfig));
00185 }else{
00186 subtractor_ = boost::shared_ptr<PileUpSubtractor>(PileUpSubtractorFactory::get()->create( puSubtractorName_, iConfig));
00187 }
00188 }
00189
00190
00191 if (iConfig.exists("doAreaDiskApprox")) {
00192 doAreaDiskApprox_ = iConfig.getParameter<bool>("doAreaDiskApprox");
00193 if (doAreaDiskApprox_ && doAreaFastjet_)
00194 throw cms::Exception("Conflicting area calculations") << "Both the calculation of jet area via fastjet and via an analytical disk approximation have been requested. Please decide on one.\n";
00195
00196 }
00197
00198
00199 if (iConfig.exists("voronoiRfact"))
00200 voronoiRfact_ = iConfig.getParameter<double>("voronoiRfact");
00201
00202
00203
00204 if ( doAreaFastjet_ || doRhoFastjet_ ) {
00205
00206
00207 double rhoEtaMax=iConfig.getParameter<double>("Rho_EtaMax");
00208
00209 double ghostEtaMax = iConfig.getParameter<double>("Ghost_EtaMax");
00210
00211 int activeAreaRepeats = iConfig.getParameter<int> ("Active_Area_Repeats");
00212
00213 double ghostArea = iConfig.getParameter<double> ("GhostArea");
00214 if (voronoiRfact_ <= 0)
00215 fjActiveArea_ = ActiveAreaSpecPtr(new fastjet::ActiveAreaSpec(ghostEtaMax,activeAreaRepeats,ghostArea));
00216 fjRangeDef_ = RangeDefPtr( new fastjet::RangeDefinition(rhoEtaMax) );
00217 }
00218
00219
00220 if ( iConfig.exists("restrictInputs") ) {
00221 restrictInputs_ = iConfig.getParameter<bool>("restrictInputs");
00222 maxInputs_ = iConfig.getParameter<unsigned int>("maxInputs");
00223 }
00224
00225
00226 string alias=iConfig.getUntrackedParameter<string>("alias",moduleLabel_);
00227
00228
00229 makeProduces( alias, jetCollInstanceName_ );
00230
00231 doFastJetNonUniform_ = false;
00232 if(iConfig.exists("doFastJetNonUniform")) doFastJetNonUniform_ = iConfig.getParameter<bool> ("doFastJetNonUniform");
00233 if(doFastJetNonUniform_){
00234 puCenters_ = iConfig.getParameter<std::vector<double> >("puCenters");
00235 puWidth_ = iConfig.getParameter<double>("puWidth");
00236 nExclude_ = iConfig.getParameter<unsigned int>("nExclude");
00237 }
00238
00239 useDeterministicSeed_ = false;
00240 minSeed_ = 0;
00241 if ( iConfig.exists("useDeterministicSeed") ) {
00242 useDeterministicSeed_ = iConfig.getParameter<bool>("useDeterministicSeed");
00243 minSeed_ = iConfig.getParameter<unsigned int>("minSeed");
00244 }
00245
00246 produces<std::vector<double> >("rhos");
00247 produces<std::vector<double> >("sigmas");
00248 produces<double>("rho");
00249 produces<double>("sigma");
00250
00251 }
00252
00253
00254 VirtualJetProducer::~VirtualJetProducer()
00255 {
00256 }
00257
00258
00260
00262
00263
00264 void VirtualJetProducer::produce(edm::Event& iEvent,const edm::EventSetup& iSetup)
00265 {
00266
00267
00268
00269
00270
00271
00272 if ( useDeterministicSeed_ ) {
00273 fastjet::GhostedAreaSpec gas;
00274 std::vector<int> seeds(2);
00275 seeds[0] = std::max(iEvent.id().run(),minSeed_ + 3) + 3 * iEvent.id().event();
00276 seeds[1] = std::max(iEvent.id().run(),minSeed_ + 5) + 5 * iEvent.id().event();
00277 gas.set_random_status(seeds);
00278 }
00279
00280 LogDebug("VirtualJetProducer") << "Entered produce\n";
00281
00282 vertex_=reco::Jet::Point(0,0,0);
00283 if (makeCaloJet(jetTypeE)&&doPVCorrection_) {
00284 LogDebug("VirtualJetProducer") << "Adding PV info\n";
00285 edm::Handle<reco::VertexCollection> pvCollection;
00286 iEvent.getByLabel(srcPVs_,pvCollection);
00287 if (pvCollection->size()>0) vertex_=pvCollection->begin()->position();
00288 }
00289
00290
00291
00292 if ( doPUOffsetCorr_ ) {
00293 subtractor_->setupGeometryMap(iEvent, iSetup);
00294 }
00295
00296
00297 LogDebug("VirtualJetProducer") << "Clear data\n";
00298 fjInputs_.clear();
00299 fjJets_.clear();
00300 inputs_.clear();
00301
00302
00303 edm::Handle<reco::CandidateView> inputsHandle;
00304 iEvent.getByLabel(src_,inputsHandle);
00305 for (size_t i = 0; i < inputsHandle->size(); ++i) {
00306 inputs_.push_back(inputsHandle->ptrAt(i));
00307 }
00308 LogDebug("VirtualJetProducer") << "Got inputs\n";
00309
00310
00311
00312
00313 fjInputs_.reserve(inputs_.size());
00314 inputTowers();
00315 LogDebug("VirtualJetProducer") << "Inputted towers\n";
00316
00317
00318
00319 if ( doPUOffsetCorr_ ) {
00320 subtractor_->reset(inputs_,fjInputs_,fjJets_);
00321 subtractor_->calculatePedestal(fjInputs_);
00322 subtractor_->subtractPedestal(fjInputs_);
00323 LogDebug("VirtualJetProducer") << "Subtracted pedestal\n";
00324 }
00325
00326
00327
00328 runAlgorithm( iEvent, iSetup );
00329 if ( doPUOffsetCorr_ ) {
00330 subtractor_->setAlgorithm(fjClusterSeq_);
00331 }
00332
00333 LogDebug("VirtualJetProducer") << "Ran algorithm\n";
00334
00335
00336
00337
00338
00339
00340
00341 if ( doPUOffsetCorr_ ) {
00342 LogDebug("VirtualJetProducer") << "Do PUOffsetCorr\n";
00343 vector<fastjet::PseudoJet> orphanInput;
00344 subtractor_->calculateOrphanInput(orphanInput);
00345 subtractor_->calculatePedestal(orphanInput);
00346 subtractor_->offsetCorrectJets();
00347 }
00348
00349
00350
00351
00352
00353 output( iEvent, iSetup );
00354 LogDebug("VirtualJetProducer") << "Wrote jets\n";
00355
00356 return;
00357 }
00358
00359
00360
00361 void VirtualJetProducer::inputTowers( )
00362 {
00363 std::vector<edm::Ptr<reco::Candidate> >::const_iterator inBegin = inputs_.begin(),
00364 inEnd = inputs_.end(), i = inBegin;
00365 for (; i != inEnd; ++i ) {
00366 reco::CandidatePtr input = *i;
00367 if (std::isnan(input->pt())) continue;
00368 if (input->et() <inputEtMin_) continue;
00369 if (input->energy()<inputEMin_) continue;
00370 if (isAnomalousTower(input)) continue;
00371 if (input->pt() == 0) {
00372 edm::LogError("NullTransverseMomentum") << "dropping input candidate with pt=0";
00373 continue;
00374 }
00375 if (makeCaloJet(jetTypeE)&&doPVCorrection_) {
00376 const CaloTower* tower=dynamic_cast<const CaloTower*>(input.get());
00377 math::PtEtaPhiMLorentzVector ct(tower->p4(vertex_));
00378 fjInputs_.push_back(fastjet::PseudoJet(ct.px(),ct.py(),ct.pz(),ct.energy()));
00379 }
00380 else {
00381 fjInputs_.push_back(fastjet::PseudoJet(input->px(),input->py(),input->pz(),
00382 input->energy()));
00383 }
00384 fjInputs_.back().set_user_index(i - inBegin);
00385 }
00386
00387 if ( restrictInputs_ && fjInputs_.size() > maxInputs_ ) {
00388 reco::helper::GreaterByPtPseudoJet pTComparator;
00389 std::sort(fjInputs_.begin(), fjInputs_.end(), pTComparator);
00390 fjInputs_.resize(maxInputs_);
00391 edm::LogWarning("JetRecoTooManyEntries") << "Too many inputs in the event, limiting to first " << maxInputs_ << ". Output is suspect.";
00392 }
00393 }
00394
00395
00396 bool VirtualJetProducer::isAnomalousTower(reco::CandidatePtr input)
00397 {
00398 if (!makeCaloJet(jetTypeE))
00399 return false;
00400 else
00401 return (*anomalousTowerDef_)(*input);
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411 void VirtualJetProducer::copyConstituents(const vector<fastjet::PseudoJet>& fjConstituents,
00412 reco::Jet* jet)
00413 {
00414 for (unsigned int i=0;i<fjConstituents.size();++i)
00415 jet->addDaughter(inputs_[fjConstituents[i].user_index()]);
00416 }
00417
00418
00419
00420 vector<reco::CandidatePtr>
00421 VirtualJetProducer::getConstituents(const vector<fastjet::PseudoJet>&fjConstituents)
00422 {
00423 vector<reco::CandidatePtr> result;
00424 for (unsigned int i=0;i<fjConstituents.size();i++) {
00425 int index = fjConstituents[i].user_index();
00426 reco::CandidatePtr candidate = inputs_[index];
00427 result.push_back(candidate);
00428 }
00429 return result;
00430 }
00431
00432
00433
00434
00435 void VirtualJetProducer::output(edm::Event & iEvent, edm::EventSetup const& iSetup)
00436 {
00437
00438
00439 switch( jetTypeE ) {
00440 case JetType::CaloJet :
00441 writeJets<reco::CaloJet>( iEvent, iSetup);
00442 break;
00443 case JetType::PFJet :
00444 writeJets<reco::PFJet>( iEvent, iSetup);
00445 break;
00446 case JetType::GenJet :
00447 writeJets<reco::GenJet>( iEvent, iSetup);
00448 break;
00449 case JetType::TrackJet :
00450 writeJets<reco::TrackJet>( iEvent, iSetup);
00451 break;
00452 case JetType::PFClusterJet :
00453 writeJets<reco::PFClusterJet>( iEvent, iSetup);
00454 break;
00455 case JetType::BasicJet :
00456 writeJets<reco::BasicJet>( iEvent, iSetup);
00457 break;
00458 default:
00459 throw cms::Exception("InvalidInput") << "invalid jet type in VirtualJetProducer\n";
00460 break;
00461 };
00462
00463 }
00464
00465 template< typename T >
00466 void VirtualJetProducer::writeJets( edm::Event & iEvent, edm::EventSetup const& iSetup )
00467 {
00468 if (doRhoFastjet_) {
00469
00470
00471 std::vector<fastjet::PseudoJet> fjexcluded_jets;
00472 fjexcluded_jets=fjJets_;
00473
00474 if(fjexcluded_jets.size()>2) fjexcluded_jets.resize(nExclude_);
00475
00476 if(doFastJetNonUniform_){
00477 std::auto_ptr<std::vector<double> > rhos(new std::vector<double>);
00478 std::auto_ptr<std::vector<double> > sigmas(new std::vector<double>);
00479 int nEta = puCenters_.size();
00480 rhos->reserve(nEta);
00481 sigmas->reserve(nEta);
00482 fastjet::ClusterSequenceAreaBase const* clusterSequenceWithArea =
00483 dynamic_cast<fastjet::ClusterSequenceAreaBase const *> ( &*fjClusterSeq_ );
00484
00485
00486 for(int ie = 0; ie < nEta; ++ie){
00487 double eta = puCenters_[ie];
00488 double etamin=eta-puWidth_;
00489 double etamax=eta+puWidth_;
00490 fastjet::RangeDefinition range_rho(etamin,etamax);
00491 fastjet::BackgroundEstimator bkgestim(*clusterSequenceWithArea,range_rho);
00492 bkgestim.set_excluded_jets(fjexcluded_jets);
00493 rhos->push_back(bkgestim.rho());
00494 sigmas->push_back(bkgestim.sigma());
00495 }
00496 iEvent.put(rhos,"rhos");
00497 iEvent.put(sigmas,"sigmas");
00498 }else{
00499 std::auto_ptr<double> rho(new double(0.0));
00500 std::auto_ptr<double> sigma(new double(0.0));
00501 double mean_area = 0;
00502
00503 fastjet::ClusterSequenceAreaBase const* clusterSequenceWithArea =
00504 dynamic_cast<fastjet::ClusterSequenceAreaBase const *> ( &*fjClusterSeq_ );
00505 clusterSequenceWithArea->get_median_rho_and_sigma(*fjRangeDef_,false,*rho,*sigma,mean_area);
00506 iEvent.put(rho,"rho");
00507 iEvent.put(sigma,"sigma");
00508 }
00509 }
00510
00511
00512
00513 using namespace reco;
00514
00515 std::auto_ptr<std::vector<T> > jets(new std::vector<T>() );
00516 jets->reserve(fjJets_.size());
00517
00518
00519
00520 std::vector<std::vector<double> > rij(fjJets_.size());
00521
00522 for (unsigned int ijet=0;ijet<fjJets_.size();++ijet) {
00523
00524 T jet;
00525
00526 const fastjet::PseudoJet& fjJet = fjJets_[ijet];
00527
00528 std::vector<fastjet::PseudoJet> fjConstituents =
00529 sorted_by_pt(fjClusterSeq_->constituents(fjJet));
00530
00531 std::vector<CandidatePtr> constituents =
00532 getConstituents(fjConstituents);
00533
00534
00535 double jetArea=0.0;
00536 if ( doAreaFastjet_ ) {
00537 fastjet::ClusterSequenceAreaBase const * clusterSequenceWithArea =
00538 dynamic_cast<fastjet::ClusterSequenceAreaBase const *>(&*fjClusterSeq_);
00539 jetArea = clusterSequenceWithArea->area(fjJet);
00540 }
00541 else if ( doAreaDiskApprox_ ) {
00542
00543
00544 jetArea = M_PI;
00545 if (ijet) {
00546 std::vector<double>& distance = rij[ijet];
00547 distance.resize(ijet);
00548 for (unsigned jJet = 0; jJet < ijet; ++jJet) {
00549 distance[jJet] = reco::deltaR(fjJets_[ijet],fjJets_[jJet]) / rParam_;
00550 jetArea -= reco::helper::VirtualJetProducerHelper::intersection(distance[jJet]);
00551 for (unsigned kJet = 0; kJet < jJet; ++kJet) {
00552 jetArea += reco::helper::VirtualJetProducerHelper::intersection(distance[jJet], distance[kJet], rij[jJet][kJet]);
00553 }
00554 }
00555 }
00556 jetArea *= rParam_;
00557 jetArea *= rParam_;
00558 }
00559
00560
00561
00562
00563 writeSpecific(jet,
00564 Particle::LorentzVector(fjJet.px(),
00565 fjJet.py(),
00566 fjJet.pz(),
00567 fjJet.E()),
00568 vertex_,
00569 constituents, iSetup);
00570
00571 jet.setJetArea (jetArea);
00572
00573 if(doPUOffsetCorr_){
00574 jet.setPileup(subtractor_->getPileUpEnergy(ijet));
00575 }else{
00576 jet.setPileup (0.0);
00577 }
00578
00579
00580 jets->push_back(jet);
00581 }
00582
00583
00584 iEvent.put(jets);
00585
00586
00587 }
00588
00589
00590