15 #define PRINTRANGE(a, b, bn) \
16 Printf(" base: %f %f %d, %s: %f %f %d", a->GetXmin(), a->GetXmax(), a->GetNbins(), bn, b->GetXmin(), b->GetXmax(), \
20 Bool_t hasLimits =
h->GetXaxis()->GetXmin() <
h->GetXaxis()->GetXmax();
21 if (
h->GetDimension() > 1) hasLimits &=
h->GetYaxis()->GetXmin() <
h->GetYaxis()->GetXmax();
22 if (
h->GetDimension() > 2) hasLimits &=
h->GetZaxis()->GetXmin() <
h->GetZaxis()->GetXmax();
55 if (ret)
return kTRUE;
59 Error(
"TH1Merger",
"Unknown type of Merge for histogram %s",
fH0->
GetName());
81 Error(
"AutoP2BuildAxes",
"undefined histogram: %p",
h);
87 Error(
"AutoP2BuildAxes",
"not in autobin-power-of-2 mode!");
95 Bool_t canextend = (
h->GetBinContent(0) > 0 ||
h->GetBinContent(a1->GetNbins() + 1) > 0) ?
kFALSE :
kTRUE;
99 a0->
Set(a1->GetNbins(), a1->GetXmin(), a1->GetXmax());
107 Double_t bwmin = (a1->GetXmax() - a1->GetXmin()) / a1->GetNbins();
115 Error(
"AutoP2BuildAxes",
"minimal bin width negative or null: %f", bwmin);
120 Double_t re = std::modf(bwmax / bwmin, &rt);
123 Error(
"AutoP2BuildAxes",
"bin widths not in integer ratio: %f", re);
130 if (a0->
GetXmin() < a1->GetXmin()) {
131 if (a0->
GetXmax() < a1->GetXmin()) {
134 Error(
"AutoP2BuildAxes",
"ranges are disconnected and under/overflows: cannot merge");
137 xmax = a1->GetXmax();
141 if (a0->
GetXmax() >= a1->GetXmax()) {
142 xmax = a1->GetXmax();
143 xmin = a1->GetXmin();
147 xmin = a1->GetXmin();
152 if (a1->GetXmax() < a0->
GetXmin()) {
155 Error(
"AutoP2BuildAxes",
"ranges are disconnected and under/overflows: cannot merge");
159 xmin = a1->GetXmin();
162 if (a1->GetXmax() >= a0->
GetXmax()) {
167 xmax = a1->GetXmax();
175 re = std::modf(range / bwmax, &rt);
178 Error(
"MergeCompatibleHistograms",
"range smaller than bin width: %f %f %f", range, bwmax, rt);
254 if (
h->GetDimension() != dimension) {
255 Error(
"Merge",
"Cannot merge histogram - dimensions are different\n "
256 "%s has dim=%d and %s has dim=%d",
fH0->
GetName(),dimension,
h->GetName(),
h->GetDimension());
262 haveWeights |=
h->GetSumw2N() != 0;
267 allHaveLimits = allHaveLimits && hasLimits;
268 allSameLimits &= allHaveLimits;
271 Error(
"Merge",
"Cannot merge histogram - some are in autobin-power-of-2 mode, but not %s!",
h->GetName());
275 Error(
"Merge",
"Cannot merge histogram - %s is in autobin-power-of-2 mode, but not the previous ones",
298 if (!initialLimitsFound) {
299 initialLimitsFound =
kTRUE;
300 if (
h->GetXaxis()->GetXbins()->GetSize() != 0)
301 fNewXAxis.
Set(
h->GetXaxis()->GetNbins(),
h->GetXaxis()->GetXbins()->GetArray());
303 fNewXAxis.
Set(
h->GetXaxis()->GetNbins(),
h->GetXaxis()->GetXmin(),
h->GetXaxis()->GetXmax());
305 if (
h->GetYaxis()->GetXbins()->GetSize() != 0)
306 fNewYAxis.
Set(
h->GetYaxis()->GetNbins(),
h->GetYaxis()->GetXbins()->GetArray());
308 fNewYAxis.
Set(
h->GetYaxis()->GetNbins(),
h->GetYaxis()->GetXmin(),
h->GetYaxis()->GetXmax());
311 if (
h->GetZaxis()->GetXbins()->GetSize() != 0)
312 fNewZAxis.
Set(
h->GetZaxis()->GetNbins(),
h->GetZaxis()->GetXbins()->GetArray());
314 fNewZAxis.
Set(
h->GetZaxis()->GetNbins(),
h->GetZaxis()->GetXmin(),
h->GetZaxis()->GetXmax());
326 Error(
"Merge",
"Cannot merge histograms - limits are inconsistent:\n "
327 "first: %s (%d, %f, %f), second: %s (%d, %f, %f)",
fH0->
GetName(),
329 h->GetName(),
h->GetXaxis()->GetNbins(),
h->GetXaxis()->GetXmin(),
330 h->GetXaxis()->GetXmax());
341 Error(
"Merge",
"Cannot merge histograms - limits are inconsistent:\n "
342 "first: %s (%d, %f, %f), second: %s (%d, %f, %f)",
fH0->
GetName(),
344 h->GetName(),
h->GetYaxis()->GetNbins(),
h->GetYaxis()->GetXmin(),
345 h->GetYaxis()->GetXmax());
352 Error(
"Merge",
"Cannot merge histograms - limits are inconsistent:\n "
353 "first: %s (%d, %f, %f), second: %s (%d, %f, %f)",
fH0->
GetName(),
355 h->GetName(),
h->GetZaxis()->GetNbins(),
h->GetZaxis()->GetXmin(),
356 h->GetZaxis()->GetXmax());
360 allSameLimits = sameLimitsX && sameLimitsY && sameLimitsZ;
365 Bool_t histoIsEmpty =
h->IsEmpty();
370 if (allHaveLabels && !histoIsEmpty) {
371 THashList* hlabelsX =
h->GetXaxis()->GetLabels();
372 THashList* hlabelsY = (dimension > 1) ?
h->GetYaxis()->GetLabels() :
nullptr;
373 THashList* hlabelsZ = (dimension > 2) ?
h->GetZaxis()->GetLabels() :
nullptr;
374 Bool_t haveOneLabelX = hlabelsX !=
nullptr;
375 Bool_t haveOneLabelY = hlabelsY !=
nullptr;
376 Bool_t haveOneLabelZ = hlabelsZ !=
nullptr;
377 Bool_t haveOneLabel = haveOneLabelX || haveOneLabelY || haveOneLabelZ;
379 if (foundLabelHist && allHaveLabels && !haveOneLabel) {
380 Warning(
"Merge",
"Not all histograms have labels. I will ignore labels,"
381 " falling back to bin numbering mode.");
384 allHaveLabels &= (haveOneLabel);
387 foundLabelHist =
kTRUE;
396 allHaveLabels &= consistentLabels;
397 if (!consistentLabels)
398 Warning(
"TH1Merger::ExamineHistogram",
"Histogram %s has inconsistent labels: %d is not consistent with %d",
399 h->GetName(), (
int)
type, (
int) labelAxisType );
400 if (
gDebug && consistentLabels)
401 Info(
"TH1Merger::ExamineHistogram",
"Histogram %s has consistent labels",
h->GetName() );
412 if (allHaveLabels && !labelAxisCanBeExtended) {
417 Info(
"TH1Merger::ExamineHistogram",
"Histogram %s to be merged is empty and we are merging with %s that has labels. Force the axis to be extended",
fH0->
GetName(),
h->GetName());
422 Info(
"TH1Merger::ExamineHistogram",
"Histogram %s to be merged has labels but corresponding axis cannot be extended - using bin numeric mode to merge. Call TH1::SetCanExtend(TH1::kAllAxes) if want to merge using label mode",
fH0->
GetName());
430 if (allHaveLabels ) {
432 Int_t non_zero_bins = 0;
434 if (hlabelsX && dimension == 1 && !
h->GetXaxis()->CanExtend()) {
435 Int_t nbins =
h->GetXaxis()->GetNbins();
437 for (
Int_t i = 1; i <= nbins; i++) {
438 if (
h->RetrieveBinContent(i) != 0 || (
h->fSumw2.fN &&
h->GetBinError(i) != 0) ) {
442 if (non_zero_bins > hlabelsX->
GetEntries() ) {
443 Warning(
"TH1Merger::ExamineHistograms",
"Histogram %s contains non-empty bins without labels - falling back to bin numbering mode",
h->GetName() );
450 if (dimension > 1 ) {
451 if (hlabelsX && !
h->GetXaxis()->CanExtend() && hlabelsX->
GetEntries() <
h->GetXaxis()->GetNbins()-1 ) {
452 Warning(
"TH1Merger::ExamineHistograms",
"Histogram %s has the X axis containing more than one bin without labels - falling back to bin numbering mode",
h->GetName() );
455 if (hlabelsY && !
h->GetYaxis()->CanExtend() && hlabelsY->
GetEntries() <
h->GetYaxis()->GetNbins()-1 ) {
456 Warning(
"TH1Merger::ExamineHistograms",
"Histogram %s has the Y axis containing more than one bin without labels - falling back to bin numbering mode",
h->GetName() );
459 if (hlabelsZ && !
h->GetZaxis()->CanExtend() && hlabelsZ->
GetEntries() <
h->GetZaxis()->GetNbins()-1 ) {
460 Warning(
"TH1Merger::ExamineHistograms",
"Histogram %s has the Z axis containing more than one bin without labels - falling back to bin numbering mode",
h->GetName() );
468 Info(
"TH1Merger::ExamineHistogram",
"Examine histogram %s - labels %d - same limits %d - axis found %d",
h->GetName(),allHaveLabels,allSameLimits,initialLimitsFound );
470 }
while ( (
h =
dynamic_cast<TH1*
> ( next() ) ) != NULL );
472 if (!
h && (*next) ) {
473 Error(
"Merge",
"Attempt to merge object of class: %s to a %s",
492 if (!initialLimitsFound) {
574 if (newLimitsX)
Info(
"DefineNewAxis",
"A new X axis has been defined Nbins=%d , [%f,%f]",
fH0->
fXaxis.
GetNbins(),
576 if (newLimitsY)
Info(
"DefineNewAxis",
"A new Y axis has been defined Nbins=%d , [%f,%f]",
fH0->
fYaxis.
GetNbins(),
578 if (newLimitsZ)
Info(
"DefineNewAxis",
"A new Z axis has been defined Nbins=%d , [%f,%f]",
fH0->
fZaxis.
GetNbins(),
590 if (!hsrc || !hsrc->
fBuffer || !hdes ) {
591 void *p1 = hsrc ? hsrc->
fBuffer : 0;
594 Warning(
"TH1Merger::CopyMerge",
"invalid inputs: %p, %p, %p, -> do nothing", hsrc, hdes, p1);
601 for (
Int_t i = 0; i < nbentries; i++)
605 auto h2 =
dynamic_cast<TH2 *
>(hdes);
607 for (
Int_t i = 0; i < nbentries; i++)
611 auto h3 =
dynamic_cast<TH3 *
>(hdes);
613 for (
Int_t i = 0; i < nbentries; i++)
622 TH1 *href = 0, *hist = 0;
627 while ((hist = (
TH1 *)nextref()) && !href) {
644 while ((hist = (
TH1 *)next())) {
647 Info(
"AutoP2BufferMerge",
"merging buffer of %s into %s", hist->GetName(), href->
GetName());
667 totstats[i] = stats[i] = 0;
677 while ((hist = (
TH1 *)next())) {
685 Info(
"TH1Merger::AutoP2Merge",
"all histograms look empty!");
691 Error(
"TH1Merger::AutoP2Merge",
"cannot create axes from %s", hist->
GetName());
695 while ((
h = (
TH1 *)next())) {
697 Error(
"TH1Merger::AutoP2Merge",
"cannot merge histogram %s: not merge compatible",
h->GetName());
718 while ((hist = (
TH1 *)next())) {
723 Info(
"TH1Merger::AutoP2Merge",
"merging histogram %s into %s (entries: %f)", hist->
GetName(),
fH0->
GetName(),
733 totstats[i] += stats[i];
764 while (
TH1* hist = (
TH1*)next()) {
769 Info(
"TH1Merger::BufferMerge",
"Merging histogram %s into %s",hist->GetName(),
fH0->
GetName() );
791 totstats[i] = stats[i] = 0;
797 while (
TH1* hist=(
TH1*)next()) {
802 Info(
"TH1Merger::SameAxesMerge",
"Merging histogram %s into %s",hist->GetName(),
fH0->
GetName() );
805 if (hist->IsEmpty())
continue;
808 hist->GetStats(stats);
810 totstats[i] += stats[i];
815 for (
Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
840 while (
TH1* hist=(
TH1*)next()) {
843 Info(
"TH1Merger::DifferentAxesMerge",
"Merging histogram %s into %s",hist->GetName(),
fH0->
GetName() );
846 if (hist->IsEmpty())
continue;
849 hist->GetStats(stats);
851 totstats[i] += stats[i];
855 for (
Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
860 Int_t binx,biny,binz;
861 hist->GetBinXYZ(ibin, binx, biny, binz);
864 if (binx <= 0 || binx >= hist->GetNbinsX() + 1) {
866 Error(
"TH1Merger::DifferentAxesMerge",
"Cannot merge histograms - the histograms %s can extend the X axis or have"
867 " different limits and underflows/overflows are present in the histogram %s.",
fH0->
GetName(),hist->GetName());
871 if (biny <= 0 || biny >= hist->GetNbinsY() + 1) {
873 Error(
"TH1Merger::DifferentAxesMerge",
"Cannot merge histograms - the histograms %s can extend the Y axis or have"
874 " different limits and underflows/overflows are present in the histogram %s.",
fH0->
GetName(),hist->GetName());
878 if (binz <= 0 || binz >= hist->GetNbinsZ() + 1) {
880 Error(
"TH1Merger::DifferentAxesMerge",
"Cannot merge histograms - the histograms %s can extend the Z axis or have"
881 " different limits and underflows/overflows are present in the histogram %s.",
fH0->
GetName(),hist->GetName());
900 Fatal(
"TH1Merger::LabelMerge",
"Fatal error merging histogram %s - bin number is %d and array size is %d",
920 if (!labels)
return kFALSE;
922 for (
const auto * obj: *labels) {
923 auto objList = labels->GetListForObject(obj);
925 if (objList->GetSize() > 1 ) {
927 std::unordered_set<std::string>
s;
928 for (
const auto * o: *objList) {
929 auto ret =
s.insert(std::string(o->GetName() ));
930 if (!ret.second)
return kTRUE;
955 Warning(
"TH1Merger::CheckForDuplicateLabels",
"Histogram %s has duplicate labels in the x axis. "
956 "Bin contents will be merged in a single bin",hist->
GetName());
960 Warning(
"TH1Merger::CheckForDuplicateLabels",
"Histogram %s has duplicate labels in the y axis. "
961 "Bin contents will be merged in a single bin",hist->
GetName());
965 Warning(
"TH1Merger::CheckForDuplicateLabels",
"Histogram %s has duplicate labels in the z axis. "
966 "Bin contents will be merged in a single bin",hist->
GetName());
986 while (
TH1* hist=(
TH1*)next()) {
989 Info(
"TH1Merger::LabelMerge",
"Merging histogram %s into %s",hist->GetName(),
fH0->
GetName() );
992 if (hist->IsEmpty())
continue;
995 hist->GetStats(stats);
997 totstats[i] += stats[i];
1000 auto labelsX = hist->GetXaxis()->GetLabels();
1001 auto labelsY = hist->GetYaxis()->GetLabels();
1002 auto labelsZ = hist->GetZaxis()->GetLabels();
1003 R__ASSERT(!( labelsX ==
nullptr && labelsY ==
nullptr && labelsZ ==
nullptr));
1011 Info(
"TH1Merger::LabelMerge",
"Merging X axis in label mode");
1013 Info(
"TH1Merger::LabelMerge",
"Merging X axis in numeric mode");
1015 Info(
"TH1Merger::LabelMerge",
"Merging Y axis in label mode");
1016 else if (hist->GetDimension() > 1)
1017 Info(
"TH1Merger::LabelMerge",
"Merging Y axis in numeric mode");
1019 Info(
"TH1Merger::LabelMerge",
"Merging Z axis in label mode" );
1020 else if (hist->GetDimension() > 2)
1021 Info(
"TH1Merger::LabelMerge",
"Merging Z axis in numeric mode");
1030 std::cout <<
"Bins of original histograms\n";
1031 for (
int ix = 1; ix <=
fH0->
GetXaxis()->GetNbins(); ++ix) {
1032 for (
int iy = 1; iy <=
fH0->
GetYaxis()->GetNbins(); ++iy) {
1033 for (
int iz = 1; iz <=
fH0->
GetZaxis()->GetNbins(); ++iz) {
1035 std::cout <<
"bin" << ix <<
"," << iy <<
"," << iz
1041 for (
Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
1046 Int_t binx,biny,binz;
1047 hist->GetBinXYZ(ibin, binx, biny, binz);
1050 const char * labelX = 0;
1051 const char * labelY = 0;
1052 const char * labelZ = 0;
1053 labelX=hist->GetXaxis()->GetBinLabel(binx);
1054 if (
fH0->
fDimension > 1) labelY = hist->GetYaxis()->GetBinLabel(biny);
1055 if (
fH0->
fDimension > 2) labelZ = hist->GetYaxis()->GetBinLabel(binz);
1065 if (binx == 0 &&
TString(labelX) ==
"" ) ix = 0;
1068 if (biny == 0 &&
TString(labelY) ==
"" ) iy = 0;
1072 if (binz == 0 &&
TString(labelZ) ==
"" ) iz = 0;
1106 Info(
"TH1Merge::LabelMerge",
"Merge bin [%d,%d,%d] with label [%s,%s,%s] into bin [%d,%d,%d]",
1107 binx,biny,binz,labelX,labelY,labelZ,ix,iy,iz);
1112 Fatal(
"TH1Merger::LabelMerge",
"Fatal error merging histogram %s - bin number is %d and array size is %d",
1131 return cu == 0 && e1sq == 0;
1156 template<
class TProfileType>
1159 TProfileType *p =
static_cast<TProfileType *
>(
fH0);
1160 p->fArray[pbin] +=
h->fArray[hbin];
1161 p->fSumw2.fArray[pbin] +=
h->fSumw2.fArray[hbin];
1162 p->fBinEntries.fArray[pbin] +=
h->fBinEntries.fArray[hbin];
1163 if (p->fBinSumw2.fN) {
1164 if (
h->fBinSumw2.fN)
1165 p->fBinSumw2.fArray[pbin] +=
h->fBinSumw2.fArray[hbin];
1167 p->fBinSumw2.fArray[pbin] +=
h->fArray[hbin];
1170 Info(
"TH1Merge::MergeProfileBin",
"Merge bin %d of profile %s with content %f in bin %d - result is %f", hbin,
1171 h->GetName(),
h->fArray[hbin], pbin, p->fArray[pbin]);