Skip to content

Commit f843e0f

Browse files
rcarson3jturner314
authored andcommitted
Add more examples to ndarray for NumPy users
1 parent f19b203 commit f843e0f

File tree

3 files changed

+229
-0
lines changed

3 files changed

+229
-0
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
//! Example of rotation with Euler angles.
2+
//!
3+
//! This is an example of some coordinate transformations (using Euler angles)
4+
//! for illustrative purposes. Note that other crates such as
5+
//! [`cgmath`](https://crates.io/crates/cgmath) or
6+
//! [`nalgebra`](https://crates.io/crates/nalgebra) may be better-suited if
7+
//! most of your work is coordinate transformations, since they have built-in
8+
//! geometry primitives.
9+
//!
10+
//! This is the original Python program:
11+
//!
12+
//! ```python
13+
//! # Euler angles (rows) for four coordinate systems (columns).
14+
//! nelems = 4
15+
//! bunge = np.ones((3, nelems))
16+
//!
17+
//! # Precompute sines and cosines
18+
//! s1 = np.sin(bunge[0, :])
19+
//! c1 = np.cos(bunge[0, :])
20+
//! s2 = np.sin(bunge[1, :])
21+
//! c2 = np.cos(bunge[1, :])
22+
//! s3 = np.sin(bunge[2, :])
23+
//! c3 = np.cos(bunge[2, :])
24+
//!
25+
//! # Rotation matrices.
26+
//! rmat = np.zeros((3, 3, nelems), order='F')
27+
//! for i in range(nelems):
28+
//! rmat[0, 0, i] = c1[i] * c3[i] - s1[i] * s3[i] * c2[i]
29+
//! rmat[0, 1, i] = -c1[i] * s3[i] - s1[i] * c2[i] * c3[i]
30+
//! rmat[0, 2, i] = s1[i] * s2[i]
31+
//!
32+
//! rmat[1, 0, i] = s1[i] * c3[i] + c1[i] * c2[i] * s3[i]
33+
//! rmat[1, 1, i] = -s1[i] * s3[i] + c1[i] * c2[i] * c3[i]
34+
//! rmat[1, 2, i] = -c1[i] * s2[i]
35+
//!
36+
//! rmat[2, 0, i] = s2[i] * s3[i]
37+
//! rmat[2, 1, i] = s2[i] * c3[i]
38+
//! rmat[2, 2, i] = c2[i]
39+
//!
40+
//! # Unit vectors of coordinate systems to rotate.
41+
//! eye2d = np.eye(3)
42+
//!
43+
//! # Unit vectors after rotation.
44+
//! rotated = np.zeros((3, 3, nelems), order='F')
45+
//! for i in range(nelems):
46+
//! rotated[:,:,i] = rmat[:,:,i].dot(eye2d)
47+
//! ```
48+
//!
49+
//! This is a direct translation to `ndarray`:
50+
//!
51+
//! ```
52+
//! #[macro_use]
53+
//! extern crate ndarray;
54+
//!
55+
//! use ndarray::prelude::*;
56+
//!
57+
//! fn main() {
58+
//! let nelems = 4;
59+
//! let bunge = Array::ones((3, nelems));
60+
//!
61+
//! let s1 = bunge.slice(s![0, ..]).mapv(f64::sin);
62+
//! let c1 = bunge.slice(s![0, ..]).mapv(f64::cos);
63+
//! let s2 = bunge.slice(s![1, ..]).mapv(f64::sin);
64+
//! let c2 = bunge.slice(s![1, ..]).mapv(f64::cos);
65+
//! let s3 = bunge.slice(s![2, ..]).mapv(f64::sin);
66+
//! let c3 = bunge.slice(s![2, ..]).mapv(f64::cos);
67+
//!
68+
//! let mut rmat = Array::zeros((3, 3, nelems).f());
69+
//! for i in 0..nelems {
70+
//! rmat[[0, 0, i]] = c1[i] * c3[i] - s1[i] * s3[i] * c2[i];
71+
//! rmat[[0, 1, i]] = -c1[i] * s3[i] - s1[i] * c2[i] * c3[i];
72+
//! rmat[[0, 2, i]] = s1[i] * s2[i];
73+
//!
74+
//! rmat[[1, 0, i]] = s1[i] * c3[i] + c1[i] * c2[i] * s3[i];
75+
//! rmat[[1, 1, i]] = -s1[i] * s3[i] + c1[i] * c2[i] * c3[i];
76+
//! rmat[[1, 2, i]] = -c1[i] * s2[i];
77+
//!
78+
//! rmat[[2, 0, i]] = s2[i] * s3[i];
79+
//! rmat[[2, 1, i]] = s2[i] * c3[i];
80+
//! rmat[[2, 2, i]] = c2[i];
81+
//! }
82+
//!
83+
//! let eye2d = Array::eye(3);
84+
//!
85+
//! let mut rotated = Array::zeros((3, 3, nelems).f());
86+
//! for i in 0..nelems {
87+
//! rotated
88+
//! .slice_mut(s![.., .., i])
89+
//! .assign({ &rmat.slice(s![.., .., i]).dot(&eye2d) });
90+
//! }
91+
//! }
92+
//! ```
93+
//!
94+
//! Instead of looping over indices, a cleaner (and usually faster) option is
95+
//! to zip arrays together. It's also possible to avoid some of the temporary
96+
//! memory allocations in the original program. The improved version looks like
97+
//! this:
98+
//!
99+
//! ```
100+
//! #[macro_use]
101+
//! extern crate ndarray;
102+
//!
103+
//! use ndarray::prelude::*;
104+
//!
105+
//! fn main() {
106+
//! let nelems = 4;
107+
//! let bunge = Array2::<f64>::ones((3, nelems));
108+
//!
109+
//! let mut rmat = Array::zeros((3, 3, nelems).f());
110+
//! azip!(mut rmat (rmat.axis_iter_mut(Axis(2))), ref bunge (bunge.axis_iter(Axis(1))) in {
111+
//! let s1 = bunge[0].sin();
112+
//! let c1 = bunge[0].cos();
113+
//! let s2 = bunge[1].sin();
114+
//! let c2 = bunge[1].cos();
115+
//! let s3 = bunge[2].sin();
116+
//! let c3 = bunge[2].cos();
117+
//!
118+
//! rmat[[0, 0]] = c1 * c3 - s1 * s3 * c2;
119+
//! rmat[[0, 1]] = -c1 * s3 - s1 * c2 * c3;
120+
//! rmat[[0, 2]] = s1 * s2;
121+
//!
122+
//! rmat[[1, 0]] = s1 * c3 + c1 * c2 * s3;
123+
//! rmat[[1, 1]] = -s1 * s3 + c1 * c2 * c3;
124+
//! rmat[[1, 2]] = -c1 * s2;
125+
//!
126+
//! rmat[[2, 0]] = s2 * s3;
127+
//! rmat[[2, 1]] = s2 * c3;
128+
//! rmat[[2, 2]] = c2;
129+
//! });
130+
//!
131+
//! let eye2d = Array2::<f64>::eye(3);
132+
//!
133+
//! let mut rotated = Array3::<f64>::zeros((3, 3, nelems).f());
134+
//! azip!(mut rotated (rotated.axis_iter_mut(Axis(2)), rmat (rmat.axis_iter(Axis(2)))) in {
135+
//! rotated.assign({ &rmat.dot(&eye2d) });
136+
//! });
137+
//! }
138+
//! ```

