CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/RecoJets/FFTJetProducers/plugins/FFTJetPatRecoProducer.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    FFTJetProducers
00004 // Class:      FFTJetPatRecoProducer
00005 // 
00013 //
00014 // Original Author:  Igor Volobouev
00015 //         Created:  Tue Jun 15 12:45:45 CDT 2010
00016 // $Id: FFTJetPatRecoProducer.cc,v 1.2 2010/12/07 00:19:43 igv Exp $
00017 //
00018 //
00019 
00020 
00021 // FFTJet headers
00022 #include "fftjet/ProximityClusteringTree.hh"
00023 #include "fftjet/ClusteringSequencer.hh"
00024 #include "fftjet/ClusteringTreeSparsifier.hh"
00025 #include "fftjet/FrequencyKernelConvolver.hh"
00026 #include "fftjet/FrequencySequentialConvolver.hh"
00027 #include "fftjet/DiscreteGauss1d.hh"
00028 #include "fftjet/DiscreteGauss2d.hh"
00029 
00030 // framework include files
00031 #include "FWCore/Framework/interface/Frameworkfwd.h"
00032 #include "FWCore/Framework/interface/EDProducer.h"
00033 #include "FWCore/Framework/interface/MakerMacros.h"
00034 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00035 
00036 #include "DataFormats/Common/interface/View.h"
00037 #include "DataFormats/Common/interface/Handle.h"
00038 #include "DataFormats/VertexReco/interface/Vertex.h"
00039 #include "DataFormats/JetReco/interface/CaloJetCollection.h"
00040 #include "DataFormats/JetReco/interface/GenJetCollection.h"
00041 #include "DataFormats/JetReco/interface/PFJetCollection.h"
00042 #include "DataFormats/JetReco/interface/BasicJetCollection.h"
00043 #include "DataFormats/JetReco/interface/TrackJetCollection.h"
00044 #include "DataFormats/Candidate/interface/Candidate.h"
00045 
00046 // Energy flow object
00047 #include "RecoJets/FFTJetAlgorithms/interface/DiscretizedEnergyFlow.h"
00048 
00049 // parameter parser header
00050 #include "RecoJets/FFTJetProducers/interface/FFTJetParameterParser.h"
00051 
00052 // functions which manipulate storable trees
00053 #include "RecoJets/FFTJetAlgorithms/interface/clusteringTreeConverters.h"
00054 
00055 // useful utilities collected in the second base
00056 #include "RecoJets/FFTJetProducers/interface/FFTJetInterface.h"
00057 
00058 using namespace fftjetcms;
00059 
00060 //
00061 // class declaration
00062 //
00063 class FFTJetPatRecoProducer : public edm::EDProducer, public FFTJetInterface
00064 {
00065 public:
00066     explicit FFTJetPatRecoProducer(const edm::ParameterSet&);
00067     ~FFTJetPatRecoProducer();
00068 
00069 protected:
00070     // Useful local typedefs
00071     typedef fftjet::ProximityClusteringTree<fftjet::Peak,long> ClusteringTree;
00072     typedef fftjet::SparseClusteringTree<fftjet::Peak,long> SparseTree;
00073     typedef fftjet::ClusteringSequencer<Real> Sequencer;
00074     typedef fftjet::ClusteringTreeSparsifier<fftjet::Peak,long> Sparsifier;
00075 
00076     // methods
00077     void beginJob() ;
00078     void produce(edm::Event&, const edm::EventSetup&);
00079     void endJob() ;
00080 
00081     void buildKernelConvolver(const edm::ParameterSet&);
00082     fftjet::PeakFinder buildPeakFinder(const edm::ParameterSet&);
00083 
00084     template<class Real>
00085     void buildSparseProduct(edm::Event&) const;
00086 
00087     template<class Real>
00088     void buildDenseProduct(edm::Event&) const;
00089 
00090     // The complete clustering tree
00091     ClusteringTree* clusteringTree;
00092 
00093     // Basically, we need to create FFTJet objects
00094     // ClusteringSequencer and ClusteringTreeSparsifier
00095     // which will subsequently perform most of the work
00096     std::auto_ptr<Sequencer> sequencer;
00097     std::auto_ptr<Sparsifier> sparsifier;
00098 
00099     // The FFT engine(s)
00100     std::auto_ptr<MyFFTEngine> engine;
00101     std::auto_ptr<MyFFTEngine> anotherEngine;
00102 
00103     // The pattern recognition kernel(s)
00104     std::auto_ptr<fftjet::AbsFrequencyKernel> kernel2d;
00105     std::auto_ptr<fftjet::AbsFrequencyKernel1d> etaKernel;
00106     std::auto_ptr<fftjet::AbsFrequencyKernel1d> phiKernel;
00107 
00108     // The kernel convolver
00109     std::auto_ptr<fftjet::AbsConvolverBase<Real> > convolver;
00110 
00111     // The peak selector for the clustering tree
00112     std::auto_ptr<fftjet::Functor1<bool,fftjet::Peak> > peakSelector;
00113 
00114     // Distance calculator for the clustering tree
00115     std::auto_ptr<fftjet::AbsDistanceCalculator<fftjet::Peak> > distanceCalc;
00116 
00117     // The sparse clustering tree
00118     SparseTree sparseTree;
00119 
00120     // The following parameters will define the behavior
00121     // of the algorithm wrt insertion of the complete event
00122     // into the clustering tree
00123     const double completeEventDataCutoff;
00124 
00125     // Are we going to make clustering trees?
00126     const bool makeClusteringTree;
00127 
00128     // Are we going to verify the data conversion for double precision
00129     // storage?
00130     const bool verifyDataConversion;
00131 
00132     // Are we going to store the discretization grid?
00133     const bool storeDiscretizationGrid;
00134 
00135     // Sparsify the clustering tree?
00136     const bool sparsify;
00137 
00138 private:
00139     FFTJetPatRecoProducer();
00140     FFTJetPatRecoProducer(const FFTJetPatRecoProducer&);
00141     FFTJetPatRecoProducer& operator=(const FFTJetPatRecoProducer&);
00142 };
00143 
00144 //
00145 // constructors and destructor
00146 //
00147 FFTJetPatRecoProducer::FFTJetPatRecoProducer(const edm::ParameterSet& ps)
00148     : FFTJetInterface(ps),
00149       clusteringTree(0),
00150       completeEventDataCutoff(ps.getParameter<double>("completeEventDataCutoff")),
00151       makeClusteringTree(ps.getParameter<bool>("makeClusteringTree")),
00152       verifyDataConversion(ps.getUntrackedParameter<bool>("verifyDataConversion",false)),
00153       storeDiscretizationGrid(ps.getParameter<bool>("storeDiscretizationGrid")),
00154       sparsify(ps.getParameter<bool>("sparsify"))
00155 {
00156     // register your products
00157     if (makeClusteringTree)
00158     {
00159       if (storeInSinglePrecision())
00160             produces<reco::PattRecoTree<float,reco::PattRecoPeak<float> > >(outputLabel);
00161         else
00162             produces<reco::PattRecoTree<double,reco::PattRecoPeak<double> > >(outputLabel);
00163     }
00164     if (storeDiscretizationGrid)
00165         produces<DiscretizedEnergyFlow>(outputLabel);
00166 
00167     if (!makeClusteringTree && !storeDiscretizationGrid)
00168     {
00169         throw cms::Exception("FFTJetBadConfig")
00170             << "FFTJetPatRecoProducer is not configured to produce anything"
00171             << std::endl;
00172     }
00173 
00174     // now do whatever other initialization is needed
00175 
00176     // Build the discretization grid
00177     energyFlow = fftjet_Grid2d_parser(
00178         ps.getParameter<edm::ParameterSet>("GridConfiguration"));
00179     checkConfig(energyFlow, "invalid discretization grid");
00180 
00181     // Build the FFT engine(s), pattern recognition kernel(s),
00182     // and the kernel convolver
00183     buildKernelConvolver(ps);
00184 
00185     // Build the peak selector
00186     peakSelector = fftjet_PeakSelector_parser(
00187         ps.getParameter<edm::ParameterSet>("PeakSelectorConfiguration"));
00188     checkConfig(peakSelector, "invalid peak selector");
00189 
00190     // Build the initial set of pattern recognition scales
00191     std::auto_ptr<std::vector<double> > iniScales = fftjet_ScaleSet_parser(
00192         ps.getParameter<edm::ParameterSet>("InitialScales"));
00193     checkConfig(iniScales, "invalid set of scales");
00194 
00195     // Do we want to use the adaptive clustering tree algorithm?
00196     const unsigned maxAdaptiveScales = 
00197         ps.getParameter<unsigned>("maxAdaptiveScales");
00198     const double minAdaptiveRatioLog = 
00199         ps.getParameter<double>("minAdaptiveRatioLog");
00200     if (minAdaptiveRatioLog <= 0.0)
00201         throw cms::Exception("FFTJetBadConfig")
00202             << "bad adaptive ratio logarithm limit" << std::endl;
00203 
00204     // Make sure that all standard scales are larger than the
00205     // complete event scale
00206     if (getEventScale() > 0.0)
00207     {
00208       const double cs = getEventScale();
00209       const unsigned nscales = iniScales->size();
00210       for (unsigned i=0; i<nscales; ++i)
00211         if (cs >= (*iniScales)[i])
00212           throw cms::Exception("FFTJetBadConfig")
00213             << "incompatible scale for complete event" << std::endl;
00214     }
00215 
00216     // At this point we are ready to build the clustering sequencer
00217     sequencer = std::auto_ptr<Sequencer>(new Sequencer(
00218         convolver.get(), peakSelector.get(), buildPeakFinder(ps),
00219         *iniScales, maxAdaptiveScales, minAdaptiveRatioLog));
00220 
00221     // Build the clustering tree sparsifier
00222     const edm::ParameterSet& SparsifierConfiguration(
00223         ps.getParameter<edm::ParameterSet>("SparsifierConfiguration"));
00224     sparsifier = fftjet_ClusteringTreeSparsifier_parser(
00225         SparsifierConfiguration);
00226     checkConfig(sparsifier, "invalid sparsifier parameters");
00227 
00228     // Build the distance calculator for the clustering tree
00229     const edm::ParameterSet& TreeDistanceCalculator(
00230         ps.getParameter<edm::ParameterSet>("TreeDistanceCalculator"));
00231     distanceCalc = fftjet_DistanceCalculator_parser(TreeDistanceCalculator);
00232     checkConfig(distanceCalc, "invalid tree distance calculator");
00233 
00234     // Build the clustering tree itself
00235     clusteringTree = new ClusteringTree(distanceCalc.get());
00236 }
00237 
00238 
00239 void FFTJetPatRecoProducer::buildKernelConvolver(const edm::ParameterSet& ps)
00240 {
00241     // Check the parameter named "etaDependentScaleFactors". If the vector
00242     // of scales is empty we will use 2d kernel, otherwise use 1d kernels
00243     const std::vector<double> etaDependentScaleFactors(
00244         ps.getParameter<std::vector<double> >("etaDependentScaleFactors"));
00245 
00246     // Make sure that the number of scale factors provided is correct
00247     const bool use2dKernel = etaDependentScaleFactors.empty();
00248     if (!use2dKernel)
00249         if (etaDependentScaleFactors.size() != energyFlow->nEta())
00250             throw cms::Exception("FFTJetBadConfig")
00251                 << "invalid number of eta-dependent scale factors"
00252                 << std::endl;
00253 
00254     // Get the eta and phi scales for the kernel(s)
00255     double kernelEtaScale = ps.getParameter<double>("kernelEtaScale");
00256     const double kernelPhiScale = ps.getParameter<double>("kernelPhiScale");
00257     if (kernelEtaScale <= 0.0 || kernelPhiScale <= 0.0)
00258         throw cms::Exception("FFTJetBadConfig")
00259             << "invalid kernel scale" << std::endl;
00260 
00261     // FFT assumes that the grid extent in eta is 2*Pi. Adjust the
00262     // kernel scale in eta to compensate.
00263     kernelEtaScale *= (2.0*M_PI/(energyFlow->etaMax() - energyFlow->etaMin()));
00264 
00265     // Are we going to try to fix the efficiency near detector edges?
00266     const bool fixEfficiency = ps.getParameter<bool>("fixEfficiency");
00267 
00268     // Minimum and maximum eta bin for the convolver
00269     unsigned convolverMinBin = 0, convolverMaxBin = 0;
00270     if (fixEfficiency || !use2dKernel)
00271     {
00272         convolverMinBin = ps.getParameter<unsigned>("convolverMinBin");
00273         convolverMaxBin = ps.getParameter<unsigned>("convolverMaxBin");
00274     }
00275 
00276     if (use2dKernel)
00277     {
00278         // Build the FFT engine
00279         engine = std::auto_ptr<MyFFTEngine>(
00280             new MyFFTEngine(energyFlow->nEta(), energyFlow->nPhi()));
00281 
00282         // 2d kernel
00283         kernel2d = std::auto_ptr<fftjet::AbsFrequencyKernel>(
00284             new fftjet::DiscreteGauss2d(
00285                 kernelEtaScale, kernelPhiScale,
00286                 energyFlow->nEta(), energyFlow->nPhi()));
00287 
00288         // 2d convolver
00289         convolver = std::auto_ptr<fftjet::AbsConvolverBase<Real> >(
00290             new fftjet::FrequencyKernelConvolver<Real,Complex>(
00291                 engine.get(), kernel2d.get(),
00292                 convolverMinBin, convolverMaxBin));
00293     }
00294     else
00295     {
00296         // Need separate FFT engines for eta and phi
00297         engine = std::auto_ptr<MyFFTEngine>(
00298             new MyFFTEngine(1, energyFlow->nEta()));
00299         anotherEngine = std::auto_ptr<MyFFTEngine>(
00300             new MyFFTEngine(1, energyFlow->nPhi()));
00301 
00302         // 1d kernels
00303         etaKernel = std::auto_ptr<fftjet::AbsFrequencyKernel1d>(
00304             new fftjet::DiscreteGauss1d(kernelEtaScale, energyFlow->nEta()));
00305 
00306         phiKernel = std::auto_ptr<fftjet::AbsFrequencyKernel1d>(
00307             new fftjet::DiscreteGauss1d(kernelPhiScale, energyFlow->nPhi()));
00308 
00309         // Sequential convolver
00310         convolver = std::auto_ptr<fftjet::AbsConvolverBase<Real> >(
00311             new fftjet::FrequencySequentialConvolver<Real,Complex>(
00312                 engine.get(), anotherEngine.get(),
00313                 etaKernel.get(), phiKernel.get(),
00314                 etaDependentScaleFactors, convolverMinBin,
00315                 convolverMaxBin, fixEfficiency));
00316     }
00317 }
00318 
00319 
00320 fftjet::PeakFinder FFTJetPatRecoProducer::buildPeakFinder(const edm::ParameterSet& ps)
00321 {
00322     const double peakFinderMaxEta = ps.getParameter<double>("peakFinderMaxEta");
00323     if (peakFinderMaxEta <= 0.0)
00324         throw cms::Exception("FFTJetBadConfig")
00325             << "invalid peak finder eta cut" << std::endl;
00326     const double maxMagnitude = ps.getParameter<double>("peakFinderMaxMagnitude");
00327     int minBin = energyFlow->getEtaBin(-peakFinderMaxEta);
00328     if (minBin < 0)
00329         minBin = 0;
00330     int maxBin = energyFlow->getEtaBin(peakFinderMaxEta) + 1;
00331     if (maxBin < 0)
00332         maxBin = 0;
00333     return fftjet::PeakFinder(maxMagnitude, true, minBin, maxBin);
00334 }
00335 
00336 
00337 FFTJetPatRecoProducer::~FFTJetPatRecoProducer()
00338 {
00339     // do anything here that needs to be done at desctruction time
00340     // (e.g. close files, deallocate resources etc.)
00341     delete clusteringTree;
00342 }
00343 
00344 
00345 //
00346 // member functions
00347 //
00348 template<class Real>
00349 void FFTJetPatRecoProducer::buildSparseProduct(edm::Event& ev) const
00350 {
00351     typedef reco::PattRecoTree<Real,reco::PattRecoPeak<Real> > StoredTree;
00352 
00353     std::auto_ptr<StoredTree> tree(new StoredTree());
00354 
00355     sparsePeakTreeToStorable(sparseTree,
00356                              sequencer->maxAdaptiveScales(),
00357                              tree.get());
00358 
00359     // Check that we can restore the tree
00360     if (verifyDataConversion && !storeInSinglePrecision())
00361     {
00362         SparseTree check;
00363         const std::vector<double>& scalesUsed(sequencer->getInitialScales());
00364         sparsePeakTreeFromStorable(*tree, &scalesUsed, getEventScale(), &check);
00365         if (sparseTree != check)
00366             throw cms::Exception("FFTJetInterface")
00367                 << "Data conversion failed for sparse clustering tree"
00368                 << std::endl;
00369     }
00370 
00371     ev.put(tree, outputLabel);
00372 }
00373 
00374 
00375 template<class Real>
00376 void FFTJetPatRecoProducer::buildDenseProduct(edm::Event& ev) const
00377 {
00378     typedef reco::PattRecoTree<Real,reco::PattRecoPeak<Real> > StoredTree;
00379 
00380     std::auto_ptr<StoredTree> tree(new StoredTree());
00381 
00382     densePeakTreeToStorable(*clusteringTree,
00383                             sequencer->maxAdaptiveScales(),
00384                             tree.get());
00385 
00386     // Check that we can restore the tree
00387     if (verifyDataConversion && !storeInSinglePrecision())
00388     {
00389         ClusteringTree check(distanceCalc.get());
00390         const std::vector<double>& scalesUsed(sequencer->getInitialScales());
00391         densePeakTreeFromStorable(*tree, &scalesUsed, getEventScale(), &check);
00392         if (*clusteringTree != check)
00393             throw cms::Exception("FFTJetInterface")
00394                 << "Data conversion failed for dense clustering tree"
00395                 << std::endl;
00396     }
00397 
00398     ev.put(tree, outputLabel);
00399 }
00400 
00401 
00402 // ------------ method called to produce the data  ------------
00403 void FFTJetPatRecoProducer::produce(
00404     edm::Event& iEvent, const edm::EventSetup& iSetup)
00405 {
00406     loadInputCollection(iEvent);
00407     discretizeEnergyFlow();
00408 
00409     if (makeClusteringTree)
00410     {
00411         sequencer->run(*energyFlow, clusteringTree);
00412         if (getEventScale() > 0.0)
00413             sequencer->insertCompleteEvent(getEventScale(), *energyFlow,
00414                                            clusteringTree, completeEventDataCutoff);
00415 
00416         if (sparsify)
00417         {
00418             sparsifier->sparsify(*clusteringTree, &sparseTree);
00419 
00420             // Do not call the "sortNodes" method of the sparse tree here.
00421             // Currently, the nodes are sorted by daughter number.
00422             // This is the way we want it in storage because the stored
00423             // tree does not include daughter ordering info explicitly.
00424 
00425             if (storeInSinglePrecision())
00426                 buildSparseProduct<float>(iEvent);
00427             else
00428                 buildSparseProduct<double>(iEvent);
00429         }
00430         else
00431         {
00432             if (storeInSinglePrecision())
00433                 buildDenseProduct<float>(iEvent);
00434             else
00435                 buildDenseProduct<double>(iEvent);
00436         }
00437     }
00438 
00439     if (storeDiscretizationGrid)
00440     {
00441         const fftjet::Grid2d<Real>& g(*energyFlow);
00442 
00443         std::auto_ptr<DiscretizedEnergyFlow> flow(
00444             new DiscretizedEnergyFlow(
00445                 g.data(), g.title(), g.etaMin(), g.etaMax(),
00446                 g.phiBin0Edge(), g.nEta(), g.nPhi()));
00447 
00448         if (verifyDataConversion)
00449         {
00450             fftjet::Grid2d<Real> check(
00451                 flow->nEtaBins(), flow->etaMin(), flow->etaMax(),
00452                 flow->nPhiBins(), flow->phiBin0Edge(), flow->title());
00453             check.blockSet(flow->data(), flow->nEtaBins(), flow->nPhiBins());
00454             assert(g == check);
00455         }
00456 
00457         iEvent.put(flow, outputLabel);
00458     }
00459 }
00460 
00461 
00462 // ------------ method called once each job just before starting event loop
00463 void FFTJetPatRecoProducer::beginJob()
00464 {
00465 }
00466 
00467 
00468 // ------------ method called once each job just after ending the event loop
00469 void FFTJetPatRecoProducer::endJob()
00470 {
00471 }
00472 
00473 
00474 //define this as a plug-in
00475 DEFINE_FWK_MODULE(FFTJetPatRecoProducer);