Crombie Tools
PlotUtils.h
Go to the documentation of this file.
1 #ifndef CROMBIETOOLS_PLOTTOOLS_PLOTUTILS_H
2 #define CROMBIETOOLS_PLOTTOOLS_PLOTUTILS_H
3 
4 #include <algorithm>
5 #include <limits>
6 #include <set>
7 
8 #include "TFile.h"
9 #include "TTree.h"
10 #include "TF1.h"
11 #include "TH1D.h"
12 #include "TH1.h"
13 #include "TGraphErrors.h"
14 #include "TMath.h"
15 #include "TCanvas.h"
16 
17 #include "Debug.h"
18 #include "UncertaintyInfo.h"
19 
20 /** @addtogroup plotgroup */
21 /* @{ */
22 
23 //--------------------------------------------------------------------
24 
25 /**
26  Applies an uncertainty file to a histogram.
27 
28  @param theHist is the histogram to modify
29  @param theUnc is a pointer to the UncertaintyInfo to use
30 
31  The error of the histogram is adjusted by the following for each bin.
32  \f[
33  e_{bin} = \sqrt{e_{bin,0}^2 + (y_{bin} \times unc_{bin})^2}
34  \f]
35 */
36 
37 void
38 ApplyUncertainty(TH1* theHist, UncertaintyInfo* theUnc)
39 {
40  TFile* uncHistFile = new TFile(theUnc->fFileName);
41  TH1* uncHist = (TH1*) uncHistFile->Get(theUnc->fHistName);
42 
43  Int_t UncBin = theUnc->fStartBin;
44  for (Int_t iBin = 1; iBin != theHist->GetXaxis()->GetNbins(); ++iBin) {
45  theHist->SetBinError(iBin,
46  TMath::Sqrt(pow(theHist->GetBinError(iBin),2) +
47  pow(theHist->GetBinContent(iBin) *
48  (uncHist->GetBinContent(UncBin) - 1), 2)
49  ));
50  if (UncBin != theUnc->fEndBin)
51  UncBin += 1;
52  }
53 
54  uncHistFile->Close();
55 }
56 
57 //--------------------------------------------------------------------
58 /// Sets the parameter errors in a TF1 to 0
59 void
60 SetZeroError(TF1* theFunc)
61 {
62  for (Int_t iParam = 0; iParam != theFunc->GetNpar(); ++iParam)
63  theFunc->SetParError(iParam, 0);
64 }
65 
66 //--------------------------------------------------------------------
67 /// Sets the bin errors in a TH1 to 0
68 void
69 SetZeroError(TH1* theHist)
70 {
71  for (Int_t iBin = 0; iBin != theHist->GetXaxis()->GetNbins(); ++iBin)
72  theHist->SetBinError(iBin + 1, 0);
73 }
74 
75 //--------------------------------------------------------------------
76 /// Sets the point errors in a TGraphErrors to 0
77 void
78 SetZeroError(TGraphErrors* theGraph)
79 {
80  for (Int_t iPoint = 0; iPoint != theGraph->GetN(); ++iPoint)
81  theGraph->SetPointError(iPoint,0,0);
82 }
83 
84 //--------------------------------------------------------------------
85 /// Does nothing, just here for template purposes
86 void
87 SetZeroError(TGraph*)
88 { }
89 
90 //--------------------------------------------------------------------
91 /// Divides two TF1 by each other, replacing the first one
92 void
93 Division(TF1*& PlotFunc, TF1* RatioFunc)
94 {
95  TString plotString = TString("(") + PlotFunc->GetExpFormula() + TString(")");
96  TString ratString = TString("(") + RatioFunc->GetExpFormula().ReplaceAll(TString("[p"),TString("[q")) + TString(")");
97  TF1 *tempFunc = new TF1("divided",plotString + TString("/") + ratString);
98  for (Int_t iParam = 0; iParam != PlotFunc->GetNpar() + RatioFunc->GetNpar(); ++iParam) {
99  if (iParam < PlotFunc->GetNpar()) {
100  tempFunc->SetParameter(iParam, PlotFunc->GetParameter(iParam));
101  tempFunc->SetParError(iParam, PlotFunc->GetParError(iParam));
102  }
103  else {
104  tempFunc->SetParameter(iParam, RatioFunc->GetParameter(iParam - PlotFunc->GetNpar()));
105  tempFunc->SetParError(iParam, RatioFunc->GetParError(iParam - PlotFunc->GetNpar()));
106  }
107  }
108  delete PlotFunc;
109  PlotFunc = tempFunc;
110 }
111 
112 //--------------------------------------------------------------------
113 /// Does nothing, just here for template purposes
114 void
115 SetGraphErrorsForRatio(TGraph*, TGraph*, Int_t)
116 { }
117 
118 //--------------------------------------------------------------------
119 /// Sets errors after dividing two TGraphErrors
120 void
121 SetGraphErrorsForRatio(TGraphErrors* PlotGraph, TGraphErrors* RatioGraph, Int_t iPoint)
122 {
123  PlotGraph->SetPointError(iPoint,0,
124  sqrt(pow(PlotGraph->GetEY()[iPoint]/RatioGraph->GetY()[iPoint],2) +
125  pow((PlotGraph->GetY()[iPoint])*(RatioGraph->GetEY()[iPoint])/
126  pow(RatioGraph->GetY()[iPoint],2),2)));
127 }
128 
129 //--------------------------------------------------------------------
130 /// Divides two TGraphs
131 void
132 Division(TGraph* PlotGraph, TGraph* RatioGraph)
133 {
134  Int_t NumPoints = RatioGraph->GetN();
135  Double_t RangeMin = 1000.;
136  Double_t RangeMax = 0.;
137  for (Int_t iPoint = 0; iPoint != NumPoints; ++iPoint) {
138  Double_t point = PlotGraph->GetY()[iPoint]/RatioGraph->GetY()[iPoint];
139  PlotGraph->SetPoint(iPoint,PlotGraph->GetX()[iPoint],point);
140  SetGraphErrorsForRatio(PlotGraph, RatioGraph, iPoint);
141  if (point < RangeMin)
142  RangeMin = point;
143  if (point > RangeMax)
144  RangeMax = point;
145  }
146  PlotGraph->GetYaxis()->SetRangeUser(RangeMin,RangeMax);
147 }
148 
149 //--------------------------------------------------------------------
150 /// Divides two TH1s. If both contain bins with 0, the content is set to 1
151 void
152 Division(TH1* PlotHist, TH1* RatioHist)
153 {
154  PlotHist->Divide(RatioHist);
155  for (Int_t iBin = 1; iBin != RatioHist->GetXaxis()->GetNbins() + 1; ++iBin) {
156  if (PlotHist->GetBinContent(iBin) == 0 && RatioHist->GetBinContent(iBin) == 0)
157  PlotHist->SetBinContent(iBin,1); // @todo: Make this configurable between 0 and 1, maybe
158  }
159 }
160 
161 //--------------------------------------------------------------------
162 /// Gets the ratios of two equally sized vectors of lines
163 template<class T>
164 std::vector<T*>
165 GetRatioToLines(std::vector<T*> InLines, std::vector<T*> RatioLines)
166 {
167  T* tempLine;
168  std::vector<T*> outLines;
169  for (UInt_t iLine = 0; iLine != InLines.size(); ++iLine) {
170  tempLine = (T*) InLines[iLine]->Clone();
171  Division(tempLine,RatioLines[iLine]);
172  outLines.push_back(tempLine);
173  }
174  return outLines;
175 }
176 
177 //--------------------------------------------------------------------
178 /// Gets the ratios of one vector of lines to a single line
179 template<class T>
180 std::vector<T*>
181 GetRatioToLine(std::vector<T*> InLines, T* RatioGraph)
182 {
183  std::vector<T*> tempRatioLines;
184  for (UInt_t iLine = 0; iLine != InLines.size(); ++iLine)
185  tempRatioLines.push_back(RatioGraph);
186  return GetRatioToLines(InLines,tempRatioLines);
187 }
188 
189 //--------------------------------------------------------------------
190 /// Gets the ratio of TGraphErrors to a single point
191 std::vector<TGraphErrors*>
192 GetRatioToPoint(std::vector<TGraphErrors*> InGraphs, Double_t RatioPoint, Double_t PointError = 0)
193 {
194  Int_t NumPoints = InGraphs[0]->GetN();
195  Double_t* GraphX = InGraphs[0]->GetX();
196  TGraphErrors tempRatioGraph(NumPoints);
197  for (Int_t iPoint = 0; iPoint != NumPoints; ++iPoint) {
198  tempRatioGraph.SetPoint(iPoint,GraphX[iPoint],RatioPoint);
199  tempRatioGraph.SetPointError(iPoint,0,PointError);
200  }
201  return GetRatioToLine(InGraphs,&tempRatioGraph);
202 }
203 
204 //--------------------------------------------------------------------
205 /// Gets the ratio of TH1Ds to a single point
206 std::vector<TH1D*>
207 GetRatioToPoint(std::vector<TH1D*> InHists, Double_t RatioPoint, Double_t PointError = 0)
208 {
209  TH1D tempRatioHist = *(InHists[0]);
210  tempRatioHist.Reset();
211  for (Int_t iBin = 0; iBin != tempRatioHist.GetXaxis()->GetNbins(); iBin++) {
212  tempRatioHist.SetBinContent(iBin + 1,RatioPoint);
213  tempRatioHist.SetBinError(iBin + 1,PointError);
214  }
215  return GetRatioToLine(InHists,&tempRatioHist);
216 }
217 
218 //--------------------------------------------------------------------
219 /// Gets the ratio of TF1s to a single point
220 std::vector<TF1*>
221 GetRatioToPoint(std::vector<TF1*> InFuncs, Double_t RatioPoint, Double_t PointError = 0)
222 {
223  TF1 tempRatioFunc("ratio","[0]");
224  tempRatioFunc.SetParameter(0,RatioPoint);
225  tempRatioFunc.SetParError(0,PointError);
226  return GetRatioToLine(InFuncs,&tempRatioFunc);
227 }
228 
229 //--------------------------------------------------------------------
230 /// Holds the action of nothing for setting up most canvases
231 template<class T>
232 void SetupCanvas(Debug*, std::vector<T*>, TCanvas*, Double_t, Double_t, TString, TString)
233 { }
234 
235 //--------------------------------------------------------------------
236 /// Draws a frame for canvases that will hold TGraphErrors
237 template<>
238 void SetupCanvas(Debug* debugger, std::vector<TGraphErrors*> theLines, TCanvas *theCanvas,
239  Double_t fAxisMin, Double_t fAxisMax, TString XLabel, TString YLabel)
240 {
241 
242  // Initialize the variables that will be used for frame
243  double YMin = std::numeric_limits<double>::max();
244  double YMax = std::numeric_limits<double>::min();
245  double XMin = std::numeric_limits<double>::max();
246  double XMax = std::numeric_limits<double>::min();
247 
248  for (std::vector<TGraphErrors*>::iterator iLine = theLines.begin(); iLine != theLines.end(); ++iLine ) {
249 
250  double ymin_, ymax_, xmin_, xmax_;
251 
252  (*iLine)->ComputeRange(xmin_, ymin_, xmax_, ymax_);
253 
254  debugger->Message(Debug::eDebug, "Computed range xmin: %f, xmax: %f, ymin: %f, ymax: %f",
255  xmin_, xmax_, ymin_, ymax_);
256 
257  XMin = std::min(XMin, xmin_);
258  XMax = std::max(XMax, xmax_);
259  YMin = std::min(YMin, ymin_);
260  YMax = std::max(YMax, ymax_);
261 
262  debugger->Message(Debug::eDebug, "Stored range xmin: %f, xmax: %f, ymin: %f, ymax: %f",
263  XMin, XMax, YMin, YMax);
264 
265  }
266 
267  if (fAxisMin != fAxisMax) {
268  YMin = fAxisMin;
269  YMax = fAxisMax;
270  }
271 
272  theCanvas->DrawFrame(XMin, YMin, XMax, YMax, ";" + XLabel + ";" + YLabel);
273 }
274 
275 /// Adds branches needed from tree for formula expression into the set of needed
276 void AddNecessaryBranches(std::set<TString>& needed, TTree* tree, TString expr) {
277  for (auto branch : *(tree->GetListOfBranches())) {
278  auto name = branch->GetName();
279  if (needed.find(name) == needed.end() && expr.Contains(name))
280  needed.insert(name);
281  }
282 }
283 
284 /* @} */
285 
286 #endif