diff -Nru nibabel-1.2.2/Changelog nibabel-1.3.0/Changelog --- nibabel-1.2.2/Changelog 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/Changelog 2012-09-11 21:02:24.000000000 +0000 @@ -28,6 +28,15 @@ Krish Subramaniam, Alexandre Gramfort, Cindee Madison, Félix C. Morency, Christian Haselgrove. +* 1.3.0 (Tuesday 11 September 2012) + + * New feature and bugfix release + * Add ability to write Freesurfer triangle files (Chris Johnson) + * Relax threshold for detecting rank deficient affines in orientation + detection (JB Poline) + * Fix for DICOM slice normal numerical error (issue #137) (Brendan Moloney) + * Fix for Python 3 error when writing zero bytes for offset padding + * 1.2.2 (Wednesday 27 June 2012) * Bugfix release diff -Nru nibabel-1.2.2/debian/changelog nibabel-1.3.0/debian/changelog --- nibabel-1.2.2/debian/changelog 2012-06-27 18:53:26.000000000 +0000 +++ nibabel-1.3.0/debian/changelog 2014-03-21 01:16:25.000000000 +0000 @@ -1,3 +1,17 @@ +nibabel (1.3.0-2) sid; urgency=medium + + * Upload to sid (the freeze is long over ;)) + * debian/control + - boosted policy to 3.9.5 + + -- Yaroslav Halchenko Thu, 20 Mar 2014 21:08:09 -0400 + +nibabel (1.3.0-1) experimental; urgency=low + + * New upstream release + + -- Yaroslav Halchenko Tue, 11 Sep 2012 18:04:46 -0400 + nibabel (1.2.2-1) unstable; urgency=low * New upstream bugfix release diff -Nru nibabel-1.2.2/debian/control nibabel-1.3.0/debian/control --- nibabel-1.2.2/debian/control 2012-06-27 18:53:26.000000000 +0000 +++ nibabel-1.3.0/debian/control 2014-03-21 01:16:25.000000000 +0000 @@ -4,7 +4,7 @@ Maintainer: NeuroDebian Team Uploaders: Michael Hanke , Yaroslav Halchenko Build-Depends: debhelper (>= 7.2.18), python-all (>= 2.5), python-support (>= 0.6), python-numpy (>= 1.2), python-nose, python-scipy, help2man, python-sphinx, python-fuse -Standards-Version: 3.9.3 +Standards-Version: 3.9.5 Homepage: http://nipy.sourceforge.net/nibabel Vcs-Browser: http://git.debian.org/?p=pkg-exppsy/pynifti.git Vcs-Git: git://git.debian.org/git/pkg-exppsy/pynifti.git diff -Nru nibabel-1.2.2/doc/source/changelog.rst nibabel-1.3.0/doc/source/changelog.rst --- nibabel-1.2.2/doc/source/changelog.rst 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/doc/source/changelog.rst 2012-09-11 21:02:24.000000000 +0000 @@ -28,6 +28,15 @@ Krish Subramaniam, Alexandre Gramfort, Cindee Madison, Félix C. Morency, Christian Haselgrove. +* 1.3.0 (Tuesday 11 September 2012) + + * New feature and bugfix release + * Add ability to write Freesurfer triangle files (Chris Johnson) + * Relax threshold for detecting rank deficient affines in orientation + detection (JB Poline) + * Fix for DICOM slice normal numerical error (issue #137) (Brendan Moloney) + * Fix for Python 3 error when writing zero bytes for offset padding + * 1.2.2 (Wednesday 27 June 2012) * Bugfix release diff -Nru nibabel-1.2.2/doc/source/devel/make_release.rst nibabel-1.3.0/doc/source/devel/make_release.rst --- nibabel-1.2.2/doc/source/devel/make_release.rst 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/doc/source/devel/make_release.rst 2012-09-11 21:02:24.000000000 +0000 @@ -55,10 +55,14 @@ are as complete as possible and that every contributor was recognized. * Use the opportunity to update the ``.mailmap`` file if there are any duplicate - authors listed from ``git shortlog``. + authors listed from ``git shortlog -nse``. * Check the ``long_description`` in ``nibabel/info.py``. Check it matches the - ``README`` in the root directory. + ``README`` in the root directory. Check the output of:: + + rst2html.py README.rst > ~/tmp/readme.html + + becase this will be the output used by pypi_ * Do a final check on the `nipy buildbot`_ diff -Nru nibabel-1.2.2/.mailmap nibabel-1.3.0/.mailmap --- nibabel-1.2.2/.mailmap 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/.mailmap 2012-09-11 21:02:24.000000000 +0000 @@ -13,7 +13,10 @@ Bertrand Thirion bthirion Stephan Gerhard Stephan Gerhard Christian Haselgrove Christian Haselgrove -CindeeM cindeem +Cindee Madison CindeeM +Cindee Madison cindeem +Ian Nimmo-Smith Ian Nimmo-Smith +Jean-Baptiste Poline jbpoline Félix C. Morency Felix C. Morency Félix C. Morency Félix C. Morency Félix C. Morency Krish Subramaniam Krish Subramaniam diff -Nru nibabel-1.2.2/nibabel/analyze.py nibabel-1.3.0/nibabel/analyze.py --- nibabel-1.2.2/nibabel/analyze.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/analyze.py 2012-09-11 21:02:24.000000000 +0000 @@ -962,11 +962,11 @@ >>> affine = np.diag([1.0,2.0,3.0,1.0]) >>> img = AnalyzeImage(data, affine) >>> hdr = img.get_header() - >>> img.shape - (2, 3, 4) + >>> img.shape == (2, 3, 4) + True >>> img.update_header() - >>> hdr.get_data_shape() - (2, 3, 4) + >>> hdr.get_data_shape() == (2, 3, 4) + True >>> hdr.get_zooms() (1.0, 2.0, 3.0) ''' diff -Nru nibabel-1.2.2/nibabel/COMMIT_INFO.txt nibabel-1.3.0/nibabel/COMMIT_INFO.txt --- nibabel-1.2.2/nibabel/COMMIT_INFO.txt 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/COMMIT_INFO.txt 2012-09-11 21:02:24.000000000 +0000 @@ -1,6 +1,6 @@ # This is an ini file that may contain information about the code state [commit hash] # The line below may contain a valid hash if it has been substituted during 'git archive' -archive_subst_hash=1867874 +archive_subst_hash=89feca8 # This line may be modified by the install process install_hash= diff -Nru nibabel-1.2.2/nibabel/data.py nibabel-1.3.0/nibabel/data.py --- nibabel-1.2.2/nibabel/data.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/data.py 2012-09-11 21:02:24.000000000 +0000 @@ -18,7 +18,16 @@ 'path to the package correctly?') -class DataError(OSError): +class DataError(Exception): + pass + + +class BomberError(DataError, AttributeError): + """ Error when trying to access Bomber instance + + Should be instance of AttributeError to allow Python 3 inspect to do various + ``hasattr`` checks without raising an error + """ pass @@ -302,7 +311,7 @@ def __getattr__(self, attr_name): ''' Raise informative error accessing not-found attributes ''' - raise DataError( + raise BomberError( 'Trying to access attribute "%s" ' 'of non-existent data "%s"\n\n%s\n' % (attr_name, self.name, self.msg)) diff -Nru nibabel-1.2.2/nibabel/ecat.py nibabel-1.3.0/nibabel/ecat.py --- nibabel-1.2.2/nibabel/ecat.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/ecat.py 2012-09-11 21:02:24.000000000 +0000 @@ -797,11 +797,11 @@ >>> ecat_file = os.path.join(nibabel_dir,'tests','data','tinypet.v') >>> img = ecat.load(ecat_file) >>> frame0 = img.get_frame(0) - >>> frame0.shape - (10, 10, 3) + >>> frame0.shape == (10, 10, 3) + True >>> data4d = img.get_data() - >>> data4d.shape - (10, 10, 3, 1) + >>> data4d.shape == (10, 10, 3, 1) + True """ self._subheader = subheader self._mlist = mlist diff -Nru nibabel-1.2.2/nibabel/eulerangles.py nibabel-1.3.0/nibabel/eulerangles.py --- nibabel-1.2.2/nibabel/eulerangles.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/eulerangles.py 2012-09-11 21:02:24.000000000 +0000 @@ -116,8 +116,8 @@ >>> yrot = -0.1 >>> xrot = 0.2 >>> M = euler2mat(zrot, yrot, xrot) - >>> M.shape - (3, 3) + >>> M.shape == (3, 3) + True The output rotation matrix is equal to the composition of the individual rotations diff -Nru nibabel-1.2.2/nibabel/externals/netcdf.py nibabel-1.3.0/nibabel/externals/netcdf.py --- nibabel-1.2.2/nibabel/externals/netcdf.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/externals/netcdf.py 2012-09-11 21:02:24.000000000 +0000 @@ -122,8 +122,8 @@ >>> time = f.variables['time'] >>> time.units #23dt next : bytes 'days since 2008-01-01' - >>> print time.shape - (10,) + >>> time.shape == (10,) + True >>> print time[-1] 9 >>> f.close() diff -Nru nibabel-1.2.2/nibabel/freesurfer/__init__.py nibabel-1.3.0/nibabel/freesurfer/__init__.py --- nibabel-1.2.2/nibabel/freesurfer/__init__.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/freesurfer/__init__.py 2012-09-11 21:02:24.000000000 +0000 @@ -2,5 +2,5 @@ """ from io import read_geometry, read_morph_data, \ - read_annot, read_label + read_annot, read_label, write_geometry from mghformat import load, save, MGHImage diff -Nru nibabel-1.2.2/nibabel/freesurfer/io.py nibabel-1.3.0/nibabel/freesurfer/io.py --- nibabel-1.2.2/nibabel/freesurfer/io.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/freesurfer/io.py 2012-09-11 21:02:24.000000000 +0000 @@ -1,6 +1,8 @@ from __future__ import with_statement import numpy as np +import getpass +import time def _fread3(fobj): @@ -93,6 +95,37 @@ return coords, faces +def write_geometry(filepath, coords, faces, create_stamp=None): + """Write a triangular format Freesurfer surface mesh. + + Parameters + ---------- + filepath : str + Path to surface file + coords : numpy array + nvtx x 3 array of vertex (x, y, z) coordinates + faces : numpy array + nfaces x 3 array of defining mesh triangles + create_stamp : str + User/time stamp (default: "created by on ") + """ + magic_bytes = np.array([255, 255, 254], dtype=np.uint8) + + if create_stamp is None: + create_stamp = "created by %s on %s" % (getpass.getuser(), + time.ctime()) + + with open(filepath, 'wb') as fobj: + magic_bytes.tofile(fobj) + fobj.write("%s\n\n" % create_stamp) + + np.array([coords.shape[0], faces.shape[0]], dtype='>i4').tofile(fobj) + + # Coerce types, just to be safe + coords.astype('>f4').reshape(-1).tofile(fobj) + faces.astype('>i4').reshape(-1).tofile(fobj) + + def read_morph_data(filepath): """Read a Freesurfer morphometry data file. diff -Nru nibabel-1.2.2/nibabel/freesurfer/tests/test_io.py nibabel-1.3.0/nibabel/freesurfer/tests/test_io.py --- nibabel-1.2.2/nibabel/freesurfer/tests/test_io.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/freesurfer/tests/test_io.py 2012-09-11 21:02:24.000000000 +0000 @@ -1,11 +1,17 @@ +from __future__ import with_statement import os from os.path import join as pjoin +import getpass +import time + +from nibabel.tmpdirs import InTemporaryDirectory from nose.tools import assert_true import numpy as np from numpy.testing import assert_equal -from .. import read_geometry, read_morph_data, read_annot, read_label +from .. import read_geometry, read_morph_data, read_annot, read_label, \ + write_geometry have_freesurfer = True @@ -36,6 +42,31 @@ assert_equal(0, faces.min()) assert_equal(coords.shape[0], faces.max() + 1) + # Test equivalence of freesurfer- and nibabel-generated triangular files + # with respect to read_geometry() + with InTemporaryDirectory(): + surf_path = 'test' + create_stamp = "created by %s on %s" % (getpass.getuser(), + time.ctime()) + write_geometry(surf_path, coords, faces, create_stamp) + + coords2, faces2 = read_geometry(surf_path) + + with open(surf_path, 'rb') as fobj: + magic = np.fromfile(fobj, ">u1", 3) + read_create_stamp = fobj.readline().rstrip('\n') + + assert_equal(create_stamp, read_create_stamp) + + np.testing.assert_array_equal(coords, coords2) + np.testing.assert_array_equal(faces, faces2) + + # Validate byte ordering + coords_swapped = coords.byteswap().newbyteorder() + faces_swapped = faces.byteswap().newbyteorder() + np.testing.assert_array_equal(coords_swapped, coords) + np.testing.assert_array_equal(faces_swapped, faces) + @freesurfer_test def test_morph_data(): diff -Nru nibabel-1.2.2/nibabel/funcs.py nibabel-1.3.0/nibabel/funcs.py --- nibabel-1.2.2/nibabel/funcs.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/funcs.py 2012-09-11 21:02:24.000000000 +0000 @@ -39,33 +39,33 @@ >>> data = np.arange(np.prod(shape)).reshape(shape) >>> affine = np.eye(4) >>> img = nf.Nifti1Image(data, affine) - >>> img.shape - (10, 20, 30, 1, 1) + >>> img.shape == (10, 20, 30, 1, 1) + True >>> img2 = squeeze_image(img) - >>> img2.shape - (10, 20, 30) + >>> img2.shape == (10, 20, 30) + True If the data are 3D then last dimensions of 1 are ignored >>> shape = (10,1,1) >>> data = np.arange(np.prod(shape)).reshape(shape) >>> img = nf.ni1.Nifti1Image(data, affine) - >>> img.shape - (10, 1, 1) + >>> img.shape == (10, 1, 1) + True >>> img2 = squeeze_image(img) - >>> img2.shape - (10, 1, 1) + >>> img2.shape == (10, 1, 1) + True Only *final* dimensions of 1 are squeezed >>> shape = (1, 1, 5, 1, 2, 1, 1) >>> data = data.reshape(shape) >>> img = nf.ni1.Nifti1Image(data, affine) - >>> img.shape - (1, 1, 5, 1, 2, 1, 1) + >>> img.shape == (1, 1, 5, 1, 2, 1, 1) + True >>> img2 = squeeze_image(img) - >>> img2.shape - (1, 1, 5, 1, 2) + >>> img2.shape == (1, 1, 5, 1, 2) + True ''' klass = img.__class__ shape = img.shape diff -Nru nibabel-1.2.2/nibabel/info.py nibabel-1.3.0/nibabel/info.py --- nibabel-1.2.2/nibabel/info.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/info.py 2012-09-11 21:02:24.000000000 +0000 @@ -7,8 +7,8 @@ # full release. '.dev' as a _version_extra string means this is a development # version _version_major = 1 -_version_minor = 2 -_version_micro = 2 +_version_minor = 3 +_version_micro = 0 #_version_extra = 'dev' _version_extra = '' @@ -38,8 +38,10 @@ This package provides read and write access to some common medical and neuroimaging file formats, including: ANALYZE_ (plain, SPM99, SPM2), -GIFTI_, NIfTI1_, MINC_, MGH_ and ECAT_ as well as PAR/REC. There is some very -limited support for DICOM_. NiBabel is the successor of PyNIfTI_. +GIFTI_, NIfTI1_, MINC_, MGH_ and ECAT_ as well as PAR/REC. We can read and +write Freesurfer_ geometry, and read Freesurfer morphometry and annotation +files. There is some very limited support for DICOM_. NiBabel is the successor +of PyNIfTI_. .. _ANALYZE: http://www.grahamwideman.com/gw/brain/analyze/formatdoc.htm .. _NIfTI1: http://nifti.nimh.nih.gov/nifti-1/ @@ -48,6 +50,7 @@ .. _GIFTI: http://www.nitrc.org/projects/gifti .. _MGH: http://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/MghFormat .. _ECAT: http://xmedcon.sourceforge.net/Docs/Ecat +.. _Freesurfer: http://surfer.nmr.mgh.harvard.edu .. _DICOM: http://medical.nema.org/ The various image format classes give full or selective access to header (meta) diff -Nru nibabel-1.2.2/nibabel/nicom/dicomwrappers.py nibabel-1.3.0/nibabel/nicom/dicomwrappers.py --- nibabel-1.2.2/nibabel/nicom/dicomwrappers.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/nicom/dicomwrappers.py 2012-09-11 21:02:24.000000000 +0000 @@ -407,14 +407,28 @@ @one_time def slice_normal(self): - slice_normal = csar.get_slice_normal(self.csa_header) - if not slice_normal is None: - return np.array(slice_normal) - iop = self.image_orient_patient - if iop is None: + #The std_slice_normal comes from the cross product of the directions + #in the ImageOrientationPatient + std_slice_normal = super(SiemensWrapper, self).slice_normal + csa_slice_normal = csar.get_slice_normal(self.csa_header) + if std_slice_normal is None and csa_slice_normal is None: return None - return np.cross(*iop.T[:]) - + elif std_slice_normal is None: + return np.array(csa_slice_normal) + elif csa_slice_normal is None: + return std_slice_normal + else: + #Make sure the two normals are very close to parallel unit vectors + dot_prod = np.dot(csa_slice_normal, std_slice_normal) + assert np.allclose(np.fabs(dot_prod), 1.0, atol=1e-5) + #Use the slice normal computed with the cross product as it will + #always be the most orthogonal, but take the sign from the CSA + #slice normal + if dot_prod < 0: + return -std_slice_normal + else: + return std_slice_normal + @one_time def series_signature(self): ''' Add ICE dims from CSA header to signature ''' Binary files /tmp/W2oEqy_CtM/nibabel-1.2.2/nibabel/nicom/tests/data/csa_slice_norm.dcm and /tmp/dOeBkVUJ5l/nibabel-1.3.0/nibabel/nicom/tests/data/csa_slice_norm.dcm differ diff -Nru nibabel-1.2.2/nibabel/nicom/tests/test_dicomreaders.py nibabel-1.3.0/nibabel/nicom/tests/test_dicomreaders.py --- nibabel-1.2.2/nibabel/nicom/tests/test_dicomreaders.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/nicom/tests/test_dicomreaders.py 2012-09-11 21:02:24.000000000 +0000 @@ -27,7 +27,8 @@ @dicom_test def test_read_dwis(): - data, aff, bs, gs = didr.read_mosaic_dwi_dir(IO_DATA_PATH, '*.dcm.gz') + data, aff, bs, gs = didr.read_mosaic_dwi_dir(IO_DATA_PATH, + 'siemens_dwi_*.dcm.gz') assert_equal(data.ndim, 4) assert_array_almost_equal(aff, EXPECTED_AFFINE) assert_array_almost_equal(bs, (0, EXPECTED_PARAMS[0])) diff -Nru nibabel-1.2.2/nibabel/nicom/tests/test_dicomwrappers.py nibabel-1.3.0/nibabel/nicom/tests/test_dicomwrappers.py --- nibabel-1.2.2/nibabel/nicom/tests/test_dicomwrappers.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/nicom/tests/test_dicomwrappers.py 2012-09-11 21:02:24.000000000 +0000 @@ -30,6 +30,7 @@ else: DATA = None DATA_FILE_B0 = pjoin(IO_DATA_PATH, 'siemens_dwi_0.dcm.gz') +DATA_FILE_SLC_NORM = pjoin(IO_DATA_PATH, 'csa_slice_norm.dcm') # This affine from our converted image was shown to match our image # spatially with an image from SPM DICOM conversion. We checked the @@ -48,7 +49,6 @@ 0.99997450, -0.005023611)] - @dicom_test def test_wrappers(): # test direct wrapper calls @@ -143,3 +143,31 @@ assert_equal(z, dw_1000.slice_indicator) dw_empty = didw.Wrapper() assert_true(dw_empty.slice_indicator is None) + + +@dicom_test +def test_orthogonal(): + #Test that the slice normal is sufficiently orthogonal + dw = didw.wrapper_from_file(DATA_FILE_SLC_NORM) + R = dw.rotation_matrix + assert np.allclose(np.eye(3), + np.dot(R, R.T), + atol=1e-6) + +@dicom_test +def test_use_csa_sign(): + #Test that we get the same slice normal, even after swapping the iop + #directions + dw = didw.wrapper_from_file(DATA_FILE_SLC_NORM) + iop = dw.image_orient_patient + dw.image_orient_patient = np.c_[iop[:,1], iop[:,0]] + dw2 = didw.wrapper_from_file(DATA_FILE_SLC_NORM) + assert np.allclose(dw.slice_normal, dw2.slice_normal) + +@dicom_test +def test_assert_parallel(): + #Test that we get an AssertionError if the cross product and the CSA + #slice normal are not parallel + dw = didw.wrapper_from_file(DATA_FILE_SLC_NORM) + dw.image_orient_patient = np.c_[[1., 0., 0.], [0., 1., 0.]] + assert_raises(AssertionError, dw.__getattribute__, 'slice_normal') diff -Nru nibabel-1.2.2/nibabel/nifti1.py nibabel-1.3.0/nibabel/nifti1.py --- nibabel-1.2.2/nibabel/nifti1.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/nifti1.py 2012-09-11 21:02:24.000000000 +0000 @@ -1779,7 +1779,7 @@ offset = header.get_data_offset() diff = offset-header_file.tell() if diff > 0: - header_file.write('\x00' * diff) + header_file.write(ZEROB * diff) def update_header(self): ''' Harmonize header with image data and affine ''' diff -Nru nibabel-1.2.2/nibabel/orientations.py nibabel-1.3.0/nibabel/orientations.py --- nibabel-1.2.2/nibabel/orientations.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/orientations.py 2012-09-11 21:02:24.000000000 +0000 @@ -37,7 +37,7 @@ threshold below which SVD values of the affine are considered zero. If `tol` is None, and ``S`` is an array with singular values for `affine`, and ``eps`` is the epsilon value for datatype of ``S``, then `tol` set to - ``S.max() * eps``. + ``S.max() * max((q, p)) * eps`` Returns ------- @@ -62,7 +62,7 @@ P, S, Qs = npl.svd(RS) # Threshold the singular values to determine the rank. if tol is None: - tol = S.max() * np.finfo(S.dtype).eps + tol = S.max() * max(RS.shape) * np.finfo(S.dtype).eps keep = (S > tol) R = np.dot(P[:, keep], Qs[keep]) # the matrix R is such that np.dot(R,R.T) is projection onto the @@ -75,7 +75,7 @@ ornt = np.ones((p, 2), dtype=np.int8) * np.nan for in_ax in range(p): col = R[:, in_ax] - if not np.alltrue(np.equal(col, 0)): + if not np.allclose(col, 0): out_ax = np.argmax(np.abs(col)) ornt[in_ax, 0] = out_ax assert col[out_ax] != 0 diff -Nru nibabel-1.2.2/nibabel/tests/test_data.py nibabel-1.3.0/nibabel/tests/test_data.py --- nibabel-1.2.2/nibabel/tests/test_data.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/tests/test_data.py 2012-09-11 21:02:24.000000000 +0000 @@ -19,8 +19,7 @@ from nose import with_setup -from nose.tools import assert_equal, \ - assert_raises, raises +from nose.tools import (assert_equal, assert_raises, raises, assert_false) from .test_environment import (setup_environment, teardown_environment, @@ -241,6 +240,11 @@ res = b.any_attribute +def test_bomber_inspect(): + b = Bomber('bomber example', 'a message') + assert_false(hasattr(b, 'any_attribute')) + + @with_environment def test_datasource_or_bomber(): pkg_def = dict( diff -Nru nibabel-1.2.2/nibabel/tests/test_nifti1.py nibabel-1.3.0/nibabel/tests/test_nifti1.py --- nibabel-1.2.2/nibabel/tests/test_nifti1.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/tests/test_nifti1.py 2012-09-11 21:02:24.000000000 +0000 @@ -469,6 +469,15 @@ # Unexpected keyword raises error assert_raises(TypeError, img.get_sform, strange=True) + def test_hdr_diff(self): + # Check an offset beyond data does not raise an error + img = self.image_class(np.zeros((2,3,4)), np.eye(4)) + ext = dict(img.files_types)['image'] + hdr = img.get_header() + hdr['vox_offset'] = 400 + with InTemporaryDirectory(): + img.to_filename('another_file' + ext) + class TestNifti1Pair(TestNifti1Image): # Run analyze-flavor spatialimage tests diff -Nru nibabel-1.2.2/nibabel/tests/test_orientations.py nibabel-1.3.0/nibabel/tests/test_orientations.py --- nibabel-1.2.2/nibabel/tests/test_orientations.py 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/nibabel/tests/test_orientations.py 2012-09-11 21:02:24.000000000 +0000 @@ -176,6 +176,33 @@ [np.nan, np.nan], [np.nan, np.nan], [np.nan, np.nan]]) + # Test behavior of thresholding + def_aff = np.array([[1., 1, 0, 0], + [0, 0, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1]]) + fail_tol = np.array([[0, 1], + [np.nan, np.nan], + [2, 1]]) + pass_tol = np.array([[0, 1], + [1, 1], + [2, 1]]) + eps = np.finfo(float).eps + # Test that a Y axis appears as we increase the difference between the first + # two columns + for y_val, has_y in ((0, False), + (eps, False), + (eps * 5, False), + (eps * 10, True), + ): + def_aff[1, 1] = y_val + res = pass_tol if has_y else fail_tol + assert_array_equal(io_orientation(def_aff), res) + # Test tol input argument + def_aff[1, 1] = eps + assert_array_equal(io_orientation(def_aff, tol=0), pass_tol) + def_aff[1, 1] = eps * 10 + assert_array_equal(io_orientation(def_aff, tol=1e-5), fail_tol) def test_ornt2axcodes(): diff -Nru nibabel-1.2.2/README.rst nibabel-1.3.0/README.rst --- nibabel-1.2.2/README.rst 2012-06-27 18:25:03.000000000 +0000 +++ nibabel-1.3.0/README.rst 2012-09-11 21:02:24.000000000 +0000 @@ -7,8 +7,10 @@ This package provides read and write access to some common medical and neuroimaging file formats, including: ANALYZE_ (plain, SPM99, SPM2), -GIFTI_, NIfTI1_, MINC_, MGH_ and ECAT_ as well as PAR/REC. There is some very -limited support for DICOM_. NiBabel is the successor of PyNIfTI_. +GIFTI_, NIfTI1_, MINC_, MGH_ and ECAT_ as well as PAR/REC. We can read and +write Freesurfer_ geometry, and read Freesurfer morphometry and annotation +files. There is some very limited support for DICOM_. NiBabel is the successor +of PyNIfTI_. .. _ANALYZE: http://www.grahamwideman.com/gw/brain/analyze/formatdoc.htm .. _NIfTI1: http://nifti.nimh.nih.gov/nifti-1/ @@ -17,6 +19,7 @@ .. _GIFTI: http://www.nitrc.org/projects/gifti .. _MGH: http://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/MghFormat .. _ECAT: http://xmedcon.sourceforge.net/Docs/Ecat +.. _Freesurfer: http://surfer.nmr.mgh.harvard.edu .. _DICOM: http://medical.nema.org/ The various image format classes give full or selective access to header (meta)