104 TRatioPlot::TRatioPlot()
111 TRatioPlot::~TRatioPlot()
114 gROOT->GetListOfCleanups()->Remove(
this);
116 if (fRatioGraph != 0)
delete fRatioGraph;
117 if (fConfidenceInterval1 != 0)
delete fConfidenceInterval1;
118 if (fConfidenceInterval2 != 0)
delete fConfidenceInterval2;
120 for (
unsigned int i=0;i<fGridlines.size();++i) {
121 delete (fGridlines[i]);
124 if (fSharedXAxis != 0)
delete fSharedXAxis;
125 if (fUpperGXaxis != 0)
delete fUpperGXaxis;
126 if (fLowerGXaxis != 0)
delete fLowerGXaxis;
127 if (fUpperGYaxis != 0)
delete fUpperGYaxis;
128 if (fLowerGYaxis != 0)
delete fLowerGYaxis;
129 if (fUpperGXaxisMirror != 0)
delete fUpperGXaxisMirror;
130 if (fLowerGXaxisMirror != 0)
delete fLowerGXaxisMirror;
131 if (fUpperGYaxisMirror != 0)
delete fUpperGYaxisMirror;
132 if (fLowerGYaxisMirror != 0)
delete fLowerGYaxisMirror;
134 if (fUpYaxis != 0)
delete fUpYaxis;
135 if (fLowYaxis != 0)
delete fLowYaxis;
142 void TRatioPlot::Init(TH1* h1, TH1* h2,Option_t *option)
150 TString optionString = TString(option);
152 if (optionString.Contains(
"divsym")) {
153 optionString.ReplaceAll(
"divsym",
"");
154 fMode = TRatioPlot::CalculationMode::kDivideHist;
155 }
else if (optionString.Contains(
"diffsig")) {
156 optionString.ReplaceAll(
"diffsig",
"");
157 fMode = TRatioPlot::CalculationMode::kDifferenceSign;
160 if (optionString.Contains(
"errasym")) {
161 fErrorMode = TRatioPlot::ErrorMode::kErrorAsymmetric;
162 optionString.ReplaceAll(
"errasym",
"");
165 if (optionString.Contains(
"errfunc")) {
166 fErrorMode = TRatioPlot::ErrorMode::kErrorFunc;
167 optionString.ReplaceAll(
"errfunc",
"");
169 }
else if (optionString.Contains(
"diff")) {
170 optionString.ReplaceAll(
"diff",
"");
171 fMode = TRatioPlot::CalculationMode::kDifference;
173 fMode = TRatioPlot::CalculationMode::kDivideGraph;
176 fOption = optionString;
181 fGraphDrawOpt =
"AP";
185 if (!BuildLowerPlot())
return;
188 fSharedXAxis = (TAxis*)(fH1->GetXaxis()->Clone());
189 fUpYaxis = (TAxis*)(fH1->GetYaxis()->Clone());
190 fLowYaxis = (TAxis*)(fRatioGraph->GetYaxis()->Clone());
200 TRatioPlot::TRatioPlot(TH1* h1, TH1* h2, Option_t *option)
203 gROOT->GetListOfCleanups()->Add(
this);
206 Warning(
"TRatioPlot",
"Need two histograms.");
210 Bool_t h1IsTH1=h1->IsA()->InheritsFrom(TH1::Class());
211 Bool_t h2IsTH1=h2->IsA()->InheritsFrom(TH1::Class());
213 if (!h1IsTH1 && !h2IsTH1) {
214 Warning(
"TRatioPlot",
"Need two histograms deriving from TH2 or TH3.");
220 Init(h1, h2, option);
232 TRatioPlot::TRatioPlot(THStack* st, TH1* h2, Option_t *option)
235 Warning(
"TRatioPlot",
"Need a histogram and a stack");
239 TList *stackHists = st->GetHists();
241 if (stackHists->GetSize() == 0) {
242 Warning(
"TRatioPlot",
"Stack does not have histograms");
246 TH1* tmpHist = (TH1*)stackHists->At(0)->Clone();
249 for (
int i=0;i<stackHists->GetSize();++i) {
250 tmpHist->Add((TH1*)stackHists->At(i));
255 Init(tmpHist, h2, option);
266 TRatioPlot::TRatioPlot(TH1* h1, Option_t *option, TFitResult *fitres)
270 gROOT->GetListOfCleanups()->Add(
this);
273 Warning(
"TRatioPlot",
"Need a histogram.");
277 Bool_t h1IsTH1=fH1->IsA()->InheritsFrom(TH1::Class());
280 Warning(
"TRatioPlot",
"Need a histogram deriving from TH2 or TH3.");
284 TList *h1Functions = fH1->GetListOfFunctions();
286 if (h1Functions->GetSize() < 1) {
287 Warning(
"TRatioPlot",
"Histogram given needs to have a (fit) function associated with it");
296 fMode = TRatioPlot::CalculationMode::kFitResidual;
298 TString optionString = TString(option);
301 if (optionString.Contains(
"errasym")) {
302 fErrorMode = TRatioPlot::ErrorMode::kErrorAsymmetric;
303 optionString.ReplaceAll(
"errasym",
"");
306 if (optionString.Contains(
"errfunc")) {
307 fErrorMode = TRatioPlot::ErrorMode::kErrorFunc;
308 optionString.ReplaceAll(
"errfunc",
"");
311 fOption = optionString;
313 if (!BuildLowerPlot())
return;
316 if (fH1->GetSumw2N() > 0) {
321 fGraphDrawOpt =
"LX";
323 fSharedXAxis = (TAxis*)(fH1->GetXaxis()->Clone());
324 fUpYaxis = (TAxis*)(fH1->GetYaxis()->Clone());
325 fLowYaxis = (TAxis*)(fRatioGraph->GetYaxis()->Clone());
336 void TRatioPlot::SetH1DrawOpt(Option_t *opt)
344 void TRatioPlot::SetH2DrawOpt(Option_t *opt)
346 TString optString = TString(opt);
347 optString.ReplaceAll(
"same",
"");
348 optString.ReplaceAll(
"SAME",
"");
350 fH2DrawOpt = optString;
356 void TRatioPlot::SetGraphDrawOpt(Option_t *opt)
364 void TRatioPlot::SetFitDrawOpt(Option_t *opt)
372 void TRatioPlot::SetupPads() {
376 if (fUpperPad != 0) {
381 if (fLowerPad != 0) {
387 Error(
"SetupPads",
"need to create a canvas first");
391 double pm = fInsetWidth;
392 double width = gPad->GetWNDC();
393 double height = gPad->GetHNDC();
394 double f = height/width;
396 fUpperPad =
new TPad(
"upper_pad",
"", pm*f, fSplitFraction, 1.-pm*f, 1.-pm);
397 fLowerPad =
new TPad(
"lower_pad",
"", pm*f, pm, 1.-pm*f, fSplitFraction);
402 fUpperPad->Connect(
"RangeAxisChanged()",
"TRatioPlot",
this,
"RangeAxisChanged()");
403 fLowerPad->Connect(
"RangeAxisChanged()",
"TRatioPlot",
this,
"RangeAxisChanged()");
405 fUpperPad->Connect(
"UnZoomed()",
"TRatioPlot",
this,
"UnZoomed()");
406 fLowerPad->Connect(
"UnZoomed()",
"TRatioPlot",
this,
"UnZoomed()");
408 fUpperPad->Connect(
"Resized()",
"TRatioPlot",
this,
"SubPadResized()");
409 fLowerPad->Connect(
"Resized()",
"TRatioPlot",
this,
"SubPadResized()");
416 fTopPad =
new TPad(
"top_pad",
"", pm*f, pm, 1-pm*f, 1-pm);
418 fTopPad->SetBit(kCannotPick);
425 void TRatioPlot::Browse(TBrowser *b)
427 Draw(b ? b->GetDrawOption() :
"");
436 void TRatioPlot::SetUpTopMargin(Float_t margin)
438 fUpTopMargin = margin;
447 void TRatioPlot::SetUpBottomMargin(Float_t margin)
449 fUpBottomMargin = margin;
458 void TRatioPlot::SetLowTopMargin(Float_t margin)
460 fLowTopMargin = margin;
469 void TRatioPlot::SetLowBottomMargin(Float_t margin)
471 fLowBottomMargin = margin;
479 void TRatioPlot::SetLeftMargin(Float_t margin)
481 fLeftMargin = margin;
490 void TRatioPlot::SetRightMargin(Float_t margin)
492 fRightMargin = margin;
506 void TRatioPlot::SetSeparationMargin(Float_t margin)
508 Float_t sf = fSplitFraction;
509 fUpBottomMargin = margin/2./(1-sf);
510 fLowTopMargin = margin/2./sf;
517 Float_t TRatioPlot::GetSeparationMargin()
const
519 Float_t sf = fSplitFraction;
520 Float_t up = fUpBottomMargin * (1-sf);
521 Float_t down = fLowTopMargin * sf;
542 void TRatioPlot::Draw(Option_t *option)
545 TString drawOpt = option;
547 if (drawOpt.Contains(
"nogrid")) {
548 drawOpt.ReplaceAll(
"nogrid",
"");
549 fShowGridlines = kFALSE;
550 }
else if (drawOpt.Contains(
"grid")) {
551 drawOpt.ReplaceAll(
"grid",
"");
552 fShowGridlines = kTRUE;
555 if (drawOpt.Contains(
"noconfint")) {
556 drawOpt.ReplaceAll(
"noconfint",
"");
557 fShowConfidenceIntervals = kFALSE;
558 }
else if (drawOpt.Contains(
"confint")) {
559 drawOpt.ReplaceAll(
"confint",
"");
560 fShowConfidenceIntervals = kTRUE;
563 if (drawOpt.Contains(
"fhideup")) {
564 fHideLabelMode = TRatioPlot::HideLabelMode::kForceHideUp;
565 }
else if (drawOpt.Contains(
"fhidelow")) {
566 fHideLabelMode = TRatioPlot::HideLabelMode::kForceHideLow;
567 }
else if (drawOpt.Contains(
"hideup")) {
568 fHideLabelMode = TRatioPlot::HideLabelMode::kHideUp;
569 }
else if (drawOpt.Contains(
"hidelow")) {
570 fHideLabelMode = TRatioPlot::HideLabelMode::kHideLow;
571 }
else if (drawOpt.Contains(
"nohide")) {
572 fHideLabelMode = TRatioPlot::HideLabelMode::kNoHide;
574 fHideLabelMode = TRatioPlot::HideLabelMode::kHideLow;
578 Error(
"Draw",
"need to create a canvas first");
582 TVirtualPad *padsav = gPad;
585 fUpperPad->SetLogy(fParentPad->GetLogy());
586 fUpperPad->SetLogx(fParentPad->GetLogx());
587 fLowerPad->SetLogx(fParentPad->GetLogx());
589 fUpperPad->SetGridx(fParentPad->GetGridx());
590 fUpperPad->SetGridy(fParentPad->GetGridy());
591 fLowerPad->SetGridx(fParentPad->GetGridx());
592 fLowerPad->SetGridy(fParentPad->GetGridy());
599 fTopPad->SetFillStyle(0);
604 fConfidenceInterval2->SetFillColor(fCi1Color);
605 fConfidenceInterval1->SetFillColor(fCi2Color);
607 if (fMode == TRatioPlot::CalculationMode::kFitResidual) {
608 TF1 *func =
dynamic_cast<TF1*
>(fH1->GetListOfFunctions()->At(0));
612 Error(
"BuildLowerPlot",
"h1 does not have a fit function");
616 fH1->Draw(
"A"+fH1DrawOpt);
617 func->Draw(fFitDrawOpt+
"same");
621 if (fShowConfidenceIntervals) {
622 fConfidenceInterval2->Draw(
"IA3");
623 fConfidenceInterval1->Draw(
"3");
624 fRatioGraph->Draw(fGraphDrawOpt+
"SAME");
626 fRatioGraph->Draw(
"IA"+fGraphDrawOpt+
"SAME");
630 if (fHistDrawProxy) {
631 if (fHistDrawProxy->InheritsFrom(TH1::Class())) {
632 ((TH1*)fHistDrawProxy)->Draw(
"A"+fH1DrawOpt);
633 }
else if (fHistDrawProxy->InheritsFrom(THStack::Class())) {
634 ((THStack*)fHistDrawProxy)->Draw(
"A"+fH1DrawOpt);
636 Warning(
"Draw",
"Draw proxy not of type TH1 or THStack, not drawing it");
640 fH2->Draw(
"A"+fH2DrawOpt+
"same");
644 TString opt = fGraphDrawOpt;
645 fRatioGraph->Draw(
"IA"+fGraphDrawOpt);
671 TGraph* TRatioPlot::GetLowerRefGraph()
const
673 if (fLowerPad == 0) {
674 Error(
"GetLowerRefGraph",
"Lower pad has not been defined");
678 TList *primlist = fLowerPad->GetListOfPrimitives();
679 if (primlist->GetSize() == 0) {
680 Error(
"GetLowerRefGraph",
"Lower pad does not have primitives");
684 TObjLink *lnk = primlist->FirstLink();
687 TObject *obj = lnk->GetObject();
689 if (obj->InheritsFrom(TGraph::Class())) {
696 Error(
"GetLowerRefGraph",
"Did not find graph in list");
705 TObject* TRatioPlot::GetUpperRefObject()
const
707 TList *primlist = fUpperPad->GetListOfPrimitives();
709 for (Int_t i=0;i<primlist->GetSize();++i) {
710 refobj = primlist->At(i);
711 if (refobj->InheritsFrom(TH1::Class()) || refobj->InheritsFrom(THStack::Class())) {
716 Error(
"GetUpperRefObject",
"No upper ref object of TH1 or THStack type found");
723 TAxis* TRatioPlot::GetUpperRefXaxis()
const
725 TObject *refobj = GetUpperRefObject();
727 if (!refobj)
return 0;
729 if (refobj->InheritsFrom(TH1::Class())) {
730 return ((TH1*)refobj)->GetXaxis();
731 }
else if (refobj->InheritsFrom(THStack::Class())) {
732 return ((THStack*)refobj)->GetXaxis();
741 TAxis* TRatioPlot::GetUpperRefYaxis()
const
743 TObject *refobj = GetUpperRefObject();
745 if (!refobj)
return 0;
747 if (refobj->InheritsFrom(TH1::Class())) {
748 return ((TH1*)refobj)->GetYaxis();
749 }
else if (refobj->InheritsFrom(THStack::Class())) {
750 return ((THStack*)refobj)->GetYaxis();
759 void TRatioPlot::CreateGridline()
762 if (!fShowGridlines) {
766 TVirtualPad *padsav = gPad;
770 unsigned int dest = fGridlinePositions.size();
772 Double_t lowYFirst = fLowerPad->GetUymin();
773 Double_t lowYLast = fLowerPad->GetUymax();
777 for (
unsigned int i=0;i<fGridlinePositions.size();++i) {
778 y = fGridlinePositions.at(i);
780 if (y < lowYFirst || lowYLast < y) {
786 dest = dest - outofrange;
789 for (
unsigned int i=0;i<fGridlines.size();++i) {
790 delete fGridlines.at(i);
793 fGridlines.erase(fGridlines.begin(), fGridlines.end());
795 for (
unsigned int i=0;i<dest;++i) {
796 TLine *newline =
new TLine(0, 0, 0, 0);
797 newline->SetLineStyle(2);
799 fGridlines.push_back(newline);
802 Double_t first = fSharedXAxis->GetBinLowEdge(fSharedXAxis->GetFirst());
803 Double_t last = fSharedXAxis->GetBinUpEdge(fSharedXAxis->GetLast());
806 unsigned int skipped = 0;
807 for (
unsigned int i=0;i<fGridlinePositions.size();++i) {
808 y = fGridlinePositions[i];
810 if (y < lowYFirst || lowYLast < y) {
816 line = fGridlines.at(i-skipped);
830 void TRatioPlot::Paint(Option_t * )
836 if (fIsUpdating) fIsUpdating = kFALSE;
842 void TRatioPlot::SyncAxesRanges()
845 Double_t first = fSharedXAxis->GetBinLowEdge(fSharedXAxis->GetFirst());
846 Double_t last = fSharedXAxis->GetBinUpEdge(fSharedXAxis->GetLast());
850 TAxis *ref = GetLowerRefXaxis();
851 ref->SetLimits(first, last);
852 ref->SetRangeUser(first, last);
854 GetUpperRefXaxis()->SetRangeUser(first, last);
862 Int_t TRatioPlot::BuildLowerPlot()
865 if (fRatioGraph != 0) {
866 fRatioGraph->IsA()->Destructor(fRatioGraph);
870 if (fConfidenceInterval1 == 0) {
871 fConfidenceInterval1 =
new TGraphErrors();
874 if (fConfidenceInterval2 == 0) {
875 fConfidenceInterval2 =
new TGraphErrors();
878 static Double_t divideGridlines[] = {0.7, 1.0, 1.3};
879 static Double_t diffGridlines[] = {0.0};
880 static Double_t signGridlines[] = {1.0, 0.0, -1.0};
884 if (fMode == TRatioPlot::CalculationMode::kDivideGraph) {
887 SetGridlines(divideGridlines, 3);
889 TH1 *tmpH1 = (TH1*)fH1->Clone();
890 TH1 *tmpH2 = (TH1*)fH2->Clone();
895 TGraphAsymmErrors *ratioGraph =
new TGraphAsymmErrors();
896 ratioGraph->Divide(tmpH1, tmpH2, fOption.Data());
897 fRatioGraph = ratioGraph;
902 }
else if (fMode == TRatioPlot::CalculationMode::kDifference) {
903 SetGridlines(diffGridlines, 3);
905 TH1 *tmpHist = (TH1*)fH1->Clone();
909 tmpHist->Add(fH1, fH2, fC1, -1*fC2);
910 fRatioGraph =
new TGraphErrors(tmpHist);
913 }
else if (fMode == TRatioPlot::CalculationMode::kDifferenceSign) {
915 SetGridlines(signGridlines, 3);
917 fRatioGraph =
new TGraphAsymmErrors();
925 for (Int_t i=0; i<=fH1->GetNbinsX();++i) {
926 val = fH1->GetBinContent(i);
927 val2 = fH2->GetBinContent(i);
929 if (fErrorMode == TRatioPlot::ErrorMode::kErrorAsymmetric) {
931 Double_t errUp = fH1->GetBinErrorUp(i);
932 Double_t errLow = fH1->GetBinErrorLow(i);
934 if (val - val2 > 0) {
942 }
else if (fErrorMode == TRatioPlot::ErrorMode::kErrorSymmetric) {
943 error = fH1->GetBinError(i);
945 Warning(
"BuildLowerPlot",
"error mode is invalid");
951 res = (val - val2) / error;
953 ((TGraphAsymmErrors*)fRatioGraph)->SetPoint(ipoint, fH1->GetBinCenter(i), res);
954 ((TGraphAsymmErrors*)fRatioGraph)->SetPointError(ipoint, fH1->GetBinWidth(i)/2., fH1->GetBinWidth(i)/2., 0.5, 0.5);
961 }
else if (fMode == TRatioPlot::CalculationMode::kFitResidual) {
963 SetGridlines(signGridlines, 3);
965 TF1 *func =
dynamic_cast<TF1*
>(fH1->GetListOfFunctions()->At(0));
969 Error(
"BuildLowerPlot",
"h1 does not have a fit function");
973 fRatioGraph =
new TGraphAsymmErrors();
979 std::vector<double> ci1;
980 std::vector<double> ci2;
982 Double_t *x_arr =
new Double_t[fH1->GetNbinsX()];
983 std::fill_n(x_arr, fH1->GetNbinsX(), 0);
984 Double_t *ci_arr1 =
new Double_t[fH1->GetNbinsX()];
985 std::fill_n(ci_arr1, fH1->GetNbinsX(), 0);
986 Double_t *ci_arr2 =
new Double_t[fH1->GetNbinsX()];
987 std::fill_n(ci_arr2, fH1->GetNbinsX(), 0);
988 for (Int_t i=0; i<fH1->GetNbinsX();++i) {
989 x_arr[i] = fH1->GetBinCenter(i+1);
995 if (fFitResult != 0) {
998 fFitResult->GetConfidenceIntervals(fH1->GetNbinsX(), 1, 1, x_arr, ci_arr1, cl1);
999 for (Int_t i=1; i<=fH1->GetNbinsX();++i) {
1000 ci1.push_back(ci_arr1[i-1]);
1003 fFitResult->GetConfidenceIntervals(fH1->GetNbinsX(), 1, 1, x_arr, ci_arr2, cl2);
1004 for (Int_t i=1; i<=fH1->GetNbinsX();++i) {
1005 ci2.push_back(ci_arr2[i-1]);
1008 (TVirtualFitter::GetFitter())->GetConfidenceIntervals(fH1->GetNbinsX(), 1, x_arr, ci_arr1, cl1);
1009 for (Int_t i=1; i<=fH1->GetNbinsX();++i) {
1010 ci1.push_back(ci_arr1[i-1]);
1012 (TVirtualFitter::GetFitter())->GetConfidenceIntervals(fH1->GetNbinsX(), 1, x_arr, ci_arr2, cl2);
1013 for (Int_t i=1; i<=fH1->GetNbinsX();++i) {
1014 ci2.push_back(ci_arr2[i-1]);
1022 for (Int_t i=0; i<=fH1->GetNbinsX();++i) {
1023 val = fH1->GetBinContent(i);
1024 x = fH1->GetBinCenter(i+1);
1026 if (fErrorMode == TRatioPlot::ErrorMode::kErrorAsymmetric) {
1028 Double_t errUp = fH1->GetBinErrorUp(i);
1029 Double_t errLow = fH1->GetBinErrorLow(i);
1031 if (val - func->Eval(fH1->GetBinCenter(i)) > 0) {
1039 }
else if (fErrorMode == TRatioPlot::ErrorMode::kErrorSymmetric) {
1040 error = fH1->GetBinError(i);
1041 }
else if (fErrorMode == TRatioPlot::ErrorMode::kErrorFunc) {
1043 error = sqrt(func->Eval(x));
1046 Warning(
"BuildLowerPlot",
"error mode is invalid");
1052 res = (fH1->GetBinContent(i)- func->Eval(fH1->GetBinCenter(i) ) ) / error;
1055 ((TGraphAsymmErrors*)fRatioGraph)->SetPoint(ipoint, fH1->GetBinCenter(i), res);
1056 ((TGraphAsymmErrors*)fRatioGraph)->SetPointError(ipoint, fH1->GetBinWidth(i)/2., fH1->GetBinWidth(i)/2., 0.5, 0.5);
1058 fConfidenceInterval1->SetPoint(ipoint, x, 0);
1059 fConfidenceInterval1->SetPointError(ipoint, x, i < (Int_t)ci1.size() ? ci1[i] / error : 0);
1060 fConfidenceInterval2->SetPoint(ipoint, x, 0);
1061 fConfidenceInterval2->SetPointError(ipoint, x, i < (Int_t)ci2.size() ? ci2[i] / error : 0);
1071 }
else if (fMode == TRatioPlot::CalculationMode::kDivideHist){
1072 SetGridlines(divideGridlines, 3);
1075 TH1 *tmpHist = (TH1*)fH1->Clone();
1078 tmpHist->Divide(fH1, fH2, fC1, fC2, fOption.Data());
1079 fRatioGraph =
new TGraphErrors(tmpHist);
1084 Error(
"BuildLowerPlot",
"Invalid fMode value");
1091 if (fRatioGraph == 0) {
1092 Error(
"BuildLowerPlot",
"Error creating lower graph");
1096 fRatioGraph->SetTitle(
"");
1097 fConfidenceInterval1->SetTitle(
"");
1098 fConfidenceInterval2->SetTitle(
"");
1107 void TRatioPlot::CreateVisualAxes()
1109 TVirtualPad *padsav = gPad;
1113 TString thisfunc =
"CreateVisualAxes";
1117 Double_t upTM = fUpperPad->GetTopMargin();
1118 Double_t upBM = fUpperPad->GetBottomMargin();
1119 Double_t upLM = fUpperPad->GetLeftMargin();
1120 Double_t upRM = fUpperPad->GetRightMargin();
1122 Double_t lowTM = fLowerPad->GetTopMargin();
1123 Double_t lowBM = fLowerPad->GetBottomMargin();
1124 Double_t lowLM = fLowerPad->GetLeftMargin();
1125 Double_t lowRM = fLowerPad->GetRightMargin();
1127 Double_t first = fSharedXAxis->GetBinLowEdge(fSharedXAxis->GetFirst());
1128 Double_t last = fSharedXAxis->GetBinUpEdge(fSharedXAxis->GetLast());
1130 Double_t upYFirst = fUpperPad->GetUymin();
1131 Double_t upYLast = fUpperPad->GetUymax();
1132 Double_t lowYFirst = fLowerPad->GetUymin();
1133 Double_t lowYLast = fLowerPad->GetUymax();
1135 Float_t sf = fSplitFraction;
1138 Bool_t mirroredAxes = fParentPad->GetFrameFillStyle() == 0;
1139 Bool_t axistop = fParentPad->GetTickx() == 1 || mirroredAxes;
1140 Bool_t axisright = fParentPad->GetTicky() == 1 || mirroredAxes;
1142 Bool_t logx = fUpperPad->GetLogx() || fLowerPad->GetLogx();
1143 Bool_t uplogy = fUpperPad->GetLogy();
1144 Bool_t lowlogy = fLowerPad->GetLogy();
1148 upYFirst = TMath::Power(10, upYFirst);
1149 upYLast = TMath::Power(10, upYLast);
1151 if (upYFirst <= 0 || upYLast <= 0) {
1152 Error(thisfunc,
"Cannot set upper Y axis to log scale");
1157 lowYFirst = TMath::Power(10, lowYFirst);
1158 lowYLast = TMath::Power(10, lowYLast);
1160 if (lowYFirst <= 0 || lowYLast <= 0) {
1161 Error(thisfunc,
"Cannot set lower Y axis to log scale");
1168 if (first <= 0 || last <= 0) {
1169 Error(thisfunc,
"Cannot set X axis to log scale");
1175 if (logx) xopt.Append(
"G");
1176 TString upyopt =
"";
1177 if (uplogy) upyopt.Append(
"G");
1178 TString lowyopt =
"";
1179 if (lowlogy) lowyopt.Append(
"G");
1182 if (fUpperGXaxis == 0) {
1183 fUpperGXaxis =
new TGaxis(0, 0, 1, 1, 0, 1, 510,
"+U"+xopt);
1184 fUpperGXaxis->Draw();
1187 if (fUpperGYaxis == 0) {
1188 fUpperGYaxis =
new TGaxis(0, 0, 1, 1, upYFirst, upYLast, 510,
"S"+upyopt);
1189 fUpperGYaxis->Draw();
1192 if (fLowerGXaxis == 0) {
1193 fLowerGXaxis =
new TGaxis(0, 0, 1, 1, first, last, 510,
"+S"+xopt);
1194 fLowerGXaxis->Draw();
1197 if (fLowerGYaxis == 0) {
1198 fLowerGYaxis =
new TGaxis(0, 0, 1, 1, lowYFirst, lowYLast, 510,
"-S"+lowyopt);
1199 fLowerGYaxis->Draw();
1203 ImportAxisAttributes(fUpperGXaxis, GetUpperRefXaxis());
1204 ImportAxisAttributes(fUpperGYaxis, GetUpperRefYaxis());
1205 ImportAxisAttributes(fLowerGXaxis, GetLowerRefXaxis());
1206 ImportAxisAttributes(fLowerGYaxis, GetLowerRefYaxis());
1209 fLowerGXaxis->SetTitle(fUpperGXaxis->GetTitle());
1212 fUpperGXaxis->SetTitle(
"");
1214 fUpperGXaxis->SetX1(upLM);
1215 fUpperGXaxis->SetX2(1-upRM);
1216 fUpperGXaxis->SetY1(upBM*(1-sf)+sf);
1217 fUpperGXaxis->SetY2(upBM*(1-sf)+sf);
1218 fUpperGXaxis->SetWmin(first);
1219 fUpperGXaxis->SetWmax(last);
1221 fUpperGYaxis->SetX1(upLM);
1222 fUpperGYaxis->SetX2(upLM);
1223 fUpperGYaxis->SetY1(upBM*(1-sf)+sf);
1224 fUpperGYaxis->SetY2( (1-upTM)*(1-sf)+sf );
1225 fUpperGYaxis->SetWmin(upYFirst);
1226 fUpperGYaxis->SetWmax(upYLast);
1228 fLowerGXaxis->SetX1(lowLM);
1229 fLowerGXaxis->SetX2(1-lowRM);
1230 fLowerGXaxis->SetY1(lowBM*sf);
1231 fLowerGXaxis->SetY2(lowBM*sf);
1232 fLowerGXaxis->SetWmin(first);
1233 fLowerGXaxis->SetWmax(last);
1235 fLowerGYaxis->SetX1(lowLM);
1236 fLowerGYaxis->SetX2(lowLM);
1237 fLowerGYaxis->SetY1(lowBM*sf);
1238 fLowerGYaxis->SetY2((1-lowTM)*sf);
1239 fLowerGYaxis->SetWmin(lowYFirst);
1240 fLowerGYaxis->SetWmax(lowYLast);
1242 fUpperGXaxis->SetNdivisions(fSharedXAxis->GetNdivisions());
1243 fUpperGYaxis->SetNdivisions(fUpYaxis->GetNdivisions());
1244 fLowerGXaxis->SetNdivisions(fSharedXAxis->GetNdivisions());
1245 fLowerGYaxis->SetNdivisions(fLowYaxis->GetNdivisions());
1247 fUpperGXaxis->SetOption(
"+U"+xopt);
1248 fUpperGYaxis->SetOption(
"S"+upyopt);
1249 fLowerGXaxis->SetOption(
"+S"+xopt);
1250 fLowerGYaxis->SetOption(
"-S"+lowyopt);
1254 Double_t ratio = ( (upBM-(1-upTM))*(1-sf) ) / ( (lowBM-(1-lowTM))*sf ) ;
1255 fUpperGXaxis->SetLabelSize(0.);
1256 Double_t ticksize = fUpperGYaxis->GetTickSize()*ratio;
1257 fLowerGYaxis->SetTickSize(ticksize);
1259 if (fHideLabelMode == TRatioPlot::HideLabelMode::kForceHideUp) {
1261 fUpperGYaxis->ChangeLabel(1, -1, 0);
1263 }
else if (fHideLabelMode == TRatioPlot::HideLabelMode::kForceHideLow) {
1265 fLowerGYaxis->ChangeLabel(-1, -1, 0);
1268 if (GetSeparationMargin() < 0.025) {
1270 if (fHideLabelMode != TRatioPlot::HideLabelMode::kNoHide) {
1271 if (fHideLabelMode == TRatioPlot::HideLabelMode::kHideUp) {
1272 fUpperGYaxis->ChangeLabel(1, -1, 0);
1273 }
else if (fHideLabelMode == TRatioPlot::HideLabelMode::kHideLow) {
1274 fLowerGYaxis->ChangeLabel(-1, -1, 0);
1280 if (fHideLabelMode == TRatioPlot::HideLabelMode::kHideUp) {
1281 fUpperGYaxis->ChangeLabel(0);
1282 }
else if (fHideLabelMode == TRatioPlot::HideLabelMode::kHideLow) {
1283 fLowerGYaxis->ChangeLabel(0);
1291 if (axistop || axisright) {
1294 if (fUpperGXaxisMirror == 0) {
1295 fUpperGXaxisMirror = (TGaxis*)fUpperGXaxis->Clone();
1296 if (axistop) fUpperGXaxisMirror->Draw();
1299 if (fLowerGXaxisMirror == 0) {
1300 fLowerGXaxisMirror = (TGaxis*)fLowerGXaxis->Clone();
1301 if (axistop) fLowerGXaxisMirror->Draw();
1304 if (fUpperGYaxisMirror == 0) {
1305 fUpperGYaxisMirror = (TGaxis*)fUpperGYaxis->Clone();
1306 if (axisright) fUpperGYaxisMirror->Draw();
1309 if (fLowerGYaxisMirror == 0) {
1310 fLowerGYaxisMirror = (TGaxis*)fLowerGYaxis->Clone();
1311 if (axisright) fLowerGYaxisMirror->Draw();
1315 ImportAxisAttributes(fUpperGXaxisMirror, GetUpperRefXaxis());
1316 ImportAxisAttributes(fUpperGYaxisMirror, GetUpperRefYaxis());
1317 ImportAxisAttributes(fLowerGXaxisMirror, GetLowerRefXaxis());
1318 ImportAxisAttributes(fLowerGYaxisMirror, GetLowerRefYaxis());
1321 fUpperGXaxisMirror->SetTitle(
"");
1322 fUpperGYaxisMirror->SetTitle(
"");
1323 fLowerGXaxisMirror->SetTitle(
"");
1324 fLowerGYaxisMirror->SetTitle(
"");
1327 fUpperGXaxisMirror->SetX1(upLM);
1328 fUpperGXaxisMirror->SetX2(1-upRM);
1329 fUpperGXaxisMirror->SetY1((1-upTM)*(1-sf)+sf);
1330 fUpperGXaxisMirror->SetY2((1-upTM)*(1-sf)+sf);
1331 fUpperGXaxisMirror->SetWmin(first);
1332 fUpperGXaxisMirror->SetWmax(last);
1334 fUpperGYaxisMirror->SetX1(1-upRM);
1335 fUpperGYaxisMirror->SetX2(1-upRM);
1336 fUpperGYaxisMirror->SetY1(upBM*(1-sf)+sf);
1337 fUpperGYaxisMirror->SetY2( (1-upTM)*(1-sf)+sf );
1338 fUpperGYaxisMirror->SetWmin(upYFirst);
1339 fUpperGYaxisMirror->SetWmax(upYLast);
1341 fLowerGXaxisMirror->SetX1(lowLM);
1342 fLowerGXaxisMirror->SetX2(1-lowRM);
1343 fLowerGXaxisMirror->SetY1((1-lowTM)*sf);
1344 fLowerGXaxisMirror->SetY2((1-lowTM)*sf);
1345 fLowerGXaxisMirror->SetWmin(first);
1346 fLowerGXaxisMirror->SetWmax(last);
1348 fLowerGYaxisMirror->SetX1(1-lowRM);
1349 fLowerGYaxisMirror->SetX2(1-lowRM);
1350 fLowerGYaxisMirror->SetY1(lowBM*sf);
1351 fLowerGYaxisMirror->SetY2((1-lowTM)*sf);
1352 fLowerGYaxisMirror->SetWmin(lowYFirst);
1353 fLowerGYaxisMirror->SetWmax(lowYLast);
1356 fLowerGYaxisMirror->SetTickSize(ticksize);
1358 fUpperGXaxisMirror->SetOption(
"-S"+xopt);
1359 fUpperGYaxisMirror->SetOption(
"+S"+upyopt);
1360 fLowerGXaxisMirror->SetOption(
"-S"+xopt);
1361 fLowerGYaxisMirror->SetOption(
"+S"+lowyopt);
1363 fUpperGXaxisMirror->SetNdivisions(fSharedXAxis->GetNdivisions());
1364 fUpperGYaxisMirror->SetNdivisions(fUpYaxis->GetNdivisions());
1365 fLowerGXaxisMirror->SetNdivisions(fSharedXAxis->GetNdivisions());
1366 fLowerGYaxisMirror->SetNdivisions(fLowYaxis->GetNdivisions());
1368 fUpperGXaxisMirror->SetLabelSize(0.);
1369 fLowerGXaxisMirror->SetLabelSize(0.);
1370 fUpperGYaxisMirror->SetLabelSize(0.);
1371 fLowerGYaxisMirror->SetLabelSize(0.);
1382 void TRatioPlot::SetPadMargins()
1384 fUpperPad->SetTopMargin(fUpTopMargin);
1385 fUpperPad->SetBottomMargin(fUpBottomMargin);
1386 fUpperPad->SetLeftMargin(fLeftMargin);
1387 fUpperPad->SetRightMargin(fRightMargin);
1388 fLowerPad->SetTopMargin(fLowTopMargin);
1389 fLowerPad->SetBottomMargin(fLowBottomMargin);
1390 fLowerPad->SetLeftMargin(fLeftMargin);
1391 fLowerPad->SetRightMargin(fRightMargin);
1399 Bool_t TRatioPlot::SyncPadMargins()
1402 Bool_t changed = kFALSE;
1404 if (fUpperPad->GetLeftMargin() != fLeftMargin) {
1405 fLeftMargin = fUpperPad->GetLeftMargin();
1408 else if (fLowerPad->GetLeftMargin() != fLeftMargin) {
1409 fLeftMargin = fLowerPad->GetLeftMargin();
1413 if (fUpperPad->GetRightMargin() != fRightMargin) {
1414 fRightMargin = fUpperPad->GetRightMargin();
1417 else if (fLowerPad->GetRightMargin() != fRightMargin) {
1418 fRightMargin = fLowerPad->GetRightMargin();
1427 Bool_t verticalChanged = kFALSE;
1429 if (fUpperPad->GetBottomMargin() != fUpBottomMargin) {
1431 verticalChanged = kTRUE;
1432 fUpBottomMargin = fUpperPad->GetBottomMargin();
1436 if (fLowerPad->GetTopMargin() != fLowTopMargin) {
1438 verticalChanged = kTRUE;
1439 fLowTopMargin = fLowerPad->GetTopMargin();
1443 if (fLowerPad->GetBottomMargin() != fLowBottomMargin) {
1445 fLowBottomMargin = fLowerPad->GetBottomMargin();
1449 if (fUpperPad->GetTopMargin() != fUpTopMargin) {
1451 fUpTopMargin = fUpperPad->GetTopMargin();
1456 if (verticalChanged) {
1460 return changed || verticalChanged;
1468 void TRatioPlot::RangeAxisChanged()
1481 fIsUpdating = kTRUE;
1484 if (fParentPad->GetLogx()) {
1485 if (!fUpperPad->GetLogx() || !fLowerPad->GetLogx()) {
1486 fParentPad->SetLogx(kFALSE);
1489 if (fUpperPad->GetLogx() || fLowerPad->GetLogx()) {
1490 fParentPad->SetLogx(kTRUE);
1495 fUpperPad->SetLogx(fParentPad->GetLogx());
1496 fLowerPad->SetLogx(fParentPad->GetLogx());
1499 TAxis *uprefx = GetUpperRefXaxis();
1500 Double_t upFirst = uprefx->GetBinLowEdge(uprefx->GetFirst());
1501 Double_t upLast = uprefx->GetBinUpEdge(uprefx->GetLast());
1503 TAxis *lowrefx = GetLowerRefXaxis();
1504 Double_t lowFirst = lowrefx->GetBinLowEdge(lowrefx->GetFirst());
1505 Double_t lowLast = lowrefx->GetBinUpEdge(lowrefx->GetLast());
1507 Double_t globFirst = fSharedXAxis->GetBinLowEdge(fSharedXAxis->GetFirst());
1508 Double_t globLast = fSharedXAxis->GetBinUpEdge(fSharedXAxis->GetLast());
1510 Bool_t upChanged = kFALSE;
1511 Bool_t lowChanged = kFALSE;
1514 if (upFirst != globFirst || upLast != globLast) {
1515 fSharedXAxis->SetRangeUser(upFirst, upLast);
1518 else if (lowFirst != globFirst || lowLast != globLast) {
1519 fSharedXAxis->SetRangeUser(lowFirst, lowLast);
1523 if (upChanged || lowChanged) {
1529 fUpperPad->Modified();
1530 fLowerPad->Modified();
1531 fTopPad->Modified();
1532 fParentPad->Modified();
1536 Bool_t marginsChanged = SyncPadMargins();
1538 if (marginsChanged) {
1539 fUpperPad->Modified();
1540 fLowerPad->Modified();
1541 fTopPad->Modified();
1542 fParentPad->Modified();
1547 fIsUpdating = kFALSE;
1554 void TRatioPlot::UnZoomed()
1557 fSharedXAxis->SetRange(0, 0);
1561 fUpperPad->Modified();
1562 fLowerPad->Modified();
1563 fTopPad->Modified();
1564 fParentPad->Modified();
1570 void TRatioPlot::SubPadResized()
1573 if (fIsPadUpdating) {
1577 fIsPadUpdating = kTRUE;
1579 Float_t upylow = fUpperPad->GetYlowNDC();
1580 Float_t lowylow = fLowerPad->GetYlowNDC();
1581 Float_t lowh = fLowerPad->GetHNDC();
1582 Float_t lowyup = lowylow + lowh;
1584 Bool_t changed = kFALSE;
1586 if (upylow != fSplitFraction) {
1588 SetSplitFraction(upylow);
1591 else if (lowyup != fSplitFraction) {
1593 SetSplitFraction(lowyup);
1601 fIsPadUpdating = kFALSE;
1608 Bool_t TRatioPlot::IsDrawn()
1610 TList *siblings = fParentPad->GetListOfPrimitives();
1611 return siblings->FindObject(
this) != 0;
1617 void TRatioPlot::SetSplitFraction(Float_t sf)
1619 if (fParentPad == 0) {
1620 Warning(
"SetSplitFraction",
"Can only be used after TRatioPlot has been drawn.");
1624 fSplitFraction = sf;
1625 double pm = fInsetWidth;
1626 double width = fParentPad->GetWNDC();
1627 double height = fParentPad->GetHNDC();
1628 double f = height/width;
1630 fUpperPad->SetPad(pm*f, fSplitFraction, 1.-pm*f, 1.-pm);
1631 fLowerPad->SetPad(pm*f, pm, 1.-pm*f, fSplitFraction);
1638 void TRatioPlot::SetInsetWidth(Double_t width)
1640 if (fParentPad == 0) {
1641 Warning(
"SetInsetWidth",
"Can only be used after TRatioPlot has been drawn.");
1645 fInsetWidth = width;
1646 SetSplitFraction(fSplitFraction);
1648 double pm = fInsetWidth;
1649 double w = fParentPad->GetWNDC();
1650 double h = fParentPad->GetHNDC();
1652 fTopPad->SetPad(pm*f, pm, 1-pm*f, 1-pm);
1659 void TRatioPlot::SetConfidenceLevels(Double_t c1, Double_t c2)
1663 if (!BuildLowerPlot())
return;
1676 void TRatioPlot::SetGridlines(std::vector<double> gridlines)
1678 fGridlinePositions = gridlines;
1688 void TRatioPlot::SetGridlines(Double_t *gridlines, Int_t numGridlines)
1690 fGridlinePositions.clear();
1692 for (Int_t i=0;i<numGridlines;++i) {
1693 fGridlinePositions.push_back(gridlines[i]);
1707 void TRatioPlot::SetConfidenceIntervalColors(Color_t ci1, Color_t ci2)
1717 void TRatioPlot::ImportAxisAttributes(TGaxis *gaxis, TAxis *axis)
1719 gaxis->SetLineColor(axis->GetAxisColor());
1720 gaxis->SetTextColor(axis->GetTitleColor());
1721 gaxis->SetTextFont(axis->GetTitleFont());
1722 gaxis->SetLabelColor(axis->GetLabelColor());
1723 gaxis->SetLabelFont(axis->GetLabelFont());
1724 gaxis->SetLabelSize(axis->GetLabelSize());
1725 gaxis->SetLabelOffset(axis->GetLabelOffset());
1726 gaxis->SetTickSize(axis->GetTickLength());
1727 gaxis->SetTitle(axis->GetTitle());
1728 gaxis->SetTitleOffset(axis->GetTitleOffset());
1729 gaxis->SetTitleSize(axis->GetTitleSize());
1730 gaxis->SetBit(TAxis::kCenterTitle, axis->TestBit(TAxis::kCenterTitle));
1731 gaxis->SetBit(TAxis::kCenterLabels, axis->TestBit(TAxis::kCenterLabels));
1732 gaxis->SetBit(TAxis::kRotateTitle, axis->TestBit(TAxis::kRotateTitle));
1733 gaxis->SetBit(TAxis::kNoExponent, axis->TestBit(TAxis::kNoExponent));
1734 gaxis->SetBit(TAxis::kTickPlus, axis->TestBit(TAxis::kTickPlus));
1735 gaxis->SetBit(TAxis::kTickMinus, axis->TestBit(TAxis::kTickMinus));
1736 gaxis->SetBit(TAxis::kMoreLogLabels, axis->TestBit(TAxis::kMoreLogLabels));
1737 if (axis->GetDecimals()) gaxis->SetBit(TAxis::kDecimals);
1738 gaxis->SetTimeFormat(axis->GetTimeFormat());