Ticket #5711: enhanced-typesetting-of-symbolic-functions.patch

File enhanced-typesetting-of-symbolic-functions.patch, 18.1 KB (added by gmhossain, 11 years ago)
  • sage/calculus/calculus.py

    # HG changeset patch
    # User Golam Mortuza Hossain <gmhossain@gmail.com>
    # Date 1239118264 10800
    # Node ID e190effda0d16b5b703ee277674984613411b0ab
    # Parent  17fe77f21e21c79cb989aaab2e2fe128d16beaa1
    Enhances typsetting of Symbolic functions within Sage
    
    diff -r 17fe77f21e21 -r e190effda0d1 sage/calculus/calculus.py
    a b  
    297297from sage.structure.parent_base import ParentWithBase
    298298
    299299import operator
    300 from sage.misc.latex import latex, latex_variable_name
     300from sage.misc.latex import latex, latex_variable_name, latex_symbolic_function
    301301from sage.misc.misc import uniq as unique
    302302from sage.structure.sage_object import SageObject
    303303
     
    97249724           
    97259725    def _latex_(self):
    97269726        r"""
    9727         Return a latex version of the function
    9728        
    9729         EXAMPLES::
    9730        
    9731             sage: var("t,u")
    9732             (t, u)
    9733             sage: y=function('y',u)
    9734             sage: z=function('z',t,u)
    9735             sage: latex(y)
    9736             y\left(u\right)
    9737             sage: latex(diff(y,u))
    9738             {{{\it \partial}}\over{{\it \partial}\,u}}\,y\left(u\right)
    9739             sage: latex(diff(y,u,3))
    9740             {{{\it \partial}^3}\over{{\it \partial}\,u^3}}\,y\left(u\right)
    9741             sage: latex(diff(z,u))
    9742             {{{\it \partial}}\over{{\it \partial}\,u}}\,z\left(t , u\right)
    9743             sage: latex(diff(z,u,t,u,t))
    9744             {{{\it \partial}^4}\over{{\it \partial}\,t^2\,{\it \partial}\,u^2}}  \,z\left(t , u\right)
    9745             sage: latex(integrate(y,u))
    9746             \int {y\left(u\right)}{\;du}
     9727        Return a LaTeX expression of the function.
     9728       
     9729        EXAMPLES::
     9730       
     9731            sage: var('x,y,a,b,t,s')
     9732            (x, y, a, b, t, s)
     9733            sage: psi(x) = function('psi',x)
     9734            sage: latex(psi(x))
     9735            \psi(x)
     9736            sage: latex(psi(x).conjugate())
     9737            {\psi}^*(x)
     9738            sage: latex(limit(psi(x),x=a))
     9739            \lim_{x \to a}\, \psi(x)
     9740
     9741            sage: f(t) = function('f',t)
     9742            sage: latex(laplace(f(t),t,s))
     9743            \mathcal{L}\left(f(t), t, s\right)
     9744
     9745            sage: F(s) = function('F',s)
     9746            sage: latex(inverse_laplace(F(s),s,t))
     9747            \mathcal{L}^{-1}\left(F(s), s, t\right)
     9748
     9749            sage: f(x) = function('f',x)
     9750            sage: latex(integrate(f(x),x))
     9751            \int f(x)\,{d x}
     9752            sage: latex(integrate(f(x),x,a,b))
     9753            \int_{a}^{b} f(x)\,{d x}
     9754
     9755            sage: var('x,y')
     9756            (x, y)
     9757            sage: f(x) = function('f',x)
     9758            sage: latex(diff(f(x),x))
     9759            \frac{d f(x)}{d x}
     9760            sage: f(x,y) = function('f',x,y)
     9761            sage: latex(diff(f(x,y),x))
     9762            \frac{\partial}{\partial x}f(x, y)
     9763
     9764            sage: myfunc(x) = function('myfunc',x)
     9765            sage: latex(myfunc(x))
     9766            {\it myfunc}(x)
    97479767
    97489768            sage: latex(derivative(ceil(x), x))
    9749             {{{\it \partial}}\over{{\it \partial}\,x}}\,\left \lceil x \right \rceil
    9750 
    9751         """
    9752         try:
    9753             return  latex(self._maxima_())
    9754         except:
    9755             return "{\\rm %s}(%s)"%(self._f._name, ', '.join([x._latex_() for
    9756                                                               x in self._args]))
    9757            
    9758        
     9769            \frac{d \left \lceil x \right \rceil}{d x}
     9770
     9771        """
     9772        return latex_symbolic_function(self)
     9773
     9774    def set_latex(self, expr=None):
     9775        r"""
     9776        Set custom LaTeX expression for the given symbolic function.
     9777
     9778        INPUTS:
     9779
     9780        -  ``expr``  -- a valid LaTeX expression to be used for the
     9781                        function.
     9782
     9783        Calling it without an arugment will reset any previously set
     9784        custom LaTeX expression. See EXAMPLES section for explicit use.
     9785   
     9786        EXAMPLES::
     9787   
     9788            sage: var('x')
     9789            x
     9790            sage: riemann(x) = function('riemann',x)
     9791            sage: latex(riemann(x))
     9792            {\it riemann}(x)
     9793            sage: riemann(x).set_latex('\\mathcal{R}')
     9794            sage: latex(riemann(x))
     9795            \mathcal{R}(x)
     9796            sage: riemann(x).set_latex()
     9797            sage: latex(riemann(x))
     9798            {\it riemann}(x)
     9799   
     9800        AUTHORS:
     9801       
     9802        - Golam Mortuza Hossain (2009-04-05)
     9803        """
     9804        from sage.misc.latex import user_defined_latex_dict as ldict
     9805        key = self._f._name
     9806        # Some sanity checks
     9807        if expr is not None and expr != "" and not expr.isspace():
     9808            ldict[key] = expr
     9809        elif key in ldict:
     9810            del ldict[key]
     9811        return None
    97599812
    97609813    def _maxima_init_(self):
    97619814        r"""
  • sage/misc/latex.py

    diff -r 17fe77f21e21 -r e190effda0d1 sage/misc/latex.py
    a b  
    756756                   'omega',
    757757                   'Omega']
    758758
     759def latex_symbolic_function(self):
     760    r"""
     761    Typeset a given symbolic function in LaTeX.
     762   
     763    EXAMPLES::
     764   
     765        sage: import sage.misc.latex as latex_module
     766        sage: latex_sym_fn = latex_module.latex_symbolic_function
     767        sage: var('x,a,b,t,s')
     768        (x, a, b, t, s)
     769        sage: psi(x) = function('psi',x)
     770        sage: latex_sym_fn(psi(x))
     771        '\\psi(x)'
     772        sage: latex_sym_fn(psi(x).conjugate())
     773        '{\\psi}^*(x)'
     774        sage: latex_sym_fn(limit(psi(x),x=a))
     775        '\\lim_{x \\to a}\\, \\psi(x)'
     776
     777        sage: f(t) = function('f',t)
     778        sage: latex_sym_fn(laplace(f(t),t,s))
     779        '\\mathcal{L}\\left(f(t), t, s\\right)'
     780
     781        sage: F(s) = function('F',s)
     782        sage: latex_sym_fn(inverse_laplace(F(s),s,t))
     783        '\\mathcal{L}^{-1}\\left(F(s), s, t\\right)'
     784
     785        sage: f(x) = function('f',x)
     786        sage: latex_sym_fn(integrate(f(x),x))
     787        '\\int f(x)\\,{d x}'
     788        sage: latex_sym_fn(integrate(f(x),x,a,b))
     789        '\\int_{a}^{b} f(x)\\,{d x}'
     790
     791        sage: var('x,y')
     792        (x, y)
     793        sage: f(x) = function('f',x)
     794        sage: latex_sym_fn(diff(f(x),x))
     795        '\\frac{d f(x)}{d x}'
     796        sage: f(x,y) = function('f',x,y)
     797        sage: latex_sym_fn(diff(f(x,y),x))
     798        '\\frac{\\partial}{\\partial x}f(x, y)'
     799
     800        sage: myfunc(x) = function('myfunc',x)
     801        sage: latex_sym_fn(myfunc(x))
     802        '{\\it myfunc}(x)'
     803   
     804    AUTHORS:
     805
     806    - Golam Mortuza Hossain (2009-04-05)
     807    """
     808        # Get the name of symbolic function
     809    fname = self._f._name
     810    # Special handling of fname where specific processing is needed
     811    if fname == "conjugate":
     812        return _conjugate_latex_(self)
     813    elif fname == "limit":
     814        return _limit_latex_(self)
     815    elif fname == "laplace":
     816        return _laplace_latex_(self)
     817    elif fname == "ilt":
     818        return _inverse_laplace_latex_(self)
     819    elif fname == "integrate":
     820        return _integrate_latex_(self)
     821    elif fname == "diff":
     822        return _derivative_latex_(self)
     823    # Check whether fname has custom LaTeX string or is a Greek letter
     824    name = latex_function_name(fname)
     825    if name is not False:
     826        return "%s%s"%(name, _args_latex_(self))
     827    # Use default typesetting scheme
     828    return _symbolic_function_default_latex_(self)
     829
     830def _symbolic_function_default_latex_(self):
     831    r"""
     832    Return LaTeX expression of a symbolic function using default scheme.
     833   
     834    EXAMPLES::
     835   
     836        sage: import sage.misc.latex as latex_module
     837        sage: _sym_def_latex_ = latex_module._symbolic_function_default_latex_
     838        sage: var('x')
     839        x
     840        sage: myfunc(x) = function('myfunc',x)
     841        sage: _sym_def_latex_(myfunc(x))
     842        '{\\it myfunc}(x)'
     843        sage: my_func(x) = function('my_func',x)
     844        sage: _sym_def_latex_(my_func(x))
     845        '{\\it my\\_func}(x)'
     846   
     847    AUTHORS:
     848
     849    - Golam Mortuza Hossain (2009-04-05)
     850    """
     851        # Get the name of the symbolic function
     852    fname = self._f._name
     853    fname = fname.replace("_", "\\_")
     854    # Default typesetting scheme (similar to Maxima scheme)
     855    return "{\\it %s}%s"%(fname, _args_latex_(self))
     856
     857def _args_latex_(self):
     858    r"""
     859    Return LaTeX expression for the arguments of a symbolic function.
     860   
     861    EXAMPLES::
     862   
     863        sage: import sage.misc.latex as latex_module
     864        sage: _args_latex_ = latex_module._args_latex_
     865        sage: var('x')
     866        x
     867        sage: f(x) = function('f',x)
     868        sage: _args_latex_(f(x))
     869        '(x)'
     870        sage: g(x) = function('g',x)
     871        sage: _args_latex_(f(g(x)))
     872        '\\left(g(x)\\right)'
     873   
     874    AUTHORS:
     875
     876    - Golam Mortuza Hossain (2009-04-06)
     877    """
     878    from sage.calculus.calculus import SymbolicVariable
     879    # If all arguments are SymbolicVariables then the function should be
     880    # typeset as f(x) rather than f\left(x\right)     
     881    use_left_right = False
     882    for x in self._args:
     883        if not isinstance(x, SymbolicVariable):
     884            use_left_right = True
     885            break
     886    if use_left_right is True:
     887        return "\\left(%s\\right)"%(', '.join([latex(x) for x in self._args]))
     888    else:
     889        return "(%s)"%(', '.join([latex(x) for x in self._args]))
     890
     891def _derivative_latex_(self):
     892    r"""
     893    Return LaTeX expression for derivatives of a symbolic function.
     894   
     895    EXAMPLES::
     896   
     897        sage: import sage.misc.latex as latex_module
     898        sage: _derivative_latex_ = latex_module._derivative_latex_
     899        sage: var('x,y')
     900        (x, y)
     901        sage: f(x) = function('f',x)
     902        sage: _derivative_latex_(diff(f(x),x))
     903        '\\frac{d f(x)}{d x}'
     904        sage: _derivative_latex_(diff(f(x),x,2))
     905        '\\frac{d^{2} f(x)}{d {x}^{2}}'
     906
     907        sage: f(x,y) = function('f',x,y)
     908        sage: _derivative_latex_(diff(f(x,y),x))
     909        '\\frac{\\partial}{\\partial x}f(x, y)'
     910        sage: _derivative_latex_(diff(f(x,y),x,3))
     911        '\\frac{\\partial^{3}}{\\partial {x}^{3}}f(x, y)'
     912        sage: _derivative_latex_(diff(f(x,y),x,y))
     913        '\\frac{\\partial^{2}}{\\partial y\\partial x}f(x, y)'
     914   
     915    AUTHORS:
     916
     917    - Golam Mortuza Hossain (2009-04-05)
     918    """
     919    n = len(self._args)
     920    # We dont do any processing for n < 2
     921    if n < 2:
     922        return _symbolic_function_default_latex_(self)
     923    # Read the function
     924    f = self._args[0]
     925    # Check whether it should be partial derivative
     926    # Logic taken from: http://trac.sagemath.org/sage_trac/ticket/4202
     927    if len(f.variables()) == 1:
     928        d_latex = "d"
     929    else:
     930        d_latex = "\\partial"
     931
     932    # Read the variables
     933    diffstr = ""; total = 0
     934    for i in range(1,n-1,2):
     935        x = self._args[i]    # variable
     936        j = self._args[i+1]  # no of times diff acts on f w.r.t. variable x
     937        total = total + j    # total no of times diff acts 
     938        if j == 1:
     939            diffstr = "%s %s"%(d_latex, latex(x)) + diffstr 
     940        else:
     941            diffstr = "%s {%s}^{%s}"%(d_latex, latex(x), latex(j)) + diffstr 
     942    # Return final expression
     943    if total == 1:
     944        if d_latex == "d":
     945            return "\\frac{%s %s}{%s}"%(d_latex, latex(f), diffstr)
     946        else:
     947            return "\\frac{%s}{%s}%s"%(d_latex, diffstr, latex(f))
     948    if d_latex == "d":
     949        return "\\frac{%s^{%d} %s}{%s}"%(d_latex, total, latex(f), diffstr)
     950    else:
     951        return "\\frac{%s^{%d}}{%s}%s"%(d_latex, total, diffstr, latex(f))
     952
     953def _integrate_latex_(self):
     954    r"""
     955    Return LaTeX expression for integration of a symbolic function.
     956   
     957    EXAMPLES::
     958   
     959        sage: import sage.misc.latex as latex_module
     960        sage: _integrate_latex_ = latex_module._integrate_latex_
     961        sage: var('x,a,b')
     962        (x, a, b)
     963        sage: f(x) = function('f',x)
     964        sage: _integrate_latex_(integrate(f(x),x))
     965        '\\int f(x)\\,{d x}'
     966        sage: _integrate_latex_(integrate(f(x),x,a,b))
     967        '\\int_{a}^{b} f(x)\\,{d x}'
     968   
     969    AUTHORS:
     970
     971    - Golam Mortuza Hossain (2009-04-05)
     972    """
     973    n = len(self._args)
     974    # We dont process if number of arguments is neither 2 nor 4
     975    if n != 2 and n != 4:
     976        # Return default typesetting
     977        return _symbolic_function_default_latex_(self)
     978    f = self._args[0]
     979    x = self._args[1]
     980    # Check whether its a definite integral
     981    if n == 4:
     982        a = self._args[2]
     983        b = self._args[3]
     984        return "\\int_{%s}^{%s} %s\\,{d %s}"%(latex(a), latex(b), latex(f), latex(x))
     985    # Typeset as indefinite integral
     986    return "\\int %s\\,{d %s}"%(latex(f), latex(x))
     987
     988def _inverse_laplace_latex_(self):
     989    r"""
     990    Return LaTeX expression for inverse Laplace transform of a symbolic function.
     991   
     992    EXAMPLES::
     993   
     994        sage: import sage.misc.latex as latex_module
     995        sage: _inverse_laplace_latex_ = latex_module._inverse_laplace_latex_
     996        sage: var('s,t')
     997        (s, t)
     998        sage: F(s) = function('F',s)
     999        sage: _inverse_laplace_latex_(inverse_laplace(F(s),s,t))
     1000        '\\mathcal{L}^{-1}\\left(F(s), s, t\\right)'
     1001   
     1002    AUTHORS:
     1003
     1004    - Golam Mortuza Hossain (2009-04-05)
     1005    """
     1006    return "\\mathcal{L}^{-1}\\left(%s\\right)"%(', '.join([latex(x) for x in self._args]))
     1007
     1008def _laplace_latex_(self):
     1009    r"""
     1010    Return LaTeX expression for Laplace transform of a symbolic function.
     1011   
     1012    EXAMPLES::
     1013   
     1014        sage: import sage.misc.latex as latex_module
     1015        sage: _laplace_latex_ = latex_module._laplace_latex_
     1016        sage: var('s,t')
     1017        (s, t)
     1018        sage: f(t) = function('f',t)
     1019        sage: _laplace_latex_(laplace(f(t),t,s))
     1020        '\\mathcal{L}\\left(f(t), t, s\\right)'
     1021   
     1022    AUTHORS:
     1023
     1024    - Golam Mortuza Hossain (2009-04-05)
     1025    """
     1026    return "\\mathcal{L}\\left(%s\\right)"%(', '.join([latex(x) for x in self._args]))
     1027
     1028def _limit_latex_(self):
     1029    r"""
     1030    Return latex expression for limit of a symbolic function.
     1031   
     1032    EXAMPLES::
     1033   
     1034        sage: import sage.misc.latex as latex_module
     1035        sage: _limit_latex_ = latex_module._limit_latex_
     1036        sage: var('x,a')
     1037        (x, a)
     1038        sage: psi(x) = function('psi',x)
     1039        sage: _limit_latex_(limit(psi(x),x=a))
     1040        '\\lim_{x \\to a}\\, \\psi(x)'
     1041   
     1042    AUTHORS:
     1043
     1044    - Golam Mortuza Hossain (2009-04-05)
     1045    """
     1046    # We process only if there are precisely three arguments
     1047    if len(self._args) == 3:
     1048        # Read f,x,a from arguments
     1049        f = self._args[0]
     1050        x = self._args[1]
     1051        a = self._args[2]
     1052        return "\\lim_{%s \\to %s}\\, %s"%(latex(x), latex(a), latex(f))
     1053    # Return default typesetting
     1054    return _symbolic_function_default_latex_(self)
     1055
     1056def _conjugate_latex_(self):
     1057    r"""
     1058    Return LaTeX expression for conjugate of a symbolic function.
     1059   
     1060    EXAMPLES::
     1061   
     1062        sage: import sage.misc.latex as latex_module
     1063        sage: _conjugate_latex_ = latex_module._conjugate_latex_
     1064        sage: var('x')
     1065        x
     1066        sage: psi(x) = function('psi',x)
     1067        sage: _conjugate_latex_(psi(x).conjugate())
     1068        '{\\psi}^*(x)'
     1069   
     1070    AUTHORS:
     1071
     1072    - Golam Mortuza Hossain (2009-04-05)
     1073    """
     1074    # We process only if there is only one argument
     1075    if len(self._args) == 1:
     1076        chld = self._args[0]
     1077        name = latex_function_name(chld._f._name)
     1078        if name is not False:
     1079                # conjugate(psi(x)) => psi^*(x)
     1080            return "{%s}^*%s"%(name, _args_latex_(chld))
     1081    # Return default typesetting
     1082    return _symbolic_function_default_latex_(self)
     1083
     1084user_defined_latex_dict = {}
     1085
     1086def latex_function_name(x):
     1087    r"""
     1088    Return common function names such as alpha, beta1, psi_00, R_mn,
     1089    etc. as latex symbols, else return False.
     1090   
     1091    EXAMPLES::
     1092   
     1093        sage: import sage.misc.latex as latex_module
     1094        sage: latex_function_name = latex_module.latex_function_name
     1095        sage: latex_function_name('psi')
     1096        '\\psi'
     1097        sage: latex_function_name('psi0')
     1098        '\\psi_{0}'
     1099        sage: latex_function_name('f1')
     1100        'f_{1}'
     1101        sage: latex_function_name('psi_mu')
     1102        '\\psi_{\\mu}'
     1103        sage: latex_function_name('psi_11')
     1104        '\\psi_{11}'
     1105        sage: latex_function_name('R_ab')
     1106        'R_{ab}'
     1107        sage: latex_function_name('R_nu')
     1108        'R_{\\nu}'
     1109        sage: latex_function_name('myfunc')
     1110        False
     1111        sage: latex_function_name('psi_')
     1112        False
     1113        sage: latex_function_name('abc_xyz_psi')
     1114        False
     1115        sage: latex_function_name('abc_beta')
     1116        False
     1117   
     1118    NOTES:
     1119
     1120    This function is based largely on latex_variable_name function.
     1121   
     1122    AUTHORS:
     1123
     1124    - Golam Mortuza Hossain (2009-04-05)
     1125    """
     1126    # If user has defined latex string then use it first
     1127    if x in user_defined_latex_dict:
     1128        return user_defined_latex_dict[x]
     1129    # For known names return them after preprending with "\\"
     1130    if x in common_varnames:
     1131        return "\\" + x
     1132    # Look for underscrore. If found then use its postion to
     1133    # find the suffix
     1134    underscore = x.find("_")
     1135    if underscore == -1:
     1136        import re
     1137        # * The "\d|[.,]" means "decimal digit" or period or comma
     1138        # * The "+" means "1 or more"
     1139        # * The "$" means "at the end of the line"
     1140        m = re.search('(\d|[.,])+$',x)
     1141        if m is None:
     1142            prefix = x
     1143            suffix = None
     1144        else:
     1145            prefix = x[:m.start()]
     1146            suffix = x[m.start():]
     1147    else:
     1148        prefix = x[:underscore]
     1149        suffix = x[underscore+1:]
     1150        if len(suffix)== 0:
     1151            return False
     1152    # If suffix contains underscores then don't process
     1153    if suffix and suffix.find("_") != -1:
     1154        return False
     1155    # If prefix is not a common name or a more-than-one letters word
     1156    # then don't process
     1157    if prefix not in common_varnames and len(prefix) != 1:
     1158        return False
     1159    # Check if prefix or suffix is a common name   
     1160    if prefix in common_varnames:
     1161        prefix = "\\" + prefix
     1162    if suffix and len(suffix) > 0:
     1163        if suffix in common_varnames:
     1164            suffix = "\\" + suffix
     1165        return '%s_{%s}'%(prefix, suffix)
     1166    else:
     1167        return '%s'%(prefix)
     1168
    7591169def latex_varify(a):
    7601170    if a in common_varnames:
    7611171        return "\\" + a