FairRoot/PandaRoot
findcuts.C
Go to the documentation of this file.
1 // --------------------------------------------------------------------------------------
2 //
3 // ******** LOAD with '.L findcuts.C+' to use as function in CINT ********
4 //
5 // Tool to find good selection for signal vs bkg. Ranks variables according to maximum (S*ws)^2/(S*ws+B*wb) on optionally normalised distributions.
6 // Double click on a pad applies corresponding cut and re-iterates.
7 //
8 // USAGE: findcuts(TTree *t, TString ctlvar, TString sigcut, TString bnames, TString precut, int numvars, double ws, double wb, int norm)
9 //
10 // t : tree containing signal and background; if given as only argument, list of available branches are printed.
11 // ctlvar : control variable to check signal quality (e.g. invariant mass); displayed in upper left pad; excluded from branch list.
12 // sigcut : cut to isolate signal; background is selected with !(sigcut).
13 // bnames : blank separated list of branch variable names to be considered; can make use of name* / *name /*name*; !(*)name(*) excludes variables (default = '*').
14 // precut : cut to be applied before variable ranking is done (default = '').
15 // numvars : number of variables to be displayed (default = 9).
16 // ws, wb : weight factors for signal & background (default = 1.0); are applied to spectra and calculations after optional normalisation.
17 // norm : normalisation of distributions before ranking (-> pdf) (default = 1.0); double click in control variable pad toggles and reruns.
18 // bins : number of histogram bins, precision depending on binning (default = 500)
19 //
20 // --------------------------------------------------------------------------------------
21 
22 #include <algorithm>
23 #include <iostream>
24 #include <map>
25 #include <vector>
26 
27 #include "TFile.h"
28 #include "TTree.h"
29 #include "TString.h"
30 #include "TH1F.h"
31 #include "TCanvas.h"
32 #include "TROOT.h"
33 #include "TEventList.h"
34 #include "TDirectory.h"
35 #include "TLine.h"
36 #include "TArrow.h"
37 #include "TStyle.h"
38 #include "TObjArray.h"
39 #include "TRegexp.h"
40 
41 typedef std::vector<TString> StrVec;
42 
43 typedef std::map<double, TString> DblStrMap;
44 typedef std::map<double, TString>::iterator DblStrMapIt;
45 
46 typedef std::map<TString, double> StrDblMap;
47 
48 typedef std::map<TString, int> StrIntMap;
49 typedef std::map<TString, int>::iterator StrIntMapIt;
50 
51 TCanvas *c1; // canvas to display variables
52 TEventList *els, *elb, *elpre; // event lists for signal/background/all
53 TTree *t; // the TTree
54 
55 int N0s, N0b; // initial signal/background count
56 int Ns, Nb; // signal/background count after preselection
57 double Wsig, Wbkg; // signal/background weights for computing S^2/(S+B)
58 TString comtemplate, comcurrent;// template command string for the TExec; and current command string
59 bool normalize; // flag for possible normalisation
60 int BINS; // histogram bins
61 
62 StrVec bnam; // vector containing the branch names to be analysed
63 DblStrMap qamap; // maps QA value -> cut
64 StrDblMap sigeff, bkgeff; // maps cut -> signal/background efficiency
65 
66 // -------------------------------------------
67 // Routine to print out the usage of this tool
69 {
70  cout <<"\nfindcuts: Tool to find good selection for signal vs bkg. Ranks variables according to maximum (S*ws)^2/(S*ws+B*wb) on optionally normalised distributions.\n";
71  cout <<" Double click on a pad applies corresponding cut and re-iterates.\n\n";
72  cout <<"USAGE:\nfindcuts(TTree *t, TString ctlvar, TString sigcut, TString bnames, TString precut, int numvars, double qaopt, double ws, double wb, int norm, int bins)\n";
73  cout <<" t : tree containing signal and background; if given as only argument, list of available branches are printed.\n";
74  cout <<" ctlvar : control variable to check signal quality (e.g. invariant mass); displayed in upper left pad; excluded from branch list.\n";
75  cout <<" sigcut : cut to isolate signal; background is selected with !(sigcut).\n";
76  cout <<" bnames : blank separated list of branch/alias variable names to be considered; can make use of name* / *name /*name*; !(*)name(*) excludes variables (default = \"*\").\n";
77  cout <<" precut : cut to be applied before variable ranking is done (default = \"\").\n";
78  cout <<" qaopt : optimisation mode; qaopt=0 : best S/sqrt(S+B); -1<qaopt<0 : best signal eff for fixed bkg reduction; 0<qaopt<1 : best bkg reduction for fixed signal eff. (default = 0).\n";
79  cout <<" numvars : number of variables to be displayed (default = 9).\n";
80  cout <<" ws, wb : weight factors for signal & background (default = 1.0); are applied to spectra and calculations after optional normalisation.\n";
81  cout <<" norm : normalisation of distributions before ranking (-> pdf) (default = 1); double click in control variable pad toggles 'norm' and reruns.\n";
82  cout <<" bins : number of histogram bins, precision depending on binning (default = 500).\n\n";
83  cout <<"Example 0: Print all available branches/aliases in tree:\n";
84  cout <<" root [0] findcuts(mytree)\n\n";
85  cout <<"Example 1: Analyse all branches in TTree 'mytree', control variable 'mass', and signal cut 'issignal':\n";
86  cout <<" root [0] findcuts(mytree, \"mass\", \"issignal\")\n\n";
87  cout <<"Example 2: Analyse all branches expect 'evcnt', 'run', those ending with 'px', 'py', or 'pz' or containing the word 'fit', after precut 'goodtracks>6&&goodphotons>2'\n";
88  cout <<" root [0] findcuts(mytree, \"mass\", \"issignal\", \"* !evcnt !run !*p[xyz] !*fit*\", \"goodtracks>6&&goodphotons>2\")\n\n";
89  return;
90 }
91 
92 // -------------------------------------------
93 // Splits a TString into vector of strings; separation character contained in delim
94 int FCSplitString(TString s, TString delim, StrVec &toks)
95 {
96  toks.clear();
97  TObjArray *tok = s.Tokenize(delim);
98  int N = tok->GetEntries();
99  for (int i=0;i<N;++i)
100  {
101  TString token = (((TObjString*)tok->At(i))->String()).Strip(TString::kBoth);
102  toks.push_back(token);
103  }
104  return toks.size();
105 }
106 
107 // -------------------------------------------
108 // Prepares the list of branches under consideration
109 // bnames contains branch list with jokers like *name or !*name* et
110 // branch ctlvar will be enabled for plotting, but excluded from the ranking list
111 // also takes into account aliases of TTree
112 void FCPrepareTree(TString bnames, TString ctlvar)
113 {
114  // Separate names of branches to be considered
115  StrVec vecpatt, vecali;
116  FCSplitString(bnames," ", vecpatt);
117 
118  // Enable/disable branches
119  t->SetBranchStatus("*",0);
120  bnam.clear(); // this array will contain the names of variables (branches and aliases) to be checked
121 
122  // ******** BRANCHES
123 
124  // Enable/disable branches according to list of patterns in vecpatt
125  for (uint i=0;i<vecpatt.size();++i)
126  if (vecpatt[i].BeginsWith("!")) t->SetBranchStatus(TString(vecpatt[i](1,1000)),0);
127  else t->SetBranchStatus(vecpatt[i],1);
128 
129  // for preparing list disable ctlvar
130  if (ctlvar!="") t->SetBranchStatus(ctlvar,0);
131 
132  // Create a vector with all variables to be considered
133  TObjArray* blist = t->GetListOfBranches();
134  for (int i=0; i<=blist->GetLast(); ++i)
135  {
136  TString name = ((TBranch*)blist->UncheckedAt(i))->GetName();
137  // Add branch name to list, excludes the control variable
138  if (t->GetBranchStatus(name)>0) bnam.push_back(name);
139  }
140 
141  // for sure enable branch with ctlvar
142  if (ctlvar!="") t->SetBranchStatus(ctlvar,1);
143 
144  // ******** ALIASES
145 
146  // now we still need to check the list of aliases and enable the branches connected
147  StrIntMap alimap; // this serves as a marker map for the active aliases
148  TList *alilist = t->GetListOfAliases();
149 
150  // Are there aliases defined?
151  if (alilist)
152  {
153  // loop through all patterns
154  for (uint i=0;i<vecpatt.size();++i)
155  {
156  // first create the regular exp to identify the aliases matching the patterns
157  TString patt = vecpatt[i];
158  patt.ReplaceAll("*",".*");
159  int toggle = 1; // switch the alias on (1) or off (0) ?
160  if (patt.BeginsWith("!")) {toggle = 0; patt=patt(1,1000);}
161  TRegexp regali(patt);
162 
163  // save the alias status (on or off) in the map
164  // therefore loop through alias list and toggle all those to either on or off, which match the pattern
165  for (int j=0; j<=alilist->GetLast(); ++j)
166  {
167  TString aliname = ((TNamed*)alilist->At(j))->GetName();
168  if (aliname(regali)!="") alimap[aliname] = toggle;
169  }
170  }
171 
172  // loop through map to save the enabled aliases in the bnam vector
173  StrIntMapIt it = alimap.begin();
174  while (it != alimap.end())
175  {
176  if (it->second) { vecali.push_back(it->first); bnam.push_back(it->first); }
177  it++;
178  }
179 
180  // now we finally need to enable all branches connected to one of the enabled aliases
181  for (uint i=0;i<vecali.size();++i)
182  {
183  // get the formula to the enabled alias
184  TString fml = t->GetAlias(vecali[i]);
185  //cout << "Alias "<<vecali[i]<<" -> "<<fml<<endl;
186  TRegexp regvar("[A-Za-z_][A-Za-z_0-9]*");
187  while (fml(regvar)!="")
188  {
189  TString sbr = fml(regvar);
190  if (t->GetBranch(sbr)) {t->SetBranchStatus(sbr,1);}
191  fml.Replace(fml.Index(sbr),sbr.Length(),"");
192  }
193  }
194  }
195 
196  // ******** REPORT
197 
198  // Print out all branches found
199  cout<<"**** Name pattern: \""<<bnames<<"\""<<endl;
200  cout<<"**** "<<bnam.size()<<" branches/aliases found: \n";
201  for (uint i=0;i<bnam.size();++i)
202  printf("%s ",bnam[i].Data());
203 
204  cout <<endl;
205 }
206 
207 // -------------------------------------------
208 // Determines the minimum and maximum value for variable named var for current selecion (for histograms)
209 bool FCFindLimits(TString var, double &min, double &max)
210 {
211  // consider signal and background after precut
212  t->SetEventList(elpre);
213  // draw into a dummy histogram; this creates value vectors in the tree
214  int nsel = t->Draw(var+">>hhh","","goff");
215  t->SetEventList(0);
216 
217  if (nsel>500000) nsel=500000;
218  TH1F *h = (TH1F*)gDirectory->Get("hhh");
219  // if no entry left return
220  if (h->GetEntries()==0) return false;
221 
222  // now determine the limits; therefore loop through TTree::GetV1()
223  // being a vector with the values of var
224  min=100000., max=-100000.;
225  double *x=t->GetV1();
226  for (int i=0;i<nsel;++i)
227  {
228  if (x[i]>max) max=x[i];
229  if (x[i]<min) min=x[i];
230  }
231  // increase the upper limit by a tiny value to include this largest value
232  // in the uppermost bin, which has a high bin edge '< max', not '<= max'
233  max+=1e-6;
234  return true;
235 }
236 
237 // -------------------------------------------
238 // Compute significance
239 double FCSfc(double S, double B)
240 {
241  return S/sqrt(S+B);
242 }
243 
244 // -------------------------------------------
245 // The QA routine. It finds the best value ws*ws*S*S/(ws*S +wb*B) for cuts from left and right
246 // It stores the found cut strings in the qamap
247 double FCQaVar(TString var, double qaopt=0)
248 {
249  double xmin, xmax;
250 
251  if (FCFindLimits(var, xmin, xmax))
252  {
253  TH1F h1("h1","",BINS,xmin,xmax);
254  TH1F h2("h2","",BINS,xmin,xmax);
255 
256  // Fill histograms for var
257 
258  // signal histo
259  t->SetEventList(els);
260  t->Draw(var+">>h1","","goff");
261 
262  // background histogram
263  t->SetEventList(elb);
264  t->Draw(var+">>h2","","goff");
265 
266  // normalize histograms (if not significance optimisation, do anyways!)
267  if (normalize || fabs(qaopt)>0.0001)
268  {
269  h1.Scale(1./h1.GetEntries());
270  h2.Scale(1./h2.GetEntries());
271  }
272 
273  // multiply histos with weights (only for significance optimisation)
274  if (fabs(qaopt)<0.0001) {h1.Scale(Wsig); h2.Scale(Wbkg);}
275  double h1ent = h1.Integral(), h2ent = h2.Integral();
276 
277  // some vars to store the best efficiencies, cuts, partial sums, etc
278  double rsums=0., lsums=0., rsumb=0., lsumb=0.;
279  double bestSr = 0., bestSl=0., bestCutl=0., bestCutr=0., besteffsl=0., besteffbl=0., besteffsr=0., besteffbr=0.;
280 
281  // integrate from both sides
282  for (int i=1;i<=BINS;++i)
283  {
284  // sum the bin contents from left
285  lsums+=h1.GetBinContent(i); // signal
286  lsumb+=h2.GetBinContent(i); // background
287 
288  // sum the bin contents from right
289  rsums+=h1.GetBinContent(BINS-i+1); // signal
290  rsumb+=h2.GetBinContent(BINS-i+1); // background
291 
292  double Sl=0, Sr=0;
293  // compute the significances; weights are already taken into account by scaling the histograms
294  if (abs(qaopt)<1e-8)
295  {
296  Sl = FCSfc(lsums,lsumb);
297  Sr = FCSfc(rsums,rsumb);
298  }
299  // compute the signal efficiency for a certain background suppression
300  else if (qaopt<0)
301  {
302  if (lsumb<=(1.+qaopt)) Sl = lsums;
303  if (rsumb<=(1.+qaopt)) Sr = rsums;
304  }
305  // compute the signal efficiency for a certain background suppression
306  else
307  {
308  if (lsums>=qaopt) Sl = 1.-lsumb;
309  if (rsumb>=qaopt) Sr = 1.-rsumb;
310  }
311 
312  // find the best ones
313  if (Sl>bestSl) {bestSl=Sl; besteffsl=lsums/h1ent; besteffbl=lsumb/h2ent; bestCutl=h1.GetBinLowEdge(i+1);}
314  if (Sr>bestSr) {bestSr=Sr; besteffsr=rsums/h1ent; besteffbr=rsumb/h2ent; bestCutr=h1.GetBinLowEdge(BINS-i+1);}
315  }
316 
317  // create cut strings
318  TString lcut = TString::Format("%s<%f",var.Data(),bestCutl);
319  TString rcut = TString::Format("%s>%f",var.Data(),bestCutr);
320 
321  // and store in map with 1/(QA value) as key (since map is sorted in increasing order)
322  double invqal = 1./bestSl, invqar = 1./bestSr;
323 
324  // if a cut with the same qa exists, insignificantly increase
325  // current values slightly for being able to store them; otherwise map entries are replaced
326  int maxsearch = 100;
327  while (qamap.find(invqal)!=qamap.end() && --maxsearch>0) invqal = 1./(1./invqal+0.0001);
328 
329  maxsearch = 100;
330  while (qamap.find(invqar)!=qamap.end() && --maxsearch>0) invqar = 1./(1./invqar+0.0001);
331 
332  // store the qa -> cut combination for left and right cut
333  qamap[invqal] = lcut;
334  qamap[invqar] = rcut;
335 
336  // store the corresponding efficiency values
337  sigeff[lcut] = besteffsl;
338  bkgeff[lcut] = besteffbl;
339  sigeff[rcut] = besteffsr;
340  bkgeff[rcut] = besteffbr;
341  }
342 
343  return 0;
344 }
345 
346 // -------------------------------------------
347 // Initialize style and find TCanvas if existing
348 // and set the event lists
349 void FCInit(int numvars)
350 {
351  gStyle->SetTitleFontSize(0.08);
352  gStyle->SetPadTopMargin(0.08);
353  gStyle->SetOptStat(0);
354 
355  t->SetEventList(0);
356  t->SetBranchStatus("*",1);
357 
358  // configure the TCanvas division and sizes of histos
359  double plotdim = 250;
360  if (numvars>11) plotdim=200;
361  int cx = numvars+1;
362  if (numvars>4) cx=(numvars+2)/2;
363  if (numvars>11) cx=5;
364  if (numvars>14) cx=6;
365  if (numvars>17) cx=7;
366 
367  int cy = (numvars+1)/cx;
368  if ((numvars+1)%cx) cy+=1;
369 
370  // refetch canvas or create a new one
371  c1=(TCanvas*)gROOT->FindObject("c1");
372  if (c1==0) c1 = new TCanvas("c1","c1",5,5,1000,650);
373  c1->Clear();
374  c1->Divide(cx, cy);
375  c1->SetWindowSize(cx*plotdim, cy*plotdim*1.1);
376 
377  // refetch event lists if existing or create new ones
378  els = (TEventList*)gROOT->FindObject("els");
379  if (els==0) els = new TEventList("els");
380 
381  elb = (TEventList*)gROOT->FindObject("elb");
382  if (elb==0) elb = new TEventList("elb");
383 
384  elpre = (TEventList*)gROOT->FindObject("elpre");
385  if (elpre==0) elpre = new TEventList("elpre");
386 }
387 
388 // -------------------------------------------
389 // Displays variable in pad #numpad in standard canvas
390 void FCDrawVariable(TString var, int numpad, int norm=1, TString cut="")
391 {
392  double xmin, xmax;
393 
394  c1->cd(numpad);
395 
396  // if pad #1 (control variable), background color is set differently
397  if (numpad==1)
398  {
399  gPad->SetFrameFillColor(18);
400  TString com = TString::Format(comcurrent.Data(),!normalize); // toggle normalize
401  gPad->AddExec("ex1","if (gPad->GetEvent()==kButton1Double) { cout<<endl<<\" -> Toggle normalize setting.\"<<endl;"+com+";}");
402  }
403 
404  // for all other pads a TExec is added which when clicked applies
405  // the corresponding cut
406  if (numpad!=1)
407  {
408  // create the command string from the template string
409  TString com = comtemplate;
410  // isolate the part "var>" or "var<" from the full cut string;
411  // this is to replace a previous cut on identical variable and direction (<,>)
412  TString cutpart = cut(0,max(cut.Index(">"),cut.Index("<"))+1);
413  TRegexp r1(cutpart+"[-]*[0-9]*.[0-9]*");
414  TString oldcut = com(r1);
415 
416  // if there was no such identical variable cut, just replace the
417  // keyword 'NEWCUT' in template with the new cut string
418  if (oldcut=="") com.ReplaceAll("NEWCUT",cut);
419  else // otherwise replace old cut with new cut and remove 'NEWCUT' or '&&NEWCUT' from template
420  {
421  com.ReplaceAll(oldcut,cut);
422  com.ReplaceAll("&&NEWCUT","");
423  com.ReplaceAll("NEWCUT","");
424  }
425  // finally add TExec to the current pad
426  gPad->AddExec("ex1","if (gPad->GetEvent()==kButton1Double) { cout<<endl<<\" -> Applying '"+cut+"'\"<<endl;"+com+";}");
427  }
428 
429  // set title for histogram
430  TString title = cut;
431  if (title=="") title=var;
432 
433  // prepare line and arrow for drawing cut
434  TLine ln;
435  ln.SetLineColor(6); ln.SetLineStyle(7); ln.SetLineWidth(2);
436 
437  TArrow arr;
438  arr.SetAngle(40); arr.SetLineWidth(2); arr.SetLineColor(6); arr.SetFillColor(6);
439 
440  bool drawcut = (cut!="");
441  int cutdir = cut.Contains("<") ? -1 : 1 ;
442 
443  // determind value of cut for displaying the line and arrow
444  double cutval = drawcut ? TString(cut(max(cut.Index(">"),cut.Index("<"))+1,1000)).Atof() : -999.;
445 
446  if (FCFindLimits(var, xmin, xmax))
447  {
448  // histograms for signal and background
449  TH1F h1("h1",title,BINS,xmin,xmax);
450  TH1F h2("h2",title,BINS,xmin,xmax);
451  // and the sum
452  TH1F hs("hs",title,BINS,xmin,xmax);
453 
454  h1.SetLineColor(4);
455  h2.SetLineColor(2);
456  hs.SetLineColor(1);
457 
458  // fill histograms
459  t->SetEventList(els);
460  t->Draw(var+">>h1");
461  t->SetEventList(elb);
462  t->Draw(var+">>h2");
463 
464  // otherwise normalize histos
465  if (norm)
466  {
467  h1.Scale(1./h1.GetEntries());
468  h2.Scale(1./h2.GetEntries());
469  }
470  h1.Scale(Wsig); h2.Scale(Wbkg);
471 
472  // if we want no normalization fill a summed histogram
473  if (!norm) {hs.Add(&h1);hs.Add(&h2);}
474 
475  // set maximum of both histos to display full y-range
476  double maxi = 1.05*max(h1.GetMaximum(), h2.GetMaximum());
477  if (!norm) maxi = hs.GetMaximum()*1.05;
478  h1.SetMaximum(maxi);
479  h2.SetMaximum(maxi);
480 
481  if (!norm) hs.DrawCopy();
482  h1.DrawCopy(norm?"":"same");
483  h2.DrawCopy("same");
484 
485  // draw the cut with direction arrow if requested
486  if (drawcut)
487  {
488  ln.DrawLine(cutval,0,cutval,maxi*0.9);
489  arr.DrawArrow(cutval,maxi*0.9,cutval+0.1*(xmax-xmin)*cutdir,maxi*0.9,0.01,"|>");
490  }
491  }
492 
493  c1->cd();
494 }
495 
496 // -------------------------------------------
497 // The main function
498 // -------------------------------------------
499 int findcuts(TTree *theTree=0, TString ctlvar="", TString sigcut="", TString bnames="", TString precut="", int numvars=9, double qaopt=0., double ws=1., double wb=1., int norm=1, int bins=500)
500 {
501  // if no argument given, print usage information
502  if (theTree==0) {FCPrintInfo();return;}
503  t=theTree;
504 
505  // check for reasonable qaopt parameter -1<qaopt<1
506  if (qaopt<-1) qaopt=-1;
507  if (qaopt>1) qaopt=1;
508  cout <<"\nOptimising for ";
509  if (qaopt<0) cout <<"best signal effciency for given background reduction of "<<fabs(qaopt)<<endl;
510  if (qaopt>0) cout <<"best background reduction for given signal efficiency of "<<qaopt<<endl;
511  else cout <<"best significance S/sqrt(S+B)"<<endl;
512 
513  // set defaults for some parameters
514  if (numvars==0) numvars = 9;
515 
516  // print some status information about the TTree
517  TString tname = t->GetName();
518  cout <<"\nTTree : "<<tname<<"\nEvents total : "<<t->GetEntriesFast()<<"\nBranches total : "<<t->GetNbranches()<<"\nAliases total : ";
519  cout<< (t->GetListOfAliases() ? t->GetListOfAliases()->GetSize() : 0) <<endl;
520 
521  // the current command string; will be printed at the end
522  comcurrent = TString::Format("findcuts(%s,\"%s\",\"%s\",\"%s\",\"%s\",%d,%.3f,%.3f,%.3f,%%d,%d)",
523  tname.Data(),ctlvar.Data(), sigcut.Data(),bnames.Data(),precut.Data(),numvars, qaopt, ws, wb, bins);
524 
525  // The template string for pasting the new cut in
526  comtemplate = TString::Format("findcuts(%s,\"%s\",\"%s\",\"%s\",\"%s%sNEWCUT\",%d,%.3f,%.3f,%.3f,%d,%d)",
527  tname.Data(), ctlvar.Data(), sigcut.Data(),bnames.Data(),precut.Data(),precut==""?"":"&&",numvars, qaopt, ws, wb, norm, bins);
528 
529  // catch some special cases
530  // if no sigcut is provided, only the list of branches is printed out
531  bool printonly = (sigcut=="");
532 
533  // empty string for branch names defaults to all branches -> '*'
534  if (bnames=="") bnames="*";
535  if (precut=="") precut="1";
536  Wsig = ws; Wbkg = wb;
537 
538  // rank with normalized spectra; else use real event numbers
539  normalize = norm;
540  BINS = bins;
541 
542  // prepare signal and background cut
543  TString bkgcut = "!("+sigcut+")";
544  TString sfull = precut+"&&"+sigcut;
545  TString bfull = precut+"&&"+bkgcut;
546 
547  // prepare event lists for signal and background
548  if (!printonly)
549  {
550  // refetch canvas and eventlists
551  FCInit(numvars);
552 
553  t->Draw(">>els",sfull);
554  t->Draw(">>elb",bfull);
555  t->Draw(">>elpre",precut);
556 
557  Ns = els->GetN();
558  Nb = elb->GetN();
559  N0s = t->GetEntries(sigcut);
560  N0b = t->GetEntries(bkgcut);
561 
562  cout <<"Events selected : "<<elpre->GetN()<<endl;
563  }
564  cout <<endl;
565 
566  // select variables and fill StrVec bnam with selected branch names
567  // ctlvar will be excluded from the ranking
568  FCPrepareTree(bnames,ctlvar);
569 
570  if (printonly) return;
571 
572  if (t->GetBranch(ctlvar)==0) {cout <<"**** Unknown control variable: "<<ctlvar<<endl<<endl; return;}
573 
574  // Draw the control variable in 1st pad
575  if (ctlvar!="") FCDrawVariable(ctlvar,1,0,"ctlvar: "+ctlvar);
576 
577  // if at least one event signal and background is left do ranking
578  if (Nb>0 && Ns>0)
579  {
580  // prepare the map for ranking
581  qamap.clear();
582 
583  // print progress bar and prepare some variables
584  cout <<"+-----------+-----------+\n";
585  double ticks = 0;
586 
587  // **** do the actual ranking procedure by analysing all variables
588  for (uint i=0;i<bnam.size();++i)
589  {
590  if (bnam[i]!=ctlvar) FCQaVar(bnam[i], qaopt);
591  // print progress bar
592  while ((double)i/(double)bnam.size()>ticks/25.) { cout <<"#"<<flush; ticks++; }
593  }
594  cout <<endl<<endl;
595 
596  // print out and display the results. qamap is sorted by its key being the qa value itself!
597  DblStrMapIt it = qamap.begin();
598  int cnt=0;
599 
600  while (it != qamap.end() && cnt++<numvars)
601  {
602  double qa = it->first;
603  TString cut = it->second;
604 
605  if (sigeff[cut]<=bkgeff[cut]) continue;
606 
607  printf("(%2d) %-25s : qa = %6.3f (eff_s = %5.3f, eff_b = %5.3f)\n", cnt, cut.Data(), 1./qa, sigeff[cut], bkgeff[cut]);
608 
609  // isolate the variable name from the cut and plot
610  TString var = cut(0,max(cut.Index(">"),cut.Index("<")));
611  FCDrawVariable(var,cnt+1,normalize,cut);
612 
613  ++it;
614  }
615  }
616  else cout <<"\n**** No "<<(Nb==0?"background":"signal")<<" events left. No ranking possible."<<endl;
617 
618  t->SetBranchStatus("*",1);
619  t->SetEventList(0);
620 
621  // the current command string; will be printed at the end
622  cout <<"\nCommand:\n"<<TString::Format(comcurrent.Data(),normalize)<<endl;
623 
624  // print efficiency values
625  double effs = (double)Ns/N0s, effb = (double)Nb/N0b;
626  double qa = normalize ? FCSfc(ws*effs, wb*effb) : FCSfc(ws*Ns, wb*Nb);
627  double pur = normalize ? ws*effs/(ws*effs+wb*effb) : ws*Ns/(ws*Ns+wb*Nb);
628  printf("\nEFF_S = %5.3f (%d/%d) EFF_B = %5.3f (%d/%d) PUR = %5.3f S/sqrt(S+B) %s= %6.3f\n",effs, Ns, N0s, effb, Nb, N0b, pur, normalize?"norm'd ":"", qa);
629 
630  c1->cd(); c1->Update();
631  return 0;
632 }
633 
int FCSplitString(TString s, TString delim, StrVec &toks)
Definition: findcuts.C:94
printf("RealTime=%f seconds, CpuTime=%f seconds\n", rtime, ctime)
TEventList * els
Definition: findcuts.C:52
Int_t i
Definition: run_full.C:25
DblStrMap qamap
Definition: findcuts.C:63
void FCPrepareTree(TString bnames, TString ctlvar)
Definition: findcuts.C:112
friend F32vec4 sqrt(const F32vec4 &a)
Definition: P4_F32vec4.h:29
bool FCFindLimits(TString var, double &min, double &max)
Definition: findcuts.C:209
TLorentzVector s
Definition: Pnd2DStar.C:50
Double_t xmax
friend F32vec4 max(const F32vec4 &a, const F32vec4 &b)
Definition: P4_F32vec4.h:26
double r1
void FCInit(int numvars)
Definition: findcuts.C:349
TString comtemplate
Definition: findcuts.C:58
int Ns
Definition: findcuts.C:56
std::map< TString, int > StrIntMap
Definition: findcuts.C:48
TCanvas * c1
Definition: findcuts.C:51
int findcuts(TTree *theTree=0, TString ctlvar="", TString sigcut="", TString bnames="", TString precut="", int numvars=9, double qaopt=0., double ws=1., double wb=1., int norm=1, int bins=500)
Definition: findcuts.C:499
std::map< int, double > effb
Definition: simubg.C:29
double Wbkg
Definition: findcuts.C:57
double cut[MAX]
Definition: autocutx.C:36
StrDblMap sigeff
Definition: findcuts.C:64
TEventList * elpre
Definition: findcuts.C:52
void FCPrintInfo()
Definition: findcuts.C:68
TString comcurrent
Definition: findcuts.C:58
std::map< double, TString > DblStrMap
Definition: findcuts.C:43
int Nb
Definition: findcuts.C:56
TTree * t
Definition: findcuts.C:53
friend F32vec4 min(const F32vec4 &a, const F32vec4 &b)
Definition: P4_F32vec4.h:25
friend F32vec4 fabs(const F32vec4 &a)
Definition: P4_F32vec4.h:47
std::vector< TString > StrVec
TString name
std::vector< TString > StrVec
Definition: findcuts.C:41
int N0b
Definition: findcuts.C:55
StrDblMap bkgeff
Definition: findcuts.C:64
StrVec bnam
Definition: findcuts.C:62
std::map< TString, double > StrDblMap
Definition: findcuts.C:46
int cy
Definition: dedx_bands.C:17
void FCDrawVariable(TString var, int numpad, int norm=1, TString cut="")
Definition: findcuts.C:390
std::map< int, double > effs
Definition: simubg.C:29
double FCQaVar(TString var, double qaopt=0)
Definition: findcuts.C:247
Double_t x
double FCSfc(double S, double B)
Definition: findcuts.C:239
TEventList * elb
Definition: findcuts.C:52
int N0s
Definition: findcuts.C:55
Int_t cnt
Definition: hist-t7.C:106
int cx
Definition: dedx_bands.C:16
std::map< double, TString >::iterator DblStrMapIt
Definition: findcuts.C:44
Double_t xmin
std::map< TString, int >::iterator StrIntMapIt
Definition: findcuts.C:49
double Wsig
Definition: findcuts.C:57
bool normalize
Definition: findcuts.C:59
int BINS
Definition: findcuts.C:60