-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample.py
More file actions
238 lines (200 loc) · 8.09 KB
/
Copy pathexample.py
File metadata and controls
238 lines (200 loc) · 8.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
import h5py
import scipy.sparse
import numpy as np
import matplotlib.pyplot as plt
def load_hdf5_array(file_name, key=None, slice=slice(0, None)):
"""Function to load data from an hdf file.
Parameters
----------
file_name: string
hdf5 file name.
key: string
Key name to load. If not provided, all keys will be loaded.
slice: slice, or tuple of slices
Load only a slice of the hdf5 array. It will load `array[slice]`.
Use a tuple of slices to get a slice in multiple dimensions.
Returns
-------
result : array or dictionary
Array, or dictionary of arrays (if `key` is None).
"""
with h5py.File(file_name, mode='r') as hf:
if key is None:
data = dict()
for k in hf.keys():
data[k] = hf[k][slice]
return data
else:
return hf[key][slice]
def load_hdf5_sparse_array(file_name, key):
"""Load a scipy sparse array from an hdf file
Parameters
----------
file_name : string
File name containing array to be loaded.
key : string
Name of variable to be loaded.
Notes
-----
This function relies on variables being stored with specific naming
conventions, so cannot be used to load arbitrary sparse arrays.
"""
with h5py.File(file_name, mode='r') as hf:
data = (hf['%s_data' % key], hf['%s_indices' % key],
hf['%s_indptr' % key])
sparsemat = scipy.sparse.csr_matrix(data, shape=hf['%s_shape' % key])
return sparsemat
def save_hdf5_dataset(file_name, dataset, mode='w'):
"""Save a dataset of arrays and sparse arrays.
Parameters
----------
file_name : str
Full name of the file.
dataset : dict of arrays
Mappers to save.
mode : str
File opening model.
Use 'w' to write from scratch, 'a' to add to existing file.
"""
print("Saving... ", end="", flush=True)
with h5py.File(file_name, mode=mode) as hf:
for name, array in dataset.items():
if scipy.sparse.issparse(array): # sparse array
array = array.tocsr()
hf.create_dataset(name + '_indices', data=array.indices,
compression='gzip')
hf.create_dataset(name + '_data', data=array.data,
compression='gzip')
hf.create_dataset(name + '_indptr', data=array.indptr,
compression='gzip')
hf.create_dataset(name + '_shape', data=array.shape,
compression='gzip')
else: # dense array
hf.create_dataset(name, data=array, compression='gzip')
print("Saved %s" % file_name)
def map_voxels_to_flatmap(voxels, mapper_file):
"""Generate flatmap image from voxel array using a mapper.
This function maps an array of voxels into a flattened representation
of an individual subject's brain.
Parameters
----------
voxels: array of shape (n_voxels, )
Voxel values to be mapped.
mapper_file: string
File containing mapping arrays for a particular subject.
Returns
-------
image : array of shape (width, height)
Flatmap image.
"""
voxel_to_flatmap = load_hdf5_sparse_array(mapper_file, 'voxel_to_flatmap')
flatmap_mask = load_hdf5_array(mapper_file, 'flatmap_mask')
badmask = np.array(voxel_to_flatmap.sum(1) > 0).ravel()
img = (np.nan * np.ones(flatmap_mask.shape)).astype(voxels.dtype)
mimg = (np.nan * np.ones(badmask.shape)).astype(voxels.dtype)
mimg[badmask] = (voxel_to_flatmap * voxels.ravel())[badmask].astype(
mimg.dtype)
img[flatmap_mask] = mimg
return img.T[::-1]
def plot_flatmap_from_mapper(voxels, mapper_file, ax=None, alpha=0.7,
cmap='inferno', vmin=None, vmax=None,
with_curvature=True, with_rois=True,
with_colorbar=True,
colorbar_location=(.4, .9, .2, .05)):
"""Plot a flatmap from a mapper file.
Note that this function does not have the full capability of pycortex,
(like cortex.quickshow) since it is based on flatmap mappers and not on the
original brain surface of the subject.
Parameters
----------
voxels : array of shape (n_voxels, )
Data to be plotted.
mapper_file : str
File name of the mapper.
ax : matplotlib Axes or None.
Axes where the figure will be plotted.
If None, a new figure is created.
alpha : float in [0, 1], or array of shape (n_voxels, )
Transparency of the flatmap.
cmap : str
Name of the matplotlib colormap.
vmin : float or None
Minimum value of the colormap. If None, use the 1st percentile of the
`voxels` array.
vmax : float or None
Minimum value of the colormap. If None, use the 99th percentile of the
`voxels` array.
with_curvature : bool
If True, show the curvature below the data layer.
with_rois : bool
If True, show the ROIs labels above the data layer.
colorbar_location : [left, bottom, width, height]
Location of the colorbar. All quantities are in fractions of figure
width and height.
Returns
-------
ax : matplotlib Axes
Axes where the figure has been plotted.
"""
# create a figure
if ax is None:
flatmap_mask = load_hdf5_array(mapper_file, key='flatmap_mask')
figsize = np.array(flatmap_mask.shape) / 100.
fig = plt.figure(figsize=figsize)
ax = fig.add_axes((0, 0, 1, 1))
ax.axis('off')
# process plotting parameters
if vmin is None:
vmin = np.percentile(voxels, 1)
if vmax is None:
vmax = np.percentile(voxels, 99)
if isinstance(alpha, np.ndarray):
alpha = map_voxels_to_flatmap(alpha, mapper_file)
# plot the data
image = map_voxels_to_flatmap(voxels, mapper_file)
cimg = ax.imshow(image, aspect='equal', zorder=1, alpha=alpha, cmap=cmap,
vmin=vmin, vmax=vmax)
if with_colorbar:
try:
cbar = ax.inset_axes(colorbar_location)
except AttributeError: # for matplotlib < 3.0
cbar = ax.figure.add_axes(colorbar_location)
ax.figure.colorbar(cimg, cax=cbar, orientation='horizontal')
# plot additional layers if present
with h5py.File(mapper_file, mode='r') as hf:
if with_curvature and "flatmap_curvature" in hf.keys():
curvature = load_hdf5_array(mapper_file, key='flatmap_curvature')
background = np.swapaxes(curvature, 0, 1)[::-1]
else:
background = map_voxels_to_flatmap(np.ones_like(voxels),
mapper_file)
ax.imshow(background, aspect='equal', cmap='gray', vmin=0, vmax=1,
zorder=0)
if with_rois and "flatmap_rois" in hf.keys():
rois = load_hdf5_array(mapper_file, key='flatmap_rois')
ax.imshow(
np.swapaxes(rois, 0, 1)[::-1], aspect='equal',
interpolation='bicubic', zorder=2)
return ax
if __name__ == "__main__":
"""
Example for how to load the fMRI test data,
and display the explainable variance on one subject's cortical surface.
More examples at https://github.com/gallantlab/voxelwise_tutorials
"""
import os
directory = os.path.abspath('.')
subject = "S01"
# Load fMRI responses on the test set
file_name = os.path.join(directory, 'responses',
f'{subject}_responses.hdf')
Y_test = load_hdf5_array(file_name, "Y_test")
# compute the explainable variance per voxel, based on the test set repeats
mean_var = np.mean(np.var(Y_test, axis=1), axis=0)
var_mean = np.var(np.mean(Y_test, axis=0), axis=0)
explainable_variance = var_mean / mean_var
# Map to subject flatmap
mapper_file = os.path.join(directory, 'mappers', f'{subject}_mappers.hdf')
plot_flatmap_from_mapper(explainable_variance, mapper_file, vmin=0,
vmax=0.7)
plt.show()