Crombie Tools
PlotHists.h
Go to the documentation of this file.
1 /**
2  @file PlotHists.h
3  Definition of PlotHists class.
4  @author Daniel Abercrombie <dabercro@mit.edu>
5 */
6 
7 #ifndef CROMBIETOOLS_PLOTTOOLS_PLOTHISTS_H
8 #define CROMBIETOOLS_PLOTTOOLS_PLOTHISTS_H
9 
10 #include <vector>
11 
12 #include "TH1D.h"
13 #include "TCanvas.h"
14 #include "TProfile.h"
15 
16 #include "PlotUtils.h"
17 #include "UncertaintyInfo.h"
18 #include "PlotBase.h"
19 
20 /**
21  @ingroup plotgroup
22  @class PlotHists
23  A flexible class that plots histograms.
24  Many practical uses are mediated by other classes.
25 */
26 
27 class PlotHists : public PlotBase
28 {
29  public:
30  PlotHists();
31  virtual ~PlotHists();
32 
33  /// Add uncertainty factors to some index of histograms about to be made
34  void AddUncertainty ( UInt_t index, TString FileName, TString HistName,
35  Int_t startBin = 1, Int_t endBin = 0 );
36  /// This just return vectors of histograms for other uses
37  std::vector<TH1D*> MakeHists ( Int_t NumXBins, Double_t *XBins );
38  std::vector<TH1D*> MakeHists ( Int_t NumXBins, Double_t MinX, Double_t MaxX );
39 
40  /// Alternatively, we can set values in PlotBase and then just give the binning
41  virtual void MakeCanvas ( TString FileBase, Int_t NumXBins, Double_t *XBins,
42  TString XLabel, TString YLabel, Bool_t logY = false);
43 
44  virtual void MakeCanvas ( TString FileBase, Int_t NumXBins, Double_t MinX, Double_t MaxX,
45  TString XLabel, TString YLabel, Bool_t logY = false);
46 
47  /// Add uncertainty factors through branch expressions instead of a histogram
48  void SetUncertaintySquared ( TString expr ) { fUncExpr = expr; }
49  /// We can set normalization to match a particular other hist (or just 1)
50  void SetNormalizedHists ( Bool_t b ) { fNormalizedHists = b; }
51  /// Set index of which histogram to normalize to
52  void SetNormalizeTo ( Int_t to ) { fNormalizeTo = to; }
53  /// We can set events per some value of x so that our legend entry is not wrong and variable binning doesn't look stupid
54  void SetEventsPer ( Double_t per ) { fEventsPer = per; }
55 
56  /// Simplest of Canvas makers with just histograms as arugments, allowing for user manipulation of histograms
57  void MakeCanvas ( TString FileBase, std::vector<TH1D*> theHists,
58  TString XLabel, TString YLabel, Bool_t logY = false)
59  { BaseCanvas(FileBase, theHists, XLabel, YLabel, logY); }
60 
61  protected:
62  Double_t fEventsPer = 0; ///< Histogram normalized to events per units of X axis
63 
64  private:
65  Bool_t fNormalizedHists = false; ///< Can normalize histograms in order to compare shapes
66  Int_t fNormalizeTo = -1; ///< If not specified, normalized to 1
67  std::vector<UInt_t> fSysUncIndices; ///< Indices of histograms to apply systematic uncertainties
68  std::vector<UncertaintyInfo> fUncerts; ///< Uncertainties to apply to histograms
69  TString fUncExpr = ""; ///< Branch expressions to add to the systematic uncertainty
70 
71 };
72 
73 //--------------------------------------------------------------------
75 {}
76 
77 //--------------------------------------------------------------------
79 { }
80 
81 //--------------------------------------------------------------------
82 void
83 PlotHists::AddUncertainty(UInt_t index, TString FileName, TString HistName,
84  Int_t startBin, Int_t endBin )
85 {
86  fSysUncIndices.push_back(index);
87  fUncerts.push_back({"", FileName, HistName, startBin, endBin});
88 }
89 
90 //--------------------------------------------------------------------
91 std::vector<TH1D*>
92 PlotHists::MakeHists(Int_t NumXBins, Double_t *XBins)
93 {
94  DisplayFunc(__func__);
95 
96  UInt_t NumPlots = 0;
97  std::vector<TH1D*> theHists;
98 
99  if (fNormalizeTo != -1)
100  fNormalizedHists = true;
101 
102  if (fInTrees.size() != 0)
103  NumPlots = fInTrees.size();
104  else if (fInCuts.size() != 0)
105  NumPlots = fInCuts.size();
106  else
107  NumPlots = fInExpr.size();
108 
109  if(NumPlots == 0){
110  Message(eError, "Number of trees:", fInTrees.size(),
111  "cuts:",fInCuts.size(),
112  "expressions:", fInExpr.size());
113  Message(eError, "Nothing has been initialized in hists plot.");
114  exit(1);
115  }
116 
117  TTree *inTree = fDefaultTree;
118  TString inExpr = fDefaultExpr;
119  TCut inCut = fDefaultCut;
120 
121  TH1D *tempHist;
122 
123  for (UInt_t iPlot = 0; iPlot != NumPlots; ++iPlot) {
124 
125  if (fInTrees.size() != 0)
126  inTree = fInTrees[iPlot];
127  if (fInCuts.size() != 0)
128  inCut = fInCuts[iPlot];
129  if (fInExpr.size() != 0)
130  inExpr = fInExpr[iPlot];
131 
132  if (!inTree || inExpr == "" || inCut == "") {
133  Message(eError, "There is a problem with one of these in plot", iPlot);
134  Message(eError, "Tree:", inTree, "Expression:", inExpr.Data(), "Cut:", inCut.GetTitle());
135  exit(12);
136  }
137 
138  TString tempName;
139  tempName.Form("Hist_%d", fPlotCounter);
140  fPlotCounter++;
141  tempHist = new TH1D(tempName, tempName, NumXBins, XBins);
142  tempHist->Sumw2();
143 
144  Message(eDebug, "About to draw %s on %s, with cut %s",
145  inExpr.Data(), tempName.Data(), inCut.GetTitle());
146 
147  inTree->Draw(inExpr + ">>" + tempName, inCut);
148 
149  if (fUncExpr != "" && tempHist->GetEntries() != 0) {
150 
151  // If there's an uncertainty expression, add systematics to the plot
152  tempName += "_unc";
153  TProfile *uncProfile = new TProfile(tempName, tempName, NumXBins, XBins);
154  inTree->Draw(fUncExpr + ":" + inExpr + ">>" + tempName, inCut);
155  for (Int_t iBin = 1; iBin != NumXBins + 1; ++iBin) {
156  Double_t uncSquared = uncProfile->GetBinContent(iBin);
157  if (uncSquared == 0.0)
158  continue;
159  Message(eDebug, "About to apply uncertainty %f", TMath::Sqrt(uncSquared));
160 
161  Double_t content = tempHist->GetBinContent(iBin);
162  Message(eDebug, "For hist %s, bin %i before: %f +- %f",
163  tempName.Data(), iBin, content, tempHist->GetBinError(iBin));
164  tempHist->SetBinError(iBin,
165  TMath::Sqrt(pow(tempHist->GetBinError(iBin), 2) +
166  content * content * uncSquared));
167  Message(eDebug, "For hist %s, bin %i after: %f +- %f",
168  tempName.Data(), iBin, content, tempHist->GetBinError(iBin));
169  }
170  delete uncProfile;
171  }
172 
173  Message(eDebug, "Number of events: %i, integral: %f",
174  (Int_t) tempHist->GetEntries(), tempHist->Integral("width"));
175 
176  theHists.push_back(tempHist);
177  }
178 
179  if (fEventsPer > 0) {
180  Message(eDebug, "Events per: %f", fEventsPer);
181 
182  TString tempName;
183  tempName.Form("Hist_%d", fPlotCounter);
184  fPlotCounter++;
185  tempHist = new TH1D(tempName, tempName, NumXBins, XBins);
186  for (Int_t iBin = 1; iBin != NumXBins + 1; ++iBin)
187  tempHist->SetBinContent(iBin, tempHist->GetBinWidth(iBin)/fEventsPer);
188 
189  SetZeroError(tempHist);
190  for (UInt_t iHist = 0; iHist != theHists.size(); ++iHist) {
191  Message(eDebug, "Now for %s, number of events: %i, integral: %f",
192  theHists[iHist]->GetName(),
193  (Int_t) tempHist->GetEntries(),
194  tempHist->Integral("width"));
195 
196  Division(theHists[iHist], tempHist);
197  }
198 
199  delete tempHist;
200  }
201 
202  if (fNormalizedHists) {
203  Double_t normInt = 1;
204  if (fNormalizeTo != -1)
205  normInt = theHists[fNormalizeTo]->Integral("width");
206 
207  for (UInt_t iHist = 0; iHist != NumPlots; ++iHist)
208  theHists[iHist]->Scale(normInt/theHists[iHist]->Integral("width"));
209  }
210 
211  for (UInt_t iUncert = 0; iUncert != fSysUncIndices.size(); ++iUncert)
212  ApplyUncertainty(theHists[fSysUncIndices[iUncert]], &(fUncerts[iUncert]));
213 
214  for (auto* hist : theHists)
215  Message(eInfo, "Mean: %f, StdDev: %f", hist->GetMean(), hist->GetStdDev());
216 
217  return theHists;
218 }
219 
220 //--------------------------------------------------------------------
221 std::vector<TH1D*>
222 PlotHists::MakeHists(Int_t NumXBins, Double_t MinX, Double_t MaxX)
223 {
224  Double_t XBins[NumXBins+1];
225  ConvertToArray(NumXBins, MinX, MaxX, XBins);
226  return MakeHists(NumXBins, XBins);
227 }
228 
229 //--------------------------------------------------------------------
230 void
231 PlotHists::MakeCanvas(TString FileBase, Int_t NumXBins, Double_t *XBins,
232  TString XLabel, TString YLabel, Bool_t logY)
233 {
234  std::vector<TH1D*> hists = MakeHists(NumXBins, XBins);
235  BaseCanvas(FileBase, hists, XLabel, YLabel, logY);
236 
237  for (UInt_t i0 = 0; i0 != hists.size(); ++i0)
238  delete hists[i0];
239 }
240 
241 //--------------------------------------------------------------------
242 void
243 PlotHists::MakeCanvas(TString FileBase, Int_t NumXBins, Double_t MinX, Double_t MaxX,
244  TString XLabel, TString YLabel, Bool_t logY)
245 {
246  Double_t XBins[NumXBins+1];
247  ConvertToArray(NumXBins, MinX, MaxX, XBins);
248  MakeCanvas(FileBase, NumXBins, XBins, XLabel, YLabel, logY);
249 }
250 
251 #endif