CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
FFTJetPileupProcessor.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: RecoJets/FFTJetProducers
4 // Class: FFTJetPileupProcessor
5 //
13 //
14 // Original Author: Igor Volobouev
15 // Created: Wed Apr 20 13:52:23 CDT 2011
16 // $Id: FFTJetPileupProcessor.cc,v 1.11 2012/11/21 03:13:26 igv Exp $
17 //
18 //
19 
20 #include <cmath>
21 #include <fstream>
22 
23 // FFTJet headers
24 #include "fftjet/FrequencyKernelConvolver.hh"
25 #include "fftjet/DiscreteGauss2d.hh"
26 #include "fftjet/EquidistantSequence.hh"
27 #include "fftjet/interpolate.hh"
28 
29 // framework include files
34 
37 // #include "DataFormats/Histograms/interface/MEtoEDMFormat.h"
39 
41 
42 // parameter parser header
44 
45 // useful utilities collected in the second base
47 
48 // Loader for the lookup tables
50 
51 
52 using namespace fftjetcms;
53 
54 //
55 // class declaration
56 //
58 {
59 public:
62 
63 protected:
64  // methods
65  void beginJob() ;
66  void produce(edm::Event&, const edm::EventSetup&);
67  void endJob() ;
68 
69 private:
73 
74  void buildKernelConvolver(const edm::ParameterSet&);
75  void mixExtraGrid();
76  void loadFlatteningFactors(const edm::EventSetup& iSetup);
77 
78  // The FFT engine
79  std::auto_ptr<MyFFTEngine> engine;
80 
81  // The pattern recognition kernel(s)
82  std::auto_ptr<fftjet::AbsFrequencyKernel> kernel2d;
83 
84  // The kernel convolver
85  std::auto_ptr<fftjet::AbsConvolverBase<Real> > convolver;
86 
87  // Storage for convolved energy flow
88  std::auto_ptr<fftjet::Grid2d<fftjetcms::Real> > convolvedFlow;
89 
90  // Filtering scales
91  std::auto_ptr<fftjet::EquidistantInLogSpace> filterScales;
92 
93  // Eta-dependent factors to use for flattening the distribution
94  // _after_ the filtering
95  std::vector<double> etaFlatteningFactors;
96 
97  // Number of percentile points to use
98  unsigned nPercentiles;
99 
100  // Bin range. Both values of 0 means use the whole range.
101  unsigned convolverMinBin;
102  unsigned convolverMaxBin;
103 
104  // Density conversion factor
106 
107  // Variable related to mixing additional grids
108  std::vector<std::string> externalGridFiles;
109  std::ifstream gridStream;
111  unsigned currentFileNum;
112 
113  // Some memory to hold the percentiles found
114  std::vector<double> percentileData;
115 
116  // Variables to load the flattening factors from
117  // the calibration database (this has to be done
118  // in sync with configuring the appropriate event
119  // setup source)
124 };
125 
126 //
127 // constructors and destructor
128 //
130  : FFTJetInterface(ps),
131  etaFlatteningFactors(
132  ps.getParameter<std::vector<double> >("etaFlatteningFactors")),
133  nPercentiles(ps.getParameter<unsigned>("nPercentiles")),
134  convolverMinBin(ps.getParameter<unsigned>("convolverMinBin")),
135  convolverMaxBin(ps.getParameter<unsigned>("convolverMaxBin")),
136  pileupEtaPhiArea(ps.getParameter<double>("pileupEtaPhiArea")),
137  externalGridFiles(ps.getParameter<std::vector<std::string> >("externalGridFiles")),
138  externalGridMaxEnergy(ps.getParameter<double>("externalGridMaxEnergy")),
139  currentFileNum(externalGridFiles.size() + 1U),
140  flatteningTableRecord(ps.getParameter<std::string>("flatteningTableRecord")),
141  flatteningTableName(ps.getParameter<std::string>("flatteningTableName")),
142  flatteningTableCategory(ps.getParameter<std::string>("flatteningTableCategory")),
143  loadFlatteningFactorsFromDB(ps.getParameter<bool>("loadFlatteningFactorsFromDB"))
144 {
145  // Build the discretization grid
147  ps.getParameter<edm::ParameterSet>("GridConfiguration"));
148  checkConfig(energyFlow, "invalid discretization grid");
149 
150  // Copy of the grid which will be used for convolutions
151  convolvedFlow = std::auto_ptr<fftjet::Grid2d<fftjetcms::Real> >(
152  new fftjet::Grid2d<fftjetcms::Real>(*energyFlow));
153 
154  // Make sure the size of flattening factors is appropriate
155  if (!etaFlatteningFactors.empty())
156  {
157  if (etaFlatteningFactors.size() != convolvedFlow->nEta())
158  throw cms::Exception("FFTJetBadConfig")
159  << "ERROR in FFTJetPileupProcessor constructor:"
160  " number of elements in the \"etaFlatteningFactors\""
161  " vector is inconsistent with the discretization grid binning"
162  << std::endl;
163  }
164 
165  // Build the FFT engine(s), pattern recognition kernel(s),
166  // and the kernel convolver
168 
169  // Build the set of pattern recognition scales
170  const unsigned nScales = ps.getParameter<unsigned>("nScales");
171  const double minScale = ps.getParameter<double>("minScale");
172  const double maxScale = ps.getParameter<double>("maxScale");
173  if (minScale <= 0.0 || maxScale < minScale || nScales == 0U)
174  throw cms::Exception("FFTJetBadConfig")
175  << "invalid filter scales" << std::endl;
176 
177  filterScales = std::auto_ptr<fftjet::EquidistantInLogSpace>(
178  new fftjet::EquidistantInLogSpace(minScale, maxScale, nScales));
179 
180  percentileData.resize(nScales*nPercentiles);
181 
182  produces<reco::DiscretizedEnergyFlow>(outputLabel);
183  produces<std::pair<double,double> >(outputLabel);
184 }
185 
186 
188 {
189  // Get the eta and phi scales for the kernel(s)
190  double kernelEtaScale = ps.getParameter<double>("kernelEtaScale");
191  const double kernelPhiScale = ps.getParameter<double>("kernelPhiScale");
192  if (kernelEtaScale <= 0.0 || kernelPhiScale <= 0.0)
193  throw cms::Exception("FFTJetBadConfig")
194  << "invalid kernel scales" << std::endl;
195 
198  convolverMaxBin > energyFlow->nEta())
199  throw cms::Exception("FFTJetBadConfig")
200  << "invalid convolver bin range" << std::endl;
201 
202  // FFT assumes that the grid extent in eta is 2*Pi. Adjust the
203  // kernel scale in eta to compensate.
204  kernelEtaScale *= (2.0*M_PI/(energyFlow->etaMax() - energyFlow->etaMin()));
205 
206  // Build the FFT engine
207  engine = std::auto_ptr<MyFFTEngine>(
208  new MyFFTEngine(energyFlow->nEta(), energyFlow->nPhi()));
209 
210  // 2d kernel
211  kernel2d = std::auto_ptr<fftjet::AbsFrequencyKernel>(
212  new fftjet::DiscreteGauss2d(
213  kernelEtaScale, kernelPhiScale,
214  energyFlow->nEta(), energyFlow->nPhi()));
215 
216  // 2d convolver
217  convolver = std::auto_ptr<fftjet::AbsConvolverBase<Real> >(
218  new fftjet::FrequencyKernelConvolver<Real,Complex>(
219  engine.get(), kernel2d.get(),
221 }
222 
223 
225 {
226 }
227 
228 
229 // ------------ method called to produce the data ------------
231  edm::Event& iEvent, const edm::EventSetup& iSetup)
232 {
233  loadInputCollection(iEvent);
235 
236  // Determine the average Et density for this event.
237  // Needs to be done here, before mixing in another grid.
238  const fftjet::Grid2d<Real>& g(*energyFlow);
239  const double densityBeforeMixing = g.sum()/pileupEtaPhiArea;
240 
241  // Mix an extra grid (if requested)
242  double densityAfterMixing = -1.0;
243  if (!externalGridFiles.empty())
244  {
245  mixExtraGrid();
246  densityAfterMixing = g.sum()/pileupEtaPhiArea;
247  }
248 
249  // Various useful variables
250  const unsigned nScales = filterScales->size();
251  const double* scales = &(*filterScales)[0];
252  Real* convData = const_cast<Real*>(convolvedFlow->data());
253  Real* sortData = convData + convolverMinBin*convolvedFlow->nPhi();
254  const unsigned dataLen = convolverMaxBin ?
256  convolvedFlow->nEta()*convolvedFlow->nPhi();
257 
258  // Load flattenning factors from DB (if requested)
260  loadFlatteningFactors(iSetup);
261 
262  // Go over all scales and perform the convolutions
263  convolver->setEventData(g.data(), g.nEta(), g.nPhi());
264  for (unsigned iscale=0; iscale<nScales; ++iscale)
265  {
266  // Perform the convolution
267  convolver->convolveWithKernel(
268  scales[iscale], convData,
269  convolvedFlow->nEta(), convolvedFlow->nPhi());
270 
271  // Apply the flattening factors
272  if (!etaFlatteningFactors.empty())
273  convolvedFlow->scaleData(&etaFlatteningFactors[0],
274  etaFlatteningFactors.size());
275 
276  // Sort the convolved data
277  std::sort(sortData, sortData+dataLen);
278 
279  // Determine the percentile points
280  for (unsigned iper=0; iper<nPercentiles; ++iper)
281  {
282  // Map percentile 0 into point number 0,
283  // 1 into point number dataLen-1
284  const double q = (iper + 0.5)/nPercentiles;
285  const double dindex = q*(dataLen-1U);
286  const unsigned ilow = static_cast<unsigned>(std::floor(dindex));
287  const double percentile = fftjet::lin_interpolate_1d(
288  ilow, ilow+1U, sortData[ilow], sortData[ilow+1U], dindex);
289 
290  // Store the calculated percentile
291  percentileData[iscale*nPercentiles + iper] = percentile;
292  }
293  }
294 
295  // Convert percentile data into a more convenient storable object
296  // and put it into the event record
297  std::auto_ptr<reco::DiscretizedEnergyFlow> pTable(
299  &percentileData[0], "FFTJetPileupProcessor",
300  -0.5, nScales-0.5, 0.0, nScales, nPercentiles));
301  iEvent.put(pTable, outputLabel);
302 
303  std::auto_ptr<std::pair<double,double> > etSum(
304  new std::pair<double,double>(densityBeforeMixing, densityAfterMixing));
305  iEvent.put(etSum, outputLabel);
306 }
307 
308 
310 {
311  const unsigned nFiles = externalGridFiles.size();
312  if (currentFileNum > nFiles)
313  {
314  // This is the first time this function is called
315  currentFileNum = 0;
317  std::ios_base::in | std::ios_base::binary);
318  if (!gridStream.is_open())
319  throw cms::Exception("FFTJetBadConfig")
320  << "ERROR in FFTJetPileupProcessor::mixExtraGrid():"
321  " failed to open external grid file "
322  << externalGridFiles[currentFileNum] << std::endl;
323  }
324 
325  const fftjet::Grid2d<float>* g = 0;
326  const unsigned maxFail = 100U;
327  unsigned nEnergyRejected = 0;
328 
329  while(!g)
330  {
332 
333  // If we can't read the grid, we need to switch to another file
334  for (unsigned ntries=0; ntries<nFiles && g == 0; ++ntries)
335  {
336  gridStream.close();
337  currentFileNum = (currentFileNum + 1U) % nFiles;
339  std::ios_base::in | std::ios_base::binary);
340  if (!gridStream.is_open())
341  throw cms::Exception("FFTJetBadConfig")
342  << "ERROR in FFTJetPileupProcessor::mixExtraGrid():"
343  " failed to open external grid file "
344  << externalGridFiles[currentFileNum] << std::endl;
346  }
347 
348  if (g)
349  if (g->sum() > externalGridMaxEnergy)
350  {
351  delete g;
352  g = 0;
353  if (++nEnergyRejected >= maxFail)
354  throw cms::Exception("FFTJetBadConfig")
355  << "ERROR in FFTJetPileupProcessor::mixExtraGrid():"
356  " too many grids in a row (" << nEnergyRejected
357  << ") failed the maximum energy cut" << std::endl;
358  }
359  }
360 
361  if (g)
362  {
363  add_Grid2d_data(energyFlow.get(), *g);
364  delete g;
365  }
366  else
367  {
368  // Too bad, no useful file found
369  throw cms::Exception("FFTJetBadConfig")
370  << "ERROR in FFTJetPileupProcessor::mixExtraGrid():"
371  " no valid grid records found" << std::endl;
372  }
373 }
374 
375 
376 // ------------ method called once each job just before starting event loop
378 {
379 }
380 
381 
382 // ------------ method called once each job just after ending the event loop
384 {
385 }
386 
387 
389 {
392  iSetup, flatteningTableRecord, h);
393  boost::shared_ptr<npstat::StorableMultivariateFunctor> f =
395 
396  // Fill out the table of flattening factors as a function of eta
397  const unsigned nEta = energyFlow->nEta();
398  etaFlatteningFactors.clear();
399  etaFlatteningFactors.reserve(nEta);
400  for (unsigned ieta=0; ieta<nEta; ++ieta)
401  {
402  const double eta = energyFlow->etaBinCenter(ieta);
403  etaFlatteningFactors.push_back((*f)(&eta, 1U));
404  }
405 }
406 
407 
408 //define this as a plug-in
T getParameter(std::string const &) const
std::auto_ptr< fftjet::Grid2d< fftjetcms::Real > > energyFlow
std::vector< std::string > externalGridFiles
void produce(edm::Event &, const edm::EventSetup &)
std::auto_ptr< fftjet::EquidistantInLogSpace > filterScales
std::auto_ptr< fftjet::Grid2d< Real > > fftjet_Grid2d_parser(const edm::ParameterSet &ps)
std::auto_ptr< fftjet::AbsConvolverBase< Real > > convolver
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
void loadInputCollection(const edm::Event &)
void checkConfig(const Ptr &ptr, const char *message)
T eta() const
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
void beginJob()
Definition: Breakpoints.cc:15
int iEvent
Definition: GenABIO.cc:243
std::vector< double > percentileData
std::auto_ptr< fftjet::Grid2d< fftjetcms::Real > > convolvedFlow
OrphanHandle< PROD > put(std::auto_ptr< PROD > product)
Put a new product.
Definition: Event.h:94
double f[11][100]
std::auto_ptr< fftjet::AbsFrequencyKernel > kernel2d
void buildKernelConvolver(const edm::ParameterSet &)
std::vector< double > etaFlatteningFactors
void loadFlatteningFactors(const edm::EventSetup &iSetup)
double Real
#define M_PI
Definition: BFit3D.cc:3
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
std::auto_ptr< MyFFTEngine > engine
fftjet::FFTWDoubleEngine MyFFTEngine
static const Mapper & instance()
void add_Grid2d_data(fftjet::Grid2d< F2 > *to, const fftjet::Grid2d< F1 > &from)
tuple size
Write out results.
const std::string outputLabel