Skip to content

Commit

Permalink
DOC: use get_fdata in docs
Browse files Browse the repository at this point in the history
We will soonish deprecate get_data, so remove from the docs now, so as
not to trip up new users.
  • Loading branch information
matthew-brett committed Jun 5, 2018
1 parent dfd113c commit 3fbfb6a
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 62 deletions.
4 changes: 2 additions & 2 deletions doc/source/coordinate_systems.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ We can load up the EPI image to get the image data array:

>>> import nibabel as nib
>>> epi_img = nib.load('downloads/someones_epi.nii.gz')
>>> epi_img_data = epi_img.get_data()
>>> epi_img_data = epi_img.get_fdata()
>>> epi_img_data.shape
(53, 61, 33)

Expand Down Expand Up @@ -64,7 +64,7 @@ and look at slices in the three axes:
:context:

>>> anat_img = nib.load('downloads/someones_anatomy.nii.gz')
>>> anat_img_data = anat_img.get_data()
>>> anat_img_data = anat_img.get_fdata()
>>> anat_img_data.shape
(57, 67, 56)
>>> show_slices([anat_img_data[28, :, :],
Expand Down
6 changes: 3 additions & 3 deletions doc/source/devel/modified_images.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ flag when anyone asks for the data, on the basis that the user may then
do something to the data and you can't know if they have::

img = nibabel.load('some_image.nii')
data = img.get_data()
data = img.get_fdata()
data[:] = 0
img2 = nibabel.load('some_image.nii')
assert not np.all(img2.get_data() == img.get_data())
assert not np.all(img2.get_fdata() == img.get_fdata())

The image consists of the data, the affine and a header. In order to
keep track of the header and affine, we could cache them when loading
Expand All @@ -96,7 +96,7 @@ When we need to know whether the image object and image file correspond, we
could check the current header and current affine (the header may be separate
from the affine for an SPM Analyze image) against their cached copies, if they
are the same and the 'dirty' flag has not been set by a previous call to
``get_data()``, we know that the image file does correspond to the image
``get_fdata()``, we know that the image file does correspond to the image
object.

This may be OK for small bits of memory like the affine and the header,
Expand Down
2 changes: 1 addition & 1 deletion doc/source/gettingstarted.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ This information is available without the need to load anything of the main
image data into the memory. Of course there is also access to the image data as
a NumPy_ array

>>> data = img.get_data()
>>> data = img.get_fdata()
>>> data.shape
(128, 96, 24, 2)
>>> type(data)
Expand Down
62 changes: 31 additions & 31 deletions doc/source/images_and_memory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ disk.

Nibabel does not load the image array from the proxy when you ``load`` the
image. It waits until you ask for the array data. The standard way to ask
for the array data is to call the ``get_data()`` method:
for the array data is to call the ``get_fdata()`` method:

>>> data = img.get_data()
>>> data = img.get_fdata()
>>> data.shape
(128, 96, 24, 2)

We also saw in :ref:`proxies-caching` that this call to ``get_data()`` will
We also saw in :ref:`proxies-caching` that this call to ``get_fdata()`` will
(by default) load the array data into an internal image cache. The image
returns the cached copy on the next call to ``get_data()``:
returns the cached copy on the next call to ``get_fdata()``:

>>> data_again = img.get_data()
>>> data_again = img.get_fdata()
>>> data is data_again
True

Expand Down Expand Up @@ -64,7 +64,7 @@ in cache, and True when it is in cache:
>>> img = nib.load(example_file)
>>> img.in_memory
False
>>> data = img.get_data()
>>> data = img.get_fdata()
>>> img.in_memory
True

Expand All @@ -73,10 +73,10 @@ True
Using ``uncache``
*****************

As y'all know, the proxy image has the array in cache, ``get_data()`` returns
As y'all know, the proxy image has the array in cache, ``get_fdata()`` returns
the cached array:

>>> data_again = img.get_data()
>>> data_again = img.get_fdata()
>>> data_again is data # same array returned from cache
True

Expand All @@ -85,34 +85,34 @@ You can uncache a proxy image with the ``uncache()`` method:
>>> img.uncache()
>>> img.in_memory
False
>>> data_once_more = img.get_data()
>>> data_once_more = img.get_fdata()
>>> data_once_more is data # a new copy read from disk
False

``uncache()`` has no effect if the image is an array image, or if the cache is
already empty.

You need to be careful when you modify arrays returned by ``get_data()`` on
You need to be careful when you modify arrays returned by ``get_fdata()`` on
proxy images, because ``uncache`` will then change the result you get back
from ``get_data()``:
from ``get_fdata()``:

>>> proxy_img = nib.load(example_file)
>>> data = proxy_img.get_data() # array cached and returned
>>> data = proxy_img.get_fdata() # array cached and returned
>>> data[0, 0, 0, 0]
0
0.0
>>> data[0, 0, 0, 0] = 99 # modify returned array
>>> data_again = proxy_img.get_data() # return cached array
>>> data_again = proxy_img.get_fdata() # return cached array
>>> data_again[0, 0, 0, 0] # cached array modified
99
99.0

So far the proxy image behaves the same as an array image. ``uncache()`` has
no effect on an array image, but it does have an effect on the returned array
of a proxy image:

>>> proxy_img.uncache() # cached array discarded from proxy image
>>> data_once_more = proxy_img.get_data() # new copy of array loaded
>>> data_once_more = proxy_img.get_fdata() # new copy of array loaded
>>> data_once_more[0, 0, 0, 0] # array modifications discarded
0
0.0

*************
Saving memory
Expand All @@ -126,8 +126,8 @@ use the ``uncache()`` method:

>>> img.uncache()

Use the array proxy instead of ``get_data()``
=============================================
Use the array proxy instead of ``get_fdata()``
==============================================

The ``dataobj`` property of a proxy image is an array proxy. We can ask the
proxy to return the array directly by passing ``dataobj`` to the numpy
Expand All @@ -145,47 +145,47 @@ This also works for array images, because ``np.asarray`` returns the array:
>>> type(data_array)
<... 'numpy.ndarray'>

If you want to avoid caching you can avoid ``get_data()`` and always use
If you want to avoid caching you can avoid ``get_fdata()`` and always use
``np.asarray(img.dataobj)``.

Use the ``caching`` keyword to ``get_data()``
=============================================
Use the ``caching`` keyword to ``get_fdata()``
==============================================

The default behavior of the ``get_data()`` function is to always fill the
The default behavior of the ``get_fdata()`` function is to always fill the
cache, if it is empty. This corresponds to the default ``'fill'`` value
to the ``caching`` keyword. So, this:

>>> proxy_img = nib.load(example_file)
>>> data = proxy_img.get_data() # default caching='fill'
>>> data = proxy_img.get_fdata() # default caching='fill'
>>> proxy_img.in_memory
True

is the same as this:

>>> proxy_img = nib.load(example_file)
>>> data = proxy_img.get_data(caching='fill')
>>> data = proxy_img.get_fdata(caching='fill')
>>> proxy_img.in_memory
True

Sometimes you may want to avoid filling the cache, if it is empty. In this
case, you can use ``caching='unchanged'``:

>>> proxy_img = nib.load(example_file)
>>> data = proxy_img.get_data(caching='unchanged')
>>> data = proxy_img.get_fdata(caching='unchanged')
>>> proxy_img.in_memory
False

``caching='unchanged'`` will leave the cache full if it is already full.

>>> data = proxy_img.get_data(caching='fill')
>>> data = proxy_img.get_fdata(caching='fill')
>>> proxy_img.in_memory
True
>>> data = proxy_img.get_data(caching='unchanged')
>>> data = proxy_img.get_fdata(caching='unchanged')
>>> proxy_img.in_memory
True

See the :meth:`get_data() docstring
<nibabel.spatialimages.SpatialImage.get_data>` for more detail.
See the :meth:`get_fdata() docstring
<nibabel.spatialimages.SpatialImage.get_fdata>` for more detail.

**********************
Saving time and memory
Expand All @@ -202,7 +202,7 @@ For example, let us say you only wanted the second volume from the example
dataset. You could do this:

>>> proxy_img = nib.load(example_file)
>>> data = proxy_img.get_data()
>>> data = proxy_img.get_fdata()
>>> data.shape
(128, 96, 24, 2)
>>> vol1 = data[..., 1]
Expand Down
2 changes: 1 addition & 1 deletion doc/source/neuro_radio_conventions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ showing the middle slice of :download:`an image
[ 0. , 2.75, 0. , -91. ],
[ 0. , 0. , 2.75, -91. ],
[ 0. , 0. , 0. , 1. ]])
>>> img_data = img.get_data()
>>> img_data = img.get_fdata()
>>> a_slice = img_data[:, :, 28]
>>> # Need transpose to put first axis left-right, second bottom-top
>>> plt.imshow(a_slice.T, cmap="gray", origin="lower") # doctest: +SKIP
Expand Down
39 changes: 28 additions & 11 deletions doc/source/nibabel_images.rst
Original file line number Diff line number Diff line change
Expand Up @@ -220,21 +220,38 @@ False
Getting the image data the easy way
===================================

For either type of image (array or proxy) you can always get the data with
the :meth:`get_data() <nibabel.spatialimages.SpatialImage.get_data>` method.
For either type of image (array or proxy) you can always get the data with the
:meth:`get_fdata() <nibabel.spatialimages.SpatialImage.get_fdata>` method.

For the array image, ``get_data()`` just returns the data array:
For the array image, ``get_fdata()`` just returns the data array, if it's already the required floating point type (default 64-bit float). If it isn't that type, ``get_fdata()`` casts it to one:

>>> image_data = array_img.get_data()
>>> image_data = array_img.get_fdata()
>>> image_data.shape
(2, 3, 4)
>>> image_data is array_data
>>> image_data.dtype == np.dtype(np.float64)
True

For the proxy image, the ``get_data()`` method fetches the array data from
The cast to floating point means the array is not the one attached to the image:

>>> image_data is array_img.dataobj
False

Here's an image backed by a floating point array:

>>> farray_img = nib.Nifti1Image(image_data.astype(np.float64), affine)
>>> farray_data = farray_img.get_fdata()
>>> farray_data.dtype == np.dtype(np.float64)
True

There was no cast, so the array returned is exactly the array attached to the image:

>>> image_data is array_img.dataobj
False

For the proxy image, the ``get_fdata()`` method fetches the array data from
disk using the proxy, and returns the array.

>>> image_data = img.get_data()
>>> image_data = img.get_fdata()
>>> image_data.shape
(128, 96, 24, 2)

Expand All @@ -249,12 +266,12 @@ Proxies and caching
===================

You may not want to keep loading the image data off disk every time
you call ``get_data()`` on a proxy image. By default, when you call
``get_data()`` the first time on a proxy image, the image object keeps a
cached copy of the loaded array. The next time you call ``img.get_data()``,
you call ``get_fdata()`` on a proxy image. By default, when you call
``get_fdata()`` the first time on a proxy image, the image object keeps a
cached copy of the loaded array. The next time you call ``img.get_fdata()``,
the image returns the array from cache rather than loading it from disk again.

>>> data_again = img.get_data()
>>> data_again = img.get_fdata()

The returned data is the same (cached) copy we returned before:

Expand Down
14 changes: 5 additions & 9 deletions doc/source/old/examples.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ previously created in a separate file. First, we open the file:
Now we select the first ten volumes and store them to another file, while
preserving as much header information as possible

>>> nim2 = nib.Nifti1Image(nim.get_data()[..., :10],
>>> nim2 = nib.Nifti1Image(nim.get_fdata()[..., :10],
... nim.get_affine(),
... nim.header)
>>> print nim2.header['dim']
Expand All @@ -127,7 +127,7 @@ Linear detrending of timeseries (SciPy module is required for this example)
===========================================================================

Let's load another 4d NIfTI file and perform a linear detrending, by fitting
a straight line to the timeseries of each voxel and substract that fit from
a straight line to the timeseries of each voxel and subtract that fit from
the data. Although this might sound complicated at first, thanks to the
excellent SciPy module it is just a few lines of code. For this example we
will first create a NIfTI image with just a single voxel and 50 timepoints
Expand All @@ -139,15 +139,11 @@ will first create a NIfTI image with just a single voxel and 50 timepoints
>>> print nim.header['dim']
[ 4 1 1 1 50 1 1 1]

Depending on the datatype of the input image the detrending process might
change the datatype from integer to float. As operations that change the
(binary) size of the NIfTI image are not supported, we need to make a copy
of the data and later create a new NIfTI image. Remember that the array has the
time axis as its first dimension (in contrast to the NIfTI file where it is
the 4th).
Remember that the array has the time axis as its first dimension (in contrast
to the NIfTI file where it is the 4th).

>>> from scipy import signal
>>> data_detrended = signal.detrend(nim.get_data(), axis=0)
>>> data_detrended = signal.detrend(nim.get_fdata(), axis=0)

Finally, create a new NIfTI image using header information from the original
source image.
Expand Down
2 changes: 1 addition & 1 deletion doc/source/old/orientation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ the affine after loading, as in::
img = nibabel.load('some_image.img')
aff = img.get_affine()
x_flipper = np.diag([-1,1,1,1])
lr_img = nibabel.Nifti1Image(img.get_data, np.dot(x_flipper, aff), img.header)
lr_img = nibabel.Nifti1Image(img.get_fdata(), np.dot(x_flipper, aff), img.header)

Affines for Analyze, SPM analyze, and NIFTI
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
6 changes: 3 additions & 3 deletions doc/source/scripts/make_coord_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
t1_img, t2_img = imgs

# Make fake localizer
data = t1_img.get_data()
data = t1_img.get_fdata()
n_x, n_y, n_z = img.shape
mid_x = round(n_x / 2)

Expand Down Expand Up @@ -171,7 +171,7 @@ def vx2mm(pts):
# resample, preserving affine
epi_cmap = nca.vox2mni(epi_vox2mm)
epi = rsm.resample(t2_img, epi_cmap, np.eye(4), epi_vox_shape)
epi_data = epi.get_data()
epi_data = epi.get_fdata()
# Do the same kind of thing for the anatomical scan
anat_vox_sizes = [2.75, 2.75, 2.75]
anat_scale = npl.inv(np.diag(anat_vox_sizes + [1]))
Expand All @@ -183,7 +183,7 @@ def vx2mm(pts):
[data.shape[0], anat_x_len, anat_y_len], anat_vox_sizes))
anat_cmap = nca.vox2mni(anat_vox2mm)
anat = rsm.resample(t1_img, anat_cmap, np.eye(4), anat_vox_shape)
anat_data = anat.get_data()
anat_data = anat.get_fdata()

save_plot()
nipy.save_image(epi, 'someones_epi.nii.gz', dtype_from='uint8')
Expand Down

0 comments on commit 3fbfb6a

Please sign in to comment.