This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Python bindings for Eigen?

Tags: None
(comma "," separated)
kbr
Registered Member
Posts
6
Karma
0

Python bindings for Eigen?

Thu Feb 05, 2015 12:05 pm
Currently, I am looking for Python bindings for Eigen, in particular with support for the geometry module <http://eigen.tuxfamily.org/dox/group__Geometry__Module.html>.

To my knowledge, the existing bindings are
  • minieigen: python bindings for the vector classes Vector{2,3,6,X}, Vector{2,3,6,X}i, the quadratic matrices Matrix{3,6,X}, AlignedBox{2,3}, and Quaternion, using the Boost.Python library.
  • pyeigen: python bindings for Vector{2,3,4}, and quadratic matrices Matrix{2,3,4}, but unfortunately the project has been discontinued since 2013-04-08 (see <http://sourceforge.net/projects/pyeigen>).
  • SpPy (former sparray): python bindings for sparse vectors and matrices with support for randomized SVD, BiCGstab and I/O. The project is using Cython.
  • In the BTK project (see <https://code.google.com/p/b-tk>), there is a fragment for SWIG to transform an Eigen matrix to a NumPy array.
  • See also <https://forum.kde.org/viewtopic.php?f=74&t=87048> and <http://eigen.tuxfamily.org/index.php?title=PythonInteropBoost> for a similar solution.
  • Some experiences with SWIG and Lua are discussed in <https://forum.kde.org/viewtopic.php?f=74&t=66122&>.
Are there any more approaches?

Unfortunately, none of the above supports the geometry module, such that we need to extend existing or generate new Python bindings for Eigen. Which of the toolboxes (e.g. Boost.Python, SWIG, Cython etc.) do you recommend?
eudoxos
Registered Member
Posts
36
Karma
0

Re: Python bindings for Eigen?

Wed Feb 11, 2015 11:59 am
Hi,

I am the author/maintainer of minieigen. The focus of minieigen is easy interfacing with c++ codes which already use Eigen and boost::python, and do most number-crunching in c++. That way, I can just expose function taking Eigen objects and feed those in from Python, or return Eigen objects from c++ to Python, transparently. There is no particular stress on performance (though I've never had performance problem with minieigen), it is more about comfort and using the same (or as similar as possible) syntax. Minieigen can be used stand-alone as well, no problem. There are packages in Debian/Ubuntu (credit of Anton Gladky of Debian Science).

If you make modifications, you can branch from https://github.com/eudoxos/minieigen and I will incorporate your changes.

Your change of basic-test.py into a unittest if an excellent idea; there is also the python's unittest framework (which I like and use, in other projects).

If you look at the source, you will perhaps see that most files are simple (small) and then there is the big visitors.hpp (https://github.com/eudoxos/minieigen/bl ... sitors.hpp) file, which contains all the nuts and bolts. The reason for the split is that boost::python tends to take huge amounts of RAM when instantiating templates, so those instantiations were split to separate files.

I hope the visitors.hpp file is readable, basically it creates templates which enable or disable some functionality for the wrapper depending on argument types - so you have some functions for float vectors, which are not meaningful for float vectors and so on. Becase c++ does not have something like "static if", the variants have to be put apart and are distinguished via a dummy template parameter (like
Code: Select all
typename boost::enable_if<boost::is_integral<Scalar> >::type
) and such, it is not nice, but works pretty well -- e.g. extending the wrapper to cover complex numbers was actually almost trivial.

Boost::python can define operators using e.g. py::def(self / self) (for same-type division) which is not possible to use with Eigen, since many operators actually return an expression template, not the result type; and those need to be wrapped. That's why methods like __mul__ are defined by-hand, returning just a*b and such. Some methods also return expression template, so they are also wrapped by hand then. Note also that data are mostly passed by value, so doing something like matrix.row(0)[1]=... will not do what you expect -- it will change the value in the temporary copy, which is immediately discarded.

I think adding the other transform classes could be fairly simple once you get the idea, and then add converters so that you can pass Transform where Quaternion is expected or vice versa.

If you decide to go with minieigen, feel free to contact me as needed.

Cheers, Václav


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], Yahoo [Bot]