Skip to content

Array3 from Vec<Array2<Complex<f32>>> #607

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cafeclimber opened this issue Mar 25, 2019 · 2 comments
Closed

Array3 from Vec<Array2<Complex<f32>>> #607

cafeclimber opened this issue Mar 25, 2019 · 2 comments

Comments

@cafeclimber
Copy link

Is it not possible to create a 3D array from a vec of Array2? Mine are complex, but I'm not sure this matters. Here's what I'm trying:

let matrix_data = vec![];
{
    ...
    let mat = aview!(&complex_vec).into_shape((rank, rank)).unwrap();
    matrix_data.push(mat.to_owned());
    ...
}
let array_3d = Array3::from(&matrix_data);

and the error I'm getting is

error[E0277]: the trait bound `ndarray::ArrayBase<ndarray::OwnedRepr<_>, ndarray::Dim<[usize; 3]>>: std::convert::From<&std::vec::Vec<ndarray::ArrayBase<ndarray::OwnedRepr<num_complex::Complex<f32>>, ndarray::Dim<[usize; 2]>>>>` is not satisfied
   --> /home/rdcampbell/Documents/Programming/scirust_rf/src/touchstone.rs:199:24
    |
199 |         let array_3d = Array3::from(&matrix_data);
    |                        ^^^^^^^^^^^^ the trait `std::convert::From<&std::vec::Vec<ndarray::ArrayBase<ndarray::OwnedRepr<num_complex::Complex<f32>>, ndarray::Dim<[usize; 2]>>>>` is not implemented for `ndarray::ArrayBase<ndarray::OwnedRepr<_>, ndarray::Dim<[usize; 3]>>`
    |
    = help: the following implementations were found:
              <ndarray::ArrayBase<ndarray::OwnedRepr<A>, ndarray::Dim<[usize; 2]>> as std::convert::From<std::vec::Vec<V>>>
              <ndarray::ArrayBase<ndarray::ViewRepr<&'a A>, D> as std::convert::From<&'a ndarray::ArrayBase<S, D>>>
              <ndarray::ArrayBase<ndarray::ViewRepr<&'a A>, ndarray::Dim<[usize; 1]>> as std::convert::From<&'a Slice>>error[E0277]: the trait bound `ndarray::ArrayBase<ndarray::OwnedRepr<_>, ndarray::Dim<[usize; 3]>>: std::convert::From<&std::vec::Vec<ndarray::ArrayBase<ndarray::OwnedRepr<num_complex::Complex<f32>>, ndarray::Dim<[usize; 2]>>>>` is not satisfied
   --> /home/rdcampbell/Documents/Programming/scirust_rf/src/touchstone.rs:199:24
    |
199 |         let array_3d = Array3::from(&matrix_data);
    |                        ^^^^^^^^^^^^ the trait `std::convert::From<&std::vec::Vec<ndarray::ArrayBase<ndarray::OwnedRepr<num_complex::Complex<f32>>, ndarray::Dim<[usize; 2]>>>>` is not implemented for `ndarray::ArrayBase<ndarray::OwnedRepr<_>, ndarray::Dim<[usize; 3]>>`
    |
    = help: the following implementations were found:
              <ndarray::ArrayBase<ndarray::OwnedRepr<A>, ndarray::Dim<[usize; 2]>> as std::convert::From<std::vec::Vec<V>>>
              <ndarray::ArrayBase<ndarray::ViewRepr<&'a A>, D> as std::convert::From<&'a ndarray::ArrayBase<S, D>>>
              <ndarray::ArrayBase<ndarray::ViewRepr<&'a A>, ndarray::Dim<[usize; 1]>> as std::convert::From<&'a Slice>>
              <ndarray::ArrayBase<ndarray::ViewRepr<&'a mut A>, D> as std::convert::From<&'a mut ndarray::ArrayBase<S, D>>>
            and 3 others
    = note: required by `std::convert::From::from`


              <ndarray::ArrayBase<ndarray::ViewRepr<&'a mut A>, D> as std::convert::From<&'a mut ndarray::ArrayBase<S, D>>>
            and 3 others
    = note: required by `std::convert::From::from`

I saw shape_from_vec, but that doesn't work for me either. I think because of the shape of my Vec

@jturner314
Copy link
Member

It's not possible to create an Array<A, D> from Vec<Array<A, D2>> without copying the data. The data in Vec<Array<A, D2>> may be scattered all over memory, because each Array within the Vec has a separate heap allocation for its data. In contrast, Array<A, D> consists of only a single heap allocation (it's effectively a fancy wrapper for Vec).

For your use-case, if you know the shape of array_3d ahead-of-time, IMO the cleanest solution is to create an empty array before the loop with Array::zeros, and then fill it in the loop. Something like this:

extern crate ndarray;

use ndarray::prelude::*;

fn main() {
    let iter_len = 5;
    let rank = 4;
    let mut array_3d = Array3::zeros((iter_len, rank, rank));
    for (i, mut v) in array_3d.axis_iter_mut(Axis(0)).enumerate() {
        let complex_vec = vec![i; rank * rank];
        let mat = Array::from_shape_vec((rank, rank), complex_vec).unwrap();
        // or: let mat = ArrayView2::from_shape((rank, rank), &complex_vec).unwrap();
        v.assign(&mat);
    }
    println!("{}", array_3d);
}

If you don't know the shape ahead-of-time, then I'd suggest placing the elements (flattened) in a single Vec, and then converting that to an Array at the end. Something like this:

extern crate ndarray;

use ndarray::prelude::*;

fn main() {
    let rank = 4;
    let mut data = Vec::new();
    let mut iter_len = 0;
    for i in 0..5 {
        iter_len += 1;
        let complex_vec = vec![i; rank * rank];
        data.extend_from_slice(&complex_vec);
    }
    let array_3d = Array3::from_shape_vec((iter_len, rank, rank), data).unwrap();
    println!("{}", array_3d);
}

If you want to stick with your existing implementation, you could do this:

extern crate ndarray;

use ndarray::prelude::*;

fn main() {
    let rank = 4;
    let mut matrix_data = vec![];
    let mut iter_len = 0;
    for i in 0..5 {
        iter_len += 1;
        let complex_vec = vec![i; rank * rank];
        let mat = Array2::from_shape_vec((rank, rank), complex_vec).unwrap();
        matrix_data.push(mat);
    }
    let data = matrix_data.iter().flatten().cloned().collect();
    let array_3d = Array3::from_shape_vec((iter_len, rank, rank), data).unwrap();
    println!("{}", array_3d);
}

@cafeclimber
Copy link
Author

Fantastic! Thank you. The first option seems like it will work perfect. More likely, I'll take the time to understand why this method might not be the best way to handle creating the array and will end up refactoring!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants