Skip to content

Commit bf53484

Browse files
committed
Merge branch 'doc-pre-release' into main-master
* doc-pre-release: (32 commits) RF: use long_description for README.rst DOC: proof reading corrections for nifti images DOC: fix see also sections for get/set q/s form DOC: correct form of Raises section DOC: clean up class and some function docstrings DOC: small rewrites / fix broken link DOC: warn about pending deprecation of data pkgs DOC: move image signature discussion up a level DOC: move / rewrite spm usecases doc DOC: remove filenames usecase document DOC: move io implementation doc to old stuff DOC: update data pkg doc for implementation RF: install sphinx in tests block DOC: document adding an image format DOC: page on adding / using test data DOC: add neuro / radio doc to tutorials RF: always close figures before plot directive DOC: add image orientation page DOC: add tutorials section DOC: add document on nifti format ... Conflicts: README.rst
2 parents adb15a3 + 7ace0af commit bf53484

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1233
-756
lines changed

.travis.yml

+12-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ matrix:
2626
- python: 2.7
2727
env:
2828
- DEPENDS="numpy==1.5.1 pydicom==0.9.7"
29+
# Documentation doctests
30+
- python: 2.7
31+
env:
32+
- DOC_DOC_TEST=1
2933
before_install:
3034
- virtualenv --python=python venv
3135
- source venv/bin/activate
@@ -59,6 +63,13 @@ script:
5963
cp ../.coveragerc .;
6064
COVER_ARGS="--with-coverage --cover-package nibabel";
6165
fi
62-
- nosetests --with-doctest $COVER_ARGS nibabel
66+
- if [ "$DOC_DOC_TEST" == "1" ]; then
67+
pip install sphinx;
68+
cd ../doc;
69+
make html;
70+
make doctest;
71+
else
72+
nosetests --with-doctest $COVER_ARGS nibabel;
73+
fi
6374
after_success:
6475
- if [ "${COVERAGE}" == "1" ]; then coveralls; fi

Changelog

+32-31
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ NiBabel Development Changelog
99
NiBabel is the successor to the much-loved PyNifti package. Here we list the
1010
releases for both packages.
1111

12-
'Close gh-' statements refer to GitHub issues that are available at::
13-
14-
http://github.com/nipy/nibabel/issues
15-
1612
The full VCS changelog is available here:
1713

1814
http://github.com/nipy/nibabel/commits/master
@@ -23,8 +19,8 @@ Releases
2319
NiBabel
2420
+++++++
2521

26-
Most work on NiBabel so far has been by Matthew Brett (MB) and Michael Hanke
27-
(MH) and Stephan Gerhard (SG).
22+
Most work on NiBabel so far has been by Matthew Brett (MB), Michael Hanke (MH)
23+
and Stephan Gerhard (SG).
2824

2925
* 2.0.0 (soon)
3026

@@ -33,30 +29,35 @@ Most work on NiBabel so far has been by Matthew Brett (MB) and Michael Hanke
3329

