Skip to content

Commit

Permalink
Merge pull request #774 from ANTsX/no_swap_numpy_dims
Browse files Browse the repository at this point in the history
No swap numpy dims
  • Loading branch information
cookpa authored Feb 5, 2025
2 parents 6d7bd92 + f22bf97 commit c816d99
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 18 deletions.
3 changes: 2 additions & 1 deletion ants/core/ants_image_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ def from_numpy(
if best_dtype != data.dtype:
data = data.astype(best_dtype)

img = _from_numpy(data.T.copy(), origin, spacing, direction, has_components, is_rgb)
# Be explicit about ordering of data - needs to be C-contiguous
img = _from_numpy(data.T.copy(order='C'), origin, spacing, direction, has_components, is_rgb)
return img


Expand Down
16 changes: 0 additions & 16 deletions src/itkPyBuffer.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ PyBuffer<TImage>
memset(&pyBuffer, 0, sizeof(Py_buffer));

SizeType size;
SizeType sizeFortran;
SizeValueType numberOfPixels = 1;

const void * buffer;
Expand Down Expand Up @@ -114,16 +113,9 @@ PyBuffer<TImage>
{
item = PySequence_Fast_GET_ITEM(shapeseq,i);
size[i] = (SizeValueType)PyLong_AsLong(item);
sizeFortran[dimension - 1 - i] = (SizeValueType)PyLong_AsLong(item);
numberOfPixels *= size[i];
}

bool isFortranContiguous = false;
if( pyBuffer.strides != NULL && pyBuffer.itemsize == pyBuffer.strides[0] )
{
isFortranContiguous = true;
}

len = numberOfPixels*numberOfComponents*pixelSize;
if ( bufferLength != len )
{
Expand All @@ -139,14 +131,6 @@ PyBuffer<TImage>
RegionType region;
region.SetIndex( start );
region.SetSize( size );
if( isFortranContiguous )
{
region.SetSize( sizeFortran );
}
else
{
region.SetSize( size );
}

PointType origin;
origin.Fill( 0.0 );
Expand Down
8 changes: 7 additions & 1 deletion src/readImage.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ AntsImage<ImageType> imageRead( std::string filename )
return myImage;
}


/**
* Create an ANTsImage from a numpy array
*
* The data array must be C-contiguous, and ordered correctly
* See "4.1.7 Importing Image Data from a Buffer"
* https://itk.org/ITKSoftwareGuide/html/Book1/ITKSoftwareGuide-Book1ch4.html
*/
template <typename ImageType>
AntsImage<ImageType> fromNumpy( nb::ndarray<nb::numpy> data, nb::tuple datashape )
{
Expand Down
22 changes: 22 additions & 0 deletions tests/test_core_ants_image_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,5 +350,27 @@ def test_image_read_write(self):
ants.image_read(tmpfile)


def test_image_from_numpy_shape(self):
arr = np.random.randn(1,9,1).astype('float32')
img = ants.from_numpy(arr)
self.assertEqual(img.shape, arr.shape)
nptest.assert_allclose(img.numpy(), arr)

arr = np.random.randn(2,3,4).astype('float32')
img = ants.from_numpy(arr)
self.assertEqual(img.shape, arr.shape)
nptest.assert_allclose(img.numpy(), arr)

# Test special case where shape is (1,N), was getting transposed
arr = np.random.randn(1,9).astype('float32')
img = ants.from_numpy(arr)
self.assertEqual(img.shape, arr.shape)
nptest.assert_allclose(img.numpy(), arr)

arr = np.random.randn(9,1).astype('float32')
img = ants.from_numpy(arr)
self.assertEqual(img.shape, arr.shape)
nptest.assert_allclose(img.numpy(), arr)

if __name__ == '__main__':
run_tests()

0 comments on commit c816d99

Please sign in to comment.