Skip to content

Commit 54a11f6

Browse files
committed
Include the code for data processing in the same tutorial
1 parent 3dfa1ec commit 54a11f6

2 files changed

Lines changed: 101 additions & 50 deletions

File tree

content/gcn_decoding.md

Lines changed: 97 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -68,65 +68,118 @@ print(X.shape)
6868
So we have 1452 time points, with one cognitive annotations each, and for each time point we have recordings of fMRI activity across 675 voxels. We can also see that the cognitive annotations span 9 different categories.
6969

7070
```{code-cell} ipython3
71-
proc_path = os.path.join(data_dir, 'haxby_proc/')
72-
concat_path = os.path.join(data_dir, 'haxby_concat/')
7371
conn_path = os.path.join(data_dir, 'haxby_connectomes/')
74-
split_path = os.path.join(data_dir, 'haxby_split_win/')
75-
```
72+
if not os.path.exists(conn_path):
73+
os.makedirs(conn_path)
7674
77-
```{code-cell} ipython3
7875
import glob
7976
import nilearn.connectome
8077
import numpy as np
8178
import warnings
8279
warnings.filterwarnings(action='once')
83-
# Estimating connectomes
80+
# Estimating connectomes and save for pytorch to load
8481
corr_measure = nilearn.connectome.ConnectivityMeasure(kind="correlation")
8582
conn = corr_measure.fit_transform([X])[0]
86-
87-
sub_no = 4
8883
np.save(os.path.join(conn_path, 'conn_subj{}.npy'.format(sub_no)), conn)
84+
```
8985

90-
conn_files = sorted(glob.glob(conn_path + '/*.npy'))
86+
```{code-cell} ipython3
87+
concat_path = os.path.join(data_dir, 'haxby_concat/')
88+
if not os.path.exists(concat_path):
89+
os.makedirs(concat_path)
90+
91+
concat_bold_files = []
92+
for i in range(0,len(y)):
93+
label = y[i]
94+
concat_bold_files = X[i:i+1]
95+
concat_file_name = concat_path + '{}_concat_fMRI.npy'.format(label)
96+
97+
if os.path.isfile(concat_file_name):
98+
concat_file = np.load(concat_file_name, allow_pickle = True)
99+
concat_file = np.concatenate((concat_file, concat_bold_files), axis = 0)
100+
np.save(concat_file_name, concat_file)
101+
else:
102+
np.save(concat_file_name, concat_bold_files)
103+
104+
105+
106+
import pandas as pd
107+
split_path = os.path.join(data_dir, 'haxby_split_win/')
108+
if not os.path.exists(split_path):
109+
os.makedirs(split_path)
91110
111+
dic_labels = {'rest':0,'face':1,'chair':2,'scissors':3,'shoe':4,'scrambledpix':5,'house':6,'cat':7,'bottle':8}
112+
label_df = pd.DataFrame(columns=['label', 'filename'])
113+
processed_bold_files = sorted(glob.glob(concat_path + '/*.npy'))
114+
window_length = 1
115+
out_file = os.path.join(split_path, '{}_{:04d}.npy')
116+
out_csv = os.path.join(split_path, 'labels.csv')
117+
118+
for proc_bold in processed_bold_files:
119+
120+
ts_data = np.load(proc_bold)
121+
ts_duration = len(ts_data)
122+
123+
ts_filename = os.path.basename(proc_bold)
124+
ts_label = ts_filename.split('_', 1)[0]
125+
126+
valid_label = dic_labels[ts_label]
127+
128+
# Split the timeseries
129+
rem = ts_duration % window_length
130+
n_splits = int(np.floor(ts_duration / window_length))
131+
132+
ts_data = ts_data[:(ts_duration-rem), :]
133+
134+
for j, split_ts in enumerate(np.split(ts_data, n_splits)):
135+
ts_output_file_name = out_file.format(ts_filename, j)
136+
137+
split_ts = np.swapaxes(split_ts, 0, 1)
138+
np.save(ts_output_file_name, split_ts)
139+
curr_label = {'label': valid_label, 'filename': os.path.basename(ts_output_file_name)}
140+
label_df = label_df.append(curr_label, ignore_index=True)
141+
142+
label_df.to_csv(out_csv, index=False)
143+
```
144+
145+
```{code-cell} ipython3
92146
# split dataset
93147
import sys
94-
sys.path.append(os.path.join(".."))
95148
sys.path.append('../src')
96-
97-
import gcn_windows_dataset
149+
from gcn_windows_dataset import TimeWindowsDataset
98150
99151
random_seed = 0
100152
101-
train_dataset = gcn_windows_dataset.TimeWindowsDataset(
102-
data_dir=split_path
103-
, partition="train"
104-
, random_seed=random_seed
105-
, pin_memory=True
106-
, normalize=True,
107-
shuffle = True)
108-
109-
valid_dataset = gcn_windows_dataset.TimeWindowsDataset(
110-
data_dir=split_path
111-
, partition="valid"
112-
, random_seed=random_seed
113-
, pin_memory=True
114-
, normalize=True,
115-
shuffle = True)
116-
117-
test_dataset = gcn_windows_dataset.TimeWindowsDataset(
118-
data_dir=split_path
119-
, partition="test"
120-
, random_seed=random_seed
121-
, pin_memory=True
122-
, normalize=True,
123-
shuffle = True)
153+
train_dataset = TimeWindowsDataset(
154+
data_dir=split_path,
155+
partition="train",
156+
random_seed=random_seed,
157+
pin_memory=True,
158+
normalize=True,
159+
shuffle=True)
160+
161+
valid_dataset = TimeWindowsDataset(
162+
data_dir=split_path,
163+
partition="valid",
164+
random_seed=random_seed,
165+
pin_memory=True,
166+
normalize=True,
167+
shuffle=True)
168+
169+
test_dataset = TimeWindowsDataset(
170+
data_dir=split_path,
171+
partition="test",
172+
random_seed=random_seed,
173+
pin_memory=True,
174+
normalize=True,
175+
shuffle=True)
124176
125177
print("train dataset: {}".format(train_dataset))
126178
print("valid dataset: {}".format(valid_dataset))
127179
print("test dataset: {}".format(test_dataset))
180+
```
128181