3430
* New feature, bugfix release with minor API breakage;
3531
* Minor API breakage: default write of NIfTI / Analyze image data offset
36-
value changed from keeping the value as read from file, to shrinking the
37-
offset the minimum necessary to make room for the header and any
38-
extensions;
39-
* Minor API breakage: data scaling in NIfTI / Analyze now set to NaN when
40-
reading images. To read the original data scaling you need to look at the
41-
``slope`` and ``inter`` properties of the image ``dataobj`` attribute;
42-
* Minor API breakage: image data offset in NIfTI / Analyze now set to zero
43-
when reading images. TO read the original data offset use the ``offset``
32+
value. The data offset is the number of bytes from the beginning of file
33+
to skip before reading the image data. Nibabel behavior changed from
34+
keeping the value as read from file, to setting the offset to zero on
35+
read, and setting the offset when writing the header. The value of the
36+
offset will now be the minimum value necessary to make room for the header
37+
and any extensions when writing the file. You can override the default
38+
offset by setting value explicitly to some value other than zero. To read
39+
the original data offset as read from the header, use the ``offset``
4440
property of the image ``dataobj`` attribute;
41+
* Minor API breakage: data scaling in NIfTI / Analyze now set to NaN when
42+
reading images. Data scaling refers to the data intercept and slope
43+
values in the NIfTI / Analyze header. To read the original data scaling
44+
you need to look at the ``slope`` and ``inter`` properties of the image
45+
``dataobj`` attribute. You can set scaling explicitly by setting the
46+
slope and intercept values in the header to values other than NaN;
4547
* New API for managing image caching; images have an ``in_memory`` property
4648
that is true if the image data has been loaded into cache, or is already
4749
an array in memory; ``get_data`` has new keyword argument ``caching`` to
4850
specify whether the cache should be filled by ``get_data``;
49-
* Images now have properties ``dataobj``, ``affine``, ``header``; we will
51+
* Images now have properties ``dataobj``, ``affine``, ``header``. We will
5052
slowly phase out the ``get_affine`` and ``get_header`` image methods;
5153
* The image ``dataobj`` can be sliced using an efficient algorithm to avoid
52-
reading unneccesary data from disk. This makes it possible to do very
54+
reading unnecessary data from disk. This makes it possible to do very
5355
efficient reads of single volumes from a time series;
54-
* You can now set NIfTI / Analyze data scaling explicitly to force this
55-
scaling to be written into the header;
5656
* NIfTI2 read / write support;
5757
* Read support for MINC2;
58-
* Much extended read support for PAR / REC, largely due to the work of Eric
59-
Larson and Gregory R. Lee giving new code, advice and code review;
58+
* Much extended read support for PAR / REC, largely due to work from Eric
59+
Larson and Gregory R. Lee on new code, advice and code review. Thanks also
60+
to Jeff Stevenson and Bennett Landman for helpful discussion;
6061
* ``parrec2nii`` script outputs images in LAS voxel orientation, which
6162
appears to be necessary for compatibility with FSL ``dtifit`` /
6263
``fslview`` diffusion analysis pipeline;
@@ -65,19 +66,19 @@ Most work on NiBabel so far has been by Matthew Brett (MB) and Michael Hanke
6566
* New function to save Freesurfer annotation files (by Github user ohinds);
6667
* Method to return MGH format ``vox2ras_tkr`` affine (Eric Larson);
6768
* A new API for reading unscaled data from NIfTI and other images, using
68-
``img.dataobj.get_unscaled()``; deprecate previous way of doing this with
69-
``read_img_data`` function;
70-
* Bug fix replacing NaN values with zero when writing floating point data as
71-
integers. If the input floating point data range did not include zero,
72-
then NaN would not get written to a value corresponding to zero in the
73-
output;
69+
``img.dataobj.get_unscaled()``. Deprecate previous way of doing this,
70+
which was to read data with the ``read_img_data`` function;
71+
* Fix for bug when replacing NaN values with zero when writing floating
72+
point data as integers. If the input floating point data range did not
73+
include zero, then NaN would not get written to a value corresponding to
74+
zero in the output;
7475
* Improvements and bug fixes to image orientation calculation and DICOM
7576
wrappers by Brendan Moloney;
76-
* Bug fix writing GIfTI files with base64 encoding that didn't match the
77-
spec, and the wrong field name for the endian code. Thanks to Basile
78-
Pinsard and Russ Poldrack for diagnosis and fixes;
79-
* Bug fix in freesurfer.read_annot with orig_ids=False when annot contains
80-
vertices with no label (Alexandre Gramfort);
77+
* Bug fixes writing GIfTI files. We were using a base64 encoding that didn't
78+
match the spec, and the wrong field name for the endian code. Thanks to
79+
Basile Pinsard and Russ Poldrack for diagnosis and fixes;
80+
* Bug fix in ``freesurfer.read_annot`` with ``orig_ids=False`` when annot
81+
contains vertices with no label (Alexandre Gramfort);
8182
* More tutorials in the documentation, including introductory tutorial on
8283
DICOM, and on coordinate systems;
8384
* Lots of code refactoring, including moving to common code-base for Python

Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -281,5 +281,8 @@ tox-stale:
281281
# installed)
282282
tox -e python25,python26,python27,python32,np-1.2.1
283283

284+
refresh-readme:
285+
$(PYTHON) tools/refresh_readme.py
286+
284287
.PHONY: orig-src pylint
285288

README.rst

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
.. -*- rest -*-
2-
.. vim:syntax=rest
2+
.. vim:syntax=rst
33
4-
|Coveralls|_
5-
6-
.. |Coveralls| image:: https://coveralls.io/repos/nipy/nibabel/badge.png?branch=master
7-
.. _Coveralls: https://coveralls.io/r/nipy/nibabel?branch=master
4+
.. image:: https://coveralls.io/repos/nipy/nibabel/badge.png?branch=master
5+
:target: https://coveralls.io/r/nipy/nibabel?branch=master
86

