Skip to content

Commit f797e1d

Browse files
committed
DOC: move nibabel images page, fix doctests
Move nibabel image description page into main documentation. Link downloads directory into docs directory to make doctests work. Fix up doctests to be a little more robust with some doctest directives. Put nibabel images page into top level of manual.
1 parent a9132b1 commit f797e1d

File tree

4 files changed

+3
-242
lines changed

4 files changed

+3
-242
lines changed

doc/downloads

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
source/downloads

doc/source/devel/image_design.rst

+1-242
Original file line numberDiff line numberDiff line change
@@ -2,245 +2,4 @@
22
The nibabel image object
33
########################
44

5-
A nibabel image object is the association of three things:
6-
7-
* an N-D array containing the image *data*
8-
* a (4, 4) *affine* matrix mapping array coordinates to coordinates in some real
9-
world
10-
* image metadata in the form of a *header*
11-
12-
*****************
13-
Header and affine
14-
*****************
15-
16-
There's an example image contained in the nibabel distribution
17-
18-
>>> import os
19-
>>> import numpy as np
20-
>>> np.set_printoptions(precision=2, suppress=True)
21-
22-
>>> import nibabel as nib
23-
>>> from nibabel.testing import data_path
24-
>>> example_file = os.path.join(data_path, 'example4d.nii.gz')
25-
>>> img = nib.load(example_file)
26-
27-
You can get direct access to the *affine* and the *header* with:
28-
29-
>>> print(img.affine)
30-
[[ -2. 0. 0. 117.86]
31-
[ -0. 1.97 -0.36 -35.72]
32-
[ 0. 0.32 2.17 -7.25]
33-
[ 0. 0. 0. 1. ]]
34-
>>> print(img.header)
35-
<class 'nibabel.nifti1.Nifti1Header'> object, endian='<'
36-
sizeof_hdr : 348
37-
data_type : b''
38-
db_name : b''
39-
extents : 0
40-
session_error : 0
41-
regular : b'r'
42-
dim_info : 57
43-
dim : [ 4 128 96 24 2 1 1 1]
44-
intent_p1 : 0.0
45-
intent_p2 : 0.0
46-
intent_p3 : 0.0
47-
intent_code : none
48-
datatype : int16
49-
bitpix : 16
50-
slice_start : 0
51-
pixdim : [ -1. 2. 2. 2.2 2000. 1. 1. 1. ]
52-
vox_offset : 416.0
53-
scl_slope : 1.0
54-
scl_inter : 0.0
55-
slice_end : 23
56-
slice_code : unknown
57-
xyzt_units : 10
58-
cal_max : 1162.0
59-
cal_min : 0.0
60-
slice_duration : 0.0
61-
toffset : 0.0
62-
glmax : 0
63-
glmin : 0
64-
descrip : b'FSL3.3\x00 v2.25 NIfTI-1 Single file format'
65-
aux_file : b''
66-
qform_code : scanner
67-
sform_code : scanner
68-
quatern_b : -1.9451068140294884e-26
69-
quatern_c : -0.9967085123062134
70-
quatern_d : -0.0810687392950058
71-
qoffset_x : 117.8551025390625
72-
qoffset_y : -35.72294235229492
73-
qoffset_z : -7.248798370361328
74-
srow_x : [ -2. 0. 0. 117.86]
75-
srow_y : [ -0. 1.97 -0.36 -35.72]
76-
srow_z : [ 0. 0.32 2.17 -7.25]
77-
intent_name : b''
78-
magic : b'n+1'
79-
80-
****************
81-
Reading the data
82-
****************
83-
84-
We defend the data from you a little, because we want to be able to load images
85-
from disk without automatically loading all the data. Images loaded like this
86-
are called *proxy images* because the data in the image is not yet an array, but
87-
an placeholder or *proxy* for the array. You can get the object holding the
88-
image data with:
89-
90-
>>> dataobj = img.dataobj
91-
92-
Because this image has been loaded from disk, ``dataobj`` is not the array
93-
itself, but a *proxy* for the array that lets you get to the array data with:
94-
95-
>>> data = np.asarray(dataobj)
96-
>>> data.shape
97-
(128, 96, 24, 2)
98-
99-
If you created the image from an array in memory, ``dataobj`` will be the
100-
data array:
101-
102-
>>> arr = np.arange(24, dtype=np.int16).reshape((2, 3, 4))
103-
>>> arr_img = nib.Nifti1Image(arr, np.eye(4))
104-
>>> arr_img.dataobj is arr
105-
True
106-
107-
For either type of image (array or proxy) you can always get the data with:
108-
109-
>>> data = img.get_data()
110-
>>> data.shape
111-
(128, 96, 24, 2)
112-
>>> data = arr_img.get_data()
113-
>>> data.shape
114-
(2, 3, 4)
115-
116-
If you created ``img`` using an array in memory, ``img.get_data()`` just returns
117-
the data array:
118-
119-
>>> data = arr_img.get_data()
120-
>>> data is arr_img.dataobj
121-
True
122-
123-
If you loaded ``img`` from disk, and have a proxy image, then the the
124-
``get_data()`` method gets the data from the proxy, and returns the array.
125-
126-
>>> proxy_img = nib.load(example_file)
127-
>>> type(proxy_img.dataobj)
128-
<class 'nibabel.arrayproxy.ArrayProxy'>
129-
>>> data = proxy_img.get_data()
130-
>>> data.shape
131-
(128, 96, 24, 2)
132-
>>> data is proxy_img.dataobj
133-
False
134-
135-
After a call to ``get_data()``, the proxy image keeps a cached copy of the
136-
loaded array, so the next time you call ``img.get_data()``, we do not have to
137-
load the array off the disk again.
138-
139-
>>> data_again = proxy_img.get_data()
140-
>>> data is data_again
141-
True
142-
143-
If you call ``img.get_data()`` on a proxy image, the image object will get much
144-
larger in memory, because the image now stores a copy of the loaded array. If
145-
you want to avoid this memory load you can:
146-
147-
* use ``np.asarray(img.dataobj)`` instead of ``img.get_data()`` or
148-
* run ``img.uncache()`` after calling ``img.get_data()``. This deletes the copy
149-
of the array inside the image, so the next time you call ``img.get_data()``
150-
the image has to load the data from disk again.
151-
152-
Here is ``uncache`` in action:
153-
154-
>>> data_again = proxy_img.get_data()
155-
>>> data is data_again
156-
True
157-
>>> proxy_img.uncache()
158-
>>> data_once_more = proxy_img.get_data()
159-
>>> data_once_more is data_again
160-
False
161-
162-
This means you need to be careful when you modify arrays returned by
163-
``get_data()`` on proxy images, because ``uncache`` will then change the result
164-
you get back from ``get_data()``:
165-
166-
>>> data = proxy_img.get_data()
167-
>>> data[0, 0, 0, 0]
168-
0
169-
>>> data[0, 0, 0, 0] = 99
170-
>>> data_again = proxy_img.get_data()
171-
>>> data_again[0, 0, 0, 0]
172-
99
173-
>>> proxy_img.uncache()
174-
>>> data_once_more = proxy_img.get_data()
175-
>>> data_once_more[0, 0, 0, 0]
176-
0
177-
178-
******************
179-
Loading and saving
180-
******************
181-
182-
The ``save`` and ``load`` functions in nibabel should do all the work for you:
183-
184-
>>> img = nib.load(example_file)
185-
>>> img.shape
186-
(128, 96, 24, 2)
187-
>>> import tempfile
188-
>>> temp_fname = tempfile.mktemp('.nii')
189-
>>> nib.save(img, temp_fname)
190-
>>> img_again = nib.load(temp_fname)
191-
>>> img_again.shape
192-
(128, 96, 24, 2)
193-
>>> os.unlink(temp_fname)
194-
195-
You can also use the ``to_filename`` method:
196-
197-
>>> temp_fname = tempfile.mktemp('.nii')
198-
>>> img.to_filename(temp_fname)
199-
>>> img_again = nib.load(temp_fname)
200-
>>> img_again.shape
201-
(128, 96, 24, 2)
202-
>>> os.unlink(temp_fname)
203-
204-
You can get and set the filename with ``get_filename()`` and ``set_filename()``:
205-
206-
>>> img.set_filename('my_image.nii')
207-
>>> img.get_filename()
208-
'my_image.nii'
209-
210-
***************************
211-
Details of files and images
212-
***************************
213-
214-
If an image can be loaded or saved on disk, the image will have an attribute
215-
called ``file_map``. ``img.file_map`` is a dictionary where the keys are the
216-
names of the files that the image uses to load / save on disk, and the values
217-
are ``FileHolder`` objects, that usually contain the filenames that the image
218-
has been loaded from or saved to. In the case of a NiFTI1 single file, this is
219-
just a single image file with a ``.nii`` extension:
220-
221-
>>> list(proxy_img.file_map)
222-
['image']
223-
>>> proxy_img.file_map['image'].filename
224-
'/Users/mb312/dev_trees/nibabel/nibabel/tests/data/example4d.nii.gz'
225-
226-
Other file types need more than one file to make up the image. The NiFTI1 pair
227-
type is one example:
228-
229-
>>> pair_img = nib.Nifti1Pair(arr, np.eye(4))
230-
>>> sorted(pair_img.file_map)
231-
['header', 'image']
232-
233-
The older Analyze format is another:
234-
235-
>>> ana_img = nib.AnalyzeImage(arr, np.eye(4))
236-
>>> sorted(ana_img.file_map)
237-
['header', 'image']
238-
239-
It is ``img.file_map`` that gets changed when you use ``set_filename`` or
240-
``to_filename``:
241-
242-
>>> ana_img.set_filename('another_image.img')
243-
>>> ana_img.file_map['image'].filename
244-
'another_image.img'
245-
>>> ana_img.file_map['header'].filename
246-
'another_image.hdr'
5+
The latest version of this page is now at :doc:`../nibabel_images`.

doc/source/manual.rst

+1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ NiBabel Manual
88

99
installation
1010
gettingstarted
11+
nibabel_images
1112
legal
1213
changelog

doc/source/nibabel_images.rst

7.07 KB
Binary file not shown.

0 commit comments

Comments
 (0)