Skip to content

Commit a2e9564

Browse files
committed
Merge remote-tracking branch 'origin/master' into chris-master
* origin/master: (76 commits) STY: Clearer conditional FIX: Fix for NumPy deprecation Better handle pathological filenames BF: flake8 the import BF(PY3): just catch all Exceptions, patch builtins module now provided in py3k BF: be resilient to optional module non-ImportError exceptions upon import better file checks - path.exists is try/except for os.stat anyways! Using another existing exception, and shorter message removing unnecessary space that nibabel checks dont like merging with upstream master to undo changes not ready to PR/merge detecting if the input is empty early on! Apparently no one needed it ;) DOC: rewrite first line of function docstring CI: Remove duplicate Travis entry [skip ci] mv test of failure + rm redundant tests COV: Omit tests, drop obsolete omissions add: tests for `nibabel.save` TEST: Delete arrayproxies, allowing Windows to close filehandles Revert "FIX: Give Windows time to decide files are closed" bf: preserve error output if not valid klass fix: use correct CIFTI intent names ...
2 parents b42c8fc + 636d5d2 commit a2e9564

35 files changed

+582
-155
lines changed

.coveragerc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@ include = */nibabel/*, */nisext/*
55
omit =
66
*/externals/*
77
*/benchmarks/*
8-
*/ast.py
9-
*/codegen.py
8+
*/tests/*

.travis.yml

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ cache:
1414
- $HOME/.cache/pip
1515
env:
1616
global:
17-
- DEPENDS="six numpy scipy matplotlib h5py pillow"
17+
- DEPENDS="six numpy scipy matplotlib h5py pillow pydicom"
1818
- OPTIONAL_DEPENDS=""
19-
- PYDICOM=1
2019
- INSTALL_TYPE="setup"
2120
- EXTRA_WHEELS="https://5cf40426d9f06eb7461d-6fe47d9331aba7cd62fc36c7196769e4.ssl.cf2.rackcdn.com"
2221
- PRE_WHEELS="https://7933911d6844c6c53a7d-47bd50c35cd79bd838daf386af554a83.ssl.cf2.rackcdn.com"
@@ -34,27 +33,23 @@ matrix:
3433
# Absolute minimum dependencies
3534
- python: 2.7
3635
env:
37-
- DEPENDS="numpy==1.7.1" PYDICOM=0
36+
- DEPENDS="numpy==1.7.1"
3837
# Absolute minimum dependencies plus oldest MPL
3938
# Check these against:
4039
# nibabel/info.py
4140
# doc/source/installation.rst
4241
# requirements.txt
4342
- python: 2.7
4443
env:
45-
- DEPENDS="numpy==1.7.1 matplotlib==1.3.1" PYDICOM=0
44+
- DEPENDS="numpy==1.7.1 matplotlib==1.3.1"
4645
# Minimum pydicom dependency
4746
- python: 2.7
4847
env:
49-
- DEPENDS="numpy==1.7.1 pydicom==0.9.7 pillow==2.6"
50-
# test against numpy 1.7
51-
- python: 2.7
52-
env:
53-
- DEPENDS="numpy==1.7.1"
54-
# pydicom 1.0 (currently unreleased)
55-
- python: 2.7
48+
- DEPENDS="numpy==1.7.1 pydicom==0.9.9 pillow==2.6"
49+
# pydicom master branch
50+
- python: 3.5
5651
env:
57-
- PYDICOM="v1.0"
52+
- DEPENDS="numpy git+https://github.com/pydicom/pydicom.git@master"
5853
# test 2.7 against pre-release builds of everything
5954
- python: 2.7
6055
env:
@@ -102,14 +97,6 @@ before_install:
10297
- pip install -U pip wheel # needed at one point
10398
- retry pip install nose flake8 mock # always
10499
- pip install $EXTRA_PIP_FLAGS $DEPENDS $OPTIONAL_DEPENDS
105-
# pydicom <= 0.9.8 doesn't install on python 3
106-
- if [ "${TRAVIS_PYTHON_VERSION:0:1}" == "2" ]; then
107-
if [ "$PYDICOM" == "1" ]; then
108-
pip install pydicom;
109-
elif [ "$PYDICOM" == "v1.0" ]; then
110-
pip install git+https://github.com/darcymason/pydicom.git@43f278444d5cb2e4648135d3edcd430c363c6975;
111-
fi
112-
fi
113100
- if [ "${COVERAGE}" == "1" ]; then
114101
pip install coverage;
115102
pip install coveralls;

doc/source/installation.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Requirements
9090
* NumPy_ 1.7.1 or greater
9191
* Six_ 1.3 or greater
9292
* SciPy_ (optional, for full SPM-ANALYZE support)
93-
* PyDICOM_ 0.9.7 or greater (optional, for DICOM support)
93+
* PyDICOM_ 0.9.9 or greater (optional, for DICOM support)
9494
* `Python Imaging Library`_ (optional, for PNG conversion in DICOMFS)
9595
* nose_ 0.11 or greater (optional, to run the tests)
9696
* mock_ (optional, to run the tests)

nibabel/analyze.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,10 +1086,6 @@ def to_file_map(self, file_map=None):
10861086
# Write header
10871087
hdr.write_to(hdrf)
10881088
# Write image
1089-
shape = hdr.get_data_shape()
1090-
if data.shape != shape:
1091-
raise HeaderDataError('Data should be shape (%s)' %
1092-
', '.join(str(s) for s in shape))
10931089
# Seek to writing position, get there by writing zeros if seek fails
10941090
seek_tell(imgf, hdr.get_data_offset(), write0=True)
10951091
# Write array data

nibabel/cifti2/cifti2.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,9 @@ def to_file_map(self, file_map=None):
13841384
header = self._nifti_header
13851385
extension = Cifti2Extension(content=self.header.to_xml())
13861386
header.extensions.append(extension)
1387+
# if intent code is not set, default to unknown CIFTI
1388+
if header.get_intent()[0] == 'none':
1389+
header.set_intent('NIFTI_INTENT_CONNECTIVITY_UNKNOWN')
13871390
data = reshape_dataobj(self.dataobj,
13881391
(1, 1, 1, 1) + self.dataobj.shape)
13891392
# If qform not set, reset pixdim values so Nifti2 does not complain

nibabel/cifti2/parse_cifti2.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,27 @@ def _mangle(self, value):
5252
# The codes below appear on the CIFTI-2 standard
5353
# http://www.nitrc.org/plugins/mwiki/index.php/cifti:ConnectivityMatrixFileFormats
5454
# https://www.nitrc.org/forum/attachment.php?attachid=341&group_id=454&forum_id=1955
55-
(3000, 'dense fiber/fan samples', (), 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN'),
56-
(3001, 'dense connectivity', (), 'NIFTI_INTENT_CONNECTIVITY_DENSE'),
57-
(3002, 'dense data series/fiber fans', (),
55+
(3000, 'ConnUnknown', (), 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN'),
56+
(3001, 'ConnDense', (), 'NIFTI_INTENT_CONNECTIVITY_DENSE'),
57+
(3002, 'ConnDenseSeries', (),
5858
'NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES'),
59-
(3003, 'parcellated connectivity', (),
59+
(3003, 'ConnParcels', (),
6060
'NIFTI_INTENT_CONNECTIVITY_PARCELLATED'),
61-
(3004, 'parcellated data series', (),
61+
(3004, 'ConnParcelSries', (),
6262
"NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SERIES"),
63-
(3006, 'dense scalar', (),
63+
(3006, 'ConnDenseScalar', (),
6464
'NIFTI_INTENT_CONNECTIVITY_DENSE_SCALARS'),
65-
(3007, 'dense label', (),
65+
(3007, 'ConnDenseLabel', (),
6666
'NIFTI_INTENT_CONNECTIVITY_DENSE_LABELS'),
67-
(3008, 'parcellated scalar', (),
67+
(3008, 'ConnParcelScalr', (),
6868
'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SCALAR'),
69-
(3009, 'parcellated dense connectivity', (),
69+
(3009, 'ConnParcelDense', (),
7070
'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_DENSE'),
71-
(3010, 'dense parcellated connectivity', (),
71+
(3010, 'ConnDenseParcel', (),
7272
'NIFTI_INTENT_CONNECTIVITY_DENSE_PARCELLATED'),
73-
(3011, 'parcellated connectivity series', (),
73+
(3011, 'ConnPPSr', (),
7474
'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SERIES'),
75-
(3012, 'parcellated connectivity scalar', (),
75+
(3012, 'ConnPPSc', (),
7676
'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SCALAR')))
7777

7878

nibabel/cifti2/tests/test_new_cifti2.py

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"""
99
import numpy as np
1010

11+
import nibabel as nib
1112
from nibabel import cifti2 as ci
1213
from nibabel.tmpdirs import InTemporaryDirectory
1314

@@ -212,10 +213,14 @@ def test_dtseries():
212213
hdr = ci.Cifti2Header(matrix)
213214
data = np.random.randn(13, 9)
214215
img = ci.Cifti2Image(data, hdr)
216+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES')
215217

216218
with InTemporaryDirectory():
217219
ci.save(img, 'test.dtseries.nii')
218-
img2 = ci.load('test.dtseries.nii')
220+
img2 = nib.load('test.dtseries.nii')
221+
assert_equal(img2.nifti_header.get_intent()[0],
222+
'ConnDenseSeries')
223+
assert_true(isinstance(img2, ci.Cifti2Image))
219224
assert_true((img2.get_data() == data).all())
220225
check_series_map(img2.header.matrix.get_index_map(0))
221226
check_geometry_map(img2.header.matrix.get_index_map(1))
@@ -231,10 +236,13 @@ def test_dscalar():
231236
hdr = ci.Cifti2Header(matrix)
232237
data = np.random.randn(2, 9)
233238
img = ci.Cifti2Image(data, hdr)
239+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_DENSE_SCALARS')
234240

235241
with InTemporaryDirectory():
236242
ci.save(img, 'test.dscalar.nii')
237-
img2 = ci.load('test.dscalar.nii')
243+
img2 = nib.load('test.dscalar.nii')
244+
assert_equal(img2.nifti_header.get_intent()[0], 'ConnDenseScalar')
245+
assert_true(isinstance(img2, ci.Cifti2Image))
238246
assert_true((img2.get_data() == data).all())
239247
check_scalar_map(img2.header.matrix.get_index_map(0))
240248
check_geometry_map(img2.header.matrix.get_index_map(1))
@@ -250,10 +258,13 @@ def test_dlabel():
250258
hdr = ci.Cifti2Header(matrix)
251259
data = np.random.randn(2, 9)
252260
img = ci.Cifti2Image(data, hdr)
261+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_DENSE_LABELS')
253262

254263
with InTemporaryDirectory():
255264
ci.save(img, 'test.dlabel.nii')
256-
img2 = ci.load('test.dlabel.nii')
265+
img2 = nib.load('test.dlabel.nii')
266+
assert_equal(img2.nifti_header.get_intent()[0], 'ConnDenseLabel')
267+
assert_true(isinstance(img2, ci.Cifti2Image))
257268
assert_true((img2.get_data() == data).all())
258269
check_label_map(img2.header.matrix.get_index_map(0))
259270
check_geometry_map(img2.header.matrix.get_index_map(1))
@@ -267,10 +278,13 @@ def test_dconn():
267278
hdr = ci.Cifti2Header(matrix)
268279
data = np.random.randn(9, 9)
269280
img = ci.Cifti2Image(data, hdr)
281+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_DENSE')
270282

271283
with InTemporaryDirectory():
272284
ci.save(img, 'test.dconn.nii')
273-
img2 = ci.load('test.dconn.nii')
285+
img2 = nib.load('test.dconn.nii')
286+
assert_equal(img2.nifti_header.get_intent()[0], 'ConnDense')
287+
assert_true(isinstance(img2, ci.Cifti2Image))
274288
assert_true((img2.get_data() == data).all())
275289
assert_equal(img2.header.matrix.get_index_map(0),
276290
img2.header.matrix.get_index_map(1))
@@ -287,10 +301,13 @@ def test_ptseries():
287301
hdr = ci.Cifti2Header(matrix)
288302
data = np.random.randn(13, 3)
289303
img = ci.Cifti2Image(data, hdr)
304+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SERIES')
290305

291306
with InTemporaryDirectory():
292307
ci.save(img, 'test.ptseries.nii')
293-
img2 = ci.load('test.ptseries.nii')
308+
img2 = nib.load('test.ptseries.nii')
309+
assert_equal(img2.nifti_header.get_intent()[0], 'ConnParcelSries')
310+
assert_true(isinstance(img2, ci.Cifti2Image))
294311
assert_true((img2.get_data() == data).all())
295312
check_series_map(img2.header.matrix.get_index_map(0))
296313
check_parcel_map(img2.header.matrix.get_index_map(1))
@@ -306,10 +323,13 @@ def test_pscalar():
306323
hdr = ci.Cifti2Header(matrix)
307324
data = np.random.randn(2, 3)
308325
img = ci.Cifti2Image(data, hdr)
326+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SCALAR')
309327

310328
with InTemporaryDirectory():
311329
ci.save(img, 'test.pscalar.nii')
312-
img2 = ci.load('test.pscalar.nii')
330+
img2 = nib.load('test.pscalar.nii')
331+
assert_equal(img2.nifti_header.get_intent()[0], 'ConnParcelScalr')
332+
assert_true(isinstance(img2, ci.Cifti2Image))
313333
assert_true((img2.get_data() == data).all())
314334
check_scalar_map(img2.header.matrix.get_index_map(0))
315335
check_parcel_map(img2.header.matrix.get_index_map(1))
@@ -325,10 +345,13 @@ def test_pdconn():
325345
hdr = ci.Cifti2Header(matrix)
326346
data = np.random.randn(2, 3)
327347
img = ci.Cifti2Image(data, hdr)
348+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED_DENSE')
328349

329350
with InTemporaryDirectory():
330351
ci.save(img, 'test.pdconn.nii')
331352
img2 = ci.load('test.pdconn.nii')
353+
assert_equal(img2.nifti_header.get_intent()[0], 'ConnParcelDense')
354+
assert_true(isinstance(img2, ci.Cifti2Image))
332355
assert_true((img2.get_data() == data).all())
333356
check_geometry_map(img2.header.matrix.get_index_map(0))
334357
check_parcel_map(img2.header.matrix.get_index_map(1))
@@ -344,10 +367,13 @@ def test_dpconn():
344367
hdr = ci.Cifti2Header(matrix)
345368
data = np.random.randn(2, 3)
346369
img = ci.Cifti2Image(data, hdr)
370+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_DENSE_PARCELLATED')
347371

348372
with InTemporaryDirectory():
349373
ci.save(img, 'test.dpconn.nii')
350374
img2 = ci.load('test.dpconn.nii')
375+
assert_equal(img2.nifti_header.get_intent()[0], 'ConnDenseParcel')
376+
assert_true(isinstance(img2, ci.Cifti2Image))
351377
assert_true((img2.get_data() == data).all())
352378
check_parcel_map(img2.header.matrix.get_index_map(0))
353379
check_geometry_map(img2.header.matrix.get_index_map(1))
@@ -367,6 +393,8 @@ def test_plabel():
367393
with InTemporaryDirectory():
368394
ci.save(img, 'test.plabel.nii')
369395
img2 = ci.load('test.plabel.nii')
396+
assert_equal(img.nifti_header.get_intent()[0], 'ConnUnknown')
397+
assert_true(isinstance(img2, ci.Cifti2Image))
370398
assert_true((img2.get_data() == data).all())
371399
check_label_map(img2.header.matrix.get_index_map(0))
372400
check_parcel_map(img2.header.matrix.get_index_map(1))
@@ -380,10 +408,13 @@ def test_pconn():
380408
hdr = ci.Cifti2Header(matrix)
381409
data = np.random.randn(3, 3)
382410
img = ci.Cifti2Image(data, hdr)
411+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED')
383412

384413
with InTemporaryDirectory():
385414
ci.save(img, 'test.pconn.nii')
386415
img2 = ci.load('test.pconn.nii')
416+
assert_equal(img.nifti_header.get_intent()[0], 'ConnParcels')
417+
assert_true(isinstance(img2, ci.Cifti2Image))
387418
assert_true((img2.get_data() == data).all())
388419
assert_equal(img2.header.matrix.get_index_map(0),
389420
img2.header.matrix.get_index_map(1))
@@ -401,10 +432,14 @@ def test_pconnseries():
401432
hdr = ci.Cifti2Header(matrix)
402433
data = np.random.randn(3, 3, 13)
403434
img = ci.Cifti2Image(data, hdr)
435+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED_'
436+
'PARCELLATED_SERIES')
404437

405438
with InTemporaryDirectory():
406439
ci.save(img, 'test.pconnseries.nii')
407440
img2 = ci.load('test.pconnseries.nii')
441+
assert_equal(img.nifti_header.get_intent()[0], 'ConnPPSr')
442+
assert_true(isinstance(img2, ci.Cifti2Image))
408443
assert_true((img2.get_data() == data).all())
409444
assert_equal(img2.header.matrix.get_index_map(0),
410445
img2.header.matrix.get_index_map(1))
@@ -423,10 +458,14 @@ def test_pconnscalar():
423458
hdr = ci.Cifti2Header(matrix)
424459
data = np.random.randn(3, 3, 13)
425460
img = ci.Cifti2Image(data, hdr)
461+
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED_'
462+
'PARCELLATED_SCALAR')
426463

427464
with InTemporaryDirectory():
428465
ci.save(img, 'test.pconnscalar.nii')
429466
img2 = ci.load('test.pconnscalar.nii')
467+
assert_equal(img.nifti_header.get_intent()[0], 'ConnPPSc')
468+
assert_true(isinstance(img2, ci.Cifti2Image))
430469
assert_true((img2.get_data() == data).all())
431470
assert_equal(img2.header.matrix.get_index_map(0),
432471
img2.header.matrix.get_index_map(1))

nibabel/deprecated.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ class ModuleProxy(object):
3131
def __init__(self, module_name):
3232
self._module_name = module_name
3333

34-
def __hasattr__(self, key):
35-
mod = __import__(self._module_name, fromlist=[''])
36-
return hasattr(mod, key)
37-
3834
def __getattr__(self, key):
3935
mod = __import__(self._module_name, fromlist=[''])
4036
return getattr(mod, key)

nibabel/filename_parser.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,7 @@ def parse_filename(filename,
147147
types_exts,
148148
trailing_suffixes,
149149
match_case=False):
150-
''' Splits filename into tuple of
151-
(fileroot, extension, trailing_suffix, guessed_name)
150+
'''Split filename into fileroot, extension, trailing suffix; guess type.
152151
153152
Parameters
154153
----------
@@ -265,9 +264,14 @@ def splitext_addext(filename,
265264
for ext in addexts:
266265
if endswith(filename, ext):
267266
extpos = -len(ext)
268-
addext = filename[extpos:]
269-
filename = filename[:extpos]
267+
filename, addext = filename[:extpos], filename[extpos:]
270268
break
271269
else:
272270
addext = ''
273-
return os.path.splitext(filename) + (addext,)
271+
# os.path.splitext() behaves unexpectedly when filename starts with '.'
272+
extpos = filename.rfind('.')
273+
if extpos < 0 or filename.strip('.') == '':
274+
root, ext = filename, ''
275+
else:
276+
root, ext = filename[:extpos], filename[extpos:]
277+
return (root, ext, addext)

0 commit comments

Comments
 (0)