Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Manage multiple space delimiter #1450

Merged
merged 2 commits into from
Mar 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions dipy/io/gradients.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from __future__ import division, print_function, absolute_import

from os.path import splitext
import re
from dipy.utils.six import string_types
import numpy as np
import csv
from nibabel.tmpdirs import InTemporaryDirectory


def read_bvals_bvecs(fbvals, fbvecs):
Expand Down Expand Up @@ -32,18 +33,22 @@ def read_bvals_bvecs(fbvals, fbvecs):
# to this list:
vals = []
for this_fname in [fbvals, fbvecs]:
# If the input was None, we don't read anything and move on:
if this_fname is None:
# If the input was None or empty string, we don't read anything and
# move on:
if this_fname is None or not this_fname:
vals.append(None)
else:
if isinstance(this_fname, string_types):
base, ext = splitext(this_fname)
if ext in ['.bvals', '.bval', '.bvecs', '.bvec', '.txt', '.eddy_rotated_bvecs', '']:
with open(this_fname, 'r') as f:
content = f.readline()
sniffer = csv.Sniffer()
detect_delimiter = sniffer.sniff(str(content))
vals.append(np.squeeze(np.loadtxt(this_fname, delimiter=detect_delimiter.delimiter)))
content = f.read()
# We replace coma and tab delimiter by space
with InTemporaryDirectory():
tmp_fname = "tmp_bvals_bvecs.txt"
with open(tmp_fname, 'w') as f:
f.write(re.sub(r'(\t|,)', ' ', content))
vals.append(np.squeeze(np.loadtxt(tmp_fname)))
elif ext == '.npy':
vals.append(np.squeeze(np.load(this_fname)))
else:
Expand All @@ -59,12 +64,12 @@ def read_bvals_bvecs(fbvals, fbvecs):
if bvecs is None:
return bvals, bvecs

if bvecs.shape[1] > bvecs.shape[0]:
bvecs = bvecs.T
if min(bvecs.shape) != 3:
raise IOError('bvec file should have three rows')
if bvecs.ndim != 2:
raise IOError('bvec file should be saved as a two dimensional array')
if bvecs.shape[1] > bvecs.shape[0]:
bvecs = bvecs.T

# If bvals is None, you don't need to check that they have the same shape:
if bvals is None:
Expand Down
144 changes: 74 additions & 70 deletions dipy/io/tests/test_io_gradients.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from __future__ import division, print_function, absolute_import

import os.path as osp
import os
import tempfile
from nibabel.tmpdirs import InTemporaryDirectory

import numpy as np
import numpy.testing as npt
Expand Down Expand Up @@ -31,74 +30,79 @@ def test_read_bvals_bvecs():

# Test for error raising with incorrect file-contents:

# These bvecs only have two rows/columns:
new_bvecs1 = bvecs[:, :2]
# Make a temporary file
bv_file1 = tempfile.NamedTemporaryFile(mode='wt')
# And fill it with these 2-columned bvecs:
for x in range(new_bvecs1.shape[0]):
bv_file1.file.write('%s %s\n' %
(new_bvecs1[x][0], new_bvecs1[x][1]))
bv_file1.close()
npt.assert_raises(IOError, read_bvals_bvecs, fbvals, bv_file1.name)

# These bvecs are saved as one long array:
new_bvecs2 = np.ravel(bvecs)
bv_file2 = tempfile.NamedTemporaryFile()
np.save(bv_file2, new_bvecs2)
bv_file2.close()
npt.assert_raises(IOError, read_bvals_bvecs, fbvals, bv_file2.name)

# There are less bvecs than bvals:
new_bvecs3 = bvecs[:-1, :]
bv_file3 = tempfile.NamedTemporaryFile()
np.save(bv_file3, new_bvecs3)
bv_file3.close()
npt.assert_raises(IOError, read_bvals_bvecs, fbvals, bv_file3.name)

# You entered the bvecs on both sides:
npt.assert_raises(IOError, read_bvals_bvecs, fbvecs, fbvecs)

# All possible delimiters should work
bv_file4 = tempfile.NamedTemporaryFile()
with open(bv_file4.name, 'w') as f:
f.write("66 55 33")
bvals_1, _ = read_bvals_bvecs(bv_file4.name, None)

bv_file5 = tempfile.NamedTemporaryFile()
with open(bv_file5.name, 'w') as f:
f.write("66, 55, 33")
bvals_2, _ = read_bvals_bvecs(bv_file5.name, None)

bv_file6 = tempfile.NamedTemporaryFile()
with open(bv_file6.name, 'w') as f:
f.write("66 \t 55 \t 33")
bvals_3, _ = read_bvals_bvecs(bv_file6.name, None)

