# # function textable -- a Python script to make LaTeX tables # from ASCII files with columns # # Version 1.0 # # Usage: # # The call # # textable(filename) # # where filename is the name of an ASCII file with columns # # generates a new file 'filename'+'.tex' # with generic header and footer, alignment tabs, and # special LaTeX characters escaped. # If the number of lines is less than 40 all one table is generated; # otherwise the data is broken into two tables. # The fontsize is reduced progressively with the number of # lines but no more than two tables will be generated. # # # O. Nielsen, ANU, April 2000 """ This module contains two functions to generate LaTeX tables. ------------------- textool.maketable() ------------------- Declaration: maketable(array,title=None,rowlab=None,collab=None,maxcol=None, \ filename=None) Usage: Generates a new file 'filename'+'.tex' with a generic header and footer, alignment tabs, and special LaTeX characters escaped. If the number of lines is less than 40 all one table is generated; otherwise the data is broken into two tables. The fontsize is reduced progressively with the number of lines but no more than two tables will be generated. Input: array array is a list of lists containing entries for the table. Each list corresponds to one row, but they do not need to be the same length. title (optional) String to be used as title rowlab (optional) List of strings to used for row labels collab (optional) List of strings to used for column labels maxcol (optional) maximal number of columns (if known) filename (optional) filename for tex file (default='maketable') ------------------ textool.textable() ------------------ Declaration: textable(filename) Usage: Reads data from the ascii file filename and calls maketable to produce a LaTeX version. The file should contain rows of data elements but not necessarily having the same length. Running textable on arbitrary files is possible but meaningless. """ def textable(FN): from string import * input = open(FN,'r') # Open file with ASCII columns #output = open(FN+'.tex','w') # Open file with LateX table x = input.readlines() print 'Textable got ', len(x), 'records from ', FN maxcol = 0 array = [] for n in range(len(x)): record = split(rstrip(x[n])) array.append(record) col = len(record) # Number of columns in this record if col > maxcol: maxcol = col # Determine maximal number of columns maketable(array,rowlab=[],collab=[],title=FN,filename=FN+'.tex') return() # # Core routine for making and writing TeX table # # array is a list of lists (rows) # def maketable(array,title=None,rowlab=None,collab=None,maxcol=None,filename=None): splitthreshold = 40 # Maximal number of lines in one table # Tables with more lines are split into two import types # # Input checks #--------------- # # File name # if not filename: if title: filename = nospace(title) + '.tex' else: filename = 'maketable.tex' output = open(filename,'w') # Open file with LateX table # # array # if not type(array) in [types.ListType, types.TupleType]: array = [array] # # Maximal number of columns # if not maxcol: maxcol = 0 for n in range(len(array)): record = array[n] if not type(record) in [types.ListType, types.TupleType]: record = [record] col = len(record) # Number of columns in this record if col > maxcol: maxcol = col # Determine maximal number of columns # # Column labels # if not collab: collab = [] collab = list(collab) # Make copy to protect input list from being modified for j in range(maxcol): if j >= len(collab): collab.append('Col '+`j`) # Default column label collab[j] = '\\textbf{'+collab[j]+'}' # # Row labels # if not rowlab: rowlab = [] rowlab = list(rowlab) # Make copy to protect input list from being modified for j in range(len(array)): if j >= len(rowlab): rowlab.append('Row '+`j`) # Default row label rowlab[j] = '\\textbf{'+rowlab[j]+'}' # # Function body # y = [] for n in range(len(array)): record = array[n] if not type(record) in [types.ListType, types.TupleType]: record = [record] col = len(record) # Number of columns in this record if col > 0: # Aggregate Latex line texline = rowlab[n]+' & ' for j in range(maxcol): if j > 0: texline = texline+'\t& ' if j < col: texline = texline+texmap(str(record[j])) texline = texline + ' \\\\' y.append(texline) # # Make a qualified guess about splitting of table and fontsize # if len(y) <= splitthreshold: splittab = 0 tabstyle = 1 elif splitthreshold < len(y) <= 2*splitthreshold: splittab = 1 tabstyle = 2 else: splittab = 1 tabstyle = 3 if 5 < maxcol < 7: tabstyle = max(tabstyle,3) elif maxcol >= 7: tabstyle = max(tabstyle,4) # # Create generic table header # header = [] colform = '|l||' + 'c|'*maxcol if tabstyle == 1: header.append('{\\normalsize') elif tabstyle == 2: header.append('{\\small') elif tabstyle == 2: header.append('{\\scriptsize') else: header.append('{\\tiny') header.append('\\begin{tabular}{'+colform+'} \\hline') colnames = ' & ' for j in range(maxcol): if j > 0: colnames = colnames+'\t& ' # colnames = colnames+'\\textbf{Col '+`j`+'}' colnames = colnames+collab[j] header.append(colnames+'\\\\ \\hline\\hline') # # Create generic table footer # footer = [] footer.append('\\end{tabular}}') # # Generate file # output.write('\\begin{table}[hbt]\n') output.write('\\begin{center}\n') if title: output.write('\\textbf{'+texmap(str(title))+'}\\\\ \n') output.write('\n') # # One column table # if not splittab: # Header for n in range(len(header)): output.write(header[n]+'\n') # Contents for n in range(len(y)): output.write(y[n]) if n == len(y)-1: # Put a hline after last entry output.write(' \\hline \n') else: output.write('\n') # Footer for n in range(len(footer)): output.write(footer[n]+'\n') # # Two column table # else: tablen = int(round(len(y)/2.0)) for m in range(1): # Header output.write('\makebox[0.48\\textwidth]{\n') for n in range(len(header)): output.write(header[n]+'\n') # Contents k = 0 for n in range(len(y)): k = k+1 output.write(y[n]) if k == tablen: # Put a hline after last entry k = 0 output.write(' \\hline \n') # Footer for j in range(len(footer)): output.write(footer[j]+'\n') output.write('}\n') output.write('\hspace*{1mm}\n') output.write('\makebox[0.48\\textwidth]{\n') # Header for j in range(len(header)): output.write(header[j]+'\n') elif n == len(y)-1: # Put a hline after last entry output.write(' \\hline \n') if n == 2*tablen-2: # add an empty line for symmetry output.write('\\multicolumn{'+`maxcol`+'}{c}{} \\\\ \n') else: output.write('\n') # # Final footer # for n in range(len(footer)): output.write(footer[n]+'\n') output.write('}\n') output.write('\\end{center}\n') output.write('\\caption{ }\n') if title: output.write('\\label{tab:'+title+'}\n') else: output.write('\\label{tab: }\n') output.write('\\end{table}\n') output.close() print 'Textable wrote generic LaTeX table to', filename # texmap(s) # maps string s into Latex # def texmap(s): import types from string import * s = replace(s,'\\','\\backslash') s = replace(s,'#','\\#') s = replace(s,'$','\\$') s = replace(s,'%','\\%') s = replace(s,'&','\\&') s = replace(s,'~','\\~') s = replace(s,'_','\\_') s = replace(s,'^','\\^') s = replace(s,'{','\\{') s = replace(s,'}','\\}') return(s) def nospace(s): # # Replace spaces in s with underscores # import string newstr = '' for i in range(len(s)): if s[i] == ' ': newstr = newstr+'_' else: newstr = newstr+s[i] return(newstr) #======================= EXAMPLE ====================== def gen_latex_section(dataset,items,years,names='',filename=None): """gen_latex_section(dataset,items,years,names ='',filename=None) Generates a LaTeX document with basic statistics relating to the cohort defined by items, dataset, and years. The content of the generated report contains graphs with agergp, gender statistics and gender, RRMA statisitics. In addition there are tables with this information. The parameter names is used in the headlines. Example: from CRCdefs import MBSitems key = 'COLONOSCOPY' gen_latex_section('mbs',MBSitems[key],[1997,1998],key) """ import os, types from re import match # Regular Expressions from textool import * if not type(years) in [types.ListType, types.TupleType]: years = [years] if not type(items) in [types.ListType, types.TupleType]: items = [items] if not filename: if names == '': filename = 'Autoreport' else: filename = nospace(names) os.system('mkdir '+ filename) #os.system('cd '+ filename) curdir = os.getcwd() os.chdir(filename) output = open(filename+'.tex','w') output.write('\\documentclass{article}\n') output.write('\\usepackage{epsfig}\n') output.write('\\begin{document}\n') output.write('\\section{Findings}\n\n') for year in years: plot_age_gender(dataset,items,year,names,geneps=1) plot_rrma_gender(dataset,items,year,names,geneps=1) output.write('\\subsection{Basic statistics from ') output.write(texmap(dataset)+'}\n') #output.write(texmap(dataset)+' in '+str(year)+'}\n') texfiles = [] epsfiles = [] files = os.listdir('.') for fname in files: if match('.+eps',fname): epsfiles.append(fname) if match('.+tex',fname) and not match(filename+'.tex',fname): texfiles.append(fname) output.write('\\begin{center}\n') for file in epsfiles: output.write(' \\epsfxsize=0.47\\textwidth \\epsfbox{'+file+'}\n') output.write('\\end{center}\n\n') output.write('\\clearpage\n\n') for file in texfiles: output.write('\\input{'+file+'}\n') output.write('\\clearpage\n\n') output.write('\\end{document}\n') output.close() os.system('latex '+filename) os.system('dvips '+filename+' -o '+filename+'.ps') os.system('ghostview '+filename+'.ps &') print 'print the report using lpr ' + filename + '.ps' #print(' ***************************************************** # print the report using lpr ' + filename + '.ps # ********************************************************') os.chdir(curdir)