Hi,

On Wed, Apr 1, 2009 at 10:11 PM, Jason Grout
<jason-s...@creativetrax.com> wrote:
>
>> Should I submit patches for each of these functions
>> separately?
>
> I think one patch covering all of the functions would be fine.  It's one
> logical issue.


... So here goes the patch to enhance the typesetting capability
of symbolic functions within sage. It includes several doc-tests
for each functions.

Main features are:

(1) Symbolics functions with name in Greek letters (with possible
suffixes), are typeset nicely in LaTeX.

Ex:  psi(x)  =>  \psi(x)

(2) Functions such as "diff", "integrate", "limit", "conjugate",
"laplace", "inverse_lapse" are now typeset within Sage itself.

Ex:  psi(x).conjugate()  =>    {\psi}^*(x)

(3) Default (fall-back) typesetting for unknown functions (as
in Maxima).

Ex:  myfn(x)   =>  {\it myfn}(x)

(4) Allows users to define their own/custom LaTeX expression
for any symbolic functions via a new method "set_latex()" for
the class SymbolicFunctionEvaluation.

Ex:  var('t');
       hubble(t) = function('hubble',t)
       hubble(t).set_latex('\\mathcal{H}')

       #To reset custom LaTeX expression
       hubble(t).set_latex()

(5)  If the arguments of a symbolic function are all symbolic
variables then typesetting will avoid using \left(, \right).

Ex:  Phi(x,y) => \Phi(x, y)  (if x,y are symbolic vars)


Note: You need to apply a small patch

http://trac.sagemath.org/sage_trac/ticket/5678

before you apply the attached patch. This patch is
created using sage-3.4.

I will be happy to hear any issues that you may find
in it, before I open a ticket for this enhancement.


Cheers,
Golam

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to 
sage-devel-unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---

# HG changeset patch
# User Golam Mortuza Hossain <gmhoss...@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/sage/calculus/calculus.py	Thu Mar 26 15:00:42 2009 -0300
+++ b/sage/calculus/calculus.py	Tue Apr 07 12:31:04 2009 -0300
@@ -297,7 +297,7 @@
 from sage.structure.parent_base import ParentWithBase
 
 import operator
-from sage.misc.latex import latex, latex_variable_name
+from sage.misc.latex import latex, latex_variable_name, latex_symbolic_function
 from sage.misc.misc import uniq as unique
 from sage.structure.sage_object import SageObject
 