ans = np.array([66., 55., 33.])
npt.assert_array_equal(ans, bvals_1)
npt.assert_array_equal(ans, bvals_2)
npt.assert_array_equal(ans, bvals_3)

bv_file7 = tempfile.NamedTemporaryFile()
with open(bv_file7.name, 'w') as f:
f.write("66 55 33\n45 34 21\n55 32 65\n")
_, bvecs_1 = read_bvals_bvecs(None, bv_file7.name)

bv_file8 = tempfile.NamedTemporaryFile()
with open(bv_file8.name, 'w') as f:
f.write("66, 55, 33\n45, 34, 21 \n 55, 32, 65\n")
_, bvecs_2 = read_bvals_bvecs(None, bv_file8.name)

bv_file9 = tempfile.NamedTemporaryFile()
with open(bv_file9.name, 'w') as f:
f.write("66 \t 55 \t 33\n45 \t 34 \t 21\n55 \t 32 \t 65\n")
_, bvecs_3 = read_bvals_bvecs(None, bv_file9.name)

ans = np.array([[66., 55., 33.], [45., 34., 21.], [55., 32., 65.]])
npt.assert_array_equal(ans, bvecs_1)
npt.assert_array_equal(ans, bvecs_2)
npt.assert_array_equal(ans, bvecs_3)
with InTemporaryDirectory():
# These bvecs only have two rows/columns:
new_bvecs1 = bvecs[:, :2]
# Make a temporary file
with open('test_bv_file1.txt', 'wt') as bv_file1:
# And fill it with these 2-columned bvecs:
for x in range(new_bvecs1.shape[0]):
bv_file1.write('%s %s\n' % (new_bvecs1[x][0],
new_bvecs1[x][1]))
npt.assert_raises(IOError, read_bvals_bvecs, fbvals, 'test_bv_file1.txt')

# These bvecs are saved as one long array:
new_bvecs2 = np.ravel(bvecs)
with open('test_bv_file2.npy', 'w') as bv_file2:
print('FILENAME:', bv_file2.name)
np.save(bv_file2.name, new_bvecs2)
npt.assert_raises(IOError, read_bvals_bvecs, fbvals, 'test_bv_file2.npy')

# There are less bvecs than bvals:
new_bvecs3 = bvecs[:-1, :]
with open('test_bv_file3.txt', 'w') as bv_file3:
np.savetxt(bv_file3.name, new_bvecs3)
npt.assert_raises(IOError, read_bvals_bvecs, fbvals, 'test_bv_file3.txt')

# You entered the bvecs on both sides:
npt.assert_raises(IOError, read_bvals_bvecs, fbvecs, fbvecs)

# All possible delimiters should work
bv_file4 = 'test_space.txt'
with open(bv_file4, 'w') as f:
f.write("66 55 33")
bvals_1, _ = read_bvals_bvecs(bv_file4, '')

bv_file5 = 'test_coma.txt'
with open(bv_file5, 'w') as f:
f.write("66, 55, 33")
bvals_2, _ = read_bvals_bvecs(bv_file5, '')

bv_file6 = 'test_tabs.txt'
with open(bv_file6, 'w') as f:
f.write("66 \t 55 \t 33")
bvals_3, _ = read_bvals_bvecs(bv_file6, '')

ans = np.array([66., 55., 33.])
npt.assert_array_equal(ans, bvals_1)
npt.assert_array_equal(ans, bvals_2)
npt.assert_array_equal(ans, bvals_3)

bv_file7 = 'test_space_2.txt'
with open(bv_file7, 'w') as f:
f.write("66 55 33\n45 34 21\n55 32 65\n")
_, bvecs_1 = read_bvals_bvecs('', bv_file7)

bv_file8 = 'test_coma_2.txt'
with open(bv_file8, 'w') as f:
f.write("66, 55, 33\n45, 34, 21 \n 55, 32, 65\n")
_, bvecs_2 = read_bvals_bvecs('', bv_file8)

bv_file9 = 'test_tabs_2.txt'
with open(bv_file9, 'w') as f:
f.write("66 \t 55 \t 33\n45 \t 34 \t 21\n55 \t 32 \t 65\n")
_, bvecs_3 = read_bvals_bvecs('', bv_file9)

bv_file10 = 'test_multiple_space.txt'
with open(bv_file10, 'w') as f:
f.write("66 55 33\n45, 34, 21 \n 55, 32, 65\n")
_, bvecs_4 = read_bvals_bvecs('', bv_file10)

ans = np.array([[66., 55., 33.], [45., 34., 21.], [55., 32., 65.]])
npt.assert_array_equal(ans, bvecs_1)
npt.assert_array_equal(ans, bvecs_2)
npt.assert_array_equal(ans, bvecs_3)
npt.assert_array_equal(ans, bvecs_4)


if __name__ == '__main__':
Expand Down