7+
.. Following contents should be from LONG_DESCRIPTION in nibabel/info.py
98
109
=======
1110
NiBabel

doc/Makefile

+4-2
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,14 @@ api-stamp:
4343
@echo "Build API docs...done."
4444
@touch $@
4545

46-
html: api-stamp
46+
html-only:
4747
mkdir -p $(BUILDROOT)/html $(BUILDROOT)/doctrees
4848
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDROOT)/html
4949
@echo
5050
@echo "Build finished. The HTML pages are in $(BUILDROOT)/html."
5151

52+
html: api-stamp html-only
53+
5254
pickle:
5355
mkdir -p $(BUILDROOT)/pickle $(BUILDROOT)/doctrees
5456
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDROOT)/pickle
@@ -87,7 +89,7 @@ linkcheck:
8789
@echo "Link check complete; look for any errors in the above output " \
8890
"or in $(BUILDROOT)/linkcheck/output.txt."
8991

90-
doctest:
92+
doctest: api-clean
9193
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDROOT)/doctest
9294
@echo "Testing of doctests in the sources finished, look at the " \
9395
"results in _build/doctest/output.txt."

doc/downloads

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

doc/source/.gitattributes

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.rst diff merge crlf

doc/source/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
_long_description.inc

doc/source/conf.py

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
rel = {}
3535
execfile('../../nibabel/info.py', rel)
3636

