Skip to content

Commit ca42ca8

Browse files
committed
Merge branch 'master' into enh/ImprovedNosetestsVerbosity
2 parents cbf58a5 + 11111cd commit ca42ca8

File tree

7 files changed

+94
-63
lines changed

7 files changed

+94
-63
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Next Release
22
============
3+
* API: Default model level for the bedpostx workflow has been set to "2" following FSL 5.0.9 lead
34
* ENH: New interfaces for interacting with AWS S3: S3DataSink and S3DataGrabber (https://github.com/nipy/nipype/pull/1201)
45

56
Release 0.11.0 (September 15, 2015)

circle.yml

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,77 @@ dependencies:
55
- "~/examples/feeds"
66
- "~/mcr"
77
- "~/spm12"
8+
- "~/fsl"
89
- "~/examples/fsl_course_data"
910
override:
1011
- pip install --upgrade pip
1112
- pip install -e .
1213
- pip install matplotlib sphinx ipython boto
1314
- gem install fakes3
15+
- if [[ ! -d ~/fsl ]]; then wget "http://fsl.fmrib.ox.ac.uk/fsldownloads/fsl-5.0.9-centos6_64.tar.gz"; tar zxvf fsl-5.0.9-centos6_64.tar.gz; mv fsl ~/fsl; fi
1416
- if [[ ! -d ~/examples/data ]]; then wget "http://tcpdiag.dl.sourceforge.net/project/nipy/nipype/nipype-0.2/nipype-tutorial.tar.bz2"; tar jxvf nipype-tutorial.tar.bz2; mkdir ~/examples; mv nipype-tutorial/* ~/examples/; fi
1517
# we download this manually because CircleCI does not cache apt
1618
- if [[ ! -d ~/examples/feeds ]]; then wget "http://fsl.fmrib.ox.ac.uk/fsldownloads/fsl-5.0.8-feeds.tar.gz"; tar zxvf fsl-5.0.8-feeds.tar.gz; mv feeds ~/examples/; fi
1719
- if [[ ! -d ~/examples/fsl_course_data ]]; then wget -c "http://fsl.fmrib.ox.ac.uk/fslcourse/fdt1.tar.gz" ; wget -c "http://fsl.fmrib.ox.ac.uk/fslcourse/fdt2.tar.gz"; wget -c "http://fsl.fmrib.ox.ac.uk/fslcourse/tbss.tar.gz"; mkdir ~/examples/fsl_course_data; tar zxvf fdt1.tar.gz -C ~/examples/fsl_course_data; tar zxvf fdt2.tar.gz -C ~/examples/fsl_course_data; tar zxvf tbss.tar.gz -C ~/examples/fsl_course_data; fi
18-
- wget -O- http://neuro.debian.net/lists/trusty.us-nh.full | sudo tee /etc/apt/sources.list.d/neurodebian.sources.list
19-
- sudo apt-key adv --recv-keys --keyserver hkp://pgp.mit.edu:80 0xA5D32F012649A5A9
20-
- sudo apt-get update -y; sudo apt-get install -y fsl-core fsl-atlases
2120
- bash ~/nipype/tools/install_spm_mcr.sh
2221
- mkdir -p ~/.nipype && echo "[logging]" > ~/.nipype/nipype.cfg && echo "workflow_level = DEBUG" >> ~/.nipype/nipype.cfg && echo "interface_level = DEBUG" >> ~/.nipype/nipype.cfg && echo "filemanip_level = DEBUG" >> ~/.nipype/nipype.cfg
2322
test:
2423
override:
25-
- . /usr/share/fsl/5.0/etc/fslconf/fsl.sh && nosetests --with-doctest --logging-level=DEBUG --verbosity=3:
24+
- nosetests --with-doctest --logging-level=DEBUG --verbosity=3:
2625
environment:
2726
SPMMCRCMD: "$HOME/spm12/run_spm12.sh $HOME/mcr/v85/ script"
2827
FORCE_SPMMCR: 1
2928
FSL_COURSE_DATA: "$HOME/examples/fsl_course_data"
29+
FSLDIR: "$HOME/fsl/"
30+
PATH: "$HOME/fsl/bin:$PATH"
31+
LD_LIBRARY_PATH: "$HOME/fsl/lib"
32+
FSLOUTPUTTYPE: "NIFTI_GZ"
3033
timeout: 2600
3134
- set -o pipefail && cd doc && make html 2>&1 | tee ~/log.txt
3235
- cat ~/log.txt && if grep -q "ERROR" ~/log.txt; then false; else true; fi
33-
- . /usr/share/fsl/5.0/etc/fslconf/fsl.sh && python ~/nipype/tools/run_examples.py test_spm Linear workflow3d workflow4d:
36+
- python ~/nipype/tools/run_examples.py test_spm Linear workflow3d workflow4d:
3437
pwd: ../examples
3538
environment:
3639
SPMMCRCMD: "$HOME/spm12/run_spm12.sh $HOME/mcr/v85/ script"
3740
FORCE_SPMMCR: 1
41+
FSLDIR: "$HOME/fsl/"
42+
PATH: "$HOME/fsl/bin:$PATH"
43+
LD_LIBRARY_PATH: "$HOME/fsl/lib"
44+
FSLOUTPUTTYPE: "NIFTI_GZ"
3845
timeout: 1600
39-
- . /usr/share/fsl/5.0/etc/fslconf/fsl.sh && python ~/nipype/tools/run_examples.py fmri_fsl_feeds Linear l1pipeline:
46+
- python ~/nipype/tools/run_examples.py fmri_fsl_feeds Linear l1pipeline:
4047
pwd: ../examples
41-
- . /usr/share/fsl/5.0/etc/fslconf/fsl.sh && python ~/nipype/tools/run_examples.py fmri_spm_dartel Linear level1 l2pipeline:
48+
environment:
49+
FSLDIR: "$HOME/fsl/"
50+
PATH: "$HOME/fsl/bin:$PATH"
51+
LD_LIBRARY_PATH: "$HOME/fsl/lib"
52+
FSLOUTPUTTYPE: "NIFTI_GZ"
53+
- python ~/nipype/tools/run_examples.py fmri_spm_dartel Linear level1 l2pipeline:
4254
pwd: ../examples
4355
environment:
4456
SPMMCRCMD: "$HOME/spm12/run_spm12.sh $HOME/mcr/v85/ script"
4557
FORCE_SPMMCR: 1
58+
FSLDIR: "$HOME/fsl/"
59+
PATH: "$HOME/fsl/bin:$PATH"
60+
LD_LIBRARY_PATH: "$HOME/fsl/lib"
61+
FSLOUTPUTTYPE: "NIFTI_GZ"
4662
timeout: 1600
47-
- . /usr/share/fsl/5.0/etc/fslconf/fsl.sh && python ~/nipype/tools/run_examples.py fmri_fsl_reuse Linear level1_workflow:
63+
- python ~/nipype/tools/run_examples.py fmri_fsl_reuse Linear level1_workflow:
4864
pwd: ../examples
49-
- . /usr/share/fsl/5.0/etc/fslconf/fsl.sh && python ~/nipype/tools/run_examples.py fmri_spm_nested Linear level1 l2pipeline:
65+
environment:
66+
FSLDIR: "$HOME/fsl/"
67+
PATH: "$HOME/fsl/bin:$PATH"
68+
LD_LIBRARY_PATH: "$HOME/fsl/lib"
69+
FSLOUTPUTTYPE: "NIFTI_GZ"
70+
- python ~/nipype/tools/run_examples.py fmri_spm_nested Linear level1 l2pipeline:
5071
pwd: ../examples
5172
environment:
5273
SPMMCRCMD: "$HOME/spm12/run_spm12.sh $HOME/mcr/v85/ script"
5374
FORCE_SPMMCR: 1
75+
FSLDIR: "$HOME/fsl/"
76+
PATH: "$HOME/fsl/bin:$PATH"
77+
LD_LIBRARY_PATH: "$HOME/fsl/lib"
78+
FSLOUTPUTTYPE: "NIFTI_GZ"
5479

5580
general:
5681
artifacts:

nipype/interfaces/fsl/dti.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class FSLXCommandInputSpec(FSLCommandInputSpec):
114114
n_fibres = traits.Range(
115115
usedefault=True, low=1, default=2, argstr='--nfibres=%d',
116116
desc=('Maximum number of fibres to fit in each voxel'), mandatory=True)
117-
model = traits.Enum(1, 2, argstr='--model=%d',
117+
model = traits.Enum(1, 2, 3, argstr='--model=%d',
118118
desc=('use monoexponential (1, default, required for '
119119
'single-shell) or multiexponential (2, multi-'
120120
'shell) model'))
@@ -246,7 +246,7 @@ class BEDPOSTX5InputSpec(FSLXCommandInputSpec):
246246
n_fibres = traits.Range(
247247
usedefault=True, low=1, default=2, argstr='-n %d',
248248
desc=('Maximum number of fibres to fit in each voxel'), mandatory=True)
249-
model = traits.Enum(1, 2, argstr='-model %d',
249+
model = traits.Enum(1, 2, 3, argstr='-model %d',
250250
desc=('use monoexponential (1, default, required for '
251251
'single-shell) or multiexponential (2, multi-'
252252
'shell) model'))

nipype/workflows/dmri/fsl/dti.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def transpose(samples_over_fibres):
1717

1818

1919
def create_bedpostx_pipeline(name='bedpostx', params={'n_fibres':2, 'fudge':1, 'burn_in':1000,
20-
'n_jumps':1250, 'sample_every':25, 'model':1,
20+
'n_jumps':1250, 'sample_every':25, 'model':2,
2121
'cnlinear':True}):
2222
"""
2323
Creates a pipeline that does the same as bedpostx script from FSL -

nipype/workflows/dmri/fsl/tests/test_dti.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def test_create_bedpostx_pipeline():
5151
nipype_bedpostx.inputs.xfibres.sample_every = 1
5252
nipype_bedpostx.inputs.xfibres.cnlinear = True
5353
nipype_bedpostx.inputs.xfibres.seed = 0
54+
nipype_bedpostx.inputs.xfibres.model = 2
5455

5556
with warnings.catch_warnings():
5657
warnings.simplefilter("ignore")
@@ -64,6 +65,7 @@ def test_create_bedpostx_pipeline():
6465
original_bedpostx.inputs.n_jumps = 1
6566
original_bedpostx.inputs.sample_every = 1
6667
original_bedpostx.inputs.seed = 0
68+
original_bedpostx.inputs.model = 2
6769

6870
test_f1 = pe.Node(util.AssertEqual(), name="mean_f1_test")
6971

nipype/workflows/dmri/fsl/tests/test_tbss.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,14 @@ def _tbss_test_helper(estimate_skeleton):
120120
os.chdir(old_dir)
121121
shutil.rmtree(test_dir)
122122

123-
123+
#this test is disabled until we figure out what is wrong with TBSS in 5.0.9
124124
@skipif(no_fsl)
125125
@skipif(no_fsl_course_data)
126-
def test_tbss_est_skeleton():
126+
def disabled_tbss_est_skeleton():
127127
_tbss_test_helper(True)
128128

129-
129+
#this test is disabled until we figure out what is wrong with TBSS in 5.0.9
130130
@skipif(no_fsl)
131131
@skipif(no_fsl_course_data)
132-
def test_tbss_est_skeleton_use_precomputed_skeleton():
132+
def disabled_tbss_est_skeleton_use_precomputed_skeleton():
133133
_tbss_test_helper(False)

nipype/workflows/dmri/fsl/utils.py

Lines changed: 50 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ def cleanup_edge_pipeline(name='Cleanup'):
1919
name='outputnode')
2020

2121
fugue = pe.Node(fsl.FUGUE(save_fmap=True, despike_2dfilter=True,
22-
despike_threshold=2.1), name='Despike')
23-
erode = pe.Node(fsl.maths.MathsCommand(nan2zeros=True,
24-
args='-kernel 2D -ero'), name='MskErode')
22+
despike_threshold=2.1), name='Despike')
23+
erode = pe.Node(fsl.maths.MathsCommand(
24+
nan2zeros=True, args='-kernel 2D -ero'), name='MskErode')
2525
newmsk = pe.Node(fsl.MultiImageMaths(op_string='-sub %s -thr 0.5 -bin'),
2626
name='NewMask')
2727
applymsk = pe.Node(fsl.ApplyMask(nan2zeros=True), name='ApplyMask')
@@ -51,13 +51,13 @@ def vsm2warp(name='Shiftmap2Warping'):
5151
"""
5252
Converts a voxel shift map (vsm) to a displacements field (warp).
5353
"""
54-
inputnode = pe.Node(niu.IdentityInterface(fields=['in_vsm',
55-
'in_ref', 'scaling', 'enc_dir']), name='inputnode')
54+
inputnode = pe.Node(niu.IdentityInterface(
55+
fields=['in_vsm', 'in_ref', 'scaling', 'enc_dir']), name='inputnode')
5656
outputnode = pe.Node(niu.IdentityInterface(fields=['out_warp']),
5757
name='outputnode')
58-
fixhdr = pe.Node(niu.Function(input_names=['in_file', 'in_file_hdr'],
59-
output_names=['out_file'], function=copy_hdr),
60-
name='Fix_hdr')
58+
fixhdr = pe.Node(niu.Function(
59+
input_names=['in_file', 'in_file_hdr'], output_names=['out_file'],
60+
function=copy_hdr), name='Fix_hdr')
6161
vsm = pe.Node(fsl.maths.BinaryMaths(operation='mul'), name='ScaleField')
6262
vsm2dfm = pe.Node(fsl.ConvertWarp(relwarp=True, out_relwarp=True),
6363
name='vsm2dfm')
@@ -81,33 +81,33 @@ def dwi_flirt(name='DWICoregistration', excl_nodiff=False,
8181
"""
8282
Generates a workflow for linear registration of dwi volumes
8383
"""
84-
inputnode = pe.Node(niu.IdentityInterface(fields=['reference',
85-
'in_file', 'ref_mask', 'in_xfms', 'in_bval']),
86-
name='inputnode')
84+
inputnode = pe.Node(niu.IdentityInterface(
85+
fields=['reference', 'in_file', 'ref_mask', 'in_xfms', 'in_bval']),
86+
name='inputnode')
8787

88-
initmat = pe.Node(niu.Function(input_names=['in_bval', 'in_xfms',
89-
'excl_nodiff'], output_names=['init_xfms'],
90-
function=_checkinitxfm), name='InitXforms')
88+
initmat = pe.Node(niu.Function(
89+
input_names=['in_bval', 'in_xfms', 'excl_nodiff'],
90+
output_names=['init_xfms'], function=_checkinitxfm), name='InitXforms')
9191
initmat.inputs.excl_nodiff = excl_nodiff
92-
dilate = pe.Node(fsl.maths.MathsCommand(nan2zeros=True,
93-
args='-kernel sphere 5 -dilM'), name='MskDilate')
92+
dilate = pe.Node(fsl.maths.MathsCommand(
93+
nan2zeros=True, args='-kernel sphere 5 -dilM'), name='MskDilate')
9494
split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs')
9595
pick_ref = pe.Node(niu.Select(), name='Pick_b0')
9696
n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3), name='Bias')
97-
enhb0 = pe.Node(niu.Function(input_names=['in_file', 'in_mask',
98-
'clip_limit'], output_names=['out_file'],
99-
function=enhance), name='B0Equalize')
97+
enhb0 = pe.Node(niu.Function(
98+
input_names=['in_file', 'in_mask', 'clip_limit'],
99+
output_names=['out_file'], function=enhance), name='B0Equalize')
100100
enhb0.inputs.clip_limit = 0.015
101-
enhdw = pe.MapNode(niu.Function(input_names=['in_file', 'in_mask'],
102-
output_names=['out_file'], function=enhance),
103-
name='DWEqualize', iterfield=['in_file'])
101+
enhdw = pe.MapNode(niu.Function(
102+
input_names=['in_file', 'in_mask'], output_names=['out_file'],
103+
function=enhance), name='DWEqualize', iterfield=['in_file'])
104104
flirt = pe.MapNode(fsl.FLIRT(**flirt_param), name='CoRegistration',
105105
iterfield=['in_file', 'in_matrix_file'])
106106
thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'],
107107
name='RemoveNegative')
108108
merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs')
109-
outputnode = pe.Node(niu.IdentityInterface(fields=['out_file',
110-
'out_xfms']), name='outputnode')
109+
outputnode = pe.Node(niu.IdentityInterface(
110+
fields=['out_file', 'out_xfms']), name='outputnode')
111111
wf = pe.Workflow(name=name)
112112
wf.connect([
113113
(inputnode, split, [('in_file', 'in_file')]),
@@ -141,10 +141,11 @@ def apply_all_corrections(name='UnwarpArtifacts'):
141141
the map of determinants of the jacobian.
142142
"""
143143

144-
inputnode = pe.Node(niu.IdentityInterface(fields=['in_sdc',
145-
'in_hmc', 'in_ecc', 'in_dwi']), name='inputnode')
146-
outputnode = pe.Node(niu.IdentityInterface(fields=['out_file', 'out_warp',
147-
'out_coeff', 'out_jacobian']), name='outputnode')
144+
inputnode = pe.Node(niu.IdentityInterface(
145+
fields=['in_sdc', 'in_hmc', 'in_ecc', 'in_dwi']), name='inputnode')
146+
outputnode = pe.Node(niu.IdentityInterface(
147+
fields=['out_file', 'out_warp', 'out_coeff', 'out_jacobian']),
148+
name='outputnode')
148149
warps = pe.MapNode(fsl.ConvertWarp(relwarp=True),
149150
iterfield=['premat', 'postmat'],
150151
name='ConvertWarp')
@@ -248,7 +249,7 @@ def hmc_split(in_file, in_bval, ref_num=0, lowbval=5.0):
248249

249250
volid = lowbs[0]
250251
if (isdefined(ref_num) and (ref_num < len(lowbs))):
251-
volid = [ref_num]
252+
volid = ref_num
252253

253254
if volid == 0:
254255
data = data[..., 1:]
@@ -265,8 +266,8 @@ def hmc_split(in_file, in_bval, ref_num=0, lowbval=5.0):
265266
out_mov = op.abspath('hmc_mov.nii.gz')
266267
out_bval = op.abspath('bval_split.txt')
267268

268-
hdr.set_data_shape(refdata.shape)
269269
refdata = data[..., volid]
270+
hdr.set_data_shape(refdata.shape)
270271
nb.Nifti1Image(refdata, im.get_affine(), hdr).to_filename(out_ref)
271272

272273
hdr.set_data_shape(data.shape)
@@ -406,8 +407,8 @@ def time_avg(in_file, index=[0], out_file=None):
406407
if len(index) == 1:
407408
data = imgs[0].get_data().astype(np.float32)
408409
else:
409-
data = np.average(np.array([im.get_data().astype(np.float32) for im in imgs]),
410-
axis=0)
410+
data = np.average(np.array([im.get_data().astype(np.float32)
411+
for im in imgs]), axis=0)
411412

412413
hdr = imgs[0].get_header().copy()
413414
hdr.set_data_shape(data.shape)
@@ -448,7 +449,9 @@ def b0_average(in_dwi, in_bval, max_b=10.0, out_file=None):
448449
out_file = op.abspath("%s_avg_b0%s" % (fname, ext))
449450

450451
imgs = np.array(nb.four_to_three(nb.load(in_dwi)))
451-
index = b0_indices(in_bval, max_b=max_b)
452+
bval = np.loadtxt(in_bval)
453+
index = np.argwhere(bval <= max_b).flatten().tolist()
454+
452455
b0s = [im.get_data().astype(np.float32)
453456
for im in imgs[index]]
454457
b0 = np.average(np.array(b0s), axis=0)
@@ -483,16 +486,16 @@ def rotate_bvecs(in_bvec, in_matrix):
483486

484487
if len(bvecs) != len(in_matrix):
485488
raise RuntimeError(('Number of b-vectors (%d) and rotation '
486-
'matrices (%d) should match.') % (len(bvecs),
487-
len(in_matrix)))
489+
'matrices (%d) should match.') % (len(bvecs),
490+
len(in_matrix)))
488491

489492
for bvec, mat in zip(bvecs, in_matrix):
490493
if np.all(bvec == 0.0):
491494
new_bvecs.append(bvec)
492495
else:
493496
invrot = np.linalg.inv(np.loadtxt(mat))[:3, :3]
494497
newbvec = invrot.dot(bvec)
495-
new_bvecs.append((newbvec/np.linalg.norm(newbvec)))
498+
new_bvecs.append((newbvec / np.linalg.norm(newbvec)))
496499

497500
np.savetxt(out_file, np.array(new_bvecs).T, fmt='%0.15f')
498501
return out_file
@@ -519,7 +522,7 @@ def eddy_rotate_bvecs(in_bvec, eddy_params):
519522

520523
if len(bvecs) != len(params):
521524
raise RuntimeError(('Number of b-vectors and rotation '
522-
'matrices should match.'))
525+
'matrices should match.'))
523526

524527
for bvec, row in zip(bvecs, params):
525528
if np.all(bvec == 0.0):
@@ -530,19 +533,19 @@ def eddy_rotate_bvecs(in_bvec, eddy_params):
530533
az = row[5]
531534

532535
Rx = np.array([[1.0, 0.0, 0.0],
533-
[0.0, cos(ax), -sin(ax)],
534-
[0.0, sin(ax), cos(ax)]])
536+
[0.0, cos(ax), -sin(ax)],
537+
[0.0, sin(ax), cos(ax)]])
535538
Ry = np.array([[cos(ay), 0.0, sin(ay)],
536-
[0.0, 1.0, 0.0],
537-
[-sin(ay), 0.0, cos(ay)]])
539+
[0.0, 1.0, 0.0],
540+
[-sin(ay), 0.0, cos(ay)]])
538541
Rz = np.array([[cos(az), -sin(az), 0.0],
539-
[sin(az), cos(az), 0.0],
540-
[0.0, 0.0, 1.0]])
542+
[sin(az), cos(az), 0.0],
543+
[0.0, 0.0, 1.0]])
541544
R = Rx.dot(Ry).dot(Rz)
542545

543546
invrot = np.linalg.inv(R)
544547
newbvec = invrot.dot(bvec)
545-
new_bvecs.append((newbvec/np.linalg.norm(newbvec)))
548+
new_bvecs.append((newbvec / np.linalg.norm(newbvec)))
546549

547550
np.savetxt(out_file, np.array(new_bvecs).T, fmt='%0.15f')
548551
return out_file
@@ -600,7 +603,7 @@ def siemens2rads(in_file, out_file=None):
600603

601604
imin = data.min()
602605
imax = data.max()
603-
data = (2.0 * math.pi * (data - imin)/(imax-imin)) - math.pi
606+
data = (2.0 * math.pi * (data - imin) / (imax - imin)) - math.pi
604607
hdr.set_data_dtype(np.float32)
605608
hdr.set_xyzt_units('mm')
606609
hdr['datatype'] = 16
@@ -624,7 +627,7 @@ def rads2radsec(in_file, delta_te, out_file=None):
624627
out_file = op.abspath('./%s_radsec.nii.gz' % fname)
625628

626629
im = nb.load(in_file)
627-
data = im.get_data().astype(np.float32) * (1.0/delta_te)
630+
data = im.get_data().astype(np.float32) * (1.0 / delta_te)
628631
nb.Nifti1Image(data, im.get_affine(),
629632
im.get_header()).to_filename(out_file)
630633
return out_file
@@ -705,7 +708,7 @@ def reorient_bvecs(in_dwi, old_dwi, in_bvec):
705708
sc_idx = np.where((np.abs(RS) != 1) & (RS != 0))
706709
S = np.ones_like(RS)
707710
S[sc_idx] = RS[sc_idx]
708-
R = RS/S
711+
R = RS / S
709712

710713
new_bvecs = [R.dot(b) for b in bvecs]
711714
np.savetxt(out_file, np.array(new_bvecs).T, fmt='%0.15f')

0 commit comments

Comments
 (0)