Skip to content

Commit

Permalink
flumpy: Explicitly fail for non-contiguous numpy arrays
Browse files Browse the repository at this point in the history
Fixed cctbx#405
  • Loading branch information
ndevenish committed Aug 9, 2021
1 parent 53a968d commit f7a4f94
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
1 change: 1 addition & 0 deletions newsfragments/405.bugfix
@@ -0,0 +1 @@
``flumpy``: Fail with an explicit error trying to convert non-contiguous numpy arrays
25 changes: 25 additions & 0 deletions src/dxtbx/boost_python/flumpy.cc
Expand Up @@ -369,6 +369,13 @@ py::object from_numpy(py::object array) {
"Cannot currently convert from non-numpy array format to flex");
}
auto np_array = py::array(array);

// Check that this array is contiguous
if (!np_array.attr("flags")["C_CONTIGUOUS"].cast<bool>()) {
throw std::invalid_argument(
"numpy array is non-contiguous - flex arrays must be contiguous");
}

// Now, see if this is a numpy object we created to wrap a flex
if (np_array.base()) {
if (py::isinstance<Scuffer>(np_array.base().attr("obj"))) {
Expand Down Expand Up @@ -441,6 +448,13 @@ py::object vec_from_numpy(py::array np_array) {
throw std::invalid_argument("Input array last dimension is not size "
+ std::to_string(VecType<int>::fixed_size));
}

// Check that this array is contiguous
if (!np_array.attr("flags")["C_CONTIGUOUS"].cast<bool>()) {
throw std::invalid_argument(
"numpy array is non-contiguous - flex arrays must be contiguous");
}

auto dtype = np_array.attr("dtype").attr("char").cast<char>();

std::string accepted_types = VecType<int>::fixed_size == 2 ? "dQ" : "di";
Expand Down Expand Up @@ -473,6 +487,11 @@ py::object vec_from_numpy(py::array np_array) {
/// Decide which sized vector we want to convert to, and hand off to the
/// specialization
py::object vecs_from_numpy(py::array np_array) {
// Check that this array is contiguous
if (!np_array.attr("flags")["C_CONTIGUOUS"].cast<bool>()) {
throw std::invalid_argument(
"numpy array is non-contiguous - flex arrays must be contiguous");
}
if (np_array.shape(np_array.ndim() - 1) == 3) {
return vec_from_numpy<scitbx::vec3>(np_array);
} else if (np_array.shape(np_array.ndim() - 1) == 2) {
Expand All @@ -483,6 +502,12 @@ py::object vecs_from_numpy(py::array np_array) {
}

py::object mat3_from_numpy(py::array np_array) {
// Check that this array is contiguous
if (!np_array.attr("flags")["C_CONTIGUOUS"].cast<bool>()) {
throw std::invalid_argument(
"numpy array is non-contiguous - flex arrays must be contiguous");
}

auto nd = np_array.ndim();
// Check our last dimension(s) are either x9 or x3x3
bool last_is_9 = np_array.shape(nd - 1) == 9;
Expand Down
13 changes: 13 additions & 0 deletions tests/test_flumpy.py
Expand Up @@ -306,3 +306,16 @@ def test_numpy_loop_nesting():
fo = flumpy.from_numpy(no)
no_2 = flumpy.to_numpy(fo)
assert no_2 is no


def test_noncontiguous():
npo = np.zeros((10, 4, 3))
flumpy.from_numpy(npo)
with pytest.raises(ValueError):
flumpy.from_numpy(npo[:, 1:])

with pytest.raises(ValueError):
flumpy.vec_from_numpy(npo[:, 1:])

with pytest.raises(ValueError):
flumpy.mat3_from_numpy(npo[:, 1:])

0 comments on commit f7a4f94

Please sign in to comment.