129-
182+
```{code-cell} ipython3
130183
import torch
131184
132185
torch.manual_seed(random_seed)
@@ -136,10 +189,6 @@ test_generator = torch.utils.data.DataLoader(test_dataset, batch_size=16, shuffl
136189
train_features, train_labels = next(iter(train_generator))
137190
print(f"Feature batch shape: {train_features.size()}; mean {torch.mean(train_features)}")
138191
print(f"Labels batch shape: {train_labels.size()}; mean {torch.mean(torch.Tensor.float(train_labels))}")
139-
140-
connectomes = []
141-
for conn_file in conn_files:
142-
connectomes += [np.load(conn_file)]
143192
```
144193

145194
## Building brain graphs
@@ -152,11 +201,14 @@ Each node is only connected to *k* other neighbours, which is __8 nodes__ with t
152201
For more details you please check out __*src/graph_construction.py*__ script.
153202

154203
```{code-cell} ipython3
155-
import graph_construction
204+
conn_files = sorted(glob.glob(conn_path + '/*.npy'))
205+
connectomes = []
206+
for conn_file in conn_files:
207+
connectomes += [np.load(conn_file)]
156208
209+
from graph_construction import make_group_graph
157210
158-
graph = graph_construction.make_group_graph(connectomes, self_loops=False,
159-
k=8, symmetric=True)
211+
graph = make_group_graph(connectomes, self_loops=False, k=8, symmetric=True)
160212
```
161213

162214
## Running model
@@ -172,11 +224,10 @@ In this example we will continue with __*window_length = 1*__, which means each
172224
TR is cycle time between corresponding points in fMRI.
173225

174226
```{code-cell} ipython3
175-
import gcn_model
227+
from gcn_model import GCN
176228
177229
window_length = 1
178-
gcn = gcn_model.GCN(graph.edge_index, graph.edge_attr,
179-
n_timepoints=window_length)
230+
gcn = GCN(graph.edge_index, graph.edge_attr, n_timepoints=window_length)
180231
gcn
181232
```
182233

src/graph_construction.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import torch_geometric as tg
44

55

6-
def make_undirected(mat):
6+
def _make_undirected(mat):
77
"""
88
Takes an input adjacency matrix and makes it undirected (symmetric).
99
@@ -21,7 +21,7 @@ def make_undirected(mat):
2121
return sym
2222

2323

24-
def knn_graph_quantile(mat, self_loops=False, k=8, symmetric=True):
24+
def _knn_graph_quantile(mat, self_loops=False, k=8, symmetric=True):
2525
"""
2626
Takes an input correlation matrix and returns a k-Nearest
2727
Neighbour weighted undirected adjacency matrix.
@@ -46,7 +46,7 @@ def knn_graph_quantile(mat, self_loops=False, k=8, symmetric=True):
4646
if not self_loops:
4747
np.fill_diagonal(adj, 0)
4848
if symmetric:
49-
adj = make_undirected(adj)
49+
adj = _make_undirected(adj)
5050
return adj
5151

5252

@@ -75,7 +75,7 @@ def make_group_graph(connectomes, k=8, self_loops=False, symmetric=True):
7575
# Group average connectome and nndirected 8 k-NN graph
7676
avg_conn = np.array(connectomes).mean(axis=0)
7777
avg_conn = np.round(avg_conn, 6)
78-
avg_conn_k = knn_graph_quantile(avg_conn, k=k, self_loops=self_loops, symmetric=symmetric)
78+
avg_conn_k = _knn_graph_quantile(avg_conn, k=k, self_loops=self_loops, symmetric=symmetric)
7979

8080
# Format matrix into graph for torch_geometric
8181
adj_sparse = tg.utils.dense_to_sparse(torch.from_numpy(avg_conn_k))

0 commit comments

Comments
 (0)