123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- from sympy.core.function import Derivative
- from sympy.core.function import UndefinedFunction, AppliedUndef
- from sympy.core.symbol import Symbol
- from sympy.interactive.printing import init_printing
- from sympy.printing.latex import LatexPrinter
- from sympy.printing.pretty.pretty import PrettyPrinter
- from sympy.printing.pretty.pretty_symbology import center_accent
- from sympy.printing.str import StrPrinter
- from sympy.printing.precedence import PRECEDENCE
- __all__ = ['vprint', 'vsstrrepr', 'vsprint', 'vpprint', 'vlatex',
- 'init_vprinting']
- class VectorStrPrinter(StrPrinter):
- """String Printer for vector expressions. """
- def _print_Derivative(self, e):
- from sympy.physics.vector.functions import dynamicsymbols
- t = dynamicsymbols._t
- if (bool(sum([i == t for i in e.variables])) &
- isinstance(type(e.args[0]), UndefinedFunction)):
- ol = str(e.args[0].func)
- for i, v in enumerate(e.variables):
- ol += dynamicsymbols._str
- return ol
- else:
- return StrPrinter().doprint(e)
- def _print_Function(self, e):
- from sympy.physics.vector.functions import dynamicsymbols
- t = dynamicsymbols._t
- if isinstance(type(e), UndefinedFunction):
- return StrPrinter().doprint(e).replace("(%s)" % t, '')
- return e.func.__name__ + "(%s)" % self.stringify(e.args, ", ")
- class VectorStrReprPrinter(VectorStrPrinter):
- """String repr printer for vector expressions."""
- def _print_str(self, s):
- return repr(s)
- class VectorLatexPrinter(LatexPrinter):
- """Latex Printer for vector expressions. """
- def _print_Function(self, expr, exp=None):
- from sympy.physics.vector.functions import dynamicsymbols
- func = expr.func.__name__
- t = dynamicsymbols._t
- if (hasattr(self, '_print_' + func) and not
- isinstance(type(expr), UndefinedFunction)):
- return getattr(self, '_print_' + func)(expr, exp)
- elif isinstance(type(expr), UndefinedFunction) and (expr.args == (t,)):
- # treat this function like a symbol
- expr = Symbol(func)
- if exp is not None:
- # copied from LatexPrinter._helper_print_standard_power, which
- # we can't call because we only have exp as a string.
- base = self.parenthesize(expr, PRECEDENCE['Pow'])
- base = self.parenthesize_super(base)
- return r"%s^{%s}" % (base, exp)
- else:
- return super()._print(expr)
- else:
- return super()._print_Function(expr, exp)
- def _print_Derivative(self, der_expr):
- from sympy.physics.vector.functions import dynamicsymbols
- # make sure it is in the right form
- der_expr = der_expr.doit()
- if not isinstance(der_expr, Derivative):
- return r"\left(%s\right)" % self.doprint(der_expr)
- # check if expr is a dynamicsymbol
- t = dynamicsymbols._t
- expr = der_expr.expr
- red = expr.atoms(AppliedUndef)
- syms = der_expr.variables
- test1 = not all(True for i in red if i.free_symbols == {t})
- test2 = not all(t == i for i in syms)
- if test1 or test2:
- return super()._print_Derivative(der_expr)
- # done checking
- dots = len(syms)
- base = self._print_Function(expr)
- base_split = base.split('_', 1)
- base = base_split[0]
- if dots == 1:
- base = r"\dot{%s}" % base
- elif dots == 2:
- base = r"\ddot{%s}" % base
- elif dots == 3:
- base = r"\dddot{%s}" % base
- elif dots == 4:
- base = r"\ddddot{%s}" % base
- else: # Fallback to standard printing
- return super()._print_Derivative(der_expr)
- if len(base_split) != 1:
- base += '_' + base_split[1]
- return base
- class VectorPrettyPrinter(PrettyPrinter):
- """Pretty Printer for vectorialexpressions. """
- def _print_Derivative(self, deriv):
- from sympy.physics.vector.functions import dynamicsymbols
- # XXX use U('PARTIAL DIFFERENTIAL') here ?
- t = dynamicsymbols._t
- dot_i = 0
- syms = list(reversed(deriv.variables))
- while len(syms) > 0:
- if syms[-1] == t:
- syms.pop()
- dot_i += 1
- else:
- return super()._print_Derivative(deriv)
- if not (isinstance(type(deriv.expr), UndefinedFunction) and
- (deriv.expr.args == (t,))):
- return super()._print_Derivative(deriv)
- else:
- pform = self._print_Function(deriv.expr)
- # the following condition would happen with some sort of non-standard
- # dynamic symbol I guess, so we'll just print the SymPy way
- if len(pform.picture) > 1:
- return super()._print_Derivative(deriv)
- # There are only special symbols up to fourth-order derivatives
- if dot_i >= 5:
- return super()._print_Derivative(deriv)
- # Deal with special symbols
- dots = {0: "",
- 1: "\N{COMBINING DOT ABOVE}",
- 2: "\N{COMBINING DIAERESIS}",
- 3: "\N{COMBINING THREE DOTS ABOVE}",
- 4: "\N{COMBINING FOUR DOTS ABOVE}"}
- d = pform.__dict__
- # if unicode is false then calculate number of apostrophes needed and
- # add to output
- if not self._use_unicode:
- apostrophes = ""
- for i in range(0, dot_i):
- apostrophes += "'"
- d['picture'][0] += apostrophes + "(t)"
- else:
- d['picture'] = [center_accent(d['picture'][0], dots[dot_i])]
- return pform
- def _print_Function(self, e):
- from sympy.physics.vector.functions import dynamicsymbols
- t = dynamicsymbols._t
- # XXX works only for applied functions
- func = e.func
- args = e.args
- func_name = func.__name__
- pform = self._print_Symbol(Symbol(func_name))
- # If this function is an Undefined function of t, it is probably a
- # dynamic symbol, so we'll skip the (t). The rest of the code is
- # identical to the normal PrettyPrinter code
- if not (isinstance(func, UndefinedFunction) and (args == (t,))):
- return super()._print_Function(e)
- return pform
- def vprint(expr, **settings):
- r"""Function for printing of expressions generated in the
- sympy.physics vector package.
- Extends SymPy's StrPrinter, takes the same setting accepted by SymPy's
- :func:`~.sstr`, and is equivalent to ``print(sstr(foo))``.
- Parameters
- ==========
- expr : valid SymPy object
- SymPy expression to print.
- settings : args
- Same as the settings accepted by SymPy's sstr().
- Examples
- ========
- >>> from sympy.physics.vector import vprint, dynamicsymbols
- >>> u1 = dynamicsymbols('u1')
- >>> print(u1)
- u1(t)
- >>> vprint(u1)
- u1
- """
- outstr = vsprint(expr, **settings)
- import builtins
- if (outstr != 'None'):
- builtins._ = outstr
- print(outstr)
- def vsstrrepr(expr, **settings):
- """Function for displaying expression representation's with vector
- printing enabled.
- Parameters
- ==========
- expr : valid SymPy object
- SymPy expression to print.
- settings : args
- Same as the settings accepted by SymPy's sstrrepr().
- """
- p = VectorStrReprPrinter(settings)
- return p.doprint(expr)
- def vsprint(expr, **settings):
- r"""Function for displaying expressions generated in the
- sympy.physics vector package.
- Returns the output of vprint() as a string.
- Parameters
- ==========
- expr : valid SymPy object
- SymPy expression to print
- settings : args
- Same as the settings accepted by SymPy's sstr().
- Examples
- ========
- >>> from sympy.physics.vector import vsprint, dynamicsymbols
- >>> u1, u2 = dynamicsymbols('u1 u2')
- >>> u2d = dynamicsymbols('u2', level=1)
- >>> print("%s = %s" % (u1, u2 + u2d))
- u1(t) = u2(t) + Derivative(u2(t), t)
- >>> print("%s = %s" % (vsprint(u1), vsprint(u2 + u2d)))
- u1 = u2 + u2'
- """
- string_printer = VectorStrPrinter(settings)
- return string_printer.doprint(expr)
- def vpprint(expr, **settings):
- r"""Function for pretty printing of expressions generated in the
- sympy.physics vector package.
- Mainly used for expressions not inside a vector; the output of running
- scripts and generating equations of motion. Takes the same options as
- SymPy's :func:`~.pretty_print`; see that function for more information.
- Parameters
- ==========
- expr : valid SymPy object
- SymPy expression to pretty print
- settings : args
- Same as those accepted by SymPy's pretty_print.
- """
- pp = VectorPrettyPrinter(settings)
- # Note that this is copied from sympy.printing.pretty.pretty_print:
- # XXX: this is an ugly hack, but at least it works
- use_unicode = pp._settings['use_unicode']
- from sympy.printing.pretty.pretty_symbology import pretty_use_unicode
- uflag = pretty_use_unicode(use_unicode)
- try:
- return pp.doprint(expr)
- finally:
- pretty_use_unicode(uflag)
- def vlatex(expr, **settings):
- r"""Function for printing latex representation of sympy.physics.vector
- objects.
- For latex representation of Vectors, Dyadics, and dynamicsymbols. Takes the
- same options as SymPy's :func:`~.latex`; see that function for more
- information;
- Parameters
- ==========
- expr : valid SymPy object
- SymPy expression to represent in LaTeX form
- settings : args
- Same as latex()
- Examples
- ========
- >>> from sympy.physics.vector import vlatex, ReferenceFrame, dynamicsymbols
- >>> N = ReferenceFrame('N')
- >>> q1, q2 = dynamicsymbols('q1 q2')
- >>> q1d, q2d = dynamicsymbols('q1 q2', 1)
- >>> q1dd, q2dd = dynamicsymbols('q1 q2', 2)
- >>> vlatex(N.x + N.y)
- '\\mathbf{\\hat{n}_x} + \\mathbf{\\hat{n}_y}'
- >>> vlatex(q1 + q2)
- 'q_{1} + q_{2}'
- >>> vlatex(q1d)
- '\\dot{q}_{1}'
- >>> vlatex(q1 * q2d)
- 'q_{1} \\dot{q}_{2}'
- >>> vlatex(q1dd * q1 / q1d)
- '\\frac{q_{1} \\ddot{q}_{1}}{\\dot{q}_{1}}'
- """
- latex_printer = VectorLatexPrinter(settings)
- return latex_printer.doprint(expr)
- def init_vprinting(**kwargs):
- """Initializes time derivative printing for all SymPy objects, i.e. any
- functions of time will be displayed in a more compact notation. The main
- benefit of this is for printing of time derivatives; instead of
- displaying as ``Derivative(f(t),t)``, it will display ``f'``. This is
- only actually needed for when derivatives are present and are not in a
- physics.vector.Vector or physics.vector.Dyadic object. This function is a
- light wrapper to :func:`~.init_printing`. Any keyword
- arguments for it are valid here.
- {0}
- Examples
- ========
- >>> from sympy import Function, symbols
- >>> t, x = symbols('t, x')
- >>> omega = Function('omega')
- >>> omega(x).diff()
- Derivative(omega(x), x)
- >>> omega(t).diff()
- Derivative(omega(t), t)
- Now use the string printer:
- >>> from sympy.physics.vector import init_vprinting
- >>> init_vprinting(pretty_print=False)
- >>> omega(x).diff()
- Derivative(omega(x), x)
- >>> omega(t).diff()
- omega'
- """
- kwargs['str_printer'] = vsstrrepr
- kwargs['pretty_printer'] = vpprint
- kwargs['latex_printer'] = vlatex
- init_printing(**kwargs)
- params = init_printing.__doc__.split('Examples\n ========')[0] # type: ignore
- init_vprinting.__doc__ = init_vprinting.__doc__.format(params) # type: ignore
|