HighLAND
DrawingUtils.cxx
1 #include "DrawingUtils.hxx"
2 #include <sstream>
3 
4 std::map<std::string, std::string> _options;
5 
6 double drawUtils::legendEntryHeight=0.05;
7 
8 //*********************************************************
9 std::string drawUtils::ToUpper(const std::string& str) {
10 //*********************************************************
11  TString tstr(str);
12  tstr.ToUpper();
13  return tstr.Data();
14 }
15 
16 //*********************************************************
17 bool drawUtils::TreeHasVar(TTree* tree, const std::string& var){
18 //*********************************************************
19 
20  if (tree->FindLeaf(var.c_str()))
21  return true;
22  else
23  return false;
24 }
25 
26 //*********************************************************
27 int drawUtils::GetVarFromTree(TTree* tree, const std::string& var){
28 //*********************************************************
29 
30  if (!TreeHasVar(tree,var)) return 0;
31 
32  TH1_h h0("v","v",1,0,1);
33  tree->Project("v","0.5",("(1==1)*"+var).c_str(),"",1);
34  return (int)(h0.GetBinContent(1));
35 }
36 
37 //*********************************************************
38 int drawUtils::GetNWeights(TTree* tree){
39 //*********************************************************
40  return GetVarFromTree(tree,"NWEIGHTS");
41 }
42 
43 //*********************************************************
44 int drawUtils::GetNToys(TTree* tree){
45 //*********************************************************
46 
47  return drawUtils::GetVarFromTree(tree,"NTOYS");
48 }
49 
50 //*********************************************************
51 int drawUtils::GetRefToy(TTree* tree){
52 //*********************************************************
53 
54  return drawUtils::GetVarFromTree(tree,"toy_ref");
55 }
56 
57 //*********************************************************
58 int drawUtils::GetVarFromExperiment(const std::string& var, Experiment& exp, const std::string& groupName, const std::string& mcSampleName){
59 //*********************************************************
60 
61  int value=-1;
62 
63  // Loop over SampleGroup's in the experiment
64  std::map< std::string, SampleGroup >::iterator it;
65  for (it = exp.GetSampleGroups().begin(); it != exp.GetSampleGroups().end(); it++) {
66  const std::string& groupName2 = it->first;
67  if (groupName2 != groupName && groupName!="all") continue;
68  SampleGroup& sampleGroup = it->second;
69 
70  // Love over MC samples in the sample group
71  std::map< std::string, DataSample*>& mcSamples = sampleGroup.GetMCSamples();
72  std::map< std::string, DataSample*>::iterator it;
73  for (it = mcSamples.begin(); it != mcSamples.end(); it++) {
74  const std::string& mcSampleName2 = it->first;
75  if (mcSampleName2 != mcSampleName && mcSampleName!="all") continue;
76  DataSample* sample2 = it->second;
77  if (sample2){
78  Int_t value2 = GetVarFromTree(sample2->GetTree(),var);
79  if (value!=-1 && value2!=value){
80  std::cout << "Experiment has different values for var " << var << "!!!!" << std::endl;
81  return -1;
82  }
83  else value=value2;
84  }
85  }
86  }
87 
88  return value;
89 }
90 
91 //*********************************************************
92 std::string drawUtils::GetString(int code){
93 //*********************************************************
94 
95  std::stringstream scode;
96  scode << code;
97 
98  return scode.str();
99 }
100 
101 //*********************************************************
102 std::string drawUtils::GetString(double code){
103 //*********************************************************
104 
105  std::stringstream scode;
106  scode << code;
107 
108  return scode.str();
109 }
110 
111 
112 //*********************************************************
113 void drawUtils::NormalizeVariableBinning(TH1* h, int mode, const std::string& uopt, Double_t& wmin){
114 //*********************************************************
115 
116  // mode = 0 --> do nothing
117  // mode = 1 --> Normalize content
118  // mode = 2 --> Normalize content and error
119 
120  //----- This is to properly normalized bins with different width -------
121 
122 
123  // TODO. For some reason the bin error must be set, otherwise the histo appears empty when using NOVARBIN option
124  if (uopt.find("NOVARBIN")!=std::string::npos || mode==0){
125  for (int i=0;i<h->GetNbinsX();i++)
126  h->SetBinError(i+1, h->GetBinError(i+1));
127  return;
128  }
129 
130  int entries = (int)h->GetEntries();
131 
132  // Get the bin with minimum width
133  if (uopt.find("USEMINWIDTH")==std::string::npos){
134  wmin=1e6;
135  for (int i=0;i<h->GetNbinsX();i++){
136  Double_t w = h->GetXaxis()->GetBinWidth(i+1);
137  if (w<wmin && h->GetBinContent(i+1)>0) wmin=w;
138  }
139  }
140  int dim = 1;
141  Double_t ymax=-1e16;
142 
143  if(h->GetNbinsY() > 1)
144  dim = 2;
145 
146  // That bin will have normalization 1 and the others with width w normalization wmin/w
147  if(dim == 1){
148  for (int i=0;i<h->GetNbinsX();i++){
149  Double_t w = h->GetBinWidth(i+1);
150  Double_t y = h->GetBinContent(i+1);
151 
152  if (y==0) continue;
153  Double_t yp = y*(wmin/w);
154  h->SetBinContent(i+1,yp);
155 
156  if (y>ymax) ymax=y;
157 
158  // normalize the bin error when requested
159  if (mode==2){
160  Double_t e = h->GetBinError(i+1);
161  Double_t ep = e*(wmin/w);
162  h->SetBinError(i+1,ep);
163 
164  }
165  }
166  }else if(dim == 2){
167  TH2 *h2 = (TH2*)h;
168 
169  double amin=1e6;
170  for (int i = 0; i < h->GetNbinsX(); i++){
171  for(int j = 0; j < h2->GetNbinsY(); j++){
172  Double_t wx = h2->GetXaxis()->GetBinWidth(i+1);
173  Double_t wy = h2->GetYaxis()->GetBinWidth(j+1);
174  Double_t a = wx * wy;
175  if (a < amin && h2->GetBinContent(h2->GetBin(i+1,j+1)) != 0) amin=a;
176  }
177  }
178  for(int i = 0; i < h2->GetNbinsX(); i++){
179  for(int j = 0; j < h2->GetNbinsY(); j++){
180  Double_t wx = h2->GetXaxis()->GetBinWidth(i+1);
181  Double_t wy = h2->GetYaxis()->GetBinWidth(j+1);
182  Double_t y = h2->GetBinContent(h2->GetBin(i+1,j+1));
183 
184  if(y == 0) continue;
185  Double_t yp = y*(amin/(wx*wy));
186  h2->SetBinContent(h2->GetBin(i+1,j+1),yp);
187 
188  if (y > ymax) ymax = y;
189 
190  // normalize the bin error when requested
191  if (mode == 2){
192  Double_t e = h2->GetBinError(i+1);
193  Double_t ep = e*(amin/(wx*wy));
194  h2->SetBinError(h2->GetBin(i+1,j+1),ep);
195  }
196  }
197  }
198  }
199  // must set the original saved number of entries. Otherwise it will use the normalized one
200  h->SetEntries(entries);
201 }
202 
203 //*********************************************************
204 void drawUtils::NormalizeVariableBinning(TH1* h, int mode, const std::string& uopt){
205 //*********************************************************
206 
207  Double_t min_width;
208  NormalizeVariableBinning(h,mode,uopt,min_width);
209 }
210 
211 //*********************************************************
212 bool drawUtils::ContainValidOptions(const std::string& uopt){
213 //*********************************************************
214 
215  char c=' ';
216  size_t pos = 0;
217  int pos_ini = 0;
218  bool valid=true;
219  while(pos!=std::string::npos){
220  pos = uopt.find(c,pos_ini);
221  std::string single_opt = uopt.substr(pos_ini, pos-pos_ini);
222  if (single_opt!=""){
223  if (!IsValidOption(single_opt)) valid=false;
224  }
225  pos_ini=pos+1;
226  }
227 
228  return valid;
229 }
230 
231 //*********************************************************
232 bool drawUtils::CheckOption(const std::string& uopt, const std::string& this_opt){
233 //*********************************************************
234 
235  if (!IsValidOption(this_opt)) return false;
236  if (uopt.find(this_opt)!= std::string::npos) return true;
237  return false;
238 }
239 
240 //*********************************************************
241 bool drawUtils::CheckInternalOption(const std::string& uopt, const std::string& this_opt){
242 //*********************************************************
243 
244  if (uopt.find(this_opt)!= std::string::npos) return true;
245  return false;
246 }
247 
248 //*********************************************************
249 bool drawUtils::CheckOption(const std::string& uopt, OptionEnum this_opt){
250 //*********************************************************
251 
252  if (uopt.find(ConvertOption(this_opt))!= std::string::npos) return true;
253  return false;
254 }
255 
256 //*********************************************************
257 std::string drawUtils::ConvertOption(OptionEnum opt){
258 //*********************************************************
259 
260  if (opt==kNOERROR) return "NOERROR";
261  else if (opt==kAREA) return "AREA";
262  else return "";
263 }
264 
265 //*********************************************************
266 void drawUtils::ExplainOption(OptionEnum opt){
267 //*********************************************************
268 
269  return ExplainOption(ConvertOption(opt));
270 }
271 
272 //*********************************************************
273 void drawUtils::ExplainOption(const std::string& opt){
274 //*********************************************************
275 
276  if (!IsValidOption(opt)) return;
277 
278  char opt2[256];
279  sprintf(opt2,"%-20s", (opt+":").c_str());
280  std::cout << opt2 << _options[opt] << std::endl;
281 }
282 
283 
284 //*********************************************************
285 /// Build the map of valid options with AddOption
287 //*********************************************************
288 
289 //! [DrawingToolsOptions]
290  drawUtils::AddOption("SCALETODATA","Scale the MC covariance matrix to data POT when using Experiment");
291  drawUtils::AddOption("NOCHOP", "??");
292  drawUtils::AddOption("E0", "Error style option for second sample. Does the same as the root option e0");
293  drawUtils::AddOption("E1", "Error style option for second sample. Does the same as the root option e1");
294  drawUtils::AddOption("E2", "Error style option for second sample. Does the same as the root option e2");
295  drawUtils::AddOption("E3", "Error style option for second sample. Does the same as the root option e3");
296  drawUtils::AddOption("E4", "Error style option for second sample. Does the same as the root option e4");
297  drawUtils::AddOption("E5", "Error style option for second sample. Does the same as the root option e5");
298  drawUtils::AddOption("E6", "Error style option for second sample. Does the same as the root option e6");
299  drawUtils::AddOption("ETOT", "When drawing with color codes, draw also the total error for the stacked histogram");
300  drawUtils::AddOption("NOTOTERROR","Don't draw the total error (stat+syst) but only the statistical or systematic error");
301  drawUtils::AddOption("NOSTERROR", "Don't draw the statistical error but only the total error, and also the systematic error when SYSTERROR options is also used");
302  drawUtils::AddOption("SYSTERROR", "Don't draw the statistical error but only the systematic error, together with the total");
303  drawUtils::AddOption("DUMP", "Print on the secreen the histo or graph contents");
304  drawUtils::AddOption("NODRAW", "Don't draw anything. You should use the option DUMP to see the results");
305  drawUtils::AddOption("ST", "When using DrawErrors or DrawRelativeErrors only statistical errors are plotted. In combination with SYS, SSYS or WSYS adds statisticak and systematic errors in quadrature");
306  drawUtils::AddOption("SYS", "draw all systematics. Error bars correspond to the RMS of all toy experiments");
307  drawUtils::AddOption("SSYS", "Draw only standard systematics (reconstructed observable variations)");
308  drawUtils::AddOption("WSYS", "Draw only weight systematics");
309  drawUtils::AddOption("WSi", "Draw only the specified (ith) weight systematic(s) (\" WS0 WS3 ... \")");
310  drawUtils::AddOption("NWSi", "Exclude the specified (ith) weight systematic(s) (\"NWS0 NWS1 ... \")");
311  drawUtils::AddOption("WCi", "Draw only the specified (ith) weight correction(s) (\" WC0 WC3 ... \")");
312  drawUtils::AddOption("NWCi", "Exclude the specified (ith) weight correction(s) (\"NWC0 NWC1 ... \")");
313  drawUtils::AddOption("WCORR", "Apply Weight corrections only (not weight systematics)");
314  drawUtils::AddOption("RELATIVE", "When computing the covariance matrix divide by the average in each bin such that a relative covariance is computed");
315  drawUtils::AddOption("NOLEG", "No legend is drawn");
316  drawUtils::AddOption("PUR", "The purity is printed on the screen and on the legend");
317  drawUtils::AddOption("EFF", "The efficiency-like ratio plot (out of two histograms, pass and total) is drawn, internal option");
318  drawUtils::AddOption("NOST2", "The stat box for the second sample is not shown");
319  drawUtils::AddOption("NOSTAT", "No stat box is shown");
320  drawUtils::AddOption("NOMIN", "The minimum in Y is not used");
321  drawUtils::AddOption("NOVARBIN", "Plotting with variable binning, bin entries are normalized by bin width. This option disables this feature.");
322  drawUtils::AddOption("NOTOYW", "No toy weight is applied for toy experiments. All toys will have the same weight 1.");
323  drawUtils::AddOption("NOW", "None of the weights (flux and pileup) are applied to the event");
324  drawUtils::AddOption("NOFLUXW", "No flux weight is applied to the event");
325  drawUtils::AddOption("NOPILEUPW", "No pile up weight is applied to the event");
326  drawUtils::AddOption("NODATA", "The data is not shown in the plot");
327  drawUtils::AddOption("NOMC", "The MC is not shown in the plot");
328  drawUtils::AddOption("NODEFAULT", "By default the -999 default is plotted unless this option is used");
329  drawUtils::AddOption("UNDER", "Underflow entries are added to the first bin");
330  drawUtils::AddOption("OVER", "Overflow entries are added to the last bin");
331  drawUtils::AddOption("PROFX", "For 2D histos a Profile histogram in X is drawn");
332  drawUtils::AddOption("PROFY", "For 2D histos a Profile histogram in Y is drawn");
333  drawUtils::AddOption("AREA", "For 1D histos normalization to 1 (if there is only one sample) or to the area of the first sample. In this normalization procedure the whole range of the variable allowed by 'cut' parameter is taken into account");
334  drawUtils::AddOption("AREA1", "For 1D histos normalization to 1. In this normalization procedure the whole range of the variable allowed by 'cut' parameter is taken into account");
335  drawUtils::AddOption("AREA100", "For 1D histos normalization to 100. In this normalization procedure the whole range of the variable allowed by 'cut' parameter is taken into account");
336  drawUtils::AddOption("POTNORM", "Normalize the MC to the POT given as input normalization factor, regardless of the data POT (interprete valid norm factor as a POT value)");
337  drawUtils::AddOption("NOPOTNORM", "Disable POT normalization. Second sample is not scaled");
338  drawUtils::AddOption("IGNOREEMPTY", "Do not put categories without entries in the legend");
339  drawUtils::AddOption("DRAWALLMC", "Draw with black contour a histogram for all MC entries (works only while plotting histogram stack)");
340  drawUtils::AddOption("DRAWALLCUTS", "Draw all cuts even if they are below the MinAccumLevelToSave when doing plots VSCuts");
341  drawUtils::AddOption("NOINFO", "Dont dump on the screen histogram info when using the Draw methods");
342  drawUtils::AddOption("SHOWSAND", "Show the sand mu type even when it is empty");
343  drawUtils::AddOption("SHOWNOTRUTH", "Show the NO TRUTH type even when it is empty");
344  drawUtils::AddOption("RATIO", "Draw the Data/MC ratio underneath the stack plot");
345 //! [DrawingToolsOptions]
346 }
347 
348 //*********************************************************
349 void drawUtils::AddOption(const std::string& opt, const std::string& info){
350 //*********************************************************
351 
352  _options[opt]=info;
353 }
354 
355 //*********************************************************
356 bool drawUtils::IsValidOption(const std::string& opt){
357 //*********************************************************
358 
359  if (_options.find(opt)==_options.end()){
360 
361  // Exclude from check WSi and NWSi options since only WS and NWS are declared as options
362  if (opt.find("WS")==0 && opt.find_first_not_of("0123456789",2)==std::string::npos) return true;
363  else if (opt.find("NWS")==0 && opt.find_first_not_of("0123456789",3)==std::string::npos) return true;
364  else if (opt.find("WC")==0 && opt.find_first_not_of("0123456789",2)==std::string::npos) return true;
365  else if (opt.find("NWC")==0 && opt.find_first_not_of("0123456789",3)==std::string::npos) return true;
366 
367  std::cout << "Invalid option '" << opt << "' !!!!" << std::endl;
368  return false;
369  }
370  return true;
371 }
372 
373 
374 //*********************************************************
376 //*********************************************************
377 
378  for (std::map<std::string, std::string>::iterator it=_options.begin();it!=_options.end();it++){
379  ExplainOption(it->first);
380  }
381 }
382 
383 //*********************************************************
384 void drawUtils::AddLegendEntry(TLegend* leg, TObject* ht, const std::string&type, const std::string& opt) {
385 //*********************************************************
386 
387  leg->AddEntry(ht, type.c_str(), opt.c_str());
388 
389  // Otherwise NDC is not set
390  leg->ConvertNDCtoPad();
391 
392  if (legendEntryHeight>0){
393  leg->SetY1NDC(leg->GetY1NDC()-legendEntryHeight);
394  }
395 
396 }
397 
void AddOption(const std::string &opt, const std::string &info)
Add option as valid, provided name and exlaination.
void AddLegendEntry(TLegend *leg, TObject *ht, const std::string &type, const std::string &opt)
Add an entry to the Legend and resize it.
TTree * GetTree(Int_t index)
Returns the a tree with a given index.
Definition: TreeManager.hxx:28
int GetNWeights(TTree *tree)
get the number of weights in the tree
void BuildOptions()
Build the map of valid options with AddOption.
void NormalizeVariableBinning(TH1 *h, int mode, const std::string &opt, Double_t &minwidth)
Normalize bin contents by bin width. return the with of the bin with minimum width.
bool TreeHasVar(TTree *tree, const std::string &var)
Check wether the tree has a given variable.
std::map< std::string, DataSample * > & GetMCSamples()
Get all MC samples in a group.
Definition: Experiment.hxx:50
int GetVarFromTree(TTree *tree, const std::string &var)
Get the Value of an integer variable from the tree.
std::string GetString(int code)
convert integer to string
bool ContainValidOptions(const std::string &uopt)
Check if the input string contails only valid options.
bool IsValidOption(const std::string &opt)
Check if the option is in the list of available options (added with AddOption)
int GetVarFromExperiment(const std::string &var, Experiment &exp, const std::string &groupName="all", const std::string &mcSampleName="all")
Get the Value of an integer variable from the experiment.
void ExplainOption(OptionEnum opt)
Explain a given option given as enum.
void ListOptions()
List sll valid options and a description of each of them.
std::string ToUpper(const std::string &str)
Definition: DrawingUtils.cxx:9
bool CheckInternalOption(const std::string &uopt, const std::string &this_opt)
Check if specific option appears in option field (don&#39;t check if it exists: Added with AddOption) ...
int GetNToys(TTree *tree)
get the number of weights in the tree
int GetRefToy(TTree *tree)
get the reference toy in the tree
std::map< std::string, SampleGroup > & GetSampleGroups()
Returns all sample groups.
Definition: Experiment.hxx:115
std::string ConvertOption(OptionEnum this_opt)
convert enum option to string
bool CheckOption(const std::string &uopt, const std::string &this_opt)
Check if specific option exists, and if so if it appears in option field.