1 // ------------------------------------------------------------------
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)
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,
16 // 1. Make the class drawable
17 // 2. Implement vertical lines in ascii print
18 // 3. Print output in HTML format
20 // Author: Michele Floris, CERN
21 // ------------------------------------------------------------------
23 #include "AliLatexTable.h"
26 #include "TObjString.h"
27 #include "TObjArray.h"
37 ClassImp(AliLatexTable);
39 AliLatexTable::AliLatexTable(Int_t ncol, TString format) : fNcol(0), fFormat(""), fRows(0), fCols(0), fNcolReady(0){
40 // constructor, specify number of cols
44 fRows = new TObjArray;
45 fCols = new TObjArray;
52 AliLatexTable::~AliLatexTable() {
55 if (fRows) delete fRows;
56 if (fCols) delete fCols;
60 void AliLatexTable::SetNextCol(Int_t val){
61 // Set next column in current row - integer
63 sprintf(col, " %d ", val);
68 void AliLatexTable::SetNextCol(Int_t val, Int_t err){
70 // Set next column in current row - int +- int
72 sprintf(col, " $%d \\pm %d$ ", val, err);
77 void AliLatexTable::SetNextCol(Double_t val, Int_t scientificNotation){
79 // Set next column in current row - double, specify resolution
82 if(scientificNotation >= 0) {
85 // cout << format << endl;
86 Double_t mantissa, exp;
87 GetMantissaAndExpBase10(val, mantissa, exp);
90 sprintf(format, " $%%%d.%df $", scientificNotation, scientificNotation);
91 sprintf(col, format, mantissa);
94 sprintf(format, " $%%%d.%df \\cdot 10^{%%0.0f} $", scientificNotation, scientificNotation);
95 sprintf(col, format, mantissa, exp);
103 } else if (scientificNotation < -1) {
105 sprintf(format, " $%%%d.%df $", -scientificNotation,-scientificNotation);
106 sprintf(col, format , val);
109 sprintf(col, " %f ", val);
114 void AliLatexTable::SetNextCol(Double_t val, Double_t err, Int_t scientificNotation){
116 // Set next column in current row - double +- double, specify resolution
118 // if scientific notation is != -1 is used to determine number of
121 //if it is > 0 exp notation is used
123 //if it is < -1 number is truncated to the number of digits after
124 //point dictated by scientificNotation,
127 if(scientificNotation >=0 ) {
129 Double_t mantissa, exp;
130 GetMantissaAndExpBase10(val, mantissa, exp);
132 Double_t mantissa_err, exp_err;
133 GetMantissaAndExpBase10(err, mantissa_err, exp_err);
135 Int_t nSigDigits =TMath::Nint(exp - exp_err);
136 if(scientificNotation != 0) nSigDigits = nSigDigits + scientificNotation - 1;
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));
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);
150 //cout << format << endl;
154 } else if (scientificNotation < -1) {
156 sprintf(format, " $%%%d.%df \\pm %%%d.%df $", -scientificNotation,-scientificNotation,-scientificNotation,-scientificNotation);
157 sprintf(col, format , val, err);
161 sprintf(col, " $%f \\pm %f$ ", val, err);
166 void AliLatexTable::SetNextCol(Double_t val, Double_t err, Double_t errSyst, Int_t scientificNotation){
168 // Set next column in current row - double +- double +- double, specify resolution
170 // if scientific notation is != -1 is used to determine number of
173 //if it is > 0 exp notation is used
175 //if it is < -1 number is truncated to the number of digits after
176 //point dictated by scientificNotation,
179 if(scientificNotation >=0 ) {
181 Double_t mantissa, exp;
182 GetMantissaAndExpBase10(val, mantissa, exp);
184 Double_t mantissa_err, exp_err;
185 GetMantissaAndExpBase10(err, mantissa_err, exp_err);
187 Double_t mantissa_errsyst, exp_errsyst;
188 GetMantissaAndExpBase10(errSyst, mantissa_errsyst, exp_errsyst);
190 Int_t nSigDigits =TMath::Nint(exp - exp_err);
191 if(scientificNotation != 0) nSigDigits = nSigDigits + scientificNotation - 1;
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));
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),
212 //cout << format << endl;
216 } else if (scientificNotation < -1) {
218 sprintf(format, " $%%%d.%df \\pm %%%d.%df \\pm %%%d.%df $", -scientificNotation,-scientificNotation,-scientificNotation,-scientificNotation, -scientificNotation,-scientificNotation);
219 sprintf(col, format , val, err);
223 sprintf(col, " $%f \\pm %f \\pm %f$ ", val, err, errSyst);
228 // void AliLatexTable::SetNextColPrintf(const char *va_(fmt), ...){
231 // const Int_t buf_size = 1024; // hope it's long enough
232 // char colBuffer[buf_size];
235 // va_start(ap, va_(fmt));
236 // Int_t n = vsnprintf(colBuffer, buf_size, fmt, ap);
238 // if (n == -1 || n >= buf_size) {
239 // Error("SetNextCol", "vsnprintf error!");
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));
248 // SetNextCol(colBuffer);
252 void AliLatexTable::SetNextCol(TString val){
254 // Set next column in current row - tstring
256 fCols->Add(new TObjString(val));
261 void AliLatexTable::InsertCustomRow(TString row){
262 // insert a full row from string. Make sure you have all the columns
263 fRows->Add(new TObjString(row));
268 void AliLatexTable::InsertRow(){
270 // Insert the row, based on all the individual columns
272 if ( fNcolReady != fNcol) {
273 Warning("InsertRow", "Wrong number of cols: %d (!= %d)", fNcolReady, fNcol);
277 for(Int_t icol = 0; icol < fNcol; icol++){
278 row = row + ((TObjString*) fCols->At(icol))->String();
279 if(icol != (fNcol-1)) row = row + " & ";
283 fRows->Add(new TObjString(row));
290 void AliLatexTable::InsertHline(){
292 // insert an horizontal line
293 fRows->Add(new TObjString("\\hline"));
298 Int_t * AliLatexTable::GetColWidths() {
300 // Compute the width of columns, for nice ascii printing
302 Int_t * col_widths= new Int_t[fNcol];
303 Int_t nrow = fRows->GetEntriesFast();
305 for(Int_t icol = 0; icol < fNcol; icol++){
306 col_widths[icol] = 0;
310 for(Int_t irow = 0; irow < nrow; irow++){
311 TString row(((TObjString*) fRows->At(irow))->String());
312 if(row.Contains("\\hline"))continue;
314 StripLatex(row, "ASCII");
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);
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;
330 void AliLatexTable::PrintTable(Option_t * opt){
332 // Print the table on screen. You can specify the format with opt.
333 // Currently supported:
335 // "ASCII" -> plain ASCII
336 // "HTML" -> HTML, to be improved
338 if(TString(opt) == "ASCII" || TString(opt)=="HTML") {
340 Int_t nrow = fRows->GetEntriesFast();
342 Int_t * col_widths = GetColWidths();
344 Int_t total_lenght = 0;
345 for(Int_t icol = 0; icol < fNcol; icol++) total_lenght = total_lenght + col_widths[icol] + 2 ;
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("-");
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();
360 sprintf(format, "%%%ds", col_widths[icol] + 2);
361 printf(format, colstr);
372 cout << "\\begin{tabular}{"<<fFormat<<"}"<<endl;
374 Int_t nrow = fRows->GetEntriesFast();
376 for(Int_t irow = 0; irow < nrow; irow++){
377 cout << ((TObjString*) fRows->At(irow))->String() << endl;
380 cout << "\\end{tabular}" << endl;
385 // void AliLatexTable::ParseExponent(TString &expo){
386 // // TString parseExponent = col;
387 // TRegexp re = "e[+-][0-9][0-9]";
388 // // cout << col << endl;
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;
399 // expo.ReplaceAll(expo(re), replacement);
400 // // cout << "A: " << expo << endl;
401 // // recursion to parse all exponents
402 // if (expo.Contains(re)) ParseExponent(expo);
404 // else Warning("", "Error parsing exponent");
407 void AliLatexTable::GetMantissaAndExpBase10(Double_t num, Double_t &man, Double_t &exp) {
409 // Helper used to get mantissa and exponent
411 exp = TMath::Floor(TMath::Log10(TMath::Abs(num)));
412 man = num / TMath::Power(10, exp);
414 // cout << "" << endl;
415 // cout << num << " = " << man << " x10^{"<<exp<<"} " << endl;
420 void AliLatexTable::StripLatex(TString &text, TString format) {
422 // Strip latex away for ascii and html printing. Replaces latex
423 // command with corresponding text/tags
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>", "⟩");
435 text.ReplaceAll("\\left<", "⟨");
436 text.ReplaceAll("\\rangle", "⟩");
437 text.ReplaceAll("\\langle", "⟨");
439 if(text.Contains("multicolumn")) {
440 // cout << "col " << text.Data() << endl;
441 // in case of multicol span, replace first column with content and
443 TObjArray * array = TPRegexp("multicolumn\{(.*)\\}\{.*\\}\{(.*)\\}").MatchS(text); // Added double \\ because gcc 4 triggers hard error on unknown escape sequence. Hope it still works...
444 const TString content = ((TObjString *)array->At(2))->GetString();
445 Int_t nspan = ((TObjString *)array->At(1))->GetString().Atoi();
447 // cout << "ns " << nspan << ((TObjString *)array->At(1))->GetString() << endl;
448 // cout << "t " << text << endl;
450 for(Int_t ispan = 1; ispan < nspan; ispan++){
453 // cout << "t " << text << endl;
458 text.ReplaceAll("\\mathrm", "");
460 text.ReplaceAll("\\", "");
461 text.Strip(TString::EStripType(1), ' ');