Skip to content

Commit cb80e24

Browse files
author
Mathieu Dubois
committed
Merge branch 'master' into fix_tutorials
2 parents f0c7abd + e3d49ea commit cb80e24

File tree

8 files changed

+101
-12
lines changed

8 files changed

+101
-12
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Next release
22
============
33

4+
* FIX: Fixed Camino output naming (https://github.com/nipy/nipype/pull/1061)
5+
* ENH: Add the average distance to ErrorMap (https://github.com/nipy/nipype/pull/1039)
46
* ENH: Inputs with name_source can be now chained in cascade (https://github.com/nipy/nipype/pull/938)
57
* ENH: Improve JSON interfaces: default settings when reading and consistent output creation
68
when writing (https://github.com/nipy/nipype/pull/1047)

nipype/algorithms/metrics.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ class ErrorMapInputSpec(BaseInterfaceInputSpec):
488488

489489
class ErrorMapOutputSpec(TraitedSpec):
490490
out_map = File(exists=True, desc="resulting error map")
491+
distance = traits.Float(desc="Average distance between volume 1 and 2")
491492

492493

493494
class ErrorMap(BaseInterface):
@@ -506,12 +507,13 @@ class ErrorMap(BaseInterface):
506507
_out_file = ''
507508

508509
def _run_interface(self, runtime):
509-
from scipy.spatial.distance import cdist, pdist
510+
# Get two numpy data matrices
510511
nii_ref = nb.load(self.inputs.in_ref)
511512
ref_data = np.squeeze(nii_ref.get_data())
512513
tst_data = np.squeeze(nb.load(self.inputs.in_tst).get_data())
513514
assert(ref_data.ndim == tst_data.ndim)
514515

516+
# Load mask
515517
comps = 1
516518
mapshape = ref_data.shape
517519

@@ -528,26 +530,29 @@ def _run_interface(self, runtime):
528530
else:
529531
msk = np.ones(shape=mapshape)
530532

533+
# Flatten both volumes and make the pixel differennce
531534
mskvector = msk.reshape(-1)
532535
msk_idxs = np.where(mskvector==1)
533536
refvector = ref_data.reshape(-1,comps)[msk_idxs].astype(np.float32)
534537
tstvector = tst_data.reshape(-1,comps)[msk_idxs].astype(np.float32)
535538
diffvector = (refvector-tstvector)
536539

540+
# Scale the difference
537541
if self.inputs.metric == 'sqeuclidean':
538542
errvector = diffvector**2
543+
if (comps > 1):
544+
errvector = np.sum(errvector, axis=1)
545+
else:
546+
errvector = np.squeeze(errvector)
539547
elif self.inputs.metric == 'euclidean':
540-
X = np.hstack((refvector, tstvector))
541-
errvector = np.linalg.norm(X, axis=1)
548+
errvector = np.linalg.norm(diffvector, axis=1)
542549

543-
if (comps > 1):
544-
errvector = np.sum(errvector, axis=1)
545-
else:
546-
errvector = np.squeeze(errvector)
547-
548-
errvectorexp = np.zeros_like(mskvector)
550+
errvectorexp = np.zeros_like(mskvector, dtype=np.float32) # The default type is uint8
549551
errvectorexp[msk_idxs] = errvector
550552

553+
# Get averaged error
554+
self._distance = np.average(errvector) # Only average the masked voxels
555+
551556
errmap = errvectorexp.reshape(mapshape)
552557

553558
hdr = nii_ref.get_header().copy()
@@ -572,6 +577,7 @@ def _run_interface(self, runtime):
572577
def _list_outputs(self):
573578
outputs = self.output_spec().get()
574579
outputs['out_map'] = self._out_file
580+
outputs['distance'] = self._distance
575581
return outputs
576582

577583

nipype/algorithms/tests/test_auto_ErrorMap.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ def test_ErrorMap_inputs():
2323
yield assert_equal, getattr(inputs.traits()[key], metakey), value
2424

2525
def test_ErrorMap_outputs():
26-
output_map = dict(out_map=dict(),
26+
output_map = dict(distance=dict(),
27+
out_map=dict(),
2728
)
2829
outputs = ErrorMap.output_spec()
2930

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
from nipype.testing import (assert_equal, example_data)
5+
from nipype.algorithms.metrics import ErrorMap
6+
import nibabel as nib
7+
import numpy as np
8+
from tempfile import mkdtemp
9+
import os
10+
11+
def test_errormap():
12+
13+
tempdir = mkdtemp()
14+
# Single-Spectual
15+
# Make two fake 2*2*2 voxel volumes
16+
volume1 = np.array([[[2.0, 8.0], [1.0, 2.0]], [[1.0, 9.0], [0.0, 3.0]]]) # John von Neumann's birthday
17+
volume2 = np.array([[[0.0, 7.0], [2.0, 3.0]], [[1.0, 9.0], [1.0, 2.0]]]) # Alan Turing's birthday
18+
mask = np.array([[[1, 0], [0, 1]], [[1, 0], [0, 1]]])
19+
20+
img1 = nib.Nifti1Image(volume1, np.eye(4))
21+
img2 = nib.Nifti1Image(volume2, np.eye(4))
22+
maskimg = nib.Nifti1Image(mask, np.eye(4))
23+
24+
nib.save(img1, os.path.join(tempdir, 'von.nii.gz'))
25+
nib.save(img2, os.path.join(tempdir, 'alan.nii.gz'))
26+
nib.save(maskimg, os.path.join(tempdir, 'mask.nii.gz'))
27+
28+
29+
# Default metric
30+
errmap = ErrorMap()
31+
errmap.inputs.in_tst = os.path.join(tempdir, 'von.nii.gz')
32+
errmap.inputs.in_ref = os.path.join(tempdir, 'alan.nii.gz')
33+
errmap.out_map = os.path.join(tempdir, 'out_map.nii.gz')
34+
result = errmap.run()
35+
yield assert_equal, result.outputs.distance, 1.125
36+
37+
# Square metric
38+
errmap.inputs.metric = 'sqeuclidean'
39+
result = errmap.run()
40+
yield assert_equal, result.outputs.distance, 1.125
41+
42+
# Linear metric
43+
errmap.inputs.metric = 'euclidean'
44+
result = errmap.run()
45+
yield assert_equal, result.outputs.distance, 0.875
46+
47+
# Masked
48+
errmap.inputs.mask = os.path.join(tempdir, 'mask.nii.gz')
49+
result = errmap.run()
50+
yield assert_equal, result.outputs.distance, 1.0
51+
52+
## Multi-Spectual
53+
volume3 = np.array([[[1.0, 6.0], [0.0, 3.0]], [[1.0, 9.0], [3.0, 6.0]]]) # Raymond Vahan Damadian's birthday
54+
55+
msvolume1 = np.zeros(shape=(2,2,2,2))
56+
msvolume1[:,:,:,0] = volume1
57+
msvolume1[:,:,:,1] = volume3
58+
msimg1 = nib.Nifti1Image(msvolume1, np.eye(4))
59+
60+
msvolume2 = np.zeros(shape=(2,2,2,2))
61+
msvolume2[:,:,:,0] = volume3
62+
msvolume2[:,:,:,1] = volume1
63+
msimg2 = nib.Nifti1Image(msvolume2, np.eye(4))
64+
65+
nib.save(msimg1, os.path.join(tempdir, 'von-ray.nii.gz'))
66+
nib.save(msimg2, os.path.join(tempdir, 'alan-ray.nii.gz'))
67+
68+
errmap.inputs.in_tst = os.path.join(tempdir, 'von-ray.nii.gz')
69+
errmap.inputs.in_ref = os.path.join(tempdir, 'alan-ray.nii.gz')
70+
errmap.inputs.metric = 'sqeuclidean'
71+
result = errmap.run()
72+
yield assert_equal, result.outputs.distance, 5.5
73+
74+
errmap.inputs.metric = 'euclidean'
75+
result = errmap.run()
76+
yield assert_equal, result.outputs.distance, np.float32(1.25 * (2**0.5))

nipype/interfaces/ants/registration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ class Registration(ANTSCommand):
395395
>>> outputs = reg4._list_outputs()
396396
>>> print outputs #doctest: +ELLIPSIS
397397
{'reverse_invert_flags': [], 'inverse_composite_transform': ['.../nipype/testing/data/output_InverseComposite.h5'], 'warped_image': '.../nipype/testing/data/output_warped_image.nii.gz', 'inverse_warped_image': <undefined>, 'forward_invert_flags': [], 'reverse_transforms': [], 'composite_transform': ['.../nipype/testing/data/output_Composite.h5'], 'forward_transforms': []}
398-
398+
399399
>>> # Test collapse transforms flag
400400
>>> reg4b = copy.deepcopy(reg4)
401401
>>> reg4b.inputs.write_composite_transform = False

nipype/interfaces/camino/dti.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,11 @@ class Track(CommandLine):
549549

550550
def _list_outputs(self):
551551
outputs = self.output_spec().get()
552-
outputs['tracked'] = os.path.abspath(self._gen_outfilename())
552+
if isdefined(self.inputs.out_file):
553+
out_file_path = os.path.abspath(self.inputs.out_file)
554+
else:
555+
out_file_path = os.path.abspath(self._gen_outfilename())
556+
outputs['tracked'] = out_file_path
553557
return outputs
554558

555559
def _gen_filename(self, name):
107 Bytes
Binary file not shown.

nipype/testing/data/von_errmap.nii.gz

96 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)