Representing Brian objects
__repr__
and __str__
Every class should specify or inherit useful __repr__
and __str__
methods. The __repr__
method should give the “official” representation of the object; if possible, this should be a valid
Python expression, ideally allowing for eval(repr(x)) == x
. The __str__
method on the other
hand, gives an “informal” representation of the object. This can be anything that is helpful but
does not have to be Python code. For example:
>>> import numpy as np
>>> ar = np.array([1, 2, 3]) * mV
>>> print(ar) # uses __str__
[ 1. 2. 3.] mV
>>> ar # uses __repr__
array([ 1., 2., 3.]) * mvolt
If the representation returned by __repr__
is not Python code, it should be enclosed in
<...>
, e.g. a Synapses
representation might be <Synapses object with 64 synapses>
.
If you don’t want to make the distinction between __repr__
and __str__
, simply define only
a __repr__
function, it will be used instead of __str__
automatically (no need to write
__str__ = __repr__
). Finally, if you include the class name in the representation (which you
should in most cases), use self.__class__.__name__
instead of spelling out the name explicitly
– this way it will automatically work correctly for subclasses. It will also prevent you from
forgetting to update the class name in the representation if you decide to rename the class.
LaTeX representations with sympy
Brian objects dealing with mathematical expressions and equations often internally use sympy.
Sympy’s latex
function does a nice job of converting expressions into
LaTeX code, using fractions, root symbols, etc. as well as converting greek variable names into
corresponding symbols and handling sub- and superscripts. For the conversion of variable names
to work, they should use an underscore for subscripts and two underscores for superscripts:
>>> from sympy import latex, Symbol
>>> tau_1__e = Symbol('tau_1__e')
>>> print(latex(tau_1__e))
\tau^{e}_{1}
Sympy’s printer supports formatting arbitrary objects, all they have to do is to implement a
_latex
method (no trailing underscore). For most Brian objects, this is unnecessary as they will
never be formatted with sympy’s LaTeX printer. For some core objects, in particular the units,
is is useful, however, as it can be reused in LaTeX representations for ipython (see below).
Note that the _latex
method should not return $
or \begin{equation}
(sympy’s method
includes a mode
argument that wraps the output automatically).
Representations for ipython
“Old” ipython console
In particular for representations involing arrays or lists, it can be useful to break up the
representation into chunks, or indent parts of the representation. This is supported by the
ipython console’s “pretty printer”. To make this work for a class, add a
_repr_pretty_(self, p, cycle)
(note the single underscores) method. You can find more
information in the ipython documentation .
“New” ipython console (qtconsole and notebook)
The new ipython consoles, the qtconsole and the ipython notebook support a much richer set of
representations for objects. As Brian deals a lot with mathematical objects, in particular the
LaTeX and to a lesser extent the HTML formatting capabilities of the ipython notebook are
interesting. To support LaTeX representation, implement a _repr_latex_
method returning the
LaTeX code (including $
, \begin{equation}
or similar). If the object already has a
_latex
method (see LaTeX representations with sympy above), this can be as simple as:
def _repr_latex_(self):
return sympy.latex(self, mode='inline') # wraps the expression in $ .. $
The LaTeX rendering only supports a single mathematical block. For complex objects, e.g.
NeuronGroup
it might be useful to have a richer representation. This can be achieved by returning
HTML code from _repr_html_
– this HTML code is processed by MathJax so it can include literal
LaTeX code that will be transformed before it is rendered as HTML. An object containing two
equations could therefore be represented with a method like this:
def _repr_html_(self):
return '''
<h3> Equation 1 </h3>
{eq_1}
<h3> Equation 2 </h3>
{eq_2}'''.format(eq_1=sympy.latex(self.eq_1, mode='equation'),
eq_2=sympy.latex(self.eq_2, mode='equation'))