CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/RecoJets/JetProducers/plugins/VirtualJetProducer.cc

Go to the documentation of this file.
00001 
00002 //
00003 // VirtualJetProducer
00004 // ------------------
00005 //
00006 //            04/21/2009 Philipp Schieferdecker <philipp.schieferdecker@cern.ch>
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 "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00036 
00037 #include "fastjet/SISConePlugin.hh"
00038 #include "fastjet/CMSIterativeConePlugin.hh"
00039 #include "fastjet/ATLASConePlugin.hh"
00040 #include "fastjet/CDFMidPointPlugin.hh"
00041 
00042 #include <iostream>
00043 #include <memory>
00044 #include <algorithm>
00045 #include <limits>
00046 #include <cmath>
00047 
00048 
00049 using namespace std;
00050 
00051 
00052 namespace reco {
00053   namespace helper {
00054     struct GreaterByPtPseudoJet {
00055       bool operator()( const fastjet::PseudoJet & t1, const fastjet::PseudoJet & t2 ) const {
00056         return t1.perp() > t2.perp();
00057       }
00058     };
00059 
00060   }
00061 }
00062 
00063 //______________________________________________________________________________
00064 const char *VirtualJetProducer::JetType::names[] = {
00065   "BasicJet","GenJet","CaloJet","PFJet","TrackJet","PFClusterJet"
00066 };
00067 
00068 
00069 //______________________________________________________________________________
00070 VirtualJetProducer::JetType::Type
00071 VirtualJetProducer::JetType::byName(const string &name)
00072 {
00073   const char **pos = std::find(names, names + LastJetType, name);
00074   if (pos == names + LastJetType) {
00075     std::string errorMessage="Requested jetType not supported: "+name+"\n"; 
00076     throw cms::Exception("Configuration",errorMessage);
00077   }
00078   return (Type)(pos-names);
00079 }
00080 
00081 
00082 void VirtualJetProducer::makeProduces( std::string alias, std::string tag ) 
00083 {
00084   if (makeCaloJet(jetTypeE)) {
00085     produces<reco::CaloJetCollection>(tag).setBranchAlias(alias);
00086   }
00087   else if (makePFJet(jetTypeE)) {
00088     produces<reco::PFJetCollection>(tag).setBranchAlias(alias);
00089   }
00090   else if (makeGenJet(jetTypeE)) {
00091     produces<reco::GenJetCollection>(tag).setBranchAlias(alias);
00092   }
00093   else if (makeTrackJet(jetTypeE)) {
00094     produces<reco::TrackJetCollection>(tag).setBranchAlias(alias);
00095   }
00096   else if (makePFClusterJet(jetTypeE)) {
00097     produces<reco::PFClusterJetCollection>(tag).setBranchAlias(alias);
00098   }
00099   else if (makeBasicJet(jetTypeE)) {
00100     produces<reco::BasicJetCollection>(tag).setBranchAlias(alias);
00101   }
00102 }
00103 
00105 // construction / destruction
00107 
00108 //______________________________________________________________________________
00109 VirtualJetProducer::VirtualJetProducer(const edm::ParameterSet& iConfig)
00110   : moduleLabel_   (iConfig.getParameter<string>       ("@module_label"))
00111   , src_           (iConfig.getParameter<edm::InputTag>("src"))
00112   , srcPVs_        (iConfig.getParameter<edm::InputTag>("srcPVs"))
00113   , jetType_       (iConfig.getParameter<string>       ("jetType"))
00114   , jetAlgorithm_  (iConfig.getParameter<string>       ("jetAlgorithm"))
00115   , rParam_        (iConfig.getParameter<double>       ("rParam"))
00116   , inputEtMin_    (iConfig.getParameter<double>       ("inputEtMin"))
00117   , inputEMin_     (iConfig.getParameter<double>       ("inputEMin"))
00118   , jetPtMin_      (iConfig.getParameter<double>       ("jetPtMin"))
00119   , doPVCorrection_(iConfig.getParameter<bool>         ("doPVCorrection"))
00120   , restrictInputs_(false)
00121   , maxInputs_(99999999)
00122   , doAreaFastjet_ (iConfig.getParameter<bool>         ("doAreaFastjet"))
00123   , doAreaDiskApprox_       (false)
00124   , doRhoFastjet_  (iConfig.getParameter<bool>         ("doRhoFastjet"))
00125   , voronoiRfact_           (-9)
00126   , doPUOffsetCorr_(iConfig.getParameter<bool>         ("doPUOffsetCorr"))
00127   , puWidth_(0)
00128   , nExclude_(0)
00129   , jetCollInstanceName_ ("")
00130 {
00131   anomalousTowerDef_ = std::auto_ptr<AnomalousTower>(new AnomalousTower(iConfig));
00132 
00133   //
00134   // additional parameters to think about:
00135   // - overlap threshold (set to 0.75 for the time being)
00136   // - p parameter for generalized kT (set to -2 for the time being)
00137   // - fastjet PU subtraction parameters (not yet considered)
00138   //
00139   if (jetAlgorithm_=="SISCone") {
00140     fjPlugin_ = PluginPtr( new fastjet::SISConePlugin(rParam_,0.75,0,0.0,false,
00141                                                       fastjet::SISConePlugin::SM_pttilde) );
00142     fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(&*fjPlugin_) );
00143   }
00144   else if (jetAlgorithm_=="IterativeCone") {
00145     fjPlugin_ = PluginPtr(new fastjet::CMSIterativeConePlugin(rParam_,1.0));
00146     fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(&*fjPlugin_));
00147   }
00148   else if (jetAlgorithm_=="CDFMidPoint") {
00149     fjPlugin_ = PluginPtr(new fastjet::CDFMidPointPlugin(rParam_,0.75));
00150     fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(&*fjPlugin_));
00151   }
00152   else if (jetAlgorithm_=="ATLASCone") {
00153     fjPlugin_ = PluginPtr(new fastjet::ATLASConePlugin(rParam_));
00154     fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(&*fjPlugin_));
00155   }
00156   else if (jetAlgorithm_=="Kt")
00157     fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(fastjet::kt_algorithm,rParam_));
00158   else if (jetAlgorithm_=="CambridgeAachen")
00159     fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(fastjet::cambridge_algorithm,
00160                                                            rParam_) );
00161   else if (jetAlgorithm_=="AntiKt")
00162     fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(fastjet::antikt_algorithm,rParam_) );
00163   else if (jetAlgorithm_=="GeneralizedKt")
00164     fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(fastjet::genkt_algorithm,
00165                                                             rParam_,-2) );
00166   else
00167     throw cms::Exception("Invalid jetAlgorithm")
00168       <<"Jet algorithm for VirtualJetProducer is invalid, Abort!\n";
00169   
00170   jetTypeE=JetType::byName(jetType_);
00171 
00172   if ( iConfig.exists("jetCollInstanceName") ) {
00173     jetCollInstanceName_ = iConfig.getParameter<string>("jetCollInstanceName");
00174   }
00175 
00176   if ( doPUOffsetCorr_ ) {
00177     if ( jetTypeE != JetType::CaloJet && jetTypeE != JetType::BasicJet) {
00178         throw cms::Exception("InvalidInput") << "Can only offset correct jets of type CaloJet or BasicJet";
00179      }
00180      
00181      if(iConfig.exists("subtractorName")) puSubtractorName_  =  iConfig.getParameter<string> ("subtractorName");
00182      else puSubtractorName_ = std::string();
00183      
00184      if(puSubtractorName_.empty()){
00185        edm::LogWarning("VirtualJetProducer") << "Pile Up correction on; however, pile up type is not specified. Using default... \n";
00186        subtractor_ =  boost::shared_ptr<PileUpSubtractor>(new PileUpSubtractor(iConfig));
00187      }else{
00188        subtractor_ =  boost::shared_ptr<PileUpSubtractor>(PileUpSubtractorFactory::get()->create( puSubtractorName_, iConfig));
00189      }
00190   }
00191 
00192   // do approximate disk-based area calculation => warn if conflicting request
00193   if (iConfig.exists("doAreaDiskApprox")) {
00194     doAreaDiskApprox_ = iConfig.getParameter<bool>("doAreaDiskApprox");
00195     if (doAreaDiskApprox_ && doAreaFastjet_)
00196       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";
00197 
00198   }
00199   // turn off jet collection output for speed
00200   // Voronoi-based area calculation allows for an empirical scale factor
00201   if (iConfig.exists("voronoiRfact"))
00202     voronoiRfact_     = iConfig.getParameter<double>("voronoiRfact");
00203 
00204 
00205   // do fasjet area / rho calcluation? => accept corresponding parameters
00206   if ( doAreaFastjet_ || doRhoFastjet_ ) {
00207     // Eta range of jets to be considered for Rho calculation
00208     // Should be at most (jet acceptance - jet radius)
00209     double rhoEtaMax=iConfig.getParameter<double>("Rho_EtaMax");
00210     // default Ghost_EtaMax should be 5
00211     double ghostEtaMax = iConfig.getParameter<double>("Ghost_EtaMax");
00212     // default Active_Area_Repeats 1
00213     int    activeAreaRepeats = iConfig.getParameter<int> ("Active_Area_Repeats");
00214     // default GhostArea 0.01
00215     double ghostArea = iConfig.getParameter<double> ("GhostArea");
00216     if (voronoiRfact_ <= 0)
00217       fjActiveArea_     = ActiveAreaSpecPtr(new fastjet::ActiveAreaSpec(ghostEtaMax,activeAreaRepeats,ghostArea));
00218     fjRangeDef_ = RangeDefPtr( new fastjet::RangeDefinition(rhoEtaMax) );
00219   } 
00220 
00221   // restrict inputs to first "maxInputs" towers?
00222   if ( iConfig.exists("restrictInputs") ) {
00223     restrictInputs_ = iConfig.getParameter<bool>("restrictInputs");
00224     maxInputs_      = iConfig.getParameter<unsigned int>("maxInputs");
00225   }
00226  
00227 
00228   string alias=iConfig.getUntrackedParameter<string>("alias",moduleLabel_);
00229 
00230   // make the "produces" statements
00231   makeProduces( alias, jetCollInstanceName_ );
00232 
00233   doFastJetNonUniform_ = false;
00234   if(iConfig.exists("doFastJetNonUniform")) doFastJetNonUniform_ = iConfig.getParameter<bool>   ("doFastJetNonUniform");
00235   if(doFastJetNonUniform_){
00236     puCenters_ = iConfig.getParameter<std::vector<double> >("puCenters");
00237     puWidth_ = iConfig.getParameter<double>("puWidth");
00238     nExclude_ = iConfig.getParameter<unsigned int>("nExclude");
00239   }
00240 
00241   useDeterministicSeed_ = false;
00242   minSeed_ = 0;
00243   if ( iConfig.exists("useDeterministicSeed") ) {
00244     useDeterministicSeed_ = iConfig.getParameter<bool>("useDeterministicSeed");
00245     minSeed_ =              iConfig.getParameter<unsigned int>("minSeed");
00246   }
00247 
00248   produces<std::vector<double> >("rhos");
00249   produces<std::vector<double> >("sigmas");
00250   produces<double>("rho");
00251   produces<double>("sigma");
00252   
00253 }
00254 
00255 //______________________________________________________________________________
00256 VirtualJetProducer::~VirtualJetProducer()
00257 {
00258 } 
00259 
00260 
00262 // implementation of member functions
00264 
00265 //______________________________________________________________________________
00266 void VirtualJetProducer::produce(edm::Event& iEvent,const edm::EventSetup& iSetup)
00267 {
00268 
00269   // If requested, set the fastjet random seed to a deterministic function
00270   // of the run/lumi/event. 
00271   // NOTE!!! The fastjet random number sequence is a global singleton.
00272   // Thus, we have to create an object and get access to the global singleton
00273   // in order to change it. 
00274   if ( useDeterministicSeed_ ) {
00275     fastjet::GhostedAreaSpec gas;
00276     std::vector<int> seeds(2);
00277     seeds[0] = std::max(iEvent.id().run(),minSeed_ + 3) + 3 * iEvent.id().event();
00278     seeds[1] = std::max(iEvent.id().run(),minSeed_ + 5) + 5 * iEvent.id().event();
00279     gas.set_random_status(seeds);
00280   }
00281 
00282   LogDebug("VirtualJetProducer") << "Entered produce\n";
00283   //determine signal vertex2
00284   vertex_=reco::Jet::Point(0,0,0);
00285   if (makeCaloJet(jetTypeE)&&doPVCorrection_) {
00286     LogDebug("VirtualJetProducer") << "Adding PV info\n";
00287     edm::Handle<reco::VertexCollection> pvCollection;
00288     iEvent.getByLabel(srcPVs_,pvCollection);
00289     if (pvCollection->size()>0) vertex_=pvCollection->begin()->position();
00290   }
00291 
00292   // For Pileup subtraction using offset correction:
00293   // set up geometry map
00294   if ( doPUOffsetCorr_ ) {
00295      subtractor_->setupGeometryMap(iEvent, iSetup);
00296   }
00297 
00298   // clear data
00299   LogDebug("VirtualJetProducer") << "Clear data\n";
00300   fjInputs_.clear();
00301   fjJets_.clear();
00302   inputs_.clear();  
00303   
00304   // get inputs and convert them to the fastjet format (fastjet::PeudoJet)
00305   edm::Handle<reco::CandidateView> inputsHandle;
00306   iEvent.getByLabel(src_,inputsHandle);
00307   for (size_t i = 0; i < inputsHandle->size(); ++i) {
00308     inputs_.push_back(inputsHandle->ptrAt(i));
00309   }
00310   LogDebug("VirtualJetProducer") << "Got inputs\n";
00311   
00312   // Convert candidates to fastjet::PseudoJets.
00313   // Also correct to Primary Vertex. Will modify fjInputs_
00314   // and use inputs_
00315   fjInputs_.reserve(inputs_.size());
00316   inputTowers();
00317   LogDebug("VirtualJetProducer") << "Inputted towers\n";
00318 
00319   // For Pileup subtraction using offset correction:
00320   // Subtract pedestal. 
00321   if ( doPUOffsetCorr_ ) {
00322      subtractor_->reset(inputs_,fjInputs_,fjJets_);
00323      subtractor_->calculatePedestal(fjInputs_); 
00324      subtractor_->subtractPedestal(fjInputs_);    
00325      LogDebug("VirtualJetProducer") << "Subtracted pedestal\n";
00326   }
00327 
00328   // Run algorithm. Will modify fjJets_ and allocate fjClusterSeq_. 
00329   // This will use fjInputs_
00330   runAlgorithm( iEvent, iSetup );
00331 
00332   if ( doPUOffsetCorr_ ) {
00333      subtractor_->setAlgorithm(fjClusterSeq_);
00334   }
00335 
00336   LogDebug("VirtualJetProducer") << "Ran algorithm\n";
00337   // For Pileup subtraction using offset correction:
00338   // Now we find jets and need to recalculate their energy,
00339   // mark towers participated in jet,
00340   // remove occupied towers from the list and recalculate mean and sigma
00341   // put the initial towers collection to the jet,   
00342   // and subtract from initial towers in jet recalculated mean and sigma of towers 
00343   if ( doPUOffsetCorr_ ) {
00344     LogDebug("VirtualJetProducer") << "Do PUOffsetCorr\n";
00345     vector<fastjet::PseudoJet> orphanInput;
00346     subtractor_->calculateOrphanInput(orphanInput);
00347     subtractor_->calculatePedestal(orphanInput);
00348     subtractor_->offsetCorrectJets();
00349   }
00350 
00351   // Write the output jets.
00352   // This will (by default) call the member function template
00353   // "writeJets", but can be overridden. 
00354   // this will use inputs_
00355   output( iEvent, iSetup );
00356   LogDebug("VirtualJetProducer") << "Wrote jets\n";
00357   
00358   return;
00359 }
00360 
00361 //______________________________________________________________________________
00362   
00363 void VirtualJetProducer::inputTowers( )
00364 {
00365   std::vector<edm::Ptr<reco::Candidate> >::const_iterator inBegin = inputs_.begin(),
00366     inEnd = inputs_.end(), i = inBegin;
00367   for (; i != inEnd; ++i ) {
00368     reco::CandidatePtr input = *i;
00369     if (std::isnan(input->pt()))           continue;
00370     if (input->et()    <inputEtMin_)  continue;
00371     if (input->energy()<inputEMin_)   continue;
00372     if (isAnomalousTower(input))      continue;
00373     if (input->pt() == 0) {
00374       edm::LogError("NullTransverseMomentum") << "dropping input candidate with pt=0";
00375       continue;
00376     }
00377     if (makeCaloJet(jetTypeE)&&doPVCorrection_) {
00378       const CaloTower* tower=dynamic_cast<const CaloTower*>(input.get());
00379       math::PtEtaPhiMLorentzVector ct(tower->p4(vertex_));
00380       fjInputs_.push_back(fastjet::PseudoJet(ct.px(),ct.py(),ct.pz(),ct.energy()));
00381       //std::cout << "tower:" << *tower << '\n';
00382     }
00383     else {
00384       /*
00385       if(makePFJet(jetTypeE)) {
00386         reco::PFCandidate* pfc = (reco::PFCandidate*)input.get();
00387         std::cout << "PF cand:" << *pfc << '\n';
00388       }
00389       */
00390       fjInputs_.push_back(fastjet::PseudoJet(input->px(),input->py(),input->pz(),
00391                                              input->energy()));
00392     }
00393     fjInputs_.back().set_user_index(i - inBegin);
00394   }
00395 
00396   if ( restrictInputs_ && fjInputs_.size() > maxInputs_ ) {
00397     reco::helper::GreaterByPtPseudoJet   pTComparator;
00398     std::sort(fjInputs_.begin(), fjInputs_.end(), pTComparator);
00399     fjInputs_.resize(maxInputs_);
00400     edm::LogWarning("JetRecoTooManyEntries") << "Too many inputs in the event, limiting to first " << maxInputs_ << ". Output is suspect.";
00401   }
00402 }
00403 
00404 //______________________________________________________________________________
00405 bool VirtualJetProducer::isAnomalousTower(reco::CandidatePtr input)
00406 {
00407   if (!makeCaloJet(jetTypeE)) 
00408       return false;
00409   else
00410       return (*anomalousTowerDef_)(*input);
00411 }
00412 
00413 //------------------------------------------------------------------------------
00414 // This is pure virtual. 
00415 //______________________________________________________________________________
00416 // void VirtualJetProducer::runAlgorithm( edm::Event & iEvent, edm::EventSetup const& iSetup,
00417 //                                        std::vector<edm::Ptr<reco::Candidate> > const & inputs_);
00418 
00419 //______________________________________________________________________________
00420 void VirtualJetProducer::copyConstituents(const vector<fastjet::PseudoJet>& fjConstituents,
00421                                           reco::Jet* jet)
00422 {
00423   for (unsigned int i=0;i<fjConstituents.size();++i)
00424     jet->addDaughter(inputs_[fjConstituents[i].user_index()]);
00425 }
00426 
00427 
00428 //______________________________________________________________________________
00429 vector<reco::CandidatePtr>
00430 VirtualJetProducer::getConstituents(const vector<fastjet::PseudoJet>&fjConstituents)
00431 {
00432   vector<reco::CandidatePtr> result;
00433   for (unsigned int i=0;i<fjConstituents.size();i++) {
00434     int index = fjConstituents[i].user_index();
00435     reco::CandidatePtr candidate = inputs_[index];
00436     result.push_back(candidate);
00437   }
00438   return result;
00439 }
00440 
00441 
00442 //_____________________________________________________________________________
00443 
00444 void VirtualJetProducer::output(edm::Event & iEvent, edm::EventSetup const& iSetup)
00445 {
00446   // Write jets and constitutents. Will use fjJets_, inputs_
00447   // and fjClusterSeq_
00448   switch( jetTypeE ) {
00449   case JetType::CaloJet :
00450     writeJets<reco::CaloJet>( iEvent, iSetup);
00451     break;
00452   case JetType::PFJet :
00453     writeJets<reco::PFJet>( iEvent, iSetup);
00454     break;
00455   case JetType::GenJet :
00456     writeJets<reco::GenJet>( iEvent, iSetup);
00457     break;
00458   case JetType::TrackJet :
00459     writeJets<reco::TrackJet>( iEvent, iSetup);
00460     break;
00461   case JetType::PFClusterJet :
00462     writeJets<reco::PFClusterJet>( iEvent, iSetup);
00463     break;
00464   case JetType::BasicJet :
00465     writeJets<reco::BasicJet>( iEvent, iSetup);
00466     break;
00467   default:
00468     throw cms::Exception("InvalidInput") << "invalid jet type in VirtualJetProducer\n";
00469     break;
00470   };
00471   
00472 }
00473 
00474 template< typename T >
00475 void VirtualJetProducer::writeJets( edm::Event & iEvent, edm::EventSetup const& iSetup )
00476 {
00477   if (doRhoFastjet_) {
00478     // declare jet collection without the two jets, 
00479     // for unbiased background estimation.
00480     std::vector<fastjet::PseudoJet> fjexcluded_jets;
00481     fjexcluded_jets=fjJets_;
00482     
00483     if(fjexcluded_jets.size()>2) fjexcluded_jets.resize(nExclude_);
00484     
00485     if(doFastJetNonUniform_){
00486       std::auto_ptr<std::vector<double> > rhos(new std::vector<double>);
00487       std::auto_ptr<std::vector<double> > sigmas(new std::vector<double>);
00488       int nEta = puCenters_.size();
00489       rhos->reserve(nEta);
00490       sigmas->reserve(nEta);
00491       fastjet::ClusterSequenceAreaBase const* clusterSequenceWithArea =
00492         dynamic_cast<fastjet::ClusterSequenceAreaBase const *> ( &*fjClusterSeq_ );
00493 
00494       
00495       for(int ie = 0; ie < nEta; ++ie){
00496         double eta = puCenters_[ie];
00497         double etamin=eta-puWidth_;
00498         double etamax=eta+puWidth_;
00499         fastjet::RangeDefinition range_rho(etamin,etamax);
00500         fastjet::BackgroundEstimator bkgestim(*clusterSequenceWithArea,range_rho);
00501         bkgestim.set_excluded_jets(fjexcluded_jets);
00502         rhos->push_back(bkgestim.rho());
00503         sigmas->push_back(bkgestim.sigma());
00504       }
00505       iEvent.put(rhos,"rhos");
00506       iEvent.put(sigmas,"sigmas");
00507     }else{
00508       std::auto_ptr<double> rho(new double(0.0));
00509       std::auto_ptr<double> sigma(new double(0.0));
00510       double mean_area = 0;
00511       
00512       fastjet::ClusterSequenceAreaBase const* clusterSequenceWithArea =
00513         dynamic_cast<fastjet::ClusterSequenceAreaBase const *> ( &*fjClusterSeq_ );
00514       /*
00515         const double nemptyjets = clusterSequenceWithArea->n_empty_jets(*fjRangeDef_);
00516         if(( nemptyjets  < -15 ) || ( nemptyjets > fjRangeDef_->area()+ 15)) {
00517         edm::LogWarning("StrangeNEmtpyJets") << "n_empty_jets is : " << clusterSequenceWithArea->n_empty_jets(*fjRangeDef_) << " with range " << fjRangeDef_->description() << ".";
00518         }
00519       */
00520       clusterSequenceWithArea->get_median_rho_and_sigma(*fjRangeDef_,false,*rho,*sigma,mean_area);
00521       if((*rho < 0)|| (std::isnan(*rho))) {
00522         edm::LogError("BadRho") << "rho value is " << *rho << " area:" << mean_area << " and n_empty_jets: " << clusterSequenceWithArea->n_empty_jets(*fjRangeDef_) << " with range " << fjRangeDef_->description()
00523                                 <<". Setting rho to rezo.";
00524         *rho = 0;
00525       }
00526       iEvent.put(rho,"rho");
00527       iEvent.put(sigma,"sigma");
00528     }
00529   } // doRhoFastjet_
00530   
00531   // produce output jet collection
00532   
00533   using namespace reco;
00534   
00535   std::auto_ptr<std::vector<T> > jets(new std::vector<T>() );
00536   jets->reserve(fjJets_.size());
00537   
00538 
00539   // Distance between jet centers -- for disk-based area calculation
00540   std::vector<std::vector<double> >   rij(fjJets_.size());
00541 
00542   for (unsigned int ijet=0;ijet<fjJets_.size();++ijet) {
00543     // allocate this jet
00544     T jet;
00545     // get the fastjet jet
00546     const fastjet::PseudoJet& fjJet = fjJets_[ijet];
00547 
00548     // calcuate the jet area
00549     double jetArea=0.0;
00550     if ( doAreaFastjet_ ) {
00551       fastjet::ClusterSequenceAreaBase const * clusterSequenceWithArea =
00552         dynamic_cast<fastjet::ClusterSequenceAreaBase const *>(&*fjClusterSeq_);
00553       jetArea = clusterSequenceWithArea->area(fjJet);
00554     }
00555     else if ( doAreaDiskApprox_ ) {
00556       // Here it is assumed that fjJets_ is in decreasing order of pT, 
00557       // which should happen in FastjetJetProducer::runAlgorithm() 
00558       jetArea   = M_PI;
00559       if (ijet) {
00560         std::vector<double>&  distance  = rij[ijet];
00561         distance.resize(ijet);
00562         for (unsigned jJet = 0; jJet < ijet; ++jJet) {
00563           distance[jJet]      = reco::deltaR(fjJets_[ijet],fjJets_[jJet]) / rParam_;
00564           jetArea            -= reco::helper::VirtualJetProducerHelper::intersection(distance[jJet]);
00565           for (unsigned kJet = 0; kJet < jJet; ++kJet) {
00566             jetArea          += reco::helper::VirtualJetProducerHelper::intersection(distance[jJet], distance[kJet], rij[jJet][kJet]);
00567           } // end loop over harder jets
00568         } // end loop over harder jets
00569       }
00570       jetArea  *= rParam_;
00571       jetArea  *= rParam_;
00572     }  
00573     
00574     // get the constituents from fastjet
00575     std::vector<fastjet::PseudoJet> fjConstituents =
00576       sorted_by_pt(fjClusterSeq_->constituents(fjJet));
00577     // convert them to CandidatePtr vector
00578     std::vector<CandidatePtr> constituents =
00579       getConstituents(fjConstituents);
00580 
00581     // write the specifics to the jet (simultaneously sets 4-vector, vertex).
00582     // These are overridden functions that will call the appropriate
00583     // specific allocator. 
00584     writeSpecific(jet,
00585                   Particle::LorentzVector(fjJet.px(),
00586                                           fjJet.py(),
00587                                           fjJet.pz(),
00588                                           fjJet.E()),
00589                   vertex_, 
00590                   constituents, iSetup);
00591 
00592     jet.setJetArea (jetArea);
00593     
00594     if(doPUOffsetCorr_){
00595       jet.setPileup(subtractor_->getPileUpEnergy(ijet));
00596     }else{
00597       jet.setPileup (0.0);
00598     }
00599     
00600     // add to the list
00601     jets->push_back(jet);        
00602   }
00603   
00604   // put the jets in the collection
00605   iEvent.put(jets,jetCollInstanceName_);
00606   
00607 
00608 }
00609 
00610 
00611