1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
//! This crate provides conversion between [`nalgebra`] and [`numpy`](https://numpy.org/). //! It is intended to be used when you want to share nalgebra matrices between Python and Rust code, //! for example with [`inline-python`](https://docs.rs/inline-python). //! //! # Conversion from numpy to nalgebra. //! //! It is possible to create either a view or a copy of a numpy array. //! You can use [`matrix_from_numpy`] to copy the data into a new matrix, //! or one of [`matrix_slice_from_numpy`] or [`matrix_slice_mut_from_numpy`] to create a view. //! If a numpy array is not compatible with the requested matrix type, //! an error is returned. //! //! Keep in mind though that the borrow checker can not enforce rules on data managed by a Python object. //! You could potentially keep an immutable view around in Rust, and then modify the data from Python. //! For this reason, creating any view -- even an immutable one -- is unsafe. //! //! # Conversion from nalgebra to numpy. //! //! A nalgebra matrix can also be converted to a numpy array, using [`matrix_to_numpy`]. //! This function always creates a copy. //! Since all nalgebra arrays can be represented as a numpy array, //! this directly returns a [`pyo3::PyObject`] rather than a `Result`. //! //! # Examples. //! //! Copy a numpy array to a new fixed size matrix: //! //! ``` //! use inline_python::{Context, python}; //! use nalgebra_numpy::{matrix_from_numpy}; //! //! # fn main() -> Result<(), nalgebra_numpy::Error> { //! let gil = pyo3::Python::acquire_gil(); //! let context = Context::new_with_gil(gil.python()); //! context.run(python! { //! import numpy as np //! matrix = np.array([ //! [1.0, 2.0, 3.0], //! [4.0, 5.0, 6.0], //! [7.0, 8.0, 9.0], //! ]) //! }); //! //! let matrix = context.globals(gil.python()).get_item("matrix").unwrap(); //! let matrix : nalgebra::Matrix3<f64> = matrix_from_numpy(gil.python(), matrix)?; //! //! assert_eq!(matrix, nalgebra::Matrix3::new( //! 1.0, 2.0, 3.0, //! 4.0, 5.0, 6.0, //! 7.0, 8.0, 9.0, //! )); //! # Ok(()) //! # } //! ``` //! //! Dynamic matrices are also supported: //! //! ``` //! # use inline_python::{Context, python}; //! # use nalgebra_numpy::{matrix_from_numpy}; //! use nalgebra::DMatrix; //! # fn main() -> Result<(), nalgebra_numpy::Error> { //! # let gil = pyo3::Python::acquire_gil(); //! # let context = Context::new_with_gil(gil.python()); //! # context.run(python! { //! # import numpy as np //! # matrix = np.array([ //! # [1.0, 2.0, 3.0], //! # [4.0, 5.0, 6.0], //! # [7.0, 8.0, 9.0], //! # ]) //! # }); //! # //! # let matrix = context.globals(gil.python()).get_item("matrix").unwrap(); //! //! let matrix : DMatrix<f64> = matrix_from_numpy(gil.python(), matrix)?; //! assert_eq!(matrix, DMatrix::from_row_slice(3, 3, &[ //! 1.0, 2.0, 3.0, //! 4.0, 5.0, 6.0, //! 7.0, 8.0, 9.0, //! ])); //! # Ok(()) //! # } //! ``` //! //! And so are partially dynamic matrices: //! //! ``` //! # use inline_python::{Context, python}; //! # use nalgebra_numpy::{matrix_from_numpy}; //! use nalgebra::{MatrixMN, Dynamic, U3}; //! # fn main() -> Result<(), nalgebra_numpy::Error> { //! # let gil = pyo3::Python::acquire_gil(); //! # let context = Context::new_with_gil(gil.python()); //! # context.run(python! { //! # import numpy as np //! # matrix = np.array([ //! # [1.0, 2.0, 3.0], //! # [4.0, 5.0, 6.0], //! # [7.0, 8.0, 9.0], //! # ]) //! # }); //! # let matrix = context.globals(gil.python()).get_item("matrix").unwrap(); //! //! let matrix : MatrixMN<f64, U3, Dynamic> = matrix_from_numpy(gil.python(), matrix)?; //! assert_eq!(matrix, MatrixMN::<f64, U3, Dynamic>::from_row_slice(&[ //! 1.0, 2.0, 3.0, //! 4.0, 5.0, 6.0, //! 7.0, 8.0, 9.0, //! ])); //! # Ok(()) //! # } //! ``` //! //! A conversion to python object looks as follows: //! ``` //! use nalgebra_numpy::matrix_to_numpy; //! use nalgebra::Matrix3; //! use inline_python::python; //! //! let gil = pyo3::Python::acquire_gil(); //! let matrix = matrix_to_numpy(gil.python(), &Matrix3::<i32>::new( //! 0, 1, 2, //! 3, 4, 5, //! 6, 7, 8, //! )); //! //! python! { //! from numpy import array_equal //! assert array_equal('matrix, [ //! [0, 1, 2], //! [3, 4, 5], //! [6, 7, 8], //! ]) //! } //! ``` mod from_numpy; mod to_numpy; pub use from_numpy::*; pub use to_numpy::*;