Package SloppyCell :: Package ExprManip :: Module Py2TeX
[hide private]

Source Code for Module SloppyCell.ExprManip.Py2TeX

  1  from compiler.ast import * 
  2  import os 
  3   
  4  import AST 
  5   
  6  # This is just and istance of Mul to use when we group numerators and  
  7  #  denominators 
  8  _EMPTY_MUL = Mul((None, None)) 
  9   
10 -def dict2TeX(d, name_dict, lhs_form='%s', split_terms=False, simpleTeX=False):
11 lines = [] 12 for lhs, rhs in d.items(): 13 if split_terms: 14 ast = AST.strip_parse(rhs) 15 pos, neg = [], [] 16 AST._collect_pos_neg(ast, pos, neg) 17 try: 18 lhsTeX = lhs_form % expr2TeX(lhs, name_dict=name_dict) 19 except TypeError: 20 lhsTeX = lhs_form 21 rhsTeX = _ast2TeX(pos[0], name_dict=name_dict) 22 lines.append(r'$ %s $ &=& $ %s $\\' % (lhsTeX, rhsTeX)) 23 24 for term in pos[1:]: 25 TeXed = _ast2TeX(term, name_dict=name_dict) 26 lines.append(r' & & $ + \, %s $\\' % TeXed) 27 for term in neg: 28 TeXed = _ast2TeX(term, name_dict=name_dict) 29 lines.append(r' & & $ - \, %s $\\' % TeXed) 30 else: 31 lhsTeX = lhs_form % expr2TeX(lhs, name_dict=name_dict) 32 rhsTeX = expr2TeX(rhs, name_dict=name_dict) 33 lines.append(r'$ %s $ & = & $ %s $\\' % (lhsTeX, rhsTeX)) 34 35 if not simpleTeX: 36 # Force a space between TeX'd entries 37 lines[-1] = '%s[5mm]' % lines[-1] 38 39 all = os.linesep.join(lines) 40 41 if not simpleTeX: 42 all = all.replace(r'\frac{', r'\tabfrac{') 43 # This makes the fractions look much nicer in the tabular output. See 44 # http://www.texnik.de/table/table.phtml#fractions 45 lines = [r'\providecommand{\tabfrac}[2]{%', 46 r' \setlength{\fboxrule}{0pt}%', 47 r' \fbox{$\frac{#1}{#2}$}}', 48 r'\begin{longtable}{lll}'] + [all] + [r'\end{longtable}'] 49 all = os.linesep.join(lines) 50 51 return all
52
53 -def expr2TeX(expr, name_dict={}):
54 """ 55 Return a TeX version of a python math expression. 56 57 name_dict: A dictionary mapping variable names used in the expression to 58 preferred TeX expressions. 59 """ 60 ast = AST.strip_parse(expr) 61 return _ast2TeX(ast, name_dict=name_dict)
62
63 -def _ast2TeX(ast, outer=AST._FARTHEST_OUT, name_dict={}, 64 adjust=0):
65 """ 66 Return a TeX version of an AST. 67 68 outer: The AST's 'parent' node, used to determine whether or not to 69 enclose the result in parentheses. The default of _FARTHEST_OUT will 70 never enclose the result in parentheses. 71 72 name_dict: A dictionary mapping variable names used in the expression to 73 preferred TeX expressions. 74 75 adjust: A numerical value to adjust the priority of this ast for 76 particular cases. For example, the denominator of a '/' needs 77 parentheses in more cases than does the numerator. 78 """ 79 if isinstance(ast, Name): 80 # Try to get a value from the name_dict, defaulting to ast.name if 81 # ast.name isn't in name_dict 82 out = name_dict.get(ast.name, ast.name) 83 elif isinstance(ast, Const): 84 out = str(ast.value) 85 elif isinstance(ast, Add): 86 out = '%s + %s' % (_ast2TeX(ast.left, ast, name_dict), 87 _ast2TeX(ast.right, ast, name_dict)) 88 elif isinstance(ast, Sub): 89 out = '%s - %s' % (_ast2TeX(ast.left, ast, name_dict), 90 _ast2TeX(ast.right, ast, name_dict, adjust = 1)) 91 elif isinstance(ast, Mul) or isinstance(ast, Div): 92 # We collect all terms numerator and denominator 93 nums, denoms = [], [] 94 AST._collect_num_denom(ast, nums, denoms) 95 # _EMPTY_MUL ensures that parentheses are done properly, since every 96 # element is now the child of a Mul 97 lam_func = lambda arg: _ast2TeX(arg, _EMPTY_MUL, name_dict) 98 nums = [lam_func(term) for term in nums] 99 if denoms: 100 denoms = [lam_func(term) for term in denoms] 101 out = r'\frac{%s}{%s}' % (r' \cdot '.join(nums), 102 r' \cdot '.join(denoms)) 103 else: 104 out = r' \cdot '.join(nums) 105 elif isinstance(ast, Power): 106 out = '{%s}^{%s}' % (_ast2TeX(ast.left, ast, name_dict, adjust = 1), 107 _ast2TeX(ast.right, ast, name_dict)) 108 elif isinstance(ast, UnarySub): 109 out = '-%s' % _ast2TeX(ast.expr, ast, name_dict) 110 elif isinstance(ast, UnaryAdd): 111 out = '+%s' % _ast2TeX(ast.expr, ast, name_dict) 112 elif isinstance(ast, CallFunc): 113 lam_func = lambda arg: _ast2TeX(arg, name_dict=name_dict) 114 name = lam_func(ast.node) 115 args = [lam_func(arg) for arg in ast.args] 116 if name == 'sqrt' and len(args) == 1: 117 # Special case 118 out = r'\sqrt{%s}' % args[0] 119 else: 120 out = r'\operatorname{%s}\left(%s\right)' % (name, r',\,'.join(args)) 121 elif isinstance(ast, Or) or isinstance(ast, And): 122 out = r'\operatorname{%s}' % (str(ast)) 123 124 if AST._need_parens(outer, ast, adjust): 125 return out 126 else: 127 return r'\left(%s\right)' % out
128