# xtensor-python
[](https://badge.fury.io/py/xtensor-python)
[](https://xtensor-python.readthedocs.io/en/latest/?badge=latest)
[](https://opensource.org/licenses/BSD-3-Clause)
Python bindings for the [xtensor](https://github.com/xtensor-stack/xtensor) C++ multi-dimensional array library.
## Overview
`xtensor-python` enables seamless interoperability between NumPy arrays and C++ through the xtensor library. It provides:
- **Zero-copy** NumPy array integration with C++
- **Broadcasting** and universal functions compatible with NumPy
- **STL-compliant** APIs for familiar C++ development
- **Header-only** library for easy integration
- **High performance** through lazy evaluation and expression templates
## Installation
### From PyPI (Recommended)
```bash
pip install xtensor-python
```
### From conda-forge
```bash
conda install -c conda-forge xtensor-python
# or
mamba install -c conda-forge xtensor-python
```
### Development Installation
```bash
git clone https://github.com/xtensor-stack/xtensor-python.git
cd xtensor-python
pip install -e .
```
## Quick Start
### Python API
The Python package provides utilities for building C++ extensions:
```python
import xtensor_python
# Get include directories for your C++ build
include_dirs = xtensor_python.get_include()
print(include_dirs)
# Use in your setup.py or pyproject.toml
from pybind11.setup_helpers import build_ext
from xtensor_python import get_cmake_dir
# CMake integration
cmake_dir = get_cmake_dir()
```
### C++ Integration
Create a C++ extension using xtensor-python:
```cpp
#include
#include
#include
// Enable numpy import
#define FORCE_IMPORT_ARRAY
#include
double sum_of_sines(xt::pyarray& arr) {
auto sines = xt::sin(arr); // Lazy evaluation
return std::accumulate(sines.begin(), sines.end(), 0.0);
}
PYBIND11_MODULE(my_extension, m) {
xt::import_numpy();
m.def("sum_of_sines", sum_of_sines, "Sum the sines of array elements");
}
```
### CMakeLists.txt Example
```cmake
cmake_minimum_required(VERSION 3.15)
project(my_extension)
find_package(Python COMPONENTS Interpreter Development REQUIRED)
find_package(pybind11 REQUIRED)
find_package(xtensor-python REQUIRED)
pybind11_add_module(my_extension src/main.cpp)
target_link_libraries(my_extension PRIVATE xtensor-python::xtensor-python)
```
## Container Types
### pyarray
Dynamic multi-dimensional arrays that can be reshaped:
```cpp
#include
void process_dynamic(xt::pyarray& arr) {
// Can reshape to different dimensions
arr.reshape({10, 5});
// Changes are reflected in Python
}
```
### pytensor
Fixed-dimension arrays with compile-time optimization:
```cpp
#include
void process_2d(xt::pytensor& tensor) {
// Fixed 2D tensor - faster than pyarray
// Shape is stack-allocated
auto result = xt::sum(tensor, {1}); // Sum along axis 1
}
```
## Migration from CMake to pip
### Before (CMake-based)
```cmake
find_package(xtensor-python REQUIRED)
target_link_libraries(mylib xtensor-python)
```
### After (pip-based)
1. **Install via pip:**
```bash
pip install xtensor-python
```
2. **Update CMakeLists.txt:**
```cmake
find_package(Python COMPONENTS Interpreter Development REQUIRED)
find_package(xtensor-python REQUIRED)
target_link_libraries(mylib PRIVATE xtensor-python::xtensor-python)
```
3. **Or use in setup.py:**
```python
from pybind11.setup_helpers import build_ext
import xtensor_python
ext_modules = [
Pybind11Extension(
"my_module",
["src/main.cpp"],
include_dirs=[xtensor_python.get_include()],
),
]
```
### Key Changes
- **Installation**: Use `pip install xtensor-python` instead of conda/manual builds
- **CMake**: The package now provides proper CMake config files
- **Headers**: Automatically available through Python package
- **Dependencies**: Managed through pip/pyproject.toml
## Advanced Usage
### Universal Functions
Create vectorized functions from scalar C++ functions:
```cpp
#include
double scalar_func(double x, double y) {
return std::sin(x) - std::cos(y);
}
PYBIND11_MODULE(my_module, m) {
xt::import_numpy();
m.def("vectorized_func", xt::pyvectorize(scalar_func));
}
```
### Custom Type Casting
```cpp
#include
// Automatic casting between NumPy and xtensor types
void process_array(const xt::xarray& arr) {
// Function automatically accepts NumPy arrays
}
```
## Building Extensions
### Using setuptools
```python
# setup.py
from pybind11.setup_helpers import Pybind11Extension, build_ext
import xtensor_python
ext_modules = [
Pybind11Extension(
"my_extension",
["src/main.cpp"],
include_dirs=[xtensor_python.get_include()],
cxx_std=14,
),
]
setup(
name="my_package",
ext_modules=ext_modules,
cmdclass={"build_ext": build_ext},
)
```
### Using pyproject.toml
```toml
[build-system]
requires = ["setuptools", "pybind11", "xtensor-python"]
[tool.setuptools]
packages = ["my_package"]
[[tool.setuptools.ext-modules]]
name = "my_package._core"
sources = ["src/main.cpp"]
```
## Dependencies
- **Python**: 3.8
- **NumPy**: 2.0
- **pybind11**: 2.6.1,