xtensor icon indicating copy to clipboard operation
xtensor copied to clipboard

Add `xt::ix_`

Open mirmohammad opened this issue 2 years ago • 2 comments

xtensor is missing cross product indices generation (numpy.ix_) https://numpy.org/doc/stable/reference/generated/numpy.ix_.html

I am posting this code as a suggestion. It works for my use cases but definitely requires more testing. The idea is to return a vector of indices (that are cross product of all the inputs) used with index_view on an xarray.

in xt namespace:

template <typename... INDICES>
std::vector<std::array<std::size_t, sizeof...(INDICES)>> ix_(INDICES &&...indices)
{
    constexpr std::size_t N = sizeof...(INDICES);
    std::vector<std::array<std::size_t, N>> ix_indices;
    auto mesh = xt::meshgrid(std::forward<INDICES>(indices)...);
    auto stack = std::apply([=](auto &&...m)
                            { return xt::stack(xt::xtuple(m...), N).reshape({-1, (int)N}); },
                            mesh);
    auto start = xt::axis_begin(stack, 0);
    auto end = xt::axis_end(stack, 0);
    while (start != end)
    {
        ix_indices.push_back({});
        std::copy(start->begin(), start->end(), ix_indices.back().begin());
        start++;
    }
    return ix_indices;
}

Example Usage 1:

xt::xarray<int> some_indices{ 0, 1, 2, 3 };
auto indices = xt::ix_(some_indices, xt::arange(2));
auto selected_scores = xt::index_view(all_scores, indices);

Example Usage 2:

xt::xarray<int> some_indices{ 0, 1 };
auto indices = xt::ix_(some_indices, some_indices, some_indices);
auto selected_scores = xt::index_view(all_scores, indices);

mirmohammad avatar Jan 10 '23 23:01 mirmohammad

@AntoinePrv Would you mind checking my solution out?

mirmohammad avatar Jan 10 '23 23:01 mirmohammad

Hi @mirmohammad,

What are you trying to achieve? From NumPy doc, it seems np.ix_ is simpler than what you are doing. It looks like one should go through the inputs and apply a reshape to add a number of 1s.

Perhaps what you are trying to do an advanced indexing where you apply a 1D index selection on each axis. As you noticed, there is no easy/performant way of doing in xtensor so far.

I ended up doing something similar when I needed: build the expanded list of indices on way or another, then pass it to xt::index_view.

AntoinePrv avatar Jan 13 '23 14:01 AntoinePrv