tweaking the output of sympy.latex

159 views
Skip to first unread message

Ryan Krauss

unread,
Jun 1, 2009, 2:10:53 PM6/1/09
to sy...@googlegroups.com
I am trying to use sympy in some code that I have that allows me to put Python code blocks in a Latex document and replace the block with pretty output.  For my code to work ideally, I need to tweak the output of sympy.latex for a matrix.  I have

In [19]: type(Uk)
Out[19]: <class 'sympy.matrices.matrices.Matrix'>

In [20]: Uk
Out[20]:
[1, 1/k, 0]
[0,   1, 0]
[0,   0, 1]

In [21]: type(Uk)
Out[21]: <class 'sympy.matrices.matrices.Matrix'>

and I can get either
In [22]: sympy.latex(Uk)
Out[22]: '$\\left(\\begin{smallmatrix}1 & \\frac{1}{k} & 0\\\\0 & 1 & 0\\\\0 & 0 & 1\\end{smallmatrix}\\right)$'

In [23]: sympy.latex(Uk, inline=False)
Out[23]: '\\begin{equation*}\\begin{pmatrix}1 & \\frac{1}{k} & 0\\\\0 & 1 & 0\\\\0 & 0 & 1\\end{pmatrix}\\end{equation*}'


what I really want is

\\begin{bmatrix}1 & \\frac{1}{k} & 0\\\\0 & 1 & 0\\\\0 & 0 & 1\\end{bmatrix}

Can I easily modify the output of sympy.latex with some settings somewhere?  It doesn't look like it takes keyword arguements.

Thanks,

Ryan

Ryan Krauss

unread,
Jun 1, 2009, 2:18:00 PM6/1/09
to sy...@googlegroups.com
So, unless I am looking in the wrong place, it appears to be hard-coded:

    def _print_Matrix(self, expr):
        lines = []

        for line in range(expr.lines): # horrible, should be 'rows'
            lines.append(" & ".join([ self._print(i) for i in expr[line,:] ]))

        if self._inline:
            tex = r"\left(\begin{smallmatrix}%s\end{smallmatrix}\right)"
        else:
            tex = r"\begin{pmatrix}%s\end{pmatrix}"

        return tex % r"\\".join(lines)

(this if from line 407 of printing/latex.py).