37+
# Write long description from info
38+
with open('_long_description.inc', 'wt') as fobj:
39+
fobj.write(rel['LONG_DESCRIPTION'])
40+
3741
# Add any Sphinx extension module names here, as strings. They can be extensions
3842
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
3943
extensions = ['sphinx.ext.autodoc',

doc/source/coordinate_systems.rst

-7
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,6 @@ the array.
6060
We collected an anatomical image in the same session. We can load that image
6161
and look at slices in the three axes:
6262

63-
.. plot::
64-
:nofigs:
65-
:include-source: false
66-
67-
# This guy just closes the previous figure so we don't get it twice
68-
plt.close('all')
69-
7063
.. plot::
7164
:context:
7265

doc/source/devel/add_image_format.rst

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
########################################
2+
How to add a new image format to nibabel
3+
########################################
4+
5+
These are some work-in-progress notes in the hope that they will help adding a
6+
new image format to NiBabel.
7+
8+
**********
9+
Philosophy
10+
**********
11+
12+
As usual, the general idea is to make your image as explicit and transparent
13+
as possible.
14+
15+
From the Zen of Python (``import this``), these guys spring to mind:
16+
17+
* Explicit is better than implicit.
18+
* Errors should never pass silently.
19+
* In the face of ambiguity, refuse the temptation to guess.
20+
* Now is better than never.
21+
* If the implementation is hard to explain, it's a bad idea.
22+
23+
So far we have tried to make the nibabel version of the image as close as
24+
possible to the way the user of the particular format is expecting to see it.
25+
26+
For example, the NIfTI format documents describe the image with the first
27+
dimension of the image data array being the fastest varying in memory (and on
28+
disk). Numpy defaults to having the last dimension of the array being the
29+
fastest varying in memory. We chose to have the first dimension vary fastest
30+
in memory to match the conventions in the NIfTI specification.
31+
32+
******************************
33+
Helping us to review your code
34+
******************************
35+
36+
You are likely to know the image format much much better than the rest of us
37+
do, but to help you with the code, we will need to learn. The following will
38+
really help us get up to speed:
39+
40+
#. Links in the code or in the docs to the information on the file format.
41+
For example, you'll see the canonical links for the NIfTI 2 format at the
42+
top of the :mod:`.nifti2` file, in the module docstring;
43+
#. Example files in the format; see :doc:`add_test_data`;
44+
#. Good test coverage. The tests help us see how you are expecting the code
45+
and the format to be used. We recommend writing the tests first; the tests
46+
do an excellent job in helping us and you see how the API is going to work.
47+
48+
***************************
49+
The format can be read-only
50+
***************************
51+
52+
Read-only access to a format is better than no access to a format, and often
53+
much better. For example, we can read but not write PAR / REC and MINC files.
54+
Having the code to read the files makes it easier to work with these files in
55+
Python, and easier for someone else to add the ability to write the format
56+
later.
57+
58+
*************
59+
The image API
60+
*************
61+
62+
An image should conform to the image API. See the module docstring for
63+
:mod:`.spatialimages` for a description of the API.
64+
65+
You should test whether your image does conform to the API by adding a test
66+
class for your image in :mod:`nibabel.tests.test_image_api`. For example, the
67+
API test for the PAR / REC image format looks like::
68+
69+
class TestPARRECAPI(LoadImageAPI):
70+
def loader(self, fname):
71+
return parrec.load(fname)
72+
73+
example_images = PARREC_EXAMPLE_IMAGES
74+
75+
where your work is to define the ``EXAMPLE_IMAGES`` list |--| see the
76+
:mod:`nibabel.tests.test_parrec` file for the PAR / REC example images
77+
definition.
78+
79+
****************************
80+
Where to start with the code
81+
****************************
82+
83+
There is no API requirement that a new image format inherit from the general
84+
:class:`.SpatialImage` class, but in fact all our image
85+
formats do inherit from this class. We strongly suggest you do the same, to
86+
get many simple methods implemented for free. You can always override the
87+
ones you don't want.
88+
89+
There is also a generic header class you might consider building on to contain
90+
your image metadata |--| :class:`.Header`. See that
91+
class for the header API.
92+
93+
The API does not require it, but if it is possible, it may be good to
94+
implement the image data as loaded from disk as an array proxy. See the
95+
docstring of :mod:`.arrayproxy` for a description of the API, and see the
96+
module code for an implementation of the API. You may be able to use the
97+
unmodified :class:`.ArrayProxy` class for your image type.
98+
99+
If you write a new array proxy class, add tests for the API of the class in
100+
:mod:`nibabel.tests.test_proxy_api`. See
101+
:class:`.TestPARRECAPI` for an example.
102+
103+
A nibabel image is the association of:
104+
105+
#. The image array data (as implemented by an array proxy or a numpy array);
106+
#. An affine relating the image array coordinates to an RAS+ world (see
107+
:doc:`../coordinate_systems`);
108+
#. Image metadata in the form of a header.
109+
110+
Your new image constructor may well be the default from
111+
:class:`.SpatialImage`, which looks like this::
112+
113+
def __init__(self, dataobj, affine, header=None,
114+
extra=None, file_map=None):
115+
116+
Your job when loading a file is to create:
117+
118+
#. ``dataobj`` - an array or array proxy;
119+
#. ``affine`` - 4 by 4 array relating array coordinates to world coordinates;
120+
#. ``header`` - a metadata container implementing at least ``get_data_dtype``,
121+
``get_data_shape``.
122+
123+
You will likely implement this logic in the ``from_file_map`` method of the
124+
image class. See :class:`.PARRECImage` for an example.
125+
126+
***************************************
127+
A recipe for writing a new image format
128+
***************************************
129+
130+
#. Find one or more examples images;
131+
#. Put them in ``nibabel/tests/data`` or a data submodule (see
132+
:doc:`add_test_data`);
133+
#. Create a file ``nibabel/tests/test_my_format_name_here.py``;
134+
#. Use some program that can read the format correctly to fill out the needed
135+
fields for an ``EXAMPLE_IMAGES`` list (see
136+
:mod:`nibabel.tests.test_parrec.py` for example);
137+
#. Add a test class using your ``EXAMPLE_IMAGES`` to
138+
:mod:`nibabel.tests.test_image_api`, using the PARREC image test class as
139+
an example. Now you have some failing tests |--| good job!;
140+
#. If you can, extract the metadata information from the test file, so it is
141+
small enough to fit as a small test file into ``nibabel/tests/data`` (don't
142+
forget the license);
143+
#. Write small maybe private functions to extract the header metadata from
144+
your new test file, testing these functions in
145+
``test_my_format_name_here.py``. See :mod:`.parrec` for examples;
146+
#. When that is working, try sub-classing :class:`.Header`, and working out how
147+
to make the ``__init__`` and ``from_fileboj`` methods for that class. Test
148+
in ``test_my_format_name_here.py``;
149+
#. When that is working, try sub-classing :class:`.SpatialImage` and working
150+
out how to load the file with the ``from_file_map`` class;
151+
#. Now try seeing if you can get your ``test_image_api.py`` tests to pass;
152+
#. Consider adding more test data files, maybe to a test data repository
153+
submodule (:doc:`add_test_data`). Check you can read these files correctly
154+
(see :mod:`nibabel.tests.test_parrec_data` for an example).
155+
#. Ask for advice as early and as often as you can, either with a
156+
work-in-progress pull request (the easiest way for us to review) or on
157+
the mailing list or via github issues.
158+
159+
.. include:: ../links_names.txt

0 commit comments

Comments
 (0)