Created
October 19, 2008 22:07
-
-
Save certik/17957 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
#latex.py | |
""" | |
Convert GAsympy output to LaTeX format | |
""" | |
import re as regrep | |
import string,copy,sys,os,StringIO,subprocess,types | |
from pyparsing import nestedExpr | |
from sympy import * | |
class LaTeX: | |
stdout = sys.stdout | |
strfile = StringIO.StringIO() | |
mode = ('^','_') | |
div = regrep.compile(r'\)/\(|\)/@[0-9]+|@[0-9]+/\(|@[0-9]+/@[0-9]+') | |
allvars = regrep.compile(r'([A-Za-z]+[_0-9]+)') | |
vars = regrep.compile(r'([A-Za-z]+)([_0-9]+)') | |
subs = regrep.compile(r'[A-Za-z]+') | |
xpon = regrep.compile(r'(\*\*[0-9]+|\*\*@[0-9]+)') | |
times = regrep.compile(r'(\*{1,2})') | |
greek = regrep.compile('(alpha|beta|gamma|delta|varepsilon|epsilon|zeta|'+\ | |
'vartheta|theta|eta|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)') | |
fcts = regrep.compile('(sin|cos|tan|cot|'+\ | |
'asin|acos|atan|acot|'+\ | |
'sinh|cosh|tanh|coth|'+\ | |
'asinh|acosh|atanh|acoth|'+\ | |
'exp|log|sqrt|abs)') | |
accents = regrep.compile('([A-Za-z]+)(hat|check|dot|breve|acute|'+\ | |
'ddot|grave|tilde|mathring|bar|vec)') | |
fctdict = {'sin':'\\sin','cos':'\\cos','tan':'\\tan','cot':'\\cot',\ | |
'asin':'\\mathrm{Sin}^{-1}','acos':'\\mathrm{Cos}^{-1}',\ | |
'atan':'\\mathrm{Tan}^{-1}','acot':'\\mathrm{Cot}^{-1}',\ | |
'sinh':'\\sinh','cosh':'\\cosh','tanh':'\\tanh','coth':'\\coth',\ | |
'asinh':'\\mathrm{Sinh}^{-1}','acosh':'\\mathrm{Cosh}^{-1}', | |
'atanh':'\\mathrm{Tanh}^{-1}','acoth':'\\mathrm{Coth}^{-1}',\ | |
'sqrt':'\\sqrt','exp':'\\exp','log':'\\mathrm{ln}','abs':'\\abs'} | |
argfcts = ('sqrt','abs') | |
ops = ('+','-','*','/') | |
preamble = '\\documentclass[12pt,letterpaper]{article}\n'+\ | |
'\\pagestyle{empty}\n'+\ | |
'\\usepackage[latin1]{inputenc}\n'+\ | |
'\\usepackage{amsmath}\n'+\ | |
'\\usepackage{amsfonts}\n'+\ | |
'\\usepackage{amssymb}\n'+\ | |
'\\newcommand{\\lp}{\\left (}\n'+\ | |
'\\newcommand{\\rp}{\\right )}\n'+\ | |
'\\newcommand{\\half}{\\frac{1}{2}}\n'+\ | |
'\\newcommand{\\difftwo}[3]{\\frac{\\partial^{#1}{#3}}{#2}}'+\ | |
'\\newcommand{\\diffthree}[3]{\\frac{\\partial^{#1}}{#2}\\lp{#3}\\rp}'+\ | |
'\\begin{document}\n' | |
postscript = '\\end{document}\n' | |
body = '' | |
format = 0 | |
subdict = {} | |
subcnt = 0 | |
@staticmethod | |
def setaccent(x): | |
return('\\%s{%s}' % (x.group(2),x.group(1))) | |
@staticmethod | |
def setvars(x): | |
return('\\%s' % x.group(1)) | |
@staticmethod | |
def setsubsup(x): | |
xtupl = x.groups() | |
if len(xtupl) == 0: | |
return(x) | |
else: | |
subsup = xtupl[1].split('_') | |
nsubsup = len(subsup) | |
if nsubsup == 1: | |
return('%s^{%s}' % (xtupl[0],subsup[0])) | |
if nsubsup == 2: | |
if subsup[0] != '': | |
return('%s^{%s}_{%s}' % (xtupl[0],subsup[0],subsup[1])) | |
else: | |
return('%s_{%s}' % (xtupl[0],subsup[1])) | |
if nsubsup > 2: | |
outstr = xtupl[0] | |
if subsup[0] == '': | |
if subsup[1] == '': | |
for i in range(2,nsubsup): | |
outstr += LaTeX.mode[i%2]+'{'+subsup[i]+'}{}' | |
return(outstr) | |
for i in range(1,nsubsup): | |
outstr += LaTeX.mode[i%2]+'{'+subsup[i]+'}{}' | |
return(outstr) | |
for i in range(nsubsup): | |
outstr += LaTeX.mode[i%2]+'{'+subsup[i]+'}{}' | |
return(outstr) | |
return(' ') | |
@staticmethod | |
def var_str(namestr): | |
if LaTeX.format == 0: | |
return(namestr) | |
pstr = regrep.sub(LaTeX.vars,LaTeX.setsubsup,namestr) | |
pstr = regrep.sub(LaTeX.accents,LaTeX.setaccent,pstr) | |
pstr = regrep.sub(LaTeX.greek,LaTeX.setvars,pstr) | |
return(pstr) | |
@staticmethod | |
def replace_all_vars(line): | |
line = regrep.sub(LaTeX.allvars,LaTeX.replace_vars,line) | |
return(line) | |
@staticmethod | |
def replace_vars(x): | |
xstr = x.group(1) | |
keystr = '@'+str(LaTeX.subcnt) | |
LaTeX.subdict[keystr] = '{'+LaTeX.var_str(xstr)+'}' | |
LaTeX.subcnt += 1 | |
return(keystr) | |
@staticmethod | |
def setformat(format): | |
if format > 0: | |
LaTeX.format = format | |
LaTeX.body = '' | |
sys.stdout = LaTeX.strfile | |
return | |
@staticmethod | |
def derivative(line): | |
tmp = line | |
Dindx = 1 | |
while Dindx != -1: | |
Dindx = tmp.find('D(') | |
if Dindx == -1: | |
break | |
else: | |
tmp = tmp[Dindx:] | |
Pindx = tmp.find(')') | |
sub = tmp[0:Pindx+1] | |
tmp = tmp[Pindx+1:] | |
subkey = '@'+str(LaTeX.subcnt) | |
LaTeX.subdict[subkey] = LaTeX.format_derivative(sub[2:-1]) | |
line = line.replace(sub,subkey) | |
LaTeX.subcnt += 1 | |
return(line) | |
@staticmethod | |
def format_derivative(dstr): | |
dstr = dstr.replace(',','') | |
dlst = dstr.split() | |
fstr = LaTeX.var_str(dlst[0]) | |
dlst = dlst[1:] | |
vlst = LaTeX.nvar*[0] | |
for ivar in dlst: | |
indx = LaTeX.ivarlst.index(ivar) | |
vlst[indx] += 1 | |
dstr = '' | |
i = 0 | |
if LaTeX.format == 1: | |
for v in vlst: | |
if v == 1: | |
dstr += '\\partial_{'+str(i)+'}' | |
if v > 1: | |
dstr += '\\partial_{'+str(i)+'}^{'+str(v)+'}' | |
i += 1 | |
dstr += fstr | |
if LaTeX.format == 2: | |
for v in vlst: | |
if v == 1: | |
dstr += '\\partial_{'+LaTeX.var_str(LaTeX.ivarlst[i])+'}' | |
if v > 1: | |
dstr += '\\partial_{'+LaTeX.var_str(LaTeX.ivarlst[i])+'}^{'+str(v)+'}' | |
i += 1 | |
dstr += fstr | |
if LaTeX.format == 3 or LaTeX.format == 4: | |
sum = 0 | |
for v in vlst: | |
sum += v | |
if v == 1: | |
dstr += '\\partial '+LaTeX.var_str(LaTeX.ivarlst[i]) | |
if v > 1: | |
dstr += '\\partial^{'+str(v)+'}'+LaTeX.var_str(LaTeX.ivarlst[i]) | |
i += 1 | |
if sum == 1: | |
strsum = '' | |
else: | |
strsum = str(sum) | |
if LaTeX.format == 3: | |
dstr = '\\frac{\\partial^{'+strsum+'}'+fstr+'}{'+dstr+'}' | |
if LaTeX.format == 4: | |
dstr = '\\frac{\\partial^{'+strsum+'}}{'+dstr+'}\\lp '+fstr+'\\rp' | |
return(dstr) | |
@staticmethod | |
def replace_all_functions(line): | |
return(line) | |
@staticmethod | |
def replace_all_times(line): | |
line = line.replace('*','') | |
return(line) | |
@staticmethod | |
def replace_all_pow(line): | |
return(line) | |
@staticmethod | |
def replace_paren(line): | |
line = line.replace('(','\\lp ') | |
line = line.replace(')','\\rp ') | |
return(line) | |
@staticmethod | |
def nested_lst_to_str(lst): | |
global lstr | |
lstr = '' | |
def sub_lst(lst): | |
global lstr | |
for x in lst: | |
if isinstance(x,types.StringType): | |
lstr += x | |
else: | |
bflg = False | |
if lstr[-1] != '{': | |
lstr += '(' | |
else: | |
bflg = True | |
sub_lst(x) | |
if bflg: | |
lstr += '}' | |
else: | |
lstr += ')' | |
sub_lst(lst) | |
return(lstr) | |
@staticmethod | |
def parse_nested_lst(lst): | |
def sub_lst(lst): | |
i = 0 | |
for x in lst: | |
if isinstance(x,types.StringType): | |
lst[i] = LaTeX.parse_str(x) | |
else: | |
lst[i] = sub_lst(x) | |
i += 1 | |
return(lst) | |
sub_lst(lst) | |
return | |
@staticmethod | |
def replace_fct(x): | |
xstr = x.group(1) | |
keystr = '@'+str(LaTeX.subcnt) | |
LaTeX.subcnt += 1 | |
LaTeX.subdict[keystr] = LaTeX.fctdict[xstr] | |
if xstr in LaTeX.argfcts: | |
keystr += '{' | |
return(keystr) | |
@staticmethod | |
def replace_xpon(x): | |
xstr = x.group(1) | |
xstr = '^{'+xstr[2:]+'}' | |
return(xstr) | |
@staticmethod | |
def parse_str(x): | |
x = regrep.sub(LaTeX.fcts,LaTeX.replace_fct,x) | |
x = regrep.sub(LaTeX.allvars,LaTeX.replace_vars,x) | |
x = LaTeX.parse_xpon(x) | |
return(x) | |
@staticmethod | |
def parse_xpon(x): | |
xpon = x.rfind('**') | |
if xpon >= 0: | |
if xpon == len(x)-2: | |
x = x[:-2]+'^{' | |
x = regrep.sub(LaTeX.xpon,LaTeX.replace_xpon,x) | |
return(x) | |
@staticmethod | |
def parseline(line): | |
line = line.replace(LaTeX.ivarstr,'') | |
line = LaTeX.derivative(line) | |
line = string.join(line.split(),"") | |
tmp = '('+line+')' | |
nestlst = nestedExpr().searchString(tmp)[0][0] | |
LaTeX.parse_nested_lst(nestlst) | |
line = LaTeX.nested_lst_to_str(nestlst) | |
line = line.replace('*','') | |
return(line) | |
@staticmethod | |
def xdvi(ivars): | |
sys.stdout = LaTeX.stdout | |
LaTeX.body = LaTeX.strfile.getvalue() | |
tmp = LaTeX.body.strip() | |
LaTeX.nvar = len(ivars) | |
LaTeX.ivarlst = [] | |
LaTeX.ivarstr = '(' | |
for ivar in ivars: | |
strvar = str(ivar) | |
LaTeX.ivarlst.append(strvar) | |
LaTeX.ivarstr += strvar+', ' | |
LaTeX.ivarstr = LaTeX.ivarstr[:-2]+')' | |
lines = tmp.split('\n') | |
indx = range(len(lines)) | |
body = '' | |
LaTeX.subcnt = 0 | |
LaTeX.subdict = {} | |
for line in lines: | |
if line.find('=') >= 0: | |
line = LaTeX.parseline(line) | |
body += '$$'+line+'$$\n' | |
else: | |
body += line+'\\newline\n' | |
for key in LaTeX.subdict.keys(): | |
body = body.replace(key,LaTeX.subdict[key]) | |
body = LaTeX.replace_paren(body) | |
LaTeX.body = LaTeX.preamble+body+LaTeX.postscript | |
if os.path.exists('textput.*'): | |
os.system('rm texput.*') | |
PIPE = subprocess.PIPE | |
p = subprocess.Popen("latex",stdin=PIPE) | |
p.stdin.write(LaTeX.body) | |
os.system('xdvi -geometry 900x400 texput &') | |
#os.wait() | |
return | |
if __name__ == '__main__': | |
""" | |
A set format argument of 1, 2, 3, or 4 will produce different | |
LaTeX formatting for partial derivatives. A set format of 0 | |
produces standard (not pretty print) sympy printed output. Try | |
it and see the differences. Note that in xdiv(x) x is the tuple | |
of independent variables that one might have to differentiate with | |
respect to. | |
""" | |
LaTeX.setformat(3) | |
x = tuple(symbols('x1','x2')) | |
f = Function('f_12')(*x) | |
g = Function('g_34')(*x) | |
x1 = x[0] | |
x2 = x[1] | |
half = Rational(1,2) | |
dfx1 = diff(f,x1) | |
dgx2 = diff(g,x2) | |
h = x1*f-half*asin(x2)*g | |
dhx1 = diff(h,x1) | |
F = h+dhx1*dgx2 | |
print 'F =',F/f | |
dF = diff(F,x2) | |
print 'dF =',dF | |
print 'Note that $x^{2}$ is not $xx$, but one of the independent variables $x^{1}$ and $x^{2}$.' | |
LaTeX.xdvi(x) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment