Added task for efficiency computation, aligned with revised code.
[u/mrichter/AliRoot.git] / PWG2 / SPECTRA / Fit / AliLatexTable.cxx
CommitLineData
4c0d7bc7 1// ------------------------------------------------------------------
2//
3// AliLatexTable
4//
5// This class is used to produce tables using latex sintax. It can
6// than print the table as Latex source code (to be pasted on a paper)
7// or ASCII.
8//
9// The basic idea is that you add columns one after the other with the
10// SetNextCol method and than you insert this row. The SetNextCol
11// method comes in different flavours to alow the insertion of
12// different type of values (numbers with or without errors,
13// strings...).
14//
15// TODO:
16// 1. Make the class drawable
17// 2. Implement vertical lines in ascii print
18// 3. Print output in HTML format
19//
20// Author: Michele Floris, CERN
21// ------------------------------------------------------------------
22
23#include "AliLatexTable.h"
24#include "TString.h"
25#include "TRegexp.h"
26#include "TObjString.h"
27#include "TObjArray.h"
28#include <stdarg.h>
29#include "snprintf.h"
30#include "Varargs.h"
31#include "TPRegexp.h"
32#include "TMath.h"
33#include <iostream>
34
35using namespace std;
36
fff5b67e 37ClassImp(AliLatexTable)
4c0d7bc7 38
39AliLatexTable::AliLatexTable(Int_t ncol, TString format) : fNcol(0), fFormat(""), fRows(0), fCols(0), fNcolReady(0){
40 // constructor, specify number of cols
41 fNcol = ncol;
42 fFormat = format;
43 fNcolReady = 0;
44 fRows = new TObjArray;
45 fCols = new TObjArray;
46
47 fRows->SetOwner();
48 fCols->SetOwner();
49}
50
51
52AliLatexTable::~AliLatexTable() {
53
54 // dtor
55 if (fRows) delete fRows;
56 if (fCols) delete fCols;
57
58}
59
60void AliLatexTable::SetNextCol(Int_t val){
61 // Set next column in current row - integer
62 char col[200];
63 sprintf(col, " %d ", val);
64 SetNextCol(col);
65
66}
67
68void AliLatexTable::SetNextCol(Int_t val, Int_t err){
69
70 // Set next column in current row - int +- int
71 char col[200];
72 sprintf(col, " $%d \\pm %d$ ", val, err);
73 SetNextCol(col);
74
75}
76
77void AliLatexTable::SetNextCol(Double_t val, Int_t scientificNotation){
78
79 // Set next column in current row - double, specify resolution
80
81 char col[200];
82 if(scientificNotation >= 0) {
83 char format[100];
84
85 // cout << format << endl;
86 Double_t mantissa, exp;
87 GetMantissaAndExpBase10(val, mantissa, exp);
88
89 if (exp == 0) {
90 sprintf(format, " $%%%d.%df $", scientificNotation, scientificNotation);
91 sprintf(col, format, mantissa);
92 }
93 else {
94 sprintf(format, " $%%%d.%df \\cdot 10^{%%0.0f} $", scientificNotation, scientificNotation);
95 sprintf(col, format, mantissa, exp);
96 }
97
98
99
100
101 SetNextCol(col);
102
103 } else if (scientificNotation < -1) {
104 char format[100];
105 sprintf(format, " $%%%d.%df $", -scientificNotation,-scientificNotation);
106 sprintf(col, format , val);
107 SetNextCol(col);
108 } else {
109 sprintf(col, " %f ", val);
110 SetNextCol(col);
111 }
112
113}
114void AliLatexTable::SetNextCol(Double_t val, Double_t err, Int_t scientificNotation){
115
116 // Set next column in current row - double +- double, specify resolution
117
118 // if scientific notation is != -1 is used to determine number of
119 // digits in error
120
121 //if it is > 0 exp notation is used
122
123 //if it is < -1 number is truncated to the number of digits after
124 //point dictated by scientificNotation,
125
126 char col[200];
127 if(scientificNotation >=0 ) {
128
129 Double_t mantissa, exp;
130 GetMantissaAndExpBase10(val, mantissa, exp);
131
132 Double_t mantissa_err, exp_err;
133 GetMantissaAndExpBase10(err, mantissa_err, exp_err);
134
135 Int_t nSigDigits =TMath::Nint(exp - exp_err);
136 if(scientificNotation != 0) nSigDigits = nSigDigits + scientificNotation - 1;
137
138
139 char format[100];
140 if (exp == 0) {
141 sprintf(format, " $%%%d.%df \\pm %%%d.%df $", nSigDigits, nSigDigits, nSigDigits, nSigDigits);
142 sprintf(col, format, mantissa, mantissa_err/TMath::Power(10,exp - exp_err));
143 }
144 else {
145 sprintf(format, " $%%%d.%df \\pm %%%d.%df \\cdot 10^{%%0.0f}$", nSigDigits, nSigDigits, nSigDigits, nSigDigits);
146 sprintf(col, format, mantissa, mantissa_err/TMath::Power(10,exp - exp_err), exp);
147 }
148
149
150 //cout << format << endl;
151
152 SetNextCol(col);
153
154 } else if (scientificNotation < -1) {
155 char format[100];
156 sprintf(format, " $%%%d.%df \\pm %%%d.%df $", -scientificNotation,-scientificNotation,-scientificNotation,-scientificNotation);
157 sprintf(col, format , val, err);
158 SetNextCol(col);
159 }
160 else {
161 sprintf(col, " $%f \\pm %f$ ", val, err);
162 SetNextCol(col);
163 }
164}
165
166void AliLatexTable::SetNextCol(Double_t val, Double_t err, Double_t errSyst, Int_t scientificNotation){
167
168 // Set next column in current row - double +- double +- double, specify resolution
169
170 // if scientific notation is != -1 is used to determine number of
171 // digits in error
172
173 //if it is > 0 exp notation is used
174
175 //if it is < -1 number is truncated to the number of digits after
176 //point dictated by scientificNotation,
177
178 char col[200];
179 if(scientificNotation >=0 ) {
180
181 Double_t mantissa, exp;
182 GetMantissaAndExpBase10(val, mantissa, exp);
183
184 Double_t mantissa_err, exp_err;
185 GetMantissaAndExpBase10(err, mantissa_err, exp_err);
186
187 Double_t mantissa_errsyst, exp_errsyst;
188 GetMantissaAndExpBase10(errSyst, mantissa_errsyst, exp_errsyst);
189
190 Int_t nSigDigits =TMath::Nint(exp - exp_err);
191 if(scientificNotation != 0) nSigDigits = nSigDigits + scientificNotation - 1;
192
193
194 char format[100];
195 if (exp == 0) {
196 sprintf(format, " $%%%d.%df \\pm %%%d.%df \\pm %%%d.%df $",
197 nSigDigits, nSigDigits, nSigDigits, nSigDigits, nSigDigits, nSigDigits);
198 sprintf(col, format, mantissa,
199 mantissa_err/TMath::Power(10,exp - exp_err),
200 mantissa_errsyst/TMath::Power(10,exp - exp_errsyst));
201 }
202 else {
203 sprintf(format, " $%%%d.%df \\pm %%%d.%df \\pm %%%d.%df \\cdot 10^{%%0.0f}$",
204 nSigDigits, nSigDigits, nSigDigits, nSigDigits, nSigDigits, nSigDigits);
205 sprintf(col, format, mantissa,
206 mantissa_err/TMath::Power(10,exp - exp_err),
207 mantissa_errsyst/TMath::Power(10,exp - exp_errsyst),
208 exp);
209 }
210
211
212 //cout << format << endl;
213
214 SetNextCol(col);
215
216 } else if (scientificNotation < -1) {
217 char format[100];
218 sprintf(format, " $%%%d.%df \\pm %%%d.%df \\pm %%%d.%df $", -scientificNotation,-scientificNotation,-scientificNotation,-scientificNotation, -scientificNotation,-scientificNotation);
219 sprintf(col, format , val, err);
220 SetNextCol(col);
221 }
222 else {
223 sprintf(col, " $%f \\pm %f \\pm %f$ ", val, err, errSyst);
224 SetNextCol(col);
225 }
226}
227
228// void AliLatexTable::SetNextColPrintf(const char *va_(fmt), ...){
229
230
231// const Int_t buf_size = 1024; // hope it's long enough
232// char colBuffer[buf_size];
233
234// va_list ap;
235// va_start(ap, va_(fmt));
236// Int_t n = vsnprintf(colBuffer, buf_size, fmt, ap);
237
238// if (n == -1 || n >= buf_size) {
239// Error("SetNextCol", "vsnprintf error!");
240// }
241
242// va_end(ap);
243
244// // for(int iobj=0; iobj<num; iobj++){ //Loop until all objects are added
245// // TH1 * obj = (TH1 *) va_arg(arguments, void *);
246// // returnValue = returnValue && AddObject(obj,(char*)fOptMany.Data(), EColor(iobj+1));
247// // }
248// SetNextCol(colBuffer);
249// }
250
251
252void AliLatexTable::SetNextCol(TString val){
253
254 // Set next column in current row - tstring
255
256 fCols->Add(new TObjString(val));
257 fNcolReady++;
258
259}
260
261void AliLatexTable::InsertCustomRow(TString row){
262 // insert a full row from string. Make sure you have all the columns
263 fRows->Add(new TObjString(row));
264}
265
266
267
268void AliLatexTable::InsertRow(){
269
270 // Insert the row, based on all the individual columns
271
272 if ( fNcolReady != fNcol) {
273 Warning("InsertRow", "Wrong number of cols: %d (!= %d)", fNcolReady, fNcol);
274 }
275
276 TString row = "";
277 for(Int_t icol = 0; icol < fNcol; icol++){
278 row = row + ((TObjString*) fCols->At(icol))->String();
279 if(icol != (fNcol-1)) row = row + " & ";
280 }
281 row+="\\\\";
282
283 fRows->Add(new TObjString(row));
284
285 fNcolReady = 0;
286 fCols->Clear();
287
288}
289
290void AliLatexTable::InsertHline(){
291
292 // insert an horizontal line
293 fRows->Add(new TObjString("\\hline"));
294
295
296}
297
298Int_t * AliLatexTable::GetColWidths() {
299
300 // Compute the width of columns, for nice ascii printing
301
302 Int_t * col_widths= new Int_t[fNcol];
303 Int_t nrow = fRows->GetEntriesFast();
304
305 for(Int_t icol = 0; icol < fNcol; icol++){
306 col_widths[icol] = 0;
307 }
308
309
310 for(Int_t irow = 0; irow < nrow; irow++){
311 TString row(((TObjString*) fRows->At(irow))->String());
312 if(row.Contains("\\hline"))continue;
313
314 StripLatex(row, "ASCII");
315
316 TObjArray * cols = row.Tokenize("&");
317 if(cols->GetEntries() != fNcol) {
318 Error("GetColWidths", "Wrong number of cols in row %s: %d - %d", row.Data(), cols->GetEntries(), fNcol);
319 }
320 for(Int_t icol = 0; icol < fNcol; icol++){
321 Int_t w = ((TObjString *) cols->At(icol))->String().Length();
322 if (w>col_widths[icol]) col_widths[icol] = w;
323 }
324
325 }
326
327 return col_widths;
328}
329
330void AliLatexTable::PrintTable(Option_t * opt){
331
332 // Print the table on screen. You can specify the format with opt.
333 // Currently supported:
334 // "" -> LaTeX
335 // "ASCII" -> plain ASCII
336 // "HTML" -> HTML, to be improved
337
338 if(TString(opt) == "ASCII" || TString(opt)=="HTML") {
339
340 Int_t nrow = fRows->GetEntriesFast();
341
342 Int_t * col_widths = GetColWidths();
343
344 Int_t total_lenght = 0;
345 for(Int_t icol = 0; icol < fNcol; icol++) total_lenght = total_lenght + col_widths[icol] + 2 ;
346
347
348 for(Int_t irow = 0; irow < nrow; irow++){
349 TString row = ((TObjString*) fRows->At(irow))->String();
350 if (row.Contains("\\hline") ){
351 for(Int_t il = 0; il < total_lenght; il++) printf("-");
352 printf("\n");
353 continue;
354 }
355 StripLatex(row, opt);
356 TObjArray * cols = row.Tokenize("&");
357 for(Int_t icol = 0; icol < fNcol; icol++){
358 const char * colstr = ((TObjString *) cols->At(icol))->String().Data();
359 char format [200];
360 sprintf(format, "%%%ds", col_widths[icol] + 2);
361 printf(format, colstr);
362
363 }
364 printf ("\n");
365 }
366
367
368 return;
369 }
370
371
372 cout << "\\begin{tabular}{"<<fFormat<<"}"<<endl;
373
374 Int_t nrow = fRows->GetEntriesFast();
375
376 for(Int_t irow = 0; irow < nrow; irow++){
377 cout << ((TObjString*) fRows->At(irow))->String() << endl;
378 }
379
380 cout << "\\end{tabular}" << endl;
381
382
383}
384
385// void AliLatexTable::ParseExponent(TString &expo){
386// // TString parseExponent = col;
387// TRegexp re = "e[+-][0-9][0-9]";
388// // cout << col << endl;
389
390// if(expo.Contains(re)){
391// Int_t index = expo.Index(re);
392// TString replacement = "\\cdot 10^{";
393// replacement = replacement + expo(index+1, 3) +"}";
394// // cout << replacement <<" --- "<< endl;
395// replacement.ReplaceAll("+","");
396// // cout << "B: " << expo << endl;
397// // cout << "RE " << expo(re) << endl;
398
399// expo.ReplaceAll(expo(re), replacement);
400// // cout << "A: " << expo << endl;
401// // recursion to parse all exponents
402// if (expo.Contains(re)) ParseExponent(expo);
403// }
404// else Warning("", "Error parsing exponent");
405// }
406
407void AliLatexTable::GetMantissaAndExpBase10(Double_t num, Double_t &man, Double_t &exp) {
408
409 // Helper used to get mantissa and exponent
410
411 exp = TMath::Floor(TMath::Log10(TMath::Abs(num)));
412 man = num / TMath::Power(10, exp);
413
414// cout << "" << endl;
415// cout << num << " = " << man << " x10^{"<<exp<<"} " << endl;
416
417
418}
419
420void AliLatexTable::StripLatex(TString &text, TString format) {
421
422 // Strip latex away for ascii and html printing. Replaces latex
423 // command with corresponding text/tags
424
425 text.ReplaceAll("\\cdot", "x");
426 text.ReplaceAll("\\pm", "+-");
427 text.ReplaceAll("$", "");
428 if (format == "ASCII") {
429 text.ReplaceAll("\\right>", ">");
430 text.ReplaceAll("\\left<", "<");
431 text.ReplaceAll("\\rangle", ">");
432 text.ReplaceAll("\\langle", "<");
433 } else if (format == "HTML") {
434 text.ReplaceAll("\\right>", "&rang;");
435 text.ReplaceAll("\\left<", "&lang;");
436 text.ReplaceAll("\\rangle", "&rang;");
437 text.ReplaceAll("\\langle", "&lang;");
438 }
439 if(text.Contains("multicolumn")) {
440 // cout << "col " << text.Data() << endl;
441 // in case of multicol span, replace first column with content and
442 // add n empty cols
fff5b67e 443 TObjArray * array = TPRegexp("multicolumn\\{(.*)\\}\\{.*\\}\\{(.*)\\}").MatchS(text); // Added double \\ because gcc 4 triggers hard error on unknown escape sequence. Hope it still works...
4c0d7bc7 444 const TString content = ((TObjString *)array->At(2))->GetString();
445 Int_t nspan = ((TObjString *)array->At(1))->GetString().Atoi();
446 text = content;
447// cout << "ns " << nspan << ((TObjString *)array->At(1))->GetString() << endl;
448// cout << "t " << text << endl;
449
450 for(Int_t ispan = 1; ispan < nspan; ispan++){
451 text+=" & ";
452 }
453 // cout << "t " << text << endl;
454
455
456 }
457
458 text.ReplaceAll("\\mathrm", "");
459
460 text.ReplaceAll("\\", "");
461 text.Strip(TString::EStripType(1), ' ');
462
463}