@@ -9724,38 +9724,91 @@
             
     def _latex_(self):
         r"""
-        Return a latex version of the function
-        
-        EXAMPLES::
-        
-            sage: var("t,u")
-            (t, u)
-            sage: y=function('y',u)
-            sage: z=function('z',t,u)
-            sage: latex(y)
-            y\left(u\right)
-            sage: latex(diff(y,u))
-            {{{\it \partial}}\over{{\it \partial}\,u}}\,y\left(u\right)
-            sage: latex(diff(y,u,3))
-            {{{\it \partial}^3}\over{{\it \partial}\,u^3}}\,y\left(u\right)
-            sage: latex(diff(z,u))
-            {{{\it \partial}}\over{{\it \partial}\,u}}\,z\left(t , u\right)
-            sage: latex(diff(z,u,t,u,t))
-            {{{\it \partial}^4}\over{{\it \partial}\,t^2\,{\it \partial}\,u^2}}  \,z\left(t , u\right)
-            sage: latex(integrate(y,u))
-            \int {y\left(u\right)}{\;du}
+        Return a LaTeX expression of the function.
+        
+        EXAMPLES::
+        
+            sage: var('x,y,a,b,t,s')
+            (x, y, a, b, t, s)
+            sage: psi(x) = function('psi',x)
+            sage: latex(psi(x))
+            \psi(x)
+            sage: latex(psi(x).conjugate())
+            {\psi}^*(x)
+            sage: latex(limit(psi(x),x=a))
+            \lim_{x \to a}\, \psi(x)
+
+            sage: f(t) = function('f',t)
+            sage: latex(laplace(f(t),t,s))
+            \mathcal{L}\left(f(t), t, s\right)
+
+            sage: F(s) = function('F',s)
+            sage: latex(inverse_laplace(F(s),s,t))
+            \mathcal{L}^{-1}\left(F(s), s, t\right)
+
+            sage: f(x) = function('f',x)
+            sage: latex(integrate(f(x),x))
+            \int f(x)\,{d x}
+            sage: latex(integrate(f(x),x,a,b))
+            \int_{a}^{b} f(x)\,{d x}
+
+            sage: var('x,y')
+            (x, y)
+            sage: f(x) = function('f',x)
+            sage: latex(diff(f(x),x))
+            \frac{d f(x)}{d x}
+            sage: f(x,y) = function('f',x,y)
+            sage: latex(diff(f(x,y),x))
+            \frac{\partial}{\partial x}f(x, y)
+
+            sage: myfunc(x) = function('myfunc',x)
+            sage: latex(myfunc(x))
+            {\it myfunc}(x)
 
             sage: latex(derivative(ceil(x), x))
-            {{{\it \partial}}\over{{\it \partial}\,x}}\,\left \lceil x \right \rceil
-
-        """
-        try:
-            return  latex(self._maxima_())
-        except:
-            return "{\\rm %s}(%s)"%(self._f._name, ', '.join([x._latex_() for
-                                                              x in self._args]))
-            
-        
+            \frac{d \left \lceil x \right \rceil}{d x}
+
+        """
+        return latex_symbolic_function(self)
+
+    def set_latex(self, expr=None):
+        r"""
+        Set custom LaTeX expression for the given symbolic function.
+
+        INPUTS:
+
+        -  ``expr``  -- a valid LaTeX expression to be used for the 
+                        function. 
+
+        Calling it without an arugment will reset any previously set 
+        custom LaTeX expression. See EXAMPLES section for explicit use.
+    
+        EXAMPLES::
+    
+            sage: var('x')
+            x
+            sage: riemann(x) = function('riemann',x)
+            sage: latex(riemann(x))
+            {\it riemann}(x)
+            sage: riemann(x).set_latex('\\mathcal{R}')
+            sage: latex(riemann(x))
+            \mathcal{R}(x)
+            sage: riemann(x).set_latex()
+            sage: latex(riemann(x))
+            {\it riemann}(x)
+    
+        AUTHORS:
+        
+        - Golam Mortuza Hossain (2009-04-05)
+        """
+        from sage.misc.latex import user_defined_latex_dict as ldict
+        key = self._f._name
+        # Some sanity checks
+        if expr is not None and expr != "" and not expr.isspace():
+            ldict[key] = expr
+        elif key in ldict:
+            del ldict[key]
+        return None
 
     def _maxima_init_(self):
         r"""
diff -r 17fe77f21e21 -r e190effda0d1 sage/misc/latex.py
--- a/sage/misc/latex.py	Thu Mar 26 15:00:42 2009 -0300
+++ b/sage/misc/latex.py	Tue Apr 07 12:31:04 2009 -0300
@@ -756,6 +756,416 @@
                    'omega',
                    'Omega']
 
