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