Rivet  3.1.4
Correlators.hh
1 // -*- C++ -*-
2 #ifndef RIVET_Correlators_HH
3 #define RIVET_Correlators_HH
4 
5 // Tools for calculating flow coefficients using correlators.
6 // Classes:
7 // Correlators: Calculates single event correlators of a given harmonic.
8 // Cumulants: An additional base class for flow analyses
9 // Use as: class MyAnalysis : public Analysis, Cumulants {};
10 // Includes a framework for calculating cumulants and flow coefficients
11 // from single event correlators, including automatic handling of
12 // statistical errors. Contains multiple internal sub-classes:
13 // CorBinBase: Base class for correlators binned in event or particle observables.
14 // CorSingleBin: A simple bin for correlators.
15 // CorBin: Has the interface of a simple bin, but does automatic calculation
16 // of statistical errors by a bootstrap method.
17 // ECorrelator: Data type for event averaged correlators.
18 //
19 // Authors: Vytautas Vislavicius, Christine O. Rasmussen, Christian Bierlich.
20 
21 #include "Rivet/Analysis.hh"
22 #include "Rivet/Projection.hh"
23 #include "Rivet/Projections/ParticleFinder.hh"
24 #include "YODA/Scatter2D.h"
25 #include <complex>
26 
27 namespace Rivet {
28  using std::complex;
29 
30 
38  class Correlators : public Projection {
39  public:
40 
54  Correlators(const ParticleFinder& fsp, int nMaxIn = 2,
55  int pMaxIn = 0, vector<double> pTbinEdgesIn = {});
56 
57  // Constructor which takes a Scatter2D to estimate bin edges.
58  Correlators(const ParticleFinder& fsp, int nMaxIn,
59  int pMaxIn, const YODA::Scatter2D hIn);
60 
68  const pair<double,double> intCorrelator(vector<int> n) const;
69 
74  const vector<pair<double,double>> pTBinnedCorrelators(vector<int> n,
75  bool overflow = false) const;
76 
85  const pair<double,double> intCorrelatorGap(const Correlators& other,
86  vector<int> n1, vector<int> n2) const;
87 
99  const vector<pair<double,double>>
100  pTBinnedCorrelatorsGap(const Correlators& other, vector<int> n1, vector<int> n2, bool overflow=false) const;
101 
106  static vector<int> hVec(int n, int m) {
107  if (m % 2 != 0) {
108  cout << "Harmonic Vector: Number of particles must be an even number." << endl;
109  return {};
110  }
111  vector<int> ret = {};
112  for (int i = 0; i < m; ++i) {
113  if (i < m/2) ret.push_back(n);
114  else ret.push_back(-n);
115  }
116  return ret;
117  }
118 
121  static pair<int,int> getMaxValues(vector< vector<int> >& hList){
122  int nMax = 0, pMax = 0;
123  for (vector<int> h : hList) {
124  int tmpN = 0, tmpP = 0;
125  for ( int i = 0; i < int(h.size()); ++i) {
126  tmpN += abs(h[i]);
127  ++tmpP;
128  }
129  if (tmpN > nMax) nMax = tmpN;
130  if (tmpP > pMax) pMax = tmpP;
131  }
132  return make_pair(nMax,pMax);
133  }
134 
135  // Clone on the heap.
136  DEFAULT_RIVET_PROJ_CLONE(Correlators);
137 
138 
139  protected:
140 
141  // @brief Loop over array and calculates Q and P vectors if needed
142  void project(const Event& e);
143 
144  // @brief Compare to other projection, testing harmonics, pT bins and underlying final state similarity
145  CmpState compare(const Projection& p) const {
146  const Correlators* other = dynamic_cast<const Correlators*>(&p);
147  if (nMax != other->nMax) return CmpState::NEQ;
148  if (pMax != other->pMax) return CmpState::NEQ;
149  if (pTbinEdges != other->pTbinEdges) return CmpState::NEQ;
150  return mkPCmp(p, "FS");
151  }
152 
153  // @brief Calculate correlators from one particle
154  void fillCorrelators(const Particle& p, const double& weight);
155 
156  // @brief Return a Q-vector.
157  const complex<double> getQ(int n, int p) const {
158  bool isNeg = (n < 0);
159  if (isNeg) return conj( qVec[abs(n)][p] );
160  else return qVec[n][p];
161  }
162 
163  // @brief Return a P-vector
164  const complex<double> getP(int n, int p, double pT = 0.) const {
165  bool isNeg = (n < 0);
166  map<double, Vec2D>::const_iterator pTitr = pVec.lower_bound(pT);
167  if (pTitr == pVec.end()) return DBL_NAN;
168  if (isNeg) return conj( pTitr->second[abs(n)][p] );
169  else return pTitr->second[n][p];
170  }
171 
172 
173  private:
174 
175  // @brief Find correlators by recursion
176  //
177  // Order = M (# of particles), n's are harmonics, p's are the powers of the weights
178  const complex<double> recCorr(int order, vector<int> n,
179  vector<int> p, bool useP, double pT = 0.) const;
180 
181  // @brief Two-particle correlator
182  //
183  // Cf. eq. (19) p6. Flag if p-vectors or q-vectors should be used to
184  // calculate the correlator.
185  const complex<double> twoPartCorr(int n1, int n2, int p1 = 1,
186  int p2 = 1, double pT = 0., bool useP = false) const;
187 
188  // Set elements in vectors to zero
189  void setToZero();
190 
191  // Shorthands for setting and comparing to zero
192  const complex<double> _ZERO = {0., 0.};
193  const double _TINY = 1e-10;
194 
195  // Shorthand typedefs for vec<vec<complex>>.
196  typedef vector< vector<complex<double>> > Vec2D;
197 
198  // Define Q-vectors and P-vectors
199  Vec2D qVec; // Q[n][p]
200  map<double, Vec2D> pVec; // p[pT][n][p]
201 
202  // The max values of n and p to be calculated.
203  int nMax, pMax;
204 
205  // pT bin-edges
206  vector<double> pTbinEdges;
207 
208  bool isPtDiff;
209 
210  };
211 
212 
213 
221  class CumulantAnalysis : public Analysis {
222  private:
223 
224  // Number of bins used for bootstrap calculation of statistical
225  // uncertainties. It is hard coded, and shout NOT be changed unless there
226  // are good reasons to do so.
227  static const int BOOT_BINS = 9;
228 
229  // Enum for choosing the method of error calculation.
230  enum Error {
231  VARIANCE,
232  ENVELOPE
233  };
234 
235  // The desired error method. Can be changed in the analysis constructor
236  // by setting it appropriately.
237  Error errorMethod;
238 
239 
241  class CorBinBase {
242  public:
243  CorBinBase() {}
244  virtual ~CorBinBase() {};
245  // Derived class should have fill and mean defined.
246  virtual void fill(const pair<double, double>& cor, const double& weight = 1.0) = 0;
247  virtual const double mean() const = 0;
248  };
249 
250 
256  class CorSingleBin : public CorBinBase {
257  public:
258 
260  CorSingleBin()
261  : _sumWX(0.), _sumW(0.), _sumW2(0.), _numEntries(0.)
262  { }
263 
264  // Destructor does nothing but must be implemented (?)
265  ~CorSingleBin() {}
266 
270  void fill(const pair<double, double>& cor, const double& weight = 1.0) {
271  // Test if denominator for the single event average is zero.
272  if (cor.second < 1e-10) return;
273  // The single event average <M> is then cor.first / cor.second.
274  // With weights this becomes just:
275  _sumWX += cor.first * weight;
276  _sumW += weight * cor.second;
277  _sumW2 += weight * weight * cor.second * cor.second;
278  _numEntries += 1.;
279  }
280 
282  const double mean() const {
283  if (_sumW < 1e-10) return 0;
284  return _sumWX / _sumW;
285  }
286 
288  const double sumW() const {
289  return _sumW;
290  }
291 
293  const double sumW2() const {
294  return _sumW2;
295  }
296 
298  const double sumWX() const {
299  return _sumWX;
300  }
301 
303  const double numEntries() const {
304  return _numEntries;
305  }
306 
308  void addContent(double ne, double sw, double sw2, double swx) {
309  _numEntries += ne;
310  _sumW += sw;
311  _sumW2 += sw2;
312  _sumWX += swx;
313  }
314 
315 
316  private:
317 
318  double _sumWX, _sumW, _sumW2, _numEntries;
319 
320  };
321 
322 
327  class CorBin : public CorBinBase {
328  public:
329 
335  CorBin() : binIndex(0), nBins(BOOT_BINS) {
336  for(size_t i = 0; i < nBins; ++i) bins.push_back(CorSingleBin());
337  }
338 
339  // Destructor does nothing but must be implemented (?)
340  ~CorBin() {}
341 
343  void fill(const pair<double, double>& cor, const double& weight = 1.0) {
344  // Test if denominator for the single event average is zero.
345  if (cor.second < 1e-10) return;
346  // Fill the correct bin.
347  bins[binIndex].fill(cor, weight);
348  if (binIndex == nBins - 1) binIndex = 0;
349  else ++binIndex;
350  }
351 
353  const double mean() const {
354  double sow = 0;
355  double sowx = 0;
356  for (auto b : bins) {
357  if (b.sumW() < 1e-10) continue;
358  sow += b.sumW();
359  sowx += b.sumWX();
360  }
361  return sowx / sow;
362  }
363 
365  const vector<CorSingleBin> getBins() const {
366  return bins;
367  }
368 
370  template<class T=CorBinBase>
371  const vector<T*> getBinPtrs() {
372  vector<T*> ret(bins.size());
373  transform(bins.begin(), bins.end(), ret.begin(),
374  [](CorSingleBin& b) {return &b;});
375  return ret;
376  }
377 
378  private:
379 
380  vector<CorSingleBin> bins;
381  size_t binIndex;
382  size_t nBins;
383 
384  };
385 
386 
387  public:
388 
393  class ECorrelator {
394  public:
395 
401  //ECorrelator(vector<int> h) : h1(h), h2({}),
402  // binX(0), binContent(0), reference() {
403  //};
404 
410  ECorrelator(vector<int> h, vector<double> binIn)
411  : h1(h), h2({}), binX(binIn), binContent(binIn.size() - 1), reference()
412  { }
413 
418  ECorrelator(vector<int> h1In, vector<int> h2In, vector<double> binIn)
419  : h1(h1In), h2(h2In), binX(binIn), binContent(binIn.size() - 1), reference()
420  { }
421 
423  void fill(const double& obs, const Correlators& c, double weight=1.0) {
424  int index = getBinIndex(obs);
425  if (index < 0) return;
426  binContent[index].fill(c.intCorrelator(h1), weight);
427  }
428 
432  void fill(const double& obs, const Correlators& c1, const Correlators& c2, double weight=1.0) {
433  if (!h2.size()) {
434  cout << "Trying to fill gapped correlator, but harmonics behind the gap (h2) are not given!" << endl;
435  return;
436  }
437  int index = getBinIndex(obs);
438  if (index < 0) return;
439  binContent[index].fill(c1.intCorrelatorGap(c2, h1, h2), weight);
440  }
441 
446  void fill(const Correlators& c, const double& weight=1.0) {
447  vector< pair<double, double> > diffCorr = c.pTBinnedCorrelators(h1);
448  // We always skip overflow when calculating the all-event average.
449  if (diffCorr.size() != binX.size() - 1)
450  cout << "Tried to fill event with wrong binning (ungapped)" << endl;
451  for (size_t i = 0; i < diffCorr.size(); ++i) {
452  int index = getBinIndex(binX[i]);
453  if (index < 0) return;
454  binContent[index].fill(diffCorr[i], weight);
455  }
456  reference.fill(c.intCorrelator(h1), weight);
457  }
458 
463  void fill(const Correlators& c1, const Correlators& c2, const double& weight = 1.0) {
464  if (!h2.size()) {
465  cout << "Trying to fill gapped correlator, but harmonics behind "
466  "the gap (h2) are not given!" << endl;
467  return;
468  }
469  vector< pair<double, double> > diffCorr = c1.pTBinnedCorrelatorsGap(c2, h1, h2);
470  // We always skip overflow when calculating the all event average.
471  if (diffCorr.size() != binX.size() - 1)
472  cout << "Tried to fill event with wrong binning (gapped)" << endl;
473  for (size_t i = 0; i < diffCorr.size(); ++i) {
474  int index = getBinIndex(binX[i]);
475  if (index < 0) return;
476  binContent[index].fill(diffCorr[i], weight);
477  }
478  reference.fill(c1.intCorrelatorGap(c2, h1, h2), weight);
479  }
480 
482  const vector<CorBin> getBins() const {
483  return binContent;
484  }
485 
487  const vector<CorBinBase*> getBinPtrs() {
488  vector<CorBinBase*> ret(binContent.size());
489  transform(binContent.begin(), binContent.end(), ret.begin(), [](CorBin& b) {return &b;});
490  return ret;
491  }
492 
494  const vector<double> getBinX() const {
495  return binX;
496  }
497 
499  const vector<int> getH1() const {
500  return h1;
501  }
502 
504  const vector<int> getH2() const {
505  return h2;
506  }
507 
509  void setReference(CorBin refIn) {
510  reference = refIn;
511  }
512 
514  const CorBin getReference() const {
515  if (reference.mean() < 1e-10)
516  cout << "Warning: ECorrelator, reference bin is zero." << endl;
517  return reference;
518  }
519 
522  void setProfs(vector<string> prIn) {
523  profs = prIn;
524  }
525 
527  bool fillFromProfile(YODA::AnalysisObjectPtr yao, string name) {
528  auto refs = reference.getBinPtrs<CorSingleBin>();
529  for (size_t i = 0; i < profs.size(); ++i) {
530  if (yao->path() == "/RAW/"+name+"/TMP/"+profs[i]) {
531  YODA::Profile1DPtr pPtr = dynamic_pointer_cast<YODA::Profile1D>(yao);
532  for (size_t j = 0; j < binX.size() - 1; ++j) {
533  const YODA::ProfileBin1D& pBin = pPtr->binAt(binX[j]);
534  auto tmp = binContent[j].getBinPtrs<CorSingleBin>();
535  tmp[i]->addContent(pBin.numEntries(), pBin.sumW(), pBin.sumW2(),
536  pBin.sumWY());
537  }
538  // Get the reference flow from the underflow bin of the histogram.
539  const YODA::Dbn2D& uBin = pPtr->underflow();
540  refs[i]->addContent(uBin.numEntries(), uBin.sumW(), uBin.sumW2(),
541  uBin.sumWY());
542  return true;
543  }
544  } // End loop of bootstrapped correlators.
545  return false;
546  }
547 
548  private:
549 
550  // Get correct bin index for a given @param obs value
551  const int getBinIndex(const double& obs) const {
552  // Find the correct index of binContent.
553  // If we are in overflow, just skip.
554  if (obs >= binX.back()) return -1;
555  // If we are in underflow, ditto.
556  if (obs < binX[0]) return -1;
557  int index = 0;
558  for (int i = 0, N = binX.size() - 1; i < N; ++i, ++index)
559  if (obs >= binX[i] && obs < binX[i + 1]) break;
560  return index;
561  }
562 
563  // The harmonics vectors.
564  vector<int> h1;
565  vector<int> h2;
566 
567  // The bins.
568  vector<double> binX;
569  vector<CorBin> binContent;
570  // The reference flow.
571  CorBin reference;
572  public:
573  // The profile histograms associated with the CorBins for streaming.
574  vector <string> profs;
575 
576  };
577 
578 
580  const pair<int, int> getMaxValues() const {
581  vector< vector<int>> harmVecs;
582  for ( auto eItr = eCorrPtrs.begin(); eItr != eCorrPtrs.end(); ++eItr) {
583  vector<int> h1 = (*eItr)->getH1();
584  vector<int> h2 = (*eItr)->getH2();
585  if (h1.size() > 0) harmVecs.push_back(h1);
586  if (h2.size() > 0) harmVecs.push_back(h2);
587  }
588  if (harmVecs.size() == 0) {
589  cout << "Warning: You tried to extract max values from harmonic "
590  "vectors, but have not booked any." << endl;
591  return pair<int,int>();
592  }
593  return Correlators::getMaxValues(harmVecs);
594  }
595 
597  typedef shared_ptr<ECorrelator> ECorrPtr;
598 
601  ECorrPtr bookECorrelator(const string name, const vector<int>& h, const YODA::Scatter2D& hIn) {
602  vector<double> binIn;
603  for (auto b : hIn.points()) binIn.push_back(b.xMin());
604  binIn.push_back(hIn.points().back().xMax());
605  return bookECorrelator(name, h, binIn);
606  }
607 
610  ECorrPtr bookECorrelator(const string name, const vector<int>& h, vector<double>& binIn) {
611  ECorrPtr ecPtr = ECorrPtr(new ECorrelator(h, binIn));
612  vector<string> eCorrProfs;
613  for (int i = 0; i < BOOT_BINS; ++i) {
614  Profile1DPtr tmp;
615  book(tmp,"TMP/"+name+"-"+to_string(i),binIn);
616  eCorrProfs.push_back(name+"-"+to_string(i));
617  }
618  ecPtr->setProfs(eCorrProfs);
619  eCorrPtrs.push_back(ecPtr);
620  return ecPtr;
621  }
622 
625  ECorrPtr bookECorrelator(const string name, const vector<int>& h1,
626  const vector<int>& h2, vector<double>& binIn) {
627  ECorrPtr ecPtr = ECorrPtr(new ECorrelator(h1, h2, binIn));
628  vector<string> eCorrProfs;
629  for (int i = 0; i < BOOT_BINS; ++i) {
630  Profile1DPtr tmp;
631  book(tmp,"TMP/"+name+"-"+to_string(i),binIn);
632  eCorrProfs.push_back(name+"-"+to_string(i));
633  }
634  ecPtr->setProfs(eCorrProfs);
635  eCorrPtrs.push_back(ecPtr);
636  return ecPtr;
637  }
638 
641  ECorrPtr bookECorrelator(const string name, const vector<int>& h1,
642  const vector<int>& h2, const YODA::Scatter2D& hIn ) {
643  vector<double> binIn;
644  for (auto b : hIn.points()) binIn.push_back(b.xMin());
645  binIn.push_back(hIn.points().back().xMax());
646  return bookECorrelator(name, h1, h2, binIn);
647  }
648 
653  ECorrPtr bookECorrelatorGap(const string name, const vector<int>& h,
654  const YODA::Scatter2D& hIn) {
655  const vector<int> h1(h.begin(), h.begin() + h.size() / 2);
656  const vector<int> h2(h.begin() + h.size() / 2, h.end());
657  return bookECorrelator(name, h1, h2, hIn);
658  }
659 
664  template<unsigned int N, unsigned int M>
665  ECorrPtr bookECorrelator(const string name, vector<double> binIn) {
666  return bookECorrelator(name, Correlators::hVec(N, M), binIn);
667  }
668 
673  template<unsigned int N, unsigned int M>
674  ECorrPtr bookECorrelator(const string name, const YODA::Scatter2D& hIn) {
675  return bookECorrelator(name, Correlators::hVec(N, M), hIn);
676  }
677 
682  template<unsigned int N, unsigned int M>
683  ECorrPtr bookECorrelatorGap(const string name, const YODA::Scatter2D& hIn) {
684  const vector<int> h = Correlators::hVec(N,M);
685  const vector<int> h1(h.begin(), h.begin() + h.size() / 2);
686  const vector<int> h2(h.begin() + h.size() / 2, h.end());
687  return bookECorrelator(name, h1, h2, hIn);
688 
689  }
690 
691  protected:
692 
693  // Bookkeeping of the event averaged correlators.
694  list<ECorrPtr> eCorrPtrs;
695 
696 
697  public:
698 
703  CumulantAnalysis(const string& n)
704  : Analysis(n), errorMethod(VARIANCE)
705  { }
706 
714  template<typename T>
715  static void fillScatter(Scatter2DPtr h, vector<double>& binx, T func) {
716  vector<YODA::Point2D> points;
717  // Test if we have proper bins from a booked histogram.
718  bool hasBins = (h->points().size() > 0);
719  for (int i = 0, N = binx.size() - 1; i < N; ++i) {
720  double xMid = (binx[i] + binx[i + 1]) / 2.0;
721  double xeMin = fabs(xMid - binx[i]);
722  double xeMax = fabs(xMid - binx[i + 1]);
723  if (hasBins) {
724  xMid = h->points()[i].x();
725  xeMin = h->points()[i].xErrMinus();
726  xeMax = h->points()[i].xErrPlus();
727  }
728  double yVal = func(i);
729  if (std::isnan(yVal)) yVal = 0.;
730  double yErr = 0;
731  points.push_back(YODA::Point2D(xMid, yVal, xeMin, xeMax, yErr, yErr));
732  }
733  h->reset();
734  h->points().clear();
735  for (int i = 0, N = points.size(); i < N; ++i) h->addPoint(points[i]);
736  }
737 
745  template<typename F>
746  const void fillScatter(Scatter2DPtr h, vector<double>& binx, F func,
747  vector<pair<double, double> >& yErr) const {
748  vector<YODA::Point2D> points;
749  // Test if we have proper bins from a booked histogram.
750  bool hasBins = (h->points().size() > 0);
751  for (int i = 0, N = binx.size() - 1; i < N; ++i) {
752  double xMid = (binx[i] + binx[i + 1]) / 2.0;
753  double xeMin = fabs(xMid - binx[i]);
754  double xeMax = fabs(xMid - binx[i + 1]);
755  if (hasBins) {
756  xMid = h->points()[i].x();
757  xeMin = h->points()[i].xErrMinus();
758  xeMax = h->points()[i].xErrPlus();
759  }
760  double yVal = func(i);
761  if (std::isnan(yVal))
762  points.push_back(YODA::Point2D(xMid, 0., xeMin, xeMax,0., 0.));
763  else
764  points.push_back(YODA::Point2D(xMid, yVal, xeMin, xeMax,
765  yErr[i].first, yErr[i].second));
766  }
767  h->reset();
768  h->points().clear();
769 
770  for (int i = 0, N = points.size(); i < N; ++i)
771  h->addPoint(points[i]);
772  }
773 
774 
778  static void nthPow(Scatter2DPtr hOut, const Scatter2DPtr hIn, const double& n, const double& k = 1.0) {
779  if (n == 0 || n == 1) {
780  cout << "Error: Do not take the 0th or 1st power of a Scatter2D,"
781  " use scale instead." << endl;
782  return;
783  }
784  if (hIn->points().size() != hOut->points().size()) {
785  cout << "nthRoot: Scatterplots: " << hIn->name() << " and " <<
786  hOut->name() << " not initialized with same length." << endl;
787  return;
788  }
789  vector<YODA::Point2D> points;
790  // The error pre-factor is k^(1/n) / n by Taylors formula.
791  double eFac = pow(k,1./n)/n;
792  for (auto b : hIn->points()) {
793  double yVal = pow(k * b.y(),n);
794  if (std::isnan(yVal))
795  points.push_back(YODA::Point2D(b.x(), 0., b.xErrMinus(),
796  b.xErrPlus(), 0, 0 ));
797  else {
798  double yemin = abs(eFac * pow(yVal,1./(n - 1.))) * b.yErrMinus();
799  if (std::isnan(yemin)) yemin = b.yErrMinus();
800  double yemax = abs(eFac * pow(yVal,1./(n - 1.))) * b.yErrPlus();
801  if (std::isnan(yemax)) yemax = b.yErrPlus();
802  points.push_back(YODA::Point2D(b.x(), yVal, b.xErrMinus(),
803  b.xErrPlus(), yemin, yemax ));
804  }
805  }
806  hOut->reset();
807  hOut->points().clear();
808  for (int i = 0, N = points.size(); i < N; ++i)
809  hOut->addPoint(points[i]);
810  }
811 
812 
816  static void nthPow(Scatter2DPtr h, const double& n, const double& k = 1.0) {
817  if (n == 0 || n == 1) {
818  cout << "Error: Do not take the 0th or 1st power of a Scatter2D,"
819  " use scale instead." << endl;
820  return;
821  }
822  vector<YODA::Point2D> points;
823  vector<YODA::Point2D> pIn = h->points();
824  // The error pre-factor is k^(1/n) / n by Taylors formula.
825  double eFac = pow(k,1./n)/n;
826  for (auto b : pIn) {
827  double yVal = pow(k * b.y(),n);
828  if (std::isnan(yVal))
829  points.push_back(YODA::Point2D(b.x(), 0., b.xErrMinus(),
830  b.xErrPlus(), 0, 0 ));
831  else {
832  double yemin = abs(eFac * pow(yVal,1./(n - 1.))) * b.yErrMinus();
833  if (std::isnan(yemin)) yemin = b.yErrMinus();
834  double yemax = abs(eFac * pow(yVal,1./(n - 1.))) * b.yErrPlus();
835  if (std::isnan(yemax)) yemax = b.yErrPlus();
836  points.push_back(YODA::Point2D(b.x(), yVal, b.xErrMinus(),
837  b.xErrPlus(), yemin, yemax ));
838  }
839  }
840  h->reset();
841  h->points().clear();
842  for (int i = 0, N = points.size(); i < N; ++i) h->addPoint(points[i]);
843  }
844 
845 
850  template<typename T>
851  static pair<double, double> sampleVariance(T func) {
852  // First we calculate the mean (two pass calculation).
853  double avg = 0.;
854  for (int i = 0; i < BOOT_BINS; ++i) avg += func(i);
855  avg /= double(BOOT_BINS);
856  // Then we find the variance.
857  double var = 0.;
858  for (int i = 0; i < BOOT_BINS; ++i) var += pow(func(i) - avg, 2.);
859  var /= (double(BOOT_BINS) - 1);
860  return pair<double, double>(var, var);
861  }
862 
863 
868  template<typename T>
869  static pair<double, double> sampleEnvelope(T func) {
870  // First we calculate the mean.
871  double avg = 0.;
872  for (int i = 0; i < BOOT_BINS; ++i) avg += func(i);
873  avg /= double(BOOT_BINS);
874  double yMax = avg;
875  double yMin = avg;
876  // Then we find the envelope using the mean as initial value.
877  for (int i = 0; i < BOOT_BINS; ++i) {
878  double yVal = func(i);
879  if (yMin > yVal) yMin = yVal;
880  else if (yMax < yVal) yMax = yVal;
881  }
882  return pair<double, double>(fabs(avg - yMin), fabs(yMax - avg));
883  }
884 
885 
887  template<typename T>
888  const pair<double, double> sampleError(T func) const {
889  if (errorMethod == VARIANCE) return sampleVariance(func);
890  else if (errorMethod == ENVELOPE) return sampleEnvelope(func);
891  else
892  cout << "Error: Error method not found!" << endl;
893  return pair<double, double>(0.,0.);
894  }
895 
896 
898  const void cnTwoInt(Scatter2DPtr h, ECorrPtr e2) const {
899  vector<CorBin> bins = e2->getBins();
900  vector<double> binx = e2->getBinX();
901  // Assert bin size.
902  if (binx.size() - 1 != bins.size()){
903  cout << "cnTwoInt: Bin size (x,y) differs!" << endl;
904  return;
905  }
906  vector<CorBinBase*> binPtrs;
907  // The mean value of the cumulant.
908  auto cn = [&] (int i) { return binPtrs[i]->mean(); };
909  // Error calculation.
910  vector<pair<double, double> > yErr;
911  for (int j = 0, N = bins.size(); j < N; ++j) {
912  binPtrs = bins[j].getBinPtrs();
913  yErr.push_back(sampleError(cn));
914  }
915  binPtrs = e2->getBinPtrs();
916  fillScatter(h, binx, cn, yErr);
917  }
918 
919 
921  const void vnTwoInt(Scatter2DPtr h, ECorrPtr e2) const {
922  cnTwoInt(h, e2);
923  nthPow(h, 0.5);
924  }
925 
926 
930  const void corrPlot(Scatter2DPtr h, ECorrPtr e) const {
931  cnTwoInt(h, e);
932  }
933 
934 
935 
936 
937  // TODO Use full path for lookup, change to single AU in output, rename.
938  void rawHookIn(YODA::AnalysisObjectPtr yao) final {
939  // Fill the corresponding ECorrelator.
940  for (auto ec : eCorrPtrs) if(ec->fillFromProfile(yao, name())) break;;
941  }
942 
947  void rawHookOut(vector<MultiweightAOPtr> raos, size_t iW) final {
948  // Loop over the correlators and extract the numbers.
949  for (auto ec : eCorrPtrs) {
950  vector<CorBin> corBins = ec->getBins();
951  vector<double> binx = ec->getBinX();
952  auto ref = ec->getReference();
953  auto refBins = ref.getBinPtrs<CorSingleBin>();
954  // Assert bin size.
955  if (binx.size() - 1 != corBins.size()){
956  cout << "corrPlot: Bin size (x,y) differs!" << endl;
957  return;
958  }
959  // Loop over the booked histograms using their names.
960  for (int i = 0, N = ec->profs.size(); i < N; ++i) {
961  for (auto rao : raos) {
962  if (rao->path() == "/"+name()+"/TMP/"+ec->profs[i]) {
963  // Get a pointer to the active profile.
964  rao.get()->setActiveWeightIdx(iW);
965  YODA::Profile1DPtr pPtr = dynamic_pointer_cast<YODA::Profile1D>(
966  rao.get()->activeYODAPtr());
967  // New bins.
968  vector<YODA::ProfileBin1D> profBins;
969  // Numbers for the summary distribution
970  double ne = 0., sow = 0., sow2 = 0.;
971  for (size_t j = 0, N = binx.size() - 1; j < N; ++j) {
972  vector<CorSingleBin*> binPtrs =
973  corBins[j].getBinPtrs<CorSingleBin>();
974  // Construct bin of the profiled quantities. We have no information
975  // (and no desire to add it) of sumWX of the profile, so really
976  // we should use a Dbn1D - but that does not work for Profile1D's.
977  profBins.push_back( YODA::ProfileBin1D(pPtr->bin(j).xEdges(),
978  YODA::Dbn2D( binPtrs[i]->numEntries(), binPtrs[i]->sumW(),
979  binPtrs[i]->sumW2(), 0., 0., binPtrs[i]->sumWX(), 0, 0)));
980  ne += binPtrs[i]->numEntries();
981  sow += binPtrs[i]->sumW();
982  sow2 += binPtrs[i]->sumW2();
983  }
984  // Put the ECorrelator into the raw histogram.
985  pPtr->reset();
986  pPtr->bins().clear();
987  // Add the bins.
988  pPtr->addBins(profBins);
989  // Set the total distribution.
990  pPtr->setTotalDbn(YODA::Dbn2D(ne,sow,sow2,0.,0.,0.,0.,0.));
991  // And reference flow in the underflow bin.
992  pPtr->setUnderflow(YODA::Dbn2D(refBins[i]->numEntries(),
993  refBins[i]->sumW(), refBins[i]->sumW2(), 0., 0.,
994  refBins[i]->sumWX(), 0., 0.));
995  }
996  }
997  }
998  }
999  }
1000 
1001  // @brief Four particle integrated cn.
1002  const void cnFourInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4) const {
1003  auto e2bins = e2->getBins();
1004  auto e4bins = e4->getBins();
1005  auto binx = e2->getBinX();
1006  if (binx.size() - 1 != e2bins.size()){
1007  cout << "cnFourInt: Bin size (x,y) differs!" << endl;
1008  return;
1009  }
1010  if (binx != e4->getBinX()) {
1011  cout << "Error in cnFourInt: Correlator x-binning differs!" << endl;
1012  return;
1013  }
1014  vector<CorBinBase*> e2binPtrs;
1015  vector<CorBinBase*> e4binPtrs;
1016  auto cn = [&] (int i) {
1017  double e22 = e2binPtrs[i]->mean() * e2binPtrs[i]->mean();
1018  return e4binPtrs[i]->mean() - 2. * e22;
1019  };
1020  // Error calculation.
1021  vector<pair<double, double> > yErr;
1022  for (int j = 0, N = e2bins.size(); j < N; ++j) {
1023  e2binPtrs = e2bins[j].getBinPtrs();
1024  e4binPtrs = e4bins[j].getBinPtrs();
1025  yErr.push_back(sampleError(cn));
1026  }
1027  // Put the bin ptrs back in place.
1028  e2binPtrs = e2->getBinPtrs();
1029  e4binPtrs = e4->getBinPtrs();
1030  fillScatter(h, binx, cn, yErr);
1031  }
1032 
1033 
1035  const void vnFourInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4) const {
1036  cnFourInt(h, e2, e4);
1037  nthPow(h, 0.25, -1.0);
1038  }
1039 
1040 
1042  const void cnSixInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4,
1043  ECorrPtr e6) const {
1044  auto e2bins = e2->getBins();
1045  auto e4bins = e4->getBins();
1046  auto e6bins = e6->getBins();
1047  auto binx = e2->getBinX();
1048  if (binx.size() - 1 != e2bins.size()){
1049  cout << "cnSixInt: Bin size (x,y) differs!" << endl;
1050  return;
1051  }
1052  if (binx != e4->getBinX() || binx != e6->getBinX()) {
1053  cout << "Error in cnSixInt: Correlator x-binning differs!" << endl;
1054  return;
1055  }
1056  vector<CorBinBase*> e2binPtrs;
1057  vector<CorBinBase*> e4binPtrs;
1058  vector<CorBinBase*> e6binPtrs;
1059  auto cn = [&] (int i) {
1060  double e23 = pow(e2binPtrs[i]->mean(), 3.0);
1061  return e6binPtrs[i]->mean() - 9.*e2binPtrs[i]->mean()*e4binPtrs[i]->mean() +
1062  12.*e23;
1063  };
1064  // Error calculation.
1065  vector<pair<double, double> > yErr;
1066  for (int j = 0, N = e2bins.size(); j < N; ++j) {
1067  e2binPtrs = e2bins[j].getBinPtrs();
1068  e4binPtrs = e4bins[j].getBinPtrs();
1069  e6binPtrs = e6bins[j].getBinPtrs();
1070  yErr.push_back(sampleError(cn));
1071  }
1072  // Put the bin ptrs back in place.
1073  e2binPtrs = e2->getBinPtrs();
1074  e4binPtrs = e4->getBinPtrs();
1075  e6binPtrs = e6->getBinPtrs();
1076  fillScatter(h, binx, cn, yErr);
1077  }
1078 
1079 
1081  const void vnSixInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4,
1082  ECorrPtr e6) const {
1083  cnSixInt(h, e2, e4, e6);
1084  nthPow(h, 1./6., 0.25);
1085  }
1086 
1087 
1089  const void cnEightInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4,
1090  ECorrPtr e6, ECorrPtr e8) const {
1091  auto e2bins = e2->getBins();
1092  auto e4bins = e4->getBins();
1093  auto e6bins = e6->getBins();
1094  auto e8bins = e8->getBins();
1095  auto binx = e2->getBinX();
1096  if (binx.size() - 1 != e2bins.size()){
1097  cout << "cnEightInt: Bin size (x,y) differs!" << endl;
1098  return;
1099  }
1100  if (binx != e4->getBinX() || binx != e6->getBinX() ||
1101  binx != e8->getBinX()) {
1102  cout << "Error in cnEightInt: Correlator x-binning differs!" << endl;
1103  return;
1104  }
1105  vector<CorBinBase*> e2binPtrs;
1106  vector<CorBinBase*> e4binPtrs;
1107  vector<CorBinBase*> e6binPtrs;
1108  vector<CorBinBase*> e8binPtrs;
1109  auto cn = [&] (int i ) {
1110  double e22 = e2binPtrs[i]->mean() * e2binPtrs[i]->mean();
1111  double e24 = e22 * e22;
1112  double e42 = e4binPtrs[i]->mean() * e4binPtrs[i]->mean();
1113  return e8binPtrs[i]->mean() - 16. * e6binPtrs[i]->mean() *
1114  e2binPtrs[i]->mean() - 18. * e42 + 144. * e4binPtrs[i]->mean()*e22
1115  - 144. * e24;
1116  };
1117  // Error calculation.
1118  vector<pair<double, double> > yErr;
1119  for (int j = 0, N = e2bins.size(); j < N; ++j) {
1120  e2binPtrs = e2bins[j].getBinPtrs();
1121  e4binPtrs = e4bins[j].getBinPtrs();
1122  e6binPtrs = e6bins[j].getBinPtrs();
1123  e8binPtrs = e8bins[j].getBinPtrs();
1124  yErr.push_back(sampleError(cn));
1125  }
1126  // Put the bin ptrs back in place.
1127  e2binPtrs = e2->getBinPtrs();
1128  e4binPtrs = e4->getBinPtrs();
1129  e6binPtrs = e6->getBinPtrs();
1130  e8binPtrs = e8->getBinPtrs();
1131  fillScatter(h, binx, cn, yErr);
1132  }
1133 
1134 
1136  const void vnEightInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4, ECorrPtr e6, ECorrPtr e8) const {
1137  cnEightInt(h, e2, e4, e6, e8);
1138  nthPow(h, 1./8., -1./33.);
1139  }
1140 
1141 
1143  const void vnTwoDiff(Scatter2DPtr h, ECorrPtr e2Dif) const {
1144  auto e2bins = e2Dif->getBins();
1145  auto ref = e2Dif->getReference();
1146  auto binx = e2Dif->getBinX();
1147  if (binx.size() -1 != e2bins.size()) {
1148  cout << "vnTwoDif: Bin size (x,y) differs!" << endl;
1149  return;
1150  }
1151  vector<CorBinBase*> e2binPtrs;
1152  vector<CorBinBase*> refPtrs;
1153  auto vn = [&] (int i) {
1154  // Test reference flow.
1155  if (ref.mean() <= 0) return 0.;
1156  return e2binPtrs[i]->mean() / sqrt(ref.mean());
1157  };
1158  // We need here a separate error function, as we don't iterate over the reference flow.
1159  auto vnerr = [&] (int i) {
1160  // Test reference flow.
1161  if (refPtrs[i]->mean() <=0) return 0.;
1162  return e2binPtrs[i]->mean() / sqrt(refPtrs[i]->mean());
1163  };
1164  // Error calculation.
1165  vector<pair<double, double> > yErr;
1166  refPtrs = ref.getBinPtrs();
1167  for (int j = 0, N = e2bins.size(); j < N; ++j) {
1168  e2binPtrs = e2bins[j].getBinPtrs();
1169  yErr.push_back(sampleError(vnerr));
1170  }
1171  // Put the e2binPtrs back in place.
1172  e2binPtrs = e2Dif->getBinPtrs();
1173  fillScatter(h, binx, vn);
1174  }
1175 
1176 
1178  const void vnFourDiff(Scatter2DPtr h, ECorrPtr e2Dif, ECorrPtr e4Dif) const {
1179  auto e2bins = e2Dif->getBins();
1180  auto e4bins = e4Dif->getBins();
1181  auto ref2 = e2Dif->getReference();
1182  auto ref4 = e4Dif->getReference();
1183  auto binx = e2Dif->getBinX();
1184  if (binx.size() - 1 != e2bins.size()){
1185  cout << "vnFourDif: Bin size (x,y) differs!" << endl;
1186  return;
1187  }
1188  if (binx != e4Dif->getBinX()) {
1189  cout << "Error in vnFourDif: Correlator x-binning differs!" << endl;
1190  return;
1191  }
1192  vector<CorBinBase*> e2binPtrs;
1193  vector<CorBinBase*> e4binPtrs;
1194  vector<CorBinBase*> ref2Ptrs;
1195  vector<CorBinBase*> ref4Ptrs;
1196  double denom = 2 * ref2.mean() * ref2.mean() - ref4.mean();
1197  auto vn = [&] (int i) {
1198  // Test denominator.
1199  if (denom <= 0 ) return 0.;
1200  return ((2 * ref2.mean() * e2bins[i].mean() - e4bins[i].mean()) / pow(denom, 0.75));
1201  };
1202  // We need here a separate error function, as we don't iterate over the reference flow.
1203  auto vnerr = [&] (int i) {
1204  double denom2 = 2 * ref2Ptrs[i]->mean() * ref2Ptrs[i]->mean() -
1205  ref4Ptrs[i]->mean();
1206  // Test denominator.
1207  if (denom2 <= 0) return 0.;
1208  return ((2 * ref2Ptrs[i]->mean() * e2binPtrs[i]->mean() - e4binPtrs[i]->mean()) / pow(denom2, 0.75));
1209  };
1210  // Error calculation.
1211  vector<pair<double, double> > yErr;
1212  ref2Ptrs = ref2.getBinPtrs();
1213  ref4Ptrs = ref4.getBinPtrs();
1214  for (int j = 0, N = e2bins.size(); j < N; ++j) {
1215  e2binPtrs = e2bins[j].getBinPtrs();
1216  e4binPtrs = e4bins[j].getBinPtrs();
1217  yErr.push_back(sampleError(vnerr));
1218  }
1219  // Put the binPtrs back in place.
1220  e2binPtrs = e2Dif->getBinPtrs();
1221  e4binPtrs = e4Dif->getBinPtrs();
1222  fillScatter(h, binx, vn, yErr);
1223  }
1224 
1225  };
1226 
1227 
1228 }
1229 
1230 #endif
ECorrPtr bookECorrelator(const string name, const YODA::Scatter2D &hIn)
Templated version of correlator booking which takes N desired harmonic and M number of particles...
Definition: Correlators.hh:674
Definition: MC_Cent_pPb.hh:10
static pair< double, double > sampleEnvelope(T func)
Calculate the bootstrapped sample envelope.
Definition: Correlators.hh:869
const vector< int > getH1() const
Get a copy of the h1 harmonic vector.
Definition: Correlators.hh:499
std::enable_if< std::is_arithmetic< NUM1 >::value &&std::is_arithmetic< NUM2 >::value, int >::type binIndex(NUM1 val, std::initializer_list< NUM2 > binedges, bool allow_overflow=false)
Return the bin index of the given value, val, given a vector of bin edges.
Definition: MathUtils.hh:416
ECorrPtr bookECorrelator(const string name, const vector< int > &h, const YODA::Scatter2D &hIn)
Book an ECorrelator in the same way as a histogram.
Definition: Correlators.hh:601
const vector< double > getBinX() const
Get a copy of the bin x-values.
Definition: Correlators.hh:494
const void vnTwoInt(Scatter2DPtr h, ECorrPtr e2) const
Two particle integrated vn.
Definition: Correlators.hh:921
void rawHookOut(vector< MultiweightAOPtr > raos, size_t iW) final
Transform RAW ECorrelator Profiles to have content before writing them. Overloaded method from Analys...
Definition: Correlators.hh:947
const void cnSixInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4, ECorrPtr e6) const
Six particle integrated cn.
Definition: Correlators.hh:1042
CmpState compare(const Projection &p) const
Definition: Correlators.hh:145
ECorrPtr bookECorrelator(const string name, const vector< int > &h, vector< double > &binIn)
Book an ECorrelator in the same way as a histogram.
Definition: Correlators.hh:610
static vector< int > hVec(int n, int m)
Construct a harmonic vectors from n harmonics and m number of particles.
Definition: Correlators.hh:106
void fill(const Correlators &c1, const Correlators &c2, const double &weight=1.0)
Fill bins with the appropriate correlator, and a rapidity gap between two Correlators.
Definition: Correlators.hh:463
const vector< CorBinBase * > getBinPtrs()
Return the bins as pointers to the base class.
Definition: Correlators.hh:487
const vector< int > getH2() const
Get a copy of the h2 harmonic vector.
Definition: Correlators.hh:504
const void vnFourDiff(Scatter2DPtr h, ECorrPtr e2Dif, ECorrPtr e4Dif) const
Four particle differential vn.
Definition: Correlators.hh:1178
static pair< double, double > sampleVariance(T func)
Calculate the bootstrapped sample variance.
Definition: Correlators.hh:851
shared_ptr< ECorrelator > ECorrPtr
Typedef of shared pointer to ECorrelator.
Definition: Correlators.hh:597
ECorrPtr bookECorrelator(const string name, const vector< int > &h1, const vector< int > &h2, const YODA::Scatter2D &hIn)
Book a gapped ECorrelator with two harmonic vectors.
Definition: Correlators.hh:641
const void cnEightInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4, ECorrPtr e6, ECorrPtr e8) const
Eight particle integrated cn.
Definition: Correlators.hh:1089
ECorrelator(vector< int > h1In, vector< int > h2In, vector< double > binIn)
Constructor for gapped correlator.
Definition: Correlators.hh:418
Particle representation, either from a HepMC::GenEvent or reconstructed.
Definition: Particle.hh:18
A helper class to calculate all event averages of correlators.
Definition: Correlators.hh:393
void fill(const double &obs, const Correlators &c1, const Correlators &c2, double weight=1.0)
Fill the appropriate bin given an input (per event) observable, e.g. centrality, with a rapidity gap ...
Definition: Correlators.hh:432
static constexpr double DBL_NAN
Convenient const for getting the double NaN value.
Definition: Utils.hh:46
Base class for projections which return subsets of an event&#39;s particles.
Definition: ParticleFinder.hh:11
ECorrPtr bookECorrelator(const string name, vector< double > binIn)
Templated version of correlator booking which takes N desired harmonic and M number of particles...
Definition: Correlators.hh:665
Tools for flow analyses.
Definition: Correlators.hh:221
const vector< pair< double, double > > pTBinnedCorrelatorsGap(const Correlators &other, vector< int > n1, vector< int > n2, bool overflow=false) const
pT differential correlators of n1 harmonic, for number n1.size()
const void vnEightInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4, ECorrPtr e6, ECorrPtr e8) const
Eight particle integrated vn.
Definition: Correlators.hh:1136
ECorrPtr bookECorrelator(const string name, const vector< int > &h1, const vector< int > &h2, vector< double > &binIn)
Book a gapped ECorrelator with two harmonic vectors.
Definition: Correlators.hh:625
void fill(const Correlators &c, const double &weight=1.0)
Fill the bins with the appropriate correlator.
Definition: Correlators.hh:446
void fill(const double &obs, const Correlators &c, double weight=1.0)
Fill the appropriate bin given an input (per event) observable, e.g. centrality.
Definition: Correlators.hh:423
void setReference(CorBin refIn)
Replace reference flow bin with another, e.g. calculated in another phase space or with other pid...
Definition: Correlators.hh:509
void setProfs(vector< string > prIn)
Set the prIn list of profile histograms associated with the internal bins.
Definition: Correlators.hh:522
This is the base class of all analysis classes in Rivet.
Definition: Analysis.hh:64
Representation of a HepMC event, and enabler of Projection caching.
Definition: Event.hh:22
Cmp< Projection > mkPCmp(const Projection &otherparent, const std::string &pname) const
const void fillScatter(Scatter2DPtr h, vector< double > &binx, F func, vector< pair< double, double > > &yErr) const
Helper method for turning correlators into Scatter2Ds with error estimates.
Definition: Correlators.hh:746
static pair< int, int > getMaxValues(vector< vector< int > > &hList)
Return the maximal values for n, p to be used in the constructor of Correlators(xxx, nMax, pMax, xxxx)
Definition: Correlators.hh:121
bool fillFromProfile(YODA::AnalysisObjectPtr yao, string name)
Fill bins with content from preloaded histograms.
Definition: Correlators.hh:527
static void nthPow(Scatter2DPtr h, const double &n, const double &k=1.0)
Take the n th power of all points in h, and put the result back in the same Scatter2D.
Definition: Correlators.hh:816
static void fillScatter(Scatter2DPtr h, vector< double > &binx, T func)
Helper method for turning correlators into Scatter2Ds.
Definition: Correlators.hh:715
const pair< double, double > sampleError(T func) const
Selection method for which sample error to use, given in the constructor.
Definition: Correlators.hh:888
const vector< pair< double, double > > pTBinnedCorrelators(vector< int > n, bool overflow=false) const
pT differential correlator of n harmonic, for number of powers n.size()
const vector< CorBin > getBins() const
Get a copy of the bin contents.
Definition: Correlators.hh:482
virtual std::string name() const
Get the name of the projection.
Definition: Projection.hh:56
const pair< double, double > intCorrelatorGap(const Correlators &other, vector< int > n1, vector< int > n2) const
Integrated correlator of n1 harmonic, for number of powers n1.size()
Projection for calculating correlators for flow measurements.
Definition: Correlators.hh:38
const pair< int, int > getMaxValues() const
Get the correct max N and max P for the set of booked correlators.
Definition: Correlators.hh:580
CumulantAnalysis(const string &n)
Constructor.
Definition: Correlators.hh:703
void project(const Event &e)
const void vnSixInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4, ECorrPtr e6) const
Six particle integrated vn.
Definition: Correlators.hh:1081
const pair< double, double > intCorrelator(vector< int > n) const
Integrated correlator of n harmonic, with the number of powers being the size of n. E.G. n should be: <<2>>_2 => n = {2, -2} <<4>>_2 => n = {2, 2, -2, -2} <<2>>_4 => n = {4, -4} <<4>>_4 => n = {4, 4, -4, 4}, and so on.
static void nthPow(Scatter2DPtr hOut, const Scatter2DPtr hIn, const double &n, const double &k=1.0)
Take the n th power of all points in hIn and put the result in hOut.
Definition: Correlators.hh:778
const void vnFourInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4) const
Four particle integrated vn.
Definition: Correlators.hh:1035
const void vnTwoDiff(Scatter2DPtr h, ECorrPtr e2Dif) const
Two particle differential vn.
Definition: Correlators.hh:1143
Correlators(const ParticleFinder &fsp, int nMaxIn=2, int pMaxIn=0, vector< double > pTbinEdgesIn={})
ECorrelator(vector< int > h, vector< double > binIn)
Constructor. Takes as argument the desired harmonic and number of correlated particles as a generic f...
Definition: Correlators.hh:410
Base class for all Rivet projections.
Definition: Projection.hh:29
const void cnTwoInt(Scatter2DPtr h, ECorrPtr e2) const
Two-particle integrated cn.
Definition: Correlators.hh:898
std::enable_if< std::is_arithmetic< NUM >::value, double >::type mean(const vector< NUM > &sample)
Definition: MathUtils.hh:458
ECorrPtr bookECorrelatorGap(const string name, const YODA::Scatter2D &hIn)
Templated version of gapped correlator booking which takes N desired harmonic and M number of particl...
Definition: Correlators.hh:683
const CorBin getReference() const
Extract the reference flow from a differential event averaged correlator.
Definition: Correlators.hh:514
ECorrPtr bookECorrelatorGap(const string name, const vector< int > &h, const YODA::Scatter2D &hIn)
Definition: Correlators.hh:653
const void corrPlot(Scatter2DPtr h, ECorrPtr e) const
Put an event-averaged correlator into a Scatter2D.
Definition: Correlators.hh:930