CMS 3D CMS Logo

FFTJetEFlowSmoother.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: FFTJetProducers
4 // Class: FFTJetEFlowSmoother
5 //
13 //
14 // Original Author: Igor Volobouev
15 // Created: Thu Jun 2 18:49:49 CDT 2011
16 //
17 //
18 
19 #include <cmath>
20 #include <memory>
21 
22 // FFTJet headers
23 #include "fftjet/FrequencyKernelConvolver.hh"
24 #include "fftjet/DiscreteGauss2d.hh"
25 #include "fftjet/EquidistantSequence.hh"
26 #include "fftjet/interpolate.hh"
27 #include "fftjet/FrequencyKernelConvolver.hh"
28 #include "fftjet/FrequencySequentialConvolver.hh"
29 #include "fftjet/DiscreteGauss1d.hh"
30 #include "fftjet/DiscreteGauss2d.hh"
31 
32 // framework include files
36 
38 #include <TH3F.h>
39 
40 // parameter parser header
42 
43 // useful utilities collected in the second base
45 
46 using namespace fftjetcms;
47 
48 //
49 // class declaration
50 //
52 public:
53  explicit FFTJetEFlowSmoother(const edm::ParameterSet&);
54  FFTJetEFlowSmoother() = delete;
56  FFTJetEFlowSmoother& operator=(const FFTJetEFlowSmoother&) = delete;
57  ~FFTJetEFlowSmoother() override;
58 
59 protected:
60  // methods
61  void produce(edm::Event&, const edm::EventSetup&) override;
62 
63 private:
64  void buildKernelConvolver(const edm::ParameterSet&);
65 
66  // Storage for convolved energy flow
67  std::unique_ptr<fftjet::Grid2d<fftjetcms::Real> > convolvedFlow;
68 
69  // Filtering scales
70  std::unique_ptr<std::vector<double> > iniScales;
71 
72  // The FFT engine(s)
73  std::unique_ptr<MyFFTEngine> engine;
74  std::unique_ptr<MyFFTEngine> anotherEngine;
75 
76  // The pattern recognition kernel(s)
77  std::unique_ptr<fftjet::AbsFrequencyKernel> kernel2d;
78  std::unique_ptr<fftjet::AbsFrequencyKernel1d> etaKernel;
79  std::unique_ptr<fftjet::AbsFrequencyKernel1d> phiKernel;
80 
81  // The kernel convolver
82  std::unique_ptr<fftjet::AbsConvolverBase<Real> > convolver;
83 
84  // The scale power to use for scaling Et
85  double scalePower;
86 
87  // Overall factor to multiply Et with
89 };
90 
91 //
92 // constructors and destructor
93 //
95  : FFTJetInterface(ps),
96  scalePower(ps.getParameter<double>("scalePower")),
97  etConversionFactor(ps.getParameter<double>("etConversionFactor")) {
98  // Build the discretization grid
100  checkConfig(energyFlow, "invalid discretization grid");
101 
102  // Copy of the grid which will be used for convolutions
103  convolvedFlow = std::make_unique<fftjet::Grid2d<fftjetcms::Real> >(*energyFlow);
104 
105  // Build the initial set of pattern recognition scales
107  checkConfig(iniScales, "invalid set of scales");
108 
109  // Build the FFT engine(s), pattern recognition kernel(s),
110  // and the kernel convolver
112 
113  // Build the set of pattern recognition scales
114  produces<TH3F>(outputLabel);
115 }
116 
118  // Check the parameter named "etaDependentScaleFactors". If the vector
119  // of scales is empty we will use 2d kernel, otherwise use 1d kernels
120  const std::vector<double> etaDependentScaleFactors(ps.getParameter<std::vector<double> >("etaDependentScaleFactors"));
121 
122  // Make sure that the number of scale factors provided is correct
123  const bool use2dKernel = etaDependentScaleFactors.empty();
124  if (!use2dKernel)
125  if (etaDependentScaleFactors.size() != energyFlow->nEta())
126  throw cms::Exception("FFTJetBadConfig") << "invalid number of eta-dependent scale factors" << std::endl;
127 
128  // Get the eta and phi scales for the kernel(s)
129  double kernelEtaScale = ps.getParameter<double>("kernelEtaScale");
130  const double kernelPhiScale = ps.getParameter<double>("kernelPhiScale");
131  if (kernelEtaScale <= 0.0 || kernelPhiScale <= 0.0)
132  throw cms::Exception("FFTJetBadConfig") << "invalid kernel scale" << std::endl;
133 
134  // FFT assumes that the grid extent in eta is 2*Pi. Adjust the
135  // kernel scale in eta to compensate.
136  kernelEtaScale *= (2.0 * M_PI / (energyFlow->etaMax() - energyFlow->etaMin()));
137 
138  // Are we going to try to fix the efficiency near detector edges?
139  const bool fixEfficiency = ps.getParameter<bool>("fixEfficiency");
140 
141  // Minimum and maximum eta bin for the convolver
142  unsigned convolverMinBin = 0, convolverMaxBin = 0;
143  if (fixEfficiency || !use2dKernel) {
144  convolverMinBin = ps.getParameter<unsigned>("convolverMinBin");
145  convolverMaxBin = ps.getParameter<unsigned>("convolverMaxBin");
146  }
147 
148  if (use2dKernel) {
149  // Build the FFT engine
150  engine = std::make_unique<MyFFTEngine>(energyFlow->nEta(), energyFlow->nPhi());
151 
152  // 2d kernel
153  kernel2d = std::unique_ptr<fftjet::AbsFrequencyKernel>(
154  new fftjet::DiscreteGauss2d(kernelEtaScale, kernelPhiScale, energyFlow->nEta(), energyFlow->nPhi()));
155 
156  // 2d convolver
157  convolver = std::unique_ptr<fftjet::AbsConvolverBase<Real> >(new fftjet::FrequencyKernelConvolver<Real, Complex>(
159  } else {
160  // Need separate FFT engines for eta and phi
161  engine = std::make_unique<MyFFTEngine>(1, energyFlow->nEta());
162  anotherEngine = std::make_unique<MyFFTEngine>(1, energyFlow->nPhi());
163 
164  // 1d kernels
165  etaKernel =
166  std::unique_ptr<fftjet::AbsFrequencyKernel1d>(new fftjet::DiscreteGauss1d(kernelEtaScale, energyFlow->nEta()));
167 
168  phiKernel =
169  std::unique_ptr<fftjet::AbsFrequencyKernel1d>(new fftjet::DiscreteGauss1d(kernelPhiScale, energyFlow->nPhi()));
170 
171  // Sequential convolver
172  convolver = std::unique_ptr<fftjet::AbsConvolverBase<Real> >(
173  new fftjet::FrequencySequentialConvolver<Real, Complex>(engine.get(),
174  anotherEngine.get(),
175  etaKernel.get(),
176  phiKernel.get(),
180  fixEfficiency));
181  }
182 }
183 
185 
186 // ------------ method called to produce the data ------------
190 
191  // Various useful variables
192  const fftjet::Grid2d<Real>& g(*energyFlow);
193  const unsigned nScales = iniScales->size();
194  const double* scales = &(*iniScales)[0];
195  Real* convData = const_cast<Real*>(convolvedFlow->data());
196  const unsigned nEta = g.nEta();
197  const unsigned nPhi = g.nPhi();
198  const double bin0edge = g.phiBin0Edge();
199 
200  // We will fill the following histo
201  auto pTable = std::make_unique<TH3F>("FFTJetEFlowSmoother",
202  "FFTJetEFlowSmoother",
203  nScales + 1U,
204  -1.5,
205  nScales - 0.5,
206  nEta,
207  g.etaMin(),
208  g.etaMax(),
209  nPhi,
210  bin0edge,
211  bin0edge + 2.0 * M_PI);
212  TH3F* h = pTable.get();
213  h->SetDirectory(nullptr);
214  h->GetXaxis()->SetTitle("Scale");
215  h->GetYaxis()->SetTitle("Eta");
216  h->GetZaxis()->SetTitle("Phi");
217 
218  // Fill the original thing
220  for (unsigned ieta = 0; ieta < nEta; ++ieta)
221  for (unsigned iphi = 0; iphi < nPhi; ++iphi)
222  h->SetBinContent(1U, ieta + 1U, iphi + 1U, factor * g.binValue(ieta, iphi));
223 
224  // Go over all scales and perform the convolutions
225  convolver->setEventData(g.data(), nEta, nPhi);
226  for (unsigned iscale = 0; iscale < nScales; ++iscale) {
227  factor = etConversionFactor * pow(scales[iscale], scalePower);
228 
229  // Perform the convolution
230  convolver->convolveWithKernel(scales[iscale], convData, convolvedFlow->nEta(), convolvedFlow->nPhi());
231 
232  // Fill the output histo
233  for (unsigned ieta = 0; ieta < nEta; ++ieta) {
234  const Real* etaData = convData + ieta * nPhi;
235  for (unsigned iphi = 0; iphi < nPhi; ++iphi)
236  h->SetBinContent(iscale + 2U, ieta + 1U, iphi + 1U, factor * etaData[iphi]);
237  }
238  }
239 
240  iEvent.put(std::move(pTable), outputLabel);
241 }
242 
243 //define this as a plug-in
std::unique_ptr< MyFFTEngine > engine
std::unique_ptr< fftjet::AbsFrequencyKernel1d > etaKernel
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
std::unique_ptr< fftjet::AbsConvolverBase< Real > > convolver
void loadInputCollection(const edm::Event &)
std::unique_ptr< MyFFTEngine > anotherEngine
FFTJetEFlowSmoother()=delete
constexpr int pow(int x)
Definition: conifer.h:24
void checkConfig(const Ptr &ptr, const char *message)
std::unique_ptr< fftjet::Grid2d< Real > > fftjet_Grid2d_parser(const edm::ParameterSet &ps)
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
Definition: Activities.doc:4
int iEvent
Definition: GenABIO.cc:224
std::unique_ptr< std::vector< double > > iniScales
std::unique_ptr< fftjet::Grid2d< fftjetcms::Real > > convolvedFlow
std::unique_ptr< fftjet::Grid2d< fftjetcms::Real > > energyFlow
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
void produce(edm::Event &, const edm::EventSetup &) override
#define M_PI
std::unique_ptr< fftjet::AbsFrequencyKernel > kernel2d
double Real
void buildKernelConvolver(const edm::ParameterSet &)
std::unique_ptr< fftjet::AbsFrequencyKernel1d > phiKernel
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
std::unique_ptr< std::vector< double > > fftjet_ScaleSet_parser(const edm::ParameterSet &ps)
const std::string outputLabel
def move(src, dest)
Definition: eostools.py:511