Rivet API documentation

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