17 Bool_t IsBinOverflow(
const TH1&
hist, Int_t
bin)
20 Int_t binx, biny, binz;
21 hist.GetBinXYZ(
bin, binx, biny, binz);
22 Int_t
dim =
hist.GetDimension();
25 return binx >=
hist.GetNbinsX() + 1;
27 return (binx >=
hist.GetNbinsX() + 1) ||
28 (biny >=
hist.GetNbinsY() + 1);
30 return (binx >=
hist.GetNbinsX() + 1) ||
31 (biny >=
hist.GetNbinsY() + 1) ||
32 (binz >=
hist.GetNbinsZ() + 1);
37 Bool_t IsBinUnderflow(
const TH1&
hist, Int_t
bin)
41 Int_t binx, biny, binz;
42 hist.GetBinXYZ(
bin, binx, biny, binz);
43 Int_t
dim =
hist.GetDimension();
48 return (binx <= 0 || biny <= 0);
50 return (binx <= 0 || biny <= 0 || binz <= 0);
62 Int_t
dim =
hist.GetDimension();
64 return (
hist.GetNbinsX()+2);
67 return (
hist.GetNbinsX()+2)*(
hist.GetNbinsY()+2);
70 return (
hist.GetNbinsX()+2)*(
hist.GetNbinsY()+2)*(
hist.GetNbinsZ()+2);
89 for (
int ix = 1; ix <=
a.GetNbinsX(); ix++){
90 for (
int iy = 1; iy <=
a.GetNbinsY(); iy++){
93 float efficiencyA =
a.GetBinContent(ix,iy)/100.;
94 float efficiencyB =
b.GetBinContent(ix,iy)/100.;
95 float efficiencyErrA =
a.GetBinError(ix,iy)/100.;
96 float efficiencyErrB =
b.GetBinError(ix,iy)/100.;
99 if (efficiencyErrA != 0 && efficiencyA != 0 && denA == 0) denA = efficiencyA*(1-efficiencyA)/efficiencyErrA/efficiencyErrA;
100 if (efficiencyErrB != 0 && efficiencyB != 0 && denB == 0) denB = efficiencyB*(1-efficiencyB)/efficiencyErrB/efficiencyErrB;
104 float denTot = denA + denB;
105 const double nEntries =
a.GetEntries() +
b.GetEntries();
107 for (
int ix = 1; ix <=
a.GetNbinsX(); ix++){
108 for (
int iy = 1; iy <=
a.GetNbinsY(); iy++){
111 float efficiencyA =
a.GetBinContent(ix,iy)/100.;
112 float efficiencyB =
b.GetBinContent(ix,iy)/100.;
117 float numA = denA * efficiencyA;
118 float numB = denB * efficiencyB;
121 float numTot = numA + numB;
122 float efficiencyTot = 0.;
123 float efficiencyErrTot = 0.;
125 if (denTot != 0.) efficiencyTot = numTot/denTot*100.;
126 if (denTot != 0.) efficiencyErrTot = std::sqrt(numTot*denTot*(denTot-numTot))/denTot/denTot*100.;
128 a.SetBinContent(ix,iy,efficiencyTot);
129 a.SetBinError(ix,iy,efficiencyErrTot);
149 constexpr
double OneSigOneSided = 0.159;
151 if (
a.GetDimension() !=
b.GetDimension()) {
152 std::cerr<<
"merge_perBinEffPerCent \""<<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality" << std::endl;
159 std::cerr<<
"merge_perBinEffPerCent \""<<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
164 a.SetCanExtend(TH1::kNoAxis);
166 const double nEntries =
a.GetEntries() +
b.GetEntries();
168 for(
int bin = 0;
bin < ncells;
bin++ ) {
169 if (IsBinUnderflow(
a,
bin) || IsBinOverflow(
a,
bin))
continue;
170 float efficiencyA =
a.GetBinContent(
bin)/100.;
171 float efficiencyB =
b.GetBinContent(
bin)/100.;
172 float efficiencyErrA =
a.GetBinError(
bin)/100.;
173 float efficiencyErrB =
b.GetBinError(
bin)/100.;
175 float efficiencyTot = 0.;
176 float efficiencyErrTot = 0.;
177 if ( efficiencyErrA == 0. ) {
178 efficiencyTot = efficiencyB;
179 efficiencyErrTot = efficiencyErrB;
182 if ( efficiencyErrB == 0. ) {
183 efficiencyTot = efficiencyA;
184 efficiencyErrTot = efficiencyErrA;
188 if ( efficiencyA == 0. ){
192 if ( efficiencyA > 0.99) {
196 denomA = efficiencyA*(1.-efficiencyA)/(efficiencyErrA*efficiencyErrA);
201 if ( efficiencyB == 0. ){
205 if ( efficiencyB > 0.99) {
209 denomB = efficiencyB*(1.-efficiencyB)/(efficiencyErrB*efficiencyErrB);
213 float denom = denomA + denomB;
214 efficiencyTot = (denomA*efficiencyA + denomB*efficiencyB)/
denom;
215 efficiencyErrTot = std::sqrt(efficiencyTot*(1.-efficiencyTot)/
denom);
216 if ( efficiencyTot == 0. ) efficiencyErrTot = 1.0-
std::pow(OneSigOneSided,1.0/
denom);
217 if ( efficiencyTot > 0.99 ) efficiencyErrTot = 1.0-
std::pow(OneSigOneSided,1.0/
denom);
220 a.SetBinContent(
bin,efficiencyTot*100.);
221 a.SetBinError(
bin,efficiencyErrTot*100.);
236 if (
a.GetDimension() !=
b.GetDimension()) {
237 std::cerr<<
"merge_effAsPerCentAlt \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
244 std::cerr<<
"merge_effAsPerCentAlt \""<<
a.GetName() <<
"\": attempt to merge histograms of different bin counts\n";
249 a.SetCanExtend(TH1::kNoAxis);
258 for(
int bin = 0;
bin < ncells;
bin++ ) {
259 if (IsBinUnderflow(
a,
bin) || IsBinOverflow(
a,
bin))
continue;
262 float efficiencyA =
a.GetBinContent(
bin)/100.;
263 float efficiencyB =
b.GetBinContent(
bin)/100.;
264 float efficiencyErrA =
a.GetBinError(
bin)/100.;
265 float efficiencyErrB =
b.GetBinError(
bin)/100.;
268 if (efficiencyErrA != 0 && efficiencyA != 0 && denA == 0) denA = efficiencyA*(1-efficiencyA)/efficiencyErrA/efficiencyErrA;
269 if (efficiencyErrB != 0 && efficiencyB != 0 && denB == 0) denB = efficiencyB*(1-efficiencyB)/efficiencyErrB/efficiencyErrB;
272 float denTot = denA + denB;
273 const double nEntries =
a.GetEntries() +
b.GetEntries();
275 for(
int bin = 0;
bin < ncells;
bin++ ) {
276 if (IsBinUnderflow(
a,
bin) || IsBinOverflow(
a,
bin))
continue;
279 float efficiencyA =
a.GetBinContent(
bin)/100.;
280 float efficiencyB =
b.GetBinContent(
bin)/100.;
285 float numA = denA * efficiencyA;
286 float numB = denB * efficiencyB;
289 float numTot = numA + numB;
290 float efficiencyTot = 0.;
291 float efficiencyErrTot = 0.;
293 if (denTot != 0.) efficiencyTot = numTot/denTot*100.;
294 if (denTot != 0.) efficiencyErrTot = std::sqrt(numTot*denTot*(denTot-numTot))/denTot/denTot*100.;
296 a.SetBinContent(
bin,efficiencyTot);
297 a.SetBinError(
bin,efficiencyErrTot);
308 if (
a.GetDimension() !=
b.GetDimension()) {
309 std::cerr<<
"merge_weightedAverage \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
316 std::cerr<<
"merge_weightedAverage \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
321 a.SetCanExtend(TH1::kNoAxis);
327 for(
int bin = 0;
bin < ncells;
bin++ ) {
328 double y1 =
a.GetBinContent(
bin);
329 double y2 =
b.GetBinContent(
bin);
330 double e1 =
a.GetBinError(
bin);
331 double e2 =
b.GetBinError(
bin);
332 double w1 = 1., w2 = 1.;
333 if (
e1 > 0) w1 = 1./(
e1*
e1);
334 if (
e2 > 0) w2 = 1./(
e2*
e2);
337 if (
e1 > 0 &&
e2 > 0){
338 a.SetBinContent(
bin, (w1*
y1 + w2*
y2)/(w1 + w2));
339 a.SetBinError(
bin, 1./std::sqrt(w1 + w2));
354 a.SetBinError(
bin, 0.);
383 for(
int binx = 0; binx <=
a.GetNbinsX()+1; binx++ ) {
384 for(
int biny = 0; biny <=
a.GetNbinsY()+1; biny++ ) {
386 int bin =
a.GetBin(binx,biny);
388 double y1 =
a.GetBinContent(
bin);
389 double y2 =
b.GetBinContent(
bin);
390 double e1 =
a.GetBinError(
bin);
391 double e2 =
b.GetBinError(
bin);
392 double w1 = 1., w2 = 1.;
393 if (
e1 > 0) w1 = 1./(
e1*
e1);
394 if (
e2 > 0) w2 = 1./(
e2*
e2);
397 if (
e1 > 0 &&
e2 > 0){
398 a.SetBinContent(
bin, (w1*
y1 + w2*
y2)/(w1 + w2));
399 a.SetBinError(
bin, 1./std::sqrt(w1 + w2));
414 a.SetBinError(
bin, 0.);
434 double entries_a =
a.GetEntries();
435 double entries_b =
b.GetEntries();
437 double weight_a = 0.0;
438 double weight_b = 0.0;
440 if (
a.GetDimension() !=
b.GetDimension()) {
441 std::cerr<<
"merge_weightedEff \""<<
a.GetName()<<
"\": attempt to merge histograms of different dimensionality\n";
446 bool sumw2 = (
a.GetSumw2N() != 0) && (
b.GetSumw2N() != 0);
451 std::cerr<<
"merge_weightedEff \""<<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
455 if (entries_b == 0) {
459 if (entries_a == 0) {
466 a.SetCanExtend(TH1::kNoAxis);
468 if (entries_a + entries_b > 0)
470 weight_a = entries_a / (entries_a + entries_b);
471 weight_b = entries_b / (entries_a + entries_b);
473 for(
int bin = 0;
bin < ncells;
bin++ ) {
474 double binContent_a =
a.GetBinContent(
bin);
475 double binContent_b =
b.GetBinContent(
bin);
479 double binError_a =
a.GetBinError(
bin);
480 double binError_b =
b.GetBinError(
bin);
483 float weightedEff = binContent_a * weight_a + binContent_b * weight_b;
484 a.SetBinContent(
bin, weightedEff);
487 float weightedError = std::sqrt(
std::pow(binError_a * weight_a,2) +
std::pow(binError_b * weight_b,2) );
488 a.SetBinError(
bin, weightedError);
495 if (!sumw2) (
a.GetSumw2())->
Set(0);
497 a.SetEntries(entries_a + entries_b);
515 if(
a.InheritsFrom(
"TProfile2D") &&
b.InheritsFrom(
"TProfile2D") &&
a.GetDimension()==
b.GetDimension()) {
516 auto binsFunc = [](TH1&
h,
int ax) {
517 if(
ax==0)
return h.GetNbinsX();
518 if(
ax==1)
return h.GetNbinsY();
519 if(
ax==2)
return h.GetNbinsZ();
522 for(
int i=0;
i<
a.GetDimension();
i++) {
523 int n1 = binsFunc(
a,
i);
524 int n2 = binsFunc(
b,
i);
525 if ((
n1 == 0) or (n2 == 0)) {
526 throw std::runtime_error(
"MonitoringFile::merge_Rebinned; nbins is zero.");
528 if((n2 %
n1 == 0) && std::bitset<
sizeof(
int)>(n2/
n1).
count()==1) {
529 while(binsFunc(
a,
i) != binsFunc(
b,
i)) {
530 a.LabelsInflate((
i==0) ?
"x" : ( (
i==1) ?
"y" :
"z"));
532 }
else if((
n1 % n2 == 0) && std::bitset<
sizeof(
int)>(
n1/n2).
count()==1) {
533 while(binsFunc(
a,
i) != binsFunc(
b,
i)) {
534 b.LabelsInflate((
i==0) ?
"x" : ( (
i==1) ?
"y" :
"z"));
541 TList *
list =
new TList;
555 int nbinsx =
a.GetNbinsX();
556 int nbinsy =
a.GetNbinsY();
557 if (
b.GetNbinsX() != nbinsx ||
b.GetNbinsY() != nbinsy)
return;
559 for(
int biny = 1; biny <= nbinsy; biny++ ) {
560 for(
int binx = 1; binx <= nbinsx; binx++ ) {
561 double bVal =
b.GetBinContent(binx, biny);
562 if (bVal == 0)
break;
563 for(
int binxa = 1; binxa <= nbinsx; binxa++ ) {
564 double aVal =
a.GetBinContent(binxa, biny);
566 a.SetBinContent(binxa, biny, bVal);
569 }
else if (bVal < aVal) {
570 for(
int bx = nbinsx;
bx > binxa;
bx-- ) {
571 double v1 =
a.GetBinContent(
bx-1, biny);
572 if (v1 == 0)
continue;
573 double v2 =
a.GetBinContent(
bx, biny);
575 a.SetBinContent(
bx, biny, v1);
577 a.SetBinContent(binxa, biny, bVal);
579 }
else if (aVal == bVal)
break;
594 if (
a.GetDimension() !=
b.GetDimension()) {
595 std::cerr<<
"merge_RMS \""<<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
602 std::cerr<<
"merge_RMS \""<<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
607 a.SetCanExtend(TH1::kNoAxis);
612 for(
int bin = 0;
bin < ncells;
bin++ ) {
613 double rms1 =
a.GetBinContent(
bin);
614 double rms2 =
b.GetBinContent(
bin);
615 double e1 =
a.GetBinError(
bin);
616 double e2 =
b.GetBinError(
bin);
628 double ntot =
n1 + n2;
630 a.SetBinContent(
bin, std::sqrt( (rms1*rms1) + (rms2*rms2) ) );
634 double rmstot = std::sqrt( ( (
std::pow(
n1 * rms1,2) / (
n1 - 1)) + (
std::pow(n2 * rms2, 2) / (n2 - 1)) ) * (ntot - 1) /
std::pow(ntot,2) );
635 a.SetBinContent(
bin, rmstot );
636 a.SetBinError(
bin, rmstot / std::sqrt( 2 * ntot ) );
657 if (
a.GetDimension() !=
b.GetDimension()) {
658 std::cerr<<
"merge_RMSpercentDeviation \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
665 std::cerr<<
"merge_RMSpercentDeviation \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
672 for(
int bin = 0;
bin < ncells;
bin++ ) {
673 double y1 =
a.GetBinContent(
bin) + 100;
674 double y2 =
b.GetBinContent(
bin) + 100;
675 double e1 =
a.GetBinError(
bin);
676 double e2 =
b.GetBinError(
bin);
688 double ntot =
n1 + n2;
690 a.SetBinContent(
bin, std::sqrt( (
y1*
y1) + (
y2*
y2) ) - 100 );
695 a.SetBinContent(
bin, ytot - 100);
696 a.SetBinError(
bin, ytot / std::sqrt( 2 * ntot ) );
714 if (
a.GetDimension() !=
b.GetDimension()) {
715 std::cerr<<
"merge_lowerLB \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
722 std::cerr<<
"merge_lowerLB \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
727 a.SetCanExtend(TH1::kNoAxis);
729 if (strcmp(
a.GetTitle(),
b.GetTitle())>0){
732 a.SetTitle(
b.GetTitle());
763 if (
a.GetDimension() !=
b.GetDimension()) {
764 std::cerr<<
"merge_identical \"" <<
a.GetName() <<
"\": attempt to merge histograms of different dimensionality\n";
771 std::cerr<<
"merge_identical \"" <<
a.GetName() <<
"\": attempt to merge histograms of different sizes\n";
779 std::cerr<<
"merge_identical \"" <<
a.GetName() <<
"\" and \"" <<
b.GetName() <<
"\" have different content\n";