# Licensed under a 3-clause BSD style license - see LICENSE.rst """An extensible ASCII table reader and writer. latex.py: Classes to read and write LaTeX tables :Copyright: Smithsonian Astrophysical Observatory (2011) :Author: Tom Aldcroft (aldcroft@head.cfa.harvard.edu) """ import re from . import core latexdicts = {'AA': {'tabletype': 'table', 'header_start': r'\hline \hline', 'header_end': r'\hline', 'data_end': r'\hline'}, 'doublelines': {'tabletype': 'table', 'header_start': r'\hline \hline', 'header_end': r'\hline\hline', 'data_end': r'\hline\hline'}, 'template': {'tabletype': 'tabletype', 'caption': 'caption', 'tablealign': 'tablealign', 'col_align': 'col_align', 'preamble': 'preamble', 'header_start': 'header_start', 'header_end': 'header_end', 'data_start': 'data_start', 'data_end': 'data_end', 'tablefoot': 'tablefoot', 'units': {'col1': 'unit of col1', 'col2': 'unit of col2'}} } RE_COMMENT = re.compile(r'(?`_ some header keywords differ from standard LaTeX. This header is modified to take that into account. ''' header_start = r'\tablehead' splitter_class = AASTexHeaderSplitter def start_line(self, lines): return find_latex_line(lines, r'\tablehead') def write(self, lines): if 'col_align' not in self.latex: self.latex['col_align'] = len(self.cols) * 'c' if 'tablealign' in self.latex: align = '[' + self.latex['tablealign'] + ']' else: align = '' lines.append(r'\begin{' + self.latex['tabletype'] + r'}{' + self.latex['col_align'] + r'}' + align) add_dictval_to_list(self.latex, 'preamble', lines) if 'caption' in self.latex: lines.append(r'\tablecaption{' + self.latex['caption'] + '}') tablehead = ' & '.join([r'\colhead{' + name + '}' for name in self.colnames]) units = self._get_units() if 'units' in self.latex: units.update(self.latex['units']) if units: tablehead += r'\\ ' + self.splitter.join([units.get(name, ' ') for name in self.colnames]) lines.append(r'\tablehead{' + tablehead + '}') class AASTexData(LatexData): r'''In a `deluxetable`_ the data is enclosed in `\startdata` and `\enddata` ''' data_start = r'\startdata' data_end = r'\enddata' def start_line(self, lines): return find_latex_line(lines, self.data_start) + 1 def write(self, lines): lines.append(self.data_start) lines_length_initial = len(lines) core.BaseData.write(self, lines) # To remove extra space(s) and // appended which creates an extra new line # in the end. if len(lines) > lines_length_initial: # we compile separately because py2.6 doesn't have a flags keyword in re.sub re_final_line = re.compile(r'\s* \\ \\ \s* $', flags=re.VERBOSE) lines[-1] = re.sub(re_final_line, '', lines[-1]) lines.append(self.data_end) add_dictval_to_list(self.latex, 'tablefoot', lines) lines.append(r'\end{' + self.latex['tabletype'] + r'}') class AASTex(Latex): '''AASTeX format table. This class implements some AASTeX specific commands. AASTeX is used for the AAS (American Astronomical Society) publications like ApJ, ApJL and AJ. It derives from the ``Latex`` reader and accepts the same keywords. However, the keywords ``header_start``, ``header_end``, ``data_start`` and ``data_end`` in ``latexdict`` have no effect. ''' _format_name = 'aastex' _io_registry_format_aliases = ['aastex'] _io_registry_suffix = '' # AASTex inherits from Latex, so override this class attr _description = 'AASTeX deluxetable used for AAS journals' header_class = AASTexHeader data_class = AASTexData def __init__(self, **kwargs): super().__init__(**kwargs) # check if tabletype was explicitly set by the user if not (('latexdict' in kwargs) and ('tabletype' in kwargs['latexdict'])): self.latex['tabletype'] = 'deluxetable'