#latex_ex.py
from __future__ import with_statement
import sys
#if sys.version.find('Stackless') >= 0:
# sys.path.append('/usr/lib/python2.5/site-packages')
import types
import StringIO
from sympy.core import S, C, Basic, Symbol
from sympy.core.function import _coeff_isneg
from sympy.printing.printer import Printer
from sympy.simplify import fraction
import re as regrep
import sympy.galgebra.GA
#import sympy.galgebra.OGA
import numpy
from sympy.core.compatibility import cmp_to_key
from sympy.utilities import default_sort_key
from sympy.printing.latex import accepted_latex_functions
from sympy.printing.preview import preview
def debug(txt):
sys.stderr.write(txt + '\n')
return
def len_cmp(str1, str2):
return(len(str2) - len(str1))
def process_equals(xstr):
eq1 = xstr.find('=')
eq2 = xstr.rfind('=')
if eq1 == eq2:
return(xstr)
xstr = xstr[:eq1] + xstr[eq2:]
return(xstr)
[docs]class LatexPrinter(Printer):
r"""
A printer class which converts an expression into its LaTeX equivalent.
This class extends the LatexPrinter class currently in sympy in the
following ways:
1. Variable and function names can now encode multiple Greek symbols,
number, Greek, and roman super and subscripts and accents plus bold
math in an alphanumeric ASCII string consisting of ``[A-Za-z0-9_]``
symbols
a) Accents and bold math are implemented in reverse notation. For
example if you wished the LaTeX output to be ``\bm{\hat{\sigma}}``
you would give the variable the name sigmahatbm.
b) Subscripts are denoted by a single underscore and superscripts
by a double underscore so that ``A_{\rho\beta}^{25}`` would be
input as A_rhobeta__25.
2. Some standard function names have been improved such as asin is now
denoted by sin^{-1} and log by ln.
3. Several LaTeX formats for multivectors are available:
a) Print multivector on one line
b) Print each grade of multivector on one line
c) Print each base of multivector on one line
4. A LaTeX output for numpy arrays containing sympy expressions is
implemented for up to a three dimensional array.
5. LaTeX formatting for raw LaTeX, eqnarray, and array is available
in simple output strings.
a) The delimiter for raw LaTeX input is '%'. The raw input starts
on the line where '%' is first encountered and continues until
the next line where '%' is encountered. It does not matter where
'%' is in the line.
b) The delimiter for eqnarray input is '@'. The rules are the same
as for raw input except that '=' in the first line is replaced
be '&=&' and '\begin{eqnarray*}' is added before the first line
and '\end{eqnarray*}' to after the last line in the group of
lines.
c) The delimiter for array input is '#'. The rules are the same
as for raw input except that '\begin{equation*}' is added before
the first line and '\end{equation*}' to after the last line in
the group of lines.
6. Additional formats for partial derivatives:
a) Same as sympy latex module
b) Use subscript notation with partial symbol to indicate which
variable the differentiation is with respect to. Symbol is of
form \partial_{differentiation variable}
"""
#printmethod ='_latex_ex'
sym_fmt = 0
fct_fmt = 0
pdiff_fmt = 0
mv_fmt = 0
str_fmt = 1
LaTeX_flg = False
mode = ('_', '^')
fmt_dict = {'sym': 0, 'fct': 0, 'pdiff': 0, 'mv': 0, 'str': 1}
fct_dict = {'sin': 'sin', 'cos': 'cos', 'tan': 'tan', 'cot': 'cot',
'asin': 'Sin^{-1}', 'acos': 'Cos^{-1}',
'atan': 'Tan^{-1}', 'acot': 'Cot^{-1}',
'sinh': 'sinh', 'cosh': 'cosh', 'tanh': 'tanh', 'coth': 'coth',
'asinh': 'Sinh^{-1}', 'acosh': 'Cosh^{-1}',
'atanh': 'Tanh^{-1}', 'acoth': 'Coth^{-1}',
'sqrt': 'sqrt', 'exp': 'exp', 'log': 'ln'}
fct_dict_keys = fct_dict.keys()
greek_keys = sorted(
('alpha', 'beta', 'gamma', 'delta', 'varepsilon', 'epsilon', 'zeta',
'vartheta', 'theta', 'iota', 'kappa', 'lambda', 'mu', 'nu', 'xi',
'varpi', 'pi', 'rho', 'varrho', 'varsigma', 'sigma', 'tau', 'upsilon',
'varphi', 'phi', 'chi', 'psi', 'omega', 'Gamma', 'Delta', 'Theta',
'Lambda', 'Xi', 'Pi', 'Sigma', 'Upsilon', 'Phi', 'Psi', 'Omega', 'partial',
'nabla', 'eta'), key=cmp_to_key(len_cmp))
accent_keys = sorted(
('hat', 'check', 'dot', 'breve', 'acute', 'ddot', 'grave', 'tilde',
'mathring', 'bar', 'vec', 'bm', 'prm', 'abs'), key=cmp_to_key(len_cmp))
greek_cnt = 0
greek_dict = {}
accent_cnt = 0
accent_dict = {}
preamble = '\\documentclass[10pt,letter,fleqn]{report}\n' \
'\\pagestyle{empty}\n' \
'\\usepackage[latin1]{inputenc}\n' \
'\\usepackage[dvips,landscape,top=1cm,nohead,nofoot]{geometry}\n' \
'\\usepackage{amsmath}\n' \
'\\usepackage{bm}\n' \
'\\usepackage{amsfonts}\n' \
'\\usepackage{amssymb}\n' \
'\\setlength{\\parindent}{0pt}\n' \
'\\newcommand{\\bfrac}[2]{\\displaystyle\\frac{#1}{#2}}\n' \
'\\newcommand{\\lp}{\\left (}\n' \
'\\newcommand{\\rp}{\\right )}\n' \
'\\newcommand{\\half}{\\frac{1}{2}}\n' \
'\\newcommand{\\llt}{\\left <}\n' \
'\\newcommand{\\rgt}{\\right >}\n' \
'\\newcommand{\\abs}[1]{\\left |{#1}\\right | }\n' \
'\\newcommand{\\pdiff}[2]{\\bfrac{\\partial {#1}}{\\partial {#2}}}\n' \
'\\newcommand{\\lbrc}{\\left \\{}\n' \
'\\newcommand{\\rbrc}{\\right \\}}\n' \
'\\newcommand{\\W}{\\wedge}\n' \
"\\newcommand{\\prm}[1]{{#1}'}\n" \
'\\newcommand{\\ddt}[1]{\\bfrac{d{#1}}{dt}}\n' \
'\\newcommand{\\R}{\\dagger}\n' \
'\\begin{document}\n'
@staticmethod
[docs] def latex_bases():
"""
Generate LaTeX strings for multivector bases
"""
if isinstance(sympy.galgebra.GA.MV.basislabel_lst, types.IntType):
sys.stderr.write(
'MV.setup() must be executed before LatexPrinter.format()!\n')
sys.exit(1)
LatexPrinter.latexbasis_lst = [['']]
for grades in sympy.galgebra.GA.MV.basislabel_lst[1:]:
grades_lst = []
for grade in grades:
grade_lst = []
for base in grade:
latex_base = LatexPrinter.extended_symbol(base)
grade_lst.append(latex_base)
grades_lst.append(grade_lst)
LatexPrinter.latexbasis_lst.append(grades_lst)
return
@staticmethod
def build_base(igrade, iblade, bld_flg):
if igrade == 0:
return('')
base_lst = LatexPrinter.latexbasis_lst[igrade][iblade]
if len(base_lst) == 1:
return(base_lst[0])
base_str = ''
for base in base_lst[:-1]:
if bld_flg:
base_str += base + '\\W '
else:
base_str += base
base_str += base_lst[-1]
return(base_str)
@staticmethod
def format(sym=0, fct=0, pdiff=0, mv=0):
LatexPrinter.LaTeX_flg = True
LatexPrinter.fmt_dict['sym'] = sym
LatexPrinter.fmt_dict['fct'] = fct
LatexPrinter.fmt_dict['pdiff'] = pdiff
LatexPrinter.fmt_dict['mv'] = mv
LatexPrinter.fmt_dict['str'] = 1
if sympy.galgebra.GA.MV.is_setup:
LatexPrinter.latex_bases()
LatexPrinter.redirect()
return
@staticmethod
def str_basic(in_str):
if not LatexPrinter.LaTeX_flg:
return(str(in_str))
Basic.__str__ = LatexPrinter.Basic__str__
out_str = str(in_str)
Basic.__str__ = LaTeX
return(out_str)
@staticmethod
def redirect():
LatexPrinter.Basic__str__ = Basic.__str__
LatexPrinter.MV__str__ = sympy.galgebra.GA.MV.__str__
LatexPrinter.stdout = sys.stdout
sys.stdout = StringIO.StringIO()
Basic.__str__ = LaTeX
sympy.galgebra.GA.MV.__str__ = LaTeX
return
@staticmethod
def restore():
LatexPrinter_stdout = sys.stdout
LatexPrinter_Basic__str__ = Basic.__str__
LatexPrinter_MV__str__ = sympy.galgebra.GA.MV.__str__
sys.stdout = LatexPrinter.stdout
Basic.__str__ = LatexPrinter.Basic__str__
sympy.galgebra.GA.MV.__str__ = LatexPrinter.MV__str__
LatexPrinter.stdout = LatexPrinter_stdout
LatexPrinter.Basic__str__ = LatexPrinter_Basic__str__
LatexPrinter.MV__str__ = LatexPrinter_MV__str__
return
@staticmethod
def format_str(fmt='0 0 0 0'):
fmt_lst = fmt.split()
if '=' not in fmt:
LatexPrinter.fmt_dict['sym'] = int(fmt_lst[0])
LatexPrinter.fmt_dict['fct'] = int(fmt_lst[1])
LatexPrinter.fmt_dict['pdiff'] = int(fmt_lst[2])
LatexPrinter.fmt_dict['mv'] = int(fmt_lst[3])
else:
for fmt in fmt_lst:
x = fmt.split('=')
LatexPrinter.fmt_dict[x[0]] = int(x[1])
if LatexPrinter.LaTeX_flg is False:
if sympy.galgebra.GA.MV.is_setup:
LatexPrinter.latex_bases()
LatexPrinter.redirect()
LatexPrinter.LaTeX_flg = True
return
@staticmethod
def append_body(xstr):
if LatexPrinter.body_flg:
LatexPrinter.body += xstr
return('')
else:
return(xstr[:-1])
@staticmethod
def tokenize_greek(name_str):
for sym in LatexPrinter.greek_keys:
isym = name_str.find(sym)
if isym > -1:
keystr = '@' + str(LatexPrinter.greek_cnt)
LatexPrinter.greek_cnt += 1
LatexPrinter.greek_dict[keystr] = sym
name_str = name_str.replace(sym, keystr)
return(name_str)
@staticmethod
def tokenize_accents(name_str):
for sym in LatexPrinter.accent_keys:
if name_str.find(sym) > -1:
keystr = '#' + str(LatexPrinter.accent_cnt) + '#'
LatexPrinter.accent_cnt += 1
LatexPrinter.accent_dict[keystr] = '\\' + sym
name_str = name_str.replace(sym, keystr)
return(name_str)
@staticmethod
def replace_greek_tokens(name_str):
if name_str.find('@') == -1:
return(name_str)
for token in LatexPrinter.greek_dict.keys():
name_str = name_str.replace(
token, '{\\' + LatexPrinter.greek_dict[token] + '}')
LatexPrinter.greek_cnt = 0
LatexPrinter.greek_dict = {}
return(name_str)
@staticmethod
def replace_accent_tokens(name_str):
tmp_lst = name_str.split('#')
name_str = tmp_lst[0]
if len(tmp_lst) == 1:
return(name_str)
for x in tmp_lst[1:]:
if x != '':
name_str = '{}' + LatexPrinter.accent_dict[
'#' + x + '#'] + '{' + name_str + '}'
LatexPrinter.accent_cnt = 0
LatexPrinter.accent_dict = {}
return(name_str)
@staticmethod
def extended_symbol(name_str):
name_str = LatexPrinter.tokenize_greek(name_str)
tmp_lst = name_str.split('_')
subsup_str = ''
sym_str = tmp_lst[0]
sym_str = LatexPrinter.tokenize_accents(sym_str)
sym_str = LatexPrinter.replace_accent_tokens(sym_str)
if len(tmp_lst) > 1:
imode = 0
for x in tmp_lst[1:]:
if x == '':
imode = (imode + 1) % 2
else:
subsup_str += LatexPrinter.mode[imode] + '{' + x + '}'
#subsup_str += LatexPrinter.mode[imode]+x+' '
imode = (imode + 1) % 2
name_str = sym_str + subsup_str
name_str = LatexPrinter.replace_greek_tokens(name_str)
return(name_str)
def coefficient(self, coef, first_flg):
if isinstance(coef, C.AssocOp) and isinstance(-coef, C.AssocOp):
coef_str = r"\lp %s\rp " % self._print(coef)
else:
coef_str = self._print(coef)
if first_flg:
first_flg = False
if coef_str[0] == '+':
coef_str = coef_str[1:]
else:
if coef_str[0] != '-':
if coef_str[0] != '+':
coef_str = '+' + coef_str
if coef_str in ('1', '+1', '-1'):
if coef_str == '1':
coef_str = ''
else:
coef_str = coef_str[0]
return(coef_str, first_flg)
def __init__(self, inline=True):
Printer.__init__(self)
self._inline = inline
def doprint(self, expr):
tex = Printer.doprint(self, expr)
xstr = ''
if self._inline:
if LatexPrinter.fmt_dict['fct'] == 1:
xstr = r"%s" % tex
else:
xstr = r"$%s$" % tex
else:
xstr = r"\begin{equation*}%s\end{equation*}" % tex
return(xstr)
def _needs_brackets(self, expr):
return not ((expr.is_Integer and expr.is_nonnegative) or expr.is_Atom)
def _do_exponent(self, expr, exp):
if exp is not None:
return r"\left(%s\right)^{%s}" % (expr, exp)
else:
return expr
def _print_Add(self, expr):
tex = str(self._print(expr.args[0]))
for term in expr.args[1:]:
if _coeff_isneg(term):
tex += r" %s" % self._print(term)
else:
tex += r" + %s" % self._print(term)
return tex
def _print_Mul(self, expr):
coeff, tail = expr.as_coeff_Mul()
if coeff.is_negative:
coeff = -coeff
tex = "- "
else:
tex = ""
numer, denom = fraction(tail)
def convert(terms):
product = []
if not terms.is_Mul:
return str(self._print(terms))
else:
for term in terms.args:
pretty = self._print(term)
if term.is_Add:
product.append(r"\left(%s\right)" % pretty)
else:
product.append(str(pretty))
return r" ".join(product)
if denom is S.One:
if coeff is not S.One:
tex += str(self._print(coeff)) + " "
if numer.is_Add:
tex += r"\left(%s\right)" % convert(numer)
else:
tex += r"%s" % convert(numer)
else:
if numer is S.One:
if coeff.is_Integer:
numer *= coeff.p
elif coeff.is_Rational:
if coeff.p != 1:
numer *= coeff.p
denom *= coeff.q
elif coeff is not S.One:
tex += str(self._print(coeff)) + " "
else:
if coeff.is_Rational and coeff.p == 1:
denom *= coeff.q
elif coeff is not S.One:
tex += str(self._print(coeff)) + " "
tex += r"\frac{%s}{%s}" % \
(convert(numer), convert(denom))
return tex
def _print_Pow(self, expr):
if expr.exp.is_Rational and expr.exp.q == 2:
base, exp = self._print(expr.base), abs(expr.exp.p)
if exp == 1:
tex = r"\sqrt{%s}" % base
else:
tex = r"\sqrt[%s]{%s}" % (exp, base)
if expr.exp.is_negative:
return r"\frac{1}{%s}" % tex
else:
return tex
else:
if expr.base.is_Function:
return self._print(expr.base, self._print(expr.exp))
else:
if expr.exp == S.NegativeOne:
#solves issue 1030
#As Mul always simplify 1/x to x**-1
#The objective is achieved with this hack
#first we get the latex for -1 * expr,
#which is a Mul expression
tex = self._print(S.NegativeOne * expr).strip()
#the result comes with a minus and a space, so we remove
if tex[:1] == "-":
return tex[1:].strip()
if self._needs_brackets(expr.base):
tex = r"\left(%s\right)^{%s}"
else:
tex = r"{%s}^{%s}"
return tex % (self._print(expr.base),
self._print(expr.exp))
def _print_Derivative(self, expr):
dim = len(expr.variables)
if dim == 1:
if LatexPrinter.fmt_dict['pdiff'] == 1:
tex = r'\partial_{%s}' % self._print(expr.variables[0])
else:
tex = r"\frac{\partial}{\partial %s}" % self._print(
expr.variables[0])
else:
multiplicity, i, tex = [], 1, ""
current = expr.variables[0]
for symbol in expr.variables[1:]:
if symbol == current:
i = i + 1
else:
multiplicity.append((current, i))
current, i = symbol, 1
else:
multiplicity.append((current, i))
if LatexPrinter.fmt_dict['pdiff'] == 1:
for x, i in multiplicity:
if i == 1:
tex += r"\partial_{%s}" % self._print(x)
else:
tex += r"\partial^{%s}_{%s}" % (i, self._print(x))
else:
for x, i in multiplicity:
if i == 1:
tex += r"\partial %s" % self._print(x)
else:
tex += r"\partial^{%s} %s" % (i, self._print(x))
tex = r"\frac{\partial^{%s}}{%s} " % (dim, tex)
if isinstance(expr.expr, C.AssocOp):
return r"%s\left(%s\right)" % (tex, self._print(expr.expr))
else:
return r"%s %s" % (tex, self._print(expr.expr))
def _print_Integral(self, expr):
tex, symbols = "", []
for symbol, limits in reversed(expr.limits):
tex += r"\int"
if limits is not None:
if not self._inline:
tex += r"\limits"
tex += "_{%s}^{%s}" % (self._print(limits[0]),
self._print(limits[1]))
symbols.insert(0, "d%s" % self._print(symbol))
return r"%s %s\,%s" % (tex,
str(self._print(expr.function)), " ".join(symbols))
def _print_Limit(self, expr):
tex = r"\lim_{%s \to %s}" % (self._print(expr.var),
self._print(expr.varlim))
if isinstance(expr.expr, C.AssocOp):
return r"%s\left(%s\right)" % (tex, self._print(expr.expr))
else:
return r"%s %s" % (tex, self._print(expr.expr))
def _print_Function(self, expr, exp=None):
func = expr.func.__name__
if hasattr(self, '_print_' + func):
return getattr(self, '_print_' + func)(expr, exp)
else:
args = [ str(self._print(arg)) for arg in expr.args ]
if LatexPrinter.fmt_dict['fct'] == 1:
if func in LatexPrinter.fct_dict_keys:
if exp is not None:
if func in accepted_latex_functions:
name = r"\%s^{%s}" % (
LatexPrinter.fct_dict[func], exp)
else:
name = r"\operatorname{%s}^{%s}" % (
LatexPrinter.fct_dict[func], exp)
else:
if LatexPrinter.fct_dict[func] in accepted_latex_functions:
name = r"\%s" % LatexPrinter.fct_dict[func]
else:
name = r"\operatorname{%s}" % LatexPrinter.fct_dict[func]
name += r"\left(%s\right)" % ",".join(args)
return name
else:
func = self.print_Symbol_name(func)
if exp is not None:
name = r"{%s}^{%s}" % (func, exp)
else:
name = r"{%s}" % func
return name
else:
if exp is not None:
if func in accepted_latex_functions:
name = r"\%s^{%s}" % (func, exp)
else:
name = r"\operatorname{%s}^{%s}" % (func, exp)
else:
if func in accepted_latex_functions:
name = r"\%s" % func
else:
name = r"\operatorname{%s}" % func
return name + r"\left(%s\right)" % ",".join(args)
def _print_floor(self, expr, exp=None):
tex = r"\lfloor{%s}\rfloor" % self._print(expr.args[0])
if exp is not None:
return r"%s^{%s}" % (tex, exp)
else:
return tex
def _print_ceiling(self, expr, exp=None):
tex = r"\lceil{%s}\rceil" % self._print(expr.args[0])
if exp is not None:
return r"%s^{%s}" % (tex, exp)
else:
return tex
def _print_abs(self, expr, exp=None):
tex = r"\lvert{%s}\rvert" % self._print(expr.args[0])
if exp is not None:
return r"%s^{%s}" % (tex, exp)
else:
return tex
def _print_re(self, expr, exp=None):
if self._needs_brackets(expr.args[0]):
tex = r"\Re\left(%s\right)" % self._print(expr.args[0])
else:
tex = r"\Re{%s}" % self._print(expr.args[0])
return self._do_exponent(tex, exp)
def _print_im(self, expr, exp=None):
if self._needs_brackets(expr.args[0]):
tex = r"\Im\left(%s\right)" % self._print(expr.args[0])
else:
tex = r"\Im{%s}" % self._print(expr.args[0])
return self._do_exponent(tex, exp)
def _print_conjugate(self, expr, exp=None):
tex = r"\overline{%s}" % self._print(expr.args[0])
if exp is not None:
return r"%s^{%s}" % (tex, exp)
else:
return tex
def _print_exp(self, expr, exp=None):
tex = r"{e}^{%s}" % self._print(expr.args[0])
return self._do_exponent(tex, exp)
def _print_gamma(self, expr, exp=None):
tex = r"\left(%s\right)" % self._print(expr.args[0])
if exp is not None:
return r"\Gamma^{%s}%s" % (exp, tex)
else:
return r"\Gamma%s" % tex
def _print_factorial(self, expr, exp=None):
x = expr.args[0]
if self._needs_brackets(x):
tex = r"\left(%s\right)!" % self._print(x)
else:
tex = self._print(x) + "!"
if exp is not None:
return r"%s^{%s}" % (tex, exp)
else:
return tex
def _print_factorial(self, expr, exp=None):
x = expr.args[0]
if self._needs_brackets(x):
tex = r"!\left(%s\right)" % self._print(x)
else:
tex = "!" + self._print(x)
if exp is not None:
return r"%s^{%s}" % (tex, exp)
else:
return tex
def _print_binomial(self, expr, exp=None):
tex = r"{{%s}\choose{%s}}" % (self._print(expr[0]),
self._print(expr[1]))
if exp is not None:
return r"%s^{%s}" % (tex, exp)
else:
return tex
def _print_RisingFactorial(self, expr, exp=None):
tex = r"{\left(%s\right)}^{\left(%s\right)}" % \
(self._print(expr[0]), self._print(expr[1]))
return self._do_exponent(tex, exp)
def _print_FallingFactorial(self, expr, exp=None):
tex = r"{\left(%s\right)}_{\left(%s\right)}" % \
(self._print(expr[0]), self._print(expr[1]))
return self._do_exponent(tex, exp)
def _print_Rational(self, expr):
if expr.q != 1:
sign = ""
p = expr.p
if expr.p < 0:
sign = "- "
p = -p
return r"%s\frac{%d}{%d}" % (sign, p, expr.q)
else:
return self._print(expr.p)
def _print_Infinity(self, expr):
return r"\infty"
def _print_NegativeInfinity(self, expr):
return r"-\infty"
def _print_ComplexInfinity(self, expr):
return r"\tilde{\infty}"
def _print_ImaginaryUnit(self, expr):
return r"\mathbf{\imath}"
def _print_NaN(self, expr):
return r"\bot"
def _print_Pi(self, expr):
return r"\pi"
def _print_Exp1(self, expr):
return r"e"
def _print_EulerGamma(self, expr):
return r"\gamma"
def _print_Order(self, expr):
return r"\\mathcal{O}\left(%s\right)" % \
self._print(expr.args[0])
@staticmethod
def print_Symbol_name(name_str):
if len(name_str) == 1:
return (name_str)
if LatexPrinter.fmt_dict['sym'] == 1:
return LatexPrinter.extended_symbol(name_str)
else:
return(name_str)
#convert trailing digits to subscript
m = regrep.match('(^[a-zA-Z]+)([0-9]+)$', name_str)
if m is not None:
name, sub = m.groups()
tex = self._print_Symbol(Symbol(name))
tex = "%s_{%s}" % (tex, sub)
return tex
# insert braces to expresions containing '_' or '^'
m = regrep.match(
'(^[a-zA-Z0-9]+)([_\^]{1})([a-zA-Z0-9]+)$', name_str)
if m is not None:
name, sep, rest = m.groups()
tex = self._print_Symbol(Symbol(name))
tex = "%s%s{%s}" % (tex, sep, rest)
return tex
greek = set([ 'alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta',
'eta', 'theta', 'iota', 'kappa', 'lambda', 'mu', 'nu',
'xi', 'omicron', 'pi', 'rho', 'sigma', 'tau', 'upsilon',
'phi', 'chi', 'psi', 'omega' ])
other = set( ['aleph', 'beth', 'daleth', 'gimel', 'ell', 'eth',
'hbar', 'hslash', 'mho' ])
if name_str.lower() in greek:
return "\\" + name_str
elif name_str in other:
return "\\" + name_str
else:
return name_str
def _print_Symbol(self, expr):
return LatexPrinter.print_Symbol_name(expr.name)
def _print_str(self, expr):
if LatexPrinter.fmt_dict['str'] > 0:
expr = expr.replace('^', '{\\wedge}')
expr = expr.replace('|', '{\\cdot}')
expr = expr.replace('__', '^')
return(expr)
def _print_ndarray(self, expr):
shape = numpy.shape(expr)
ndim = len(shape)
expr_str = ''
if ndim == 1:
expr_str += '#\\left [ \\begin{array}{' + shape[0]*'c' + '} \n'
for col in expr:
expr_str += self._print(col) + ' & '
expr_str = expr_str[:-2] + '\n\\end{array}\\right ]#\n'
return(expr_str)
if ndim == 2:
expr_str += '#\\left [ \\begin{array}{' + shape[1]*'c' + '} \n'
for row in expr[:-1]:
for xij in row[:-1]:
expr_str += self._print(xij) + ' & '
expr_str += self._print(row[-1]) + ' \\\\ \n'
for xij in expr[-1][:-1]:
expr_str += self._print(xij) + ' & '
expr_str += self._print(
expr[-1][-1]) + '\n \\end{array} \\right ] #\n'
return(expr_str)
if ndim == 3:
expr_str = '#\\left \\{ \\begin{array}{' + shape[0]*'c' + '} \n'
for x in expr[:-1]:
xstr = self._print(x).replace('#', '')
expr_str += xstr + ' , & '
xstr = self._print(expr[-1]).replace('#', '')
expr_str += xstr + '\n\\end{array} \\right \\}#\n'
return(expr_str)
def _print_MV(self, expr):
igrade = 0
MV_str = ''
line_lst = []
for grade in expr.mv:
if not isinstance(grade, types.IntType):
ibase = 0
for base in grade:
if base != 0:
tmp = Symbol('XYZW')
base_str = str(base*tmp)
if base_str[0] != '-':
base_str = '+' + base_str
base_str = base_str.replace('- ', '-')
if base_str[1:5] == 'XYZW':
base_str = base_str.replace('XYZW', '')
else:
base_str = base_str.replace('XYZW', '1')
MV_str += base_str + LatexPrinter.build_base(
igrade, ibase, expr.bladeflg)
if LatexPrinter.fmt_dict['mv'] == 3:
line_lst.append(MV_str)
MV_str = ''
ibase += 1
if LatexPrinter.fmt_dict['mv'] == 2:
if MV_str != '':
line_lst.append(MV_str)
MV_str = ''
igrade += 1
n_lines = len(line_lst)
if MV_str == '':
if n_lines > 0 and line_lst[0][0] == '+':
line_lst[0] = line_lst[0][1:]
else:
if MV_str[0] == '+':
MV_str = MV_str[1:]
if n_lines == 1:
MV_str = line_lst[0]
n_lines = 0
if LatexPrinter.fmt_dict['mv'] >= 2:
MV_str = '@' + line_lst[0] + ' \\\\ \n'
for line in line_lst[1:-1]:
MV_str += '& ' + line + ' \\\\ \n'
MV_str += '& ' + line_lst[-1] + '@\n'
if MV_str == '':
MV_str = '0'
if expr.name != '':
MV_str = LatexPrinter.extended_symbol(expr.name) + ' = ' + MV_str
return(MV_str)
def _print_OMV(self, expr):
igrade = 0
MV_str = ''
line_lst = []
for grade in expr.mv:
if not isinstance(grade, None):
ibase = 0
for base in grade:
if base != 0:
tmp = Symbol('XYZW')
base_str = str(base*tmp)
if base_str[0] != '-':
base_str = '+' + base_str
base_str = base_str.replace('- ', '-')
if base_str[1:5] == 'XYZW':
base_str = base_str.replace('XYZW', '')
else:
base_str = base_str.replace('XYZW', '1')
MV_str += base_str + LatexPrinter.build_base(
igrade, ibase, expr.bladeflg)
if LatexPrinter.fmt_dict['mv'] == 3:
line_lst.append(MV_str)
MV_str = ''
ibase += 1
if LatexPrinter.fmt_dict['mv'] == 2:
if MV_str != '':
line_lst.append(MV_str)
MV_str = ''
igrade += 1
n_lines = len(line_lst)
if MV_str == '':
if n_lines > 0 and line_lst[0][0] == '+':
line_lst[0] = line_lst[0][1:]
else:
if MV_str[0] == '+':
MV_str = MV_str[1:]
if n_lines == 1:
MV_str = line_lst[0]
n_lines = 0
if LatexPrinter.fmt_dict['mv'] >= 2:
MV_str = '@' + line_lst[0] + ' \\\\ \n'
for line in line_lst[1:-1]:
MV_str += '& ' + line + ' \\\\ \n'
MV_str += '& ' + line_lst[-1] + '@\n'
if MV_str == '':
MV_str = '0'
if expr.name != '':
MV_str = LatexPrinter.extended_symbol(expr.name) + ' = ' + MV_str
return(MV_str)
def _print_Relational(self, expr):
charmap = {
"==": "=",
"<": "<",
"<=": r"\leq",
"!=": r"\neq",
}
return "%s %s %s" % (self._print(expr.lhs),
charmap[expr.rel_op], self._print(expr.rhs))
def _print_Matrix(self, expr):
lines = []
for line in range(expr.lines): # horrible, should be 'rows'
lines.append(" & ".join([ self._print(i) for i in expr[line, :] ]))
if self._inline:
tex = r"\left(\begin{smallmatrix}%s\end{smallmatrix}\right)"
else:
tex = r"\begin{pmatrix}%s\end{pmatrix}"
return tex % r"\\".join(lines)
def _print_tuple(self, expr):
return r"\begin{pmatrix}%s\end{pmatrix}" % \
r", & ".join([ self._print(i) for i in expr ])
def _print_list(self, expr):
return r"\begin{bmatrix}%s\end{bmatrix}" % \
r", & ".join([ self._print(i) for i in expr ])
def _print_dict(self, expr):
items = []
keys = expr.keys()
keys.sort(key=default_sort_key)
for key in keys:
val = expr[key]
items.append("%s : %s" % (self._print(key), self._print(val)))
return r"\begin{Bmatrix}%s\end{Bmatrix}" % r", & ".join(items)
def _print_DiracDelta(self, expr):
if len(expr.args) == 1 or expr.args[1] == 0:
tex = r"\delta\left(%s\right)" % self._print(expr.args[0])
else:
tex = r"\delta^{\left( %s \right)}\left( %s \right)" % (
self._print(expr.args[1]), self._print(expr.args[0]))
return tex
[docs]def LaTeX(expr, inline=True):
"""
Convert the given expression to LaTeX representation.
You can specify how the generated code will be delimited.
If the 'inline' keyword is set then inline LaTeX $ $ will
be used. Otherwise the resulting code will be enclosed in
'equation*' environment (remember to import 'amsmath').
>>> from sympy import Rational
>>> from sympy.abc import tau, mu, x, y
>>> from sympy.galgebra.latex_ex import LaTeX
>>> LaTeX((2*tau)**Rational(7,2))
'$8 \\\\sqrt{2} \\\\sqrt[7]{\\\\tau}$'
>>> LaTeX((2*mu)**Rational(7,2), inline=False)
'\\\\begin{equation*}8 \\\\sqrt{2} \\\\sqrt[7]{\\\\mu}\\\\end{equation*}'
Besides all Basic based expressions, you can recursively
convert Python containers (lists, tuples and dicts) and
also SymPy matrices:
>>> LaTeX([2/x, y])
'$\\\\begin{bmatrix}\\\\frac{2}{x}, & y\\\\end{bmatrix}$'
The extended latex printer will also append the output to a
string (LatexPrinter.body) that will be processed by xdvi()
for immediate display one xdvi() is called.
"""
xstr = LatexPrinter(inline).doprint(expr)
return (xstr)
[docs]def print_LaTeX(expr):
"""Prints LaTeX representation of the given expression."""
print LaTeX(expr)
def Format(fmt='1 1 1 1'):
LatexPrinter.format_str(fmt)
return
[docs]def xdvi(filename='tmplatex.tex', debug=False):
"""
Post processes LaTeX output (see comments below), adds preamble and
postscript, generates tex file, inputs file to latex, displays resulting
dvi file with xdvi or yap.
"""
if not LatexPrinter.LaTeX_flg:
return
body = sys.stdout.getvalue()
LatexPrinter.restore()
body_lst = body.split('\n')
body = ''
array_flg = False
eqnarray_flg = False
raw_flg = False
i = iter(body_lst)
line = i.next()
while True:
if '$' in line: # Inline math expression(s)
if len(line) > 0:
line += '\\newline \n'
body += line
try:
line = i.next()
except StopIteration:
break
elif '%' in line: # Raw LaTeX input
"""
If % in line assume line is beginning of raw LaTeX input and stop
post processing
"""
line = line.replace('%', '')
raw_flg = True
while raw_flg:
if '%' in line:
"""
If % in line assume line is end of LaTeX input and begin
post processing
"""
raw_flg = False
line = line.replace('%', '') + '\n'
else:
line += '\n'
line = process_equals(line)
body += line
try:
line = i.next()
except StopIteration:
break
elif '#' in line: # Array input
"""
If # in line assume line is beginning of array input and contains
\begin{array} statement
"""
line = line.replace('#', '')
array_flg = True
line = '\\begin{equation*}\n' + line
while array_flg:
if '#' in line:
"""
If # in line assume line is end of array input and contains
\end{array} statement
"""
array_flg = False
line = line.replace('#', '')
line += '\\end{equation*}\n'
else:
line += '\n'
line = process_equals(line)
body += line
try:
line = i.next()
except StopIteration:
break
elif '@' in line: # Align input
"""
If @ in line assume line is beginning of align input
"""
line = line.replace('@', '')
line = line.replace('=', '& = ')
eqnarray_flg = True
line = '\\begin{align*}\n' + line
line = process_equals(line)
body += line
try:
line = i.next()
except StopIteration:
break
while eqnarray_flg:
if '@' in line:
"""
If @ in line assume line is end of align input
"""
eqnarray_flg = False
line = line.replace('@', '')
line += '\\end{align*}\n'
else:
line + '\n'
line = process_equals(line)
body += line
try:
line = i.next()
except StopIteration:
break
else:
if '=' in line: # Single line equation
line = '\\begin{equation*}\n' + line + '\n\\end{equation*}'
else: # Text with no math expression(s)unless \ or _ in line
if '\\' in line or '_' in line or '^' in line:
line = '\\begin{equation*}\n' + line + '\n\\end{equation*}'
else:
if len(line) > 0:
line += '\\newline \n'
line = process_equals(line)
body += line
try:
line = i.next()
except StopIteration:
break
preview(body, output='dvi', outputTexFile=filename,
preamble=LatexPrinter.preamble)
LatexPrinter.LaTeX_flg = False
return
def ext_str(xstr):
return(LatexPrinter.extended_symbol(xstr))