|
a |
|
b/ants/utils/matrix_image.py |
|
|
1 |
|
|
|
2 |
__all__ = [ |
|
|
3 |
"matrix_to_images", |
|
|
4 |
"images_from_matrix", |
|
|
5 |
"image_list_to_matrix", |
|
|
6 |
"images_to_matrix", |
|
|
7 |
"matrix_from_images", |
|
|
8 |
"timeseries_to_matrix", |
|
|
9 |
"matrix_to_timeseries" |
|
|
10 |
] |
|
|
11 |
|
|
|
12 |
import os |
|
|
13 |
import json |
|
|
14 |
import numpy as np |
|
|
15 |
import warnings |
|
|
16 |
|
|
|
17 |
import ants |
|
|
18 |
from ants.decorators import image_method |
|
|
19 |
|
|
|
20 |
@image_method |
|
|
21 |
def matrix_to_timeseries(image, matrix, mask=None): |
|
|
22 |
""" |
|
|
23 |
converts a matrix to a ND image. |
|
|
24 |
|
|
|
25 |
ANTsR function: `matrix2timeseries` |
|
|
26 |
|
|
|
27 |
Arguments |
|
|
28 |
--------- |
|
|
29 |
|
|
|
30 |
image: reference ND image |
|
|
31 |
|
|
|
32 |
matrix: matrix to convert to image |
|
|
33 |
|
|
|
34 |
mask: mask image defining voxels of interest |
|
|
35 |
|
|
|
36 |
|
|
|
37 |
Returns |
|
|
38 |
------- |
|
|
39 |
ANTsImage |
|
|
40 |
|
|
|
41 |
Example |
|
|
42 |
------- |
|
|
43 |
>>> import ants |
|
|
44 |
>>> img = ants.make_image( (10,10,10,5 ) ) |
|
|
45 |
>>> mask = ants.ndimage_to_list( img )[0] * 0 |
|
|
46 |
>>> mask[ 4:8, 4:8, 4:8 ] = 1 |
|
|
47 |
>>> mat = ants.timeseries_to_matrix( img, mask = mask ) |
|
|
48 |
>>> img2 = ants.matrix_to_timeseries( img, mat, mask) |
|
|
49 |
""" |
|
|
50 |
|
|
|
51 |
if mask is None: |
|
|
52 |
mask = temp[0] * 0 + 1 |
|
|
53 |
temp = matrix_to_images(matrix, mask) |
|
|
54 |
newImage = ants.list_to_ndimage(image, temp) |
|
|
55 |
ants.copy_image_info(image, newImage) |
|
|
56 |
return newImage |
|
|
57 |
|
|
|
58 |
|
|
|
59 |
def matrix_to_images(data_matrix, mask): |
|
|
60 |
""" |
|
|
61 |
Unmasks rows of a matrix and writes as images |
|
|
62 |
|
|
|
63 |
ANTsR function: `matrixToImages` |
|
|
64 |
|
|
|
65 |
Arguments |
|
|
66 |
--------- |
|
|
67 |
data_matrix : numpy.ndarray |
|
|
68 |
each row corresponds to an image |
|
|
69 |
array should have number of columns equal to non-zero voxels in the mask |
|
|
70 |
|
|
|
71 |
mask : ANTsImage |
|
|
72 |
image containing a binary mask. Rows of the matrix are |
|
|
73 |
unmasked and written as images. The mask defines the output image space |
|
|
74 |
|
|
|
75 |
Returns |
|
|
76 |
------- |
|
|
77 |
list of ANTsImage types |
|
|
78 |
|
|
|
79 |
Example |
|
|
80 |
------- |
|
|
81 |
>>> import ants |
|
|
82 |
>>> img = ants.image_read(ants.get_ants_data('r16')) |
|
|
83 |
>>> msk = ants.get_mask( img ) |
|
|
84 |
>>> img2 = ants.image_read(ants.get_ants_data('r16')) |
|
|
85 |
>>> img3 = ants.image_read(ants.get_ants_data('r16')) |
|
|
86 |
>>> mat = ants.image_list_to_matrix([img,img2,img3], msk ) |
|
|
87 |
>>> ilist = ants.matrix_to_images( mat, msk ) |
|
|
88 |
""" |
|
|
89 |
|
|
|
90 |
if data_matrix.ndim > 2: |
|
|
91 |
data_matrix = data_matrix.reshape(data_matrix.shape[0], -1) |
|
|
92 |
|
|
|
93 |
numimages = len(data_matrix) |
|
|
94 |
numVoxelsInMatrix = data_matrix.shape[1] |
|
|
95 |
numVoxelsInMask = (mask >= 0.5).sum() |
|
|
96 |
if numVoxelsInMask != numVoxelsInMatrix: |
|
|
97 |
raise ValueError( |
|
|
98 |
"Num masked voxels %i must match data matrix %i" |
|
|
99 |
% (numVoxelsInMask, numVoxelsInMatrix) |
|
|
100 |
) |
|
|
101 |
|
|
|
102 |
imagelist = [] |
|
|
103 |
for i in range(numimages): |
|
|
104 |
img = mask.clone() |
|
|
105 |
img[mask >= 0.5] = data_matrix[i, :] |
|
|
106 |
imagelist.append(img) |
|
|
107 |
return imagelist |
|
|
108 |
|
|
|
109 |
|
|
|
110 |
images_from_matrix = matrix_to_images |
|
|
111 |
|
|
|
112 |
|
|
|
113 |
def images_to_matrix(image_list, mask=None, sigma=None, epsilon=0.5): |
|
|
114 |
""" |
|
|
115 |
Read images into rows of a matrix, given a mask - much faster for |
|
|
116 |
large datasets as it is based on C++ implementations. |
|
|
117 |
|
|
|
118 |
ANTsR function: `imagesToMatrix` |
|
|
119 |
|
|
|
120 |
Arguments |
|
|
121 |
--------- |
|
|
122 |
image_list : list of ANTsImage types |
|
|
123 |
images to convert to ndarray |
|
|
124 |
|
|
|
125 |
mask : ANTsImage (optional) |
|
|
126 |
Mask image, voxels in the mask (>= epsilon) are placed in the matrix. If None, |
|
|
127 |
the first image in image_list is thresholded at its mean value to create a mask. |
|
|
128 |
|
|
|
129 |
sigma : scaler (optional) |
|
|
130 |
smoothing factor |
|
|
131 |
|
|
|
132 |
epsilon : scalar |
|
|
133 |
threshold for mask, values >= epsilon are included in the mask. |
|
|
134 |
|
|
|
135 |
Returns |
|
|
136 |
------- |
|
|
137 |
ndarray |
|
|
138 |
array with a row for each image |
|
|
139 |
shape = (N_IMAGES, N_VOXELS) |
|
|
140 |
|
|
|
141 |
Example |
|
|
142 |
------- |
|
|
143 |
>>> import ants |
|
|
144 |
>>> img = ants.image_read(ants.get_ants_data('r16')) |
|
|
145 |
>>> img2 = ants.image_read(ants.get_ants_data('r16')) |
|
|
146 |
>>> img3 = ants.image_read(ants.get_ants_data('r16')) |
|
|
147 |
>>> mat = ants.image_list_to_matrix([img,img2,img3]) |
|
|
148 |
""" |
|
|
149 |
if mask is None: |
|
|
150 |
mask = ants.get_mask(image_list[0]) |
|
|
151 |
|
|
|
152 |
num_images = len(image_list) |
|
|
153 |
mask_thresh = mask.clone() >= epsilon |
|
|
154 |
mask_arr = mask.numpy() >= epsilon |
|
|
155 |
num_voxels = np.sum(mask_arr) |
|
|
156 |
|
|
|
157 |
data_matrix = np.empty((num_images, num_voxels)) |
|
|
158 |
do_smooth = sigma is not None |
|
|
159 |
for i, img in enumerate(image_list): |
|
|
160 |
if do_smooth: |
|
|
161 |
img = ants.smooth_image(img, sigma, sigma_in_physical_coordinates=True) |
|
|
162 |
if np.sum(np.array(img.shape) - np.array(mask_thresh.shape)) != 0: |
|
|
163 |
img = ants.resample_image_to_target(img, mask_thresh, 2) |
|
|
164 |
data_matrix[i, :] = img[mask_thresh] |
|
|
165 |
return data_matrix |
|
|
166 |
|
|
|
167 |
|
|
|
168 |
image_list_to_matrix = images_to_matrix |
|
|
169 |
matrix_from_images = images_to_matrix |
|
|
170 |
|
|
|
171 |
@image_method |
|
|
172 |
def timeseries_to_matrix(image, mask=None): |
|
|
173 |
""" |
|
|
174 |
Convert a timeseries image into a matrix. |
|
|
175 |
|
|
|
176 |
ANTsR function: `timeseries2matrix` |
|
|
177 |
|
|
|
178 |
Arguments |
|
|
179 |
--------- |
|
|
180 |
image : image whose slices we convert to a matrix. E.g. a 3D image of size |
|
|
181 |
x by y by z will convert to a z by x*y sized matrix |
|
|
182 |
|
|
|
183 |
mask : ANTsImage (optional) |
|
|
184 |
image containing binary mask. voxels in the mask are placed in the matrix |
|
|
185 |
|
|
|
186 |
Returns |
|
|
187 |
------- |
|
|
188 |
ndarray |
|
|
189 |
array with a row for each image |
|
|
190 |
shape = (N_IMAGES, N_VOXELS) |
|
|
191 |
|
|
|
192 |
Example |
|
|
193 |
------- |
|
|
194 |
>>> import ants |
|
|
195 |
>>> img = ants.make_image( (10,10,10,5 ) ) |
|
|
196 |
>>> mat = ants.timeseries_to_matrix( img ) |
|
|
197 |
""" |
|
|
198 |
temp = ants.ndimage_to_list(image) |
|
|
199 |
if mask is None: |
|
|
200 |
mask = temp[0] * 0 + 1 |
|
|
201 |
return image_list_to_matrix(temp, mask) |
|
|
202 |
|