ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/cbrown/AnalysisFramework/Plotting/Modules/GeneralToolBox.C
Revision: 1.59
Committed: Thu Jan 19 08:39:06 2012 UTC (13 years, 3 months ago) by buchmann
Content type: text/plain
Branch: MAIN
CVS Tags: beforeFR20120418, cbaf_4p7ifb
Changes since 1.58: +5 -2 lines
Log Message:
Added --paper switch, which removed 'Preliminary' from plots

File Contents

# User Rev Content
1 buchmann 1.1 #include <iostream>
2 fronga 1.17 #include <iomanip>
3 buchmann 1.1 #include <sstream>
4 buchmann 1.13 #include <fstream>
5 buchmann 1.1 #include <vector>
6     #include <stdio.h>
7     #include <stdlib.h>
8     #include <sys/types.h>
9     #include <sys/stat.h>
10 buchmann 1.15 #include <limits>
11 buchmann 1.43 #include <time.h>
12 buchmann 1.44 #include <sys/types.h>
13     #include <dirent.h>
14 buchmann 1.47 #include <cstdlib>
15     #include <sys/types.h>
16     #include <sys/socket.h>
17     #include <netdb.h>
18     #include <stdio.h>
19     #include <string.h>
20 buchmann 1.1
21     #include <TFile.h>
22     #include <TTree.h>
23     #include <TCut.h>
24     #include <TLegend.h>
25     #include <TLatex.h>
26     #include <TText.h>
27     #include <TGraph.h>
28     #include <TH1.h>
29 buchmann 1.2 #include <TF1.h>
30 buchmann 1.1 #include <TMath.h>
31 buchmann 1.38 #include <THStack.h>
32     #include <TColor.h>
33 buchmann 1.1 #include <TStyle.h>
34     #include <TCanvas.h>
35     #include <TError.h>
36 buchmann 1.3 #include <TVirtualPad.h>
37 buchmann 1.1 #include <TGraphAsymmErrors.h>
38 buchmann 1.7 #include <TPaveText.h>
39 buchmann 1.1 #include <TRandom.h>
40 buchmann 1.38 #include <TGraphErrors.h>
41 buchmann 1.1 #ifndef Verbosity
42     #define Verbosity 0
43     #endif
44    
45 buchmann 1.38
46 buchmann 1.1 /*
47     #ifndef SampleClassLoaded
48     #include "SampleClass.C"
49     #endif
50     */
51     #define GeneralToolBoxLoaded
52    
53     using namespace std;
54    
55 buchmann 1.32 namespace PlottingSetup {
56     string cbafbasedir="";
57 buchmann 1.34 string basedirectory="";
58 buchmann 1.45 vector<float> global_ratio_binning;
59 buchmann 1.55 int publicmode=0;
60 buchmann 1.59 int PaperMode=0; // PaperMode=true will suppress "Preliminary" in DrawPrelim()
61 buchmann 1.32 }
62    
63 buchmann 1.1 bool dopng=false;
64     bool doC=false;
65     bool doeps=false;
66 buchmann 1.5 bool dopdf=false;
67 buchmann 1.33 bool doroot=false;
68 buchmann 1.26 float generaltoolboxlumi;
69 buchmann 1.1
70 fronga 1.50 TLegend* make_legend(string title, float posx1, float posy1, bool drawleg, float posx2, float posy2);
71 buchmann 1.26 TText* write_title(bool, string);
72 buchmann 1.1 TText* write_title_low(string title);
73    
74     TText* write_text(float xpos,float ypos,string title);
75     float computeRatioError(float a, float da, float b, float db);
76     float computeProductError(float a, float da, float b, float db);
77     TGraphAsymmErrors *histRatio(TH1F *h1,TH1F *h2, int id, vector<float>binning);
78     void setlumi(float l);
79 buchmann 1.26 void DrawPrelim(float writelumi);
80 buchmann 1.1 void CompleteSave(TCanvas *can, string filename, bool feedback);
81 buchmann 1.3 void CompleteSave(TVirtualPad *can, string filename, bool feedback);
82 buchmann 1.1 void write_warning(string funcname, string text);
83     void write_error(string funcname, string text);
84     void write_info(string funcname, string text);
85 buchmann 1.13 string get_directory();
86 buchmann 1.40 bool Contains(string wholestring, string findme);
87 buchmann 1.1 //-------------------------------------------------------------------------------------
88 buchmann 1.13
89 buchmann 1.15 template<typename U>
90     inline bool isanyinf(U value)
91     {
92     return !(value >= std::numeric_limits<U>::min() && value <=
93     std::numeric_limits<U>::max());
94     }
95 buchmann 1.13
96 buchmann 1.32 stringstream warningsummary;
97     stringstream infosummary;
98     stringstream errorsummary;
99    
100 buchmann 1.1 template<class A>
101     string any2string(const A& a){
102     ostringstream out;
103     out << a;
104     return out.str();
105     }
106    
107     void do_png(bool s) { dopng=s;}
108     void do_eps(bool s) { doeps=s;}
109     void do_C(bool s) { doC=s;}
110 buchmann 1.33 void do_pdf(bool s) { dopdf=s;}
111     void do_root(bool s){ doroot=s;}
112 buchmann 1.1
113     string topdir(string child) {
114     string tempdirectory=child;
115     if(tempdirectory.substr(tempdirectory.length()-1,1)=="/") tempdirectory=tempdirectory.substr(0,tempdirectory.length());
116     //we now have a directory without the trailing slash so we can just look for the last non-slash character :-)
117     for(int ichar=tempdirectory.length()-1;ichar>=0;ichar--) {
118     if(tempdirectory.substr(ichar,1)=="/") {
119     return tempdirectory.substr(0,ichar);
120     }
121     }
122     }
123    
124 buchmann 1.12 template < typename CHAR_TYPE,
125     typename TRAITS_TYPE = std::char_traits<CHAR_TYPE> >
126    
127     struct basic_teebuf : public std::basic_streambuf< CHAR_TYPE, TRAITS_TYPE >
128     {
129     typedef std::basic_streambuf< CHAR_TYPE, TRAITS_TYPE > streambuf_type ;
130     typedef typename TRAITS_TYPE::int_type int_type ;
131    
132     basic_teebuf( streambuf_type* buff_a, streambuf_type* buff_b )
133     : first(buff_a), second(buff_b) {}
134    
135     protected:
136     virtual int_type overflow( int_type c )
137     {
138     const int_type eof = TRAITS_TYPE::eof() ;
139     if( TRAITS_TYPE::eq_int_type( c, eof ) )
140     return TRAITS_TYPE::not_eof(c) ;
141     else
142     {
143     const CHAR_TYPE ch = TRAITS_TYPE::to_char_type(c) ;
144     if( TRAITS_TYPE::eq_int_type( first->sputc(ch), eof ) ||
145     TRAITS_TYPE::eq_int_type( second->sputc(ch), eof ) )
146     return eof ;
147     else return c ;
148     }
149     }
150    
151     virtual int sync()
152     { return !first->pubsync() && !second->pubsync() ? 0 : -1 ; }
153    
154     private:
155     streambuf_type* first ;
156     streambuf_type* second ;
157     };
158    
159     template < typename CHAR_TYPE,
160     typename TRAITS_TYPE = std::char_traits<CHAR_TYPE> >
161     struct basic_teestream : public std::basic_ostream< CHAR_TYPE, TRAITS_TYPE >
162     {
163     typedef std::basic_ostream< CHAR_TYPE, TRAITS_TYPE > stream_type ;
164     typedef basic_teebuf< CHAR_TYPE, TRAITS_TYPE > streambuff_type ;
165    
166     basic_teestream( stream_type& first, stream_type& second )
167     : stream_type( &stmbuf), stmbuf( first.rdbuf(), second.rdbuf() ) {}
168    
169     ~basic_teestream() { stmbuf.pubsync() ; }
170    
171     private: streambuff_type stmbuf ;
172     };
173    
174     typedef basic_teebuf<char> teebuf ;
175     typedef basic_teestream<char> teestream ;
176    
177 buchmann 1.13 std::ofstream file("LOG.txt",ios::app) ;
178 buchmann 1.28 std::ofstream texfile("Tex.txt") ;
179 buchmann 1.14 std::ofstream efile("LOGerr.txt",ios::app) ;
180 buchmann 1.13 teestream dout( file, std::cout ) ; // double out
181     teestream eout( efile, std::cout ) ; // double out (errors)
182 buchmann 1.12
183 buchmann 1.28 template < typename CHAR_TYPE,
184     typename TRAITS_TYPE = std::char_traits<CHAR_TYPE> >
185    
186     struct basic_tripbuf : public std::basic_streambuf< CHAR_TYPE, TRAITS_TYPE >
187     {
188     typedef std::basic_streambuf< CHAR_TYPE, TRAITS_TYPE > streambuf_type ;
189     typedef typename TRAITS_TYPE::int_type int_type ;
190    
191     basic_tripbuf( streambuf_type* buff_a, streambuf_type* buff_b, streambuf_type* buff_c )
192     : first(buff_a), second(buff_b), third(buff_c) {}
193    
194     protected:
195     virtual int_type overflow( int_type d )
196     {
197     const int_type eof = TRAITS_TYPE::eof() ;
198     if( TRAITS_TYPE::eq_int_type( d, eof ) )
199     return TRAITS_TYPE::not_eof(d) ;
200     else
201     {
202     const CHAR_TYPE ch = TRAITS_TYPE::to_char_type(d) ;
203     if( TRAITS_TYPE::eq_int_type( first->sputc(ch), eof ) ||
204     TRAITS_TYPE::eq_int_type( second->sputc(ch), eof )||
205     TRAITS_TYPE::eq_int_type( third->sputc(ch), eof ) )
206     return eof ;
207     else return d ;
208     }
209     }
210    
211     virtual int sync()
212     { return !first->pubsync() && !second->pubsync() && !third->pubsync() ? 0 : -1 ; }
213    
214     private:
215     streambuf_type* first ;
216     streambuf_type* second ;
217     streambuf_type* third ;
218     };
219    
220     template < typename CHAR_TYPE,
221     typename TRAITS_TYPE = std::char_traits<CHAR_TYPE> >
222     struct basic_tripstream : public std::basic_ostream< CHAR_TYPE, TRAITS_TYPE >
223     {
224     typedef std::basic_ostream< CHAR_TYPE, TRAITS_TYPE > stream_type ;
225     typedef basic_tripbuf< CHAR_TYPE, TRAITS_TYPE > streambuff_type ;
226    
227     basic_tripstream( stream_type& first, stream_type& second, stream_type& third )
228     : stream_type( &stmbuf), stmbuf( first.rdbuf(), second.rdbuf(), third.rdbuf() ) {}
229    
230     ~basic_tripstream() { stmbuf.pubsync() ; }
231    
232     private: streambuff_type stmbuf ;
233     };
234    
235     //typedef basic_tripbuf<char> teebuf ;
236     typedef basic_tripstream<char> tripplestream ;
237    
238     tripplestream tout( file, texfile , std::cout ) ; // tripple out
239    
240 buchmann 1.1 void ensure_directory_exists(string thisdirectory) {
241     struct stat st;
242     if(stat(thisdirectory.c_str(),&st) == 0) {
243 buchmann 1.13 if(Verbosity>0) dout << "Directory " << thisdirectory << " exists!" << endl;
244 buchmann 1.1 }
245     else {
246 buchmann 1.13 if(Verbosity>0) dout << "Directory " << thisdirectory << " does not exist. Need to create it!" << endl;
247 buchmann 1.1 ensure_directory_exists(topdir(thisdirectory));
248     if (mkdir(thisdirectory.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
249 buchmann 1.13 if(Verbosity>0) dout << "Created the directory " << thisdirectory << endl;
250 buchmann 1.1 }
251     }
252    
253 buchmann 1.13 void initialize_log() {
254 buchmann 1.55 if(!PlottingSetup::publicmode) {
255     dout << "____________________________________________________________" << endl;
256     dout << endl;
257     dout << " " << endl;
258     dout << " JJJJJJJJJJJZZZZZZZZZZZZZZZZZZZBBBBBBBBBBBBBBBBB " << endl;
259     dout << " J:::::::::JZ:::::::::::::::::ZB::::::::::::::::B " << endl;
260     dout << " J:::::::::JZ:::::::::::::::::ZB::::::BBBBBB:::::B " << endl;
261     dout << " JJ:::::::JJZ:::ZZZZZZZZ:::::Z BB:::::B B:::::B" << endl;
262     dout << " J:::::J ZZZZZ Z:::::Z B::::B B:::::B" << endl;
263     dout << " J:::::J Z:::::Z B::::B B:::::B" << endl;
264     dout << " J:::::J Z:::::Z B::::BBBBBB:::::B " << endl;
265     dout << " J:::::j Z:::::Z B:::::::::::::BB " << endl;
266     dout << " J:::::J Z:::::Z B::::BBBBBB:::::B " << endl;
267     dout << "JJJJJJJ J:::::J Z:::::Z B::::B B:::::B" << endl;
268     dout << "J:::::J J:::::J Z:::::Z B::::B B:::::B" << endl;
269     dout << "J::::::J J::::::J ZZZ:::::Z ZZZZZ B::::B B:::::B" << endl;
270     dout << "J:::::::JJJ:::::::J Z::::::ZZZZZZZZ:::ZBB:::::BBBBBB::::::B" << endl;
271     dout << " JJ:::::::::::::JJ Z:::::::::::::::::ZB:::::::::::::::::B " << endl;
272     dout << " JJ:::::::::JJ Z:::::::::::::::::ZB::::::::::::::::B " << endl;
273     dout << " JJJJJJJJJ ZZZZZZZZZZZZZZZZZZZBBBBBBBBBBBBBBBBB " << endl;
274     dout << " " << endl;
275     dout << endl << endl;
276     dout << "____________________________________________________________" << endl;
277     } else {
278     dout << " PUBLIC MODE " << endl;
279     }
280 buchmann 1.13 time_t rawtime;
281     struct tm * timeinfo;
282     time ( &rawtime );
283     dout << " Analysis run on " << asctime (localtime ( &rawtime ));
284     dout << "____________________________________________________________" << endl;
285     dout << " Results saved in : " << get_directory() << endl << endl;
286     }
287    
288 buchmann 1.32 void extract_cbaf_dir(string curpath) {
289     int position=curpath.find("/Plotting");
290     if(position<0) position=curpath.find("/DistributedModelCalculations");
291     if(position<0) position=curpath.find("/various_assignments");
292     PlottingSetup::cbafbasedir=curpath.substr(0,position);
293     }
294    
295 buchmann 1.1 void set_directory(string basedir="") {
296     if(basedir.substr(0,1)=="/") basedir=basedir.substr(1,basedir.length()-1);
297     if(basedir.substr(basedir.length()-1,1)!="/") basedir+="/";
298     char currentpath[1024];
299 buchmann 1.32 char *path = getcwd(currentpath,1024);
300 buchmann 1.34 PlottingSetup::basedirectory=(string)currentpath+"/Plots/"+basedir;
301     ensure_directory_exists(PlottingSetup::basedirectory);
302 buchmann 1.13 initialize_log();
303 buchmann 1.32 extract_cbaf_dir(currentpath);
304 buchmann 1.1 }
305    
306 buchmann 1.6 string get_directory() {
307 buchmann 1.34 return PlottingSetup::basedirectory;
308 buchmann 1.6 }
309    
310 buchmann 1.1 string extract_directory(string savethis) {
311     bool foundslash=false;
312     int position=savethis.length();
313     while(!foundslash&&position>0) {
314     position--;
315     if(savethis.substr(position,1)=="/") foundslash=true;
316     }
317     if(position>0) return savethis.substr(0,position+1);
318     else return "";
319     }
320    
321 buchmann 1.33 string extract_root_dir(string name) {
322     int position = -1;
323     if(name.substr(0,1)=="/") name=name.substr(1,name.length()-1);
324     for(int ipos=0;ipos<name.length();ipos++) {
325     if(name.substr(ipos,1)=="/") position=ipos;
326     }
327     if(position==-1) return "";
328     return name.substr(0,position);
329     }
330    
331     string extract_root_filename(string name) {
332     int position = -1;
333     if(name.substr(0,1)=="/") name=name.substr(1,name.length()-1);
334     for(int ipos=0;ipos<name.length();ipos++) {
335     if(name.substr(ipos,1)=="/") position=ipos;
336     }
337     return name.substr(position+1,name.length()-position-1);
338     }
339    
340 buchmann 1.40 void SaveToRoot(TCanvas *can, string name) {
341 fronga 1.58 can->Update();
342 buchmann 1.34 TFile *fout = new TFile((TString(PlottingSetup::basedirectory)+TString("allplots.root")),"UPDATE");
343 buchmann 1.33 fout->cd();
344     string directory=extract_root_dir(name);
345     string filename=extract_root_filename(name);
346     if(directory!="") {
347     if(fout->GetDirectory(directory.c_str())) {
348     fout->cd(directory.c_str());
349     can->Write(filename.c_str());
350     }else {
351     fout->mkdir(directory.c_str());
352     fout->cd(directory.c_str());
353     can->Write(filename.c_str());
354     }
355     } else {
356     can->Write(filename.c_str());
357     }
358     fout->cd();
359     fout->Close();
360     }
361    
362 fronga 1.18 void CompleteSave(TCanvas *can, string filename, bool feedback=false, bool redraw=true) {
363 buchmann 1.3 //any change you make here should also be done below in the CompleteSave function for virtual pads
364 buchmann 1.1 Int_t currlevel=gErrorIgnoreLevel;
365     if(!feedback) gErrorIgnoreLevel=1001;
366 fronga 1.18 if(redraw) can->RedrawAxis();
367 buchmann 1.34 ensure_directory_exists(extract_directory(PlottingSetup::basedirectory+filename));
368     if(dopng) can->SaveAs((PlottingSetup::basedirectory+filename+".png").c_str());
369     if(doeps) can->SaveAs((PlottingSetup::basedirectory+filename+".eps").c_str());
370     if(dopdf) can->SaveAs((PlottingSetup::basedirectory+filename+".pdf").c_str());
371     if(doC) can->SaveAs((PlottingSetup::basedirectory+filename+".C").c_str());
372 buchmann 1.33 if(doroot) SaveToRoot(can,filename);
373 buchmann 1.1 gErrorIgnoreLevel=currlevel;
374 buchmann 1.13 dout << "Saved " << filename << " in all requested formats" << endl;
375 buchmann 1.1 }
376 buchmann 1.3
377 fronga 1.18 void CompleteSave(TVirtualPad *can, string filename, bool feedback=false, bool redraw=true) {
378 buchmann 1.3 Int_t currlevel=gErrorIgnoreLevel;
379     if(!feedback) gErrorIgnoreLevel=1001;
380 fronga 1.18 if(redraw) can->RedrawAxis();
381 buchmann 1.34 ensure_directory_exists(extract_directory(PlottingSetup::basedirectory+filename));
382     if(dopng) can->SaveAs((PlottingSetup::basedirectory+filename+".png").c_str());
383     if(doeps) can->SaveAs((PlottingSetup::basedirectory+filename+".eps").c_str());
384 buchmann 1.54 if(dopdf) can->SaveAs((PlottingSetup::basedirectory+filename+".pdf").c_str());
385 buchmann 1.34 if(doC) can->SaveAs((PlottingSetup::basedirectory+filename+".C").c_str());
386 buchmann 1.3 gErrorIgnoreLevel=currlevel;
387 buchmann 1.13 dout << "Saved " << filename << " in all requested formats" << endl;
388 buchmann 1.3 }
389    
390 buchmann 1.1
391     void setlumi(float l) {
392 buchmann 1.24 generaltoolboxlumi=l;
393 buchmann 1.1 }
394    
395     int write_first_line(vector<vector<string> > &entries) {
396     if(entries.size()>0) {
397     vector<string> firstline = entries[0];
398     int ncolumns=firstline.size();
399     int ndividers=ncolumns+1;
400     int cellwidth=(int)(((float)(60-ndividers))/(ncolumns));
401 buchmann 1.13 dout << " |";
402 buchmann 1.1 for(int idiv=0;idiv<ncolumns;idiv++) {
403 buchmann 1.13 for(int isig=0;isig<cellwidth;isig++) dout << "-";
404     dout << "|";
405 buchmann 1.1 }
406 buchmann 1.13 dout << endl;
407 buchmann 1.1 return ncolumns;
408     } else {
409     return 0;
410     }
411     }
412    
413     void write_entry(string entry,int width,int iline=0,int ientry=0) {
414     int currwidth=entry.size();
415     while(currwidth<width) {
416     entry=" "+entry;
417     if(entry.size()<width) entry=entry+" ";
418     currwidth=entry.size();
419     }
420     bool do_special=false;
421 buchmann 1.13 if(iline==1&&ientry==1) { dout << "\033[1;32m" << entry << "\033[0m|";do_special=true;}//observed
422     if(iline==1&&ientry==2) { dout << "\033[1;34m" << entry << "\033[0m|";do_special=true;}//predicted (1)
423     if(iline==2&&ientry==1) { dout << "\033[1;34m" << entry << "\033[0m|";do_special=true;}//predicted (1)
424     if(iline==2&&ientry==2) { dout << "\033[1;34m" << entry << "\033[0m|";do_special=true;}//predicted (1)
425     if(!do_special) dout << entry << "|";
426 buchmann 1.1 }
427    
428     void make_nice_table(vector<vector <string> > &entries) {
429     int ncolumns=write_first_line(entries);
430     int cellwidth=(int)(((float)(60-(ncolumns+1)))/(ncolumns));
431     for(int iline=0;iline<entries.size();iline++) {
432     vector<string> currline = entries[iline];
433 buchmann 1.13 dout << " |";
434 buchmann 1.1 for(int ientry=0;ientry<currline.size();ientry++) {
435     write_entry(currline[ientry],cellwidth);
436     }
437 buchmann 1.13 dout << endl;
438 buchmann 1.1 if(iline==0) write_first_line(entries);
439     }
440     write_first_line(entries);
441     }
442    
443     void make_nice_jzb_table(vector<vector <string> > &entries) {
444     int ncolumns=write_first_line(entries);
445     int cellwidth=(int)(((float)(60-(ncolumns+1)))/(ncolumns));
446     for(int iline=0;iline<entries.size();iline++) {
447     vector<string> currline = entries[iline];
448 buchmann 1.13 dout << " |";
449 buchmann 1.1 for(int ientry=0;ientry<currline.size();ientry++) {
450     write_entry(currline[ientry],cellwidth,iline,ientry);
451     }
452 buchmann 1.13 dout << endl;
453 buchmann 1.1 if(iline==0) write_first_line(entries);
454     }
455     write_first_line(entries);
456     }
457    
458    
459     void write_warning(string funcname, string text) {
460 buchmann 1.40 string colid="[1;35m";
461     char hostname[1023];
462     gethostname(hostname,1023);
463     if(!Contains((string)hostname,"t3")) colid="[1;33m";
464     eout << endl << endl;
465     eout << "\033"<<colid<<"" << " _ " << endl;
466     eout << "\033"<<colid<<"" << " (_) " << endl;
467     eout << "\033"<<colid<<"" << "__ ____ _ _ __ _ __ _ _ __ __ _ " << endl;
468     eout << "\033"<<colid<<"" << "\\ \\ /\\ / / _` | '__| '_ \\| | '_ \\ / _` |" << endl;
469     eout << "\033"<<colid<<"" << " \\ V V / (_| | | | | | | | | | | (_| |" << endl;
470     eout << "\033"<<colid<<"" << " \\_/\\_/ \\__,_|_| |_| |_|_|_| |_|\\__, |" << endl;
471     eout << "\033"<<colid<<"" << " __/ |" << endl;
472     eout << "\033"<<colid<<"" << " |___/ " << endl;
473 buchmann 1.13 eout << endl;
474 buchmann 1.40 eout << "\033"<<colid<<" [" << funcname << "] " << text << " \033[0m" << endl;
475 buchmann 1.13 eout << endl << endl;
476 buchmann 1.32 warningsummary << "[" << funcname << "] " << text << endl;
477 buchmann 1.1 }
478 buchmann 1.40
479 buchmann 1.1 void write_error(string funcname, string text) {
480 buchmann 1.13 eout << endl << endl;
481     eout << "\033[1;31m ___ _ __ _ __ ___ _ __ " << endl;
482     eout << "\033[1;31m / _ \\ __| __/ _ \\| '__|" << endl;
483     eout << "\033[1;31m| __/ | | | | (_) | | " << endl;
484     eout << "\033[1;31m \\___|_| |_| \\___/|_| " << endl;
485     eout << endl;
486     eout << "\033[1;31m [" << funcname << "] " << text << " \033[0m" << endl;
487     eout << endl << endl;
488 buchmann 1.32 errorsummary << "[" << funcname << "] " << text << endl;
489 buchmann 1.1 }
490    
491     void write_info(string funcname, string text) {
492 buchmann 1.13 dout << endl << endl;
493     dout << "\033[1;34m _____ __ " << endl;
494     dout << "\033[1;34m |_ _| / _| " << endl;
495     dout << "\033[1;34m | | _ __ | |_ ___ " << endl;
496     dout << "\033[1;34m | | | '_ \\| _/ _ \\ " << endl;
497     dout << "\033[1;34m _| |_| | | | || (_) | " << endl;
498     dout << "\033[1;34m |_____|_| |_|_| \\___/ " << endl;
499     dout << endl;
500     dout << "\033[1;34m [" << funcname << "] " << text << " \033[0m" << endl;
501     dout << endl << endl;
502 buchmann 1.32 infosummary << "[" << funcname << "] " << text << endl;
503 buchmann 1.1 }
504    
505     TText* write_text(float xpos,float ypos,string title)
506     {
507     TLatex* titlebox = new TLatex (xpos,ypos,title.c_str());
508     titlebox->SetNDC(true);
509     titlebox->SetTextFont(42);
510     titlebox->SetTextSize(0.04);
511     titlebox->SetTextAlign(21);
512     return titlebox;
513     }
514    
515     TText* write_title(string title)
516     {
517 buchmann 1.15 TText* titlebox = write_text(0.5,0.945,title);
518 buchmann 1.1 return titlebox;
519     }
520    
521 buchmann 1.7 TText* write_cut_on_canvas(string cut) {
522     // TLatex *normbox = new TLatex(0.96,0.5,cut.c_str());
523     TLatex *normbox = new TLatex(0.96,0.5,"");//currently deactivated
524     normbox->SetNDC(true);
525     normbox->SetTextFont(42);
526     normbox->SetTextSize(0.01);
527     normbox->SetTextAlign(21);
528     normbox->SetTextAngle(270);
529     return normbox;
530     }
531    
532 buchmann 1.1 TText* write_title_low(string title)
533     {
534     TText* titlebox = write_text(0.5,0.94,title);
535     return titlebox;
536     }
537    
538 buchmann 1.27 void DrawPrelim(float writelumi=generaltoolboxlumi,bool isMC=false) {
539 buchmann 1.26 string barn="pb";
540     if(writelumi>=1000)
541     {
542     writelumi/=1000;
543     barn="fb";
544     }
545    
546     stringstream prelimtext;
547 buchmann 1.59 string prel=" Preliminary";
548     if(PlottingSetup::PaperMode) prel="";
549 buchmann 1.26 //prelimtext << "CMS Preliminary 2011 , #sqrt{s}= 7 TeV, L= O(1) fb^{-1}"; //temporary replacement
550 pablom 1.56 if(writelumi == 0) {
551 pablom 1.57 if(isMC) prelimtext << "CMS Simulation, #sqrt{s} = 7 TeV";
552 buchmann 1.59 else prelimtext << "CMS" << prel << ", #sqrt{s} = 7 TeV";
553 pablom 1.56 } else {
554 pablom 1.57 if(isMC) prelimtext << "CMS Simulation, #sqrt{s} = 7 TeV, L_{int} = " << std::setprecision(2) <<writelumi<<" "<<barn<<"^{-1}";
555 buchmann 1.59 else prelimtext << "CMS" << prel << ", #sqrt{s} = 7 TeV, L_{int} = " << std::setprecision(2) <<writelumi<<" "<<barn<<"^{-1}";
556 pablom 1.56 }
557 buchmann 1.26 TPaveText *eventSelectionPaveText = new TPaveText(0.27, 0.93,0.77, 1.0,"blNDC");
558     eventSelectionPaveText->SetFillStyle(4000);
559 buchmann 1.51 eventSelectionPaveText->SetBorderSize(0);
560 buchmann 1.26 eventSelectionPaveText->SetFillColor(kWhite);
561     eventSelectionPaveText->SetTextFont(42);
562     eventSelectionPaveText->SetTextSize(0.042);
563     eventSelectionPaveText->AddText(prelimtext.str().c_str());
564     eventSelectionPaveText->Draw();
565     }
566    
567 buchmann 1.27 void DrawMCPrelim(float writelumi=generaltoolboxlumi) {
568     DrawPrelim(writelumi,true);
569     }
570    
571 fronga 1.50 TLegend* make_legend(string title="", float posx1=0.6, float posy1=0.55, bool drawleg=true, float posx2 = 0.89, float posy2 = 0.89 )
572 buchmann 1.1 {
573     gStyle->SetTextFont(42);
574 fronga 1.50 TLegend *leg = new TLegend(posx1,posy1,posx2,posy2);
575 buchmann 1.1 if(title!="") leg->SetHeader(title.c_str());
576     leg->SetTextFont(42);
577 fronga 1.17 leg->SetTextSize(0.04);
578 buchmann 1.1 leg->SetFillColor(kWhite);
579     leg->SetBorderSize(0);
580     leg->SetLineColor(kWhite);
581 buchmann 1.26 if(drawleg) DrawPrelim();
582 buchmann 1.1 return leg;
583     }
584    
585 buchmann 1.26 TLegend* make_legend(bool drawleg, string title) {
586     return make_legend(title,0.6,0.55,drawleg);
587     }
588    
589 buchmann 1.1 TGraph* make_nice_ratio(int nbins,float binning[],TH1F* histo)
590     {
591     float errorsquared[nbins];
592     float errors[nbins];
593     float bincontent[nbins];
594     for (int i=0;i<nbins;i++) {
595     errorsquared[i]=0;
596     bincontent[i]=0;
597     errors[i]=0;
598     }
599     float currlimit=binning[0];
600     int currtoplim=1;
601     for(int ibin=1;ibin<=histo->GetNbinsX();ibin++)
602     {
603     if(binning[currtoplim]<histo->GetBinCenter(ibin)) currtoplim++;
604 buchmann 1.13 dout << "Bin i=" << ibin << " with bin center " << histo->GetBinCenter(ibin) << " contains " << histo->GetBinContent(ibin) << " is within " << binning[currtoplim-1] << " and " << binning[currtoplim] << endl;
605 buchmann 1.1
606     }
607    
608     return 0;
609     }
610    
611     float statErrorN(float x){return x - 0.5*TMath::ChisquareQuantile(0.3173/2,2*x);}
612     float statErrorP(float x){return 0.5*TMath::ChisquareQuantile(1-0.3173/2,2*(x+1))-x;}
613     float lowLimit(float a, float x){return 0.5*TMath::ChisquareQuantile(a,2*x);}
614     float highLimit(float a,float x){return 0.5*TMath::ChisquareQuantile(1-a,2*(x+1));}
615    
616     float computeRatioError(float a, float da, float b, float db)
617     {
618     float val=0.;
619     float errorSquare = (a/b)*(a/b)*( (da/a)*(da/a) + (db/b)*(db/b));
620     val = TMath::Sqrt(errorSquare);
621     return val;
622    
623     }
624     float computeProductError(float a, float da, float b, float db)
625     {
626     float val=0.;
627     float errorSquare = (a*b)*(a*b)*( (da/a)*(da/a) + (db/b)*(db/b));
628     val = TMath::Sqrt(errorSquare);
629     return val;
630     }
631    
632 buchmann 1.23 TGraphAsymmErrors *histRatio(TH1F *h1,TH1F *h2, int id, vector<float>binning, bool precise=false)
633 buchmann 1.1 {
634     int absJZBbinsNumber = binning.size()-1;
635     TGraphAsymmErrors* graph = new TGraphAsymmErrors(absJZBbinsNumber);
636    
637     for(unsigned int i=0;i<absJZBbinsNumber;i++)
638     {
639     float xCenter=h1->GetBinCenter(i+1);
640     float xWidth=(h1->GetBinWidth(i+1))*0.5;
641     float nominatorError = h1->GetBinError(i+1);
642     float nominator=h1->GetBinContent(i+1);
643     float denominatorError=h2->GetBinError(i+1);
644     float denominator=h2->GetBinContent(i+1);
645     float errorN = 0;
646     float errorP = computeRatioError(nominator,nominatorError,denominator,denominatorError);
647     if(id==1) // (is data)
648     {
649 buchmann 1.23 if(!precise) errorP = computeRatioError(nominator,statErrorP(nominator),denominator,statErrorP(denominator));
650     else errorP = computeRatioError(nominator,nominatorError,denominator,denominatorError);
651 buchmann 1.1 errorN = errorP; // symmetrize using statErrorP
652     } else {
653     errorN = computeRatioError(nominator,nominatorError,denominator,denominatorError);
654 buchmann 1.23 errorP = errorN;
655 buchmann 1.1 }
656     if(denominator!=0) {
657     graph->SetPoint(i, xCenter, nominator/denominator);
658     graph->SetPointError(i,xWidth,xWidth,errorN,errorP);
659     }
660     else {
661     graph->SetPoint(i, xCenter, -999);
662     graph->SetPointError(i,xWidth,xWidth,errorN,errorP);
663     }
664     }
665     return graph;
666     }
667    
668     string print_range(float cent, float down, float up) {//note that up&down can be flipped, we don't care, but the central value needs to come 1st!
669     float uperr=0,downerr=0;
670     if(down>up&&down>cent) uperr=down-cent;
671     if(up>down&&up>cent) uperr=up-cent;
672     if(down<cent&&down<up) downerr=cent-down;
673     if(up<cent&&up<down) downerr=cent-up;
674     if(cent>up&&cent>down&&(up!=0&&down!=0)) write_error("print_range"," WATCH OUT: THE CENTRAL VALUE SEEMS TO BE LARGER THAN BOTH UP&DOWN!");
675     if(cent<up&&cent<down&&(up!=0&&down!=0)) write_error("print_range"," WATCH OUT: THE CENTRAL VALUE SEEMS TO BE SMALLER THAN BOTH UP&DOWN!");
676     stringstream result;
677     result << cent << " + " << uperr << " - " << downerr;
678     return result.str();
679     }
680    
681     void bubbleSort ( int arr [ ], int size, int order [ ]) // nice way to sort an array (called arr) which is currently in a random order (indices in (order")
682     {
683     int last = size - 2;
684     int isChanged = 1;
685    
686     while ( last >= 0 && isChanged )
687     {
688     isChanged = 0;
689     for ( int k = 0; k <= last; k++ )
690     if ( arr[k] > arr[k+1] )
691     {
692     swap ( arr[k], arr[k+1] );
693     isChanged = 1;
694     int bkp=order[k];
695     order[k]=order[k+1];
696     order[k+1]=bkp;
697     }
698     last--;
699     }
700     }
701    
702     void swapvec(vector<float> &vec,int j, int k) {
703     float bkp=vec[j];
704     vec[j]=vec[k];
705     vec[k]=bkp;
706     }
707    
708     void bubbleSort ( vector<float> &arr , vector<int> &order) // nice way to sort an array (called arr) which is currently in a random order (indices in (order")
709     {
710     int last = arr.size() - 2;
711     int isChanged = 1;
712    
713     while ( last >= 0 && isChanged )
714     {
715     isChanged = 0;
716     for ( int k = 0; k <= last; k++ )
717     if ( arr[k] > arr[k+1] )
718     {
719     swapvec (arr,k,k+1);
720     isChanged = 1;
721     int bkp=order[k];
722     order[k]=order[k+1];
723     order[k+1]=bkp;
724     }
725     last--;
726     }
727     }
728    
729     int numerichistoname=0;
730 buchmann 1.16 bool givingnumber=false;
731 buchmann 1.1 string GetNumericHistoName() {
732 buchmann 1.16 while(givingnumber) sleep(1);
733     givingnumber=true;
734 buchmann 1.1 stringstream b;
735     b << "h_" << numerichistoname;
736     numerichistoname++;
737 buchmann 1.16 givingnumber=false;
738 buchmann 1.1 return b.str();
739     }
740    
741     //********************** BELOW : CUT INTERPRETATION **************************//
742     void splitupcut(string incut, vector<string> &partvector)
743     {
744     //idea: go thru the string called incut; if a parantheses is opened, then the cut cannot be split up until the parantheses is closed.
745     //ok anyway screw the parantheses.
746     int paranthesis_open=0;
747     int substr_start=0;
748     string currchar="";
749     for (int ichar=0;ichar<incut.length();ichar++)
750     {
751     currchar=incut.substr(ichar,1);
752     // if(currchar=="(") paranthesis_open++;
753     // if(currchar==")") paranthesis_open--;
754     if(currchar=="&"&&incut.substr(ichar+1,1)=="&"&&paranthesis_open==0) {
755     partvector.push_back(incut.substr(substr_start,ichar-substr_start));
756     substr_start=ichar+2;
757     }
758     }
759     partvector.push_back(incut.substr(substr_start,incut.length()-substr_start));
760     if(Verbosity>1) {
761 buchmann 1.13 dout << "[ splitupcut() ] : The cut vector now contains the following elements: "<< endl;
762 buchmann 1.1 for (int ipart=0;ipart<partvector.size();ipart++)
763     {
764 buchmann 1.13 dout << " - " << partvector[ipart] << endl;
765 buchmann 1.1 }
766     }
767     }
768    
769     int atleastvalue(string expression, int &morethanlessthan) // takes in an expression such as ">2" or ">=3" and returns e.g. 3 (in both examples)
770     {
771     int retval=0;
772     if(expression.substr(0,1)==">"&&expression.substr(1,1)=="=") {
773 buchmann 1.13 // dout << "The expression " << expression << " is saying that we have at least " << atoi(expression.substr(2,1).c_str()) << " jets" << endl;
774 buchmann 1.1 morethanlessthan=1;
775     return atoi(expression.substr(2,1).c_str());
776     }
777     if(expression.substr(0,1)=="="&&expression.substr(1,1)=="=") {
778 buchmann 1.13 // dout << "The expression " << expression << " is saying that we have at least " << atoi(expression.substr(1,1).c_str())+1 << " jets" << endl;
779 buchmann 1.1 morethanlessthan=0;
780     return atoi(expression.substr(1,1).c_str());
781     }
782     if(expression.substr(0,1)=="<"&&expression.substr(1,1)=="=") {
783 buchmann 1.13 // dout << "The expression " << expression << " is saying that we have at least " << atoi(expression.substr(1,1).c_str())+1 << " jets" << endl;
784 buchmann 1.1 morethanlessthan=-1;
785     return 1+atoi(expression.substr(1,1).c_str());
786     }
787     if(expression.substr(0,1)==">") {
788 buchmann 1.13 // dout << "The expression " << expression << " is saying that we have at least " << atoi(expression.substr(2,1).c_str()) << " jets" << endl;
789 buchmann 1.1 morethanlessthan=1;
790     return 1+atoi(expression.substr(2,1).c_str());
791     }
792     if(expression.substr(0,1)=="<"&&expression.substr(1,1)=="=") {
793 buchmann 1.13 // dout << "The expression " << expression << " is saying that we have at least " << atoi(expression.substr(2,1).c_str()) << " jets" << endl;
794 buchmann 1.1 morethanlessthan=-1;
795     return 1+atoi(expression.substr(2,1).c_str());
796     }
797     }
798    
799     int do_jet_cut(string incut, int *nJets) {
800     string expression=(incut.substr(12,incut.size()-12));
801 buchmann 1.13 dout << "Going to analyze the jet cut : " << expression << " with 0,1 being " << expression.substr(0,1) << " and 1,1 being " << expression.substr(1,1) << endl;
802 buchmann 1.1 if(expression.substr(0,1)=="<"&&expression.substr(1,1)=="=") {
803     int nJet=atoi(expression.substr(2,1).c_str());
804     for(int i=nJet+1;i<20;i++) nJets[i]=0;
805 buchmann 1.13 dout << "Is of type <=" << endl;
806 buchmann 1.1 return 0;
807     }
808     if(expression.substr(0,1)=="="&&expression.substr(1,1)=="=") {
809     int nJet=atoi(expression.substr(2,1).c_str());
810     for(int i=0;i<20&&i!=nJet;i++) nJets[i]=0;
811 buchmann 1.13 dout << "Is of type ==" << endl;
812 buchmann 1.1 return 0;
813     }
814     if(expression.substr(0,1)==">"&&expression.substr(1,1)=="=") {
815     int nJet=atoi(expression.substr(2,1).c_str());
816     for(int i=0;i<nJet&&i!=nJet;i++) nJets[i]=0;
817 buchmann 1.13 dout << "Is of type >=" << endl;
818 buchmann 1.1 return 0;
819     }
820     if(expression.substr(0,1)=="<") {
821     int nJet=atoi(expression.substr(1,1).c_str());
822     for(int i=nJet;i<20;i++) nJets[i]=0;
823 buchmann 1.13 dout << "Is of type <" << endl;
824 buchmann 1.1 return 0;
825     }
826     if(expression.substr(0,1)==">") {
827     int nJet=atoi(expression.substr(1,1).c_str());
828     for(int i=0;i<nJet+1&&i!=nJet;i++) nJets[i]=0;
829 buchmann 1.13 dout << "Is of type >" << endl;
830 buchmann 1.1 return 0;
831     }
832     }
833    
834     string interpret_cut(string incut, bool &isJetCut, int *permittednJets)
835     {
836     // isJetCut=false;nJets=-1;
837     if(incut=="()") return "";
838     while(incut.substr(0,1)=="(") incut=incut.substr(1,incut.length()-1);
839     while(incut.length()>0&&incut.substr(incut.length()-1,1)==")") incut=incut.substr(0,incut.length()-1);
840     // if(incut.substr(0,1)=="("&&incut.substr(incut.length()-1,1)==")") incut=incut.substr(1,incut.length()-2); //this is to make (cut) to cut.
841    
842     if(Verbosity>0) {
843 buchmann 1.13 dout << "Now interpreting cut " << incut << endl;
844 buchmann 1.1 }
845     /*
846     if(incut=="ch1*ch2<0") return "OS";
847     if(incut=="id1==id2") return "SF";
848     if(incut=="id1!=id2") return "OF";
849     */
850     if(incut=="ch1*ch2<0") return "";
851 buchmann 1.5 if(incut=="(mll>55&&mll<70)||(mll>112&&mll<160)") return "SB";
852     if(incut=="(mll>61&&mll<70)||(mll>112&&mll<190)") return "SB'";
853 buchmann 1.1 if(incut=="id1==id2") return "";
854     if(incut=="id1!=id2") return "";
855     if(incut=="mll>2") return "";
856    
857     if(incut=="mll>0") return ""; // my typical "fake cut"
858    
859     if(incut=="passed_triggers||!is_data") return "Triggers";
860     if(incut=="pfjzb[0]>-998") return "";
861    
862    
863     if(incut=="id1==0") return "ee";
864     if(incut=="id1==1") return "#mu#mu";
865     if(incut=="abs(mll-91.2)<20") return "|m_{l^{+}l^{-}}-m_{Z}|<20";
866     if(incut=="pfJetGoodID[0]") return "";
867     if(incut=="pfJetGoodID[1]") return "";
868     if((int)incut.find("pfJetGoodNum")>-1) {
869     //do_jet_cut(incut,permittednJets);
870     stringstream result;
871     result << "nJets" << incut.substr(12,incut.size()-12);
872 buchmann 1.13 /* dout << "Dealing with a jet cut: " << incut << endl;
873 buchmann 1.1 stringstream result;
874     result << "nJets" << incut.substr(12,incut.size()-12);
875     isJetCut=true;
876     if(exactjetcut(incut,nJets))
877     // nJets=atleastvalue((incut.substr(12,incut.size()-12)),morethanlessthan);
878     return result.str();*/
879     return result.str();
880     }
881     return incut;
882     }
883    
884     string interpret_nJet_range(int *nJets) {
885 buchmann 1.13 for (int i=0;i<20;i++) dout << i << " : " << nJets[i] << endl;
886 buchmann 1.1 return "hello";
887     }
888    
889     string interpret_cuts(vector<string> &cutparts)
890     {
891     stringstream nicecut;
892     int nJets;
893     bool isJetCut;
894     int finalJetCut=-1;
895     int permittednJets[20];
896     for(int ijet=0;ijet<20;ijet++) permittednJets[ijet]=1;
897     int morethanlessthan=0;//-1: less than, 0: exactly, 1: more than
898     for(int icut=0;icut<cutparts.size();icut++)
899     {
900     if(icut==0) nicecut<<interpret_cut(cutparts[icut],isJetCut,permittednJets);
901     else {
902     string nice_this_cut = interpret_cut(cutparts[icut],isJetCut,permittednJets);//blublu
903     if(nice_this_cut.length()>0&&nicecut.str().length()>0) {
904     if(!isJetCut) nicecut<<"&&"<<nice_this_cut;
905     else {
906     if(nJets>finalJetCut) finalJetCut=nJets;
907     }
908     }
909     if(nice_this_cut.length()>0&&nicecut.str().length()==0) {
910     if(!isJetCut) {
911     nicecut<<nice_this_cut;
912     }
913     else {
914     if(nJets>finalJetCut) finalJetCut=nJets;
915     }
916     }
917     }
918     }
919     if(finalJetCut>-1) {
920     if(nicecut.str().length()==0) {
921     nicecut << "nJets#geq" << finalJetCut;
922     }
923     else
924     {
925     nicecut << "&&nJets#geq " << finalJetCut;
926     }
927     }
928    
929 buchmann 1.13 // dout << "The nJet allowed range is given by: " << interpret_nJet_range(permittednJets) << endl;
930 buchmann 1.1
931     return nicecut.str();
932     }
933    
934     string decipher_cut(TCut originalcut,TCut ignorethispart)
935     {
936     string incut=(const char*)originalcut;
937     string ignore=(const char*)ignorethispart;
938    
939     if(ignore.length()>0 && incut.find(ignore)!=string::npos) incut=incut.replace(incut.find(ignore),ignore.length(),"");
940    
941     vector<string>cutparts;
942     splitupcut(incut,cutparts);
943     string write_cut=interpret_cuts(cutparts);
944     return write_cut;
945     }
946    
947     //********************** ABOVE : CUT INTERPRETATION **************************//
948 buchmann 1.2
949     Double_t GausRandom(Double_t mu, Double_t sigma) {
950     return gRandom->Gaus(mu,sigma);// real deal
951     //return mu;//debugging : no smearing.
952     }
953    
954 buchmann 1.3 int functionalhistocounter=0;
955 buchmann 1.2 TH1F * makehistofromfunction(TF1 *f1,TH1F *model) {
956     TH1F *histo = (TH1F*)model->Clone();
957 buchmann 1.3 functionalhistocounter++;
958     stringstream histoname;
959     histoname << "histo_based_on_function_" << f1->GetName() << "__"<<functionalhistocounter;
960     histo->SetTitle(histoname.str().c_str());
961     histo->SetName(histoname.str().c_str());
962 buchmann 1.2 int nbins=histo->GetNbinsX();
963     float low=histo->GetBinLowEdge(1);
964     float hi=histo->GetBinLowEdge(histo->GetNbinsX())+histo->GetBinWidth(histo->GetNbinsX());
965    
966     for(int i=0;i<=nbins;i++) {
967 buchmann 1.4 histo->SetBinContent(i,(f1->Integral(histo->GetBinLowEdge(i),histo->GetBinLowEdge(i)+histo->GetBinWidth(i)))/histo->GetBinWidth(i));
968     histo->SetBinError(i,TMath::Sqrt(histo->GetBinContent(i)));
969 buchmann 1.2 }
970    
971     return histo;
972 buchmann 1.4 }
973    
974     float hintegral(TH1 *histo, float low, float high) {
975     float sum=0;
976     for(int i=1;i<histo->GetNbinsX();i++) {
977     if((histo->GetBinLowEdge(i)>=low)&&(histo->GetBinLowEdge(i)+histo->GetBinWidth(i))<=high) sum+=histo->GetBinContent(i);
978     //now on to the less clear cases!
979     if(histo->GetBinLowEdge(i)<low&&(histo->GetBinLowEdge(i)+histo->GetBinWidth(i))>low) {
980     //need to consider this case still ... the bin is kind of in range but not sooooo much.
981     }
982     if(histo->GetBinLowEdge(i)<high&&(histo->GetBinLowEdge(i)+histo->GetBinWidth(i))>high) {
983     //need to consider this case still ... the bin is kind of in range but not sooooo much.
984     }
985    
986     }
987     return sum;
988 buchmann 1.5 }
989    
990 buchmann 1.6 string newjzbexpression(string oldexpression,float shift) {
991     stringstream ss;
992     if(shift>0) ss<<"("<<oldexpression<<"+"<<shift<<")";
993     if(shift<0) ss<<"("<<oldexpression<<shift<<")";
994     if(shift==0) ss<<oldexpression;
995     return ss.str();
996     }
997    
998 buchmann 1.29 float Round(float num, unsigned int dig)
999 buchmann 1.11 {
1000 fronga 1.58 num *= pow((double)10, (double)dig);
1001 buchmann 1.11 if (num >= 0)
1002     num = floor(num + 0.5);
1003     else
1004     num = ceil(num - 0.5);
1005 fronga 1.58 num/= pow((double)10, (double)dig);
1006 buchmann 1.11 return num;
1007 buchmann 1.16 }
1008    
1009 buchmann 1.54 float SigDig(double number, float N) {
1010     int exp=0;
1011     while(number<pow(10,N-1)) {
1012     number*=10;
1013     exp+=1;
1014     }
1015     while(number>pow(10,N)) {
1016     number/=10;
1017     exp-=1;
1018     }
1019     number=int(number+0.5);
1020 fronga 1.58 return number/pow((double)10,(double)exp);
1021 buchmann 1.29 }
1022    
1023 buchmann 1.16 // The two functions below are for distributed processing
1024    
1025     int get_job_number(float ipoint, float Npoints,float Njobs) {
1026     float pointposition=(ipoint/Npoints);
1027 buchmann 1.48 int njob=(int)floor(pointposition*Njobs);
1028 buchmann 1.16 if(njob>=Njobs) njob--;
1029     // cout << "Looking at point " << ipoint << " out of " << Npoints << " which is at position " << pointposition << " corresponding to " << pointposition*Njobs << " --> JOB " << njob << endl;
1030     return njob;
1031     }
1032    
1033    
1034     bool do_this_point(int ipoint, int Npoints, int jobnumber, int Njobs) {
1035     if(get_job_number(ipoint,Npoints,Njobs)==jobnumber) return true;
1036     return false;
1037     }
1038 buchmann 1.19
1039     Double_t DoIntegral(TH1F *histo, Int_t binx1, Int_t binx2, Int_t biny1, Int_t biny2, Int_t binz1, Int_t binz2, Double_t & error ,
1040     Option_t *option, Bool_t doError)
1041     {
1042     // internal function compute integral and optionally the error between the limits
1043     // specified by the bin number values working for all histograms (1D, 2D and 3D)
1044    
1045     Int_t nbinsx = histo->GetNbinsX();
1046     if (binx1 < 0) binx1 = 0;
1047     if (binx2 > nbinsx+1 || binx2 < binx1) binx2 = nbinsx+1;
1048     if (histo->GetDimension() > 1) {
1049     Int_t nbinsy = histo->GetNbinsY();
1050     if (biny1 < 0) biny1 = 0;
1051     if (biny2 > nbinsy+1 || biny2 < biny1) biny2 = nbinsy+1;
1052     } else {
1053     biny1 = 0; biny2 = 0;
1054     }
1055     if (histo->GetDimension() > 2) {
1056     Int_t nbinsz = histo->GetNbinsZ();
1057     if (binz1 < 0) binz1 = 0;
1058     if (binz2 > nbinsz+1 || binz2 < binz1) binz2 = nbinsz+1;
1059     } else {
1060     binz1 = 0; binz2 = 0;
1061     }
1062    
1063     // - Loop on bins in specified range
1064     TString opt = option;
1065     opt.ToLower();
1066     Bool_t width = kFALSE;
1067     if (opt.Contains("width")) width = kTRUE;
1068    
1069    
1070     Double_t dx = 1.;
1071     Double_t dy = 1.;
1072     Double_t dz = 1.;
1073     Double_t integral = 0;
1074     Double_t igerr2 = 0;
1075     for (Int_t binx = binx1; binx <= binx2; ++binx) {
1076     if (width) dx = histo->GetXaxis()->GetBinWidth(binx);
1077     for (Int_t biny = biny1; biny <= biny2; ++biny) {
1078     if (width) dy = histo->GetYaxis()->GetBinWidth(biny);
1079     for (Int_t binz = binz1; binz <= binz2; ++binz) {
1080     if (width) dz = histo->GetZaxis()->GetBinWidth(binz);
1081     Int_t bin = histo->GetBin(binx, biny, binz);
1082     if (width) integral += histo->GetBinContent(bin)*dx*dy*dz;
1083     else integral += histo->GetBinContent(bin);
1084     if (doError) {
1085     if (width) igerr2 += histo->GetBinError(bin)*histo->GetBinError(bin)*dx*dx*dy*dy*dz*dz;
1086     else igerr2 += histo->GetBinError(bin)*histo->GetBinError(bin);
1087     }
1088     }
1089     }
1090     }
1091    
1092     if (doError) error = TMath::Sqrt(igerr2);
1093     return integral;
1094     }
1095    
1096     Double_t IntegralAndError(TH1F *histo, Int_t binx1, Int_t binx2, Double_t & error, Option_t *option)
1097     {
1098     //Return integral of bin contents in range [binx1,binx2] and its error
1099     // By default the integral is computed as the sum of bin contents in the range.
1100     // if option "width" is specified, the integral is the sum of
1101     // the bin contents multiplied by the bin width in x.
1102     // the error is computed using error propagation from the bin errors assumming that
1103     // all the bins are uncorrelated
1104     return DoIntegral(histo,binx1,binx2,0,-1,0,-1,error,option,kTRUE);
1105 buchmann 1.21 }
1106    
1107     void print_usage() {
1108     cout << "Some distributed model calculations call Create_All_Plots.exec with the argument \"1\" to calculate some basic quantities, such as the peak position in MC and data, observed and predicted, and so on. If you want to test this, you can just run this program with argument 1 yourself :-) " << endl;
1109 buchmann 1.22 }
1110    
1111    
1112     string format_number( int value )
1113     {
1114     if( value == 0 ) return "00";
1115     if( value < 10 ) return "0"+any2string(value);
1116     return any2string(value);
1117     }
1118    
1119     string seconds_to_time(int seconds) {
1120     const static unsigned int SECONDS_IN_AN_HOUR = 3600;
1121     const static unsigned int SECONDS_IN_A_MINUTE = 60;
1122     stringstream answer;
1123     if( seconds > 0 )
1124     {
1125     answer << format_number( (unsigned int)(seconds / SECONDS_IN_AN_HOUR) ) << ":";
1126     answer << format_number( (unsigned int)((seconds % SECONDS_IN_AN_HOUR) / SECONDS_IN_A_MINUTE) ) << ":";
1127     answer << format_number( (unsigned int)((seconds % SECONDS_IN_AN_HOUR) % (SECONDS_IN_A_MINUTE)) );
1128     }
1129     else
1130     {
1131     answer << "00:00:00";
1132     }
1133     return answer.str();
1134     }
1135 buchmann 1.29
1136     bool Contains(string wholestring, string findme) {
1137 buchmann 1.30 if((int)wholestring.find(findme)>-1) return true;
1138 buchmann 1.29 else return false;
1139 fronga 1.31 }
1140 buchmann 1.35
1141     //////////////////////////////////////////////////////////////////////////////
1142     //
1143     // http://stackoverflow.com/questions/669438/how-to-get-memory-usage-at-run-time-in-c
1144     // process_mem_usage(double &, double &) - takes two doubles by reference,
1145     // attempts to read the system-dependent data for a process' virtual memory
1146     // size and resident set size, and return the results in KB.
1147     //
1148     // On failure, returns 0.0, 0.0
1149    
1150     /* usage:
1151     double vm2, rss2;
1152     process_mem_usage(vm2, rss2);
1153     cout << "Memory usage: VM: " << vm << "; RSS: " << rss << endl;
1154     */
1155    
1156     void process_mem_usage(double& vm_usage, double& resident_set)
1157     {
1158     using std::ios_base;
1159     using std::ifstream;
1160     using std::string;
1161    
1162     vm_usage = 0.0;
1163     resident_set = 0.0;
1164    
1165     // 'file' stat seems to give the most reliable results
1166     //
1167     ifstream stat_stream("/proc/self/stat",ios_base::in);
1168    
1169     // dummy vars for leading entries in stat that we don't care about
1170     //
1171     string pid, comm, state, ppid, pgrp, session, tty_nr;
1172     string tpgid, flags, minflt, cminflt, majflt, cmajflt;
1173     string utime, stime, cutime, cstime, priority, nice;
1174     string O, itrealvalue, starttime;
1175    
1176     // the two fields we want
1177     //
1178     unsigned long vsize;
1179     long rss;
1180    
1181     stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
1182     >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
1183     >> utime >> stime >> cutime >> cstime >> priority >> nice
1184     >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest
1185    
1186     stat_stream.close();
1187    
1188     long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
1189     vm_usage = vsize / 1024.0;
1190     resident_set = rss * page_size_kb;
1191     }
1192 buchmann 1.38
1193 buchmann 1.45 TGraphAsymmErrors* produce_ratio_graph(TH1F *baseratio) {
1194 buchmann 1.38 int nbins=baseratio->GetNbinsX();
1195     double x[nbins];
1196     double y[nbins];
1197     double ex[nbins];
1198     double ey[nbins];
1199    
1200     for(int ibin=1;ibin<=nbins;ibin++) {
1201     x[ibin-1]=baseratio->GetBinCenter(ibin);
1202     y[ibin-1]=baseratio->GetBinContent(ibin);
1203     ex[ibin-1]=0.5*baseratio->GetBinWidth(ibin);
1204     ey[ibin-1]=baseratio->GetBinError(ibin);
1205     }
1206    
1207 buchmann 1.45 TGraphAsymmErrors *result = new TGraphAsymmErrors(nbins, x,y,ex,ex,ey,ey);
1208 buchmann 1.38 return result;
1209     }
1210    
1211 buchmann 1.53
1212     Double_t MarcosChi2TestX(const TH1* h1, const TH1* h2, Double_t &chi2, Int_t &ndf, Int_t &igood, Option_t *option)
1213     {
1214    
1215     TString opt = option;
1216     opt.ToUpper();
1217    
1218     Double_t prob = h1->Chi2TestX(h2,chi2,ndf,igood,option);
1219    
1220     if(opt.Contains("P")) {
1221     printf("Chi2 = %f, Prob = %g, NDF = %d, igood = %d\n", chi2,prob,ndf,igood);
1222     }
1223     if(opt.Contains("CHI2/NDF")) {
1224     if (ndf == 0) return 0;
1225     return chi2/ndf;
1226     }
1227     if(opt.Contains("CHI2")) {
1228     return chi2;
1229     }
1230    
1231     return prob;
1232     }
1233    
1234 fronga 1.58 void save_with_ratio(TH1F *nominator, TH1F *denominator, TVirtualPad *canvas, string savemeas, bool do_bpred_ratio=false, bool extendrange=false, string yaxistitle="ratio") {
1235 buchmann 1.45 //this function saves the pad being passed as well as a new one including the ratio.
1236     CompleteSave(canvas,savemeas);
1237    
1238 buchmann 1.38 float bottommargin=gStyle->GetPadBottomMargin();
1239     float canvas_height=gStyle->GetCanvasDefH();
1240     float canvas_width=gStyle->GetCanvasDefW();
1241     float ratiospace=0.25;// space the ratio should take up (relative to original pad)
1242    
1243     float ratiobottommargin=0.3;
1244     float ratiotopmargin=0.1;
1245    
1246     float xstretchfactor=((1-ratiospace)*(1-gStyle->GetPadTopMargin()))/((1)*ratiospace);
1247    
1248 buchmann 1.48 TCanvas *main_canvas = new TCanvas("main_canvas","main_canvas",(Int_t)canvas_width,(Int_t)(canvas_height*(1+ratiospace)));
1249 buchmann 1.38 TPad *mainpad = new TPad("mainpad","mainpad",0,1-(1.0/(1+ratiospace)),1,1);//top (main) pad
1250 buchmann 1.46 TPad *coverpad = new TPad("coverpad","coverpad",gStyle->GetPadLeftMargin()-0.008,1-(1.0/(1+ratiospace))-0.04,1,1-(1.0/(1+ratiospace))+0.103);//pad covering up the x scale
1251     TPad *bottompad = new TPad("bottompad", "Ratio Pad",0,0,1,(1-(1-bottommargin)/(1+ratiospace))-0.015); //bottom pad
1252 buchmann 1.38
1253     main_canvas->Range(0,0,1,1);
1254     main_canvas->SetBorderSize(0);
1255     main_canvas->SetFrameFillColor(0);
1256    
1257     mainpad->Draw();
1258     mainpad->cd();
1259     mainpad->Range(0,0,1,1);
1260     mainpad->SetFillColor(kWhite);
1261     mainpad->SetBorderSize(0);
1262     mainpad->SetFrameFillColor(0);
1263     canvas->Range(0,0,1,1);
1264     canvas->Draw("same");
1265     mainpad->Modified();
1266     main_canvas->cd();
1267 buchmann 1.46 coverpad->Draw();
1268     coverpad->cd();
1269     coverpad->Range(0,0,1,1);
1270     coverpad->SetFillColor(kWhite);
1271     coverpad->SetBorderSize(0);
1272     coverpad->SetFrameFillColor(0);
1273     coverpad->Modified();
1274     main_canvas->cd();
1275 buchmann 1.38 bottompad->SetTopMargin(ratiotopmargin);
1276     bottompad->SetBottomMargin(ratiobottommargin);
1277     bottompad->Draw();
1278     bottompad->cd();
1279     bottompad->Range(0,0,1,1);
1280     bottompad->SetFillColor(kWhite);
1281     TH1F *ratio = (TH1F*)nominator->Clone(GetNumericHistoName().c_str());
1282     ratio->Divide(denominator);
1283 buchmann 1.45
1284    
1285     TGraphAsymmErrors *eratio;
1286     if(!do_bpred_ratio) eratio = produce_ratio_graph(ratio);
1287     else {
1288     bool using_data=false;
1289     if((int)savemeas.find("Data")>0) using_data=true;
1290     eratio = histRatio(nominator,denominator,using_data,PlottingSetup::global_ratio_binning,false);
1291     for(int i=1;i<=ratio->GetNbinsX();i++) {
1292     ratio->SetBinContent(i,0);
1293     ratio->SetBinError(i,0);
1294     }
1295     }
1296 buchmann 1.38 eratio->SetFillColor(TColor::GetColor("#00ADE1"));
1297    
1298     ratio->SetTitle("");
1299     ratio->GetYaxis()->SetRangeUser(0.5,1.5);
1300 buchmann 1.45 if(do_bpred_ratio) ratio->GetYaxis()->SetRangeUser(0.0,2.0);
1301     if(extendrange) ratio->GetYaxis()->SetRangeUser(0.0,4.0);
1302 buchmann 1.38 ratio->GetXaxis()->SetTitle(nominator->GetXaxis()->GetTitle());
1303     ratio->GetXaxis()->CenterTitle();
1304 fronga 1.58 ratio->GetYaxis()->SetTitle(yaxistitle.c_str());
1305 buchmann 1.38 ratio->GetYaxis()->SetTitleOffset(0.4);
1306     ratio->GetYaxis()->CenterTitle();
1307     ratio->SetStats(0);
1308     ratio->GetXaxis()->SetLabelSize(xstretchfactor*ratio->GetXaxis()->GetLabelSize());
1309     ratio->GetYaxis()->SetLabelSize(xstretchfactor*ratio->GetYaxis()->GetLabelSize());
1310     ratio->GetXaxis()->SetTitleSize(xstretchfactor*gStyle->GetTitleSize());
1311     ratio->GetYaxis()->SetTitleSize(xstretchfactor*gStyle->GetTitleSize());
1312     ratio->GetYaxis()->SetNdivisions(502,false);
1313     ratio->SetFillColor(TColor::GetColor("#58D3F7"));
1314     ratio->SetMarkerSize(0);
1315     ratio->Draw("e2");
1316     eratio->Draw("2");
1317     ratio->Draw("same,axis");
1318     TLine *oneline = new TLine(ratio->GetXaxis()->GetBinLowEdge(1),1,ratio->GetXaxis()->GetBinLowEdge(ratio->GetNbinsX())+ratio->GetXaxis()->GetBinWidth(ratio->GetNbinsX()),1);
1319     oneline->SetLineStyle(2);
1320     oneline->SetLineColor(kBlue);
1321     oneline->Draw("same");
1322    
1323     main_canvas->cd();
1324     main_canvas->Modified();
1325     main_canvas->cd();
1326     main_canvas->SetSelected(main_canvas);
1327    
1328 buchmann 1.45 CompleteSave(main_canvas,savemeas+"_withratio");
1329 buchmann 1.53 bottompad->cd();
1330    
1331     Double_t chi2;
1332     Int_t ndf,igood;
1333     Double_t res=0.0;
1334     Double_t chi2prob = MarcosChi2TestX(nominator,denominator,chi2,ndf,igood,"UW");
1335    
1336     stringstream Chi2text;
1337     Chi2text << "#chi^{2} / ndf: " << chi2 << " / " << ndf;
1338     stringstream Chi2probtext;
1339     Chi2probtext << "#chi^{2} prob: " << chi2prob;
1340     TText* chi2box = write_text(0.02,0.11,Chi2text.str());
1341     chi2box->SetTextSize(0.08);
1342     chi2box->SetTextAlign(11);
1343     chi2box->Draw();
1344     TText* chi2probbox = write_text(0.02,0.04,Chi2probtext.str());
1345     chi2probbox->SetTextSize(0.08);
1346     chi2probbox->SetTextAlign(11);
1347     chi2probbox->Draw();
1348     CompleteSave(main_canvas,savemeas+"_withratio_and_Chi2");
1349    
1350     // float KS = nominator->KolmogorovTest(denominator);
1351     // stringstream KStext;
1352     // Chi2text << "KS = " << KS << endl;
1353     //cout << "Found : " << KStext.str() << endl;
1354    
1355    
1356 buchmann 1.45 delete main_canvas;
1357 buchmann 1.38 }
1358    
1359    
1360     TH1F* CollapseStack(THStack stack) {
1361     TH1F *bhist = ((TH1F*)((stack.GetHists())->At(0)));
1362     TH1F *basehisto = (TH1F*)bhist->Clone("base");
1363     TIter next(stack.GetHists());
1364     TH1F *h;
1365     int counter=0;
1366     while ((h=(TH1F*)next())) {
1367     counter++;
1368     if(counter==1) continue;
1369     basehisto->Add(h);
1370     }
1371     return basehisto;
1372     }
1373    
1374 buchmann 1.45 void save_with_ratio(TH1F *nominator, THStack denominator, TVirtualPad *canvas, string savemeas, bool do_bpred_ratio=false) {
1375     save_with_ratio(nominator, CollapseStack(denominator), canvas, savemeas, do_bpred_ratio);
1376 buchmann 1.38 }
1377    
1378 buchmann 1.40 void flag_this_change(string function, int line, int checked=0) {
1379 buchmann 1.38 stringstream peakmodificationwarning;
1380 buchmann 1.40 if(checked==0) peakmodificationwarning << "There's been a change on line " << line << " in function " << function << " that affects the functionality you're using. If you've checked that it works well please change the function call to flag_this_change(..,..,true) so this will only be an info instead of a warning :-) ";
1381     if(checked==1) peakmodificationwarning << "There's been a change on line " << line << " in function " << function << " that affects the functionality you're using. This modification has already been checked. Please produce the corresponding plot manually and then mark this as done (i.e. flag_this_change(..,..,2)";
1382     if(checked==2) peakmodificationwarning << "Xchecked: There's been a change on line " << line << " in function " << function << " that affects the functionality you're using. This modification has been checked and crosschecked.";
1383    
1384    
1385     if(checked==0) write_warning(function,peakmodificationwarning.str());
1386     // if(checked==1) write_info(function,peakmodificationwarning.str());
1387     peakmodificationwarning << " This modification has been checked and the changes have been reproduced. Checks completed.";
1388     if(checked==2) write_info(function,peakmodificationwarning.str());
1389     }
1390    
1391 buchmann 1.41 void write_analysis_type(bool isonpeak) {
1392     //http://www.network-science.de/ascii/, ogre
1393 buchmann 1.55 if(!PlottingSetup::publicmode) {
1394     if(isonpeak) {
1395 buchmann 1.42 dout << "\033[1;34m" << endl;
1396 buchmann 1.41 dout << " //\\\\ _ _ _ " << endl;
1397     dout << " // \\\\ ___ _ __ _ __ ___ __ _| | __ __ _ _ __ __ _| |_ _ ___(_)___" << endl;
1398     dout << " // \\\\ / _ \\| '_ \\| '_ \\ / _ \\/ _` | |/ / / _` | '_ \\ / _` | | | | / __| / __|" << endl;
1399     dout << " // \\\\ | (_) | | | | |_) | __/ (_| | < | (_| | | | | (_| | | |_| \\__ \\ \\__ \\" << endl;
1400     dout << "// \\\\ \\___/|_| |_| .__/ \\___|\\__,_|_|\\_\\ \\__,_|_| |_|\\__,_|_|\\__, |___/_|___/" << endl;
1401     dout << " |_| |___/" << endl;
1402 buchmann 1.55 } else {
1403 buchmann 1.42 dout << "\033[1;33m" << endl;
1404 buchmann 1.41 dout << " __ __ _ _ _ " << endl;
1405     dout << " ___ / _|/ _|_ __ ___ __ _| | __ __ _ _ __ __ _| |_ _ ___(_)___ " << endl;
1406     dout << " /\\ / _ \\| |_| |_| '_ \\ / _ \\/ _` | |/ / / _` | '_ \\ / _` | | | | / __| / __|" << endl;
1407     dout << " __/ \\__ | (_) | _| _| |_) | __/ (_| | < | (_| | | | | (_| | | |_| \\__ \\ \\__ \\" << endl;
1408     dout << " \\___/|_| |_| | .__/ \\___|\\__,_|_|\\_\\ \\__,_|_| |_|\\__,_|_|\\__, |___/_|___/" << endl;
1409     dout << " |_| |___/ " << endl;
1410 buchmann 1.55 }
1411     dout << "\033[0m" << endl;
1412 buchmann 1.41 }
1413     }
1414    
1415    
1416 buchmann 1.43 vector<string> StringSplit(string str, string delim)
1417     {
1418     vector<string> results;
1419    
1420     int cutAt;
1421     while( (cutAt = str.find_first_of(delim)) != str.npos )
1422     {
1423     if(cutAt > 0)
1424     {
1425     results.push_back(str.substr(0,cutAt));
1426     }
1427     str = str.substr(cutAt+1);
1428     }
1429     if(str.length() > 0)
1430     {
1431     results.push_back(str);
1432     }
1433     return results;
1434     }
1435 buchmann 1.41
1436 buchmann 1.43 void manually_set_jzb_cuts(vector<float> &jzb_cut,string jzbcut_string) {
1437     vector<string> jzbcutvector = StringSplit(jzbcut_string,",");
1438     for(int i=0;i<jzbcutvector.size();i++) {
1439     jzb_cut.push_back(atoi(jzbcutvector[i].c_str()));
1440     dout << "Added a JZB cut manually at " << atoi(jzbcutvector[i].c_str()) << endl;
1441     }
1442     }
1443 buchmann 1.41
1444 buchmann 1.44 void process_directory(TString directory, vector<string> &files)
1445     {
1446     DIR *dp;
1447     struct dirent *ep;
1448    
1449     dp = opendir (directory);
1450     if (dp != NULL)
1451     {
1452     while (ep = readdir (dp))
1453     {
1454     string filename=(string)ep->d_name;
1455     if(filename.find(".root")!=-1)
1456     {
1457     files.push_back(string(directory)+filename);
1458     }
1459     }
1460     (void) closedir (dp);
1461     }
1462     else
1463     perror ("Couldn't open the directory");
1464     }
1465 buchmann 1.41
1466 buchmann 1.52 /*string GetCompleteHostname() {
1467 buchmann 1.47 struct addrinfo hints, *info, *p;
1468     int gai_result;
1469     char hostname[1024];
1470     hostname[1023] = '\0';
1471     gethostname(hostname, 1023);
1472    
1473     string answer="GetCompleteHostname_ERROR";
1474    
1475     memset(&hints, 0, sizeof hints);
1476     hints.ai_family = AF_UNSPEC;
1477     hints.ai_socktype = SOCK_STREAM;
1478     hints.ai_flags = AI_CANONNAME;
1479    
1480     if ((gai_result = getaddrinfo(hostname, "http", &hints, &info)) != 0) {
1481     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(gai_result));
1482     }
1483    
1484     for(p = info; p != NULL; p = p->ai_next) {
1485     answer=p->ai_canonname;
1486     printf("hostname: %s\n", p->ai_canonname);
1487     }
1488     return answer;
1489 buchmann 1.52 }*/
1490 buchmann 1.47
1491 buchmann 1.53 const char* concatenate (const char* a, const char* b) {
1492     stringstream bla;
1493     bla << a << b;
1494     return bla.str().c_str();
1495     }
1496    
1497 buchmann 1.40 stringstream all_bugs;
1498    
1499     void bug_tracker(string function, int line, string description) {
1500     cout << "\033[1;31m .-. " << endl;
1501     cout << " o \\ .-. " << endl;
1502     cout << " .----.' \\ " << endl;
1503     cout << " .'o) / `. o " << endl;
1504     cout << " / | " << endl;
1505     cout << " \\_) /-. " << endl;
1506     cout << " '_.` \\ \\ " << endl;
1507     cout << " `. | \\ " << endl;
1508     cout << " | \\ | " << endl;
1509     cout << " .--/`-. / / " << endl;
1510     cout << " .'.-/`-. `. .\\| " << endl;
1511     cout << " /.' /`._ `- '-. " << endl;
1512     cout << " ____(|__/`-..`- '-._ \\ " << endl;
1513     cout << " |`------.'-._ ` ||\\ \\ " << endl;
1514     cout << " || # /-. ` / || \\| " << endl;
1515     cout << " || #/ `--' / /_::_|)__ " << endl;
1516     cout << " `|____|-._.-` / ||`--------` " << endl;
1517     cout << " \\-.___.` | / || # | " << endl;
1518     cout << " \\ | | || # # | " << endl;
1519     cout << " /`.___.'\\ |.`|________| " << endl;
1520     cout << " | /`.__.'|'.` " << endl;
1521     cout << " __/ \\ __/ \\ " << endl;
1522     cout << " /__.-.) /__.-.) LGB " << endl;
1523     cout << "" << endl;
1524     // bug ascii from : http://www.chris.com/ASCII/index.php?art=animals/insects/other
1525     cout << "There is a bug in " << function << " on line " << line << endl;
1526     cout << "The bug description is : " << description << endl;
1527     all_bugs << "There is a bug in " << function << " on line " << line << endl;
1528     all_bugs << "The bug description is : " << description << " \033[0m" << endl;
1529 buchmann 1.38 }
1530 buchmann 1.40
1531     //TODO: Write a bug summary at the end.
1532