File indexing completed on 2025-04-19 09:06:51
0001
0002 #ifndef RIVET_Correlators_HH
0003 #define RIVET_Correlators_HH
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include "Rivet/Analysis.hh"
0023 #include "Rivet/Projection.hh"
0024 #include "Rivet/Projections/ParticleFinder.hh"
0025 #include "YODA/Scatter.h"
0026
0027 namespace Rivet {
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 class Correlators : public Projection {
0038 public:
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 Correlators(const ParticleFinder& fsp, int nMaxIn = 2,
0054 int pMaxIn = 0, vector<double> pTbinEdgesIn = {});
0055
0056
0057 Correlators(const ParticleFinder& fsp, int nMaxIn,
0058 int pMaxIn, const YODA::Estimate1D hIn);
0059
0060
0061 using Projection::operator =;
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 const pair<double,double> intCorrelator(vector<int> n) const;
0072
0073
0074
0075
0076
0077 const vector<pair<double,double>> pTBinnedCorrelators(vector<int> n,
0078 bool overflow = false) const;
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088 const pair<double,double> intCorrelatorGap(const Correlators& other,
0089 vector<int> n1, vector<int> n2) const;
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 const vector<pair<double,double>>
0103 pTBinnedCorrelatorsGap(const Correlators& other, vector<int> n1, vector<int> n2, bool overflow=false) const;
0104
0105
0106
0107
0108
0109 static vector<int> hVec(int n, int m) {
0110 if (m % 2 != 0) {
0111 cout << "Harmonic Vector: Number of particles must be an even number." << endl;
0112 return {};
0113 }
0114 vector<int> ret = {};
0115 for (int i = 0; i < m; ++i) {
0116 if (i < m/2) ret.push_back(n);
0117 else ret.push_back(-n);
0118 }
0119 return ret;
0120 }
0121
0122
0123
0124 static pair<int,int> getMaxValues(vector< vector<int> >& hList){
0125 int nMax = 0, pMax = 0;
0126 for (vector<int> h : hList) {
0127 int tmpN = 0, tmpP = 0;
0128 for ( int i = 0; i < int(h.size()); ++i) {
0129 tmpN += abs(h[i]);
0130 ++tmpP;
0131 }
0132 if (tmpN > nMax) nMax = tmpN;
0133 if (tmpP > pMax) pMax = tmpP;
0134 }
0135 return make_pair(nMax,pMax);
0136 }
0137
0138
0139 RIVET_DEFAULT_PROJ_CLONE(Correlators);
0140
0141
0142 protected:
0143
0144
0145 void project(const Event& e);
0146
0147
0148 CmpState compare(const Projection& p) const {
0149 const Correlators* other = dynamic_cast<const Correlators*>(&p);
0150 if (nMax != other->nMax) return CmpState::NEQ;
0151 if (pMax != other->pMax) return CmpState::NEQ;
0152 if (pTbinEdges != other->pTbinEdges) return CmpState::NEQ;
0153 return mkPCmp(p, "FS");
0154 }
0155
0156
0157 void fillCorrelators(const Particle& p, const double& weight);
0158
0159
0160 const complex<double> getQ(int n, int p) const {
0161 bool isNeg = (n < 0);
0162 if (isNeg) return conj( qVec[abs(n)][p] );
0163 else return qVec[n][p];
0164 }
0165
0166
0167 const complex<double> getP(int n, int p, double pT = 0.) const {
0168 bool isNeg = (n < 0);
0169 map<double, Vec2D>::const_iterator pTitr = pVec.lower_bound(pT);
0170 if (pTitr == pVec.end()) return DBL_NAN;
0171 if (isNeg) return conj( pTitr->second[abs(n)][p] );
0172 else return pTitr->second[n][p];
0173 }
0174
0175
0176 private:
0177
0178
0179
0180
0181 const complex<double> recCorr(int order, vector<int> n,
0182 vector<int> p, bool useP, double pT = 0.) const;
0183
0184
0185
0186
0187
0188 const complex<double> twoPartCorr(int n1, int n2, int p1 = 1,
0189 int p2 = 1, double pT = 0., bool useP = false) const;
0190
0191
0192 void setToZero();
0193
0194
0195 const complex<double> _ZERO = {0., 0.};
0196 const double _TINY = 1e-10;
0197
0198
0199 typedef vector< vector<complex<double>> > Vec2D;
0200
0201
0202 Vec2D qVec;
0203 map<double, Vec2D> pVec;
0204
0205
0206 int nMax, pMax;
0207
0208
0209 vector<double> pTbinEdges;
0210
0211 bool isPtDiff;
0212
0213 };
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 class CumulantAnalysis : public Analysis {
0225 private:
0226
0227
0228
0229
0230 static const int BOOT_BINS = 9;
0231
0232
0233 enum Error {
0234 VARIANCE,
0235 ENVELOPE
0236 };
0237
0238
0239
0240 Error errorMethod;
0241
0242
0243
0244 class CorBinBase {
0245 public:
0246 CorBinBase() {}
0247 virtual ~CorBinBase() {};
0248
0249 virtual void fill(const pair<double, double>& cor, const double& weight = 1.0) = 0;
0250 virtual double mean() const = 0;
0251 };
0252
0253
0254
0255
0256
0257
0258
0259 class CorSingleBin : public CorBinBase {
0260 public:
0261
0262
0263 CorSingleBin()
0264 : _sumWX(0.), _sumW(0.), _sumW2(0.), _numEntries(0.)
0265 { }
0266
0267
0268 ~CorSingleBin() {}
0269
0270
0271
0272
0273 void fill(const pair<double, double>& cor, const double& weight = 1.0) {
0274
0275 if (cor.second < 1e-10) return;
0276
0277
0278 _sumWX += cor.first * weight;
0279 _sumW += weight * cor.second;
0280 _sumW2 += weight * weight * cor.second * cor.second;
0281 _numEntries += 1.;
0282 }
0283
0284
0285 double mean() const {
0286 if (_sumW < 1e-10) return 0;
0287 return _sumWX / _sumW;
0288 }
0289
0290
0291 double sumW() const {
0292 return _sumW;
0293 }
0294
0295
0296 double sumW2() const {
0297 return _sumW2;
0298 }
0299
0300
0301 double sumWX() const {
0302 return _sumWX;
0303 }
0304
0305
0306 double numEntries() const {
0307 return _numEntries;
0308 }
0309
0310
0311 void addContent(double ne, double sw, double sw2, double swx) {
0312 _numEntries += ne;
0313 _sumW += sw;
0314 _sumW2 += sw2;
0315 _sumWX += swx;
0316 }
0317
0318
0319 private:
0320
0321 double _sumWX, _sumW, _sumW2, _numEntries;
0322
0323 };
0324
0325
0326
0327
0328
0329
0330 class CorBin : public CorBinBase {
0331 public:
0332
0333
0334
0335
0336
0337
0338 CorBin() : binIndex(0), nBins(BOOT_BINS) {
0339 for(size_t i = 0; i < nBins; ++i) bins.push_back(CorSingleBin());
0340 }
0341
0342
0343 ~CorBin() {}
0344
0345
0346 void fill(const pair<double, double>& cor, const double& weight = 1.0) {
0347
0348 if (cor.second < 1e-10) return;
0349
0350 bins[binIndex].fill(cor, weight);
0351 if (binIndex == nBins - 1) binIndex = 0;
0352 else ++binIndex;
0353 }
0354
0355
0356 double mean() const {
0357 double sow = 0;
0358 double sowx = 0;
0359 for (auto b : bins) {
0360 if (b.sumW() < 1e-10) continue;
0361 sow += b.sumW();
0362 sowx += b.sumWX();
0363 }
0364 return sowx / sow;
0365 }
0366
0367
0368 const vector<CorSingleBin>& getBins() const {
0369 return bins;
0370 }
0371
0372
0373 template<class T=CorBinBase>
0374 vector<T*> getBinPtrs() {
0375 vector<T*> ret(bins.size());
0376 transform(bins.begin(), bins.end(), ret.begin(), [](CorSingleBin& b) {return &b;});
0377 return ret;
0378 }
0379
0380
0381 template<class T=CorBinBase>
0382 vector<const T*> getBinPtrs() const {
0383 vector<const T*> ret(bins.size());
0384 transform(bins.begin(), bins.end(), ret.begin(), [](const CorSingleBin& b) {return &b;});
0385 return ret;
0386 }
0387
0388 private:
0389
0390 vector<CorSingleBin> bins;
0391 size_t binIndex;
0392 size_t nBins;
0393
0394 };
0395
0396
0397 public:
0398
0399
0400
0401
0402
0403 class ECorrelator {
0404 public:
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420 ECorrelator(const vector<int>& h, const vector<double>& binIn)
0421 : h1(h), h2({}), binX(binIn), binContent(binIn.size() - 1), reference()
0422 { }
0423
0424
0425
0426
0427
0428 ECorrelator(const vector<int>& h1In, const vector<int>& h2In, const vector<double>& binIn)
0429 : h1(h1In), h2(h2In), binX(binIn), binContent(binIn.size() - 1), reference()
0430 { }
0431
0432
0433 void fill(const double& obs, const Correlators& c, double weight=1.0) {
0434 int index = getBinIndex(obs);
0435 if (index < 0) return;
0436 binContent[index].fill(c.intCorrelator(h1), weight);
0437 }
0438
0439
0440
0441
0442 void fill(const double& obs, const Correlators& c1, const Correlators& c2, double weight=1.0) {
0443 if (!h2.size()) {
0444 cout << "Trying to fill gapped correlator, but harmonics behind the gap (h2) are not given!" << endl;
0445 return;
0446 }
0447 int index = getBinIndex(obs);
0448 if (index < 0) return;
0449 binContent[index].fill(c1.intCorrelatorGap(c2, h1, h2), weight);
0450 }
0451
0452
0453
0454
0455
0456 void fill(const Correlators& c, const double weight=1.0) {
0457 vector< pair<double, double> > diffCorr = c.pTBinnedCorrelators(h1);
0458
0459 if (diffCorr.size() != binX.size() - 1)
0460 cout << "Tried to fill event with wrong binning (ungapped)" << endl;
0461 for (size_t i = 0; i < diffCorr.size(); ++i) {
0462 int index = getBinIndex(binX[i]);
0463 if (index < 0) return;
0464 binContent[index].fill(diffCorr[i], weight);
0465 }
0466 reference.fill(c.intCorrelator(h1), weight);
0467 }
0468
0469
0470
0471
0472
0473 void fill(const Correlators& c1, const Correlators& c2, const double weight = 1.0) {
0474 if (!h2.size()) {
0475 cout << "Trying to fill gapped correlator, but harmonics behind "
0476 "the gap (h2) are not given!" << endl;
0477 return;
0478 }
0479 vector< pair<double, double> > diffCorr = c1.pTBinnedCorrelatorsGap(c2, h1, h2);
0480
0481 if (diffCorr.size() != binX.size() - 1)
0482 cout << "Tried to fill event with wrong binning (gapped)" << endl;
0483 for (size_t i = 0; i < diffCorr.size(); ++i) {
0484 int index = getBinIndex(binX[i]);
0485 if (index < 0) return;
0486 binContent[index].fill(diffCorr[i], weight);
0487 }
0488 reference.fill(c1.intCorrelatorGap(c2, h1, h2), weight);
0489 }
0490
0491
0492 const vector<CorBin>& getBins() const {
0493 return binContent;
0494 }
0495
0496
0497 vector<const CorBinBase*> getBinPtrs() const {
0498 vector<const CorBinBase*> ret(binContent.size());
0499 transform(binContent.begin(), binContent.end(), ret.begin(), [](const CorBin& b) {return &b;});
0500 return ret;
0501 }
0502
0503
0504 const vector<double>& getBinX() const {
0505 return binX;
0506 }
0507
0508
0509 const vector<int>& getH1() const {
0510 return h1;
0511 }
0512
0513
0514 const vector<int>& getH2() const {
0515 return h2;
0516 }
0517
0518
0519 void setReference(CorBin refIn) {
0520 reference = refIn;
0521 }
0522
0523
0524 CorBin getReference() const {
0525 if (reference.mean() < 1e-10)
0526 cout << "Warning: ECorrelator, reference bin is zero." << endl;
0527 return reference;
0528 }
0529
0530
0531
0532 void setProfs(vector<string> prIn) {
0533 profs = prIn;
0534 }
0535
0536
0537 bool fillFromProfile(YODA::AnalysisObjectPtr yao, string name) {
0538 auto refs = reference.getBinPtrs<CorSingleBin>();
0539 for (size_t i = 0; i < profs.size(); ++i) {
0540 if (yao->path() == "/RAW/"+name+"/TMP/"+profs[i]) {
0541 YODA::Profile1DPtr pPtr = dynamic_pointer_cast<YODA::Profile1D>(yao);
0542 for (size_t j = 0; j < binX.size() - 1; ++j) {
0543 const YODA::Dbn2D& pBin = pPtr->binAt(binX[j]);
0544 auto tmp = binContent[j].getBinPtrs<CorSingleBin>();
0545 tmp[i]->addContent(pBin.numEntries(), pBin.sumW(), pBin.sumW2(),
0546 pBin.sumWY());
0547 }
0548
0549 const YODA::Dbn2D& uBin = pPtr->bin(0);
0550 refs[i]->addContent(uBin.numEntries(), uBin.sumW(), uBin.sumW2(),
0551 uBin.sumWY());
0552 return true;
0553 }
0554 }
0555 return false;
0556 }
0557
0558 private:
0559
0560
0561 int getBinIndex(const double& obs) const {
0562
0563
0564 if (obs >= binX.back()) return -1;
0565
0566 if (obs < binX[0]) return -1;
0567 int index = 0;
0568 for (int i = 0, N = binX.size() - 1; i < N; ++i, ++index)
0569 if (obs >= binX[i] && obs < binX[i + 1]) break;
0570 return index;
0571 }
0572
0573
0574 vector<int> h1;
0575 vector<int> h2;
0576
0577
0578 vector<double> binX;
0579 vector<CorBin> binContent;
0580
0581 CorBin reference;
0582 public:
0583
0584 vector <string> profs;
0585
0586 };
0587
0588
0589
0590 const pair<int, int> getMaxValues() const {
0591 vector< vector<int>> harmVecs;
0592 for ( auto eItr = eCorrPtrs.begin(); eItr != eCorrPtrs.end(); ++eItr) {
0593 const vector<int>& h1 = (*eItr)->getH1();
0594 const vector<int>& h2 = (*eItr)->getH2();
0595 if (h1.size() > 0) harmVecs.push_back(h1);
0596 if (h2.size() > 0) harmVecs.push_back(h2);
0597 }
0598 if (harmVecs.size() == 0) {
0599 cout << "Warning: You tried to extract max values from harmonic "
0600 "vectors, but have not booked any." << endl;
0601 return pair<int,int>();
0602 }
0603 return Correlators::getMaxValues(harmVecs);
0604 }
0605
0606
0607 typedef shared_ptr<ECorrelator> ECorrPtr;
0608
0609
0610
0611 ECorrPtr bookECorrelator(const string name, const vector<int>& h, const YODA::Estimate1D& hIn) {
0612 vector<double> binIn;
0613 const YODA::Scatter2D s = hIn.mkScatter();
0614 for (const auto& p : s.points()) binIn.push_back(p.xMin());
0615 binIn.push_back(s.points().back().xMax());
0616 return bookECorrelator(name, h, binIn);
0617 }
0618
0619
0620
0621 ECorrPtr bookECorrelator(const string name, const vector<int>& h, const vector<double>& binIn) {
0622 ECorrPtr ecPtr = ECorrPtr(new ECorrelator(h, binIn));
0623 vector<string> eCorrProfs;
0624 for (int i = 0; i < BOOT_BINS; ++i) {
0625 Profile1DPtr tmp;
0626 book(tmp,"TMP/"+name+"-"+to_string(i),binIn);
0627 eCorrProfs.push_back(name+"-"+to_string(i));
0628 }
0629 ecPtr->setProfs(eCorrProfs);
0630 eCorrPtrs.push_back(ecPtr);
0631 return ecPtr;
0632 }
0633
0634
0635
0636 ECorrPtr bookECorrelator(const string name, const vector<int>& h1,
0637 const vector<int>& h2, const vector<double>& binIn) {
0638 ECorrPtr ecPtr = ECorrPtr(new ECorrelator(h1, h2, binIn));
0639 vector<string> eCorrProfs;
0640 Profile1DPtr tmp;
0641 for (int i = 0; i < BOOT_BINS; ++i) {
0642 book(tmp, "TMP/"+name+"-"+to_string(i), binIn);
0643 eCorrProfs.push_back(name+"-"+to_string(i));
0644 }
0645 ecPtr->setProfs(eCorrProfs);
0646 eCorrPtrs.push_back(ecPtr);
0647 return ecPtr;
0648 }
0649
0650
0651
0652 ECorrPtr bookECorrelator(const string& name, const vector<int>& h1,
0653 const vector<int>& h2, const YODA::Estimate1D& hIn) {
0654 vector<double> binIn;
0655 const YODA::Scatter2D s = hIn.mkScatter();
0656 for (const auto& p : s.points()) binIn.push_back(p.xMin());
0657 binIn.push_back(s.points().back().xMax());
0658 return bookECorrelator(name, h1, h2, binIn);
0659 }
0660
0661
0662
0663
0664
0665 ECorrPtr bookECorrelatorGap(const string& name, const vector<int>& h,
0666 const YODA::Estimate1D& hIn) {
0667 const vector<int> h1(h.begin(), h.begin() + h.size() / 2);
0668 const vector<int> h2(h.begin() + h.size() / 2, h.end());
0669 return bookECorrelator(name, h1, h2, hIn);
0670 }
0671
0672
0673
0674
0675
0676 template<unsigned int N, unsigned int M>
0677 ECorrPtr bookECorrelator(const string& name, const vector<double>& binIn) {
0678 return bookECorrelator(name, Correlators::hVec(N, M), binIn);
0679 }
0680
0681
0682
0683
0684
0685 template<unsigned int N, unsigned int M>
0686 ECorrPtr bookECorrelator(const string& name, const YODA::Estimate1D& hIn) {
0687 return bookECorrelator(name, Correlators::hVec(N, M), hIn);
0688 }
0689
0690
0691
0692
0693
0694 template<unsigned int N, unsigned int M>
0695 ECorrPtr bookECorrelatorGap(const string& name, const YODA::Estimate1D& hIn) {
0696 const vector<int> h = Correlators::hVec(N,M);
0697 const vector<int> h1(h.begin(), h.begin() + h.size() / 2);
0698 const vector<int> h2(h.begin() + h.size() / 2, h.end());
0699 return bookECorrelator(name, h1, h2, hIn);
0700
0701 }
0702
0703 protected:
0704
0705
0706 list<ECorrPtr> eCorrPtrs;
0707
0708
0709 public:
0710
0711
0712
0713
0714
0715 CumulantAnalysis(const string& n)
0716 : Analysis(n), errorMethod(VARIANCE)
0717 { }
0718
0719
0720
0721
0722
0723
0724
0725
0726 template<typename T>
0727 static void fillScatter(Scatter2DPtr h, const vector<double>& binx, const T& func) {
0728 vector<YODA::Point2D> points;
0729
0730 bool hasBins = (h->points().size() > 0);
0731 for (int i = 0, N = binx.size() - 1; i < N; ++i) {
0732 double xMid = (binx[i] + binx[i + 1]) / 2.0;
0733 double xeMin = fabs(xMid - binx[i]);
0734 double xeMax = fabs(xMid - binx[i + 1]);
0735 if (hasBins) {
0736 xMid = h->points()[i].x();
0737 xeMin = h->points()[i].xErrMinus();
0738 xeMax = h->points()[i].xErrPlus();
0739 }
0740 double yVal = func(i);
0741 if (std::isnan(yVal)) yVal = 0.;
0742 double yErr = 0;
0743 points.push_back(YODA::Point2D(xMid, yVal, xeMin, xeMax, yErr, yErr));
0744 }
0745 h->reset();
0746 h->points().clear();
0747 for (int i = 0, N = points.size(); i < N; ++i) h->addPoint(points[i]);
0748 }
0749
0750
0751
0752
0753
0754
0755
0756
0757 template<typename F>
0758 void fillScatter(Scatter2DPtr h, const vector<double>& binx, const F func,
0759 vector<pair<double, double> >& yErr) const {
0760 vector<YODA::Point2D> points;
0761
0762 const bool hasBins = (h->points().size() > 0);
0763 for (int i = 0, N = binx.size() - 1; i < N; ++i) {
0764 double xMid = (binx[i] + binx[i + 1]) / 2.0;
0765 double xeMin = fabs(xMid - binx[i]);
0766 double xeMax = fabs(xMid - binx[i + 1]);
0767 if (hasBins) {
0768 xMid = h->points()[i].x();
0769 xeMin = h->points()[i].xErrMinus();
0770 xeMax = h->points()[i].xErrPlus();
0771 }
0772 const double yVal = func(i);
0773 if (std::isnan(yVal))
0774 points.push_back(YODA::Point2D(xMid, 0., xeMin, xeMax,0., 0.));
0775 else
0776 points.push_back(YODA::Point2D(xMid, yVal, xeMin, xeMax,
0777 yErr[i].first, yErr[i].second));
0778 }
0779 h->reset();
0780
0781 for (int i = 0, N = points.size(); i < N; ++i) {
0782 h->addPoint(points[i]);
0783 }
0784 }
0785
0786
0787
0788
0789
0790 static void nthPow(Scatter2DPtr hOut, const Scatter2DPtr hIn, const double& n, const double& k = 1.0) {
0791 if (n == 0 || n == 1) {
0792 cout << "Error: Do not take the 0th or 1st power of a Scatter2D,"
0793 " use scale instead." << endl;
0794 return;
0795 }
0796 if (hIn->points().size() != hOut->points().size()) {
0797 cout << "nthRoot: Scatterplots: " << hIn->name() << " and " <<
0798 hOut->name() << " not initialized with same length." << endl;
0799 return;
0800 }
0801 vector<YODA::Point2D> points;
0802
0803 double eFac = pow(k,1./n)/n;
0804 for (auto b : hIn->points()) {
0805 double yVal = pow(k * b.y(),n);
0806 if (std::isnan(yVal))
0807 points.push_back(YODA::Point2D(b.x(), 0., b.xErrMinus(),
0808 b.xErrPlus(), 0, 0 ));
0809 else {
0810 double yemin = abs(eFac * pow(yVal,1./(n - 1.))) * b.yErrMinus();
0811 if (std::isnan(yemin)) yemin = b.yErrMinus();
0812 double yemax = abs(eFac * pow(yVal,1./(n - 1.))) * b.yErrPlus();
0813 if (std::isnan(yemax)) yemax = b.yErrPlus();
0814 points.push_back(YODA::Point2D(b.x(), yVal, b.xErrMinus(),
0815 b.xErrPlus(), yemin, yemax ));
0816 }
0817 }
0818 hOut->reset();
0819 for (int i = 0, N = points.size(); i < N; ++i)
0820 hOut->addPoint(points[i]);
0821 }
0822
0823
0824
0825
0826
0827 static void nthPow(Scatter2DPtr h, const double n, const double k = 1.0) {
0828 if (n == 0 || n == 1) {
0829 cout << "Error: Do not take the 0th or 1st power of a Scatter2D,"
0830 " use scale instead." << endl;
0831 return;
0832 }
0833 vector<YODA::Point2D> points;
0834 vector<YODA::Point2D> pIn = h->points();
0835
0836 double eFac = pow(k,1./n)/n;
0837 for (const auto& b : pIn) {
0838 const double yVal = pow(k * b.y(), n);
0839 if (std::isnan(yVal)) {
0840 points.push_back(YODA::Point2D(b.x(), 0., b.xErrMinus(),
0841 b.xErrPlus(), 0, 0 ));
0842 }
0843 else {
0844 double yemin = abs(eFac * pow(yVal,1./(n - 1.))) * b.yErrMinus();
0845 if (std::isnan(yemin)) yemin = b.yErrMinus();
0846 double yemax = abs(eFac * pow(yVal,1./(n - 1.))) * b.yErrPlus();
0847 if (std::isnan(yemax)) yemax = b.yErrPlus();
0848 points.push_back(YODA::Point2D(b.x(), yVal, b.xErrMinus(),
0849 b.xErrPlus(), yemin, yemax ));
0850 }
0851 }
0852 h->reset();
0853 for (int i = 0, N = points.size(); i < N; ++i) h->addPoint(points[i]);
0854 }
0855
0856
0857
0858
0859
0860
0861 template<typename T>
0862 static pair<double, double> sampleVariance(T func) {
0863
0864 double avg = 0.;
0865 for (int i = 0; i < BOOT_BINS; ++i) avg += func(i);
0866 avg /= double(BOOT_BINS);
0867
0868 double var = 0.;
0869 for (int i = 0; i < BOOT_BINS; ++i) var += pow(func(i) - avg, 2.);
0870 var /= (double(BOOT_BINS) - 1);
0871 return pair<double, double>(var, var);
0872 }
0873
0874
0875
0876
0877
0878
0879 template<typename T>
0880 static pair<double, double> sampleEnvelope(T func) {
0881
0882 double avg = 0.;
0883 for (int i = 0; i < BOOT_BINS; ++i) avg += func(i);
0884 avg /= double(BOOT_BINS);
0885 double yMax = avg;
0886 double yMin = avg;
0887
0888 for (int i = 0; i < BOOT_BINS; ++i) {
0889 double yVal = func(i);
0890 if (yMin > yVal) yMin = yVal;
0891 else if (yMax < yVal) yMax = yVal;
0892 }
0893 return pair<double, double>(fabs(avg - yMin), fabs(yMax - avg));
0894 }
0895
0896
0897
0898 template<typename T>
0899 const pair<double, double> sampleError(T func) const {
0900 if (errorMethod == VARIANCE) return sampleVariance(func);
0901 else if (errorMethod == ENVELOPE) return sampleEnvelope(func);
0902 else
0903 cout << "Error: Error method not found!" << endl;
0904 return pair<double, double>(0.,0.);
0905 }
0906
0907
0908
0909 void cnTwoInt(Scatter2DPtr h, ECorrPtr e2) const {
0910 const vector<CorBin>& bins = e2->getBins();
0911 const vector<double>& binx = e2->getBinX();
0912
0913 if (binx.size() - 1 != bins.size()){
0914 cout << "cnTwoInt: Bin size (x,y) differs!" << endl;
0915 return;
0916 }
0917 vector<const CorBinBase*> binPtrs;
0918
0919 auto cn = [&](const int i) { return binPtrs[i]->mean(); };
0920
0921 vector<pair<double,double>> yErr;
0922 for (int j = 0, N = bins.size(); j < N; ++j) {
0923 binPtrs = bins[j].getBinPtrs();
0924 yErr.push_back(sampleError(cn));
0925 }
0926 binPtrs = e2->getBinPtrs();
0927 fillScatter(h, binx, cn, yErr);
0928 }
0929
0930
0931
0932 void vnTwoInt(Scatter2DPtr h, ECorrPtr e2) const {
0933 cnTwoInt(h, e2);
0934 nthPow(h, 0.5);
0935 }
0936
0937
0938
0939
0940
0941 void corrPlot(Scatter2DPtr h, ECorrPtr e) const {
0942 cnTwoInt(h, e);
0943 }
0944
0945
0946
0947
0948
0949 void rawHookIn(YODA::AnalysisObjectPtr yao) final {
0950
0951 for (auto ec : eCorrPtrs) if(ec->fillFromProfile(yao, name())) break;;
0952 }
0953
0954
0955
0956
0957
0958 void rawHookOut(const vector<MultiplexAOPtr>& raos, size_t iW) final {
0959
0960 for (auto ec : eCorrPtrs) {
0961 const vector<CorBin>& corBins = ec->getBins();
0962 const vector<double>& binx = ec->getBinX();
0963 auto ref = ec->getReference();
0964 auto refBins = ref.getBinPtrs<CorSingleBin>();
0965
0966 if (binx.size() - 1 != corBins.size()){
0967 cout << "corrPlot: Bin size (x,y) differs!" << endl;
0968 return;
0969 }
0970
0971 for (int i = 0, N = ec->profs.size(); i < N; ++i) {
0972 for (auto rao : raos) {
0973 if (rao->path() != "/"+name()+"/TMP/"+ec->profs[i]) continue;
0974
0975 rao.get()->setActiveWeightIdx(iW);
0976 YODA::Profile1DPtr pPtr = dynamic_pointer_cast<YODA::Profile1D>(rao.get()->activeAO());
0977
0978 vector<YODA::Dbn2D> profBins;
0979
0980 pPtr->bin(0).set( YODA::Dbn2D(refBins[i]->numEntries(), refBins[i]->sumW(),
0981 refBins[i]->sumW2(), 0., 0., refBins[i]->sumWX(), 0., 0.) );
0982 for (size_t j = 0, N = binx.size() - 1; j < N; ++j) {
0983 vector<const CorSingleBin*> binPtrs = corBins[j].getBinPtrs<CorSingleBin>();
0984
0985
0986
0987
0988 pPtr->bin(j).set( YODA::Dbn2D(binPtrs[i]->numEntries(), binPtrs[i]->sumW(),
0989 binPtrs[i]->sumW2(), 0., 0., binPtrs[i]->sumWX(), 0, 0) );
0990 }
0991 }
0992 }
0993 }
0994 }
0995
0996
0997 void cnFourInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4) const {
0998 const auto& e2bins = e2->getBins();
0999 const auto& e4bins = e4->getBins();
1000 const vector<double>& binx = e2->getBinX();
1001 if (binx.size() - 1 != e2bins.size()){
1002 cout << "cnFourInt: Bin size (x,y) differs!" << endl;
1003 return;
1004 }
1005 if (binx != e4->getBinX()) {
1006 cout << "Error in cnFourInt: Correlator x-binning differs!" << endl;
1007 return;
1008 }
1009 vector<const CorBinBase*> e2binPtrs;
1010 vector<const CorBinBase*> e4binPtrs;
1011 auto cn = [&] (const int i) {
1012 double e22 = e2binPtrs[i]->mean() * e2binPtrs[i]->mean();
1013 return e4binPtrs[i]->mean() - 2. * e22;
1014 };
1015
1016 vector<pair<double, double> > yErr;
1017 for (int j = 0, N = e2bins.size(); j < N; ++j) {
1018 e2binPtrs = e2bins[j].getBinPtrs();
1019 e4binPtrs = e4bins[j].getBinPtrs();
1020 yErr.push_back(sampleError(cn));
1021 }
1022
1023 e2binPtrs = e2->getBinPtrs();
1024 e4binPtrs = e4->getBinPtrs();
1025 fillScatter(h, binx, cn, yErr);
1026 }
1027
1028
1029
1030 void vnFourInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4) const {
1031 cnFourInt(h, e2, e4);
1032 nthPow(h, 0.25, -1.0);
1033 }
1034
1035
1036
1037 void cnSixInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4,
1038 ECorrPtr e6) const {
1039 const auto& e2bins = e2->getBins();
1040 const auto& e4bins = e4->getBins();
1041 const auto& e6bins = e6->getBins();
1042 const auto& binx = e2->getBinX();
1043 if (binx.size() - 1 != e2bins.size()){
1044 cout << "cnSixInt: Bin size (x,y) differs!" << endl;
1045 return;
1046 }
1047 if (binx != e4->getBinX() || binx != e6->getBinX()) {
1048 cout << "Error in cnSixInt: Correlator x-binning differs!" << endl;
1049 return;
1050 }
1051 vector<const CorBinBase*> e2binPtrs;
1052 vector<const CorBinBase*> e4binPtrs;
1053 vector<const CorBinBase*> e6binPtrs;
1054 auto cn = [&] (const int i) {
1055 const double e2mean = e2binPtrs[i]->mean();
1056 const double e4mean = e4binPtrs[i]->mean();
1057 const double e6mean = e6binPtrs[i]->mean();
1058 const double e23 = pow(e2mean, 3.0);
1059 return e6mean - 9.*e2mean*e4mean + 12.*e23;
1060 };
1061
1062 vector<pair<double, double> > yErr;
1063 for (int j = 0, N = e2bins.size(); j < N; ++j) {
1064 e2binPtrs = e2bins[j].getBinPtrs();
1065 e4binPtrs = e4bins[j].getBinPtrs();
1066 e6binPtrs = e6bins[j].getBinPtrs();
1067 yErr.push_back(sampleError(cn));
1068 }
1069
1070 e2binPtrs = e2->getBinPtrs();
1071 e4binPtrs = e4->getBinPtrs();
1072 e6binPtrs = e6->getBinPtrs();
1073 fillScatter(h, binx, cn, yErr);
1074 }
1075
1076
1077
1078 void vnSixInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4,
1079 ECorrPtr e6) const {
1080 cnSixInt(h, e2, e4, e6);
1081 nthPow(h, 1./6., 0.25);
1082 }
1083
1084
1085
1086 void cnEightInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4,
1087 ECorrPtr e6, ECorrPtr e8) const {
1088 const auto& e2bins = e2->getBins();
1089 const auto& e4bins = e4->getBins();
1090 const auto& e6bins = e6->getBins();
1091 const auto& e8bins = e8->getBins();
1092 const vector<double>& binx = e2->getBinX();
1093 if (binx.size() - 1 != e2bins.size()){
1094 cout << "cnEightInt: Bin size (x,y) differs!" << endl;
1095 return;
1096 }
1097 if (binx != e4->getBinX() || binx != e6->getBinX() || binx != e8->getBinX()) {
1098 cout << "Error in cnEightInt: Correlator x-binning differs!" << endl;
1099 return;
1100 }
1101 vector<const CorBinBase*> e2binPtrs;
1102 vector<const CorBinBase*> e4binPtrs;
1103 vector<const CorBinBase*> e6binPtrs;
1104 vector<const CorBinBase*> e8binPtrs;
1105 auto cn = [&] (const int i) {
1106 const double e2mean = e2binPtrs[i]->mean();
1107 const double e4mean = e4binPtrs[i]->mean();
1108 const double e6mean = e6binPtrs[i]->mean();
1109 const double e8mean = e8binPtrs[i]->mean();
1110 const double e22 = sqr(e2mean);
1111 const double e24 = sqr(e22);
1112 const double e42 = sqr(e4mean);
1113 return e8mean - 16. * e6mean * e2mean - 18. * e42 + 144. * e4mean*e22 - 144. * e24;
1114 };
1115
1116 vector<pair<double, double> > yErr;
1117 for (int j = 0, N = e2bins.size(); j < N; ++j) {
1118 e2binPtrs = e2bins[j].getBinPtrs();
1119 e4binPtrs = e4bins[j].getBinPtrs();
1120 e6binPtrs = e6bins[j].getBinPtrs();
1121 e8binPtrs = e8bins[j].getBinPtrs();
1122 yErr.push_back(sampleError(cn));
1123 }
1124
1125 e2binPtrs = e2->getBinPtrs();
1126 e4binPtrs = e4->getBinPtrs();
1127 e6binPtrs = e6->getBinPtrs();
1128 e8binPtrs = e8->getBinPtrs();
1129 fillScatter(h, binx, cn, yErr);
1130 }
1131
1132
1133
1134 void vnEightInt(Scatter2DPtr h, ECorrPtr e2, ECorrPtr e4, ECorrPtr e6, ECorrPtr e8) const {
1135 cnEightInt(h, e2, e4, e6, e8);
1136 nthPow(h, 1./8., -1./33.);
1137 }
1138
1139
1140
1141 void vnTwoDiff(Scatter2DPtr h, ECorrPtr e2Dif) const {
1142 const auto& e2bins = e2Dif->getBins();
1143 const auto& ref = e2Dif->getReference();
1144 const auto& binx = e2Dif->getBinX();
1145 if (binx.size() -1 != e2bins.size()) {
1146 cout << "vnTwoDif: Bin size (x,y) differs!" << endl;
1147 return;
1148 }
1149 vector<const CorBinBase*> e2binPtrs;
1150 vector<const CorBinBase*> refPtrs;
1151 auto vn = [&] (const int i) {
1152
1153 if (ref.mean() <= 0) return 0.;
1154 return e2binPtrs[i]->mean() / sqrt(ref.mean());
1155 };
1156
1157 auto vnerr = [&] (const int i) {
1158
1159 if (refPtrs[i]->mean() <=0) return 0.;
1160 return e2binPtrs[i]->mean() / sqrt(refPtrs[i]->mean());
1161 };
1162
1163 vector<pair<double,double>> yErr;
1164 refPtrs = ref.getBinPtrs();
1165 for (int j = 0, N = e2bins.size(); j < N; ++j) {
1166 e2binPtrs = e2bins[j].getBinPtrs();
1167 yErr.push_back(sampleError(vnerr));
1168 }
1169
1170 e2binPtrs = e2Dif->getBinPtrs();
1171 fillScatter(h, binx, vn);
1172 }
1173
1174
1175
1176 void vnFourDiff(Scatter2DPtr h, ECorrPtr e2Dif, ECorrPtr e4Dif) const {
1177 const auto& e2bins = e2Dif->getBins();
1178 const auto& e4bins = e4Dif->getBins();
1179 const auto& ref2 = e2Dif->getReference();
1180 const auto& ref4 = e4Dif->getReference();
1181 const auto& binx = e2Dif->getBinX();
1182 if (binx.size() - 1 != e2bins.size()){
1183 cout << "vnFourDif: Bin size (x,y) differs!" << endl;
1184 return;
1185 }
1186 if (binx != e4Dif->getBinX()) {
1187 cout << "Error in vnFourDif: Correlator x-binning differs!" << endl;
1188 return;
1189 }
1190 vector<const CorBinBase*> e2binPtrs;
1191 vector<const CorBinBase*> e4binPtrs;
1192 vector<const CorBinBase*> ref2Ptrs;
1193 vector<const CorBinBase*> ref4Ptrs;
1194 double denom = 2 * ref2.mean() * ref2.mean() - ref4.mean();
1195 auto vn = [&] (const int i) {
1196
1197 if (denom <= 0 ) return 0.;
1198 return ((2 * ref2.mean() * e2bins[i].mean() - e4bins[i].mean()) / pow(denom, 0.75));
1199 };
1200
1201 auto vnerr = [&] (const int i) {
1202 double denom2 = 2 * ref2Ptrs[i]->mean() * ref2Ptrs[i]->mean() -
1203 ref4Ptrs[i]->mean();
1204
1205 if (denom2 <= 0) return 0.;
1206 return ((2 * ref2Ptrs[i]->mean() * e2binPtrs[i]->mean() - e4binPtrs[i]->mean()) / pow(denom2, 0.75));
1207 };
1208
1209 vector<pair<double,double> > yErr;
1210 ref2Ptrs = ref2.getBinPtrs();
1211 ref4Ptrs = ref4.getBinPtrs();
1212 for (int j = 0, N = e2bins.size(); j < N; ++j) {
1213 e2binPtrs = e2bins[j].getBinPtrs();
1214 e4binPtrs = e4bins[j].getBinPtrs();
1215 yErr.push_back(sampleError(vnerr));
1216 }
1217
1218 e2binPtrs = e2Dif->getBinPtrs();
1219 e4binPtrs = e4Dif->getBinPtrs();
1220 fillScatter(h, binx, vn, yErr);
1221 }
1222
1223 };
1224
1225
1226 }
1227
1228 #endif