source: tools/demos/textool.py @ 3217

Last change on this file since 3217 was 2712, checked in by ole, 19 years ago

Added old example of automatically generated LaTeX files

File size: 11.5 KB
RevLine 
[2712]1#
2# function textable -- a Python script to make LaTeX tables
3# from ASCII files with columns
4#
5# Version 1.0
6#
7# Usage:
8#
9# The call
10#
11#       textable(filename)
12#
13#   where filename is the name of an ASCII file with columns
14#
15#   generates a new file 'filename'+'.tex'
16#   with generic header and footer, alignment tabs, and
17#   special LaTeX characters escaped.
18#   If the number of lines is less than 40 all one table is generated;
19#   otherwise the data is broken into two tables.
20#   The fontsize is reduced progressively with the number of
21#   lines but no more than two tables will be generated.
22#
23#
24# O. Nielsen, ANU, April 2000
25
26
27"""
28This module contains two functions to generate LaTeX tables.
29
30-------------------
31textool.maketable()
32-------------------
33
34Declaration:
35  maketable(array,title=None,rowlab=None,collab=None,maxcol=None, \
36            filename=None)
37
38Usage:
39  Generates a new file 'filename'+'.tex'
40  with a generic header and footer, alignment tabs, and
41  special LaTeX characters escaped.
42  If the number of lines is less than 40 all one table is generated;
43  otherwise the data is broken into two tables.
44  The fontsize is reduced progressively with the number of
45  lines but no more than two tables will be generated.
46
47  Input: array     array is a list of lists containing entries for the
48                   table. Each list corresponds to one row, but they do
49                   not need to be the same length.
50         title     (optional) String to be used as title
51         rowlab    (optional) List of strings to used for row labels
52         collab    (optional) List of strings to used for column labels
53         maxcol    (optional) maximal number of columns (if known)
54         filename  (optional) filename for tex file (default='maketable')
55
56
57
58
59------------------
60textool.textable()
61------------------
62
63Declaration:
64  textable(filename)
65
66Usage:
67  Reads data from the ascii file filename and calls maketable to produce
68  a LaTeX version. The file should contain rows of data elements but not
69  necessarily having the same length.
70  Running textable on arbitrary files is possible but meaningless.
71
72
73         
74"""
75
76
77
78def textable(FN):       
79  from string import *
80 
81  input = open(FN,'r')         # Open file with ASCII columns
82  #output = open(FN+'.tex','w') # Open file with LateX table
83
84  x = input.readlines()
85  print 'Textable got ', len(x), 'records from ', FN
86
87 
88  maxcol = 0
89  array = []
90  for n in range(len(x)):   
91    record = split(rstrip(x[n]))
92    array.append(record)
93    col = len(record)   # Number of columns in this record 
94    if col > maxcol:
95      maxcol = col      # Determine maximal number of columns     
96
97  maketable(array,rowlab=[],collab=[],title=FN,filename=FN+'.tex')     
98
99  return()
100
101#
102# Core routine for making and writing TeX table
103#
104# array is a list of lists (rows)
105
106def maketable(array,title=None,rowlab=None,collab=None,maxcol=None,filename=None):       
107
108  splitthreshold = 40 # Maximal number of lines in one table
109                      # Tables with more lines are split into two
110
111  import types
112                     
113  #
114  # Input checks
115  #---------------
116 
117  #
118  # File name
119  #
120  if not filename:
121    if title:
122      filename = nospace(title) + '.tex'
123    else: 
124      filename = 'maketable.tex'
125   
126  output = open(filename,'w') # Open file with LateX table
127
128  #
129  # array
130  #
131 
132  if not type(array) in [types.ListType, types.TupleType]:
133    array = [array]
134 
135  #
136  # Maximal number of columns
137  #
138  if not maxcol:
139    maxcol = 0 
140    for n in range(len(array)):   
141      record = array[n]
142      if not type(record) in [types.ListType, types.TupleType]:     
143        record = [record]
144      col = len(record)   # Number of columns in this record 
145      if col > maxcol:
146        maxcol = col      # Determine maximal number of columns     
147
148  #
149  # Column labels
150  #     
151  if not collab:
152    collab = []
153   
154  collab = list(collab) # Make copy to protect input list from being modified
155     
156
157  for j in range(maxcol):
158    if j >= len(collab): 
159      collab.append('Col '+`j`)    # Default column label
160    collab[j] = '\\textbf{'+collab[j]+'}'
161
162  #
163  # Row labels
164  #     
165  if not rowlab:
166    rowlab = [] 
167   
168  rowlab = list(rowlab) # Make copy to protect input list from being modified 
169   
170  for j in range(len(array)):
171    if j >= len(rowlab): 
172      rowlab.append('Row '+`j`)    # Default row label
173    rowlab[j] = '\\textbf{'+rowlab[j]+'}'
174
175  #
176  # Function body
177  #     
178  y = []
179  for n in range(len(array)):   
180    record = array[n]
181    if not type(record) in [types.ListType, types.TupleType]:     
182      record = [record]
183   
184    col = len(record)   # Number of columns in this record 
185   
186    if col > 0:
187      # Aggregate Latex line 
188      texline = rowlab[n]+' & '
189      for j in range(maxcol):
190        if j > 0: 
191          texline = texline+'\t& '
192       
193        if j < col:
194          texline = texline+texmap(str(record[j])) 
195 
196      texline = texline + ' \\\\'
197      y.append(texline)
198 
199 
200  #
201  # Make a qualified guess about splitting of table and fontsize
202  #   
203  if len(y) <= splitthreshold:
204    splittab = 0
205    tabstyle = 1
206  elif splitthreshold < len(y) <= 2*splitthreshold:
207    splittab = 1
208    tabstyle = 2
209  else:
210    splittab = 1 
211    tabstyle = 3 
212
213  if 5 < maxcol < 7:
214    tabstyle = max(tabstyle,3)
215  elif maxcol >= 7:     
216    tabstyle = max(tabstyle,4)
217           
218 
219  #
220  # Create generic table header
221  #
222  header = []
223  colform = '|l||' + 'c|'*maxcol
224  if tabstyle == 1:
225    header.append('{\\normalsize') 
226  elif tabstyle == 2:
227    header.append('{\\small')
228  elif tabstyle == 2:
229    header.append('{\\scriptsize')
230  else:         
231    header.append('{\\tiny')
232     
233  header.append('\\begin{tabular}{'+colform+'} \\hline')
234
235 
236  colnames = ' & '
237  for j in range(maxcol):
238    if j > 0: 
239      colnames = colnames+'\t& '
240   
241  #  colnames = colnames+'\\textbf{Col '+`j`+'}'
242    colnames = colnames+collab[j]
243
244  header.append(colnames+'\\\\ \\hline\\hline')
245
246  #
247  # Create generic table footer
248  #
249  footer = []
250  footer.append('\\end{tabular}}')
251
252
253  #
254  # Generate file
255  #
256 
257  output.write('\\begin{table}[hbt]\n')
258  output.write('\\begin{center}\n') 
259  if title:
260    output.write('\\textbf{'+texmap(str(title))+'}\\\\ \n')   
261  output.write('\n') 
262
263  #
264  # One column table
265 
266  if not splittab:
267    # Header
268    for n in range(len(header)): 
269      output.write(header[n]+'\n')         
270   
271    # Contents   
272    for n in range(len(y)): 
273      output.write(y[n])         
274      if n == len(y)-1:            # Put a hline after last entry
275        output.write(' \\hline \n') 
276      else:
277        output.write('\n')     
278    # Footer           
279    for n in range(len(footer)): 
280      output.write(footer[n]+'\n')
281
282  #
283  # Two column table
284 
285  else:
286    tablen = int(round(len(y)/2.0))
287    for m in range(1):
288      # Header
289      output.write('\makebox[0.48\\textwidth]{\n')               
290      for n in range(len(header)): 
291        output.write(header[n]+'\n')         
292     
293      # Contents   
294      k = 0
295      for n in range(len(y)): 
296        k = k+1
297        output.write(y[n])         
298        if k == tablen:            # Put a hline after last entry
299          k = 0
300          output.write(' \\hline \n') 
301          # Footer     
302          for j in range(len(footer)): 
303            output.write(footer[j]+'\n')
304          output.write('}\n') 
305          output.write('\hspace*{1mm}\n')                         
306          output.write('\makebox[0.48\\textwidth]{\n')                   
307          # Header
308          for j in range(len(header)): 
309            output.write(header[j]+'\n')         
310        elif n == len(y)-1:        # Put a hline after last entry           
311          output.write(' \\hline \n')   
312          if n == 2*tablen-2:      # add an empty line for symmetry
313            output.write('\\multicolumn{'+`maxcol`+'}{c}{} \\\\ \n') 
314        else:
315          output.write('\n')     
316         
317      #   
318      # Final footer           
319      #
320      for n in range(len(footer)): 
321        output.write(footer[n]+'\n')
322      output.write('}\n')       
323           
324  output.write('\\end{center}\n') 
325  output.write('\\caption{ }\n') 
326  if title: 
327    output.write('\\label{tab:'+title+'}\n') 
328  else:
329    output.write('\\label{tab: }\n') 
330   
331  output.write('\\end{table}\n')
332             
333  output.close()   
334  print 'Textable wrote generic LaTeX table to', filename
335
336 
337# texmap(s)
338#  maps string s into Latex
339#
340def texmap(s):
341  import types
342  from string import *
343
344  s = replace(s,'\\','\\backslash') 
345  s = replace(s,'#','\\#') 
346  s = replace(s,'$','\\$')
347  s = replace(s,'%','\\%') 
348  s = replace(s,'&','\\&')
349  s = replace(s,'~','\\~')
350  s = replace(s,'_','\\_')
351  s = replace(s,'^','\\^')
352  s = replace(s,'{','\\{')
353  s = replace(s,'}','\\}') 
354     
355  return(s)
356
357def nospace(s):
358  #
359  # Replace spaces in s with underscores
360 
361
362  import string
363 
364  newstr = ''
365  for i in range(len(s)):
366    if s[i] == ' ':
367      newstr = newstr+'_'
368    else:
369      newstr = newstr+s[i] 
370     
371  return(newstr)   
372
373
374#======================= EXAMPLE ======================
375
376def gen_latex_section(dataset,items,years,names='',filename=None):
377
378  """gen_latex_section(dataset,items,years,names ='',filename=None)
379     Generates a LaTeX document with basic statistics relating
380     to the cohort defined by items, dataset, and years.
381     The content of the generated report contains graphs with agergp,
382     gender statistics and gender, RRMA statisitics.
383     In addition there are tables with this information.
384     The parameter names is used in the headlines.
385
386     Example:
387     from CRCdefs import MBSitems
388
389     key = 'COLONOSCOPY'
390     gen_latex_section('mbs',MBSitems[key],[1997,1998],key)
391  """
392
393  import os, types
394  from re import match                           # Regular Expressions
395  from textool import *
396
397  if not type(years) in [types.ListType, types.TupleType]:
398    years = [years]
399  if not type(items) in [types.ListType, types.TupleType]:
400    items = [items]
401   
402  if not filename:
403    if names == '': 
404      filename = 'Autoreport'
405    else:
406      filename = nospace(names)
407   
408  os.system('mkdir '+ filename)
409  #os.system('cd '+ filename) 
410  curdir = os.getcwd()
411  os.chdir(filename) 
412 
413  output = open(filename+'.tex','w') 
414 
415  output.write('\\documentclass{article}\n') 
416  output.write('\\usepackage{epsfig}\n') 
417  output.write('\\begin{document}\n')   
418 
419  output.write('\\section{Findings}\n\n')
420  for year in years:
421    plot_age_gender(dataset,items,year,names,geneps=1) 
422    plot_rrma_gender(dataset,items,year,names,geneps=1)     
423 
424  output.write('\\subsection{Basic statistics from ')
425  output.write(texmap(dataset)+'}\n')   
426  #output.write(texmap(dataset)+' in '+str(year)+'}\n')
427 
428  texfiles = []
429  epsfiles = []   
430  files = os.listdir('.')
431   
432  for fname in files:
433    if match('.+eps',fname):
434      epsfiles.append(fname)
435
436    if match('.+tex',fname) and not match(filename+'.tex',fname):
437      texfiles.append(fname)
438
439  output.write('\\begin{center}\n')       
440  for file in epsfiles:
441    output.write(\\epsfxsize=0.47\\textwidth \\epsfbox{'+file+'}\n')
442  output.write('\\end{center}\n\n')
443  output.write('\\clearpage\n\n') 
444 
445  for file in texfiles: 
446    output.write('\\input{'+file+'}\n')
447     
448  output.write('\\clearpage\n\n')
449   
450  output.write('\\end{document}\n')       
451  output.close()     
452             
453  os.system('latex '+filename)
454  os.system('dvips '+filename+' -o '+filename+'.ps')
455  os.system('ghostview '+filename+'.ps &') 
456  print 'print the report using lpr ' + filename + '.ps' 
457  #print(' *****************************************************
458  #          print the report using lpr ' + filename + '.ps
459  #        ********************************************************')
460 
461  os.chdir(curdir) 
462 
Note: See TracBrowser for help on using the repository browser.