13
13
# Standard library imports
17
18
# Standard scientific libraries imports (more specific imports are
18
19
# delayed, so that the part module can be used without them).
22
from scipy import ndimage, stats
23
from nifti import NiftiImage
26
from fff2.utils.mask import compute_mask, _largest_cc
27
from fff2.utils.emp_null import ENN
22
30
# The sform for MNI templates
23
31
mni_sform = np.array([[-1, 0, 0, 90],
39
47
# Functions for automatic choice of cuts coordinates
40
48
################################################################################
51
""" Largest connect components extraction code that fails gracefully
52
when mask is too big for C extension code.
55
mask = _largest_cc(mask)
58
return mask.astype(np.bool)
42
60
def coord_transform(x, y, z, affine):
43
61
""" Convert the x, y, z coordinates from one image space to another
44
space, using the given affine, that maps from input to output
47
Warning: The x, y and z have their Talairach meaning, not 3D
67
The x coordinates in the input space
69
The y coordinates in the input space
71
The z coordinates in the input space
72
affine : 2D 4x4 ndarray
73
affine that maps from input to output space.
78
The x coordinates in the output space
80
The y coordinates in the output space
82
The z coordinates in the output space
84
Warning: The x, y and z have their Talairach ordering, not 3D
50
87
coords = np.c_[np.atleast_1d(x).flat,
51
88
np.atleast_1d(y).flat,
76
113
def find_activation(map, mask=None, pvalue=0.05, upper_only=False):
77
""" Use the fff2 FDR estimator to guess threshold for negative
78
and positive activation.
80
If mask is None, the mask is computed from the map.
81
If mask is False, the map is assumed to be already masked
83
If mask is a 3D boolean array, it is used to mask the map.
85
If upper_only is true, only a threshold for positive
86
activation is estimated.
114
""" Use the empirical normal null estimator to find threshold for
115
negative and positive activation.
120
The activation map, as a 3D image.
121
mask : 3D ndarray, boolean, optional
122
The brain mask. If None, the mask is computed from the map.
123
pvalue : float, optional
124
The pvalue of the false discovery rate used.
125
upper_only : boolean, optional
126
If true, only a threshold for positive activation is estimated.
130
vmin : float, optional
131
The upper threshold for negative activation, not returned
132
if upper_only is True.
134
The lower threshod for positive activation.
88
from fff2.utils.emp_null import ENN
89
from fff2.utils.mask import compute_mask_intra_array
92
mask = compute_mask_intra_array(map)
138
mask = compute_mask(map)
95
140
vmax = ENN(map).threshold(alpha=pvalue)
102
147
def find_cut_coords(map, mask=None, activation_threshold=None):
103
148
""" Find the center of the largest activation connect component.
104
Returns the coordinates in voxels.
106
Mask is the brain mask.
108
If mask is None, the mask is computed from the map.
109
If mask is False, the map is assumed to be already masked
111
If mask is a 3D boolean array, it is used to mask the map.
153
The activation map, as a 3D image.
154
mask : 3D ndarray, boolean, optional
155
The brain mask. If None, the mask is computed from the map.
156
activation_threshold : float, optional
157
The lower threshold to the positive activation. If None, the
158
activation threshold is computed using find_activation.
163
the x coordinate in voxels.
165
the y coordinate in voxels.
167
the z coordinate in voxels.
113
from fff2.utils.mask import _largest_cc
114
from scipy import ndimage, stats
116
170
my_map = map.copy()
117
171
if activation_threshold is None:
200
248
""" Plot three cuts of a given activation map (Frontal, Axial, and Lateral)
253
The activation map, as a 3D image.
255
The affine matrix going from image voxel space to MNI space.
256
cut_coords: 3-tuple of floats
257
The MNI coordinates of the cut to perform, in MNI coordinates
259
anat : 3D ndarray, optional
260
The anatomical image to be used as a background. If None, the
261
MNI152 T1 1mm template is used.
262
anat_sform : 4x4 ndarray, optional
263
The affine matrix going from the anatomical image voxel space to
264
MNI space. This parameter is not used when the default
265
anatomical is used, but it is compulsory when using an
266
explicite anatomical image.
267
vmin : float, optional
268
The lower threshold of the positive activation. This
269
parameter is used to threshold the activation map.
270
figure_num : integer, optional
271
The number of the matplotlib figure used. If None is given, a
272
new figure is created.
273
axes : 4 tuple of float: (xmin, xmax, ymin, ymin), optional
274
The coordinates, in matplotlib figure space, of the axes
275
used to display the plot. If None, the complete figure is
277
title : string, optional
278
The title dispayed on the figure.
279
mask : 3D ndarray, boolean, optional
280
The brain mask. If None, the mask is computed from the map.
202
284
All the 3D arrays are in numpy convention: (x, y, z)
204
anat and anat_sform are respectively the 3D anatomical image used
205
for the background, and its sform. If None is given, a MNI
208
286
Cut coordinates are in Talairach coordinates. Warning: Talairach
209
287
coordinates are (y, x, z), if (x, y, z) are in voxel-ordering
212
axes is an optional four-tuple [xmin, xmax, ymin, ymax] giving
213
the region, in figure units, of the figure used to plot.
216
291
anat, anat_sform, vmax_anat = _AnatCache.get_anat()
388
462
""" Plot a 3D volume rendering view of the activation, with an
389
463
outline of the brain.
468
The activation map, as a 3D image.
470
The affine matrix going from image voxel space to MNI space.
471
cut_coords: 3-tuple of floats, optional
472
The MNI coordinates of a 3D cursor to indicate a feature
473
or a cut, in MNI coordinates and order.
474
anat : 3D ndarray, optional
475
The anatomical image to be used as a background. If None, the
476
MNI152 T1 1mm template is used.
477
anat_sform : 4x4 ndarray, optional
478
The affine matrix going from the anatomical image voxel space to
479
MNI space. This parameter is not used when the default
480
anatomical is used, but it is compulsory when using an
481
explicite anatomical image.
482
vmin : float, optional
483
The lower threshold of the positive activation. This
484
parameter is used to threshold the activation map.
485
figure_num : integer, optional
486
The number of the Mayavi figure used. If None is given, a
487
new figure is created.
488
mask : 3D ndarray, boolean, optional
489
The brain mask. If None, the mask is computed from the map.
391
493
All the 3D arrays are in numpy convention: (x, y, z)
393
anat and anat_sform are respectively the 3D anatomical image used
394
for the background, and its sform. If None is given, a MNI
397
If cut_coords is given, it is Talairach coordinates of a
398
cross cursor position. Warning: Talairach coordinates are
399
(y, x, z), if (x, y, z) are in voxel-ordering convention.
401
The mask is used to estimate threshold for activation, if
495
Cut coordinates are in Talairach coordinates. Warning: Talairach
496
coordinates are (y, x, z), if (x, y, z) are in voxel-ordering
499
If you are using a VTK version below 5.2, there is no way to
500
avoid opening a window during the rendering under Linux. This is
501
necessary to use the graphics card for the rendering. You must
502
maintain this window on top of others and on the screen.
504
If you are running on Windows, or using a recent version of VTK,
505
you can force offscreen mode using::
507
from enthought.mayavi import mlab
508
mlab.options.offscreen = True
404
511
from enthought.mayavi import mlab
405
512
from enthought.mayavi.sources.api import ArraySource
512
def plot_map(map, sform, cut_coords=None, anat=None, anat_sform=None,
619
def plot_map(map, sform, cut_coords, anat=None, anat_sform=None,
513
620
vmin=None, figure_num=None, title='', mask=None):
514
621
""" Plot a together a 3D volume rendering view of the activation, with an
515
622
outline of the brain, and 2D cuts. If Mayavi is not installed,
516
623
falls back to 2D views only.
628
The activation map, as a 3D image.
630
The affine matrix going from image voxel space to MNI space.
631
cut_coords: 3-tuple of floats, optional
632
The MNI coordinates of the cut to perform, in MNI coordinates
633
and order. If None is given, the cut_coords are automaticaly
635
anat : 3D ndarray, optional
636
The anatomical image to be used as a background. If None, the
637
MNI152 T1 1mm template is used.
638
anat_sform : 4x4 ndarray, optional
639
The affine matrix going from the anatomical image voxel space to
640
MNI space. This parameter is not used when the default
641
anatomical is used, but it is compulsory when using an
642
explicite anatomical image.
643
vmin : float, optional
644
The lower threshold of the positive activation. This
645
parameter is used to threshold the activation map.
646
figure_num : integer, optional
647
The number of the matplotlib and Mayavi figures used. If None is
648
given, a new figure is created.
649
title : string, optional
650
The title dispayed on the figure.
651
mask : 3D ndarray, boolean, optional
652
The brain mask. If None, the mask is computed from the map.
518
656
All the 3D arrays are in numpy convention: (x, y, z)
520
anat and anat_sform are respectively the 3D anatomical image used
521
for the background, and its sform. If None is given, a MNI
524
If cut_coords is given, it is Talairach coordinates of a
525
cross cursor position. Warning: Talairach coordinates are
526
(y, x, z), if (x, y, z) are in voxel-ordering convention.
658
Cut coordinates are in Talairach coordinates. Warning: Talairach
659
coordinates are (y, x, z), if (x, y, z) are in voxel-ordering
529
663
from enthought.mayavi import version
530
664
if not int(version.version[0]) > 2:
531
665
raise ImportError
532
666
except ImportError:
534
667
print >> sys.stderr, 'Mayavi > 3.x not installed, plotting only 2D'
535
668
return plot_map_2d(map, sform, cut_coords=cut_coords, anat=anat,
536
669
anat_sform=anat_sform, vmin=vmin,
570
702
def auto_plot_map(map, sform, vmin=None, cut_coords=None, do3d=False,
571
703
anat=None, anat_sform=None, title='',
572
704
figure_num=None, mask=None, auto_sign=True):
705
""" Automatic plotting of an activation map.
707
Plot a together a 3D volume rendering view of the activation, with an
708
outline of the brain, and 2D cuts. If Mayavi is not installed,
709
falls back to 2D views only.
714
The activation map, as a 3D image.
716
The affine matrix going from image voxel space to MNI space.
717
vmin : float, optional
718
The lower threshold of the positive activation. This
719
parameter is used to threshold the activation map.
720
cut_coords: 3-tuple of floats, optional
721
The MNI coordinates of the cut to perform, in MNI coordinates
722
and order. If None is given, the cut_coords are automaticaly
724
do3d : boolean, optional
725
If do3d is True, a 3D plot is created if Mayavi is installed.
726
anat : 3D ndarray, optional
727
The anatomical image to be used as a background. If None, the
728
MNI152 T1 1mm template is used.
729
anat_sform : 4x4 ndarray, optional
730
The affine matrix going from the anatomical image voxel space to
731
MNI space. This parameter is not used when the default
732
anatomical is used, but it is compulsory when using an
733
explicite anatomical image.
734
title : string, optional
735
The title dispayed on the figure.
736
figure_num : integer, optional
737
The number of the matplotlib and Mayavi figures used. If None is
738
given, a new figure is created.
739
mask : 3D ndarray, boolean, optional
740
The brain mask. If None, the mask is computed from the map.
741
auto_sign : boolean, optional
742
If auto_sign is True, the sign of the activation is
743
automaticaly computed: negative activation can thus be
748
All the 3D arrays are in numpy convention: (x, y, z)
750
Cut coordinates are in Talairach coordinates. Warning: Talairach
751
coordinates are (y, x, z), if (x, y, z) are in voxel-ordering
574
755
if do3d == 'offscreen':
596
779
if cut_coords is None:
597
780
x, y, z = find_cut_coords(map, activation_threshold=vmin)
598
x, y, z = coord_transform(x, y, z, sform)
599
# XXX: in Talairach the order is (y, x, z)
600
cut_coords = (y, x, z)
781
# XXX: Careful with Voxel/MNI ordering
782
y, x, z = coord_transform(x, y, z, sform)
783
cut_coords = (x, y, z)
601
784
plotter(map, sform, vmin=vmin, cut_coords=cut_coords,
602
785
anat=anat, anat_sform=anat_sform, title=title,
603
786
figure_num=figure_num, mask=mask)
604
787
return vmin, cut_coords
607
def plot_niftifile(filename, do3d=False, outputname=None, vmin=None,
790
def plot_niftifile(filename, outputname=None, do3d=False, vmin=None,
608
791
cut_coords=None, anat_filename=None, figure_num=None,
609
792
mask_filename=None, auto_sign=True):
610
""" Given a nifti filename, plot an view of it to a file (png by
793
""" Given a nifti filename, plot a view of it to a file (png by
799
The name of the Nifti file of the map to be plotted
800
outputname : string, optional
801
The file name of the output file created. By default
802
the name of the input file with a png extension is used.
803
do3d : boolean, optional
804
If do3d is True, a 3D plot is created if Mayavi is installed.
805
vmin : float, optional
806
The lower threshold of the positive activation. This
807
parameter is used to threshold the activation map.
808
cut_coords: 3-tuple of floats, optional
809
The MNI coordinates of the cut to perform, in MNI coordinates
810
and order. If None is given, the cut_coords are automaticaly
812
anat : string, optional
813
Name of the Nifti image file to be used as a background. If None,
814
the MNI152 T1 1mm template is used.
815
title : string, optional
816
The title dispayed on the figure.
817
figure_num : integer, optional
818
The number of the matplotlib and Mayavi figures used. If None is
819
given, a new figure is created.
820
mask_filename : string, optional
821
Name of the Nifti file to be used as brain mask. If None, the
822
mask is computed from the map.
823
auto_sign : boolean, optional
824
If auto_sign is True, the sign of the activation is
825
automaticaly computed: negative activation can thus be
831
Cut coordinates are in Talairach coordinates. Warning: Talairach
832
coordinates are (y, x, z), if (x, y, z) are in voxel-ordering
613
836
if outputname is None:
614
837
outputname = os.path.splitext(filename)[0] + '.png'
615
838
if not os.path.exists(filename):
616
839
raise OSError, 'File %s does not exist' % filename
619
nim = nifti.NiftiImage(filename)
841
nim = NiftiImage(filename)
620
842
sform = nim.sform
621
843
if any(np.linalg.eigvals(sform)==0):
622
844
raise SformError, "sform affine is not inversible"
623
845
if anat_filename is not None:
624
anat_im = nifti.NiftiImage(anat_filename)
846
anat_im = NiftiImage(anat_filename)
625
847
anat = anat_im.data.T
626
848
anat_sform = anat_im.sform