ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/cbrown/AnalysisFramework/Plotting/Modules/GeneralToolBox.C
Revision: 1.58
Committed: Wed Jan 18 14:06:12 2012 UTC (13 years, 3 months ago) by fronga
Content type: text/plain
Branch: MAIN
Changes since 1.57: +6 -5 lines
Log Message:
Add possibility to change y axis title in ratio plot.

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