Source code for delphin.extra.latex

"""
Generate LaTeX snippets for rendering DELPH-IN data.
"""

from collections import defaultdict

from delphin.mrs.components import nodes, links
from delphin.mrs.config import (
    RSTR_ROLE, EQ_POST, H_POST
)

from delphin.mrs.xmrs import Xmrs

# latex character escaping code copied from Xigt:
#   (https://github.com/xigt/xigt)

# order matters here
_LATEX_CHARMAP = [
    ('\\', '\\textbackslash'),
    ('&', '\\&'),
    ('%', '\\%'),
    ('$', '\\$'),
    ('#', '\\#'),
    ('_', '\\_'),
    ('{', '\\{'),
    ('}', '\\}'),
    ('~', '\\textasciitilde'),
    ('^', '\\textasciicircum'),
 ]

def _latex_escape(s):
    # consider a re sub with a function. e.g.
    # _character_unescapes = {'\\s': _field_delimiter, '\\n': '\n', '\\\\':     '\\'}
    # _unescape_func = lambda m: _character_unescapes[m.group(0)]
    # _unescape_re = re.compile(r'(\\s|\\n|\\\\)')
    # _unescape_re.sub(_unescape_func, string, flags=re.UNICODE)
    for c, r in _LATEX_CHARMAP:
        s = s.replace(c, r)
    return s

[docs]def dmrs_tikz_dependency(xs, **kwargs): """ Return a LaTeX document with each Xmrs in *xs* rendered as DMRSs. DMRSs use the `tikz-dependency` package for visualization. """ def link_label(link): return '{}/{}'.format(link.rargname or '', link.post) def label_edge(link): if link.post == H_POST and link.rargname == RSTR_ROLE: return 'rstr' elif link.post == EQ_POST: return 'eq' else: return 'arg' if isinstance(xs, Xmrs): xs = [xs] lines = """\\documentclass{standalone} \\usepackage{tikz-dependency} \\usepackage{relsize} %%% %%% style for dmrs graph %%% \\depstyle{dmrs}{edge unit distance=1.5ex, label style={above, scale=.9, opacity=0, text opacity=1}, baseline={([yshift=-0.7\\baselineskip]current bounding box.north)}} %%% set text opacity=0 to hide text, opacity = 0 to hide box \\depstyle{root}{edge unit distance=3ex, label style={opacity=1}} \\depstyle{arg}{edge above} \\depstyle{rstr}{edge below, dotted, label style={text opacity=1}} \\depstyle{eq}{edge below, label style={text opacity=1}} \\depstyle{icons}{edge below, dashed} \\providecommand{\\named}{} \\renewcommand{\\named}{named} %%% styles for predicates and roles (from mrs.sty) \\providecommand{\\spred}{} \\renewcommand{\\spred}[1]{\\mbox{\\textsf{#1}}} \\providecommand{\\srl}{} \\renewcommand{\\srl}[1]{\\mbox{\\textsf{\\smaller #1}}} %%% \\begin{document}""".split("\n") for ix, x in enumerate(xs): lines.append("%%%\n%%% {}\n%%%".format(ix+1)) lines.append("\\begin{dependency}[dmrs]") ns = nodes(x) ### predicates lines.append(" \\begin{deptext}[column sep=10pt]") for i, n in enumerate(ns): sep = "\\&" if (i < len(ns) - 1) else "\\\\" pred = _latex_escape(n.pred.short_form()) pred = "\\named{}" if pred == 'named' else pred if n.carg is not None: print(n.carg.strip('"')) pred += "\\smaller ({})".format(n.carg.strip('"')) lines.append(" \\spred{{{}}} {} % node {}".format( pred, sep, i+1)) lines.append(" \\end{deptext}") nodeidx = {n.nodeid: i+1 for i, n in enumerate(ns)} ### links for link in links(x): if link.start == 0: lines.append( ' \\deproot[root]{{{}}}{{{}}}'.format( nodeidx[link.end], '\\srl{TOP}' # _latex_escape('/' + link.post) ) ) else: lines.append(' \\depedge[{}]{{{}}}{{{}}}{{\\srl{{{}}}}}'.format( label_edge(link), nodeidx[link.start], nodeidx[link.end], _latex_escape(link_label(link)) )) ### placeholder for icons lines.append('% \\depedge[icons]{f}{t}{FOCUS}') lines.append('\\end{dependency}\n') lines.append('\\end{document}') return '\n'.join(lines)