647void GHSym::FitSlices(TF1* f1, Int_t firstbin, Int_t lastbin, Int_t cut, Option_t* option, TObjArray* arr)
698 Int_t nbins = fYaxis.GetNbins();
702 if(lastbin < 0 || lastbin > nbins + 1) {
705 if(lastbin < firstbin) {
709 TString opt = option;
712 if(opt.Contains(
"g2")) {
714 opt.ReplaceAll(
"g2",
"");
716 if(opt.Contains(
"g3")) {
718 opt.ReplaceAll(
"g3",
"");
720 if(opt.Contains(
"g4")) {
722 opt.ReplaceAll(
"g4",
"");
724 if(opt.Contains(
"g5")) {
726 opt.ReplaceAll(
"g5",
"");
730 Int_t nstep = ngroup;
731 if(opt.Contains(
"s")) {
737 f1 =
static_cast<TF1*
>(gROOT->GetFunction(
"gaus"));
739 f1 =
new TF1(
"gaus",
"gaus", fXaxis.GetXmin(), fXaxis.GetXmax());
741 f1->SetRange(fXaxis.GetXmin(), fXaxis.GetXmax());
744 Int_t npar = f1->GetNpar();
748 auto* parsave =
new Double_t[npar];
749 f1->GetParameters(parsave);
753 arr->Expand(npar + 1);
757 auto** hlist =
new TH1D*[npar];
758 auto* name =
new char[2000];
759 auto* title =
new char[2000];
760 const TArrayD* bins = fYaxis.GetXbins();
761 for(Int_t ipar = 0; ipar < npar; ++ipar) {
762 snprintf(name, 2000,
"%s_%d", GetName(), ipar);
763 snprintf(title, 2000,
"Fitted value of par[%d]=%s", ipar, f1->GetParName(ipar));
764 delete gDirectory->FindObject(name);
766 hlist[ipar] =
new TH1D(name, title, nbins, fYaxis.GetXmin(), fYaxis.GetXmax());
768 hlist[ipar] =
new TH1D(name, title, nbins, bins->fArray);
770 hlist[ipar]->GetXaxis()->SetTitle(fYaxis.GetTitle());
772 (*arr)[ipar] = hlist[ipar];
775 snprintf(name, 2000,
"%s_chi2", GetName());
776 delete gDirectory->FindObject(name);
777 TH1D* hchi2 =
nullptr;
779 hchi2 =
new TH1D(name,
"chisquare", nbins, fYaxis.GetXmin(), fYaxis.GetXmax());
781 hchi2 =
new TH1D(name,
"chisquare", nbins, bins->fArray);
783 hchi2->GetXaxis()->SetTitle(fYaxis.GetTitle());
785 (*arr)[npar] = hchi2;
791 for(Int_t bin = firstbin; bin + ngroup - 1 <= lastbin; bin += nstep) {
792 TH1D* proj =
Projection(
"_temp", bin, bin + ngroup - 1,
"e");
793 if(proj ==
nullptr) {
796 auto nentries =
static_cast<Long64_t
>(proj->GetEntries());
797 if(nentries == 0 || nentries < cut) {
801 f1->SetParameters(parsave);
802 proj->Fit(f1, opt.Data());
803 Int_t npfits = f1->GetNumberFitPoints();
804 if(npfits > npar && npfits >= cut) {
805 Int_t binOn = bin + ngroup / 2;
806 for(Int_t ipar = 0; ipar < npar; ++ipar) {
807 hlist[ipar]->Fill(fYaxis.GetBinCenter(binOn), f1->GetParameter(ipar));
808 hlist[ipar]->SetBinError(binOn, f1->GetParError(ipar));
810 hchi2->Fill(fYaxis.GetBinCenter(binOn), f1->GetChisquare() / (npfits - npar));
1150 Int_t bin_x = fXaxis.FindBin(x);
1151 Int_t bin_y = fYaxis.FindBin(y);
1152 if(bin_x < 1 || bin_x > GetNbinsX() || bin_y < 1 || bin_y > GetNbinsY()) {
1153 Error(
"Interpolate",
"Cannot interpolate outside histogram domain.");
1158 dx = fXaxis.GetBinUpEdge(bin_x) - x;
1159 dy = fYaxis.GetBinUpEdge(bin_y) - y;
1160 if(dx <= fXaxis.GetBinWidth(bin_x) / 2 && dy <= fYaxis.GetBinWidth(bin_y) / 2) {
1163 if(dx > fXaxis.GetBinWidth(bin_x) / 2 && dy <= fYaxis.GetBinWidth(bin_y) / 2) {
1166 if(dx > fXaxis.GetBinWidth(bin_x) / 2 && dy > fYaxis.GetBinWidth(bin_y) / 2) {
1169 if(dx <= fXaxis.GetBinWidth(bin_x) / 2 && dy > fYaxis.GetBinWidth(bin_y) / 2) {
1174 x1 = fXaxis.GetBinCenter(bin_x);
1175 y1 = fYaxis.GetBinCenter(bin_y);
1176 x2 = fXaxis.GetBinCenter(bin_x + 1);
1177 y2 = fYaxis.GetBinCenter(bin_y + 1);
1180 x1 = fXaxis.GetBinCenter(bin_x - 1);
1181 y1 = fYaxis.GetBinCenter(bin_y);
1182 x2 = fXaxis.GetBinCenter(bin_x);
1183 y2 = fYaxis.GetBinCenter(bin_y + 1);
1186 x1 = fXaxis.GetBinCenter(bin_x - 1);
1187 y1 = fYaxis.GetBinCenter(bin_y - 1);
1188 x2 = fXaxis.GetBinCenter(bin_x);
1189 y2 = fYaxis.GetBinCenter(bin_y);
1192 x1 = fXaxis.GetBinCenter(bin_x);
1193 y1 = fYaxis.GetBinCenter(bin_y - 1);
1194 x2 = fXaxis.GetBinCenter(bin_x + 1);
1195 y2 = fYaxis.GetBinCenter(bin_y);
1198 Int_t bin_x1 = fXaxis.FindBin(x1);
1202 Int_t bin_x2 = fXaxis.FindBin(x2);
1203 if(bin_x2 > GetNbinsX()) {
1204 bin_x2 = GetNbinsX();
1206 Int_t bin_y1 = fYaxis.FindBin(y1);
1210 Int_t bin_y2 = fYaxis.FindBin(y2);
1211 if(bin_y2 > GetNbinsY()) {
1212 bin_y2 = GetNbinsY();
1214 Int_t bin_q22 = GetBin(bin_x2, bin_y2);
1215 Int_t bin_q12 = GetBin(bin_x1, bin_y2);
1216 Int_t bin_q11 = GetBin(bin_x1, bin_y1);
1217 Int_t bin_q21 = GetBin(bin_x2, bin_y1);
1218 Double_t q11 = GetBinContent(bin_q11);
1219 Double_t q12 = GetBinContent(bin_q12);
1220 Double_t q21 = GetBinContent(bin_q21);
1221 Double_t q22 = GetBinContent(bin_q22);
1222 Double_t d = 1.0 * (x2 - x1) * (y2 - y1);
1223 f = 1.0 * q11 / d * (x2 - x) * (y2 - y) + 1.0 * q21 / d * (x - x1) * (y2 - y) + 1.0 * q12 / d * (x2 - x) * (y - y1) +
1224 1.0 * q22 / d * (x - x1) * (y - y1);
1263 TString opt = option;
1267 TH1* h1 =
const_cast<TH1*
>(
static_cast<const TH1*
>(
this));
1271 TAxis* xaxis1 = h1->GetXaxis();
1272 auto* xaxis2 =
const_cast<TAxis*
>(h2->GetXaxis());
1273 TAxis* yaxis1 = h1->GetYaxis();
1274 auto* yaxis2 =
const_cast<TAxis*
>(h2->GetYaxis());
1275 Int_t ncx1 = xaxis1->GetNbins();
1276 Int_t ncx2 = xaxis2->GetNbins();
1277 Int_t ncy1 = yaxis1->GetNbins();
1278 Int_t ncy2 = yaxis2->GetNbins();
1281 if(h1->GetDimension() != 2 || h2->GetDimension() != 2) {
1282 Error(
"KolmogorovTest",
"Histograms must be 2-D\n");
1288 Error(
"KolmogorovTest",
"Number of channels in X is different, %d and %d\n", ncx1, ncx2);
1292 Error(
"KolmogorovTest",
"Number of channels in Y is different, %d and %d\n", ncy1, ncy2);
1297 Bool_t afunc1 = kFALSE;
1298 Bool_t afunc2 = kFALSE;
1299 Double_t difprec = 1e-5;
1300 Double_t diff1 = TMath::Abs(xaxis1->GetXmin() - xaxis2->GetXmin());
1301 Double_t diff2 = TMath::Abs(xaxis1->GetXmax() - xaxis2->GetXmax());
1302 if(diff1 > difprec || diff2 > difprec) {
1303 Error(
"KolmogorovTest",
"histograms with different binning along X");
1306 diff1 = TMath::Abs(yaxis1->GetXmin() - yaxis2->GetXmin());
1307 diff2 = TMath::Abs(yaxis1->GetXmax() - yaxis2->GetXmax());
1308 if(diff1 > difprec || diff2 > difprec) {
1309 Error(
"KolmogorovTest",
"histograms with different binning along Y");
1318 if(opt.Contains(
"U")) {
1322 if(opt.Contains(
"O")) {
1331 for(Int_t i = ibeg; i <= iend; ++i) {
1332 for(Int_t j = jbeg; j <= jend; ++j) {
1333 sum1 += h1->GetBinContent(i, j);
1334 sum2 += h2->GetBinContent(i, j);
1335 Double_t ew1 = h1->GetBinError(i, j);
1336 Double_t ew2 = h2->GetBinError(i, j);
1344 Error(
"KolmogorovTest",
"Integral is zero for h1=%s\n", h1->GetName());
1348 Error(
"KolmogorovTest",
"Integral is zero for h2=%s\n", h2->GetName());
1354 Double_t esum1 = 0.;
1355 Double_t esum2 = 0.;
1357 esum1 = sum1 * sum1 / w1;
1363 esum2 = sum2 * sum2 / w2;
1368 if(afunc2 && afunc1) {
1369 Error(
"KolmogorovTest",
"Errors are zero for both histograms\n");
1374 Double_t s1 = 1 / sum1;
1375 Double_t s2 = 1 / sum2;
1376 Double_t dfmax1 = 0;
1377 Double_t rsum1 = 0.;
1378 Double_t rsum2 = 0.;
1379 for(Int_t i = ibeg; i <= iend; ++i) {
1380 for(Int_t j = jbeg; j <= jend; ++j) {
1381 rsum1 += s1 * h1->GetCellContent(i, j);
1382 rsum2 += s2 * h2->GetCellContent(i, j);
1383 dfmax1 = TMath::Max(dfmax1, TMath::Abs(rsum1 - rsum2));
1388 Double_t dfmax2 = 0;
1391 for(Int_t j = jbeg; j <= jend; ++j) {
1392 for(Int_t i = ibeg; i <= iend; ++i) {
1393 rsum1 += s1 * h1->GetCellContent(i, j);
1394 rsum2 += s2 * h2->GetCellContent(i, j);
1395 dfmax2 = TMath::Max(dfmax2, TMath::Abs(rsum1 - rsum2));
1400 Double_t factnm = 0.;
1402 factnm = TMath::Sqrt(esum2);
1404 factnm = TMath::Sqrt(esum1);
1406 factnm = TMath::Sqrt(esum1 * sum2 / (esum1 + esum2));
1410 Double_t dfmax = 0.5 * (dfmax1 + dfmax2);
1411 Double_t z = dfmax * factnm;
1413 prb = TMath::KolmogorovProb(z);
1418 if(opt.Contains(
"N") && !(afunc1 || afunc2)) {
1421 Double_t d12 = esum1 - esum2;
1422 Double_t chi2 = d12 * d12 / (esum1 + esum2);
1423 prb2 = TMath::Prob(chi2, 1);
1425 if(prb > 0 && prb2 > 0) {
1426 prb = prb * prb2 * (1 - TMath::Log(prb * prb2));
1432 if(opt.Contains(
"D")) {
1433 std::cout <<
" Kolmo Prob h1 = " << h1->GetName() <<
", sum1 = " << sum1 << std::endl;
1434 std::cout <<
" Kolmo Prob h2 = " << h2->GetName() <<
", sum2 = " << sum2 << std::endl;
1435 std::cout <<
" Kolmo Probabil = " << prb <<
", Max dist = " << dfmax << std::endl;
1436 if(opt.Contains(
"N")) {
1437 std::cout <<
" Kolmo Probabil = " << prb1 <<
" for shape alone, " << prb2 <<
" for normalisation alone" << std::endl;
1441 if(TMath::Abs(rsum1 - 1) > 0.002) {
1442 Warning(
"KolmogorovTest",
"Numerical problems with h1=%s\n", h1->GetName());
1444 if(TMath::Abs(rsum2 - 1) > 0.002) {
1445 Warning(
"KolmogorovTest",
"Numerical problems with h2=%s\n", h2->GetName());
1448 if(opt.Contains(
"M")) {
1470 if(list ==
nullptr) {
1473 if(list->IsEmpty()) {
1474 return static_cast<Long64_t
>(GetEntries());
1478 inlist.AddAll(list);
1482 Bool_t initialLimitsFound = kFALSE;
1483 Bool_t allSameLimits = kTRUE;
1484 Bool_t sameLimitsX = kTRUE;
1485 Bool_t sameLimitsY = kTRUE;
1486 Bool_t allHaveLimits = kTRUE;
1487 Bool_t firstHistWithLimits = kTRUE;
1489 TIter next(&inlist);
1492 Bool_t hasLimits = h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax();
1493 allHaveLimits = allHaveLimits && hasLimits;
1500 if(firstHistWithLimits) {
1503 if(!SameLimitsAndNBins(fXaxis, *(h->GetXaxis()))) {
1504 if(h->GetXaxis()->GetXbins()->GetSize() != 0) {
1505 fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXbins()->GetArray());
1507 fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
1510 if(!SameLimitsAndNBins(fYaxis, *(h->GetYaxis()))) {
1511 if(h->GetYaxis()->GetXbins()->GetSize() != 0) {
1512 fYaxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXbins()->GetArray());
1514 fYaxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax());
1518 firstHistWithLimits = kFALSE;
1521 if(!initialLimitsFound) {
1524 initialLimitsFound = kTRUE;
1525 if(h->GetXaxis()->GetXbins()->GetSize() != 0) {
1526 newXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXbins()->GetArray());
1528 newXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
1530 if(h->GetYaxis()->GetXbins()->GetSize() != 0) {
1531 newYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXbins()->GetArray());
1533 newYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax());
1537 if(!SameLimitsAndNBins(newXAxis, *(h->GetXaxis()))) {
1538 sameLimitsX = kFALSE;
1542 if(!RecomputeAxisLimits(newXAxis, *(h->GetXaxis()))) {
1543 Error(
"Merge",
"Cannot merge histograms - limits are inconsistent:\n "
1544 "first: (%d, %f, %f), second: (%d, %f, %f)",
1545 newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(), h->GetXaxis()->GetNbins(),
1546 h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
1552 if(!SameLimitsAndNBins(newYAxis, *(h->GetYaxis()))) {
1553 sameLimitsY = kFALSE;
1557 if(!RecomputeAxisLimits(newYAxis, *(h->GetYaxis()))) {
1558 Error(
"Merge",
"Cannot merge histograms - limits are inconsistent:\n "
1559 "first: (%d, %f, %f), second: (%d, %f, %f)",
1560 newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax(), h->GetYaxis()->GetNbins(),
1561 h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax());
1565 allSameLimits = sameLimitsY && sameLimitsX;
1568 }
while((h =
static_cast<GHSym*
>(next())) !=
nullptr);
1569 if(h ==
nullptr && ((*next) !=
nullptr)) {
1570 Error(
"Merge",
"Attempt to merge object of class: %s to a %s", (*next)->ClassName(), ClassName());
1579 TH2* hclone =
nullptr;
1580 if(!allSameLimits) {
1583 Bool_t mustCleanup = TestBit(kMustCleanup);
1585 ResetBit(kMustCleanup);
1587 hclone =
static_cast<TH2*
>(IsA()->New());
1588 hclone->SetDirectory(
nullptr);
1591 SetBit(kMustCleanup);
1596 inlist.AddFirst(hclone);
1599 if(!allSameLimits && initialLimitsFound) {
1601 fXaxis.SetRange(0, 0);
1602 if(newXAxis.GetXbins()->GetSize() != 0) {
1603 fXaxis.Set(newXAxis.GetNbins(), newXAxis.GetXbins()->GetArray());
1605 fXaxis.Set(newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax());
1609 fYaxis.SetRange(0, 0);
1610 if(newYAxis.GetXbins()->GetSize() != 0) {
1611 fYaxis.Set(newYAxis.GetNbins(), newYAxis.GetXbins()->GetArray());
1613 fYaxis.Set(newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax());
1616 fZaxis.Set(1, 0, 1);
1617 fNcells = (fXaxis.GetNbins() + 2) * (fYaxis.GetNbins() + 2);
1618 SetBinsLength(fNcells);
1619 if(fSumw2.fN != 0) {
1620 fSumw2.Set(fNcells);
1624 if(!allHaveLimits) {
1626 while((h =
static_cast<GHSym*
>(next())) !=
nullptr) {
1627 if(h->GetXaxis()->GetXmin() >= h->GetXaxis()->GetXmax() && (h->fBuffer !=
nullptr)) {
1629 auto nbentries =
static_cast<Int_t
>(h->fBuffer[0]);
1630 for(Int_t i = 0; i < nbentries; i++) {
1631 Fill(h->fBuffer[3 * i + 2], h->fBuffer[3 * i + 3], h->fBuffer[3 * i + 1]);
1637 if(!initialLimitsFound) {
1638 if(hclone !=
nullptr) {
1639 inlist.Remove(hclone);
1642 return static_cast<Long64_t
>(GetEntries());
1648 std::array<Double_t, kNstat> stats;
1649 std::array<Double_t, kNstat> totstats;
1650 for(Int_t i = 0; i < kNstat; ++i) {
1651 totstats[i] = stats[i] = 0;
1654 Double_t nentries = GetEntries();
1658 Bool_t canExtend = CanExtendAllAxes();
1659 SetCanExtend(TH1::kNoAxis);
1661 while((h =
static_cast<GHSym*
>(next())) !=
nullptr) {
1663 Double_t histEntries = h->GetEntries();
1664 if(h->fTsumw == 0 && histEntries == 0) {
1669 if(h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax()) {
1672 for(Int_t i = 0; i < kNstat; ++i) {
1673 totstats[i] += stats[i];
1675 nentries += histEntries;
1677 Int_t nx = h->GetXaxis()->GetNbins();
1678 Int_t ny = h->GetYaxis()->GetNbins();
1680 for(Int_t biny = 0; biny <= ny + 1; ++biny) {
1681 if(!allSameLimits) {
1682 iy = fYaxis.FindBin(h->GetYaxis()->GetBinCenter(biny));
1686 for(Int_t binx = 0; binx <= nx + 1; ++binx) {
1687 cu = h->GetBinContent(binx, biny);
1688 if(!allSameLimits) {
1689 if(cu != 0 && ((!sameLimitsX && (binx == 0 || binx == nx + 1)) ||
1690 (!sameLimitsY && (biny == 0 || biny == ny + 1)))) {
1691 Error(
"Merge",
"Cannot merge histograms - the histograms have"
1692 " different limits and undeflows/overflows are present."
1693 " The initial histogram is now broken!");
1696 ix = fXaxis.FindBin(h->GetXaxis()->GetBinCenter(binx));
1701 Int_t ibin =
GetBin(ix, iy);
1706 AddBinContent(ibin, cu);
1707 if(fSumw2.fN != 0) {
1708 Double_t error1 = h->GetBinError(
GetBin(binx, biny));
1709 fSumw2.fArray[ibin] += error1 * error1;
1715 SetCanExtend(
static_cast<UInt_t
>(canExtend));
1719 SetEntries(nentries);
1720 if(hclone !=
nullptr) {
1721 inlist.Remove(hclone);
1724 return static_cast<Long64_t
>(nentries);
1727TProfile*
GHSym::Profile(
const char* name, Int_t firstbin, Int_t lastbin, Option_t* option)
const
1767 TString opt = option;
1770 Int_t i1 = opt.Index(
"[");
1772 Int_t i2 = opt.Index(
"]");
1773 cut = opt(i1, i2 - i1 + 1);
1776 bool originalRange = opt.Contains(
"o");
1778 Int_t inN = fYaxis.GetNbins();
1779 const char* expectedName =
"_pf";
1781 Int_t firstOutBin = fXaxis.GetFirst();
1782 Int_t lastOutBin = fXaxis.GetLast();
1783 if(firstOutBin == 0 && lastOutBin == 0) {
1785 lastOutBin = fXaxis.GetNbins();
1788 if(lastbin < firstbin && fYaxis.TestBit(TAxis::kAxisRange)) {
1789 firstbin = fYaxis.GetFirst();
1790 lastbin = fYaxis.GetLast();
1794 if(firstbin == 0 && lastbin == 0) {
1796 lastbin = fYaxis.GetNbins();
1805 if(lastbin > inN + 1) {
1810 char* pname =
const_cast<char*
>(name);
1811 if((name !=
nullptr) && strcmp(name, expectedName) == 0) {
1812 auto nch = strlen(GetName()) + 5;
1813 pname =
new char[nch];
1814 snprintf(pname, nch,
"%s%s", GetName(), name);
1816 TProfile* h1 =
nullptr;
1819 TObject* h1obj = gROOT->FindObject(pname);
1820 if((h1obj !=
nullptr) && h1obj->InheritsFrom(TH1::Class())) {
1821 if(h1obj->IsA() != TProfile::Class()) {
1822 Error(
"DoProfile",
"Histogram with name %s must be a TProfile and is a %s", name, h1obj->ClassName());
1825 h1 =
static_cast<TProfile*
>(h1obj);
1830 const TArrayD* xbins = fXaxis.GetXbins();
1831 if(xbins->fN == 0) {
1833 h1->SetBins(fXaxis.GetNbins(), fXaxis.GetXmin(), fXaxis.GetXmax());
1835 h1->SetBins(lastOutBin - firstOutBin + 1, fXaxis.GetBinLowEdge(firstOutBin),
1836 fXaxis.GetBinUpEdge(lastOutBin));
1841 h1->SetBins(fXaxis.GetNbins(), xbins->fArray);
1843 h1->SetBins(lastOutBin - firstOutBin + 1, &xbins->fArray[firstOutBin - 1]);
1849 if(opt.Contains(
"[")) {
1850 const_cast<GHSym*
>(
this)->GetPainter();
1851 if(fPainter !=
nullptr) {
1852 ncuts = fPainter->MakeCuts(
const_cast<char*
>(cut.Data()));
1857 const TArrayD* bins = fXaxis.GetXbins();
1860 h1 =
new TProfile(pname, GetTitle(), fXaxis.GetNbins(), fXaxis.GetXmin(), fXaxis.GetXmax(), opt);
1862 h1 =
new TProfile(pname, GetTitle(), lastOutBin - firstOutBin + 1, fXaxis.GetBinLowEdge(firstOutBin),
1863 fXaxis.GetBinUpEdge(lastOutBin), opt);
1868 h1 =
new TProfile(pname, GetTitle(), fXaxis.GetNbins(), bins->fArray, opt);
1870 h1 =
new TProfile(pname, GetTitle(), lastOutBin - firstOutBin + 1, &bins->fArray[firstOutBin - 1], opt);
1879 h1->GetXaxis()->ImportAttributes(&fXaxis);
1880 h1->SetLineColor(GetLineColor());
1881 h1->SetFillColor(GetFillColor());
1882 h1->SetMarkerColor(GetMarkerColor());
1883 h1->SetMarkerStyle(GetMarkerStyle());
1887 bool useWeights = (GetSumw2N() > 0);
1894 TArrayD& binSumw2 = *(h1->GetBinSumw2());
1899 for(Int_t outbin = 0; outbin <= fXaxis.GetNbins() + 1; ++outbin) {
1900 if(fXaxis.TestBit(TAxis::kAxisRange) && (outbin < firstOutBin || outbin > lastOutBin)) {
1905 Double_t xOut = fXaxis.GetBinCenter(outbin);
1906 Int_t binOut = h1->GetXaxis()->FindBin(xOut);
1911 for(Int_t inbin = firstbin; inbin <= lastbin; ++inbin) {
1912 Int_t binx = outbin;
1916 if(!fPainter->IsInside(binx, biny)) {
1920 Int_t bin =
GetBin(binx, biny);
1921 Double_t cxy = GetBinContent(bin);
1927 tmp = binSumw2.fArray[binOut];
1929 h1->Fill(xOut, fYaxis.GetBinCenter(inbin), cxy);
1931 binSumw2.fArray[binOut] = tmp + fSumw2.fArray[bin];
1943 h1->SetEntries(h1->GetEffectiveEntries());
1945 if(opt.Contains(
"d")) {
1946 TVirtualPad* padsav = gPad;
1947 TVirtualPad* pad = gROOT->GetSelectedPad();
1948 if(pad !=
nullptr) {
1951 opt.Remove(opt.First(
"d"), 1);
1952 if(!gPad || !gPad->FindObject(h1)) {
1957 if(padsav !=
nullptr) {
1968 const char* expectedName =
"_pr";
1970 TString opt = option;
1972 Int_t i1 = opt.Index(
"[");
1974 Int_t i2 = opt.Index(
"]");
1975 cut = opt(i1, i2 - i1 + 1);
1978 bool originalRange = opt.Contains(
"o");
1980 Int_t firstXBin = fXaxis.GetFirst();
1981 Int_t lastXBin = fXaxis.GetLast();
1983 if(firstXBin == 0 && lastXBin == 0) {
1985 lastXBin = fXaxis.GetNbins();
1988 if(lastBin < firstBin && fYaxis.TestBit(TAxis::kAxisRange)) {
1989 firstBin = fYaxis.GetFirst();
1990 lastBin = fYaxis.GetLast();
1994 if(firstBin == 0 && lastBin == 0) {
1996 lastBin = fYaxis.GetNbins();
2003 lastBin = fYaxis.GetLast() + 1;
2005 if(lastBin > fYaxis.GetLast() + 1) {
2006 lastBin = fYaxis.GetLast() + 1;
2010 char* pname =
const_cast<char*
>(name);
2011 if(name !=
nullptr && strcmp(name, expectedName) == 0) {
2012 auto nch = strlen(GetName()) + 4;
2013 pname =
new char[nch];
2014 snprintf(pname, nch,
"%s%s", GetName(), name);
2020 TObject* h1obj = gROOT->FindObject(pname);
2021 if((h1obj !=
nullptr) && h1obj->InheritsFrom(TH1::Class())) {
2022 if(h1obj->IsA() != TH1D::Class()) {
2023 Error(
"DoProjection",
"Histogram with name %s must be a TH1D and is a %s", name, h1obj->ClassName());
2026 h1 =
static_cast<TH1D*
>(h1obj);
2031 const TArrayD* xbins = fXaxis.GetXbins();
2032 if(xbins->fN == 0) {
2034 h1->SetBins(fXaxis.GetNbins(), fXaxis.GetXmin(), fXaxis.GetXmax());
2036 h1->SetBins(lastXBin - firstXBin + 1, fXaxis.GetBinLowEdge(firstXBin), fXaxis.GetBinUpEdge(lastXBin));
2041 h1->SetBins(fXaxis.GetNbins(), xbins->fArray);
2043 h1->SetBins(lastXBin - firstXBin + 1, &(xbins->fArray[firstXBin - 1]));
2048 if(opt.Contains(
"[")) {
2049 const_cast<GHSym*
>(
this)->GetPainter();
2050 if(fPainter !=
nullptr) {
2051 ncuts = fPainter->MakeCuts(
const_cast<char*
>(cut.Data()));
2056 const TArrayD* bins = fXaxis.GetXbins();
2059 h1 =
new TH1D(pname, GetTitle(), fXaxis.GetNbins(), fXaxis.GetXmin(), fXaxis.GetXmax());
2061 h1 =
new TH1D(pname, GetTitle(), lastXBin - firstXBin + 1, fXaxis.GetBinLowEdge(firstXBin),
2062 fXaxis.GetBinUpEdge(lastXBin));
2067 h1 =
new TH1D(pname, GetTitle(), fXaxis.GetNbins(), bins->fArray);
2069 h1 =
new TH1D(pname, GetTitle(), lastXBin - firstXBin + 1, &(bins->fArray[firstXBin - 1]));
2072 if(opt.Contains(
"e") || (GetSumw2N() != 0)) {
2081 h1->GetXaxis()->ImportAttributes(&fXaxis);
2082 THashList* labels =
const_cast<TAxis*
>(&fXaxis)->GetLabels();
2083 if(labels !=
nullptr) {
2085 TObjString* lb =
nullptr;
2087 while((lb =
static_cast<TObjString*
>(iL())) !=
nullptr) {
2088 h1->GetXaxis()->SetBinLabel(i, lb->String().Data());
2093 h1->SetLineColor(GetLineColor());
2094 h1->SetFillColor(GetFillColor());
2095 h1->SetMarkerColor(GetMarkerColor());
2096 h1->SetMarkerStyle(GetMarkerStyle());
2099 Double_t totcont = 0;
2100 Bool_t computeErrors = h1->GetSumw2N() != 0;
2105 for(Int_t xbin = 0; xbin <= fXaxis.GetNbins() + 1; ++xbin) {
2108 if(fXaxis.TestBit(TAxis::kAxisRange) && (xbin < firstXBin || xbin > lastXBin)) {
2112 for(Int_t ybin = firstBin; ybin <= lastBin; ++ybin) {
2114 if(!fPainter->IsInside(xbin, ybin)) {
2126 Int_t binOut = h1->GetXaxis()->FindBin(fXaxis.GetBinCenter(xbin));
2127 h1->SetBinContent(binOut, cont);
2129 h1->SetBinError(binOut, TMath::Sqrt(err2));
2136 bool reuseStats =
false;
2137 if((!fgStatOverflows && firstBin == 1 && lastBin == fYaxis.GetLast()) ||
2138 (fgStatOverflows && firstBin == 0 && lastBin == fYaxis.GetLast() + 1)) {
2142 double eps = 1.E-12;
2143 if(IsA() == GHSymF::Class()) {
2146 if(fTsumw != 0 && TMath::Abs(fTsumw - totcont) < TMath::Abs(fTsumw) * eps) {
2154 bool reuseEntries = reuseStats;
2156 reuseEntries &=
static_cast<int>(firstBin == 0 && lastBin == fYaxis.GetLast() + 1);
2158 std::array<Double_t, kNstat> stats;
2160 h1->PutStats(stats.data());
2165 h1->SetEntries(h1->GetEffectiveEntries());
2168 h1->SetEntries(fEntries);
2174 Double_t entries = TMath::Floor(totcont + 0.5);
2175 if(h1->GetSumw2N() != 0) {
2176 entries = h1->GetEffectiveEntries();
2178 h1->SetEntries(entries);
2181 if(opt.Contains(
"d")) {
2182 TVirtualPad* padsav = gPad;
2183 TVirtualPad* pad = gROOT->GetSelectedPad();
2184 if(pad !=
nullptr) {
2187 opt.Remove(opt.First(
"d"), 1);
2189 if(opt.Contains(
"e")) {
2190 opt.Remove(opt.First(
"e"), 1);
2192 if(!gPad || !gPad->FindObject(h1)) {
2197 if(padsav !=
nullptr) {
2239 Int_t nbins = fXaxis.GetNbins();
2240 Double_t min = fXaxis.GetXmin();
2241 Double_t max = fXaxis.GetXmax();
2242 if((ngroup <= 0) || (ngroup > nbins)) {
2243 Error(
"Rebin",
"Illegal value of ngroup=%d", ngroup);
2247 Int_t newbins = nbins / ngroup;
2250 Double_t entries = fEntries;
2251 auto* oldBins =
new Double_t[(nbins + 2) * (nbins + 3) / 2];
2252 for(Int_t xbin = 0; xbin < nbins + 2; xbin++) {
2253 for(Int_t ybin = 0; ybin <= xbin; ybin++) {
2254 Int_t bin =
GetBin(xbin, ybin);
2255 oldBins[bin] = GetBinContent(bin);
2258 Double_t* oldErrors =
nullptr;
2259 if(fSumw2.fN != 0) {
2260 oldErrors =
new Double_t[(nbins + 2) * (nbins + 3) / 2];
2261 for(Int_t xbin = 0; xbin < nbins + 2; xbin++) {
2262 for(Int_t ybin = 0; ybin <= xbin; ybin++) {
2263 Int_t bin =
GetBin(xbin, ybin);
2264 oldErrors[bin] = GetBinError(bin);
2271 if((newname !=
nullptr) && (strlen(newname) != 0u)) {
2272 hnew =
static_cast<GHSym*
>(Clone());
2273 hnew->SetName(newname);
2277 std::array<Double_t, kNstat> stats;
2279 bool resetStat =
false;
2282 if(newbins * ngroup != nbins) {
2283 max = fXaxis.GetBinUpEdge(newbins * ngroup);
2287 Int_t nXdivisions = fXaxis.GetNdivisions();
2288 Color_t xAxisColor = fXaxis.GetAxisColor();
2289 Color_t xLabelColor = fXaxis.GetLabelColor();
2290 Style_t xLabelFont = fXaxis.GetLabelFont();
2291 Float_t xLabelOffset = fXaxis.GetLabelOffset();
2292 Float_t xLabelSize = fXaxis.GetLabelSize();
2293 Float_t xTickLength = fXaxis.GetTickLength();
2294 Float_t xTitleOffset = fXaxis.GetTitleOffset();
2295 Float_t xTitleSize = fXaxis.GetTitleSize();
2296 Color_t xTitleColor = fXaxis.GetTitleColor();
2297 Style_t xTitleFont = fXaxis.GetTitleFont();
2299 Int_t nYdivisions = fYaxis.GetNdivisions();
2300 Color_t yAxisColor = fYaxis.GetAxisColor();
2301 Color_t yLabelColor = fYaxis.GetLabelColor();
2302 Style_t yLabelFont = fYaxis.GetLabelFont();
2303 Float_t yLabelOffset = fYaxis.GetLabelOffset();
2304 Float_t yLabelSize = fYaxis.GetLabelSize();
2305 Float_t yTickLength = fYaxis.GetTickLength();
2306 Float_t yTitleOffset = fYaxis.GetTitleOffset();
2307 Float_t yTitleSize = fYaxis.GetTitleSize();
2308 Color_t yTitleColor = fYaxis.GetTitleColor();
2309 Style_t yTitleFont = fYaxis.GetTitleFont();
2313 if(fXaxis.GetXbins()->GetSize() > 0 || fYaxis.GetXbins()->GetSize() > 0) {
2315 auto* bins =
new Double_t[newbins + 1];
2316 for(Int_t i = 0; i <= newbins; ++i) {
2317 bins[i] = fXaxis.GetBinLowEdge(1 + i * ngroup);
2319 hnew->SetBins(newbins, bins, newbins, bins);
2322 hnew->SetBins(newbins, min, max, newbins, min, max);
2327 for(Int_t xbin = 1; xbin <= newbins; ++xbin) {
2329 for(Int_t ybin = 1; ybin <= xbin; ++ybin) {
2330 Double_t binContent = 0.;
2331 Double_t binError = 0.;
2332 for(Int_t i = 0; i < ngroup; ++i) {
2333 if(oldxbin + i > nbins) {
2336 for(Int_t j = 0; j < ngroup; ++j) {
2337 if(oldybin + j > nbins) {
2342 if(oldybin + j <= oldxbin + i) {
2343 bin = oldxbin + i + (oldybin + j) * (2 * fXaxis.GetNbins() - (oldybin + j) + 3) / 2;
2345 bin = oldybin + j + (oldxbin + i) * (2 * fXaxis.GetNbins() - (oldxbin + i) + 3) / 2;
2347 binContent += oldBins[bin];
2348 if(oldErrors !=
nullptr) {
2349 binError += oldErrors[bin] * oldErrors[bin];
2353 hnew->SetBinContent(xbin, ybin, binContent);
2354 if(oldErrors !=
nullptr) {
2355 hnew->SetBinError(xbin, ybin, TMath::Sqrt(binError));
2365 hnew->SetBinContent(0, 0, oldBins[0]);
2366 if(oldErrors !=
nullptr) {
2367 hnew->SetBinError(0, 0, oldErrors[0]);
2371 Double_t binContent = 0.;
2372 Double_t binError = 0.;
2373 for(Int_t xbin = oldxbin; xbin <= nbins + 1; ++xbin) {
2374 for(Int_t ybin = oldybin; ybin <= xbin; ++ybin) {
2375 Int_t bin = xbin + ybin * (2 * nbins - ybin + 3) / 2;
2376 binContent += oldBins[bin];
2377 if(oldErrors !=
nullptr) {
2378 binError += oldErrors[bin] * oldErrors[bin];
2382 hnew->SetBinContent(newbins + 1, newbins + 1, binContent);
2383 if(oldErrors !=
nullptr) {
2384 hnew->SetBinError(newbins + 1, newbins + 1, TMath::Sqrt(binError));
2390 for(Int_t ybin = oldybin; ybin <= nbins + 1; ++ybin) {
2391 Int_t bin = ybin * (2 * nbins - ybin + 3) / 2;
2392 binContent += oldBins[bin];
2393 if(oldErrors !=
nullptr) {
2394 binError += oldErrors[bin] * oldErrors[bin];
2397 hnew->SetBinContent(0, newbins + 1, binContent);
2398 if(oldErrors !=
nullptr) {
2399 hnew->SetBinError(0, newbins + 1, TMath::Sqrt(binError));
2405 for(Int_t xbin = oldxbin; xbin <= nbins + 1; ++xbin) {
2407 binContent += oldBins[bin];
2408 if(oldErrors !=
nullptr) {
2409 binError += oldErrors[bin] * oldErrors[bin];
2412 hnew->SetBinContent(newbins + 1, 0, binContent);
2413 if(oldErrors !=
nullptr) {
2414 hnew->SetBinError(newbins + 1, 0, TMath::Sqrt(binError));
2419 for(Int_t xbin = 1; xbin <= newbins; ++xbin) {
2420 Double_t binContent0 = 0.;
2421 Double_t binContent2 = 0.;
2422 Double_t binError0 = 0.;
2423 Double_t binError2 = 0.;
2424 for(Int_t i = 0; i < ngroup; ++i) {
2425 if(oldxbin2 + i > nbins) {
2429 Int_t ufbin = oldxbin2 + i;
2430 binContent0 += oldBins[ufbin];
2431 if(oldErrors !=
nullptr) {
2432 binError0 += oldErrors[ufbin] * oldErrors[ufbin];
2434 for(Int_t ybin = oldybin; ybin <= nbins + 1; ++ybin) {
2436 Int_t ofbin = ufbin + ybin * (nbins + 2);
2437 binContent2 += oldBins[ofbin];
2438 if(oldErrors !=
nullptr) {
2439 binError2 += oldErrors[ofbin] * oldErrors[ofbin];
2443 hnew->SetBinContent(xbin, 0, binContent0);
2444 hnew->SetBinContent(xbin, newbins + 1, binContent2);
2445 if(oldErrors !=
nullptr) {
2446 hnew->SetBinError(xbin, 0, TMath::Sqrt(binError0));
2447 hnew->SetBinError(xbin, newbins + 1, TMath::Sqrt(binError2));
2454 for(Int_t ybin = 1; ybin <= newbins; ++ybin) {
2455 Double_t binContent0 = 0.;
2456 Double_t binContent2 = 0.;
2457 Double_t binError0 = 0.;
2458 Double_t binError2 = 0.;
2459 for(Int_t i = 0; i < ngroup; ++i) {
2460 if(oldybin2 + i > nbins) {
2464 Int_t ufbin = (oldybin2 + i) * (nbins + 2);
2465 binContent0 += oldBins[ufbin];
2466 if(oldErrors !=
nullptr) {
2467 binError0 += oldErrors[ufbin] * oldErrors[ufbin];
2469 for(Int_t xbin = oldxbin; xbin <= nbins + 1; ++xbin) {
2470 Int_t ofbin = ufbin + xbin;
2471 binContent2 += oldBins[ofbin];
2472 if(oldErrors !=
nullptr) {
2473 binError2 += oldErrors[ofbin] * oldErrors[ofbin];
2477 hnew->SetBinContent(0, ybin, binContent0);
2478 hnew->SetBinContent(newbins + 1, ybin, binContent2);
2479 if(oldErrors !=
nullptr) {
2480 hnew->SetBinError(0, ybin, TMath::Sqrt(binError0));
2481 hnew->SetBinError(newbins + 1, ybin, TMath::Sqrt(binError2));
2488 fXaxis.SetNdivisions(nXdivisions);
2489 fXaxis.SetAxisColor(xAxisColor);
2490 fXaxis.SetLabelColor(xLabelColor);
2491 fXaxis.SetLabelFont(xLabelFont);
2492 fXaxis.SetLabelOffset(xLabelOffset);
2493 fXaxis.SetLabelSize(xLabelSize);
2494 fXaxis.SetTickLength(xTickLength);
2495 fXaxis.SetTitleOffset(xTitleOffset);
2496 fXaxis.SetTitleSize(xTitleSize);
2497 fXaxis.SetTitleColor(xTitleColor);
2498 fXaxis.SetTitleFont(xTitleFont);
2500 fYaxis.SetNdivisions(nYdivisions);
2501 fYaxis.SetAxisColor(yAxisColor);
2502 fYaxis.SetLabelColor(yLabelColor);
2503 fYaxis.SetLabelFont(yLabelFont);
2504 fYaxis.SetLabelOffset(yLabelOffset);
2505 fYaxis.SetLabelSize(yLabelSize);
2506 fYaxis.SetTickLength(yTickLength);
2507 fYaxis.SetTitleOffset(yTitleOffset);
2508 fYaxis.SetTitleSize(yTitleSize);
2509 fYaxis.SetTitleColor(yTitleColor);
2510 fYaxis.SetTitleFont(yTitleFont);
2513 hnew->SetEntries(entries);
2631 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}}};
2632 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}}};
2633 std::array<std::array<Double_t, 3>, 3> k3a = {{{0, 1, 0}, {1, 2, 1}, {0, 1, 0}}};
2636 Warning(
"Smooth",
"Currently only ntimes=1 is supported");
2638 TString opt = option;
2640 Int_t ksize_x = k5a.size();
2641 Int_t ksize_y = k5a.size();
2642 Double_t* kernel = k5a.data()->data();
2643 if(opt.Contains(
"k5b")) {
2644 kernel = k5b.data()->data();
2646 if(opt.Contains(
"k3a")) {
2647 kernel = k3a.data()->data();
2648 ksize_x = k3a.size();
2649 ksize_y = k3a.size();
2653 Int_t ifirst = fXaxis.GetFirst();
2654 Int_t ilast = fXaxis.GetLast();
2655 Int_t jfirst = fYaxis.GetFirst();
2656 Int_t jlast = fYaxis.GetLast();
2659 Double_t nentries = fEntries;
2660 Int_t nx = GetNbinsX();
2661 Int_t ny = GetNbinsY();
2662 Int_t bufSize = (nx + 2) * (ny + 2);
2663 auto* buf =
new Double_t[bufSize];
2664 Double_t* ebuf =
nullptr;
2665 if(fSumw2.fN != 0) {
2666 ebuf =
new Double_t[bufSize];
2670 for(Int_t i = ifirst; i <= ilast; ++i) {
2671 for(Int_t j = jfirst; j <= jlast; ++j) {
2672 Int_t bin =
GetBin(i, j);
2673 buf[bin] = GetBinContent(bin);
2674 if(ebuf !=
nullptr) {
2675 ebuf[bin] = GetBinError(bin);
2681 Int_t x_push = (ksize_x - 1) / 2;
2682 Int_t y_push = (ksize_y - 1) / 2;
2685 for(Int_t i = ifirst; i <= ilast; ++i) {
2686 for(Int_t j = jfirst; j <= jlast; ++j) {
2687 Double_t content = 0.0;
2688 Double_t error = 0.0;
2689 Double_t norm = 0.0;
2691 for(Int_t n = 0; n < ksize_x; ++n) {
2692 for(Int_t m = 0; m < ksize_y; ++m) {
2693 Int_t xb = i + (n - x_push);
2694 Int_t yb = j + (m - y_push);
2695 if((xb >= 1) && (xb <= nx) && (yb >= 1) && (yb <= ny)) {
2696 Int_t bin =
GetBin(xb, yb);
2697 Double_t k = kernel[n * ksize_y + m];
2700 content += k * buf[bin];
2701 if(ebuf !=
nullptr) {
2702 error += k * k * ebuf[bin] * ebuf[bin];
2710 SetBinContent(i, j, content / norm);
2711 if(ebuf !=
nullptr) {
2712 error /= (norm * norm);
2713 SetBinError(i, j, sqrt(error));
2718 fEntries = nentries;