78 if(fBuffer ==
nullptr) {
82 auto nbEntries =
static_cast<Int_t
>(fBuffer[0]);
86 if(nbEntries < 0 && action == 0) {
89 Double_t* buffer = fBuffer;
91 nbEntries = -nbEntries;
97 const bool xbinAuto = fXaxis.GetXmax() <= fXaxis.GetXmin();
98 const bool ybinAuto = fYaxis.GetXmax() <= fYaxis.GetXmin();
99 const bool zbinAuto = fZaxis.GetXmax() <= fZaxis.GetXmin();
100 const bool extend = CanExtendAllAxes();
101 if(extend || xbinAuto || ybinAuto || zbinAuto) {
104 Double_t min = fBuffer[2];
106 if(fBuffer[3] < min) {
109 if(fBuffer[3] > max) {
112 for(Int_t i = 1; i < nbEntries; ++i) {
113 Double_t x = fBuffer[4 * i + 2];
120 Double_t y = fBuffer[4 * i + 3];
127 Double_t z = fBuffer[4 * i + 4];
135 if(xbinAuto || ybinAuto || zbinAuto) {
136#if ROOT_VERSION_CODE < ROOT_VERSION(6, 40, 0)
137 THLimitsFinder::GetLimitsFinder()->FindGoodLimits(
this, min, max, min, max, min, max);
139 THLimitsFinder::GetLimitsFinder()->FindGoodLimitsXYZ(
this, min, max, min, max, min, max, xbinAuto ? 0 : fXaxis.GetNbins(), ybinAuto ? 0 : fYaxis.GetNbins(), zbinAuto ? 0 : fZaxis.GetNbins());
143 Int_t keep = fBufferSize;
145 if(min < fXaxis.GetXmin()) {
146 RebinAxis(min, &fXaxis);
148 if(max >= fXaxis.GetXmax()) {
149 RebinAxis(max, &fXaxis);
151 if(min < fYaxis.GetXmin()) {
152 RebinAxis(min, &fYaxis);
154 if(max >= fYaxis.GetXmax()) {
155 RebinAxis(max, &fYaxis);
157 if(min < fZaxis.GetXmin()) {
158 RebinAxis(min, &fZaxis);
160 if(max >= fZaxis.GetXmax()) {
161 RebinAxis(max, &fZaxis);
169 for(Int_t i = 0; i < nbEntries; ++i) {
170 Fill(buffer[4 * i + 2], buffer[4 * i + 3], buffer[4 * i + 4], buffer[4 * i + 1]);
179 if(nbEntries ==
static_cast<Int_t
>(fEntries)) {
180 fBuffer[0] = -nbEntries;
818void GCube::FitSlicesZ(TF1* f1, Int_t binminx, Int_t binmaxx, Int_t binminy, Int_t binmaxy, Int_t cut, Option_t* option)
820 Int_t nbinsx = fXaxis.GetNbins();
821 Int_t nbinsy = fYaxis.GetNbins();
822 Int_t nbinsz = fZaxis.GetNbins();
826 if(binmaxx > nbinsx) {
829 if(binmaxx < binminx) {
836 if(binmaxy > nbinsy) {
839 if(binmaxy < binminy) {
846 f1 =
static_cast<TF1*
>(gROOT->GetFunction(
"gaus"));
848 f1 =
new TF1(
"gaus",
"gaus", fZaxis.GetXmin(), fZaxis.GetXmax());
850 f1->SetRange(fZaxis.GetXmin(), fZaxis.GetXmax());
853 const char* fname = f1->GetName();
854 Int_t npar = f1->GetNpar();
855 auto* parsave =
new Double_t[npar];
856 f1->GetParameters(parsave);
859 std::array<char, 80> name;
860 std::array<char, 80> title;
861 std::vector<TH2D*> hlist(npar);
862 const TArrayD* xbins = fXaxis.GetXbins();
863 const TArrayD* ybins = fYaxis.GetXbins();
864 for(Int_t ipar = 0; ipar < npar; ++ipar) {
865 snprintf(name.data(), name.size(),
"%s_%d", GetName(), ipar);
866 snprintf(title.data(), title.size(),
"Fitted value of par[%d]=%s", ipar, f1->GetParName(ipar));
868 hlist[ipar] =
new TH2D(name.data(), title.data(), nbinsx, fXaxis.GetXmin(), fXaxis.GetXmax(), nbinsy, fYaxis.GetXmin(), fYaxis.GetXmax());
870 hlist[ipar] =
new TH2D(name.data(), title.data(), nbinsx, xbins->fArray, nbinsy, ybins->fArray);
872 hlist[ipar]->GetXaxis()->SetTitle(fXaxis.GetTitle());
873 hlist[ipar]->GetYaxis()->SetTitle(fYaxis.GetTitle());
875 snprintf(name.data(), name.size(),
"%s_chi2", GetName());
876 auto* hchi2 =
new TH2D(name.data(),
"chisquare", nbinsx, fXaxis.GetXmin(), fXaxis.GetXmax(), nbinsy, fYaxis.GetXmin(), fYaxis.GetXmax());
879 auto* hpz =
new TH1D(
"R_temp",
"_temp", nbinsz, fZaxis.GetXmin(), fZaxis.GetXmax());
880 for(Int_t biny = binminy; biny <= binmaxy; biny++) {
881 Double_t y = fYaxis.GetBinCenter(biny);
882 for(Int_t binx = binminx; binx <= binmaxx; binx++) {
883 Double_t x = fXaxis.GetBinCenter(binx);
886 for(Int_t binz = 1; binz <= nbinsz; binz++) {
887 Int_t bin =
GetBin(binx, biny, binz);
888 Double_t w = RetrieveBinContent(bin);
892 hpz->Fill(fZaxis.GetBinCenter(binz), w);
893 hpz->SetBinError(binz, GetBinError(bin));
899 f1->SetParameters(parsave);
900 hpz->Fit(fname, option);
901 Int_t npfits = f1->GetNumberFitPoints();
902 if(npfits > npar && npfits >= cut) {
903 for(Int_t ipar = 0; ipar < npar; ipar++) {
904 hlist[ipar]->Fill(x, y, f1->GetParameter(ipar));
905 hlist[ipar]->SetBinError(binx, biny, f1->GetParError(ipar));
907 hchi2->SetBinContent(binx, biny, f1->GetChisquare() / (npfits - npar));
1326 Int_t ubx = fXaxis.FindBin(x);
1327 if(x < fXaxis.GetBinCenter(ubx)) {
1330 Int_t obx = ubx + 1;
1332 Int_t uby = fYaxis.FindBin(y);
1333 if(y < fYaxis.GetBinCenter(uby)) {
1336 Int_t oby = uby + 1;
1338 Int_t ubz = fZaxis.FindBin(z);
1339 if(z < fZaxis.GetBinCenter(ubz)) {
1342 Int_t obz = ubz + 1;
1344 if(ubx <= 0 || uby <= 0 || ubz <= 0 || obx > fXaxis.GetNbins() || oby > fYaxis.GetNbins() ||
1345 obz > fZaxis.GetNbins()) {
1346 Error(
"Interpolate",
"Cannot interpolate outside histogram domain.");
1350 Double_t xw = fXaxis.GetBinCenter(obx) - fXaxis.GetBinCenter(ubx);
1351 Double_t yw = fYaxis.GetBinCenter(oby) - fYaxis.GetBinCenter(uby);
1352 Double_t zw = fZaxis.GetBinCenter(obz) - fZaxis.GetBinCenter(ubz);
1354 Double_t xd = (x - fXaxis.GetBinCenter(ubx)) / xw;
1355 Double_t yd = (y - fYaxis.GetBinCenter(uby)) / yw;
1356 Double_t zd = (z - fZaxis.GetBinCenter(ubz)) / zw;
1358 std::array<Double_t, 8> v = {GetBinContent(ubx, uby, ubz), GetBinContent(ubx, uby, obz), GetBinContent(ubx, oby, ubz),
1359 GetBinContent(ubx, oby, obz), GetBinContent(obx, uby, ubz), GetBinContent(obx, uby, obz),
1360 GetBinContent(obx, oby, ubz), GetBinContent(obx, oby, obz)};
1362 Double_t i1 = v[0] * (1 - zd) + v[1] * zd;
1363 Double_t i2 = v[2] * (1 - zd) + v[3] * zd;
1364 Double_t j1 = v[4] * (1 - zd) + v[5] * zd;
1365 Double_t j2 = v[6] * (1 - zd) + v[7] * zd;
1367 Double_t w1 = i1 * (1 - yd) + i2 * yd;
1368 Double_t w2 = j1 * (1 - yd) + j2 * yd;
1370 Double_t result = w1 * (1 - xd) + w2 * xd;
1398 TString opt = option;
1402 auto* h1 =
const_cast<TH1*
>(
static_cast<const TH1*
>(
this));
1406 TAxis* xaxis1 = h1->GetXaxis();
1407 auto* xaxis2 =
const_cast<TAxis*
>(h2->GetXaxis());
1408 Int_t nc1 = xaxis1->GetNbins();
1409 Int_t nc2 = xaxis2->GetNbins();
1412 if(h1->GetDimension() != 3 || h2->GetDimension() != 3) {
1413 Error(
"KolmogorovTest",
"Histograms must be 3-D\n");
1418 if(nc1 != nc2 || nc1 < 1) {
1419 Error(
"KolmogorovTest",
"Number of channels is different, %d and %d\n", nc1, nc2);
1424 Bool_t afunc1 = kFALSE;
1425 Bool_t afunc2 = kFALSE;
1426 Double_t difprec = 1e-5;
1427 Double_t diff1 = TMath::Abs(xaxis1->GetXmin() - xaxis2->GetXmin());
1428 Double_t diff2 = TMath::Abs(xaxis1->GetXmax() - xaxis2->GetXmax());
1429 if(diff1 > difprec || diff2 > difprec) {
1430 Error(
"KolmogorovTest",
"histograms with different binning along X");
1437 if(opt.Contains(
"U")) {
1440 if(opt.Contains(
"O")) {
1448 for(Int_t i = ibeg; i <= iend; ++i) {
1449 for(Int_t j = ibeg; j <= iend; ++j) {
1450 for(Int_t k = ibeg; k <= iend; ++k) {
1451 sum1 += h1->GetBinContent(i, j, k);
1452 sum2 += h2->GetBinContent(i, j, k);
1453 Double_t ew1 = h1->GetBinError(i, j, k);
1454 Double_t ew2 = h2->GetBinError(i, j, k);
1463 Error(
"KolmogorovTest",
"Integral is zero for h1=%s\n", h1->GetName());
1467 Error(
"KolmogorovTest",
"Integral is zero for h2=%s\n", h2->GetName());
1473 Double_t esum1 = 0.;
1474 Double_t esum2 = 0.;
1476 esum1 = sum1 * sum1 / w1;
1482 esum2 = sum2 * sum2 / w2;
1487 if(afunc2 && afunc1) {
1488 Error(
"KolmogorovTest",
"Errors are zero for both histograms\n");
1494 std::array<int, 3> order = {0, 1, 2};
1495 std::array<int, 3> binbeg;
1496 std::array<int, 3> binend;
1497 std::array<int, 3> ibin;
1504 std::array<Double_t, 6> vdfmax;
1506 Double_t s1 = 1. / (6. * sum1);
1507 Double_t s2 = 1. / (6. * sum2);
1508 Double_t rsum1 = 0.;
1509 Double_t rsum2 = 0.;
1513 for(Int_t i = binbeg[order[0]]; i <= binend[order[0]]; i++) {
1514 for(Int_t j = binbeg[order[1]]; j <= binend[order[1]]; j++) {
1515 for(Int_t k = binbeg[order[2]]; k <= binend[order[2]]; k++) {
1519 int bin = h1->GetBin(ibin[0], ibin[1], ibin[2]);
1520 rsum1 += s1 * h1->GetBinContent(bin);
1521 rsum2 += s2 * h2->GetBinContent(bin);
1522 dmax = TMath::Max(dmax, TMath::Abs(rsum1 - rsum2));
1526 vdfmax[icomb] = dmax;
1528 }
while(TMath::Permute(3, order.data()));
1531 Double_t dfmax = TMath::Mean(vdfmax.size(), vdfmax.data());
1534 Double_t factnm = 0.;
1536 factnm = TMath::Sqrt(sum2);
1538 factnm = TMath::Sqrt(sum1);
1540 factnm = TMath::Sqrt(sum1 * sum2 / (sum1 + sum2));
1542 Double_t z = dfmax * factnm;
1544 prb = TMath::KolmogorovProb(z);
1549 if(opt.Contains(
"N") && !(afunc1 || afunc2)) {
1552 Double_t d12 = esum1 - esum2;
1553 Double_t chi2 = d12 * d12 / (esum1 + esum2);
1554 prb2 = TMath::Prob(chi2, 1);
1556 if(prb > 0 && prb2 > 0) {
1557 prb = prb * prb2 * (1 - TMath::Log(prb * prb2));
1564 if(opt.Contains(
"D")) {
1565 std::cout <<
" Kolmo Prob h1 = " << h1->GetName() <<
", sum1 = " << sum1 << std::endl;
1566 std::cout <<
" Kolmo Prob h2 = " << h2->GetName() <<
", sum2 = " << sum2 << std::endl;
1567 std::cout <<
" Kolmo Probabil = " << prb <<
", Max dist = " << dfmax << std::endl;
1568 if(opt.Contains(
"N")) {
1569 std::cout <<
" Kolmo Probabil = " << prb1 <<
" for shape alone, " << prb2 <<
" for normalisation alone" << std::endl;
1573 if(TMath::Abs(rsum1 - 1) > 0.002) {
1574 Warning(
"KolmogorovTest",
"Numerical problems with h1=%s\n", h1->GetName());
1576 if(TMath::Abs(rsum2 - 1) > 0.002) {
1577 Warning(
"KolmogorovTest",
"Numerical problems with h2=%s\n", h2->GetName());
1580 if(opt.Contains(
"M")) {
1602 if(list ==
nullptr) {
1605 if(list->IsEmpty()) {
1606 return static_cast<Long64_t
>(GetEntries());
1610 inlist.AddAll(list);
1615 Bool_t initialLimitsFound = kFALSE;
1616 Bool_t allSameLimits = kTRUE;
1617 Bool_t allHaveLimits = kTRUE;
1618 Bool_t firstNonEmptyHist = kTRUE;
1620 TIter next(&inlist);
1624 if(h->fTsumw == 0 && h->GetEntries() == 0) {
1628 Bool_t hasLimits = h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax();
1629 allHaveLimits = allHaveLimits && hasLimits;
1636 if(firstNonEmptyHist) {
1639 if(!SameLimitsAndNBins(fXaxis, *(h->GetXaxis()))) {
1640 fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
1642 if(!SameLimitsAndNBins(fYaxis, *(h->GetYaxis()))) {
1643 fYaxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax());
1645 if(!SameLimitsAndNBins(fZaxis, *(h->GetZaxis()))) {
1646 fZaxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(), h->GetZaxis()->GetXmax());
1649 firstNonEmptyHist = kFALSE;
1652 if(!initialLimitsFound) {
1655 initialLimitsFound = kTRUE;
1656 newXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
1657 newYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax());
1658 newZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(), h->GetYaxis()->GetXmax());
1661 if(!SameLimitsAndNBins(newXAxis, *(h->GetXaxis())) || !SameLimitsAndNBins(newYAxis, *(h->GetYaxis())) ||
1662 !SameLimitsAndNBins(newZAxis, *(h->GetZaxis()))) {
1663 allSameLimits = kFALSE;
1667 if(!RecomputeAxisLimits(newXAxis, *(h->GetXaxis()))) {
1668 Error(
"Merge",
"Cannot merge histograms - limits are inconsistent:\n "
1669 "first: (%d, %f, %f), second: (%d, %f, %f)",
1670 newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(), h->GetXaxis()->GetNbins(),
1671 h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
1674 if(!RecomputeAxisLimits(newYAxis, *(h->GetYaxis()))) {
1675 Error(
"Merge",
"Cannot merge histograms - limits are inconsistent:\n "
1676 "first: (%d, %f, %f), second: (%d, %f, %f)",
1677 newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax(), h->GetYaxis()->GetNbins(),
1678 h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax());
1681 if(!RecomputeAxisLimits(newZAxis, *(h->GetZaxis()))) {
1682 Error(
"Merge",
"Cannot merge histograms - limits are inconsistent:\n "
1683 "first: (%d, %f, %f), second: (%d, %f, %f)",
1684 newZAxis.GetNbins(), newZAxis.GetXmin(), newZAxis.GetXmax(), h->GetZaxis()->GetNbins(),
1685 h->GetZaxis()->GetXmin(), h->GetZaxis()->GetXmax());
1691 }
while((h =
static_cast<GCube*
>(next())) !=
nullptr);
1692 if(h ==
nullptr && ((*next) !=
nullptr)) {
1693 Error(
"Merge",
"Attempt to merge object of class: %s to a %s", (*next)->ClassName(), ClassName());
1702 GCube* hclone =
nullptr;
1703 if(!allSameLimits) {
1706 Bool_t mustCleanup = TestBit(kMustCleanup);
1708 ResetBit(kMustCleanup);
1710 hclone =
static_cast<GCube*
>(IsA()->New());
1711 hclone->SetDirectory(
nullptr);
1714 SetBit(kMustCleanup);
1719 inlist.AddFirst(hclone);
1722 if(!allSameLimits && initialLimitsFound) {
1723 SetBins(newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(), newYAxis.GetNbins(), newYAxis.GetXmin(),
1724 newYAxis.GetXmax(), newZAxis.GetNbins(), newZAxis.GetXmin(), newZAxis.GetXmax());
1727 if(!allHaveLimits) {
1729 while((h =
static_cast<GCube*
>(next())) !=
nullptr) {
1730 if(h->GetXaxis()->GetXmin() >= h->GetXaxis()->GetXmax() && (h->fBuffer !=
nullptr)) {
1732 auto nbentries =
static_cast<Int_t
>(h->fBuffer[0]);
1733 for(Int_t i = 0; i < nbentries; i++) {
1734 Fill(h->fBuffer[4 * i + 2], h->fBuffer[4 * i + 3], h->fBuffer[4 * i + 4], h->fBuffer[4 * i + 1]);
1740 if(!initialLimitsFound) {
1741 if(hclone !=
nullptr) {
1742 inlist.Remove(hclone);
1745 return static_cast<Long64_t
>(GetEntries());
1751 std::array<Double_t, kNstat> stats;
1752 std::array<Double_t, kNstat> totstats;
1753 for(Int_t i = 0; i < kNstat; ++i) {
1754 totstats[i] = stats[i] = 0;
1757 Double_t nentries = GetEntries();
1761 Bool_t canExtend = CanExtendAllAxes();
1762 SetCanExtend(TH1::kNoAxis);
1764 while((h =
static_cast<GCube*
>(next())) !=
nullptr) {
1766 if(h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax()) {
1769 for(Int_t i = 0; i < kNstat; ++i) {
1770 totstats[i] += stats[i];
1772 nentries += h->GetEntries();
1774 Int_t nx = h->GetXaxis()->GetNbins();
1775 Int_t ny = h->GetYaxis()->GetNbins();
1776 Int_t nz = h->GetZaxis()->GetNbins();
1780 for(Int_t binz = 0; binz <= nz + 1; ++binz) {
1781 if(!allSameLimits) {
1782 iz = fZaxis.FindBin(h->GetZaxis()->GetBinCenter(binz));
1787 for(Int_t biny = 0; biny <= ny + 1; ++biny) {
1788 if(!allSameLimits) {
1789 iy = fYaxis.FindBin(h->GetYaxis()->GetBinCenter(biny));
1793 for(Int_t binx = 0; binx <= nx + 1; ++binx) {
1794 Int_t bin = binx + (nx + 2) * (biny + (ny + 2) * binz);
1795 Double_t cu = h->GetBinContent(bin);
1796 if(!allSameLimits) {
1798 if(cu != 0 && (h->IsBinUnderflow(bin) || h->IsBinOverflow(bin))) {
1799 Error(
"Merge",
"Cannot merge histograms - the histograms have"
1800 " different limits and undeflows/overflows are present."
1801 " The initial histogram is now broken!");
1804 ix = fXaxis.FindBin(h->GetXaxis()->GetBinCenter(binx));
1809 Int_t ibin =
GetBin(ix, iy, iz);
1814 AddBinContent(ibin, cu);
1815 if(fSumw2.fN != 0) {
1816 Double_t error1 = h->GetBinError(bin);
1817 fSumw2.fArray[ibin] += error1 * error1;
1825 SetCanExtend(
static_cast<UInt_t
>(canExtend));
1830 SetEntries(nentries);
1831 if(hclone !=
nullptr) {
1832 inlist.Remove(hclone);
1835 return static_cast<Long64_t
>(nentries);
1838TH1D*
GCube::Projection(
const char* name, Int_t firstBiny, Int_t lastBiny, Int_t firstBinz, Int_t lastBinz,
1839 Option_t* option)
const
1842 const char* expectedName =
"_pr";
1844 TString opt = option;
1846 Int_t i1 = opt.Index(
"[");
1848 Int_t i2 = opt.Index(
"]");
1849 cut = opt(i1, i2 - i1 + 1);
1852 bool originalRange = opt.Contains(
"o");
1854 Int_t firstXBin = fXaxis.GetFirst();
1855 Int_t lastXBin = fXaxis.GetLast();
1857 if(firstXBin == 0 && lastXBin == 0) {
1859 lastXBin = fXaxis.GetNbins();
1862 if(lastBiny < firstBiny && fYaxis.TestBit(TAxis::kAxisRange)) {
1863 firstBiny = fYaxis.GetFirst();
1864 lastBiny = fYaxis.GetLast();
1868 if(firstBiny == 0 && lastBiny == 0) {
1870 lastBiny = fYaxis.GetNbins();
1877 lastBiny = fYaxis.GetLast() + 1;
1879 if(lastBiny > fYaxis.GetLast() + 1) {
1880 lastBiny = fYaxis.GetLast() + 1;
1883 if(lastBinz < firstBinz && fZaxis.TestBit(TAxis::kAxisRange)) {
1884 firstBinz = fZaxis.GetFirst();
1885 lastBinz = fZaxis.GetLast();
1889 if(firstBinz == 0 && lastBinz == 0) {
1891 lastBinz = fZaxis.GetNbins();
1898 lastBinz = fZaxis.GetLast() + 1;
1900 if(lastBinz > fZaxis.GetLast() + 1) {
1901 lastBinz = fZaxis.GetLast() + 1;
1905 char* pname =
const_cast<char*
>(name);
1906 if(name !=
nullptr && strcmp(name, expectedName) == 0) {
1907 auto nch = strlen(GetName()) + 4;
1908 pname =
new char[nch];
1909 snprintf(pname, nch,
"%s%s", GetName(), name);
1915 TObject* h1obj = gROOT->FindObject(pname);
1916 if((h1obj !=
nullptr) && h1obj->InheritsFrom(TH1::Class())) {
1917 if(h1obj->IsA() != TH1D::Class()) {
1918 Error(
"DoProjection",
"Histogram with name %s must be a TH1D and is a %s", name, h1obj->ClassName());
1921 h1 =
static_cast<TH1D*
>(h1obj);
1926 const TArrayD* xbins = fXaxis.GetXbins();
1927 if(xbins->fN == 0) {
1929 h1->SetBins(fXaxis.GetNbins(), fXaxis.GetXmin(), fXaxis.GetXmax());
1931 h1->SetBins(lastXBin - firstXBin + 1, fXaxis.GetBinLowEdge(firstXBin), fXaxis.GetBinUpEdge(lastXBin));
1936 h1->SetBins(fXaxis.GetNbins(), xbins->fArray);
1938 h1->SetBins(lastXBin - firstXBin + 1, &(xbins->fArray[firstXBin - 1]));
1944 const TArrayD* bins = fXaxis.GetXbins();
1947 h1 =
new TH1D(pname, GetTitle(), fXaxis.GetNbins(), fXaxis.GetXmin(), fXaxis.GetXmax());
1949 h1 =
new TH1D(pname, GetTitle(), lastXBin - firstXBin + 1, fXaxis.GetBinLowEdge(firstXBin),
1950 fXaxis.GetBinUpEdge(lastXBin));
1955 h1 =
new TH1D(pname, GetTitle(), fXaxis.GetNbins(), bins->fArray);
1957 h1 =
new TH1D(pname, GetTitle(), lastXBin - firstXBin + 1, &(bins->fArray[firstXBin - 1]));
1960 if(opt.Contains(
"e") || (GetSumw2N() != 0)) {
1969 h1->GetXaxis()->ImportAttributes(&fXaxis);
1970 THashList* labels =
const_cast<TAxis*
>(&fXaxis)->GetLabels();
1971 if(labels !=
nullptr) {
1973 TObjString* lb =
nullptr;
1975 while((lb =
static_cast<TObjString*
>(iL())) !=
nullptr) {
1976 h1->GetXaxis()->SetBinLabel(i, lb->String().Data());
1981 h1->SetLineColor(GetLineColor());
1982 h1->SetFillColor(GetFillColor());
1983 h1->SetMarkerColor(GetMarkerColor());
1984 h1->SetMarkerStyle(GetMarkerStyle());
1987 Double_t totcont = 0.;
1988 Bool_t computeErrors = h1->GetSumw2N() != 0;
1993 for(Int_t xbin = 0; xbin <= fXaxis.GetNbins() + 1; ++xbin) {
1996 if(fXaxis.TestBit(TAxis::kAxisRange) && (xbin < firstXBin || xbin > lastXBin)) {
2000 for(Int_t ybin = firstBiny; ybin <= lastBiny; ++ybin) {
2001 for(Int_t zbin = firstBinz; zbin <= lastBinz; ++zbin) {
2003 cont += GetBinContent(xbin, ybin, zbin);
2005 Double_t exy = GetBinError(xbin, ybin, zbin);
2011 Int_t binOut = h1->GetXaxis()->FindBin(fXaxis.GetBinCenter(xbin));
2012 h1->SetBinContent(binOut, cont);
2014 h1->SetBinError(binOut, TMath::Sqrt(err2));
2021 bool reuseStats =
false;
2022 if(((!fgStatOverflows && firstBiny == 1 && lastBiny == fYaxis.GetLast()) ||
2023 (fgStatOverflows && firstBiny == 0 && lastBiny == fYaxis.GetLast() + 1)) &&
2024 ((!fgStatOverflows && firstBinz == 1 && lastBinz == fZaxis.GetLast()) ||
2025 (fgStatOverflows && firstBinz == 0 && lastBinz == fZaxis.GetLast() + 1))) {
2029 double eps = 1.E-12;
2030 if(IsA() == GCubeF::Class()) {
2033 if(fTsumw != 0 && TMath::Abs(fTsumw - totcont) < TMath::Abs(fTsumw) * eps) {
2038 bool reuseEntries = reuseStats;
2040 reuseEntries &=
static_cast<int>(firstBiny == 0 && lastBiny == fYaxis.GetLast() + 1 && firstBinz == 0 &&
2041 lastBinz == fYaxis.GetLast() + 1);
2043 std::array<Double_t, kNstat> stat;
2045 h1->PutStats(stat.data());
2050 h1->SetEntries(h1->GetEffectiveEntries());
2053 h1->SetEntries(fEntries);
2059 Double_t entries = TMath::Floor(totcont + 0.5);
2060 if(h1->GetSumw2N() != 0) {
2061 entries = h1->GetEffectiveEntries();
2063 h1->SetEntries(entries);
2066 if(opt.Contains(
"d")) {
2067 TVirtualPad* padsav = gPad;
2068 TVirtualPad* pad = gROOT->GetSelectedPad();
2069 if(pad !=
nullptr) {
2072 opt.Remove(opt.First(
"d"), 1);
2074 if(opt.Contains(
"e")) {
2075 opt.Remove(opt.First(
"e"), 1);
2077 if(!gPad || !gPad->FindObject(h1)) {
2082 if(padsav !=
nullptr) {
2128 Int_t nbins = fXaxis.GetNbins();
2129 Double_t min = fXaxis.GetXmin();
2130 Double_t max = fXaxis.GetXmax();
2131 if((ngroup <= 0) || (ngroup > nbins)) {
2132 Error(
"Rebin",
"Illegal value of ngroup=%d", ngroup);
2136 Int_t newbins = nbins / ngroup;
2139 Double_t entries = fEntries;
2140 auto* oldBins =
new Double_t[(nbins + 2) * (nbins + 3) * (nbins + 4) / 6];
2141 for(Int_t xbin = 0; xbin < nbins + 2; xbin++) {
2142 for(Int_t ybin = 0; ybin <= xbin; ybin++) {
2143 for(Int_t zbin = 0; zbin <= ybin; zbin++) {
2144 Int_t bin =
GetBin(xbin, ybin, zbin);
2145 oldBins[bin] = GetBinContent(bin);
2149 Double_t* oldErrors =
nullptr;
2150 if(fSumw2.fN != 0) {
2151 oldErrors =
new Double_t[(nbins + 2) * (nbins + 3) * (nbins + 4) / 6];
2152 for(Int_t xbin = 0; xbin < nbins + 2; xbin++) {
2153 for(Int_t ybin = 0; ybin <= xbin; ybin++) {
2154 for(Int_t zbin = 0; zbin <= ybin; zbin++) {
2155 Int_t bin =
GetBin(xbin, ybin, zbin);
2156 oldErrors[bin] = GetBinError(bin);
2164 if(newname !=
nullptr && (strlen(newname) != 0u)) {
2165 hnew =
static_cast<GCube*
>(Clone());
2166 hnew->SetName(newname);
2170 std::array<Double_t, kNstat> stat;
2173 bool resetStat =
false;
2176 if(newbins * ngroup != nbins) {
2177 max = fXaxis.GetBinUpEdge(newbins * ngroup);
2181 Int_t nXdivisions = fXaxis.GetNdivisions();
2182 Color_t xAxisColor = fXaxis.GetAxisColor();
2183 Color_t xLabelColor = fXaxis.GetLabelColor();
2184 Style_t xLabelFont = fXaxis.GetLabelFont();
2185 Float_t xLabelOffset = fXaxis.GetLabelOffset();
2186 Float_t xLabelSize = fXaxis.GetLabelSize();
2187 Float_t xTickLength = fXaxis.GetTickLength();
2188 Float_t xTitleOffset = fXaxis.GetTitleOffset();
2189 Float_t xTitleSize = fXaxis.GetTitleSize();
2190 Color_t xTitleColor = fXaxis.GetTitleColor();
2191 Style_t xTitleFont = fXaxis.GetTitleFont();
2193 Int_t nYdivisions = fYaxis.GetNdivisions();
2194 Color_t yAxisColor = fYaxis.GetAxisColor();
2195 Color_t yLabelColor = fYaxis.GetLabelColor();
2196 Style_t yLabelFont = fYaxis.GetLabelFont();
2197 Float_t yLabelOffset = fYaxis.GetLabelOffset();
2198 Float_t yLabelSize = fYaxis.GetLabelSize();
2199 Float_t yTickLength = fYaxis.GetTickLength();
2200 Float_t yTitleOffset = fYaxis.GetTitleOffset();
2201 Float_t yTitleSize = fYaxis.GetTitleSize();
2202 Color_t yTitleColor = fYaxis.GetTitleColor();
2203 Style_t yTitleFont = fYaxis.GetTitleFont();
2205 Int_t nZdivisions = fZaxis.GetNdivisions();
2206 Color_t zAxisColor = fZaxis.GetAxisColor();
2207 Color_t zLabelColor = fZaxis.GetLabelColor();
2208 Style_t zLabelFont = fZaxis.GetLabelFont();
2209 Float_t zLabelOffset = fZaxis.GetLabelOffset();
2210 Float_t zLabelSize = fZaxis.GetLabelSize();
2211 Float_t zTickLength = fZaxis.GetTickLength();
2212 Float_t zTitleOffset = fZaxis.GetTitleOffset();
2213 Float_t zTitleSize = fZaxis.GetTitleSize();
2214 Color_t zTitleColor = fZaxis.GetTitleColor();
2215 Style_t zTitleFont = fZaxis.GetTitleFont();
2219 if(fXaxis.GetXbins()->GetSize() > 0 || fYaxis.GetXbins()->GetSize() > 0 || fZaxis.GetXbins()->GetSize() > 0) {
2221 auto* bins =
new Double_t[newbins + 1];
2222 for(Int_t i = 0; i <= newbins; ++i) {
2223 bins[i] = fXaxis.GetBinLowEdge(1 + i * ngroup);
2225 hnew->SetBins(newbins, bins, newbins, bins);
2228 hnew->SetBins(newbins, min, max, newbins, min, max);
2234 for(Int_t xbin = 1; xbin <= newbins; ++xbin) {
2236 for(Int_t ybin = 1; ybin <= xbin; ++ybin) {
2237 Double_t binContent = 0;
2238 Double_t binError = 0;
2239 for(Int_t i = 0; i < ngroup; ++i) {
2240 if(oldxbin + i > nbins) {
2243 for(Int_t j = 0; j < ngroup; ++j) {
2244 if(oldybin + j > nbins) {
2248 if(oldybin + j <= oldxbin + i) {
2249 bin = oldxbin + i + (oldybin + j) * (2 * fXaxis.GetNbins() - (oldybin + j) + 3) / 2;
2251 bin = oldybin + j + (oldxbin + i) * (2 * fXaxis.GetNbins() - (oldxbin + i) + 3) / 2;
2253 binContent += oldBins[bin];
2254 if(oldErrors !=
nullptr) {
2255 binError += oldErrors[bin] * oldErrors[bin];
2259 hnew->SetBinContent(xbin, ybin, binContent);
2260 if(oldErrors !=
nullptr) {
2261 hnew->SetBinError(xbin, ybin, TMath::Sqrt(binError));
2271 hnew->SetBinContent(0, 0, oldBins[0]);
2272 if(oldErrors !=
nullptr) {
2273 hnew->SetBinError(0, 0, oldErrors[0]);
2277 Double_t binContent = 0.;
2278 Double_t binError = 0.;
2279 for(Int_t xbin = oldxbin; xbin <= nbins + 1; ++xbin) {
2280 for(Int_t ybin = oldybin; ybin <= xbin; ++ybin) {
2281 bin = xbin + ybin * (2 * nbins - ybin + 3) / 2;
2282 binContent += oldBins[bin];
2283 if(oldErrors !=
nullptr) {
2284 binError += oldErrors[bin] * oldErrors[bin];
2288 hnew->SetBinContent(newbins + 1, newbins + 1, binContent);
2289 if(oldErrors !=
nullptr) {
2290 hnew->SetBinError(newbins + 1, newbins + 1, TMath::Sqrt(binError));
2296 for(Int_t ybin = oldybin; ybin <= nbins + 1; ++ybin) {
2297 bin = ybin * (2 * nbins - ybin + 3) / 2;
2298 binContent += oldBins[bin];
2299 if(oldErrors !=
nullptr) {
2300 binError += oldErrors[bin] * oldErrors[bin];
2303 hnew->SetBinContent(0, newbins + 1, binContent);
2304 if(oldErrors !=
nullptr) {
2305 hnew->SetBinError(0, newbins + 1, TMath::Sqrt(binError));
2311 for(Int_t xbin = oldxbin; xbin <= nbins + 1; ++xbin) {
2313 binContent += oldBins[bin];
2314 if(oldErrors !=
nullptr) {
2315 binError += oldErrors[bin] * oldErrors[bin];
2318 hnew->SetBinContent(newbins + 1, 0, binContent);
2319 if(oldErrors !=
nullptr) {
2320 hnew->SetBinError(newbins + 1, 0, TMath::Sqrt(binError));
2325 for(Int_t xbin = 1; xbin <= newbins; ++xbin) {
2326 Double_t binContent0 = 0.;
2327 Double_t binContent2 = 0.;
2328 Double_t binError0 = 0.;
2329 Double_t binError2 = 0.;
2330 for(Int_t i = 0; i < ngroup; ++i) {
2331 if(oldxbin2 + i > nbins) {
2335 Int_t ufbin = oldxbin2 + i;
2336 binContent0 += oldBins[ufbin];
2337 if(oldErrors !=
nullptr) {
2338 binError0 += oldErrors[ufbin] * oldErrors[ufbin];
2340 for(Int_t ybin = oldybin; ybin <= nbins + 1; ++ybin) {
2342 Int_t ofbin = ufbin + ybin * (nbins + 2);
2343 binContent2 += oldBins[ofbin];
2344 if(oldErrors !=
nullptr) {
2345 binError2 += oldErrors[ofbin] * oldErrors[ofbin];
2349 hnew->SetBinContent(xbin, 0, binContent0);
2350 hnew->SetBinContent(xbin, newbins + 1, binContent2);
2351 if(oldErrors !=
nullptr) {
2352 hnew->SetBinError(xbin, 0, TMath::Sqrt(binError0));
2353 hnew->SetBinError(xbin, newbins + 1, TMath::Sqrt(binError2));
2360 for(Int_t ybin = 1; ybin <= newbins; ++ybin) {
2361 Double_t binContent0 = 0.;
2362 Double_t binContent2 = 0.;
2363 Double_t binError0 = 0.;
2364 Double_t binError2 = 0.;
2365 for(Int_t i = 0; i < ngroup; ++i) {
2366 if(oldybin2 + i > nbins) {
2370 Int_t ufbin = (oldybin2 + i) * (nbins + 2);
2371 binContent0 += oldBins[ufbin];
2372 if(oldErrors !=
nullptr) {
2373 binError0 += oldErrors[ufbin] * oldErrors[ufbin];
2375 for(Int_t xbin = oldxbin; xbin <= nbins + 1; ++xbin) {
2376 Int_t ofbin = ufbin + xbin;
2377 binContent2 += oldBins[ofbin];
2378 if(oldErrors !=
nullptr) {
2379 binError2 += oldErrors[ofbin] * oldErrors[ofbin];
2383 hnew->SetBinContent(0, ybin, binContent0);
2384 hnew->SetBinContent(newbins + 1, ybin, binContent2);
2385 if(oldErrors !=
nullptr) {
2386 hnew->SetBinError(0, ybin, TMath::Sqrt(binError0));
2387 hnew->SetBinError(newbins + 1, ybin, TMath::Sqrt(binError2));
2394 fXaxis.SetNdivisions(nXdivisions);
2395 fXaxis.SetAxisColor(xAxisColor);
2396 fXaxis.SetLabelColor(xLabelColor);
2397 fXaxis.SetLabelFont(xLabelFont);
2398 fXaxis.SetLabelOffset(xLabelOffset);
2399 fXaxis.SetLabelSize(xLabelSize);
2400 fXaxis.SetTickLength(xTickLength);
2401 fXaxis.SetTitleOffset(xTitleOffset);
2402 fXaxis.SetTitleSize(xTitleSize);
2403 fXaxis.SetTitleColor(xTitleColor);
2404 fXaxis.SetTitleFont(xTitleFont);
2406 fYaxis.SetNdivisions(nYdivisions);
2407 fYaxis.SetAxisColor(yAxisColor);
2408 fYaxis.SetLabelColor(yLabelColor);
2409 fYaxis.SetLabelFont(yLabelFont);
2410 fYaxis.SetLabelOffset(yLabelOffset);
2411 fYaxis.SetLabelSize(yLabelSize);
2412 fYaxis.SetTickLength(yTickLength);
2413 fYaxis.SetTitleOffset(yTitleOffset);
2414 fYaxis.SetTitleSize(yTitleSize);
2415 fYaxis.SetTitleColor(yTitleColor);
2416 fYaxis.SetTitleFont(yTitleFont);
2418 fZaxis.SetNdivisions(nZdivisions);
2419 fZaxis.SetAxisColor(zAxisColor);
2420 fZaxis.SetLabelColor(zLabelColor);
2421 fZaxis.SetLabelFont(zLabelFont);
2422 fZaxis.SetLabelOffset(zLabelOffset);
2423 fZaxis.SetLabelSize(zLabelSize);
2424 fZaxis.SetTickLength(zTickLength);
2425 fZaxis.SetTitleOffset(zTitleOffset);
2426 fZaxis.SetTitleSize(zTitleSize);
2427 fZaxis.SetTitleColor(zTitleColor);
2428 fZaxis.SetTitleFont(zTitleFont);
2431 hnew->SetEntries(entries);
2538 std::array<std::array<Double_t, 5>, 5> k5a = {{{0, 0, 1, 0, 0}, {0, 2, 2, 2, 0}, {1, 2, 5, 2, 1}, {0, 2, 2, 2, 0}, {0, 0, 1, 0, 0}}};
2539 std::array<std::array<Double_t, 5>, 5> k5b = {{{0, 1, 2, 1, 0}, {1, 2, 4, 2, 1}, {2, 4, 8, 4, 2}, {1, 2, 4, 2, 1}, {0, 1, 2, 1, 0}}};
2540 std::array<std::array<Double_t, 3>, 3> k3a = {{{0, 1, 0}, {1, 2, 1}, {0, 1, 0}}};
2543 Warning(
"Smooth",
"Currently only ntimes=1 is supported");
2545 TString opt = option;
2547 Int_t ksize_x = k5a.size();
2548 Int_t ksize_y = k5a.size();
2549 Double_t* kernel = k5a.data()->data();
2550 if(opt.Contains(
"k5b")) {
2551 kernel = k5b.data()->data();
2553 if(opt.Contains(
"k3a")) {
2554 kernel = k3a.data()->data();
2555 ksize_x = k3a.size();
2556 ksize_y = k3a.size();
2560 Int_t ifirst = fXaxis.GetFirst();
2561 Int_t ilast = fXaxis.GetLast();
2562 Int_t jfirst = fYaxis.GetFirst();
2563 Int_t jlast = fYaxis.GetLast();
2566 Double_t nentries = fEntries;
2567 Int_t nx = GetNbinsX();
2568 Int_t ny = GetNbinsY();
2569 Int_t bufSize = (nx + 2) * (ny + 2);
2570 auto* buf =
new Double_t[bufSize];
2571 Double_t* ebuf =
nullptr;
2572 if(fSumw2.fN != 0) {
2573 ebuf =
new Double_t[bufSize];
2577 for(Int_t i = ifirst; i <= ilast; ++i) {
2578 for(Int_t j = jfirst; j <= jlast; ++j) {
2579 Int_t bin =
GetBin(i, j);
2580 buf[bin] = GetBinContent(bin);
2581 if(ebuf !=
nullptr) {
2582 ebuf[bin] = GetBinError(bin);
2588 Int_t x_push = (ksize_x - 1) / 2;
2589 Int_t y_push = (ksize_y - 1) / 2;
2592 for(Int_t i = ifirst; i <= ilast; ++i) {
2593 for(Int_t j = jfirst; j <= jlast; ++j) {
2594 Double_t content = 0.0;
2595 Double_t error = 0.0;
2596 Double_t norm = 0.0;
2598 for(Int_t n = 0; n < ksize_x; ++n) {
2599 for(Int_t m = 0; m < ksize_y; ++m) {
2600 Int_t xb = i + (n - x_push);
2601 Int_t yb = j + (m - y_push);
2602 if((xb >= 1) && (xb <= nx) && (yb >= 1) && (yb <= ny)) {
2603 Int_t bin =
GetBin(xb, yb);
2604 Double_t k = kernel[n * ksize_y + m];
2607 content += k * buf[bin];
2608 if(ebuf !=
nullptr) {
2609 error += k * k * ebuf[bin] * ebuf[bin];
2617 SetBinContent(i, j, content / norm);
2618 if(ebuf !=
nullptr) {
2619 error /= (norm * norm);
2620 SetBinError(i, j, sqrt(error));
2625 fEntries = nentries;