15 Bool_t IsBinOverflow(
const TH1&
hist, Int_t
bin) {
17 Int_t binx, biny, binz;
19 hist.GetBinXYZ(
bin, binx, biny, binz);
20 Int_t
dim =
hist.GetDimension();
22 if (
dim == 1)
return binx >=
hist.GetNbinsX() + 1;
23 else if (
dim == 2)
return (binx >=
hist.GetNbinsX() + 1) ||
24 (biny >=
hist.GetNbinsY() + 1);
26 return (binx >=
hist.GetNbinsX() + 1) ||
27 (biny >=
hist.GetNbinsY() + 1) ||
28 (binz >=
hist.GetNbinsZ() + 1);
32 Bool_t IsBinUnderflow(
const TH1&
hist, Int_t
bin) {
34 Int_t binx, biny, binz;
36 hist.GetBinXYZ(
bin, binx, biny, binz);
37 Int_t
dim =
hist.GetDimension();
39 if (
dim == 1)
return(binx <= 0);
40 else if (
dim == 2)
return(binx <= 0 || biny <= 0);
41 else if (
dim == 3)
return(binx <= 0 || biny <= 0 || binz <= 0);
50 Int_t
dim =
hist.GetDimension();
53 return(
hist.GetNbinsX() + 2);
56 return (
hist.GetNbinsX() + 2) * (
hist.GetNbinsY() + 2);
59 return (
hist.GetNbinsX() + 2) * (
hist.GetNbinsY() + 2) * (
hist.GetNbinsZ() + 2);
78 for (
int ix = 1; ix <=
a.GetNbinsX(); ix++) {
79 for (
int iy = 1; iy <=
a.GetNbinsY(); iy++) {
82 float efficiencyA =
a.GetBinContent(ix, iy) / 100.;
83 float efficiencyB =
b.GetBinContent(ix, iy) / 100.;
84 float efficiencyErrA =
a.GetBinError(ix, iy) / 100.;
85 float efficiencyErrB =
b.GetBinError(ix, iy) / 100.;
88 if (efficiencyErrA != 0 && efficiencyA != 0 &&
89 denA == 0) denA = efficiencyA * (1 - efficiencyA) / efficiencyErrA / efficiencyErrA;
90 if (efficiencyErrB != 0 && efficiencyB != 0 &&
91 denB == 0) denB = efficiencyB * (1 - efficiencyB) / efficiencyErrB / efficiencyErrB;
95 float denTot = denA + denB;
96 const double nEntries =
a.GetEntries() +
b.GetEntries();
98 for (
int ix = 1; ix <=
a.GetNbinsX(); ix++) {
99 for (
int iy = 1; iy <=
a.GetNbinsY(); iy++) {
102 float efficiencyA =
a.GetBinContent(ix, iy) / 100.;
103 float efficiencyB =
b.GetBinContent(ix, iy) / 100.;
108 float numA = denA * efficiencyA;
109 float numB = denB * efficiencyB;
112 float numTot = numA + numB;
113 float efficiencyTot = 0.;
114 float efficiencyErrTot = 0.;
116 if (denTot != 0.) efficiencyTot = numTot / denTot * 100.;
117 if (denTot != 0.) efficiencyErrTot = sqrt(numTot * denTot * (denTot - numTot)) / denTot / denTot * 100.;
119 a.SetBinContent(ix, iy, efficiencyTot);
120 a.SetBinError(ix, iy, efficiencyErrTot);
139 constexpr
double OneSigOneSided = 0.159;
142 if (
a.GetDimension() !=
b.GetDimension()) {
143 std::cerr <<
"merge_perBinEffPerCent \"" <<
a.GetName() <<
144 "\": attempt to merge histograms of different dimensionality" << std::endl;
151 std::cerr <<
"merge_perBinEffPerCent \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
156 a.SetCanExtend(TH1::kNoAxis);
158 const double nEntries =
a.GetEntries() +
b.GetEntries();
161 if (IsBinUnderflow(
a,
bin) || IsBinOverflow(
a,
bin))
continue;
162 float efficiencyA =
a.GetBinContent(
bin) / 100.;
163 float efficiencyB =
b.GetBinContent(
bin) / 100.;
164 float efficiencyErrA =
a.GetBinError(
bin) / 100.;
165 float efficiencyErrB =
b.GetBinError(
bin) / 100.;
167 float efficiencyTot = 0.;
168 float efficiencyErrTot = 0.;
169 if (efficiencyErrA == 0.) {
170 efficiencyTot = efficiencyB;
171 efficiencyErrTot = efficiencyErrB;
173 if (efficiencyErrB == 0.) {
174 efficiencyTot = efficiencyA;
175 efficiencyErrTot = efficiencyErrA;
178 if (efficiencyA == 0.) {
181 if (efficiencyA > 0.99) {
184 denomA = efficiencyA * (1. - efficiencyA) / (efficiencyErrA * efficiencyErrA);
189 if (efficiencyB == 0.) {
192 if (efficiencyB > 0.99) {
195 denomB = efficiencyB * (1. - efficiencyB) / (efficiencyErrB * efficiencyErrB);
199 float denom = denomA + denomB;
200 efficiencyTot = (denomA * efficiencyA + denomB * efficiencyB) /
denom;
201 efficiencyErrTot = std::sqrt(efficiencyTot * (1. - efficiencyTot) /
denom);
202 if (efficiencyTot == 0.) efficiencyErrTot = 1.0 -
std::pow(OneSigOneSided, 1.0 /
denom);
203 if (efficiencyTot > 0.99) efficiencyErrTot = 1.0 -
std::pow(OneSigOneSided, 1.0 /
denom);
206 a.SetBinContent(
bin, efficiencyTot * 100.);
207 a.SetBinError(
bin, efficiencyErrTot * 100.);
221 if (
a.GetDimension() !=
b.GetDimension()) {
222 std::cerr <<
"merge_effAsPerCentAlt \"" <<
a.GetName() <<
223 "\": attempt to merge histograms of different dimensionality\n";
230 std::cerr <<
"merge_effAsPerCentAlt \"" <<
a.GetName() <<
231 "\": attempt to merge histograms of different bin counts\n";
236 a.SetCanExtend(TH1::kNoAxis);
246 if (IsBinUnderflow(
a,
bin) || IsBinOverflow(
a,
bin))
continue;
249 float efficiencyA =
a.GetBinContent(
bin) / 100.;
250 float efficiencyB =
b.GetBinContent(
bin) / 100.;
251 float efficiencyErrA =
a.GetBinError(
bin) / 100.;
252 float efficiencyErrB =
b.GetBinError(
bin) / 100.;
255 if (efficiencyErrA != 0 && efficiencyA != 0 &&
256 denA == 0) denA = efficiencyA * (1 - efficiencyA) / efficiencyErrA / efficiencyErrA;
257 if (efficiencyErrB != 0 && efficiencyB != 0 && denB == 0) denB = efficiencyB * (1 - efficiencyB) / efficiencyErrB / efficiencyErrB;
260 float denTot = denA + denB;
261 const double nEntries =
a.GetEntries() +
b.GetEntries();
264 if (IsBinUnderflow(
a,
bin) || IsBinOverflow(
a,
bin))
continue;
267 float efficiencyA =
a.GetBinContent(
bin) / 100.;
268 float efficiencyB =
b.GetBinContent(
bin) / 100.;
273 float numA = denA * efficiencyA;
274 float numB = denB * efficiencyB;
277 float numTot = numA + numB;
278 float efficiencyTot = 0.;
279 float efficiencyErrTot = 0.;
281 if (denTot != 0.) efficiencyTot = numTot / denTot * 100.;
282 if (denTot != 0.) efficiencyErrTot = sqrt(numTot * denTot * (denTot - numTot)) / denTot / denTot * 100.;
284 a.SetBinContent(
bin, efficiencyTot);
285 a.SetBinError(
bin, efficiencyErrTot);
293 if (
a.GetDimension() !=
b.GetDimension()) {
294 std::cerr <<
"merge_weightedAverage \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
301 std::cerr <<
"merge_weightedAverage \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
306 a.SetCanExtend(TH1::kNoAxis);
313 double y1 =
a.GetBinContent(
bin);
314 double y2 =
b.GetBinContent(
bin);
315 double e1 =
a.GetBinError(
bin);
316 double e2 =
b.GetBinError(
bin);
317 double w1 = 1., w2 = 1.;
318 if (
e1 > 0) w1 = 1. / (
e1 *
e1);
319 if (
e2 > 0) w2 = 1. / (
e2 *
e2);
322 if (
e1 > 0 &&
e2 > 0) {
323 a.SetBinContent(
bin, (w1 *
y1 + w2 *
y2) / (w1 + w2));
324 a.SetBinError(
bin, 1. / sqrt(w1 + w2));
338 a.SetBinContent(
bin, (
y1 +
y2) / 2.);
339 a.SetBinError(
bin, 0.);
365 for (
int binx = 0; binx <=
a.GetNbinsX() + 1; binx++) {
366 for (
int biny = 0; biny <=
a.GetNbinsY() + 1; biny++) {
367 int bin =
a.GetBin(binx, biny);
369 double y1 =
a.GetBinContent(
bin);
370 double y2 =
b.GetBinContent(
bin);
371 double e1 =
a.GetBinError(
bin);
372 double e2 =
b.GetBinError(
bin);
373 double w1 = 1., w2 = 1.;
374 if (
e1 > 0) w1 = 1. / (
e1 *
e1);
375 if (
e2 > 0) w2 = 1. / (
e2 *
e2);
378 if (
e1 > 0 &&
e2 > 0) {
379 a.SetBinContent(
bin, (w1 *
y1 + w2 *
y2) / (w1 + w2));
380 a.SetBinError(
bin, 1. / sqrt(w1 + w2));
394 a.SetBinContent(
bin, (
y1 +
y2) / 2.);
395 a.SetBinError(
bin, 0.);
413 double entries_a =
a.GetEntries();
414 double entries_b =
b.GetEntries();
416 double weight_a = 0.0;
417 double weight_b = 0.0;
419 if (
a.GetDimension() !=
b.GetDimension()) {
420 std::cerr <<
"merge_weightedEff \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
425 bool sumw2 = (
a.GetSumw2N() != 0) && (
b.GetSumw2N() != 0);
430 std::cerr <<
"merge_weightedEff \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
434 if (entries_b == 0) {
438 if (entries_a == 0) {
445 a.SetCanExtend(TH1::kNoAxis);
447 if (entries_a + entries_b > 0) {
448 weight_a = entries_a / (entries_a + entries_b);
449 weight_b = entries_b / (entries_a + entries_b);
452 double binContent_a =
a.GetBinContent(
bin);
453 double binContent_b =
b.GetBinContent(
bin);
457 double binError_a =
a.GetBinError(
bin);
458 double binError_b =
b.GetBinError(
bin);
461 float weightedEff = binContent_a * weight_a + binContent_b * weight_b;
462 a.SetBinContent(
bin, weightedEff);
465 float weightedError = sqrt(
pow(binError_a * weight_a, 2) +
pow(binError_b * weight_b, 2));
466 a.SetBinError(
bin, weightedError);
473 if (!sumw2) (
a.GetSumw2())->
Set(0);
475 a.SetEntries(entries_a + entries_b);
489 TList*
list =
new TList;
501 int nbinsx =
a.GetNbinsX();
502 int nbinsy =
a.GetNbinsY();
504 if (
b.GetNbinsX() != nbinsx ||
b.GetNbinsY() != nbinsy)
return;
507 for (
int biny = 1; biny <= nbinsy; biny++) {
508 for (
int binx = 1; binx <= nbinsx; binx++) {
509 double bVal =
b.GetBinContent(binx, biny);
510 if (bVal == 0)
break;
511 for (
int binxa = 1; binxa <= nbinsx; binxa++) {
512 double aVal =
a.GetBinContent(binxa, biny);
514 a.SetBinContent(binxa, biny, bVal);
517 }
else if (bVal < aVal) {
518 for (
int bx = nbinsx;
bx > binxa;
bx--) {
519 double v1 =
a.GetBinContent(
bx - 1, biny);
520 if (v1 == 0)
continue;
521 double v2 =
a.GetBinContent(
bx, biny);
523 a.SetBinContent(
bx, biny, v1);
525 a.SetBinContent(binxa, biny, bVal);
527 }
else if (aVal == bVal)
break;
541 if (
a.GetDimension() !=
b.GetDimension()) {
542 std::cerr <<
"merge_RMS \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
549 std::cerr <<
"merge_RMS \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
554 a.SetCanExtend(TH1::kNoAxis);
560 double rms1 =
a.GetBinContent(
bin);
561 double rms2 =
b.GetBinContent(
bin);
562 double e1 =
a.GetBinError(
bin);
563 double e2 =
b.GetBinError(
bin);
572 n2 =
pow(rms2 /
e2, 2) / 2;
575 double ntot =
n1 + n2;
577 a.SetBinContent(
bin, sqrt((rms1 * rms1) + (rms2 * rms2)));
580 double rmstot = sqrt(((
pow(
n1 * rms1, 2) / (
n1 - 1)) + (
pow(n2 * rms2, 2) / (n2 - 1))) * (ntot - 1) /
pow(ntot, 2));
581 a.SetBinContent(
bin, rmstot);
582 a.SetBinError(
bin, rmstot / sqrt(2 * ntot));
602 if (
a.GetDimension() !=
b.GetDimension()) {
603 std::cerr <<
"merge_RMSpercentDeviation \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
610 std::cerr <<
"merge_RMSpercentDeviation \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
618 double y1 =
a.GetBinContent(
bin) + 100;
619 double y2 =
b.GetBinContent(
bin) + 100;
620 double e1 =
a.GetBinError(
bin);
621 double e2 =
b.GetBinError(
bin);
633 double ntot =
n1 + n2;
635 a.SetBinContent(
bin, sqrt((
y1 *
y1) + (
y2 *
y2)) - 100);
638 double ytot = sqrt(((
pow(
n1 *
y1, 2) / (
n1 - 1)) + (
pow(n2 *
y2, 2) / (n2 - 1))) * (ntot - 1) /
pow(ntot, 2));
639 a.SetBinContent(
bin, ytot - 100);
640 a.SetBinError(
bin, ytot / sqrt(2 * ntot));
657 if (
a.GetDimension() !=
b.GetDimension()) {
658 std::cerr <<
"merge_lowerLB \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
665 std::cerr <<
"merge_lowerLB \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
670 a.SetCanExtend(TH1::kNoAxis);
672 if (strcmp(
a.GetTitle(),
b.GetTitle()) > 0) {
675 a.SetTitle(
b.GetTitle());
704 if (
a.GetDimension() !=
b.GetDimension()) {
705 std::cerr <<
"merge_identical \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
712 std::cerr <<
"merge_identical \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
720 std::cerr <<
"merge_identical \"" <<
a.GetName() <<
"\" and \"" <<
b.GetName() <<
"\" have different content\n";