"""
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)