CMS 3D CMS Logo

HiFJGridEmptyAreaCalculator.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: HiJetBackground/HiFJGridEmptyAreaCalculator
4 // Class: HiFJGridEmptyAreaCalculator
5 // Based on: fastjet/tools/GridMedianBackgroundEstimator
6 //
7 // Original Author: Doga Gulhan
8 // Created: Wed Mar 16 14:00:04 CET 2016
9 //
10 //
11 
13 using namespace std;
14 using namespace edm;
15 
17  : gridWidth_(iConfig.getParameter<double>("gridWidth")),
18  band_(iConfig.getParameter<double>("bandWidth")),
19  hiBinCut_(iConfig.getParameter<int>("hiBinCut")),
20  doCentrality_(iConfig.getParameter<bool>("doCentrality")),
21  keepGridInfo_(iConfig.getParameter<bool>("keepGridInfo")) {
22  ymin_ = -99;
23  ymax_ = -99;
24  dy_ = -99;
25  dphi_ = -99;
26  tileArea_ = -99;
27 
28  dyJet_ = 99;
29  yminJet_ = -99;
30  ymaxJet_ = -99;
31  totalInboundArea_ = -99;
32  etaminJet_ = -99;
33  etamaxJet_ = -99;
34 
35  ny_ = 0;
36  nphi_ = 0;
37  ntotal_ = 0;
38 
39  ntotalJet_ = 0;
40  nyJet_ = 0;
41 
42  pfCandsToken_ = consumes<reco::CandidateView>(iConfig.getParameter<edm::InputTag>("pfCandSource"));
43  mapEtaToken_ = consumes<std::vector<double>>(iConfig.getParameter<edm::InputTag>("mapEtaEdges"));
44  mapRhoToken_ = consumes<std::vector<double>>(iConfig.getParameter<edm::InputTag>("mapToRho"));
45  mapRhoMToken_ = consumes<std::vector<double>>(iConfig.getParameter<edm::InputTag>("mapToRhoM"));
46  jetsToken_ = consumes<edm::View<reco::Jet>>(iConfig.getParameter<edm::InputTag>("jetSource"));
47  centralityBinToken_ = consumes<int>(iConfig.getParameter<edm::InputTag>("CentralityBinSrc"));
48 
49  //register your products
50  produces<std::vector<double>>("mapEmptyCorrFac");
51  produces<std::vector<double>>("mapToRhoCorr");
52  produces<std::vector<double>>("mapToRhoMCorr");
53  produces<std::vector<double>>("mapToRhoCorr1Bin");
54  produces<std::vector<double>>("mapToRhoMCorr1Bin");
55  //rho calculation on a grid using median
56  if (keepGridInfo_) {
57  produces<std::vector<double>>("mapRhoVsEtaGrid");
58  produces<std::vector<double>>("mapMeanRhoVsEtaGrid");
59  produces<std::vector<double>>("mapEtaMaxGrid");
60  produces<std::vector<double>>("mapEtaMinGrid");
61  }
62 }
63 
65  // do anything here that needs to be done at desctruction time
66  // (e.g. close files, deallocate resources etc.)
67 }
68 
70  using namespace edm;
71  //Values from rho calculator
72  edm::Handle<std::vector<double>> mapEtaRanges;
73  iEvent.getByToken(mapEtaToken_, mapEtaRanges);
74 
76  iEvent.getByToken(mapRhoToken_, mapRho);
77 
79  iEvent.getByToken(mapRhoMToken_, mapRhoM);
80 
81  // if doCentrality is set to true calculate empty area correction
82  // for only events with hiBin > hiBinCut
83  int hiBin = -1;
84  bool doEmptyArea = true;
85  if (doCentrality_) {
86  edm::Handle<int> cbin;
87  iEvent.getByToken(centralityBinToken_, cbin);
88  hiBin = *cbin;
89 
90  if (hiBin < hiBinCut_)
91  doEmptyArea = false;
92  }
93 
94  //Define output vectors
95  int neta = (int)mapEtaRanges->size();
96 
97  auto mapToRhoCorrOut = std::make_unique<std::vector<double>>(neta - 1, 1e-6);
98  auto mapToRhoMCorrOut = std::make_unique<std::vector<double>>(neta - 1, 1e-6);
99  auto mapToRhoCorr1BinOut = std::make_unique<std::vector<double>>(neta - 1, 1e-6);
100  auto mapToRhoMCorr1BinOut = std::make_unique<std::vector<double>>(neta - 1, 1e-6);
101 
102  setupGrid(mapEtaRanges->at(0), mapEtaRanges->at(neta - 1));
103 
104  //calculate empty area correction over full acceptance leaving eta bands on the sides
105  double allAcceptanceCorr = 1;
106  if (doEmptyArea) {
107  etaminJet_ = mapEtaRanges->at(0) - band_;
108  etamaxJet_ = mapEtaRanges->at(neta - 1) + band_;
109 
111 
112  allAcceptanceCorr = totalInboundArea_;
113  }
114 
115  //calculate empty area correction in each eta range
116  for (int ieta = 0; ieta < (neta - 1); ieta++) {
117  double correctionKt = 1;
118  double rho = mapRho->at(ieta);
119  double rhoM = mapRhoM->at(ieta);
120 
121  if (doEmptyArea) {
122  double etamin = mapEtaRanges->at(ieta);
123  double etamax = mapEtaRanges->at(ieta + 1);
124 
125  etaminJet_ = etamin + band_;
126  etamaxJet_ = etamax - band_;
127 
129  correctionKt = totalInboundArea_;
130  }
131 
132  mapToRhoCorrOut->at(ieta) = correctionKt * rho;
133  mapToRhoMCorrOut->at(ieta) = correctionKt * rhoM;
134 
135  mapToRhoCorr1BinOut->at(ieta) = allAcceptanceCorr * rho;
136  mapToRhoMCorr1BinOut->at(ieta) = allAcceptanceCorr * rhoM;
137  }
138 
139  iEvent.put(std::move(mapToRhoCorrOut), "mapToRhoCorr");
140  iEvent.put(std::move(mapToRhoMCorrOut), "mapToRhoMCorr");
141  iEvent.put(std::move(mapToRhoCorr1BinOut), "mapToRhoCorr1Bin");
142  iEvent.put(std::move(mapToRhoMCorr1BinOut), "mapToRhoMCorr1Bin");
143 
144  //calculate rho from grid as a function of eta over full range using PF candidates
145 
146  auto mapRhoVsEtaGridOut = std::make_unique<std::vector<double>>(ny_, 0.);
147  auto mapMeanRhoVsEtaGridOut = std::make_unique<std::vector<double>>(ny_, 0.);
148  auto mapEtaMaxGridOut = std::make_unique<std::vector<double>>(ny_, 0.);
149  auto mapEtaMinGridOut = std::make_unique<std::vector<double>>(ny_, 0.);
150  calculateGridRho(iEvent, iSetup);
151  if (keepGridInfo_) {
152  for (int ieta = 0; ieta < ny_; ieta++) {
153  mapRhoVsEtaGridOut->at(ieta) = rhoVsEta_[ieta];
154  mapMeanRhoVsEtaGridOut->at(ieta) = meanRhoVsEta_[ieta];
155  mapEtaMaxGridOut->at(ieta) = etaMaxGrid_[ieta];
156  mapEtaMinGridOut->at(ieta) = etaMinGrid_[ieta];
157  }
158 
159  iEvent.put(std::move(mapRhoVsEtaGridOut), "mapRhoVsEtaGrid");
160  iEvent.put(std::move(mapMeanRhoVsEtaGridOut), "mapMeanRhoVsEtaGrid");
161  iEvent.put(std::move(mapEtaMaxGridOut), "mapEtaMaxGrid");
162  iEvent.put(std::move(mapEtaMinGridOut), "mapEtaMinGrid");
163  }
164 }
165 
166 //----------------------------------------------------------------------
167 // setting a new event
168 //----------------------------------------------------------------------
169 // tell the background estimator that it has a new event, composed
170 // of the specified particles.
172  vector<vector<double>> scalarPt(ny_, vector<double>(nphi_, 0.0));
173 
175  iEvent.getByToken(pfCandsToken_, pfCands);
176  const auto& pfCandidateColl = pfCands.product();
177  for (const auto& pfCandidate : *pfCandidateColl) {
178  //use ony the particles within the eta range
179  if (pfCandidate.eta() < ymin_ || pfCandidate.eta() > ymax_)
180  continue;
181  int jeta = tileIndexEta(&pfCandidate);
182  int jphi = tileIndexPhi(&pfCandidate);
183  scalarPt[jeta][jphi] += pfCandidate.pt();
184  }
185 
186  rhoVsEta_.resize(ny_);
187  meanRhoVsEta_.resize(ny_);
188  for (int jeta = 0; jeta < ny_; jeta++) {
189  rhoVsEta_[jeta] = 0;
190  meanRhoVsEta_[jeta] = 0;
191  vector<double> rhoVsPhi;
192  int nEmpty = 0;
193 
194  for (int jphi = 0; jphi < nphi_; jphi++) {
195  double binpt = scalarPt[jeta][jphi];
196  meanRhoVsEta_[jeta] += binpt;
197  //fill in the vector for median calculation
198  if (binpt > 0)
199  rhoVsPhi.push_back(binpt);
200  else
201  nEmpty++;
202  }
203  meanRhoVsEta_[jeta] /= ((double)nphi_);
205 
206  //median calculation
207  sort(rhoVsPhi.begin(), rhoVsPhi.end());
208  //use only the nonzero grid cells for median calculation;
209  int nFull = nphi_ - nEmpty;
210  if (nFull == 0) {
211  rhoVsEta_[jeta] = 0;
212  continue;
213  }
214  if (nFull % 2 == 0) {
215  rhoVsEta_[jeta] = (rhoVsPhi[(int)(nFull / 2 - 1)] + rhoVsPhi[(int)(nFull / 2)]) / 2;
216  } else {
217  rhoVsEta_[jeta] = rhoVsPhi[(int)(nFull / 2)];
218  }
219  //correct for empty cells
220  rhoVsEta_[jeta] *= (((double)nFull) / ((double)nphi_));
221  //normalize to area
223  }
224 }
225 
228  iEvent.getByToken(jetsToken_, jets);
229 
230  //calculate jet kt area fraction inside boundary by grid
231  totalInboundArea_ = 0;
232 
233  for (const auto& jet : *jets) {
234  if (jet.eta() < etaminJet_ || jet.eta() > etamaxJet_)
235  continue;
236 
237  double areaKt = jet.jetArea();
238  setupGridJet(&jet);
239  std::vector<std::pair<int, int>> pfIndicesJet;
240  std::vector<std::pair<int, int>> pfIndicesJetInbound;
241  int nConstitJet = 0;
242  int nConstitJetInbound = 0;
243  for (const auto& daughter : jet.getJetConstituentsQuick()) {
244  auto pfCandidate = static_cast<const reco::PFCandidate*>(daughter);
245 
246  int jeta = tileIndexEtaJet(&*pfCandidate);
247  int jphi = tileIndexPhi(&*pfCandidate);
248  pfIndicesJet.push_back(std::make_pair(jphi, jeta));
249  nConstitJet++;
250  if (pfCandidate->eta() < etaminJet_ && pfCandidate->eta() > etamaxJet_)
251  continue;
252  pfIndicesJetInbound.push_back(std::make_pair(jphi, jeta));
253  nConstitJetInbound++;
254  }
255 
256  //if the jet is well within the eta range just add the area
257  if (nConstitJet == nConstitJetInbound) {
258  totalInboundArea_ += areaKt;
259  continue;
260  }
261 
262  //for jets that fall outside of eta range calculate fraction of area
263  //inside the range with a grid
264  int nthis = 0;
265  if (nConstitJet > 0)
266  nthis = numJetGridCells(pfIndicesJet);
267 
268  int nthisInbound = 0;
269  if (nConstitJetInbound > 0)
270  nthisInbound = numJetGridCells(pfIndicesJetInbound);
271 
272  double fractionArea = ((double)nthisInbound) / ((double)nthis);
273  totalInboundArea_ += areaKt * fractionArea;
274  }
275 
276  //divide by the total area in that range
278 
279  //the fraction can still be greater than 1 because kt area fraction inside
280  //the range can differ from what we calculated with the grid
281  if (totalInboundArea_ > 1)
282  totalInboundArea_ = 1;
283 }
284 
285 // #ifndef FASTJET_GMBGE_USEFJGRID
286 //----------------------------------------------------------------------
287 // protected material
288 //----------------------------------------------------------------------
289 // configure the grid
291  // since we've exchanged the arguments of the grid constructor,
292  // there's a danger of calls with exchanged ymax,spacing arguments --
293  // the following check should catch most such situations.
294  ymin_ = etamin;
295  ymax_ = etamax;
296 
298 
299  // this grid-definition code is becoming repetitive -- it should
300  // probably be moved somewhere central...
301  double nyDouble = (ymax_ - ymin_) / gridWidth_;
302  ny_ = int(nyDouble + 0.5);
303  dy_ = (ymax_ - ymin_) / ny_;
304 
305  nphi_ = int(twopi_ / gridWidth_ + 0.5);
306  dphi_ = twopi_ / nphi_;
307 
308  // some sanity checking (could throw a fastjet::Error)
309  assert(ny_ >= 1 && nphi_ >= 1);
310 
311  ntotal_ = nphi_ * ny_;
312  //_scalar_pt.resize(_ntotal);
313  tileArea_ = dy_ * dphi_;
314 
315  etaMaxGrid_.resize(ny_);
316  etaMinGrid_.resize(ny_);
317  for (int jeta = 0; jeta < ny_; jeta++) {
318  etaMinGrid_[jeta] = etamin + dy_ * ((double)jeta);
319  etaMaxGrid_[jeta] = etamin + dy_ * ((double)jeta + 1.);
320  }
321 }
322 
323 //----------------------------------------------------------------------
324 // retrieve the grid tile index for a given PseudoJet
326  // directly taking int does not work for values between -1 and 0
327  // so use floor instead
328  // double iy_double = (p.rap() - _ymin) / _dy;
329  // if (iy_double < 0.0) return -1;
330  // int iy = int(iy_double);
331  // if (iy >= _ny) return -1;
332 
333  // writing it as below gives a huge speed gain (factor two!). Even
334  // though answers are identical and the routine here is not the
335  // speed-critical step. It's not at all clear why.
336 
337  int iphi = int((pfCand->phi() + (twopi_ / 2.)) / dphi_);
338  assert(iphi >= 0 && iphi <= nphi_);
339  if (iphi == nphi_)
340  iphi = 0; // just in case of rounding errors
341 
342  return iphi;
343 }
344 
345 //----------------------------------------------------------------------
346 // retrieve the grid tile index for a given PseudoJet
348  // directly taking int does not work for values between -1 and 0
349  // so use floor instead
350  // double iy_double = (p.rap() - _ymin) / _dy;
351  // if (iy_double < 0.0) return -1;
352  // int iy = int(iy_double);
353  // if (iy >= _ny) return -1;
354 
355  // writing it as below gives a huge speed gain (factor two!). Even
356  // though answers are identical and the routine here is not the
357  // speed-critical step. It's not at all clear why.
358  int iy = int(floor((pfCand->eta() - ymin_) / dy_));
359  if (iy < 0 || iy >= ny_)
360  return -1;
361 
362  assert(iy < ny_ && iy >= 0);
363 
364  return iy;
365 }
366 
367 // #ifndef FASTJET_GMBGE_USEFJGRID
368 //----------------------------------------------------------------------
369 // protected material
370 //----------------------------------------------------------------------
371 // configure the grid
373  // since we've exchanged the arguments of the grid constructor,
374  // there's a danger of calls with exchanged ymax,spacing arguments --
375  // the following check should catch most such situations.
376  yminJet_ = jet->eta() - 0.6;
377  ymaxJet_ = jet->eta() + 0.6;
378 
380 
381  // this grid-definition code is becoming repetitive -- it should
382  // probably be moved somewhere central...
383  double nyDouble = (ymaxJet_ - yminJet_) / gridWidth_;
384  nyJet_ = int(nyDouble + 0.5);
385  dyJet_ = (ymaxJet_ - yminJet_) / nyJet_;
386 
387  assert(nyJet_ >= 1);
388 
389  ntotalJet_ = nphi_ * nyJet_;
390  //_scalar_pt.resize(_ntotal);
391 }
392 
393 //----------------------------------------------------------------------
394 // retrieve the grid tile index for a given PseudoJet
396  // directly taking int does not work for values between -1 and 0
397  // so use floor instead
398  // double iy_double = (p.rap() - _ymin) / _dy;
399  // if (iy_double < 0.0) return -1;
400  // int iy = int(iy_double);
401  // if (iy >= _ny) return -1;
402 
403  // writing it as below gives a huge speed gain (factor two!). Even
404  // though answers are identical and the routine here is not the
405  // speed-critical step. It's not at all clear why.
406  int iyjet = int(floor((pfCand->eta() - yminJet_) / dy_));
407  if (iyjet < 0 || iyjet >= nyJet_)
408  return -1;
409 
410  assert(iyjet < nyJet_ && iyjet >= 0);
411 
412  return iyjet;
413 }
414 
416  int ngrid = 0;
417  //sort phi eta grid indices in phi
418  std::sort(indices.begin(), indices.end());
419  int lowestJPhi = indices[0].first;
420  int lowestJEta = indices[0].second;
421  int highestJEta = lowestJEta;
422 
423  //for each fixed phi value calculate the number of grids in eta
424  for (const auto& index : indices) {
425  int jphi = index.first;
426  int jeta = index.second;
427  if (jphi == lowestJPhi) {
428  if (jeta < lowestJEta)
429  lowestJEta = jeta;
430  if (jeta > highestJEta)
431  highestJEta = jeta;
432  } else {
433  lowestJPhi = jphi;
434  ngrid += highestJEta - lowestJEta + 1;
435  lowestJEta = jeta;
436  highestJEta = jeta;
437  }
438  }
439  ngrid += highestJEta - lowestJEta + 1;
440  return ngrid;
441 }
442 
444 
446 
449  desc.add<edm::InputTag>("jetSource", edm::InputTag("kt4PFJets"));
450  desc.add<edm::InputTag>("CentralityBinSrc", edm::InputTag("centralityBin"));
451  desc.add<edm::InputTag>("mapEtaEdges", edm::InputTag("mapEtaEdges"));
452  desc.add<edm::InputTag>("mapToRho", edm::InputTag("mapToRho"));
453  desc.add<edm::InputTag>("mapToRhoM", edm::InputTag("mapToRhoM"));
454  desc.add<edm::InputTag>("pfCandSource", edm::InputTag("particleFlow"));
455  desc.add<double>("gridWidth", 0.05);
456  desc.add<double>("bandWidth", 0.2);
457  desc.add<bool>("doCentrality", true);
458  desc.add<int>("hiBinCut", 100);
459  desc.add<bool>("keepGridInfo", false);
460  descriptions.add("hiFJGridEmptyAreaCalculator", desc);
461 }
462 
edm::EDGetTokenT< std::vector< double > > mapRhoToken_
edm::EDGetTokenT< int > centralityBinToken_
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
int numJetGridCells(std::vector< std::pair< int, int >> &indices)
number of grid cells that overlap with jet constituents filling in the in between area ...
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
double ymin_
internal parameters for grid
edm::EDGetTokenT< edm::View< reco::Jet > > jetsToken_
input tokens
Base class for all types of Jets.
Definition: Jet.h:20
T const * product() const
Definition: Handle.h:70
void setupGrid(double eta_min, double eta_max)
configure the grid
edm::EDGetTokenT< std::vector< double > > mapRhoMToken_
assert(be >=bs)
void setupGridJet(const reco::Jet *jet)
edm::EDGetTokenT< std::vector< double > > mapEtaToken_
int tileIndexPhi(const reco::Candidate *pfCand)
int iEvent
Definition: GenABIO.cc:224
const int neta
void calculateAreaFractionOfJets(const edm::Event &iEvent, const edm::EventSetup &iSetup)
int tileIndexEta(const reco::Candidate *pfCand)
const double twopi_
information about the grid
int tileIndexEtaJet(const reco::Candidate *pfCand)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
void beginStream(edm::StreamID) override
edm::EDGetTokenT< reco::CandidateView > pfCandsToken_
void calculateGridRho(const edm::Event &iEvent, const edm::EventSetup &iSetup)
HiFJGridEmptyAreaCalculator(const edm::ParameterSet &)
void produce(edm::Event &, const edm::EventSetup &) override
void add(std::string const &label, ParameterSetDescription const &psetDescription)
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:41
HLT enums.
ALPAKA_FN_ACC ALPAKA_FN_INLINE uint32_t iy(uint32_t id)
def move(src, dest)
Definition: eostools.py:511
virtual double phi() const =0
momentum azimuthal angle
virtual double eta() const =0
momentum pseudorapidity