Python bindings for the xtensor C++ multi-dimensional array library.
-
xtensor
is a C++ library for multi-dimensional arrays enabling numpy-style broadcasting and lazy computing. -
xtensor-python
enables inplace use of numpy arrays in C++ with all the benefits fromxtensor
- C++ universal function and broadcasting
- STL - compliant APIs.
- A broad coverage of numpy APIs (see the numpy to xtensor cheat sheet).
The Python bindings for xtensor
are based on the pybind11 C++ library, which enables seemless interoperability between C++ and Python.
xtensor-python
is a header-only library. We provide a package for the conda package manager.
conda install -c conda-forge xtensor-python
To get started with using xtensor-python
, check out the full documentation
http://xtensor-python.readthedocs.io/
xtensor-python offers two container types wrapping numpy arrays inplace to provide an xtensor semantics
pytensor
pyarray
.
Both containers enable the numpy-style APIs of xtensor (see the numpy to xtensor cheat sheet).
-
On the one hand,
pyarray
has a dynamic number of dimensions. Just like numpy arrays, it can be reshaped with a shape of a different length (and the new shape is reflected on the python side). -
On the other hand
pytensor
has a compile time number of dimensions, specified with a template parameter. Shapes ofpytensor
instances are stack allocated, makingpytensor
a significantly faster expression thanpyarray
.
C++ code
#include <numeric> // Standard library import for std::accumulate
#include "pybind11/pybind11.h" // Pybind11 import to define Python bindings
#include "xtensor/xmath.hpp" // xtensor import for the C++ universal functions
#define FORCE_IMPORT_ARRAY
#include "xtensor-python/pyarray.hpp" // Numpy bindings
double sum_of_sines(xt::pyarray<double>& m)
{
auto sines = xt::sin(m); // sines does not actually hold values.
return std::accumulate(sines.begin(), sines.end(), 0.0);
}
PYBIND11_MODULE(xtensor_python_test, m)
{
xt::import_numpy();
m.doc() = "Test module for xtensor python bindings";
m.def("sum_of_sines", sum_of_sines, "Sum the sines of the input values");
}
Python Code
import numpy as np
import xtensor_python_test as xt
v = np.arange(15).reshape(3, 5)
s = xt.sum_of_sines(v)
s
Outputs
1.2853996391883833
C++ code
#include "pybind11/pybind11.h"
#define FORCE_IMPORT_ARRAY
#include "xtensor-python/pyvectorize.hpp"
#include <numeric>
#include <cmath>
namespace py = pybind11;
double scalar_func(double i, double j)
{
return std::sin(i) - std::cos(j);
}
PYBIND11_MODULE(xtensor_python_test, m)
{
xt::import_numpy();
m.doc() = "Test module for xtensor python bindings";
m.def("vectorized_func", xt::pyvectorize(scalar_func), "");
}
Python Code
import numpy as np
import xtensor_python_test as xt
x = np.arange(15).reshape(3, 5)
y = [1, 2, 3, 4, 5]
z = xt.vectorized_func(x, y)
z
Outputs
[[-0.540302, 1.257618, 1.89929 , 0.794764, -1.040465],
[-1.499227, 0.136731, 1.646979, 1.643002, 0.128456],
[-1.084323, -0.583843, 0.45342 , 1.073811, 0.706945]]
We provide a package for the conda package manager.
conda install -c conda-forge xtensor-python
This will pull the dependencies to xtensor-python, that is pybind11
and xtensor
.
A template for a project making use of xtensor-python
is available in the form of a cookiecutter here.
This project is meant to help library authors get started with the xtensor python bindings.
It produces a project following the best practices for the packaging and distribution of Python extensions based on xtensor-python
, including a setup.py
file and a conda recipe.
Testing xtensor-python
requires pytest
py.test .
To pick up changes in xtensor-python
while rebuilding, delete the build/
directory.
xtensor-python
's documentation is built with three tools
While doxygen must be installed separately, you can install breathe by typing
pip install breathe
Breathe can also be installed with conda
conda install -c conda-forge breathe
Finally, build the documentation with
make html
from the docs
subdirectory.
xtensor-python
depends on the xtensor
and pybind11
libraries
xtensor-python |
xtensor |
pybind11 |
---|---|---|
master | ^0.17.0 | ~2.2.1 |
0.20.x | ^0.17.0 | ~2.2.1 |
0.19.x | ^0.16.0 | ~2.2.1 |
0.18.x | ^0.16.0 | ~2.1.0 or ~2.2.1 |
0.17.x | ^0.15.1 | ~2.1.0 or ~2.2.1 |
0.16.x | ^0.14.0 | ~2.1.0 or ~2.2.1 |
0.15.x | ^0.13.1 | ~2.1.0 or ~2.2.1 |
These dependencies are automatically resolved when using the conda package manager.
We use a shared copyright model that enables all contributors to maintain the copyright on their contributions.
This software is licensed under the BSD-3-Clause license. See the LICENSE file for details.