15#ifndef ALICEO2_UTILS_BOOSTHISTOGRAMUTILS
16#define ALICEO2_UTILS_BOOSTHISTOGRAMUTILS
29#include "TLinearFitter.h"
33#include "HFitInterface.h"
34#include "TFitResultPtr.h"
35#include "TFitResult.h"
36#include "Fit/Fitter.h"
37#include "Fit/BinData.h"
38#include "Math/WrappedMultiTF1.h"
40#include <boost/histogram.hpp>
41#include <boost/histogram/histogram.hpp>
42#include <boost/format.hpp>
43#include <boost/histogram/axis.hpp>
44#include <boost/histogram/make_histogram.hpp>
45#include <boost/histogram/accumulators/mean.hpp>
47using boostHisto2d = boost::histogram::histogram<std::tuple<boost::histogram::axis::regular<double, boost::use_default, boost::use_default, boost::use_default>, boost::histogram::axis::regular<double, boost::use_default, boost::use_default, boost::use_default>>, boost::histogram::unlimited_storage<std::allocator<char>>>;
48using boostHisto1d = boost::histogram::histogram<std::tuple<boost::histogram::axis::regular<double, boost::use_default, boost::use_default, boost::use_default>>>;
50using boostHisto2d_VarAxis = boost::histogram::histogram<std::tuple<boost::histogram::axis::variable<double, boost::use_default, boost::use_default, std::allocator<double>>, boost::histogram::axis::variable<double, boost::use_default, boost::use_default, std::allocator<double>>>>;
51using boostHisto1d_VarAxis = boost::histogram::histogram<std::tuple<boost::histogram::axis::variable<double, boost::use_default, boost::use_default, boost::use_default>>>;
60template <
typename AxisIterator>
73 AxisIterator
result(mBaseIterator);
79 return mBaseIterator != rhs.mBaseIterator;
82 decltype(
auto)
operator*() {
return mBaseIterator->center(); }
85 AxisIterator mBaseIterator;
90template <
typename AxisIterator>
100 return mBaseIterator;
104 AxisIterator
result(mBaseIterator);
111 return mBaseIterator != rhs.mBaseIterator;
114 decltype(
auto)
operator*() {
return mBaseIterator->upper(); }
117 AxisIterator mBaseIterator;
122template <
typename AxisIterator>
132 return mBaseIterator;
136 AxisIterator
result(mBaseIterator);
142 return mBaseIterator != rhs.mBaseIterator;
145 decltype(
auto)
operator*() {
return mBaseIterator->lower(); }
148 AxisIterator mBaseIterator;
151template <
typename AxisIterator>
155 for (
int i = 0;
i <
n;
i++) {
161template <
typename AxisIterator>
165 for (
int i = 0;
i <
n;
i++) {
171template <
typename AxisIterator>
175 for (
int i = 0;
i <
n;
i++) {
181template <
typename T,
int nparams>
190 memcpy(mFitParameters.data(),
list,
sizeof(T) * nparams);
197 static_assert(
index <= nparams,
"Acessing invalid parameter");
198 return mFitParameters[
index];
205 static_assert(
index <= nparams,
"Attempting to set invalid parameter");
206 mFitParameters[
index] = parameter;
218 std::array<T, nparams> mFitParameters;
249template <
typename T,
typename Iterator,
typename BinCenterView>
250std::vector<double> fitGaus(Iterator
first, Iterator last,
BinCenterView axisfirst,
const bool ignoreUnderOverflowBin =
true)
253 if (ignoreUnderOverflowBin) {
259 TLinearFitter fitter(3,
"pol2");
261 double kTol = mat.GetTol();
262 fitter.StoreData(kFALSE);
263 fitter.ClearPoints();
270 auto yMax = std::max_element(
first, last);
271 auto nbins = std::distance(
first, last);
273 double binCenter1 = *axisiter;
275 double binCenter2 = *axisiter;
276 return std::abs(binCenter1 - binCenter2);
278 double binWidth = getBinWidth(axisfirst);
287 for (
auto iter =
first; iter != last; iter++) {
302 std::vector<double>
result;
303 for (
int r = 0;
r < 5;
r++) {
311 auto axisiter = axisfirst;
312 for (
auto iter =
first; iter != last; iter++, axisiter++) {
316 if (std::isnan(*axisiter) || std::isinf(*axisiter) || *iter <= 0 || *iter == 1) {
319 double x = *axisiter;
321 double y = std::log(*iter);
323 double ey = std::sqrt(fabs(*iter)) / fabs(*iter);
325 fitter.AddPoint(&
x,
y, ey);
329 A(npoints, 2) =
x *
x;
331 meanCOG +=
x * nbins;
332 rms2COG +=
x *
x * nbins;
352 fitter.GetParameters(par);
353 fitter.GetCovarianceMatrix(mat);
354 result.at(4) = (fitter.GetChisquare() / double(npoints));
357 if (std::abs(par[1]) < kTol) {
360 if (std::abs(par[2]) < kTol) {
365 T param1 = T(par[1] / (-2. * par[2]));
367 result.at(2) = T(1. / std::sqrt(std::abs(-2. * par[2])));
368 auto lnparam0 = par[0] - par[1] * par[1] / (4 * par[2]);
369 if (lnparam0 > 307) {
373 result.at(0) = T(std::exp(lnparam0));
376 }
else if (npoints == 2) {
383 result.at(2) = std::sqrt(std::abs(meanCOG * meanCOG - rms2COG));
385 }
else if (npoints == 1) {
390 result.at(2) = binWidth / std::sqrt(12);
397template <
typename valuetype,
typename... axes>
400 return fitGaus<valuetype>(hist.begin(), hist.end(),
BinCenterView(hist.axis(0).begin()));
404template <
typename Hist>
408 int nBins = inHist1D->GetNbinsX();
409 std::vector<double> binEdges;
410 for (
int i = 0;
i < nBins + 1;
i++) {
411 binEdges.push_back(inHist1D->GetBinLowEdge(
i + 1));
415 if constexpr (std::is_same<Hist, boostHisto1d_VarAxis>::value) {
416 mHisto = boost::histogram::make_histogram(boost::histogram::axis::variable<>(binEdges));
418 mHisto = boost::histogram::make_histogram(boost::histogram::axis::regular<>(nBins, binEdges[0], binEdges.back()));
422 for (Int_t
x = 1;
x < nBins + 1;
x++) {
423 mHisto.at(
x - 1) = inHist1D->GetBinContent(
x);
429template <
typename Hist>
433 const int nBinsX = inHist2D->GetNbinsX();
434 std::vector<double> binEdgesX;
435 for (
int i = 0;
i < nBinsX + 1;
i++) {
436 binEdgesX.push_back(inHist2D->GetXaxis()->GetBinLowEdge(
i + 1));
439 const int nBinsY = inHist2D->GetNbinsY();
440 std::vector<double> binEdgesY;
441 for (
int i = 0;
i < nBinsY + 1;
i++) {
442 binEdgesY.push_back(inHist2D->GetYaxis()->GetBinLowEdge(
i + 1));
447 if constexpr (std::is_same<Hist, boostHisto2d_VarAxis>::value) {
448 mHisto = boost::histogram::make_histogram(boost::histogram::axis::variable<>(binEdgesX), boost::histogram::axis::variable<>(binEdgesY));
450 mHisto = boost::histogram::make_histogram(boost::histogram::axis::regular<>(nBinsX, binEdgesX[0], binEdgesX.back()), boost::histogram::axis::regular<>(nBinsY, binEdgesY[0], binEdgesY.back()));
454 for (Int_t
x = 1;
x < nBinsX + 1;
x++) {
455 for (Int_t
y = 1;
y < nBinsY + 1;
y++) {
456 mHisto.at(
x - 1,
y - 1) = inHist2D->GetBinContent(
x,
y);
467template <
typename... axes>
468double getMeanBoost1D(boost::histogram::histogram<axes...>& inHist1D,
const double rangeLow = 0,
const double rangeHigh = 0)
472 bool restrictRange = rangeLow < rangeHigh ? true :
false;
473 auto histiter = inHist1D.begin() + 1;
474 const auto& axis = inHist1D.axis(0);
478 if (*bincenter < rangeLow || *bincenter > rangeHigh) {
482 stats.add(*bincenter, *histiter);
484 return stats.getMean();
494template <
typename... axes>
495double getVarianceBoost1D(boost::histogram::histogram<axes...>& inHist1D,
double mean = -999999,
const double rangeLow = 0,
const double rangeHigh = 0,
const double weight = 1)
497 if (std::abs(mean + 999999) < 0.00001) {
500 bool restrictRange = rangeLow < rangeHigh ? true :
false;
501 unsigned int nMeas = 0;
502 auto histiter = inHist1D.begin() + 1;
503 const auto& axis = inHist1D.axis(0);
507 LOG(
debug) <<
" *bincenter " << *bincenter <<
" rangeLow " << rangeLow <<
" rangeHigh " << rangeHigh;
508 if (*bincenter < rangeLow || *bincenter > rangeHigh) {
512 nMeas += *histiter /
weight;
513 variance += *histiter * (*bincenter - mean) * (*bincenter - mean);
518 variance /= (nMeas - 1);
523template <
class BoostHist>
526 const int nbinsx = hist.axis(0).size();
527 const double binxlow = hist.axis(0).bin(0).lower();
528 const double binxhigh = hist.axis(0).bin(nbinsx - 1).upper();
530 TH1F hRoot(
name,
name, nbinsx, binxlow, binxhigh);
532 for (
int x = 0;
x < nbinsx;
x++) {
533 hRoot.SetBinContent(
x + 1, hist.at(
x));
540template <
class BoostHist>
543 const int nbinsx = hist.axis(0).size();
544 const int nbinsy = hist.axis(1).size();
545 const double binxlow = hist.axis(0).bin(0).lower();
546 const double binxhigh = hist.axis(0).bin(nbinsx - 1).upper();
547 const double binylow = hist.axis(1).bin(0).lower();
548 const double binyhigh = hist.axis(1).bin(nbinsy - 1).upper();
550 TH2F hRoot(
name,
name, nbinsx, binxlow, binxhigh, nbinsy, binylow, binyhigh);
552 for (
int x = 0;
x < nbinsx;
x++) {
553 for (
int y = 0;
y < nbinsy;
y++) {
554 hRoot.SetBinContent(
x + 1,
y + 1, hist.at(
x,
y));
566template <
typename... axes>
567auto ProjectBoostHistoX(
const boost::histogram::histogram<axes...>& hist2d,
const int binLow,
const int binHigh)
569 using namespace boost::histogram::literals;
571 unsigned int nbins = hist2d.axis(0).size();
573 auto reducedHisto2d = boost::histogram::algorithm::reduce(hist2d, boost::histogram::algorithm::shrink(hist2d.axis(0).bin(0).lower(), hist2d.axis(0).bin(nbins - 1).upper()), boost::histogram::algorithm::shrink(binLow, binHigh));
576 for (
int i = 0;
i < reducedHisto2d.axis(0).
size(); ++
i) {
577 reducedHisto2d.at(
i, -1) = 0;
578 reducedHisto2d.at(
i, reducedHisto2d.axis(1).size()) = 0;
581 auto histoProj = boost::histogram::algorithm::project(reducedHisto2d, 0_c);
592template <
typename... axes>
595 unsigned int nbins = hist2d.axis(0).size();
596 double binStartX = hist2d.axis(0).bin(0).lower();
597 double binEndX = hist2d.axis(0).bin(nbins - 1).upper();
598 auto histoProj = boost::histogram::make_histogram(boost::histogram::axis::regular<>(nbins, binStartX, binEndX));
601 for (
int x = 0;
x < nbins; ++
x) {
603 for (
int y = binLow;
y < binHigh; ++
y) {
604 histoProj.at(
x) = histoProj.at(
x) + hist2d.at(
x,
y);
620template <
typename... axes>
621auto ReduceBoostHistoFastSlice(
const boost::histogram::histogram<axes...>& hist2d,
int binXLow,
int binXHigh,
int binYLow,
int binYHigh,
bool includeOverflowUnderflow)
623 int nXbins = binXHigh - binXLow + 1;
624 int nYbins = binYHigh - binYLow + 1;
625 double valueStartX = hist2d.axis(0).bin(binXLow).lower();
626 double valueEndX = hist2d.axis(0).bin(binXHigh).upper();
627 double valueStartY = hist2d.axis(1).bin(binYLow).lower();
628 double valueEndY = hist2d.axis(1).bin(binYHigh).upper();
630 auto histoReduced = boost::histogram::make_histogram(boost::histogram::axis::regular<>(nXbins, valueStartX, valueEndX), boost::histogram::axis::regular<>(nYbins, valueStartY, valueEndY));
632 int nbinsxOld = hist2d.axis(0).size();
633 int nbinsyOld = hist2d.axis(1).size();
635 for (
int x = -1;
x < nbinsxOld + 1; ++
x) {
636 for (
int y = -1;
y < nbinsyOld + 1; ++
y) {
637 int nXbinsNew =
x - binXLow;
638 int nYbinsNew =
y - binYLow;
639 if (nXbinsNew < 0 || nYbinsNew < 0 || nXbinsNew >= nXbins || nYbinsNew >= nYbins) {
640 if (!includeOverflowUnderflow) {
644 nXbinsNew =
int(std::min(
int(std::max(nXbinsNew, -1)), nXbins));
645 nYbinsNew =
int(std::min(
int(std::max(nYbinsNew, -1)), nYbins));
646 histoReduced.at(nXbinsNew, nYbinsNew) += hist2d.at(
x,
y);
649 histoReduced.at(nXbinsNew, nYbinsNew) = hist2d.at(
x,
y);
664template <
typename... axes>
668 int nXbins = binXHigh - binXLow + 1;
669 double valueStartX = hist1d.axis(0).bin(binXLow).lower();
670 double valueEndX = hist1d.axis(0).bin(binXHigh).upper();
673 auto histoReduced = boost::histogram::make_histogram(boost::histogram::axis::regular<>(nXbins, valueStartX, valueEndX));
676 int nbinsxOld = hist1d.axis(0).size();
678 for (
int x = -1;
x < nbinsxOld + 1; ++
x) {
679 int nXbinsNew =
x - binXLow;
680 if (nXbinsNew < 0 || nXbinsNew >= nXbins) {
681 if (!includeOverflowUnderflow) {
685 nXbinsNew =
int(std::min(
int(std::max(nXbinsNew, -1)), nXbins));
686 histoReduced.at(nXbinsNew) += hist1d.at(
x);
689 histoReduced.at(nXbinsNew) = hist1d.at(
x);
705template <
typename... axes>
709 int binXLow = hist2d.axis(0).index(xLow);
710 int binXHigh = hist2d.axis(0).index(xHigh);
711 int binYLow = hist2d.axis(1).index(yLow);
712 int binYHigh = hist2d.axis(1).index(yHigh);
722template <
typename... axes>
726 std::array<int, 2> axisLimitsIndex = {hist.axis(0).index(
min), hist.axis(0).index(
max)};
728 for (
auto& bin : axisLimitsIndex) {
731 }
else if (bin >= hist.axis(0).size()) {
732 bin = hist.axis(0).size() - 1;
737 return boost::histogram::algorithm::sum(slicedHist);
boost::histogram::histogram< std::tuple< boost::histogram::axis::variable< double, boost::use_default, boost::use_default, std::allocator< double > >, boost::histogram::axis::variable< double, boost::use_default, boost::use_default, std::allocator< double > > > > boostHisto2d_VarAxis
boost::histogram::histogram< std::tuple< boost::histogram::axis::regular< double, boost::use_default, boost::use_default, boost::use_default > > > boostHisto1d
boost::histogram::histogram< std::tuple< boost::histogram::axis::regular< double, boost::use_default, boost::use_default, boost::use_default >, boost::histogram::axis::regular< double, boost::use_default, boost::use_default, boost::use_default > >, boost::histogram::unlimited_storage< std::allocator< char > > > boostHisto2d
boost::histogram::histogram< std::tuple< boost::histogram::axis::variable< double, boost::use_default, boost::use_default, boost::use_default > > > boostHisto1d_VarAxis
Axis iterator over bin centers.
AxisIterator operator++(int)
bool operator!=(const BinCenterView &rhs) const
AxisIterator & operator++()
BinCenterView(AxisIterator iter)
Axis iterator over bin lower edges.
AxisIterator operator++(int)
AxisIterator & operator++()
bool operator!=(const BinLowerView &rhs) const
BinLowerView(AxisIterator iter)
Axis iterator over bin upper edges.
bool operator!=(const BinUpperView &rhs) const
AxisIterator & operator++()
AxisIterator operator++(int)
BinUpperView(AxisIterator iter)
void setParameter(T parameter)
Set the paratmeters of a fit result. Ex: result.setParameter<1>(T(value)));.
void setChi2(double chi2In)
Set the chi2 of the fit result.
T getParameter() const
Get the paratmeters of a fit result. Ex: result.getParameter<1>();.
fitResult(T chi2, const T(&list)[nparams])
GLuint const GLchar * name
GLuint GLuint GLfloat weight
GLboolean GLboolean GLboolean b
TH2F TH2FFromBoost(BoostHist hist, const char *name="hist")
Convert a 2D boost histogram to a root histogram.
auto ProjectBoostHistoXFast(const boost::histogram::histogram< axes... > &hist2d, const int binLow, const int binHigh)
Function to project 2d boost histogram onto x-axis.
Hist boosthistoFromRoot_1D(TH1D *inHist1D)
Convert a 1D root histogram to a Boost histogram.
FitGausError_t
Error code for invalid result in the fitGaus process.
@ FIT_ERROR_KTOL_MEAN
Gaus fit failed! std::abs(par[1]) < kTol.
@ FIT_ERROR_KTOL_RMS
Gaus fit failed! RMS < kTol.
@ FIT_ERROR_ENTRIES
Gaus fit failed! entries < 12.
@ FIT_ERROR_MIN
Gaus fit failed! yMax < 4.
@ FIT_ERROR_KTOL_SIGMA
Gaus fit failed! std::abs(par[2]) < kTol.
@ FIT_ERROR_MAX
Gaus fit failed! yMax too large.
double getIntegralBoostHist(boost::histogram::histogram< axes... > &hist, double min, double max)
Function to integrate 1d boost histogram in specified range.
TH1F TH1FFromBoost(BoostHist hist, const char *name="hist")
Convert a 2D boost histogram to a root histogram.
std::vector< double > fitBoostHistoWithGaus(boost::histogram::histogram< axes... > &hist)
auto ReduceBoostHistoFastSliceByValue(boost::histogram::histogram< axes... > &hist2d, double xLow, double xHigh, double yLow, double yHigh, bool includeOverflowUnderflow)
Function to project 2d boost histogram onto x-axis.
Hist boostHistoFromRoot_2D(TH2D *inHist2D)
Convert a 2D root histogram to a Boost histogram.
BinCenterView< AxisIterator > operator+(BinCenterView< AxisIterator > lhs, int n)
auto ProjectBoostHistoX(const boost::histogram::histogram< axes... > &hist2d, const int binLow, const int binHigh)
Function to project 2d boost histogram onto x-axis.
auto ReduceBoostHistoFastSlice(const boost::histogram::histogram< axes... > &hist2d, int binXLow, int binXHigh, int binYLow, int binYHigh, bool includeOverflowUnderflow)
Function to project 2d boost histogram onto x-axis.
std::string createErrorMessageFitGaus(o2::utils::FitGausError_t errorcode)
Printing an error message when then fit returns an invalid result.
auto ReduceBoostHistoFastSlice1D(boost::histogram::histogram< axes... > &hist1d, int binXLow, int binXHigh, bool includeOverflowUnderflow)
double getMeanBoost1D(boost::histogram::histogram< axes... > &inHist1D, const double rangeLow=0, const double rangeHigh=0)
Get the mean of a 1D boost histogram.
double getVarianceBoost1D(boost::histogram::histogram< axes... > &inHist1D, double mean=-999999, const double rangeLow=0, const double rangeHigh=0, const double weight=1)
Get the variance of a 1D boost histogram.
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Common utility functions.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"