+def latex_symbolic_function(self):
+    r"""
+    Typeset a given symbolic function in LaTeX.
+    
+    EXAMPLES::
+    
+        sage: import sage.misc.latex as latex_module
+        sage: latex_sym_fn = latex_module.latex_symbolic_function
+        sage: var('x,a,b,t,s')
+        (x, a, b, t, s)
+        sage: psi(x) = function('psi',x)
+        sage: latex_sym_fn(psi(x))
+        '\\psi(x)'
+        sage: latex_sym_fn(psi(x).conjugate())
+        '{\\psi}^*(x)'
+        sage: latex_sym_fn(limit(psi(x),x=a))
+        '\\lim_{x \\to a}\\, \\psi(x)'
+
+        sage: f(t) = function('f',t)
+        sage: latex_sym_fn(laplace(f(t),t,s))
+        '\\mathcal{L}\\left(f(t), t, s\\right)'
+
+        sage: F(s) = function('F',s)
+        sage: latex_sym_fn(inverse_laplace(F(s),s,t))
+        '\\mathcal{L}^{-1}\\left(F(s), s, t\\right)'
+
+        sage: f(x) = function('f',x)
+        sage: latex_sym_fn(integrate(f(x),x))
+        '\\int f(x)\\,{d x}'
+        sage: latex_sym_fn(integrate(f(x),x,a,b))
+        '\\int_{a}^{b} f(x)\\,{d x}'
+
+        sage: var('x,y')
+        (x, y)
+        sage: f(x) = function('f',x)
+        sage: latex_sym_fn(diff(f(x),x))
+        '\\frac{d f(x)}{d x}'
+        sage: f(x,y) = function('f',x,y)
+        sage: latex_sym_fn(diff(f(x,y),x))
+        '\\frac{\\partial}{\\partial x}f(x, y)'
+
+        sage: myfunc(x) = function('myfunc',x)
+        sage: latex_sym_fn(myfunc(x))
+        '{\\it myfunc}(x)'
+    
+    AUTHORS:
+
+    - Golam Mortuza Hossain (2009-04-05)
+    """
+ 	# Get the name of symbolic function 
+    fname = self._f._name
+    # Special handling of fname where specific processing is needed
+    if fname == "conjugate":
+        return _conjugate_latex_(self)
+    elif fname == "limit":
+        return _limit_latex_(self)
+    elif fname == "laplace":
+        return _laplace_latex_(self)
+    elif fname == "ilt":
+        return _inverse_laplace_latex_(self)
+    elif fname == "integrate":
+        return _integrate_latex_(self)
+    elif fname == "diff":
+        return _derivative_latex_(self)
+    # Check whether fname has custom LaTeX string or is a Greek letter
+    name = latex_function_name(fname)
+    if name is not False:
+        return "%s%s"%(name, _args_latex_(self))
+    # Use default typesetting scheme
+    return _symbolic_function_default_latex_(self)
+
+def _symbolic_function_default_latex_(self):
+    r"""
+    Return LaTeX expression of a symbolic function using default scheme.
+    
+    EXAMPLES::
+    
+        sage: import sage.misc.latex as latex_module
+        sage: _sym_def_latex_ = latex_module._symbolic_function_default_latex_
+        sage: var('x')
+        x
+        sage: myfunc(x) = function('myfunc',x)
+        sage: _sym_def_latex_(myfunc(x))
+        '{\\it myfunc}(x)'
+        sage: my_func(x) = function('my_func',x)
+        sage: _sym_def_latex_(my_func(x))
+        '{\\it my\\_func}(x)'
+    
+    AUTHORS:
+
+    - Golam Mortuza Hossain (2009-04-05)
+    """
+ 	# Get the name of the symbolic function 
+    fname = self._f._name
+    fname = fname.replace("_", "\\_")
+    # Default typesetting scheme (similar to Maxima scheme)
+    return "{\\it %s}%s"%(fname, _args_latex_(self))
+
+def _args_latex_(self):
+    r"""
+    Return LaTeX expression for the arguments of a symbolic function.
+    
+    EXAMPLES::
+    
+        sage: import sage.misc.latex as latex_module
+        sage: _args_latex_ = latex_module._args_latex_
+        sage: var('x')
+        x
+        sage: f(x) = function('f',x)
+        sage: _args_latex_(f(x))
+        '(x)'
+        sage: g(x) = function('g',x)
+        sage: _args_latex_(f(g(x)))
+        '\\left(g(x)\\right)'
+    
+    AUTHORS:
+
+    - Golam Mortuza Hossain (2009-04-06)
+    """
+    from sage.calculus.calculus import SymbolicVariable
+    # If all arguments are SymbolicVariables then the function should be 
+    # typeset as f(x) rather than f\left(x\right)     
+    use_left_right = False
+    for x in self._args:
+        if not isinstance(x, SymbolicVariable):
+            use_left_right = True
+            break
+    if use_left_right is True:
+        return "\\left(%s\\right)"%(', '.join([latex(x) for x in self._args]))
+    else:
+        return "(%s)"%(', '.join([latex(x) for x in self._args]))
+
+def _derivative_latex_(self):
+    r"""
+    Return LaTeX expression for derivatives of a symbolic function.
+    
+    EXAMPLES::
+    
+        sage: import sage.misc.latex as latex_module
+        sage: _derivative_latex_ = latex_module._derivative_latex_
+        sage: var('x,y')
+        (x, y)
+        sage: f(x) = function('f',x)
+        sage: _derivative_latex_(diff(f(x),x))
+        '\\frac{d f(x)}{d x}'
+        sage: _derivative_latex_(diff(f(x),x,2))
+        '\\frac{d^{2} f(x)}{d {x}^{2}}'
+
+        sage: f(x,y) = function('f',x,y)
+        sage: _derivative_latex_(diff(f(x,y),x))
+        '\\frac{\\partial}{\\partial x}f(x, y)'
+        sage: _derivative_latex_(diff(f(x,y),x,3))
+        '\\frac{\\partial^{3}}{\\partial {x}^{3}}f(x, y)'
+        sage: _derivative_latex_(diff(f(x,y),x,y))
+        '\\frac{\\partial^{2}}{\\partial y\\partial x}f(x, y)'
+    
+    AUTHORS:
+
+    - Golam Mortuza Hossain (2009-04-05)
+    """
+    n = len(self._args)
+    # We dont do any processing for n < 2
+    if n < 2:
+        return _symbolic_function_default_latex_(self)
+    # Read the function
+    f = self._args[0]
+    # Check whether it should be partial derivative 
+    # Logic taken from: http://trac.sagemath.org/sage_trac/ticket/4202
+    if len(f.variables()) == 1:
+        d_latex = "d"
+    else:
+        d_latex = "\\partial"
+
+    # Read the variables
+    diffstr = ""; total = 0
+    for i in range(1,n-1,2):
+        x = self._args[i]    # variable
+        j = self._args[i+1]  # no of times diff acts on f w.r.t. variable x 
+        total = total + j    # total no of times diff acts  
+        if j == 1:
+            diffstr = "%s %s"%(d_latex, latex(x)) + diffstr  
+        else:
+            diffstr = "%s {%s}^{%s}"%(d_latex, latex(x), latex(j)) + diffstr  
+    # Return final expression 
+    if total == 1:
+        if d_latex == "d":
+            return "\\frac{%s %s}{%s}"%(d_latex, latex(f), diffstr)
+        else:
+            return "\\frac{%s}{%s}%s"%(d_latex, diffstr, latex(f))
+    if d_latex == "d":
+        return "\\frac{%s^{%d} %s}{%s}"%(d_latex, total, latex(f), diffstr)
+    else:
+        return "\\frac{%s^{%d}}{%s}%s"%(d_latex, total, diffstr, latex(f))
+
+def _integrate_latex_(self):
+    r"""
+    Return LaTeX expression for integration of a symbolic function.
+    
+    EXAMPLES::
+    
+        sage: import sage.misc.latex as latex_module
+        sage: _integrate_latex_ = latex_module._integrate_latex_
+        sage: var('x,a,b')
+        (x, a, b)
+        sage: f(x) = function('f',x)
+        sage: _integrate_latex_(integrate(f(x),x))
+        '\\int f(x)\\,{d x}'
+        sage: _integrate_latex_(integrate(f(x),x,a,b))
+        '\\int_{a}^{b} f(x)\\,{d x}'
+    
+    AUTHORS:
+
+    - Golam Mortuza Hossain (2009-04-05)
+    """
+    n = len(self._args)
+    # We dont process if number of arguments is neither 2 nor 4
+    if n != 2 and n != 4:
+        # Return default typesetting
+        return _symbolic_function_default_latex_(self)
+    f = self._args[0]
+    x = self._args[1]
+    # Check whether its a definite integral
+    if n == 4:
+        a = self._args[2]
+        b = self._args[3]
+        return "\\int_{%s}^{%s} %s\\,{d %s}"%(latex(a), latex(b), latex(f), latex(x))
+    # Typeset as indefinite integral
+    return "\\int %s\\,{d %s}"%(latex(f), latex(x))
+
+def _inverse_laplace_latex_(self):
+    r"""
+    Return LaTeX expression for inverse Laplace transform of a symbolic function.
+    
+    EXAMPLES::
+    
+        sage: import sage.misc.latex as latex_module
+        sage: _inverse_laplace_latex_ = latex_module._inverse_laplace_latex_
+        sage: var('s,t')
+        (s, t)
+        sage: F(s) = function('F',s)
+        sage: _inverse_laplace_latex_(inverse_laplace(F(s),s,t))
+        '\\mathcal{L}^{-1}\\left(F(s), s, t\\right)'
+    
+    AUTHORS:
+
+    - Golam Mortuza Hossain (2009-04-05)
+    """
+    return "\\mathcal{L}^{-1}\\left(%s\\right)"%(', '.join([latex(x) for x in self._args]))
+
+def _laplace_latex_(self):
+    r"""
+    Return LaTeX expression for Laplace transform of a symbolic function.
+    
+    EXAMPLES::
+    
+        sage: import sage.misc.latex as latex_module
+        sage: _laplace_latex_ = latex_module._laplace_latex_
+        sage: var('s,t')
+        (s, t)
+        sage: f(t) = function('f',t)
+        sage: _laplace_latex_(laplace(f(t),t,s))
+        '\\mathcal{L}\\left(f(t), t, s\\right)'
+    
+    AUTHORS:
+
+    - Golam Mortuza Hossain (2009-04-05)
+    """
+    return "\\mathcal{L}\\left(%s\\right)"%(', '.join([latex(x) for x in self._args]))
+
+def _limit_latex_(self):
+    r"""
+    Return latex expression for limit of a symbolic function.
+    
+    EXAMPLES::
+    
+        sage: import sage.misc.latex as latex_module
+        sage: _limit_latex_ = latex_module._limit_latex_
+        sage: var('x,a')
+        (x, a)
+        sage: psi(x) = function('psi',x)
+        sage: _limit_latex_(limit(psi(x),x=a))
+        '\\lim_{x \\to a}\\, \\psi(x)'
+    
+    AUTHORS:
+
+    - Golam Mortuza Hossain (2009-04-05)
+    """
+    # We process only if there are precisely three arguments
+    if len(self._args) == 3:
+        # Read f,x,a from arguments
+        f = self._args[0]
+        x = self._args[1]
+        a = self._args[2]
+        return "\\lim_{%s \\to %s}\\, %s"%(latex(x), latex(a), latex(f))
+    # Return default typesetting
+    return _symbolic_function_default_latex_(self)
+
+def _conjugate_latex_(self):
+    r"""
+    Return LaTeX expression for conjugate of a symbolic function.
+    
+    EXAMPLES::
+    
+        sage: import sage.misc.latex as latex_module
+        sage: _conjugate_latex_ = latex_module._conjugate_latex_
+        sage: var('x')
+        x
+        sage: psi(x) = function('psi',x)
+        sage: _conjugate_latex_(psi(x).conjugate())
+        '{\\psi}^*(x)'
+    
+    AUTHORS:
+
+    - Golam Mortuza Hossain (2009-04-05)
+    """
+    # We process only if there is only one argument
+    if len(self._args) == 1:
+        chld = self._args[0]
+        name = latex_function_name(chld._f._name)
+        if name is not False:
+ 	        # conjugate(psi(x)) => psi^*(x)
+            return "{%s}^*%s"%(name, _args_latex_(chld))
+    # Return default typesetting
+    return _symbolic_function_default_latex_(self)
+
+user_defined_latex_dict = {}
+
+def latex_function_name(x):
+    r"""
+    Return common function names such as alpha, beta1, psi_00, R_mn, 
+    etc. as latex symbols, else return False.
+    
+    EXAMPLES::
+    
+        sage: import sage.misc.latex as latex_module
+        sage: latex_function_name = latex_module.latex_function_name
+        sage: latex_function_name('psi')
+        '\\psi'
+        sage: latex_function_name('psi0')
+        '\\psi_{0}'
+        sage: latex_function_name('f1')
+        'f_{1}'
+        sage: latex_function_name('psi_mu')
+        '\\psi_{\\mu}'
+        sage: latex_function_name('psi_11')
+        '\\psi_{11}'
+        sage: latex_function_name('R_ab')
+        'R_{ab}'
+        sage: latex_function_name('R_nu')
+        'R_{\\nu}'
+        sage: latex_function_name('myfunc')
+        False
+        sage: latex_function_name('psi_')
+        False
+        sage: latex_function_name('abc_xyz_psi')
+        False
+        sage: latex_function_name('abc_beta')
+        False
+    
+    NOTES:
+
+    This function is based largely on latex_variable_name function.
+    
+    AUTHORS:
+
+    - Golam Mortuza Hossain (2009-04-05)
+    """
+    # If user has defined latex string then use it first
+    if x in user_defined_latex_dict:
+        return user_defined_latex_dict[x]
+    # For known names return them after preprending with "\\"
+    if x in common_varnames:
+        return "\\" + x
+    # Look for underscrore. If found then use its postion to 
+    # find the suffix
+    underscore = x.find("_")
+    if underscore == -1:
+        import re
+        # * The "\d|[.,]" means "decimal digit" or period or comma
+        # * The "+" means "1 or more"
+        # * The "$" means "at the end of the line"
+        m = re.search('(\d|[.,])+$',x)
+        if m is None:
+            prefix = x
+            suffix = None
+        else:
+            prefix = x[:m.start()]
+            suffix = x[m.start():]
+    else:
+        prefix = x[:underscore]
+        suffix = x[underscore+1:]
+        if len(suffix)== 0:
+            return False
+    # If suffix contains underscores then don't process
+    if suffix and suffix.find("_") != -1:
+        return False
+    # If prefix is not a common name or a more-than-one letters word
+    # then don't process
+    if prefix not in common_varnames and len(prefix) != 1:
+        return False
+    # Check if prefix or suffix is a common name    
+    if prefix in common_varnames:
+        prefix = "\\" + prefix
+    if suffix and len(suffix) > 0:
+        if suffix in common_varnames:
+            suffix = "\\" + suffix
+        return '%s_{%s}'%(prefix, suffix)
+    else:
+        return '%s'%(prefix)
+
 def latex_varify(a):
     if a in common_varnames:
         return "\\" + a

Reply via email to