src/doc/ndarray_for_numpy_users/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,3 +610,5 @@
610610
//! [Zip]: ../../struct.Zip.html
611611
612612
pub mod rk_step;
613+
pub mod coord_transform;
614+
pub mod simple_math;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//! Example of simple math operations on 2-D arrays.
2+
//!
3+
//! <table>
4+
//!
5+
//! <tr>
6+
//! <th>
7+
//!
8+
//! NumPy
9+
//!
10+
//! </th>
11+
//! <th>
12+
//!
13+
//! `ndarray`
14+
//!
15+
//! </th>
16+
//! </tr>
17+
//! <tr>
18+
//! <td>
19+
//!
20+
//! ```python
21+
//! import numpy as np
22+
//!
23+
//!
24+
//!
25+
//!
26+
//!
27+
//! a = np.full((5, 4), 3.)
28+
//!
29+
//!
30+
//! a[::2, :] = 2.
31+
//!
32+
//!
33+
//! a[:, 1] = np.sin(a[:, 1]) + 1.
34+
//!
35+
//!
36+
//! a[a < 1.5] = 4.
37+
//!
38+
//!
39+
//! odd_sum = a[:, 1::2].sum()
40+
//!
41+
//!
42+
//! b = np.exp(np.arange(4))
43+
//!
44+
//!
45+
//! c = a + b
46+
//!
47+
//!
48+
//! d = c.T.dot(a)
49+
//! ```
50+
//!
51+
//! </td>
52+
//! <td>
53+
//!
54+
//! ```
55+
//! #[macro_use]
56+
//! extern crate ndarray;
57+
//!
58+
//! use ndarray::prelude::*;
59+
//!
60+
//! # fn main() {
61+
//! // Create a 5×4 array of threes.
62+
//! let mut a = Array2::<f64>::from_elem((5, 4), 3.);
63+
//!
64+
//! // Fill the even-index rows with twos.
65+
//! a.slice_mut(s![..;2, ..]).fill(2.);
66+
//!
67+
//! // Change column 1 to sin(x) + 1.
68+
//! a.column_mut(1).mapv_inplace(|x| x.sin() + 1.);
69+
//!
70+
//! // Change values less than 1.5 to 4.
71+
//! a.mapv_inplace(|x| if x < 1.5 { 4. } else { x });
72+
//!
73+
//! // Compute the scalar sum of the odd-index columns.
74+
//! let odd_sum = a.slice(s![.., 1..;2]).scalar_sum();
75+
//!
76+
//! // Create a 1-D array of exp(index).
77+
//! let b = Array::from_shape_fn(4, |i| (i as f64).exp());
78+
//!
79+
//! // Add b to a (broadcasting to rows).
80+
//! let c = a + &b;
81+
//!
82+
//! // Matrix product of c transpose with c.
83+
//! let d = c.t().dot(&c);
84+
//! # }
85+
//! ```
86+
//!
87+
//! </td>
88+
//! </tr>
89+
//! </table>

0 commit comments

Comments
 (0)