Skip to content

Commit 6f3020c

Browse files
committed
Add proper readme
1 parent e84008c commit 6f3020c

File tree

3 files changed

+162
-24
lines changed

3 files changed

+162
-24
lines changed

README.md

Lines changed: 126 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,138 @@
1-
# Requirement
1+
# xtensor-python
22

3-
- pybind11 master (not 1.8.1)
4-
- xtensor 0.1.0
3+
Python bindings for the [xtensor](https://github.com/QuantStack/xtensor) C++ multi-dimensional array library.
54

6-
# Installation
5+
- `xtensor` is a C++ library for multi-dimensional arrays enabling numpy-style broadcasting and lazy computing.
6+
- `xtensor-python` enables inplace use of numpy arrays with all the benefits from `xtensor`
77

8-
- build and install conda recipe
8+
- C++ universal function and broadcasting
9+
- STL - compliant APIs.
910

10-
# Dev installation
11+
The Python bindings for `xtensor` are based on the [pybind11](https://github.com/pybind/pybind11/) C++ library, which enables seemless interoperability between C++ and Python.
1112

12-
- symlink `include\xtensor-python` to `$SYS_PREFIX\include\xtensor-python`
13+
## Usage
1314

14-
# Testing
15+
### Example 1: Use an algorithm of the C++ library on a numpy array inplace.
1516

16-
Testing `xtensor-python` requires `nosetests`
17+
**C++ code**
18+
19+
```cpp
20+
#include <numeric> // Standard library import for std::accumulate
21+
#include "pybind11/pybind11.h" // Pybind11 import to define Python bindings
22+
#include "xtensor/xmath.hpp" // xtensor import for the C++ universal functions
23+
#include "xtensor-python/pyarray.hpp" // Numpy bindings
24+
25+
double sum_of_sines(xt::pyarray<double> &m)
26+
{
27+
auto sines = xt::sin(m); // sines does not actually hold any value, which are only computed upon access
28+
return std::accumulate(sines.begin(), sines.end(), 0.0);
29+
}
30+
31+
PYBIND11_PLUGIN(xtensor_python_test)
32+
{
33+
pybind11::module m("xtensor_python_test", "Test module for xtensor python bindings");
34+
35+
m.def("sum_of_sines", sum_of_sines, "Computes the sum of the sines of the values of the input array");
36+
37+
return m.ptr();
38+
}
39+
```
40+
41+
**Python Code**
42+
43+
```python
44+
import numpy as np
45+
import xtensor_python_test as xt
46+
47+
a = np.arange(15).reshape(3, 5)
48+
s = xt.sum_of_sines(v)
49+
s
50+
```
51+
52+
**Outputs**
53+
54+
```
55+
1.2853996391883833
56+
```
57+
58+
### Example 2: Create a universal function from a C++ scalar function
59+
60+
**C++ code**
61+
62+
```cpp
63+
#include "pybind11/pybind11.h"
64+
#include "xtensor-python/pyvectorize.hpp"
65+
#include <numeric>
66+
#include <cmath>
67+
68+
namespace py = pybind11;
69+
70+
double scalar_func(double i, double j)
71+
{
72+
return std::sin(i) - std::cos(j);
73+
}
74+
75+
PYBIND11_PLUGIN(xtensor_python_test)
76+
{
77+
py::module m("xtensor_python_test", "Test module for xtensor python bindings");
78+
79+
m.def("vectorized_func", xt::pyvectorize(scalar_func), "");
80+
81+
return m.ptr();
82+
}
83+
```
84+
85+
**Python Code**
86+
87+
```python
88+
import numpy as np
89+
import xtensor_python_test as xt
90+
91+
x = np.arange(15).reshape(3, 5)
92+
y = [1, 2, 3]
93+
z = xt.vectorized_func(x, y)
94+
z
95+
```
96+
97+
**Outputs**
98+
99+
```
100+
[[-1. , 0.301169, 1.325444, 1.131113, -0.103159],
101+
[-1.958924, -0.819718, 1.073133, 1.979351, 1.065762],
102+
[-1.544021, -1.540293, -0.120426, 1.41016 , 1.644251]]
103+
```
104+
105+
## Installation
106+
107+
We provide a package for the conda package manager.
108+
109+
```bash
110+
conda install -c conda-forge xtensor-python
111+
```
112+
113+
This will pull the dependencies to xtensor-python, that is `pybind11` and `xtensor`.
114+
115+
## Project cookiecutter
116+
117+
A template for a project making use of `xtensor-python` is available in the form of a cookie cutter [here](https://github.com/QuantStack/xtensor-cookiecutter).
118+
119+
This project is meant to help library authors get started with the xtensor python bindings.
120+
121+
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.
122+
123+
## Building and Running the Tests
124+
125+
Testing `xtensor-python` requires `nosetests`
17126

18127
``` bash
19128
nosetests .
20129
```
21130

22-
To pick up changes in `xtensor-python` while rebuilding, delete the `build/` directory.
131+
To pick up changes in `xtensor-python` while rebuilding, delete the `build/` directory.
132+
133+
## License
134+
135+
We use a shared copyright model that enables all contributors to maintain the
136+
copyright on their contributions.
137+
138+
This software is licensed under the BSD-3-Clause license. See the [LICENSE](LICENSE) file for details.

test/main.cpp

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,50 @@
1-
#include <pybind11/pybind11.h>
1+
#include "pybind11/pybind11.h"
2+
#include "xtensor/xmath.hpp"
23
#include "xtensor/xarray.hpp"
34
#include "xtensor-python/pyarray.hpp"
45
#include "xtensor-python/pyvectorize.hpp"
56
#include <iostream>
7+
#include <numeric>
68

79
namespace py = pybind11;
810

9-
int add(int i, int j) {
10-
return i + j;
11-
}
11+
// Examples
1212

13-
double test0(xt::pyarray<double> &m)
13+
double example1(xt::pyarray<double> &m)
1414
{
1515
return m(0);
1616
}
1717

18-
xt::pyarray<double> test1(xt::pyarray<double> &m)
18+
xt::pyarray<double> example2(xt::pyarray<double> &m)
1919
{
2020
return m + 2;
2121
}
2222

23+
// Readme Examples
24+
25+
double readme_example1(xt::pyarray<double> &m)
26+
{
27+
auto sines = xt::sin(m);
28+
return std::accumulate(sines.begin(), sines.end(), 0.0);
29+
}
30+
31+
// Vectorize Examples
32+
33+
int add(int i, int j)
34+
{
35+
return i + j;
36+
}
37+
2338
PYBIND11_PLUGIN(xtensor_python_test)
2439
{
2540
py::module m("xtensor_python_test", "Test module for xtensor python bindings");
2641

27-
m.def("test0", test0, "");
28-
m.def("test1", test1, "");
29-
m.def("vec_add", xt::pyvectorize(add), "");
42+
m.def("example1", example1, "");
43+
m.def("example2", example2, "");
44+
45+
m.def("readme_example1", readme_example1, "");
46+
47+
m.def("vectorize_example1", xt::pyvectorize(add), "");
3048

3149
return m.ptr();
3250
}

test/test_pyarray.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,23 @@
1515

1616
class ExampleTest(TestCase):
1717

18-
def test_example0(self):
19-
self.assertEqual(4, xt.test0([4, 5, 6]))
20-
2118
def test_example1(self):
19+
self.assertEqual(4, xt.example1([4, 5, 6]))
20+
21+
def test_example2(self):
2222
x = np.array([[0., 1.], [2., 3.]])
2323
res = np.array([[2., 3.], [4., 5.]])
24-
y = xt.test1(x)
24+
y = xt.example2(x)
2525
np.testing.assert_allclose(y, res, 1e-12)
2626

2727
def test_vectorize(self):
2828
x1 = np.array([[0, 1], [2, 3]])
2929
x2 = np.array([0, 1])
3030
res = np.array([[0, 2], [2, 4]])
31-
y = xt.vec_add(x1, x2)
31+
y = xt.vectorize_example1(x1, x2)
3232
np.testing.assert_array_equal(y, res)
3333

34+
def test_readme_example1(self):
35+
v = np.arange(15).reshape(3, 5)
36+
y = xt.readme_example1(v)
37+
np.testing.assert_allclose(y, 1.2853996391883833, 1e-12)

0 commit comments

Comments
 (0)