#include "AliLatexTable.h"
#include "TString.h"
#include "TRegexp.h"
#include "TObjString.h"
#include "TObjArray.h"
#include <stdarg.h>
#include "snprintf.h"
#include "Varargs.h"
#include "TPRegexp.h"
#include "TMath.h"
#include <iostream>
#include <fstream>
#include "AliLog.h"
using namespace std;
ClassImp(AliLatexTable)
AliLatexTable::AliLatexTable() : fNcol(0), fFormat(""), fRows(0), fCols(0), fNcolReady(0){
fNcol = 1;
fFormat = "c";
fNcolReady = 0;
fRows = new TObjArray;
fCols = new TObjArray;
fRows->SetOwner();
fCols->SetOwner();
}
AliLatexTable::AliLatexTable(Int_t ncol, TString format) : fNcol(0), fFormat(""), fRows(0), fCols(0), fNcolReady(0){
fNcol = ncol;
fFormat = format;
fNcolReady = 0;
fRows = new TObjArray;
fCols = new TObjArray;
fRows->SetOwner();
fCols->SetOwner();
}
AliLatexTable::~AliLatexTable() {
if (fRows) delete fRows;
if (fCols) delete fCols;
}
void AliLatexTable::SetNextCol(Int_t val){
char col[200];
snprintf(col, 200, " %d ", val);
SetNextCol(col);
}
void AliLatexTable::SetNextCol(Int_t val, Int_t err){
char col[200];
snprintf(col, 200, " $%d \\pm %d$ ", val, err);
SetNextCol(col);
}
void AliLatexTable::SetNextCol(Double_t val, Int_t scientificNotation, Bool_t rounding){
char col[200];
if(rounding) {
if(scientificNotation >= 0) {
char format[100];
Double_t mantissa, exp;
GetMantissaAndExpBase10(val, mantissa, exp);
if (exp == 0) {
snprintf(format, 100," $%%%d.%df $", scientificNotation, scientificNotation);
snprintf(col, 200, format, mantissa);
}
else {
snprintf(format, 100," $%%%d.%df \\cdot 10^{%%0.0f} $", scientificNotation, scientificNotation);
snprintf(col, 200,format, mantissa, exp);
}
SetNextCol(col);
} else {
char format[100];
snprintf(format, 100," $%%%d.%df $", -scientificNotation,-scientificNotation);
snprintf(col, 200, format , TMath::Nint(val*TMath::Power(10,-scientificNotation))/TMath::Power(10,-scientificNotation));
SetNextCol(col);
}
}else {
snprintf(col,200, " %f ", val);
SetNextCol(col);
}
}
void AliLatexTable::SetNextCol(Double_t val, Double_t err, Int_t scientificNotation, Bool_t rounding){
char col[200];
if(rounding) {
if(scientificNotation >=0 ) {
Double_t mantissa, exp;
GetMantissaAndExpBase10(val, mantissa, exp);
Double_t mantissa_err, exp_err;
GetMantissaAndExpBase10(err, mantissa_err, exp_err);
Int_t nSigDigits =TMath::Nint(exp - exp_err);
if(scientificNotation != 0) nSigDigits = nSigDigits + scientificNotation - 1;
char format[100];
if (exp == 0) {
snprintf(format, 100," $%%%d.%df \\pm %%%d.%df $", nSigDigits, nSigDigits, nSigDigits, nSigDigits);
snprintf(col, 200,format, mantissa, mantissa_err/TMath::Power(10,exp - exp_err));
}
else {
snprintf(format, 100, " $%%%d.%df \\pm %%%d.%df \\cdot 10^{%%0.0f}$", nSigDigits, nSigDigits, nSigDigits, nSigDigits);
snprintf(col, 200, format, mantissa, mantissa_err/TMath::Power(10,exp - exp_err), exp);
}
SetNextCol(col);
} else {
char format[100];
snprintf(format, 100, " $%%%d.%df \\pm %%%d.%df $", -scientificNotation,-scientificNotation,-scientificNotation,-scientificNotation);
snprintf(col, 200, format , TMath::Nint(val*TMath::Power(10,-scientificNotation))/TMath::Power(10,-scientificNotation), TMath::Nint(err*TMath::Power(10,-scientificNotation))/TMath::Power(10,-scientificNotation));
SetNextCol(col);
}
}
else {
snprintf(col, 200, " $%f \\pm %f$ ", val, err);
SetNextCol(col);
}
}
void AliLatexTable::SetNextCol(Double_t val, Double_t err, Double_t errSyst, Int_t scientificNotation, Bool_t rounding){
char col[200];
if (rounding) {
if(scientificNotation >=0 ) {
Double_t mantissa, exp;
GetMantissaAndExpBase10(val, mantissa, exp);
Double_t mantissa_err, exp_err;
GetMantissaAndExpBase10(err, mantissa_err, exp_err);
Double_t mantissa_errsyst, exp_errsyst;
GetMantissaAndExpBase10(errSyst, mantissa_errsyst, exp_errsyst);
Int_t nSigDigits =TMath::Nint(exp - exp_err);
if(scientificNotation != 0) nSigDigits = nSigDigits + scientificNotation - 1;
char format[100];
if (exp == 0) {
snprintf(format, 100, " $%%%d.%df \\pm %%%d.%df \\pm %%%d.%df $",
nSigDigits, nSigDigits, nSigDigits, nSigDigits, nSigDigits, nSigDigits);
snprintf(col, 200, format, mantissa,
mantissa_err/TMath::Power(10,exp - exp_err),
mantissa_errsyst/TMath::Power(10,exp - exp_errsyst));
}
else {
snprintf(format, 100, " $%%%d.%df \\pm %%%d.%df \\pm %%%d.%df \\cdot 10^{%%0.0f}$",
nSigDigits, nSigDigits, nSigDigits, nSigDigits, nSigDigits, nSigDigits);
snprintf(col, 200, format, mantissa,
mantissa_err/TMath::Power(10,exp - exp_err),
mantissa_errsyst/TMath::Power(10,exp - exp_errsyst),
exp);
}
SetNextCol(col);
} else {
char format[100];
snprintf(format, 100, " $%%%d.%df \\pm %%%d.%df \\pm %%%d.%df $", -scientificNotation,-scientificNotation,-scientificNotation,-scientificNotation, -scientificNotation,-scientificNotation);
snprintf(col, 200, format ,TMath::Nint(val*TMath::Power(10,-scientificNotation))/TMath::Power(10,-scientificNotation), TMath::Nint(err*TMath::Power(10,-scientificNotation))/TMath::Power(10,-scientificNotation), TMath::Nint(errSyst*TMath::Power(10,-scientificNotation))/TMath::Power(10,-scientificNotation));
SetNextCol(col);
}
}
else {
snprintf(col, 200, " $%f \\pm %f \\pm %f$ ", val, err, errSyst);
SetNextCol(col);
}
}
void AliLatexTable::SetNextCol(TString val){
fCols->Add(new TObjString(val));
fNcolReady++;
}
void AliLatexTable::InsertCustomRow(TString row){
fRows->Add(new TObjString(row));
}
void AliLatexTable::InsertRow(){
if ( fNcolReady != fNcol) {
Warning("InsertRow", "Wrong number of cols: %d (!= %d)", fNcolReady, fNcol);
}
TString row = "";
for(Int_t icol = 0; icol < fNcol; icol++){
row = row + ((TObjString*) fCols->At(icol))->String();
if(icol != (fNcol-1)) row = row + " & ";
}
row+="\\\\";
fRows->Add(new TObjString(row));
fNcolReady = 0;
fCols->Clear();
}
void AliLatexTable::InsertHline(){
fRows->Add(new TObjString("\\hline"));
}
Int_t * AliLatexTable::GetColWidths() {
Int_t * col_widths= new Int_t[fNcol];
Int_t nrow = fRows->GetEntriesFast();
for(Int_t icol = 0; icol < fNcol; icol++){
col_widths[icol] = 0;
}
for(Int_t irow = 0; irow < nrow; irow++){
TString row(((TObjString*) fRows->At(irow))->String());
if(row.Contains("\\hline"))continue;
StripLatex(row, "ASCII");
TObjArray * cols = row.Tokenize("&");
if(cols->GetEntries() != fNcol) {
Error("GetColWidths", "Wrong number of cols in row %s: %d - %d", row.Data(), cols->GetEntries(), fNcol);
}
for(Int_t icol = 0; icol < fNcol; icol++){
Int_t w = ((TObjString *) cols->At(icol))->String().Length();
if (w>col_widths[icol]) col_widths[icol] = w;
}
delete cols;
}
return col_widths;
}
void AliLatexTable::PrintTable(Option_t * opt){
if(TString(opt) == "ASCII" || TString(opt)=="HTML" || TString(opt)=="CSV" || TString(opt)=="TWIKI") {
Int_t nrow = fRows->GetEntriesFast();
Int_t * colWidths = GetColWidths();
Int_t total_lenght = 0;
for(Int_t icol = 0; icol < fNcol; icol++) total_lenght = total_lenght + colWidths[icol] + 2 ;
for(Int_t irow = 0; irow < nrow; irow++){
TString row = ((TObjString*) fRows->At(irow))->String();
if (row.Contains("\\hline")){
if (TString(opt)!="CSV" && TString(opt)!="TWIKI") {
for(Int_t il = 0; il < total_lenght; il++) printf("-");
printf("\n");
}
continue;
}
StripLatex(row, opt);
TObjArray * cols = row.Tokenize("&");
if (TString(opt)=="TWIKI") printf(" | ");
for(Int_t icol = 0; icol < fNcol; icol++){
TString strTmp = ((TObjString *) cols->At(icol))->String();
if(TString(opt)=="TWIKI" || TString(opt)=="HTML"){
strTmp.ReplaceAll("AMPER","&");
}
const char * colstr = strTmp.Data();
char format [200];
if (TString(opt)!="CSV") {
snprintf(format, 200, "%%%ds", colWidths[icol] + 2);
} else {
snprintf(format, 200, "%%s");
}
printf(format, colstr);
if (TString(opt)=="CSV") printf(", ");
if (TString(opt)=="TWIKI") printf(" | ");
}
printf ("\n");
delete cols;
}
delete [] colWidths;
return;
}
cout << "\\begin{tabular}{"<<fFormat<<"}"<<endl;
Int_t nrow = fRows->GetEntriesFast();
for(Int_t irow = 0; irow < nrow; irow++){
cout << ((TObjString*) fRows->At(irow))->String() << endl;
}
cout << "\\end{tabular}" << endl;
}
void AliLatexTable::GetMantissaAndExpBase10(Double_t num, Double_t &man, Double_t &exp) {
exp = TMath::Floor(TMath::Log10(TMath::Abs(num)));
man = num / TMath::Power(10, exp);
}
void AliLatexTable::StripLatex(TString &text, TString format) {
text.ReplaceAll("\\cdot", "x");
text.ReplaceAll("$", "");
if (format == "ASCII") {
text.ReplaceAll("\\right>", ">");
text.ReplaceAll("\\left<", "<");
text.ReplaceAll("\\rangle", ">");
text.ReplaceAll("\\langle", "<");
text.ReplaceAll("\\pm", "+-");
} else if (format == "HTML" || format == "TWIKI") {
text.ReplaceAll("\\right>", "AMPERrang;");
text.ReplaceAll("\\left<", "AMPERlang;");
text.ReplaceAll("\\rangle", "AMPERrang;");
text.ReplaceAll("\\langle", "AMPERlang;");
text.ReplaceAll("\\pm", "AMPERplusmn;");
}
if(text.Contains("multicolumn")) {
TObjArray * array = TPRegexp("multicolumn\\{([^}]*)\\}\\{[^}]*\\}\\{([^]]*)\\}").MatchS(text);
const TString content = ((TObjString *)array->At(2))->GetString();
Int_t nspan = ((TObjString *)array->At(1))->GetString().Atoi();
text = content;
for(Int_t ispan = 1; ispan < nspan; ispan++){
text+=" & ";
}
}
text.ReplaceAll("\\mathrm", "");
text.ReplaceAll("\\", "");
text.Strip(TString::EStripType(1), ' ');
}
void AliLatexTable::LoadTeXFromFileAndPrintASCII(const char * filename) {
ifstream file (filename);
if (!file.is_open()) {
AliError(Form("Cannot open file %s", filename));
}
TString line;
while (line.ReadLine(file)) {
if (line.Contains("begin") && line.Contains("tabular")) {
TPRegexp re(".*begin{tabular}{(.*)}");
TObjArray * arr = re.MatchS(line);
if (arr->GetLast() > 0){
TString subStr = ((TObjString *)arr->At(1))->GetString();
subStr.ReplaceAll("|","");
subStr.ReplaceAll(" ","");
subStr.ReplaceAll("\t","");
fNcol = subStr.Length();
delete arr;
}
}
if (line.Contains("begin")) continue;
if (line.Contains("end")) continue;
if (line.Contains("tabular")) continue;
InsertCustomRow(line.Data());
}
PrintTable("ASCII");
}