ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/cbrown/Development/Plotting/Modules/GeneralToolBox.C
Revision: 1.6
Committed: Wed Apr 18 12:48:24 2012 UTC (13 years ago) by buchmann
Content type: text/plain
Branch: MAIN
Changes since 1.5: +4 -2 lines
Log Message:
Ported changes from paper to this version. In matters of style, changes were overruled

File Contents

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