What is the best solution to my problem?  I can hack my own code to replace the
\left(\begin{smallmatrix} --> \begin{bmatrix}
and
\end{smallmatrix}\right  --> \end{bmatrix}

and if I am the only one who wants this feature, no problem.  Are other people interested, and if so, how should this be correctly handled if I were going to write a patch?

Ryan

Tim Lahey

unread,
Jun 1, 2009, 2:21:11 PM6/1/09
to sy...@googlegroups.com
On Mon, Jun 1, 2009 at 2:18 PM, Ryan Krauss <ryan...@gmail.com> wrote:
>
> What is the best solution to my problem?  I can hack my own code to replace
> the
> \left(\begin{smallmatrix} --> \begin{bmatrix}
> and
> \end{smallmatrix}\right  --> \end{bmatrix}
>
> and if I am the only one who wants this feature, no problem.  Are other
> people interested, and if so, how should this be correctly handled if I were
> going to write a patch?
>

I use bmatrix all the time for my matrices and I never use pmatrix, so an option
would be a good thing.

I see two possibilities. First, have a setting somewhere to choose the matrix
display type, or make it a parameter to be passed, probably with some default.

Cheers,

Tim.

---
Tim Lahey
PhD Candidate, Systems Design Engineering
University of Waterloo
http://www.linkedin.com/in/timlahey

Ryan Krauss

unread,
Jun 1, 2009, 2:31:30 PM6/1/09
to sy...@googlegroups.com
Either of those could work.  A keyword argument makes sense.

As I look at the code, it seems like trying to handle too many options is going to get messy fast.  Any thoughts on how to proceed?  A full-fledged rc file might be overkill and confusing to the novice user.

Ryan

Ryan Krauss

unread,
Jun 1, 2009, 2:46:27 PM6/1/09
to sy...@googlegroups.com
So, I have something that I think is working.  No idea if people who understand more of sympy's design than I do will think this is a good idea or not.

class LatexPrinter(Printer):
    printmethod = "_latex_"

    def __init__(self, inline=True, matstr='bmatrix', matdelim=None):
        Printer.__init__(self)
        self._inline = inline
        self._matstr = matstr
        self._matdelim = matdelim
        self._delim_dict = {'(':')','[':']'}

    def doprint(self, expr):
        tex = Printer.doprint(self, expr)

        if self._inline is None:
            return "%s" % tex
        elif self._inline:
            return r"$%s$" % tex
        else:
            return r"\begin{equation*}%s\end{equation*}" % tex



    def _print_Matrix(self, expr):
        lines = []

        for line in range(expr.lines): # horrible, should be 'rows'
            lines.append(" & ".join([ self._print(i) for i in expr[line,:] ]))

        out_str = r'\begin{%MATSTR%}%s\end{%MATSTR%}'
        out_str = out_str.replace('%MATSTR%', self._matstr)
        if self._matdelim:
            out_str = r'\left' + self._matdelim + ' ' + out_str + ' '+ \
                      r'\right' + self._delim_dict[self._matdelim]
        return out_str % r"\\".join(lines)


def latex(expr, inline=True, matstr=None, matdelim=None):
    if inline:
        if matstr is None:
            matstr = 'smallmatrix'
        if matdelim is None:
            matdelim = '('
    else:
        if matstr is None:
            matstr = 'bmatrix'

    return LatexPrinter(inline, matstr=matstr, matdelim=matdelim).doprint(expr)



Here are the results of my preliminary tests:

In [4]: sympy.latex(Uk)
Out[4]: '$\\left( \\begin{smallmatrix}1 & \\frac{1}{k} & 0\\\\0 & 1 & 0\\\\0 & 0 & 1\\end{smallmatrix} \\right)$'

In [5]: sympy.latex(Uk, inline=False)
Out[5]: '\\begin{equation*}\\begin{bmatrix}1 & \\frac{1}{k} & 0\\\\0 & 1 & 0\\\\0 & 0 & 1\\end{bmatrix}\\end{equation*}'

In [6]: sympy.latex(Uk, inline=None)
Out[6]: '\\begin{bmatrix}1 & \\frac{1}{k} & 0\\\\0 & 1 & 0\\\\0 & 0 & 1\\end{bmatrix}'

In [7]: sympy.latex(Uk, inline=None, matstr='pmatrix')
Out[7]: '\\begin{pmatrix}1 & \\frac{1}{k} & 0\\\\0 & 1 & 0\\\\0 & 0 & 1\\end{pmatrix}'

In [8]: sympy.latex(Uk, inline=True, matstr='pmatrix', matdelim='[')
Out[8]: '$\\left[ \\begin{pmatrix}1 & \\frac{1}{k} & 0\\\\0 & 1 & 0\\\\0 & 0 & 1\\end{pmatrix} \\right]$'

If this is unnecessarily complicated, I could live with just the option to change matstr and have the inline=None option that doesn't wrap the output in either $..$ or \begin{equation*} ... \end{equation*}

Any thoughts?

Ryan

Ondrej Certik

unread,
Jun 1, 2009, 3:51:05 PM6/1/09
to sy...@googlegroups.com
Hi Ryan!


On Mon, Jun 1, 2009 at 12:46 PM, Ryan Krauss <ryan...@gmail.com> wrote:
> So, I have something that I think is working.  No idea if people who
> understand more of sympy's design than I do will think this is a good idea
> or not.

looks good. Could you please send it as a patch to sympy? We'll include it.

Thanks,
Ondrej

Ryan Krauss

unread,
Jun 1, 2009, 4:14:32 PM6/1/09
to sy...@googlegroups.com
I will work on that shortly.

Ryan Krauss

unread,
Jun 3, 2009, 9:41:29 AM6/3/09
to sy...@googlegroups.com
So, I was getting ready to make my first patch (I think I have two to submit - one on tweaking the output of sympy.latex to allow different matrix choices like bmatrix and one on the mainvar idea), when I noticed that I am not running the latest version.  This raises two issues for me.

I am running whatever version came with Ubnuntu 9.04 Jaunty Jackolope (apprently it is 0.6.3).  So, my first question was going to be how do I run the latest git version, but it seems like that is just an issue of editting my PYTHONPATH.  Since it seems like the git checkout created a full sympy dir, I just need to make sure that dir is listed in my PYTHONPATH before the one that contains 0.6.3 and I will be working with the latest version.  How do you guys handle this issue?  I guess I could also just install the version from git, but then I can't go back to 0.6.3 if I break something.

So my second issue, which is the main one, is that there seems to be some work on _settings for printers.  It seems like my approach for handling the changing of the latex matrix type and allowing inline to be None should be handled by profiles and _settings right?  Perhaps even mainvar should be a _setting.

Ryan

Ryan Krauss

unread,
Jun 3, 2009, 10:44:20 AM6/3/09
to sy...@googlegroups.com
So, I think I successfully created my first patch to handle the stuff of this thread (changing matrix type in latex and allowing inline=None).  I think I joined the patches group and sent the email from git.  Can anyone confirm receiving it?

Thanks,

Ryan

Ryan Krauss

unread,
Jun 3, 2009, 10:55:08 AM6/3/09
to sy...@googlegroups.com
So, I re-sent the email from the email address that is actually a member of sympy-patches, but I still see no proof of it going through (I didn't get the email).  Here is the output of git send-email

ryan@ryan-duo-laptop:~/git/sympy$ git send-email 000*
0001-sympy.latex-allowed-specifying-the-latex-matrix-typ.patch
Who should the emails appear to be from? [Ryan Krauss <ryan...@gmail.com>]
Emails will be sent from: Ryan Krauss <ryan...@gmail.com>
Message-ID to be used as In-Reply-To for the first email?
(mbox) Adding cc: Ryan Krauss <ryanw...@gmail.com> from line 'From: Ryan Krauss <ryanw...@gmail.com>'
OK. Log says:
Sendmail: /usr/sbin/sendmail -i sympy-...@googlegroups.com ryanw...@gmail.com
From: Ryan Krauss <ryan...@gmail.com>
To: sympy-...@googlegroups.com
Cc: Ryan Krauss <ryanw...@gmail.com>
Subject: [PATCH 1/1] sympy.latex: allowed specifying the latex matrix type (bmatrix, pmatrix, ...) and allowed inline=None to mean no wrapping of the latex output (no $...$ and no equation environmenr).  This is all handled through the profile.
Date: Wed,  3 Jun 2009 09:52:12 -0500
Message-Id: <1244040732-17869-1-gi...@gmail.com>
X-Mailer: git-send-email 1.6.0.4

Result: OK

Does that look right?

Ryan

Aaron S. Meurer

unread,
Jun 3, 2009, 12:21:11 PM6/3/09
to sy...@googlegroups.com
You don't have to install the git version.  Just cd into the git sympy directory.  Any time you import sympy, it will import the git version.  At least, that works for me.  

Also, you should probably install 0.6.4 on your system to fall back into like you said.  There were many bug fixes included in 0.6.4.  

As for the email, I too am having problems sending emails from git.  It may have something to do with gmail IMAP from what I've heard, but I haven't seen the patch (you can check for yourself on the webpage: http://groups.google.com/group/sympy-patches).  I have had to send all of my patches manually.  

Aaron Meurer

Ondrej Certik

unread,
Jun 3, 2009, 2:33:39 PM6/3/09
to sy...@googlegroups.com
On Wed, Jun 3, 2009 at 10:21 AM, Aaron S. Meurer <asme...@gmail.com> wrote:
> You don't have to install the git version.  Just cd into the git sympy
> directory.  Any time you import sympy, it will import the git version.  At
> least, that works for me.
> Also, you should probably install 0.6.4 on your system to fall back into
> like you said.  There were many bug fixes included in 0.6.4.
>
> As for the email, I too am having problems sending emails from git.  It may
> have something to do with gmail IMAP from what I've heard, but I haven't
> seen the patch (you can check for yourself on the
> webpage: http://groups.google.com/group/sympy-patches).  I have had to send
> all of my patches manually.
> Aaron Meurer

If it's just couple patches, do "git format-patch -1" (or -n for n
patches) and attach it to some issue manually. If it's more patches,
publish your branch on github (or anywhere else) and we'll pull it.

github actually allows to review and comment the branch online, which
is a nice feature.

Ondrej

Ryan Krauss

unread,
Jun 3, 2009, 3:24:39 PM6/3/09
to sy...@googlegroups.com
I am just creating two patches for now and am about to email them (one I already sent to sympy-patches).

But I also just opened a github account.  Should I fork from
http://github.com/certik/sympy/tree/master
and is that the same as the one I just checked out a few hour ago using
git clone git://git.sympy.org/sympy.git

and how can I make my new github account play nicely with the fact that I already have these two changes after my clone?

Thanks,

Ryan

Ondrej Certik

unread,
Jun 3, 2009, 4:20:10 PM6/3/09
to sy...@googlegroups.com
On Wed, Jun 3, 2009 at 1:24 PM, Ryan Krauss <ryan...@gmail.com> wrote:
> I am just creating two patches for now and am about to email them (one I
> already sent to sympy-patches).
>
> But I also just opened a github account.  Should I fork from
> http://github.com/certik/sympy/tree/master
> and is that the same as the one I just checked out a few hour ago using
>
> git clone git://git.sympy.org/sympy.git
>
> and how can I make my new github account play nicely with the fact that I
> already have these two changes after my clone?

You can fork it from me, or you can just push everything at once, it
doesn't matter.

As to handling patches with git, you have two options. Either just
work in the master branch, then you just push everything to github,
but then when we merge it, or if some more changes are needed, or we
merge something else first into our main repository, your master
branch will then be very different to our official repository, thus
making it harder for you to work with.

Thus I recommend to work in branches, e.g. create a new branch:

git co -b ryan

work in there, commit some stuff, push to gihtub

git push github ryan

(assuming the "github" remote points to github, see "git remote -v"),
and keep you master branch always identical with our main sympy
repository.

That way you can easily work on your stuff, while you can also update
from our main repository and you can also easily rebase etc.

Ondrej

Reply all
Reply to author
Forward
0 new messages