testtest123 commited on
Commit
35a599b
·
0 Parent(s):

Sync from GitHub ncclab-sustech/DCA main

Browse files

Source: https://github.com/ncclab-sustech/DCA@3b717c902b8ff8b153293e441dfac2f716d254a0

.gitattributes ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ DCA/data/fmri/101915_FWHM6.nii.gz filter=lfs diff=lfs merge=lfs -text
2
+ DCA/data/fmri/101915_raw.nii.gz filter=lfs diff=lfs merge=lfs -text
3
+ AtlaScore/downstream/fc_data/fc_data.zip filter=lfs diff=lfs merge=lfs -text
4
+ DCA/data/swin_model_epoch_30.pth filter=lfs diff=lfs merge=lfs -text
5
+ DCA/data/fmri/101915_FWHM3.nii.gz filter=lfs diff=lfs merge=lfs -text
6
+ *.zip filter=lfs diff=lfs merge=lfs -text
7
+ *.npy filter=lfs diff=lfs merge=lfs -text
8
+ *.png filter=lfs diff=lfs merge=lfs -text
9
+ *.pth filter=lfs diff=lfs merge=lfs -text
10
+ *.gz filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__/
AtlaScore/downstream/demo.ipynb ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "71ead501",
6
+ "metadata": {},
7
+ "source": [
8
+ "This notebook demonstrates how to run AtlaScore downstream tasks on the proposed **DCA100 atlas**.\n",
9
+ "\n",
10
+ "For DCA100, we provide precomputed functional connectivity (FC) features required to run the downstream evaluations. You can directly execute the section *run AtlaScore downstream tasks* to evaluate the performance of DCA100.\n",
11
+ "\n",
12
+ "For other atlases, you will need to first download the required NIfTI data, extract the region-wise time series, and compute FC features. These steps are provided in the *get nii data* and *get FC data* sections.\n",
13
+ "\n",
14
+ "Note: Preprocessed data from the ADNI dataset will be shared via OneDrive after the paper is accepted. The corresponding download link and notebook updates will be made available at that time. Until then, attempting to run `get_fc_ADNI` or `AD_diagnosis` for other atlases will result in errors (as the required data is not yet accessible)."
15
+ ]
16
+ },
17
+ {
18
+ "cell_type": "code",
19
+ "execution_count": 1,
20
+ "id": "cb56d181",
21
+ "metadata": {},
22
+ "outputs": [],
23
+ "source": [
24
+ "import numpy as np\n",
25
+ "import downstream\n",
26
+ "import zipfile"
27
+ ]
28
+ },
29
+ {
30
+ "cell_type": "markdown",
31
+ "id": "79e7c8c5",
32
+ "metadata": {},
33
+ "source": [
34
+ "#### get nii data"
35
+ ]
36
+ },
37
+ {
38
+ "cell_type": "markdown",
39
+ "id": "3eda46a0",
40
+ "metadata": {},
41
+ "source": [
42
+ "##### HCP"
43
+ ]
44
+ },
45
+ {
46
+ "cell_type": "markdown",
47
+ "id": "785975f0",
48
+ "metadata": {},
49
+ "source": [
50
+ "To access and download Human Connectome Project (HCP) data locally for use with AtlaScore, you must first obtain the necessary credentials. Visit the official HCP website at [https://db.humanconnectome.org](https://db.humanconnectome.org), create an account, and request data access. Once your request is approved, you will be able to retrieve your `access_key` and `secret_key` from your account.\n",
51
+ "\n",
52
+ "These credentials are required to authenticate and download data using the provided scripts. Please insert your keys into the corresponding variables in the notebook.\n",
53
+ "\n",
54
+ "Downloading the required HCP data typically takes around 15 hours and requires over 500 GB of disk space."
55
+ ]
56
+ },
57
+ {
58
+ "cell_type": "code",
59
+ "execution_count": null,
60
+ "id": "5d2cd2d1",
61
+ "metadata": {},
62
+ "outputs": [],
63
+ "source": [
64
+ "# access_key = 'your_access_key'\n",
65
+ "# secret_key = 'your_secret_key'\n",
66
+ "\n",
67
+ "# for subj in np.loadtxt('./docs/HCP_subjlist.txt', dtype = str):\n",
68
+ "\n",
69
+ "# downstream.get_sub_HCP_rfMRI(subject = subj, access_key = access_key, secret_key = secret_key)\n",
70
+ "# downstream.get_sub_HCP_tfMRI(subject = subj, access_key = access_key, secret_key = secret_key)"
71
+ ]
72
+ },
73
+ {
74
+ "cell_type": "markdown",
75
+ "id": "13c96145",
76
+ "metadata": {},
77
+ "source": [
78
+ "##### ABIDE"
79
+ ]
80
+ },
81
+ {
82
+ "cell_type": "markdown",
83
+ "id": "375a6ff8",
84
+ "metadata": {},
85
+ "source": [
86
+ "To use the ABIDE dataset for functional connectivity analysis, you will need to download the preprocessed data. The dataset includes resting-state fMRI scans from multiple sites and subjects.\n",
87
+ "\n",
88
+ "Please note that downloading the full ABIDE dataset may take up to 9 hours and requires approximately 90 GB of disk space. Make sure you have sufficient bandwidth and storage before starting the download."
89
+ ]
90
+ },
91
+ {
92
+ "cell_type": "code",
93
+ "execution_count": null,
94
+ "id": "2924faf6",
95
+ "metadata": {},
96
+ "outputs": [],
97
+ "source": [
98
+ "# downstream.get_ABIDE()"
99
+ ]
100
+ },
101
+ {
102
+ "cell_type": "markdown",
103
+ "id": "fe6a85a6",
104
+ "metadata": {},
105
+ "source": [
106
+ "##### ADNI"
107
+ ]
108
+ },
109
+ {
110
+ "cell_type": "markdown",
111
+ "id": "8a427acd",
112
+ "metadata": {},
113
+ "source": [
114
+ "The ADNI dataset contains multimodal neuroimaging data, including structural and functional MRI. For our analysis, we used preprocessed data derived from ADNI scans.\n",
115
+ "\n",
116
+ "The total size of the processed dataset is approximately 70 GB. This preprocessed version will be made available for download via OneDrive after the paper is accepted for publication."
117
+ ]
118
+ },
119
+ {
120
+ "cell_type": "markdown",
121
+ "id": "df3d8336",
122
+ "metadata": {},
123
+ "source": [
124
+ "#### get FC data"
125
+ ]
126
+ },
127
+ {
128
+ "cell_type": "markdown",
129
+ "id": "c12ae2e8",
130
+ "metadata": {},
131
+ "source": [
132
+ "##### HCP"
133
+ ]
134
+ },
135
+ {
136
+ "cell_type": "markdown",
137
+ "id": "45082e6b",
138
+ "metadata": {},
139
+ "source": [
140
+ "To run the analysis on your own atlas, please modify the `atlas_name` and `atlas_loc` arguments in the corresponding functions."
141
+ ]
142
+ },
143
+ {
144
+ "cell_type": "code",
145
+ "execution_count": null,
146
+ "id": "051d4cbb",
147
+ "metadata": {},
148
+ "outputs": [],
149
+ "source": [
150
+ "# for subj in np.loadtxt('./docs/HCP_subjlist.txt', dtype = str):\n",
151
+ "\n",
152
+ "# downstream.get_fc_HCP_rfMRI(subject = subj, atlas_name = 'DCA100', atlas_loc = './docs/DCA100.nii.gz')\n",
153
+ "# downstream.get_fc_HCP_tfMRI(subject = subj, atlas_name = 'DCA100', atlas_loc = './docs/DCA100.nii.gz')"
154
+ ]
155
+ },
156
+ {
157
+ "cell_type": "markdown",
158
+ "id": "5f831e97",
159
+ "metadata": {},
160
+ "source": [
161
+ "##### ABIDE"
162
+ ]
163
+ },
164
+ {
165
+ "cell_type": "markdown",
166
+ "id": "156aeebf",
167
+ "metadata": {},
168
+ "source": [
169
+ "To run the analysis on your own atlas, please modify the `atlas_name` and `atlas_loc` arguments in the corresponding functions."
170
+ ]
171
+ },
172
+ {
173
+ "cell_type": "code",
174
+ "execution_count": null,
175
+ "id": "b568852b",
176
+ "metadata": {},
177
+ "outputs": [],
178
+ "source": [
179
+ "# downstream.get_fc_ABIDE(atlas_name = 'DCA100', atlas_loc = './docs/DCA100.nii.gz')"
180
+ ]
181
+ },
182
+ {
183
+ "cell_type": "markdown",
184
+ "id": "0b5eeb0c",
185
+ "metadata": {},
186
+ "source": [
187
+ "##### ADNI"
188
+ ]
189
+ },
190
+ {
191
+ "cell_type": "markdown",
192
+ "id": "021a9c9c",
193
+ "metadata": {},
194
+ "source": [
195
+ "To run the analysis on your own atlas, please modify the `atlas_name` and `atlas_loc` arguments in the corresponding functions."
196
+ ]
197
+ },
198
+ {
199
+ "cell_type": "code",
200
+ "execution_count": null,
201
+ "id": "4cf92856",
202
+ "metadata": {},
203
+ "outputs": [],
204
+ "source": [
205
+ "# downstream.get_fc_ADNI(atlas_name = 'DCA100', atlas_loc = './docs/DCA100.nii.gz')"
206
+ ]
207
+ },
208
+ {
209
+ "cell_type": "markdown",
210
+ "id": "b4faef6a",
211
+ "metadata": {},
212
+ "source": [
213
+ "#### run AtlaScore downstream tasks"
214
+ ]
215
+ },
216
+ {
217
+ "cell_type": "code",
218
+ "execution_count": 2,
219
+ "id": "835bd40c",
220
+ "metadata": {},
221
+ "outputs": [
222
+ {
223
+ "name": "stdout",
224
+ "output_type": "stream",
225
+ "text": [
226
+ "--- DCA100 downstream report ---\n",
227
+ "Gender classification: 0.666±0.080\n",
228
+ "Fluid intelligence: 0.491±0.082\n",
229
+ "Cognitive task (7-way): 0.869±0.062\n",
230
+ "Cognitive task (24-way): 0.452±0.030\n",
231
+ "Autism diagnosis: 0.655±0.054\n",
232
+ "AD diagnosis: 0.387±0.077\n",
233
+ "FC stability: 0.650±0.045\n",
234
+ "Fingerprinting: 0.696±0.201\n",
235
+ "Age group classification: 0.452±0.136\n",
236
+ "Crystallized intelligence: 0.472±0.095\n",
237
+ "General intelligence: 0.442±0.104\n",
238
+ "Autism cross-site: 0.662±0.068\n"
239
+ ]
240
+ }
241
+ ],
242
+ "source": [
243
+ "with zipfile.ZipFile('./fc_data/fc_data.zip', 'r') as zip_file: zip_file.extractall('./fc_data/')\n",
244
+ "downstream.downstream_all(atlas_name = 'DCA100')"
245
+ ]
246
+ }
247
+ ],
248
+ "metadata": {
249
+ "kernelspec": {
250
+ "display_name": "connectome",
251
+ "language": "python",
252
+ "name": "python3"
253
+ },
254
+ "language_info": {
255
+ "codemirror_mode": {
256
+ "name": "ipython",
257
+ "version": 3
258
+ },
259
+ "file_extension": ".py",
260
+ "mimetype": "text/x-python",
261
+ "name": "python",
262
+ "nbconvert_exporter": "python",
263
+ "pygments_lexer": "ipython3",
264
+ "version": "3.12.2"
265
+ }
266
+ },
267
+ "nbformat": 4,
268
+ "nbformat_minor": 5
269
+ }
AtlaScore/downstream/docs/DCA100.nii.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:55cb73621697360e6107394f51fc0606367c1c43a88d96c8693c0d810d91d8d1
3
+ size 132151
AtlaScore/downstream/docs/HCP_subjlist.txt ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 100206
2
+ 100307
3
+ 100408
4
+ 100610
5
+ 101006
6
+ 101107
7
+ 101309
8
+ 101915
9
+ 102008
10
+ 102109
11
+ 102311
12
+ 102513
13
+ 102614
14
+ 102715
15
+ 102816
16
+ 103010
17
+ 103111
18
+ 103212
19
+ 103414
20
+ 103515
21
+ 103818
22
+ 104012
23
+ 104416
24
+ 104820
25
+ 105014
26
+ 105115
27
+ 105216
28
+ 105620
29
+ 105923
30
+ 106016
31
+ 106319
32
+ 106521
33
+ 106824
34
+ 107018
35
+ 107321
36
+ 107422
37
+ 107725
38
+ 108020
39
+ 108121
40
+ 108222
41
+ 108323
42
+ 108525
43
+ 108828
44
+ 109123
45
+ 109325
46
+ 109830
47
+ 110007
48
+ 110411
49
+ 110613
50
+ 111009
51
+ 111211
52
+ 111312
53
+ 111413
54
+ 111514
55
+ 111716
56
+ 112112
57
+ 112314
58
+ 112516
59
+ 112920
60
+ 113215
61
+ 113316
62
+ 113619
63
+ 113922
64
+ 114217
65
+ 114318
66
+ 114419
67
+ 114621
68
+ 114823
69
+ 114924
70
+ 115017
71
+ 115219
72
+ 115320
73
+ 115724
74
+ 115825
75
+ 116524
76
+ 116726
77
+ 117021
78
+ 117122
79
+ 117324
80
+ 117930
81
+ 118023
82
+ 118124
83
+ 118225
84
+ 118528
85
+ 118730
86
+ 118831
87
+ 118932
88
+ 119025
89
+ 119126
90
+ 119732
91
+ 119833
92
+ 120111
93
+ 120212
94
+ 120414
95
+ 120515
96
+ 120717
97
+ 121416
98
+ 121618
99
+ 121921
100
+ 122317
AtlaScore/downstream/docs/behavior_ABIDE.csv ADDED
@@ -0,0 +1,872 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SUB_ID,SITE_ID,FILE_ID,DX_GROUP,DSM_IV_TR,AGE_AT_SCAN,SEX,HANDEDNESS_CATEGORY
2
+ 50003,PITT,Pitt_0050003,1,1,24.45,1,R
3
+ 50004,PITT,Pitt_0050004,1,1,19.09,1,R
4
+ 50005,PITT,Pitt_0050005,1,1,13.73,2,R
5
+ 50006,PITT,Pitt_0050006,1,1,13.37,1,L
6
+ 50007,PITT,Pitt_0050007,1,1,17.78,1,R
7
+ 50008,PITT,Pitt_0050008,1,1,32.45,1,R
8
+ 50010,PITT,Pitt_0050010,1,1,35.2,1,L
9
+ 50011,PITT,Pitt_0050011,1,1,16.93,1,L
10
+ 50012,PITT,Pitt_0050012,1,1,21.48,1,R
11
+ 50013,PITT,Pitt_0050013,1,1,9.33,1,R
12
+ 50014,PITT,Pitt_0050014,1,1,14.2,1,R
13
+ 50015,PITT,Pitt_0050015,1,1,14.2,1,R
14
+ 50016,PITT,Pitt_0050016,1,1,21.82,1,R
15
+ 50020,PITT,Pitt_0050020,1,1,20.83,1,R
16
+ 50022,PITT,Pitt_0050022,1,1,16.99,1,R
17
+ 50023,PITT,Pitt_0050023,1,1,12.64,2,R
18
+ 50024,PITT,Pitt_0050024,1,1,22.64,1,R
19
+ 50025,PITT,Pitt_0050025,1,1,31.72,1,R
20
+ 50026,PITT,Pitt_0050026,1,1,16.28,1,R
21
+ 50027,PITT,Pitt_0050027,1,1,12.24,1,R
22
+ 50028,PITT,Pitt_0050028,1,1,12.74,1,R
23
+ 50030,PITT,Pitt_0050030,2,0,25.12,1,-9999
24
+ 50031,PITT,Pitt_0050031,2,0,12.92,1,R
25
+ 50032,PITT,Pitt_0050032,2,0,19.8,1,R
26
+ 50033,PITT,Pitt_0050033,2,0,12.15,1,R
27
+ 50034,PITT,Pitt_0050034,2,0,14.77,1,R
28
+ 50035,PITT,Pitt_0050035,2,0,17.36,1,R
29
+ 50036,PITT,Pitt_0050036,2,0,13.28,2,R
30
+ 50037,PITT,Pitt_0050037,2,0,19.16,1,R
31
+ 50038,PITT,Pitt_0050038,2,0,13.95,2,R
32
+ 50039,PITT,Pitt_0050039,2,0,30.66,1,R
33
+ 50040,PITT,Pitt_0050040,2,0,24.6,1,R
34
+ 50041,PITT,Pitt_0050041,2,0,27.92,1,R
35
+ 50042,PITT,Pitt_0050042,2,0,33.17,1,R
36
+ 50043,PITT,Pitt_0050043,2,0,13.78,1,R
37
+ 50044,PITT,Pitt_0050044,2,0,17.13,1,R
38
+ 50045,PITT,Pitt_0050045,2,0,15.7,1,R
39
+ 50046,PITT,Pitt_0050046,2,0,20.65,1,R
40
+ 50047,PITT,Pitt_0050047,2,0,15.35,1,R
41
+ 50048,PITT,Pitt_0050048,2,0,11.81,1,R
42
+ 50049,PITT,Pitt_0050049,2,0,15.82,2,R
43
+ 50050,PITT,Pitt_0050050,2,0,14.37,1,L
44
+ 50051,PITT,Pitt_0050051,2,0,12.83,1,R
45
+ 50052,PITT,Pitt_0050052,2,0,33.24,1,R
46
+ 50053,PITT,Pitt_0050053,1,1,12.03,1,R
47
+ 50054,PITT,Pitt_0050054,2,0,9.44,1,R
48
+ 50056,PITT,Pitt_0050056,1,1,13.59,1,R
49
+ 50057,PITT,Pitt_0050057,1,1,12.62,2,R
50
+ 50059,PITT,Pitt_0050059,2,0,21.22,2,R
51
+ 50060,PITT,Pitt_0050060,2,0,20.34,1,R
52
+ 50102,OLIN,Olin_0050102,2,0,14,1,R
53
+ 50103,OLIN,Olin_0050103,2,0,14,1,R
54
+ 50104,OLIN,Olin_0050104,2,0,16,1,R
55
+ 50105,OLIN,Olin_0050105,2,0,17,1,R
56
+ 50106,OLIN,Olin_0050106,2,0,10,1,R
57
+ 50107,OLIN,Olin_0050107,2,0,21,1,R
58
+ 50109,OLIN,Olin_0050109,2,0,20,1,R
59
+ 50111,OLIN,Olin_0050111,2,0,14,1,R
60
+ 50112,OLIN,Olin_0050112,2,0,17,1,R
61
+ 50113,OLIN,Olin_0050113,2,0,15,2,R
62
+ 50114,OLIN,Olin_0050114,2,0,20,2,R
63
+ 50115,OLIN,Olin_0050115,2,0,23,1,L
64
+ 50116,OLIN,Olin_0050116,2,0,15,1,R
65
+ 50117,OLIN,Olin_0050117,2,0,21,1,L
66
+ 50118,OLIN,Olin_0050118,1,0,15,1,R
67
+ 50119,OLIN,Olin_0050119,1,0,19,2,R
68
+ 50121,OLIN,Olin_0050121,1,0,20,1,R
69
+ 50123,OLIN,Olin_0050123,1,0,17,1,R
70
+ 50124,OLIN,Olin_0050124,1,0,18,1,R
71
+ 50125,OLIN,Olin_0050125,1,0,24,2,R
72
+ 50127,OLIN,Olin_0050127,1,0,14,2,R
73
+ 50128,OLIN,Olin_0050128,1,0,16,1,R
74
+ 50129,OLIN,Olin_0050129,1,0,12,1,R
75
+ 50130,OLIN,Olin_0050130,1,0,18,1,R
76
+ 50131,OLIN,Olin_0050131,1,0,21,1,L
77
+ 50132,OLIN,Olin_0050132,1,0,16,1,R
78
+ 50134,OLIN,Olin_0050134,1,0,18,1,L
79
+ 50135,OLIN,Olin_0050135,1,0,12,1,L
80
+ 50142,OHSU,OHSU_0050142,1,-9999,13.99,1,L
81
+ 50143,OHSU,OHSU_0050143,1,-9999,13.79,1,R
82
+ 50144,OHSU,OHSU_0050144,1,-9999,10.22,1,R
83
+ 50145,OHSU,OHSU_0050145,1,-9999,10.75,1,R
84
+ 50146,OHSU,OHSU_0050146,1,-9999,8,1,R
85
+ 50147,OHSU,OHSU_0050147,1,-9999,11.35,1,R
86
+ 50148,OHSU,OHSU_0050148,1,-9999,12.65,1,R
87
+ 50149,OHSU,OHSU_0050149,1,-9999,12.32,1,R
88
+ 50150,OHSU,OHSU_0050150,1,-9999,9.42,1,R
89
+ 50152,OHSU,OHSU_0050152,1,-9999,9.73,1,R
90
+ 50153,OHSU,OHSU_0050153,1,-9999,9.72,1,R
91
+ 50156,OHSU,OHSU_0050156,1,-9999,15.23,1,R
92
+ 50157,OHSU,OHSU_0050157,2,-9999,10.5,1,R
93
+ 50158,OHSU,OHSU_0050158,2,-9999,11.55,1,R
94
+ 50159,OHSU,OHSU_0050159,2,-9999,10.29,1,R
95
+ 50160,OHSU,OHSU_0050160,2,-9999,11.45,1,R
96
+ 50161,OHSU,OHSU_0050161,2,-9999,9.15,1,R
97
+ 50162,OHSU,OHSU_0050162,2,-9999,8.94,1,R
98
+ 50163,OHSU,OHSU_0050163,2,-9999,9.4,1,R
99
+ 50164,OHSU,OHSU_0050164,2,-9999,8.86,1,R
100
+ 50167,OHSU,OHSU_0050167,2,-9999,10.08,1,R
101
+ 50168,OHSU,OHSU_0050168,2,-9999,9.69,1,R
102
+ 50169,OHSU,OHSU_0050169,2,-9999,11.99,1,R
103
+ 50170,OHSU,OHSU_0050170,2,-9999,10.53,1,R
104
+ 50171,OHSU,OHSU_0050171,2,-9999,10.64,1,R
105
+ 50182,SDSU,SDSU_0050182,1,2,16.61,1,R
106
+ 50183,SDSU,SDSU_0050183,1,1,14.14,1,R
107
+ 50184,SDSU,SDSU_0050184,1,2,17.15,1,R
108
+ 50186,SDSU,SDSU_0050186,1,2,12.13,1,R
109
+ 50187,SDSU,SDSU_0050187,1,2,16.48,1,R
110
+ 50188,SDSU,SDSU_0050188,1,-9999,15.4,1,R
111
+ 50189,SDSU,SDSU_0050189,1,2,16.64,1,R
112
+ 50190,SDSU,SDSU_0050190,1,2,13.99,1,R
113
+ 50193,SDSU,SDSU_0050193,2,0,14.75,1,R
114
+ 50194,SDSU,SDSU_0050194,2,0,13.35,1,L
115
+ 50195,SDSU,SDSU_0050195,2,0,12.58,1,R
116
+ 50196,SDSU,SDSU_0050196,2,0,12.91,1,R
117
+ 50198,SDSU,SDSU_0050198,2,0,15.28,1,R
118
+ 50199,SDSU,SDSU_0050199,2,0,15.53,1,R
119
+ 50200,SDSU,SDSU_0050200,2,0,13.88,1,R
120
+ 50201,SDSU,SDSU_0050201,2,0,13.77,2,R
121
+ 50202,SDSU,SDSU_0050202,2,0,12.08,1,R
122
+ 50203,SDSU,SDSU_0050203,2,0,16.05,1,L
123
+ 50204,SDSU,SDSU_0050204,2,0,14.86,1,R
124
+ 50205,SDSU,SDSU_0050205,2,0,14.1,2,R
125
+ 50206,SDSU,SDSU_0050206,2,0,8.67,2,R
126
+ 50208,SDSU,SDSU_0050208,2,0,13.78,2,R
127
+ 50210,SDSU,SDSU_0050210,2,0,16.6,1,R
128
+ 50213,SDSU,SDSU_0050213,2,0,12.38,2,R
129
+ 50214,SDSU,SDSU_0050214,2,0,14.76,1,R
130
+ 50215,SDSU,SDSU_0050215,2,0,16.88,2,R
131
+ 50217,SDSU,SDSU_0050217,2,0,12.9,1,R
132
+ 50232,TRINITY,Trinity_0050232,1,3,23.08,1,R
133
+ 50233,TRINITY,Trinity_0050233,1,3,20.75,1,R
134
+ 50234,TRINITY,Trinity_0050234,1,3,15.66,1,R
135
+ 50236,TRINITY,Trinity_0050236,1,3,19.16,1,R
136
+ 50237,TRINITY,Trinity_0050237,1,3,21.42,1,R
137
+ 50239,TRINITY,Trinity_0050239,1,1,17.03,1,R
138
+ 50240,TRINITY,Trinity_0050240,1,2,15.05,1,R
139
+ 50241,TRINITY,Trinity_0050241,1,1,17.17,1,R
140
+ 50243,TRINITY,Trinity_0050243,1,1,13.75,1,R
141
+ 50245,TRINITY,Trinity_0050245,1,1,21.58,1,R
142
+ 50247,TRINITY,Trinity_0050247,1,2,12,1,R
143
+ 50248,TRINITY,Trinity_0050248,1,1,13.58,1,R
144
+ 50249,TRINITY,Trinity_0050249,1,1,13.83,1,R
145
+ 50250,TRINITY,Trinity_0050250,1,1,13.91,1,R
146
+ 50251,TRINITY,Trinity_0050251,1,1,17.25,1,R
147
+ 50252,TRINITY,Trinity_0050252,1,2,15.25,1,R
148
+ 50253,TRINITY,Trinity_0050253,1,2,18.01,1,R
149
+ 50254,TRINITY,Trinity_0050254,1,2,19.41,1,R
150
+ 50255,TRINITY,Trinity_0050255,1,2,14.41,1,R
151
+ 50257,TRINITY,Trinity_0050257,2,0,14.91,1,R
152
+ 50259,TRINITY,Trinity_0050259,2,0,19.83,1,R
153
+ 50260,TRINITY,Trinity_0050260,2,0,20.33,1,R
154
+ 50261,TRINITY,Trinity_0050261,2,0,20.08,1,R
155
+ 50262,TRINITY,Trinity_0050262,2,0,21.33,1,R
156
+ 50263,TRINITY,Trinity_0050263,2,0,19.08,1,R
157
+ 50264,TRINITY,Trinity_0050264,2,0,25.66,1,R
158
+ 50265,TRINITY,Trinity_0050265,2,0,12.25,1,R
159
+ 50266,TRINITY,Trinity_0050266,2,0,15.91,1,R
160
+ 50267,TRINITY,Trinity_0050267,2,0,17.5,1,R
161
+ 50268,TRINITY,Trinity_0050268,2,0,14.41,1,R
162
+ 50269,TRINITY,Trinity_0050269,2,0,14.66,1,R
163
+ 50270,TRINITY,Trinity_0050270,2,0,19.33,1,R
164
+ 50271,TRINITY,Trinity_0050271,2,0,19.66,1,R
165
+ 50272,UM_1,UM_1_0050272,1,1,14.2,1,R
166
+ 50273,UM_1,UM_1_0050273,1,1,16.8,1,R
167
+ 50274,UM_1,UM_1_0050274,1,1,14.2,1,R
168
+ 50275,UM_1,UM_1_0050275,1,1,11.5,1,L
169
+ 50276,UM_1,UM_1_0050276,1,1,16.8,2,-9999
170
+ 50278,UM_1,UM_1_0050278,1,1,11.3,2,R
171
+ 50282,UM_1,UM_1_0050282,1,1,15.2,1,
172
+ 50284,UM_1,UM_1_0050284,1,2,11.2,2,R
173
+ 50285,UM_1,UM_1_0050285,1,1,12.8,2,R
174
+ 50287,UM_1,UM_1_0050287,1,1,14.4,1,L
175
+ 50289,UM_1,UM_1_0050289,1,2,12.9,1,L
176
+ 50290,UM_1,UM_1_0050290,1,1,14,1,R
177
+ 50291,UM_1,UM_1_0050291,1,1,13.9,1,R
178
+ 50292,UM_1,UM_1_0050292,1,1,12.6,1,R
179
+ 50293,UM_1,UM_1_0050293,1,1,12.4,1,R
180
+ 50294,UM_1,UM_1_0050294,1,2,12.6,1,R
181
+ 50295,UM_1,UM_1_0050295,1,1,11.5,1,R
182
+ 50297,UM_1,UM_1_0050297,1,-9999,15.9,1,R
183
+ 50298,UM_1,UM_1_0050298,1,1,12.8,1,R
184
+ 50300,UM_1,UM_1_0050300,1,3,9.7,2,R
185
+ 50301,UM_1,UM_1_0050301,1,1,16.1,1,L
186
+ 50302,UM_1,UM_1_0050302,1,-9999,10.4,2,R
187
+ 50304,UM_1,UM_1_0050304,1,1,11,1,-9999
188
+ 50308,UM_1,UM_1_0050308,1,1,8.9,1,-9999
189
+ 50310,UM_1,UM_1_0050310,1,1,9.7,1,R
190
+ 50312,UM_1,UM_1_0050312,1,1,11.2,1,R
191
+ 50314,UM_1,UM_1_0050314,1,2,16.1,1,R
192
+ 50315,UM_1,UM_1_0050315,1,1,13.4,1,R
193
+ 50318,UM_1,UM_1_0050318,1,1,9.2,1,L
194
+ 50319,UM_1,UM_1_0050319,1,1,15,2,R
195
+ 50320,UM_1,UM_1_0050320,1,1,18.6,1,R
196
+ 50321,UM_1,UM_1_0050321,1,1,18,2,R
197
+ 50324,UM_1,UM_1_0050324,1,1,13.8,1,R
198
+ 50325,UM_1,UM_1_0050325,1,2,13.1,1,R
199
+ 50327,UM_1,UM_1_0050327,2,0,15.3,1,L
200
+ 50329,UM_1,UM_1_0050329,2,0,17.1,1,R
201
+ 50330,UM_1,UM_1_0050330,2,0,16.1,1,R
202
+ 50331,UM_1,UM_1_0050331,2,0,17.2,1,L
203
+ 50332,UM_1,UM_1_0050332,2,0,10.4,1,R
204
+ 50333,UM_1,UM_1_0050333,2,0,10.2,1,R
205
+ 50334,UM_1,UM_1_0050334,2,0,11,1,R
206
+ 50335,UM_1,UM_1_0050335,2,0,17.8,1,R
207
+ 50336,UM_1,UM_1_0050336,2,0,14.3,2,R
208
+ 50337,UM_1,UM_1_0050337,2,0,11.8,1,R
209
+ 50338,UM_1,UM_1_0050338,2,0,13.5,2,R
210
+ 50339,UM_1,UM_1_0050339,2,0,18,1,R
211
+ 50340,UM_1,UM_1_0050340,2,0,16.1,2,R
212
+ 50341,UM_1,UM_1_0050341,2,0,18.2,2,R
213
+ 50342,UM_1,UM_1_0050342,2,0,12.6,1,R
214
+ 50343,UM_1,UM_1_0050343,2,0,13.8,2,R
215
+ 50344,UM_1,UM_1_0050344,2,0,18.2,1,R
216
+ 50345,UM_1,UM_1_0050345,2,0,17.3,1,R
217
+ 50346,UM_1,UM_1_0050346,2,0,18.9,1,R
218
+ 50347,UM_1,UM_1_0050347,2,0,15.6,1,R
219
+ 50348,UM_1,UM_1_0050348,2,0,19.2,2,R
220
+ 50349,UM_1,UM_1_0050349,2,0,18.9,1,R
221
+ 50350,UM_1,UM_1_0050350,2,0,12.4,1,R
222
+ 50351,UM_1,UM_1_0050351,2,0,16.8,1,R
223
+ 50352,UM_1,UM_1_0050352,2,0,15.5,1,L
224
+ 50353,UM_1,UM_1_0050353,2,0,13.1,2,R
225
+ 50354,UM_1,UM_1_0050354,2,0,14,2,R
226
+ 50355,UM_1,UM_1_0050355,2,0,10.9,1,R
227
+ 50356,UM_1,UM_1_0050356,2,0,17.2,2,L
228
+ 50357,UM_1,UM_1_0050357,2,0,9.5,2,R
229
+ 50358,UM_1,UM_1_0050358,2,0,9.8,1,R
230
+ 50359,UM_1,UM_1_0050359,2,0,10.4,1,R
231
+ 50360,UM_1,UM_1_0050360,2,0,13.9,1,R
232
+ 50361,UM_1,UM_1_0050361,2,0,18.3,2,-9999
233
+ 50362,UM_1,UM_1_0050362,2,0,11.2,1,L
234
+ 50363,UM_1,UM_1_0050363,2,0,9.8,1,R
235
+ 50364,UM_1,UM_1_0050364,2,0,10.8,1,R
236
+ 50365,UM_1,UM_1_0050365,2,0,15.6,1,L
237
+ 50366,UM_1,UM_1_0050366,2,0,8.2,1,-9999
238
+ 50367,UM_1,UM_1_0050367,2,0,10.8,1,-9999
239
+ 50368,UM_1,UM_1_0050368,2,0,17.9,1,R
240
+ 50369,UM_1,UM_1_0050369,2,0,14.8,2,R
241
+ 50370,UM_1,UM_1_0050370,2,0,12.8,1,R
242
+ 50372,UM_1,UM_1_0050372,2,0,10.2,1,R
243
+ 50373,UM_1,UM_1_0050373,2,0,17.2,2,R
244
+ 50374,UM_1,UM_1_0050374,2,0,9.7,2,R
245
+ 50375,UM_1,UM_1_0050375,2,0,11.6,2,R
246
+ 50376,UM_1,UM_1_0050376,2,0,9.2,1,R
247
+ 50377,UM_1,UM_1_0050377,2,0,11.5,1,R
248
+ 50379,UM_1,UM_1_0050379,2,0,14.3,2,R
249
+ 50380,UM_1,UM_1_0050380,2,0,17.4,2,L
250
+ 50381,UM_1,UM_1_0050381,2,0,16.5,1,R
251
+ 50382,UM_2,UM_2_0050382,2,0,28.8,1,R
252
+ 50383,UM_2,UM_2_0050383,2,0,14.4,1,R
253
+ 50385,UM_2,UM_2_0050385,2,0,17.8,1,R
254
+ 50386,UM_2,UM_2_0050386,2,0,17.8,1,R
255
+ 50387,UM_2,UM_2_0050387,2,0,14,1,R
256
+ 50388,UM_2,UM_2_0050388,2,0,26.8,1,R
257
+ 50390,UM_2,UM_2_0050390,2,0,14.5,1,R
258
+ 50391,UM_2,UM_2_0050391,2,0,17.2,1,L
259
+ 50397,UM_2,UM_2_0050397,1,1,14.7,1,-9999
260
+ 50399,UM_2,UM_2_0050399,1,2,17.4,1,R
261
+ 50402,UM_2,UM_2_0050402,1,1,13.1,1,R
262
+ 50403,UM_2,UM_2_0050403,1,2,12.8,1,R
263
+ 50404,UM_2,UM_2_0050404,1,1,15.8,1,R
264
+ 50405,UM_2,UM_2_0050405,1,1,16.6,1,R
265
+ 50406,UM_2,UM_2_0050406,1,1,15.2,1,R
266
+ 50407,UM_2,UM_2_0050407,1,1,16.6,2,R
267
+ 50408,UM_2,UM_2_0050408,1,1,14.8,1,R
268
+ 50410,UM_2,UM_2_0050410,1,1,16.1,1,R
269
+ 50411,UM_2,UM_2_0050411,1,2,14,1,R
270
+ 50412,UM_2,UM_2_0050412,1,1,13.2,1,R
271
+ 50413,UM_2,UM_2_0050413,1,1,13.1,1,L
272
+ 50414,UM_2,UM_2_0050414,2,0,13.8,2,R
273
+ 50415,UM_2,UM_2_0050415,2,0,17.6,1,R
274
+ 50416,UM_2,UM_2_0050416,2,0,14.8,1,R
275
+ 50417,UM_2,UM_2_0050417,2,0,13.3,1,L
276
+ 50418,UM_2,UM_2_0050418,2,0,14.9,1,R
277
+ 50419,UM_2,UM_2_0050419,2,0,15.8,1,R
278
+ 50421,UM_2,UM_2_0050421,2,0,15.4,1,R
279
+ 50422,UM_2,UM_2_0050422,2,0,14.8,1,R
280
+ 50424,UM_2,UM_2_0050424,2,0,17.9,1,R
281
+ 50425,UM_2,UM_2_0050425,2,0,16.6,1,R
282
+ 50426,UM_2,UM_2_0050426,2,0,13.6,1,R
283
+ 50427,UM_2,UM_2_0050427,2,0,15.8,1,R
284
+ 50428,UM_2,UM_2_0050428,2,0,15.5,1,R
285
+ 50433,USM,USM_0050433,2,0,18.7379,1,
286
+ 50434,USM,USM_0050434,2,0,18.2615,1,
287
+ 50435,USM,USM_0050435,2,0,16.104,1,
288
+ 50436,USM,USM_0050436,2,0,13.8097,1,
289
+ 50437,USM,USM_0050437,2,0,14.9432,1,
290
+ 50438,USM,USM_0050438,2,0,15.0253,1,
291
+ 50439,USM,USM_0050439,2,0,22.601,1,
292
+ 50440,USM,USM_0050440,2,0,23.948,1,
293
+ 50441,USM,USM_0050441,2,0,27.5975,1,
294
+ 50442,USM,USM_0050442,2,0,26.8528,1,
295
+ 50443,USM,USM_0050443,2,0,17.0705,1,
296
+ 50444,USM,USM_0050444,2,0,24.9884,1,
297
+ 50445,USM,USM_0050445,2,0,18.1383,1,
298
+ 50446,USM,USM_0050446,2,0,27.3238,1,
299
+ 50447,USM,USM_0050447,2,0,12.9391,1,
300
+ 50448,USM,USM_0050448,2,0,10.4668,1,
301
+ 50449,USM,USM_0050449,2,0,18.2177,1,
302
+ 50453,USM,USM_0050453,2,0,8.7721,1,
303
+ 50463,USM,USM_0050463,2,0,28.3669,1,
304
+ 50466,USM,USM_0050466,2,0,39.2526,1,
305
+ 50467,USM,USM_0050467,2,0,19.7591,1,
306
+ 50468,USM,USM_0050468,2,0,39.3949,1,
307
+ 50469,USM,USM_0050469,2,0,28.5613,1,
308
+ 50470,USM,USM_0050470,2,0,9.9165,1,
309
+ 50477,USM,USM_0050477,1,1,20.1807,1,
310
+ 50480,USM,USM_0050480,1,1,29.0897,1,
311
+ 50481,USM,USM_0050481,1,1,17.1663,1,
312
+ 50482,USM,USM_0050482,1,1,27.4114,1,
313
+ 50483,USM,USM_0050483,1,1,21.4346,1,
314
+ 50485,USM,USM_0050485,1,1,23.5948,1,
315
+ 50486,USM,USM_0050486,1,1,17.7878,1,
316
+ 50487,USM,USM_0050487,1,1,25.7972,1,
317
+ 50488,USM,USM_0050488,1,1,25.4511,1,
318
+ 50490,USM,USM_0050490,1,1,19.6277,1,
319
+ 50491,USM,USM_0050491,1,1,26.9487,1,
320
+ 50492,USM,USM_0050492,1,1,32.5503,1,
321
+ 50493,USM,USM_0050493,1,1,35.7098,1,
322
+ 50494,USM,USM_0050494,1,1,37.7769,1,
323
+ 50496,USM,USM_0050496,1,1,24.3231,1,
324
+ 50497,USM,USM_0050497,1,1,34.4613,1,
325
+ 50498,USM,USM_0050498,1,1,21.1307,1,
326
+ 50499,USM,USM_0050499,1,1,25.4346,1,
327
+ 50500,USM,USM_0050500,1,1,17.2375,1,
328
+ 50501,USM,USM_0050501,1,1,17.7057,1,
329
+ 50502,USM,USM_0050502,1,1,32.9582,1,
330
+ 50503,USM,USM_0050503,1,1,28.6708,1,
331
+ 50504,USM,USM_0050504,1,1,17.6454,1,
332
+ 50507,USM,USM_0050507,1,1,28.1095,1,
333
+ 50509,USM,USM_0050509,1,1,16.7337,1,
334
+ 50510,USM,USM_0050510,1,1,14.1437,1,
335
+ 50514,USM,USM_0050514,1,1,21.4018,1,
336
+ 50515,USM,USM_0050515,1,1,15.8522,1,
337
+ 50516,USM,USM_0050516,1,1,17.1143,1,
338
+ 50518,USM,USM_0050518,1,1,18.6585,1,
339
+ 50519,USM,USM_0050519,1,1,16.3778,1,
340
+ 50520,USM,USM_0050520,1,1,17.6728,1,
341
+ 50521,USM,USM_0050521,1,1,18.4175,1,
342
+ 50523,USM,USM_0050523,1,1,17.3251,1,
343
+ 50524,USM,USM_0050524,1,1,12.334,1,
344
+ 50525,USM,USM_0050525,1,1,32.8487,1,
345
+ 50526,USM,USM_0050526,1,1,50.2231,1,
346
+ 50527,USM,USM_0050527,1,3,18.4148,1,
347
+ 50528,USM,USM_0050528,1,1,11.3539,1,
348
+ 50529,USM,USM_0050529,1,1,42.3354,1,
349
+ 50530,USM,USM_0050530,1,1,18.245,1,
350
+ 50531,USM,USM_0050531,1,1,28.0903,1,
351
+ 50532,USM,USM_0050532,1,1,16.9199,1,
352
+ 50551,YALE,Yale_0050551,2,0,15.92,1,R
353
+ 50552,YALE,Yale_0050552,2,0,12.75,1,R
354
+ 50555,YALE,Yale_0050555,2,0,14.42,2,R
355
+ 50557,YALE,Yale_0050557,2,0,14.25,2,R
356
+ 50558,YALE,Yale_0050558,2,0,13.75,2,R
357
+ 50561,YALE,Yale_0050561,2,0,13.33,1,R
358
+ 50563,YALE,Yale_0050563,2,0,13.92,2,R
359
+ 50565,YALE,Yale_0050565,2,0,11,2,R
360
+ 50568,YALE,Yale_0050568,2,0,13.92,1,R
361
+ 50569,YALE,Yale_0050569,2,0,16.66,2,R
362
+ 50570,YALE,Yale_0050570,2,0,16.66,1,L
363
+ 50571,YALE,Yale_0050571,2,0,11,1,R
364
+ 50572,YALE,Yale_0050572,2,0,15.75,2,R
365
+ 50573,YALE,Yale_0050573,2,0,14.17,1,R
366
+ 50574,YALE,Yale_0050574,2,0,10.92,1,R
367
+ 50575,YALE,Yale_0050575,2,0,14,1,R
368
+ 50576,YALE,Yale_0050576,2,0,8.42,2,R
369
+ 50577,YALE,Yale_0050577,2,0,15.25,1,R
370
+ 50578,YALE,Yale_0050578,2,0,12.33,1,L
371
+ 50601,YALE,Yale_0050601,1,3,14.33,1,L
372
+ 50602,YALE,Yale_0050602,1,2,10,1,R
373
+ 50603,YALE,Yale_0050603,1,1,13.25,1,L
374
+ 50604,YALE,Yale_0050604,1,1,14.42,2,R
375
+ 50606,YALE,Yale_0050606,1,3,16.42,1,R
376
+ 50607,YALE,Yale_0050607,1,2,17.17,1,R
377
+ 50608,YALE,Yale_0050608,1,3,16.58,1,R
378
+ 50612,YALE,Yale_0050612,1,2,11.83,1,R
379
+ 50613,YALE,Yale_0050613,1,2,12.5,1,L
380
+ 50614,YALE,Yale_0050614,1,1,17.75,1,R
381
+ 50615,YALE,Yale_0050615,1,2,8.58,2,R
382
+ 50616,YALE,Yale_0050616,1,3,11.83,1,R
383
+ 50619,YALE,Yale_0050619,1,1,16.5,2,R
384
+ 50620,YALE,Yale_0050620,1,3,12.75,2,R
385
+ 50621,YALE,Yale_0050621,1,2,16.58,2,R
386
+ 50622,YALE,Yale_0050622,1,3,9.92,1,R
387
+ 50623,YALE,Yale_0050623,1,3,13.66,2,R
388
+ 50624,YALE,Yale_0050624,1,3,11.08,2,R
389
+ 50625,YALE,Yale_0050625,1,3,7,1,L
390
+ 50626,YALE,Yale_0050626,1,3,11.08,1,L
391
+ 50627,YALE,Yale_0050627,1,3,9.5,2,R
392
+ 50628,YALE,Yale_0050628,1,3,14.42,1,R
393
+ 50642,CMU,CMU_a_0050642,1,1,33,1,R
394
+ 50644,CMU,CMU_b_0050644,1,1,19,2,R
395
+ 50647,CMU,CMU_a_0050647,1,1,27,1,R
396
+ 50648,CMU,CMU_b_0050648,1,1,31,2,R
397
+ 50649,CMU,CMU_a_0050649,1,1,22,1,R
398
+ 50654,CMU,CMU_a_0050654,1,1,24,1,L
399
+ 50656,CMU,CMU_a_0050656,2,0,28,2,R
400
+ 50659,CMU,CMU_a_0050659,2,0,27,1,R
401
+ 50664,CMU,CMU_a_0050664,2,0,21,1,R
402
+ 50665,CMU,CMU_a_0050665,2,0,33,1,R
403
+ 50669,CMU,CMU_b_0050669,2,0,30,2,R
404
+ 50682,LEUVEN_1,Leuven_1_0050682,2,0,23,1,R
405
+ 50683,LEUVEN_1,Leuven_1_0050683,2,0,24,1,R
406
+ 50685,LEUVEN_1,Leuven_1_0050685,2,0,23,1,R
407
+ 50686,LEUVEN_1,Leuven_1_0050686,1,1,19,1,R
408
+ 50687,LEUVEN_1,Leuven_1_0050687,2,0,22,1,R
409
+ 50688,LEUVEN_1,Leuven_1_0050688,2,0,21,1,R
410
+ 50689,LEUVEN_1,Leuven_1_0050689,1,1,21,1,R
411
+ 50690,LEUVEN_1,Leuven_1_0050690,1,1,22,1,R
412
+ 50691,LEUVEN_1,Leuven_1_0050691,2,0,22,1,R
413
+ 50692,LEUVEN_1,Leuven_1_0050692,2,0,22,1,R
414
+ 50693,LEUVEN_1,Leuven_1_0050693,1,1,22,1,R
415
+ 50694,LEUVEN_1,Leuven_1_0050694,1,1,19,1,R
416
+ 50695,LEUVEN_1,Leuven_1_0050695,1,1,19,1,R
417
+ 50696,LEUVEN_1,Leuven_1_0050696,1,1,20,1,R
418
+ 50697,LEUVEN_1,Leuven_1_0050697,1,1,19,1,R
419
+ 50698,LEUVEN_1,Leuven_1_0050698,2,0,28,1,R
420
+ 50699,LEUVEN_1,Leuven_1_0050699,2,0,21,1,R
421
+ 50700,LEUVEN_1,Leuven_1_0050700,1,1,23,1,L
422
+ 50701,LEUVEN_1,Leuven_1_0050701,2,0,18,1,R
423
+ 50702,LEUVEN_1,Leuven_1_0050702,1,1,18,1,R
424
+ 50703,LEUVEN_1,Leuven_1_0050703,2,0,29,1,R
425
+ 50704,LEUVEN_1,Leuven_1_0050704,1,1,29,1,R
426
+ 50705,LEUVEN_1,Leuven_1_0050705,1,1,24,1,R
427
+ 50706,LEUVEN_1,Leuven_1_0050706,2,0,22,1,L
428
+ 50707,LEUVEN_1,Leuven_1_0050707,2,0,22,1,R
429
+ 50708,LEUVEN_1,Leuven_1_0050708,1,1,32,1,R
430
+ 50709,LEUVEN_1,Leuven_1_0050709,2,0,25,1,R
431
+ 50711,LEUVEN_1,Leuven_1_0050711,1,1,19,1,R
432
+ 50722,LEUVEN_2,Leuven_2_0050722,2,0,13.8,2,L
433
+ 50723,LEUVEN_2,Leuven_2_0050723,2,0,13.8,2,L
434
+ 50724,LEUVEN_2,Leuven_2_0050724,2,0,15.1,1,R
435
+ 50725,LEUVEN_2,Leuven_2_0050725,2,0,14.2,1,L
436
+ 50726,LEUVEN_2,Leuven_2_0050726,2,0,16.6,1,R
437
+ 50728,LEUVEN_2,Leuven_2_0050728,2,0,15.6,1,R
438
+ 50730,LEUVEN_2,Leuven_2_0050730,2,0,12.3,2,R
439
+ 50731,LEUVEN_2,Leuven_2_0050731,2,0,16.2,1,R
440
+ 50733,LEUVEN_2,Leuven_2_0050733,2,0,14.7,1,R
441
+ 50735,LEUVEN_2,Leuven_2_0050735,2,0,14.3,2,R
442
+ 50737,LEUVEN_2,Leuven_2_0050737,2,0,12.2,1,R
443
+ 50738,LEUVEN_2,Leuven_2_0050738,2,0,12.8,1,R
444
+ 50739,LEUVEN_2,Leuven_2_0050739,2,0,15.2,1,R
445
+ 50740,LEUVEN_2,Leuven_2_0050740,2,0,12.4,1,R
446
+ 50741,LEUVEN_2,Leuven_2_0050741,2,0,14.2,1,R
447
+ 50742,LEUVEN_2,Leuven_2_0050742,2,0,16.9,1,R
448
+ 50743,LEUVEN_2,Leuven_2_0050743,1,1,14.2,2,R
449
+ 50744,LEUVEN_2,Leuven_2_0050744,1,1,12.5,2,R
450
+ 50745,LEUVEN_2,Leuven_2_0050745,1,1,13,1,R
451
+ 50748,LEUVEN_2,Leuven_2_0050748,1,1,14.2,1,R
452
+ 50749,LEUVEN_2,Leuven_2_0050749,1,1,15.3,2,L
453
+ 50750,LEUVEN_2,Leuven_2_0050750,1,1,16.8,1,R
454
+ 50751,LEUVEN_2,Leuven_2_0050751,1,1,12.1,1,R
455
+ 50752,LEUVEN_2,Leuven_2_0050752,1,1,14.7,1,L
456
+ 50754,LEUVEN_2,Leuven_2_0050754,1,1,12.3,1,R
457
+ 50755,LEUVEN_2,Leuven_2_0050755,1,1,12.2,1,R
458
+ 50756,LEUVEN_2,Leuven_2_0050756,1,1,14.9,1,R
459
+ 50757,LEUVEN_2,Leuven_2_0050757,1,1,14.3,1,R
460
+ 50772,KKI,KKI_0050772,2,0,12.77,1,R
461
+ 50773,KKI,KKI_0050773,2,0,10.84,1,R
462
+ 50774,KKI,KKI_0050774,2,0,10.64,1,R
463
+ 50775,KKI,KKI_0050775,2,0,11,1,R
464
+ 50776,KKI,KKI_0050776,2,0,9.3,1,R
465
+ 50777,KKI,KKI_0050777,2,0,8.39,1,R
466
+ 50778,KKI,KKI_0050778,2,0,9.73,2,R
467
+ 50780,KKI,KKI_0050780,2,0,9.82,2,R
468
+ 50781,KKI,KKI_0050781,2,0,9.3,1,R
469
+ 50782,KKI,KKI_0050782,2,0,10.18,1,R
470
+ 50783,KKI,KKI_0050783,2,0,10.4,2,R
471
+ 50786,KKI,KKI_0050786,2,0,8.75,1,R
472
+ 50790,KKI,KKI_0050790,2,0,8.83,2,R
473
+ 50791,KKI,KKI_0050791,1,1,10.18,1,R
474
+ 50792,KKI,KKI_0050792,1,2,8.2,2,Mixed
475
+ 50796,KKI,KKI_0050796,1,2,11.99,2,R
476
+ 50797,KKI,KKI_0050797,1,2,12.54,1,R
477
+ 50798,KKI,KKI_0050798,1,1,10.17,2,Mixed
478
+ 50799,KKI,KKI_0050799,1,1,11.14,1,R
479
+ 50800,KKI,KKI_0050800,1,2,11.76,1,R
480
+ 50801,KKI,KKI_0050801,1,1,11.27,1,R
481
+ 50803,KKI,KKI_0050803,1,2,8.45,1,R
482
+ 50807,KKI,KKI_0050807,1,1,10.65,1,Mixed
483
+ 50812,KKI,KKI_0050812,2,0,9.97,2,R
484
+ 50814,KKI,KKI_0050814,2,0,8.46,1,L
485
+ 50816,KKI,KKI_0050816,2,0,9.73,1,Mixed
486
+ 50817,KKI,KKI_0050817,2,0,9.97,1,Mixed
487
+ 50818,KKI,KKI_0050818,2,0,11.79,1,R
488
+ 50820,KKI,KKI_0050820,2,0,8.87,2,R
489
+ 50821,KKI,KKI_0050821,2,0,11.17,1,R
490
+ 50822,KKI,KKI_0050822,2,0,12.43,1,R
491
+ 50823,KKI,KKI_0050823,1,2,11.37,1,R
492
+ 50824,KKI,KKI_0050824,1,2,10.29,1,R
493
+ 50952,NYU,NYU_0050952,1,1,8.74,2,
494
+ 50954,NYU,NYU_0050954,1,1,14.75,2,
495
+ 50955,NYU,NYU_0050955,1,1,12.64,2,
496
+ 50956,NYU,NYU_0050956,1,1,14.06,2,
497
+ 50957,NYU,NYU_0050957,1,1,14.75,2,
498
+ 50958,NYU,NYU_0050958,1,1,10.23,2,
499
+ 50959,NYU,NYU_0050959,1,2,22.81,2,
500
+ 50960,NYU,NYU_0050960,1,2,38.76,2,
501
+ 50961,NYU,NYU_0050961,1,2,25.02,2,
502
+ 50962,NYU,NYU_0050962,1,2,24.41,2,
503
+ 50964,NYU,NYU_0050964,1,1,12.75,1,
504
+ 50965,NYU,NYU_0050965,1,3,9.25,1,
505
+ 50966,NYU,NYU_0050966,1,3,15.14,1,
506
+ 50967,NYU,NYU_0050967,1,3,9.74,1,
507
+ 50968,NYU,NYU_0050968,1,3,9.95,1,
508
+ 50969,NYU,NYU_0050969,1,2,7.61,1,
509
+ 50970,NYU,NYU_0050970,1,2,8.9,1,
510
+ 50972,NYU,NYU_0050972,1,2,13.95,1,
511
+ 50973,NYU,NYU_0050973,1,2,17.88,1,
512
+ 50974,NYU,NYU_0050974,1,2,11.56,1,
513
+ 50976,NYU,NYU_0050976,1,2,14.65,1,
514
+ 50977,NYU,NYU_0050977,1,2,7.13,1,
515
+ 50978,NYU,NYU_0050978,1,2,9.58,1,
516
+ 50979,NYU,NYU_0050979,1,2,9.37,1,
517
+ 50981,NYU,NYU_0050981,1,1,12.96,1,
518
+ 50982,NYU,NYU_0050982,1,1,9.46,1,
519
+ 50983,NYU,NYU_0050983,1,1,10.48,1,
520
+ 50984,NYU,NYU_0050984,1,1,13.2,1,
521
+ 50985,NYU,NYU_0050985,1,1,13.09,1,
522
+ 50986,NYU,NYU_0050986,1,1,8.53,1,
523
+ 50987,NYU,NYU_0050987,1,1,8.56,1,
524
+ 50988,NYU,NYU_0050988,1,1,14.21,1,
525
+ 50989,NYU,NYU_0050989,1,1,9.78,1,
526
+ 50990,NYU,NYU_0050990,1,1,13.71,1,
527
+ 50991,NYU,NYU_0050991,1,1,10.9,1,
528
+ 50992,NYU,NYU_0050992,1,1,10.66,1,
529
+ 50993,NYU,NYU_0050993,1,1,10.87,1,
530
+ 50994,NYU,NYU_0050994,1,1,15.66,1,
531
+ 50995,NYU,NYU_0050995,1,1,16.74,1,
532
+ 50996,NYU,NYU_0050996,1,1,15.81,1,
533
+ 50997,NYU,NYU_0050997,1,1,16.27,1,
534
+ 50999,NYU,NYU_0050999,1,1,14.53,1,
535
+ 51000,NYU,NYU_0051000,1,1,13.33,1,
536
+ 51001,NYU,NYU_0051001,1,1,10.71,1,
537
+ 51002,NYU,NYU_0051002,1,1,7.228,1,
538
+ 51003,NYU,NYU_0051003,1,1,8.51,1,
539
+ 51006,NYU,NYU_0051006,1,1,11.11,1,
540
+ 51007,NYU,NYU_0051007,1,1,11.92,1,
541
+ 51008,NYU,NYU_0051008,1,1,12.37,1,
542
+ 51009,NYU,NYU_0051009,1,1,11.03,1,
543
+ 51010,NYU,NYU_0051010,1,1,8.53,1,
544
+ 51011,NYU,NYU_0051011,1,1,8.79,1,
545
+ 51012,NYU,NYU_0051012,1,1,9.79,1,
546
+ 51013,NYU,NYU_0051013,1,1,7.15,1,
547
+ 51014,NYU,NYU_0051014,1,1,11.005,1,
548
+ 51015,NYU,NYU_0051015,1,2,29.98,1,
549
+ 51016,NYU,NYU_0051016,1,2,22.99,1,
550
+ 51017,NYU,NYU_0051017,1,2,22.04,1,
551
+ 51018,NYU,NYU_0051018,1,2,20.25,1,
552
+ 51019,NYU,NYU_0051019,1,2,22.29,1,
553
+ 51020,NYU,NYU_0051020,1,1,28.58,1,
554
+ 51021,NYU,NYU_0051021,1,1,23.66,1,
555
+ 51023,NYU,NYU_0051023,1,1,20.62,1,
556
+ 51024,NYU,NYU_0051024,1,1,39.1,1,
557
+ 51025,NYU,NYU_0051025,1,1,19.64,1,
558
+ 51026,NYU,NYU_0051026,1,1,18.58,1,
559
+ 51027,NYU,NYU_0051027,1,1,22.98,1,
560
+ 51028,NYU,NYU_0051028,1,1,29.18,1,
561
+ 51029,NYU,NYU_0051029,1,1,26.516,1,
562
+ 51030,NYU,NYU_0051030,1,3,7.29,1,
563
+ 51032,NYU,NYU_0051032,1,1,7.15,1,
564
+ 51033,NYU,NYU_0051033,1,1,9.98,1,
565
+ 51034,NYU,NYU_0051034,1,1,10.65,1,
566
+ 51035,NYU,NYU_0051035,1,1,10.27,1,
567
+ 51036,NYU,NYU_0051036,2,0,8.04,2,
568
+ 51038,NYU,NYU_0051038,2,0,8.26,2,
569
+ 51039,NYU,NYU_0051039,2,0,8.5,2,
570
+ 51040,NYU,NYU_0051040,2,0,8.52,2,
571
+ 51041,NYU,NYU_0051041,2,0,8.9,2,
572
+ 51042,NYU,NYU_0051042,2,0,8.91,2,
573
+ 51044,NYU,NYU_0051044,2,0,10.86,2,
574
+ 51045,NYU,NYU_0051045,2,0,11.56,2,
575
+ 51046,NYU,NYU_0051046,2,0,11.56,2,
576
+ 51047,NYU,NYU_0051047,2,0,12.1,2,
577
+ 51048,NYU,NYU_0051048,2,0,12.44,2,
578
+ 51049,NYU,NYU_0051049,2,0,13.22,2,
579
+ 51050,NYU,NYU_0051050,2,0,13.25,2,
580
+ 51051,NYU,NYU_0051051,2,0,14.06,2,
581
+ 51052,NYU,NYU_0051052,2,0,14.18,2,
582
+ 51053,NYU,NYU_0051053,2,0,14.38,2,
583
+ 51054,NYU,NYU_0051054,2,0,14.42,2,
584
+ 51055,NYU,NYU_0051055,2,0,15.95,2,
585
+ 51056,NYU,NYU_0051056,2,0,17.31,2,
586
+ 51057,NYU,NYU_0051057,2,0,21.58,2,
587
+ 51058,NYU,NYU_0051058,2,0,22.11,2,
588
+ 51059,NYU,NYU_0051059,2,0,22.76,2,
589
+ 51060,NYU,NYU_0051060,2,0,22.74,2,
590
+ 51061,NYU,NYU_0051061,2,0,27.03,2,
591
+ 51062,NYU,NYU_0051062,2,0,27.76,2,
592
+ 51063,NYU,NYU_0051063,2,0,29.13,2,
593
+ 51064,NYU,NYU_0051064,2,0,7.26,1,
594
+ 51065,NYU,NYU_0051065,2,0,10.52,1,
595
+ 51066,NYU,NYU_0051066,2,0,18.59,1,
596
+ 51067,NYU,NYU_0051067,2,0,23.65,1,
597
+ 51068,NYU,NYU_0051068,2,0,31.78,1,
598
+ 51069,NYU,NYU_0051069,2,0,8.15,1,
599
+ 51070,NYU,NYU_0051070,2,0,7.29,1,
600
+ 51072,NYU,NYU_0051072,2,0,11.91,1,
601
+ 51073,NYU,NYU_0051073,2,0,12.49,1,
602
+ 51074,NYU,NYU_0051074,2,0,12.81,1,
603
+ 51075,NYU,NYU_0051075,2,0,14.2,1,
604
+ 51076,NYU,NYU_0051076,2,0,16.93,1,
605
+ 51077,NYU,NYU_0051077,2,0,17.3,1,
606
+ 51078,NYU,NYU_0051078,2,0,6.47,1,
607
+ 51079,NYU,NYU_0051079,2,0,7.19,1,
608
+ 51080,NYU,NYU_0051080,2,0,8.01,1,
609
+ 51081,NYU,NYU_0051081,2,0,8.82,1,
610
+ 51082,NYU,NYU_0051082,2,0,8.88,1,
611
+ 51083,NYU,NYU_0051083,2,0,8.93,1,
612
+ 51084,NYU,NYU_0051084,2,0,9.23,1,
613
+ 51085,NYU,NYU_0051085,2,0,9.81,1,
614
+ 51086,NYU,NYU_0051086,2,0,10.46,1,
615
+ 51087,NYU,NYU_0051087,2,0,10.52,1,
616
+ 51088,NYU,NYU_0051088,2,0,10.73,1,
617
+ 51089,NYU,NYU_0051089,2,0,10.76,1,
618
+ 51090,NYU,NYU_0051090,2,0,11.03,1,
619
+ 51091,NYU,NYU_0051091,2,0,11.32,1,
620
+ 51093,NYU,NYU_0051093,2,0,11.69,1,
621
+ 51094,NYU,NYU_0051094,2,0,12.1,1,
622
+ 51095,NYU,NYU_0051095,2,0,12.23,1,
623
+ 51096,NYU,NYU_0051096,2,0,13.18,1,
624
+ 51097,NYU,NYU_0051097,2,0,13.583,1,
625
+ 51098,NYU,NYU_0051098,2,0,13.628,1,
626
+ 51099,NYU,NYU_0051099,2,0,13.72,1,
627
+ 51100,NYU,NYU_0051100,2,0,14.36,1,
628
+ 51101,NYU,NYU_0051101,2,0,14.425,1,
629
+ 51102,NYU,NYU_0051102,2,0,14.653,1,
630
+ 51103,NYU,NYU_0051103,2,0,14.66,1,
631
+ 51104,NYU,NYU_0051104,2,0,15.27,1,
632
+ 51105,NYU,NYU_0051105,2,0,15.284,1,
633
+ 51106,NYU,NYU_0051106,2,0,15.42,1,
634
+ 51107,NYU,NYU_0051107,2,0,15.53,1,
635
+ 51109,NYU,NYU_0051109,2,0,16.13,1,
636
+ 51110,NYU,NYU_0051110,2,0,16.28,1,
637
+ 51111,NYU,NYU_0051111,2,0,16.55,1,
638
+ 51112,NYU,NYU_0051112,2,0,19.228,1,
639
+ 51113,NYU,NYU_0051113,2,0,22.38,1,
640
+ 51114,NYU,NYU_0051114,2,0,22.48,1,
641
+ 51116,NYU,NYU_0051116,2,0,25.34,1,
642
+ 51117,NYU,NYU_0051117,2,0,28.203,1,
643
+ 51118,NYU,NYU_0051118,2,0,29.02,1,
644
+ 51122,NYU,NYU_0051122,2,0,11.92,1,
645
+ 51123,NYU,NYU_0051123,2,0,12.07,1,
646
+ 51124,NYU,NYU_0051124,2,0,12.67,1,
647
+ 51126,NYU,NYU_0051126,2,0,16.31,1,
648
+ 51127,NYU,NYU_0051127,2,0,16.55,1,
649
+ 51128,NYU,NYU_0051128,2,0,16.88,1,
650
+ 51129,NYU,NYU_0051129,2,0,17.7,1,
651
+ 51130,NYU,NYU_0051130,2,0,19.13,1,
652
+ 51131,NYU,NYU_0051131,2,0,19.73,1,
653
+ 51132,TRINITY,Trinity_0051132,2,0,24.83,1,R
654
+ 51133,TRINITY,Trinity_0051133,2,0,12.04,1,R
655
+ 51134,TRINITY,Trinity_0051134,2,0,16.83,1,R
656
+ 51135,TRINITY,Trinity_0051135,2,0,13.75,1,R
657
+ 51136,TRINITY,Trinity_0051136,2,0,12.66,1,R
658
+ 51137,TRINITY,Trinity_0051137,2,0,13.25,1,R
659
+ 51138,TRINITY,Trinity_0051138,2,0,12.66,1,R
660
+ 51139,TRINITY,Trinity_0051139,2,0,19.5,1,R
661
+ 51140,TRINITY,Trinity_0051140,2,0,15.75,1,R
662
+ 51141,TRINITY,Trinity_0051141,2,0,15.91,1,R
663
+ 51142,TRINITY,Trinity_0051142,2,0,14.91,1,R
664
+ 51146,NYU,NYU_0051146,2,0,20.02,1,
665
+ 51147,NYU,NYU_0051147,2,0,20.04,1,
666
+ 51148,NYU,NYU_0051148,2,0,20.3,1,
667
+ 51149,NYU,NYU_0051149,2,0,20.56,1,
668
+ 51150,NYU,NYU_0051150,2,0,22.77,1,
669
+ 51151,NYU,NYU_0051151,2,0,23.08,1,
670
+ 51152,NYU,NYU_0051152,2,0,23.35,1,
671
+ 51153,NYU,NYU_0051153,2,0,26.17,1,
672
+ 51154,NYU,NYU_0051154,2,0,30.08,1,
673
+ 51155,NYU,NYU_0051155,2,0,30.78,1,
674
+ 51156,NYU,NYU_0051156,2,0,21.15,1,
675
+ 51159,NYU,NYU_0051159,2,0,12.81,1,
676
+ 51161,STANFORD,Stanford_0051161,1,-9999,9.0301,1,R
677
+ 51162,STANFORD,Stanford_0051162,1,-9999,8.9199,2,L
678
+ 51163,STANFORD,Stanford_0051163,1,-9999,9.0821,1,R
679
+ 51164,STANFORD,Stanford_0051164,1,-9999,8.4216,2,Ambi
680
+ 51168,STANFORD,Stanford_0051168,1,-9999,11.2628,1,L
681
+ 51169,STANFORD,Stanford_0051169,1,-9999,9.7775,1,L
682
+ 51170,STANFORD,Stanford_0051170,1,-9999,10.8652,2,R
683
+ 51171,STANFORD,Stanford_0051171,1,-9999,12.9363,1,R
684
+ 51173,STANFORD,Stanford_0051173,1,-9999,7.5284,1,R
685
+ 51177,STANFORD,Stanford_0051177,1,-9999,11.6982,1,R
686
+ 51178,STANFORD,Stanford_0051178,1,-9999,11.4326,1,R
687
+ 51179,STANFORD,Stanford_0051179,1,-9999,11.6543,1,R
688
+ 51180,STANFORD,Stanford_0051180,2,-9999,7.7502,2,R
689
+ 51181,STANFORD,Stanford_0051181,2,-9999,9.3149,1,R
690
+ 51182,STANFORD,Stanford_0051182,2,-9999,10.6927,1,R
691
+ 51183,STANFORD,Stanford_0051183,2,-9999,8.2656,1,R
692
+ 51184,STANFORD,Stanford_0051184,2,-9999,9.1068,2,R
693
+ 51185,STANFORD,Stanford_0051185,2,-9999,8.2464,1,R
694
+ 51187,STANFORD,Stanford_0051187,2,-9999,8.3313,1,R
695
+ 51188,STANFORD,Stanford_0051188,2,-9999,8.9747,2,R
696
+ 51189,STANFORD,Stanford_0051189,2,-9999,9.2081,1,R
697
+ 51192,STANFORD,Stanford_0051192,2,-9999,10.2218,2,R
698
+ 51194,STANFORD,Stanford_0051194,2,-9999,12.3477,1,R
699
+ 51197,STANFORD,Stanford_0051197,2,-9999,12.4298,1,R
700
+ 51198,STANFORD,Stanford_0051198,2,-9999,12.2546,1,Ambi
701
+ 51201,UCLA_1,UCLA_1_0051201,1,1,13.52,1,R
702
+ 51202,UCLA_1,UCLA_1_0051202,1,1,11.56,1,R
703
+ 51203,UCLA_1,UCLA_1_0051203,1,1,13.37,1,R
704
+ 51204,UCLA_1,UCLA_1_0051204,1,1,14.57,1,R
705
+ 51205,UCLA_1,UCLA_1_0051205,1,1,17.94,1,R
706
+ 51206,UCLA_1,UCLA_1_0051206,1,1,15.78,1,R
707
+ 51207,UCLA_1,UCLA_1_0051207,1,1,14.11,2,R
708
+ 51208,UCLA_1,UCLA_1_0051208,1,1,16.98,1,L
709
+ 51210,UCLA_1,UCLA_1_0051210,1,1,16.56,1,R
710
+ 51211,UCLA_1,UCLA_1_0051211,1,1,11.27,1,R
711
+ 51212,UCLA_1,UCLA_1_0051212,1,1,15.66,1,L
712
+ 51214,UCLA_1,UCLA_1_0051214,1,1,10.41,1,R
713
+ 51215,UCLA_1,UCLA_1_0051215,1,1,11.56,2,R
714
+ 51216,UCLA_1,UCLA_1_0051216,1,1,10.54,1,L
715
+ 51217,UCLA_1,UCLA_1_0051217,1,1,15.22,1,R
716
+ 51218,UCLA_1,UCLA_1_0051218,1,1,16.87,1,R
717
+ 51219,UCLA_1,UCLA_1_0051219,1,1,13.93,2,R
718
+ 51220,UCLA_1,UCLA_1_0051220,1,1,14.74,1,R
719
+ 51221,UCLA_1,UCLA_1_0051221,1,1,14.58,1,R
720
+ 51222,UCLA_1,UCLA_1_0051222,1,1,11.81,1,R
721
+ 51223,UCLA_1,UCLA_1_0051223,1,1,13.31,1,R
722
+ 51224,UCLA_1,UCLA_1_0051224,1,1,12.99,1,R
723
+ 51225,UCLA_1,UCLA_1_0051225,1,1,12.33,1,R
724
+ 51226,UCLA_1,UCLA_1_0051226,1,1,9.26,2,R
725
+ 51228,UCLA_1,UCLA_1_0051228,1,1,8.36,2,R
726
+ 51229,UCLA_1,UCLA_1_0051229,1,1,14.59,1,R
727
+ 51230,UCLA_1,UCLA_1_0051230,1,1,17.53,2,R
728
+ 51231,UCLA_1,UCLA_1_0051231,1,1,10.28,1,R
729
+ 51234,UCLA_1,UCLA_1_0051234,1,1,10.91,1,R
730
+ 51235,UCLA_1,UCLA_1_0051235,1,1,10.67,1,R
731
+ 51236,UCLA_1,UCLA_1_0051236,1,1,12.42,1,R
732
+ 51237,UCLA_1,UCLA_1_0051237,1,1,17.4,1,R
733
+ 51239,UCLA_1,UCLA_1_0051239,1,1,13.67,1,R
734
+ 51240,UCLA_1,UCLA_1_0051240,1,1,14.96,1,R
735
+ 51241,UCLA_1,UCLA_1_0051241,1,1,10.9,1,R
736
+ 51248,UCLA_1,UCLA_1_0051248,1,1,13.5,1,R
737
+ 51249,UCLA_1,UCLA_1_0051249,1,1,8.49,1,R
738
+ 51250,UCLA_1,UCLA_1_0051250,2,0,14.88,1,R
739
+ 51251,UCLA_1,UCLA_1_0051251,2,0,12.36,1,R
740
+ 51252,UCLA_1,UCLA_1_0051252,2,0,10.99,1,R
741
+ 51253,UCLA_1,UCLA_1_0051253,2,0,11.8,1,L
742
+ 51254,UCLA_1,UCLA_1_0051254,2,0,14.44,1,L
743
+ 51255,UCLA_1,UCLA_1_0051255,2,0,14.8,1,R
744
+ 51256,UCLA_1,UCLA_1_0051256,2,0,15.04,1,R
745
+ 51257,UCLA_1,UCLA_1_0051257,2,0,13.38,1,R
746
+ 51260,UCLA_1,UCLA_1_0051260,2,0,13.66,1,R
747
+ 51261,UCLA_1,UCLA_1_0051261,2,0,17.79,1,R
748
+ 51262,UCLA_1,UCLA_1_0051262,2,0,11.56,1,R
749
+ 51264,UCLA_1,UCLA_1_0051264,2,0,13.46,2,R
750
+ 51265,UCLA_1,UCLA_1_0051265,2,0,15.92,1,R
751
+ 51266,UCLA_1,UCLA_1_0051266,2,0,14.03,1,R
752
+ 51267,UCLA_1,UCLA_1_0051267,2,0,11.25,2,R
753
+ 51268,UCLA_1,UCLA_1_0051268,2,0,17.78,1,R
754
+ 51269,UCLA_1,UCLA_1_0051269,2,0,14.29,1,R
755
+ 51271,UCLA_1,UCLA_1_0051271,2,0,12.09,1,R
756
+ 51272,UCLA_1,UCLA_1_0051272,2,0,13.41,1,R
757
+ 51273,UCLA_1,UCLA_1_0051273,2,0,12.68,1,R
758
+ 51275,UCLA_1,UCLA_1_0051275,2,0,15.74,1,R
759
+ 51276,UCLA_1,UCLA_1_0051276,2,0,13.85,1,R
760
+ 51277,UCLA_1,UCLA_1_0051277,2,0,12.01,1,R
761
+ 51278,UCLA_1,UCLA_1_0051278,2,0,9.21,1,L
762
+ 51279,UCLA_1,UCLA_1_0051279,2,0,13.82,2,R
763
+ 51280,UCLA_1,UCLA_1_0051280,2,0,9.5,1,R
764
+ 51281,UCLA_1,UCLA_1_0051281,2,0,11.83,1,R
765
+ 51291,UCLA_2,UCLA_2_0051291,1,1,16.47,1,R
766
+ 51292,UCLA_2,UCLA_2_0051292,1,1,12.24,1,R
767
+ 51293,UCLA_2,UCLA_2_0051293,1,1,13.08,1,R
768
+ 51294,UCLA_2,UCLA_2_0051294,1,1,11.7,1,R
769
+ 51295,UCLA_2,UCLA_2_0051295,1,1,10.04,1,L
770
+ 51297,UCLA_2,UCLA_2_0051297,1,1,14.27,1,L
771
+ 51298,UCLA_2,UCLA_2_0051298,1,1,10.57,1,R
772
+ 51299,UCLA_2,UCLA_2_0051299,1,1,14.77,1,R
773
+ 51300,UCLA_2,UCLA_2_0051300,1,1,14.08,1,L
774
+ 51301,UCLA_2,UCLA_2_0051301,1,1,13.28,1,R
775
+ 51302,UCLA_2,UCLA_2_0051302,1,1,10.85,1,R
776
+ 51303,UCLA_2,UCLA_2_0051303,2,0,13,2,R
777
+ 51304,UCLA_2,UCLA_2_0051304,2,0,10.53,1,R
778
+ 51305,UCLA_2,UCLA_2_0051305,2,0,12.64,2,R
779
+ 51306,UCLA_2,UCLA_2_0051306,2,0,11.66,1,R
780
+ 51307,UCLA_2,UCLA_2_0051307,2,0,12.15,1,R
781
+ 51308,UCLA_2,UCLA_2_0051308,2,0,9.79,1,R
782
+ 51309,UCLA_2,UCLA_2_0051309,2,0,11.9,1,R
783
+ 51311,UCLA_2,UCLA_2_0051311,2,0,11.95,1,R
784
+ 51313,UCLA_2,UCLA_2_0051313,2,0,13.36,1,R
785
+ 51315,UCLA_2,UCLA_2_0051315,2,0,13.63,1,R
786
+ 51318,MAX_MUN,MaxMun_a_0051318,1,2,19,1,R
787
+ 51319,MAX_MUN,MaxMun_a_0051319,1,2,33,1,R
788
+ 51320,MAX_MUN,MaxMun_a_0051320,1,2,31,1,R
789
+ 51321,MAX_MUN,MaxMun_a_0051321,1,2,45,2,R
790
+ 51322,MAX_MUN,MaxMun_b_0051322,1,2,29,1,L
791
+ 51323,MAX_MUN,MaxMun_b_0051323,1,2,30,1,R
792
+ 51325,MAX_MUN,MaxMun_b_0051325,1,2,32,2,L
793
+ 51326,MAX_MUN,MaxMun_b_0051326,1,2,42,1,R
794
+ 51327,MAX_MUN,MaxMun_b_0051327,1,2,58,1,R
795
+ 51328,MAX_MUN,MaxMun_c_0051328,1,2,22,1,R
796
+ 51329,MAX_MUN,MaxMun_d_0051329,1,2,18,1,R
797
+ 51330,MAX_MUN,MaxMun_d_0051330,1,2,45,1,R
798
+ 51331,MAX_MUN,MaxMun_d_0051331,1,2,35,1,R
799
+ 51332,MAX_MUN,MaxMun_c_0051332,2,0,23,1,R
800
+ 51333,MAX_MUN,MaxMun_c_0051333,2,0,24,1,R
801
+ 51334,MAX_MUN,MaxMun_c_0051334,2,0,27,1,R
802
+ 51335,MAX_MUN,MaxMun_c_0051335,2,0,23,1,R
803
+ 51336,MAX_MUN,MaxMun_c_0051336,2,0,26,1,R
804
+ 51338,MAX_MUN,MaxMun_c_0051338,2,0,30,1,R
805
+ 51339,MAX_MUN,MaxMun_c_0051339,2,0,29,1,R
806
+ 51340,MAX_MUN,MaxMun_c_0051340,2,0,29,1,R
807
+ 51341,MAX_MUN,MaxMun_c_0051341,2,0,29,1,R
808
+ 51342,MAX_MUN,MaxMun_c_0051342,2,0,23,1,R
809
+ 51343,MAX_MUN,MaxMun_c_0051343,2,0,30,1,R
810
+ 51344,MAX_MUN,MaxMun_c_0051344,2,0,22,1,R
811
+ 51345,MAX_MUN,MaxMun_c_0051345,2,0,35,1,R
812
+ 51346,MAX_MUN,MaxMun_c_0051346,2,0,25,1,R
813
+ 51347,MAX_MUN,MaxMun_c_0051347,2,0,24,1,R
814
+ 51349,MAX_MUN,MaxMun_d_0051349,1,2,11,1,R
815
+ 51350,MAX_MUN,MaxMun_d_0051350,1,1,11,1,R
816
+ 51351,MAX_MUN,MaxMun_d_0051351,1,1,11,1,R
817
+ 51354,MAX_MUN,MaxMun_d_0051354,1,2,12,1,R
818
+ 51356,MAX_MUN,MaxMun_d_0051356,2,0,10,1,R
819
+ 51357,MAX_MUN,MaxMun_d_0051357,2,0,11,1,R
820
+ 51359,MAX_MUN,MaxMun_d_0051359,2,0,13,1,R
821
+ 51360,MAX_MUN,MaxMun_d_0051360,2,0,7,1,R
822
+ 51361,MAX_MUN,MaxMun_d_0051361,2,0,16,1,R
823
+ 51362,MAX_MUN,MaxMun_a_0051362,2,0,33,1,R
824
+ 51363,MAX_MUN,MaxMun_a_0051363,2,0,32,1,R
825
+ 51364,MAX_MUN,MaxMun_a_0051364,2,0,26,1,R
826
+ 51365,MAX_MUN,MaxMun_a_0051365,2,0,23,1,R
827
+ 51369,MAX_MUN,MaxMun_a_0051369,2,0,32,1,R
828
+ 51370,MAX_MUN,MaxMun_a_0051370,2,0,32,2,R
829
+ 51373,MAX_MUN,MaxMun_a_0051373,2,0,46,1,R
830
+ 51461,CALTECH,Caltech_0051461,1,4,37.7,1,R
831
+ 51463,CALTECH,Caltech_0051463,1,1,20.2,2,R
832
+ 51464,CALTECH,Caltech_0051464,1,1,20.9,1,Ambi
833
+ 51465,CALTECH,Caltech_0051465,1,1,20.2,1,R
834
+ 51473,CALTECH,Caltech_0051473,1,1,21.2,1,R
835
+ 51477,CALTECH,Caltech_0051477,2,0,42.5,1,R
836
+ 51479,CALTECH,Caltech_0051479,2,0,20,2,R
837
+ 51480,CALTECH,Caltech_0051480,2,0,20.8,2,R
838
+ 51481,CALTECH,Caltech_0051481,2,0,27.9,1,R
839
+ 51482,CALTECH,Caltech_0051482,2,0,21.1,2,R
840
+ 51484,CALTECH,Caltech_0051484,2,0,23.6,1,R
841
+ 51487,CALTECH,Caltech_0051487,2,0,17,1,R
842
+ 51488,CALTECH,Caltech_0051488,2,0,23.3,1,L
843
+ 51491,CALTECH,Caltech_0051491,2,0,56.2,1,R
844
+ 51493,CALTECH,Caltech_0051493,2,0,29.2,2,R
845
+ 51556,SBL,SBL_0051556,2,0,20,1,
846
+ 51557,SBL,SBL_0051557,2,0,26,1,
847
+ 51558,SBL,SBL_0051558,2,0,27,1,
848
+ 51559,SBL,SBL_0051559,2,0,27,1,
849
+ 51560,SBL,SBL_0051560,2,0,27,1,
850
+ 51562,SBL,SBL_0051562,2,0,37,1,
851
+ 51563,SBL,SBL_0051563,2,0,38,1,
852
+ 51564,SBL,SBL_0051564,2,0,39,1,
853
+ 51565,SBL,SBL_0051565,2,0,39,1,
854
+ 51566,SBL,SBL_0051566,2,0,41,1,
855
+ 51567,SBL,SBL_0051567,2,0,34,1,
856
+ 51568,SBL,SBL_0051568,2,0,37,1,
857
+ 51569,SBL,SBL_0051569,2,0,36,1,
858
+ 51570,SBL,SBL_0051570,2,0,42,1,
859
+ 51572,SBL,SBL_0051572,1,2,28,1,
860
+ 51573,SBL,SBL_0051573,1,3,30,1,L
861
+ 51574,SBL,SBL_0051574,1,2,30,1,
862
+ 51576,SBL,SBL_0051576,1,3,31,1,
863
+ 51577,SBL,SBL_0051577,1,3,31,1,
864
+ 51578,SBL,SBL_0051578,1,2,33,1,
865
+ 51579,SBL,SBL_0051579,1,3,41,1,
866
+ 51580,SBL,SBL_0051580,1,3,42,1,
867
+ 51582,SBL,SBL_0051582,1,2,31,1,
868
+ 51583,SBL,SBL_0051583,1,2,35,1,
869
+ 51584,SBL,SBL_0051584,1,2,49,1,
870
+ 51585,SBL,SBL_0051585,1,1,27,1,
871
+ 51606,MAX_MUN,MaxMun_a_0051606,1,2,29,2,R
872
+ 51607,MAX_MUN,MaxMun_a_0051607,1,2,26,1,R
AtlaScore/downstream/docs/behavior_ADNI.csv ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Subject ID,Sex,Research Group
2
+ 003_S_6258,M,MCI
3
+ 003_S_6259,M,CN
4
+ 003_S_6264,M,AD
5
+ 003_S_6678,F,MCI
6
+ 003_S_6833,F,AD
7
+ 006_S_6209,M,CN
8
+ 006_S_6234,F,CN
9
+ 006_S_6657,M,MCI
10
+ 006_S_6672,M,MCI
11
+ 006_S_6682,M,MCI
12
+ 006_S_6689,M,AD
13
+ 009_S_6212,F,CN
14
+ 009_S_6286,F,CN
15
+ 009_S_6402,M,MCI
16
+ 011_S_6303,M,AD
17
+ 012_S_6503,M,MCI
18
+ 013_S_6768,F,AD
19
+ 013_S_6975,M,AD
20
+ 014_S_6145,F,CN
21
+ 014_S_6522,M,CN
22
+ 014_S_6935,F,CN
23
+ 014_S_6944,F,MCI
24
+ 018_S_6207,F,CN
25
+ 018_S_6351,F,CN
26
+ 019_S_6585,F,AD
27
+ 019_S_6630,M,MCI
28
+ 019_S_6668,F,MCI
29
+ 019_S_6712,M,AD
30
+ 020_S_6566,M,CN
31
+ 021_S_6914,M,CN
32
+ 021_S_6940,M,CN
33
+ 022_S_6013,F,AD
34
+ 022_S_6069,F,CN
35
+ 022_S_6716,M,MCI
36
+ 027_S_6001,F,CN
37
+ 027_S_6648,M,AD
38
+ 027_S_6733,M,AD
39
+ 027_S_6793,M,MCI
40
+ 027_S_6849,M,AD
41
+ 027_S_6965,M,AD
42
+ 027_S_7024,M,CN
43
+ 032_S_6055,M,MCI
44
+ 032_S_6600,F,AD
45
+ 032_S_6602,M,AD
46
+ 032_S_6701,F,CN
47
+ 032_S_6717,M,CN
48
+ 032_S_6855,M,AD
49
+ 035_S_6195,F,CN
50
+ 035_S_6200,M,CN
51
+ 035_S_6306,M,CN
52
+ 035_S_6480,F,MCI
53
+ 035_S_6551,F,CN
54
+ 035_S_6650,M,AD
55
+ 035_S_6660,F,AD
56
+ 035_S_6730,M,CN
57
+ 035_S_6950,F,CN
58
+ 035_S_6967,F,CN
59
+ 035_S_6999,M,CN
60
+ 035_S_7001,M,AD
61
+ 035_S_7073,M,MCI
62
+ 035_S_7105,M,MCI
63
+ 035_S_7120,M,AD
64
+ 037_S_6115,F,CN
65
+ 041_S_6354,F,CN
66
+ 041_S_6447,F,CN
67
+ 053_S_7109,F,AD
68
+ 057_S_6746,M,AD
69
+ 057_S_6869,M,AD
70
+ 070_S_6229,M,MCI
71
+ 070_S_7078,M,MCI
72
+ 082_S_6197,F,CN
73
+ 082_S_6415,F,CN
74
+ 082_S_6690,F,AD
75
+ 094_S_6250,F,CN
76
+ 094_S_6269,F,CN
77
+ 098_S_6601,M,AD
78
+ 098_S_6655,M,AD
79
+ 098_S_6658,F,AD
80
+ 098_S_6734,F,CN
81
+ 099_S_6097,M,CN
82
+ 100_S_6308,M,CN
83
+ 100_S_6349,M,CN
84
+ 100_S_6713,F,AD
85
+ 109_S_6213,M,CN
86
+ 109_S_6363,M,MCI
87
+ 109_S_6373,F,MCI
88
+ 109_S_6376,F,MCI
89
+ 109_S_6405,F,CN
90
+ 114_S_6063,F,CN
91
+ 114_S_6347,M,AD
92
+ 114_S_6368,M,AD
93
+ 114_S_6595,M,AD
94
+ 116_S_6100,F,AD
95
+ 116_S_6458,M,CN
96
+ 116_S_6537,F,CN
97
+ 116_S_6543,M,AD
98
+ 116_S_6750,M,CN
99
+ 123_S_6118,F,CN
100
+ 123_S_6825,F,AD
101
+ 123_S_6891,M,AD
102
+ 126_S_6683,M,AD
103
+ 126_S_6721,M,AD
104
+ 126_S_6724,M,MCI
105
+ 126_S_7015,M,MCI
106
+ 126_S_7060,M,MCI
107
+ 126_S_7083,M,MCI
108
+ 127_S_6173,F,CN
109
+ 127_S_6330,M,CN
110
+ 127_S_6433,M,AD
111
+ 127_S_6512,M,MCI
112
+ 127_S_6549,M,AD
113
+ 129_S_6288,F,CN
114
+ 129_S_6457,M,CN
115
+ 129_S_6763,F,AD
116
+ 129_S_6784,M,AD
117
+ 129_S_6852,M,MCI
118
+ 130_S_6072,F,AD
119
+ 130_S_6111,F,CN
120
+ 130_S_6469,F,CN
121
+ 130_S_6558,F,CN
122
+ 130_S_6611,M,MCI
123
+ 131_S_6616,M,MCI
124
+ 131_S_7032,M,MCI
125
+ 135_S_6284,M,AD
126
+ 135_S_6389,M,AD
127
+ 135_S_6411,M,CN
128
+ 135_S_6544,F,MCI
129
+ 135_S_6545,F,AD
130
+ 135_S_6586,M,MCI
131
+ 135_S_6622,M,MCI
132
+ 135_S_6687,F,AD
133
+ 135_S_6840,F,AD
134
+ 135_S_7003,F,AD
135
+ 141_S_6061,F,CN
136
+ 141_S_6075,M,MCI
137
+ 141_S_6787,F,MCI
138
+ 141_S_6964,F,MCI
139
+ 168_S_6049,F,CN
140
+ 168_S_6065,F,CN
141
+ 168_S_6108,M,CN
142
+ 168_S_6142,F,AD
143
+ 168_S_6321,M,CN
144
+ 168_S_6426,F,MCI
145
+ 168_S_6591,F,MCI
146
+ 168_S_6735,F,AD
147
+ 168_S_6754,M,AD
148
+ 168_S_6827,M,AD
149
+ 168_S_6828,M,AD
150
+ 168_S_6843,F,AD
151
+ 168_S_6851,F,MCI
152
+ 168_S_6874,F,MCI
153
+ 168_S_6921,M,AD
154
+ 168_S_6938,M,AD
155
+ 177_S_6420,F,CN
156
+ 301_S_6501,F,CN
157
+ 301_S_6592,M,AD
158
+ 301_S_6615,F,MCI
159
+ 301_S_6811,F,MCI
160
+ 305_S_6438,F,CN
161
+ 305_S_6498,M,MCI
162
+ 305_S_6810,M,AD
163
+ 305_S_6850,M,AD
164
+ 305_S_6877,M,MCI
165
+ 305_S_6881,F,AD
166
+ 941_S_6017,M,MCI
167
+ 941_S_6068,M,MCI
168
+ 136_S_4993,F,AD
169
+ 136_S_4932,M,MCI
170
+ 136_S_4848,M,MCI
171
+ 136_S_4836,M,MCI
172
+ 136_S_4727,F,CN
173
+ 136_S_4726,F,CN
174
+ 136_S_4433,F,CN
175
+ 136_S_4408,M,MCI
176
+ 136_S_4269,F,CN
177
+ 131_S_5138,M,AD
178
+ 130_S_5231,F,AD
179
+ 130_S_5059,M,AD
180
+ 130_S_5006,F,AD
181
+ 130_S_4997,F,AD
182
+ 130_S_4990,F,AD
183
+ 130_S_4984,F,AD
184
+ 130_S_4982,F,AD
185
+ 130_S_4971,M,AD
186
+ 130_S_4925,M,MCI
187
+ 130_S_4817,M,MCI
188
+ 130_S_4730,F,AD
189
+ 130_S_4660,F,AD
190
+ 130_S_4641,F,AD
191
+ 130_S_4605,F,MCI
192
+ 130_S_4589,F,AD
193
+ 130_S_4542,F,MCI
194
+ 130_S_4352,M,CN
195
+ 130_S_4343,M,CN
196
+ 130_S_4294,F,MCI
197
+ 100_S_5246,F,CN
198
+ 100_S_5106,M,AD
199
+ 100_S_5091,M,CN
200
+ 100_S_4970,M,MCI
201
+ 100_S_4556,M,MCI
202
+ 100_S_4511,M,CN
203
+ 100_S_4469,M,CN
204
+ 053_S_5208,M,AD
205
+ 053_S_5070,M,AD
206
+ 053_S_4578,F,CN
207
+ 031_S_4721,M,MCI
208
+ 031_S_4590,F,MCI
209
+ 031_S_4496,F,CN
210
+ 031_S_4474,M,CN
211
+ 031_S_4218,M,CN
212
+ 031_S_4203,F,MCI
213
+ 031_S_4194,M,MCI
214
+ 031_S_4042,M,MCI
215
+ 031_S_4032,F,CN
216
+ 031_S_4029,M,MCI
217
+ 031_S_4024,F,AD
218
+ 031_S_4021,M,CN
219
+ 019_S_5019,F,AD
220
+ 019_S_5012,M,AD
221
+ 019_S_4835,M,CN
222
+ 019_S_4549,M,AD
223
+ 019_S_4548,M,MCI
224
+ 019_S_4477,F,AD
225
+ 019_S_4367,F,CN
226
+ 019_S_4293,M,MCI
227
+ 019_S_4252,F,AD
228
+ 018_S_5240,F,AD
229
+ 018_S_5074,F,AD
230
+ 018_S_4889,M,MCI
231
+ 018_S_4733,M,AD
232
+ 018_S_4696,F,AD
233
+ 018_S_4400,M,CN
234
+ 018_S_4349,F,CN
235
+ 018_S_4313,F,CN
236
+ 018_S_4257,M,CN
237
+ 013_S_5071,M,AD
238
+ 013_S_4985,F,MCI
239
+ 013_S_4731,F,CN
240
+ 013_S_4616,M,CN
241
+ 013_S_4595,M,MCI
242
+ 013_S_4580,F,CN
243
+ 013_S_4395,F,MCI
244
+ 013_S_4236,F,MCI
245
+ 010_S_5163,M,AD
246
+ 010_S_4442,F,CN
247
+ 010_S_4135,F,MCI
248
+ 006_S_4960,M,MCI
249
+ 006_S_4867,M,AD
250
+ 006_S_4713,M,MCI
251
+ 006_S_4546,M,AD
252
+ 006_S_4515,M,MCI
253
+ 006_S_4485,M,CN
254
+ 006_S_4449,F,CN
255
+ 006_S_4363,F,MCI
256
+ 006_S_4357,F,CN
257
+ 006_S_4346,M,MCI
258
+ 006_S_4192,M,AD
259
+ 006_S_4153,M,AD
260
+ 006_S_4150,M,CN
261
+ 002_S_4270,F,CN
262
+ 002_S_4264,F,CN
263
+ 002_S_4262,F,CN
264
+ 002_S_4251,M,MCI
265
+ 002_S_4229,M,MCI
266
+ 002_S_4219,F,MCI
267
+ 002_S_4213,F,CN
268
+ 002_S_4171,M,MCI
AtlaScore/downstream/docs/behavior_HCP.csv ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Subject,Release,Acquisition,Gender,Age,Age_Group,MMSE_Score,PMAT24_A_CR,CogFluidComp_AgeAdj,CogFluidComp_AgeAdj_Group,CogCrystalComp_AgeAdj,CogCrystalComp_AgeAdj_Group,CogTotalComp_AgeAdj,CogTotalComp_AgeAdj_Group
2
+ 100206,S900,Q11,M,26-30,1,30,20,130.07,2,113.89,1,133.76,2
3
+ 100307,Q1,Q01,F,26-30,1,29,17,107.88,1,97.42,1,106.85,1
4
+ 100408,Q3,Q03,M,31-35,2,30,7,113.77,1,134.57,2,133.96,2
5
+ 100610,S900,Q08,M,26-30,1,30,23,115.63,2,149.19,2,153.36,2
6
+ 101006,S500,Q06,F,31-35,2,28,11,72.02,0,82.93,0,72.15,0
7
+ 101107,S500,Q06,M,22-25,0,29,14,106.57,1,118.74,2,120.13,2
8
+ 101309,S500,Q06,M,26-30,1,29,15,90.01,1,110.72,1,100.32,1
9
+ 101915,Q3,Q04,F,31-35,2,29,21,87.99,1,117.73,2,103.22,1
10
+ 102008,S500,Q06,M,22-25,0,30,20,112.08,1,129.31,2,131.66,2
11
+ 102109,S1200,Q13,M,26-30,1,29,21,93.65,1,117.69,2,109.51,1
12
+ 102311,S500,Q06,F,26-30,1,30,20,93.44,1,107.45,1,101.53,1
13
+ 102513,S900,Q10,M,26-30,1,29,18,72.82,0,120.41,2,92.5,1
14
+ 102614,S1200,Q12,M,22-25,0,29,18,139.94,2,98.7,1,134.26,2
15
+ 102715,S1200,Q12,M,26-30,1,29,22,104.28,1,124.02,2,122.45,2
16
+ 102816,Q3,Q03,F,26-30,1,29,17,102.9,1,75.59,0,86.38,1
17
+ 103010,S1200,Q12,M,22-25,0,28,19,87.61,1,100.28,1,91.51,1
18
+ 103111,S500,Q06,M,26-30,1,26,21,100.56,1,117.11,2,113.45,1
19
+ 103212,S1200,Q13,M,31-35,2,26,15,94.11,1,124.11,2,114.23,1
20
+ 103414,Q2,Q02,F,22-25,0,29,17,84.22,0,99.49,1,88.44,1
21
+ 103515,Q1,Q02,F,26-30,1,27,8,77.63,0,71.99,0,69.84,0
22
+ 103818,Q1,Q01,F,31-35,2,28,16,95.9,1,124.18,2,115.58,2
23
+ 104012,MEG2,Q07,F,26-30,1,27,10,79.7,0,87.94,1,79.29,0
24
+ 104416,S900,Q09,F,31-35,2,30,23,131.74,2,125.37,2,143.78,2
25
+ 104820,S500,Q06,F,36+,2,27,15,101.58,1,77.78,0,86.97,1
26
+ 105014,S500,Q05,F,26-30,1,30,21,85.35,1,123.5,2,107.29,1
27
+ 105115,Q2,Q02,M,31-35,2,29,22,105.98,1,116.28,2,116.5,2
28
+ 105216,Q3,Q03,M,26-30,1,29,22,141.25,2,127.97,2,153.36,2
29
+ 105620,S900,Q08,F,31-35,2,30,22,136.5,2,120.16,2,143.87,2
30
+ 105923,MEG2,Q07,F,31-35,2,30,22,94.52,1,119.01,2,110.18,1
31
+ 106016,Q3,Q04,F,31-35,2,30,22,108.46,1,107.77,1,112.08,1
32
+ 106319,Q3,Q03,M,26-30,1,30,24,107.24,1,132.49,2,131.22,2
33
+ 106521,S500,Q06,F,26-30,1,30,23,131.41,2,134.58,2,153.36,2
34
+ 106824,S1200,Q13,M,22-25,0,30,22,124.28,2,121.7,2,135.54,2
35
+ 107018,S900,Q09,F,26-30,1,28,10,87.55,1,121.64,2,107.92,1
36
+ 107321,S500,Q04,F,22-25,0,30,23,133.33,2,128.4,2,153.36,2
37
+ 107422,S500,Q07,M,22-25,0,29,24,126.89,2,139.39,2,153.36,2
38
+ 107725,S900,Q08,F,31-35,2,29,10,101.54,1,80.79,0,88.74,1
39
+ 108020,S1200,Q12,M,22-25,0,30,21,108.5,1,106.25,1,112.78,1
40
+ 108121,S500,Q04,F,26-30,1,30,16,115.5,2,111.32,1,122.49,2
41
+ 108222,S900,Q07,M,31-35,2,29,22,134.37,2,124.34,2,146.49,2
42
+ 108323,S500,Q04,F,26-30,1,30,13,119.88,2,106.66,1,124.12,2
43
+ 108525,S500,Q05,M,22-25,0,30,18,67.64,0,87.61,1,72.18,0
44
+ 108828,S500,Q05,M,31-35,2,29,20,83.74,0,113.24,1,96.69,1
45
+ 109123,S500,Q06,M,31-35,2,30,22,138.61,2,123.43,2,153.36,2
46
+ 109325,S500,Q07,M,31-35,2,28,19,112.13,1,89.24,1,103.1,1
47
+ 109830,S900,Q08,F,31-35,2,28,,76.61,0,128.72,2,104.97,1
48
+ 110007,S900,Q11,F,31-35,2,30,18,108.12,1,95.69,1,104.22,1
49
+ 110411,Q2,Q02,M,31-35,2,29,16,122.5,2,124.37,2,134.04,2
50
+ 110613,S900,Q11,M,26-30,1,30,17,88.25,1,122.21,2,109.09,1
51
+ 111009,S900,Q03,F,26-30,1,30,20,,,,,,
52
+ 111211,S1200,Q12,F,26-30,1,30,19,107.41,1,122.72,2,123.48,2
53
+ 111312,Q1,Q01,F,31-35,2,28,17,118.47,2,78.3,0,101.2,1
54
+ 111413,S500,Q04,F,26-30,1,28,13,110.99,1,108.65,1,117.02,2
55
+ 111514,MEG2,Q02,M,31-35,2,29,17,,,,,,
56
+ 111716,Q3,Q04,F,31-35,2,29,22,92.62,1,124.93,2,113.39,1
57
+ 112112,S900,Q11,M,26-30,1,30,21,94.23,1,122.33,2,113.93,1
58
+ 112314,S900,Q11,F,26-30,1,27,18,101.73,1,110.66,1,109.66,1
59
+ 112516,S900,Q08,F,31-35,2,29,11,97.49,1,95.85,1,95.5,1
60
+ 112920,S900,Q10,M,31-35,2,30,17,115.57,2,115.82,2,122.8,2
61
+ 113215,Q3,Q03,F,26-30,1,30,17,132.08,2,125.77,2,146.88,2
62
+ 113316,S1200,Q12,M,22-25,0,29,20,95.84,1,113.65,1,107.75,1
63
+ 113619,Q2,Q02,F,31-35,2,30,15,100.19,1,123.11,2,118.51,2
64
+ 113922,S500,Q04,M,31-35,2,30,15,134.06,2,91.33,1,125.45,2
65
+ 114217,S900,Q08,F,26-30,1,30,21,128.13,2,127.38,2,141.91,2
66
+ 114318,S900,Q06,F,22-25,0,27,16,113.23,1,113.67,1,122.26,2
67
+ 114419,S500,Q07,M,31-35,2,30,13,113.1,1,111.34,1,118.24,2
68
+ 114621,S900,Q09,M,26-30,1,30,15,89.35,1,112.92,1,101.67,1
69
+ 114823,S900,Q07,F,31-35,2,28,22,134.48,2,133.1,2,153.36,2
70
+ 114924,Q1,Q01,M,26-30,1,29,4,86.17,1,75.08,0,76.08,0
71
+ 115017,S900,Q06,F,31-35,2,29,15,95.82,1,107.64,1,102.13,1
72
+ 115219,S900,Q09,M,31-35,2,28,18,119.95,2,126.58,2,133.55,2
73
+ 115320,Q2,Q02,F,31-35,2,28,14,94.78,1,87.1,1,88.56,1
74
+ 115724,S1200,Q12,F,22-25,0,29,10,113.45,1,82.77,0,102.85,1
75
+ 115825,S900,Q10,M,22-25,0,27,9,76.5,0,70.59,0,68.82,0
76
+ 116524,S500,Q05,M,26-30,1,29,13,85.74,1,74.77,0,75.57,0
77
+ 116726,S900,Q08,M,26-30,1,29,19,131.22,2,123.89,2,143.4,2
78
+ 117021,S1200,Q12,F,26-30,1,29,23,116.82,2,125.18,2,130.46,2
79
+ 117122,Q1,Q01,F,26-30,1,30,24,127.07,2,116.33,2,131.87,2
80
+ 117324,Q3,Q03,F,22-25,0,29,12,77.63,0,85.67,1,76.33,0
81
+ 117930,S900,Q10,F,31-35,2,30,13,88.12,1,122.75,2,108.49,1
82
+ 118023,S900,Q07,F,26-30,1,30,19,99.19,1,101.19,1,102.25,1
83
+ 118124,S900,Q07,F,31-35,2,28,16,92.55,1,84.34,0,84.66,0
84
+ 118225,S900,Q08,M,26-30,1,29,23,115.22,2,126.2,2,132.22,2
85
+ 118528,S500,Q04,F,26-30,1,30,8,106.92,1,107.59,1,112.46,1
86
+ 118730,Q2,Q03,M,22-25,0,30,10,96.74,1,99.71,1,99.08,1
87
+ 118831,S1200,Q13,M,22-25,0,27,17,109.26,1,137.29,2,135.38,2
88
+ 118932,Q1,Q02,M,26-30,1,29,19,99.3,1,113.38,1,110.42,1
89
+ 119025,S1200,Q12,M,26-30,1,30,20,102.59,1,131.98,2,127.91,2
90
+ 119126,S900,Q11,F,22-25,0,30,17,108.5,1,94.54,1,105.89,1
91
+ 119732,S900,Q10,F,31-35,2,28,22,78.61,0,117.14,2,95.4,1
92
+ 119833,Q1,Q01,F,26-30,1,29,12,105.97,1,93.51,1,102.68,1
93
+ 120111,Q3,Q03,F,26-30,1,28,14,88.41,1,119.68,2,107.01,1
94
+ 120212,Q1,Q01,F,31-35,2,29,22,117.91,2,123.06,2,130.39,2
95
+ 120414,S1200,Q12,F,26-30,1,27,12,69.33,0,104.91,1,80.31,0
96
+ 120515,S500,Q04,F,26-30,1,30,21,87.13,1,95.96,1,88.94,1
97
+ 120717,S900,Q09,F,31-35,2,29,20,128.67,2,123.49,2,138.26,2
98
+ 121416,S900,Q08,M,26-30,1,29,20,74.66,0,116.24,2,91.2,1
99
+ 121618,S500,Q05,M,31-35,2,27,11,93.24,1,122.8,2,112.11,1
100
+ 121921,S900,Q07,M,31-35,2,30,21,86.02,1,119.97,2,103.44,1
101
+ 122317,Q3,Q04,M,31-35,2,30,18,99.89,1,87.97,1,92.99,1
AtlaScore/downstream/downstream.py ADDED
@@ -0,0 +1,740 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from boto3.session import Session
3
+ import nibabel as nib
4
+ from nilearn.image import resample_to_img
5
+ from nilearn.datasets import fetch_abide_pcp
6
+ import numpy as np
7
+ import pandas as pd
8
+ from scipy.signal import detrend
9
+ from scipy.stats import zscore
10
+ import shutil
11
+ from sklearn.model_selection import StratifiedKFold, KFold
12
+ from sklearn.decomposition import PCA
13
+ from sklearn.svm import SVC
14
+ from sklearn.metrics import accuracy_score
15
+ from sklearn.preprocessing import StandardScaler
16
+
17
+
18
+
19
+ def get_sub_HCP_rfMRI(subject, access_key, secret_key, addr = './nii_data'):
20
+
21
+ bucketName = 'hcp-openaccess'
22
+ prefix = 'HCP_1200/'
23
+ session = Session(aws_access_key_id = access_key, aws_secret_access_key = secret_key)
24
+ bucket = session.resource('s3').Bucket(bucketName)
25
+ os.makedirs(os.path.join(addr, 'HCP_rfMRI'), exist_ok = True)
26
+
27
+ for run in ['REST1_LR', 'REST1_RL', 'REST2_LR', 'REST2_RL']:
28
+
29
+ source_addr = '{}{}/MNINonLinear/Results/rfMRI_{}/rfMRI_{}_hp2000_clean.nii.gz'.format(prefix, subject, run, run)
30
+ target_addr = os.path.join(addr, 'HCP_rfMRI/{}_rfMRI_{}_hp2000_clean.nii.gz'.format(subject, run))
31
+
32
+ if not os.path.exists(target_addr):
33
+ try: bucket.download_file(source_addr, target_addr)
34
+ except: continue
35
+
36
+
37
+
38
+ def get_sub_HCP_tfMRI(subject, access_key, secret_key, addr = './nii_data'):
39
+
40
+ bucketName = 'hcp-openaccess'
41
+ prefix = 'HCP_1200/'
42
+ session = Session(aws_access_key_id = access_key, aws_secret_access_key = secret_key)
43
+ bucket = session.resource('s3').Bucket(bucketName)
44
+ os.makedirs(os.path.join(addr, 'HCP_tfMRI'), exist_ok = True)
45
+
46
+ for task in ['WM', 'GAMBLING', 'MOTOR', 'LANGUAGE', 'SOCIAL', 'RELATIONAL', 'EMOTION']:
47
+
48
+ if task == 'WM': subtask_list = ['0bk_body', '0bk_faces', '0bk_places', '0bk_tools', '2bk_body', '2bk_faces', '2bk_places', '2bk_tools']
49
+ elif task == 'GAMBLING': subtask_list = ['win', 'loss']
50
+ elif task == 'MOTOR': subtask_list = ['cue', 'lf', 'rf', 'lh', 'rh', 't']
51
+ elif task == 'LANGUAGE': subtask_list = ['story', 'math']
52
+ elif task == 'SOCIAL': subtask_list = ['mental', 'rnd']
53
+ elif task == 'RELATIONAL': subtask_list = ['relation', 'match']
54
+ else: subtask_list = ['fear', 'neut']
55
+
56
+ source_addr = '{}{}/MNINonLinear/Results/tfMRI_{}_LR/tfMRI_{}_LR.nii.gz'.format(prefix, subject, task, task)
57
+ target_addr = os.path.join(addr, 'HCP_tfMRI/{}_tfMRI_{}_LR.nii.gz'.format(subject, task))
58
+
59
+ if not os.path.exists(target_addr):
60
+ try: bucket.download_file(source_addr, target_addr)
61
+ except: continue
62
+
63
+ for subtask in subtask_list:
64
+
65
+ subtask_source_addr = '{}{}/MNINonLinear/Results/tfMRI_{}_LR/EVs/{}.txt'.format(prefix, subject, task, subtask)
66
+ subtask_target_addr = os.path.join(addr, 'HCP_tfMRI/{}_tfMRI_{}_{}_ev.txt'.format(subject, task, subtask))
67
+
68
+ if not os.path.exists(subtask_target_addr):
69
+ try: bucket.download_file(subtask_source_addr, subtask_target_addr)
70
+ except: continue
71
+
72
+
73
+
74
+ def get_ABIDE(addr = './nii_data'):
75
+
76
+ fetch_abide_pcp(data_dir = addr, band_pass_filtering = True)
77
+ os.remove(os.path.join(addr, 'README.md'))
78
+ os.remove(os.path.join(addr, 'ABIDE_pcp/Phenotypic_V1_0b_preprocessed1.csv'))
79
+ shutil.move(os.path.join(addr, 'ABIDE_pcp/cpac/filt_noglobal'), os.path.join(addr, 'ABIDE'))
80
+ shutil.rmtree(os.path.join(addr, 'ABIDE_pcp'))
81
+
82
+
83
+
84
+ def get_fc_HCP_rfMRI(subject, atlas_name, atlas_loc, nii_addr = './nii_data', fc_addr = './fc_data'):
85
+
86
+ os.makedirs(os.path.join(fc_addr, 'HCP_rfMRI', atlas_name), exist_ok = True)
87
+
88
+ for run in ['REST1_LR', 'REST1_RL', 'REST2_LR', 'REST2_RL']:
89
+
90
+ rfmri_img = nib.load(os.path.join(nii_addr, 'HCP_rfMRI', '{}_rfMRI_{}_hp2000_clean.nii.gz'.format(subject, run)))
91
+ rfmri_data = rfmri_img.get_fdata(); X = rfmri_data.reshape(-1, rfmri_data.shape[-1])
92
+ atlas = nib.load(atlas_loc); atlas = resample_to_img(atlas, rfmri_img, interpolation = 'nearest')
93
+ labels = atlas.get_fdata().astype(int).flatten()
94
+ time_series = np.stack([X[labels == label, :].mean(axis = 0) for label in np.sort(np.unique(labels[labels > 0]))], axis = 1)
95
+ time_series = zscore(detrend(time_series, axis = 0, type = 'linear'), axis = 0, ddof = 1)
96
+
97
+ for i in range(int(X.shape[1]/300)):
98
+
99
+ fc = np.corrcoef(time_series[i*300:(i+1)*300].T); n = fc.shape[0]; fc = fc[np.triu_indices(n, k = 1)]
100
+ if not np.isnan(fc).any(): np.savez_compressed(os.path.join(fc_addr, 'HCP_rfMRI', '{}/{}_{}_{}.npz'.format(atlas_name, subject, run, i)), fc)
101
+
102
+
103
+
104
+ def get_fc_HCP_tfMRI(subject, atlas_name, atlas_loc, nii_addr = './nii_data', fc_addr = './fc_data'):
105
+
106
+ os.makedirs(os.path.join(fc_addr, 'HCP_tfMRI', atlas_name), exist_ok = True)
107
+
108
+ for task in ['WM', 'GAMBLING', 'MOTOR', 'LANGUAGE', 'SOCIAL', 'RELATIONAL', 'EMOTION']:
109
+
110
+ if task == 'WM': subtask_list = ['0bk_body', '0bk_faces', '0bk_places', '0bk_tools', '2bk_body', '2bk_faces', '2bk_places', '2bk_tools']
111
+ elif task == 'GAMBLING': subtask_list = ['win', 'loss']
112
+ elif task == 'MOTOR': subtask_list = ['cue', 'lf', 'rf', 'lh', 'rh', 't']
113
+ elif task == 'LANGUAGE': subtask_list = ['story', 'math']
114
+ elif task == 'SOCIAL': subtask_list = ['mental', 'rnd']
115
+ elif task == 'RELATIONAL': subtask_list = ['relation', 'match']
116
+ else: subtask_list = ['fear', 'neut']
117
+
118
+ tfmri_img = nib.load(os.path.join(nii_addr, 'HCP_tfMRI', '{}_tfMRI_{}_LR.nii.gz'.format(subject, task)))
119
+ tfmri_data = tfmri_img.get_fdata(); X = tfmri_data.reshape(-1, tfmri_data.shape[-1])
120
+ atlas = nib.load(atlas_loc); atlas = resample_to_img(atlas, tfmri_img, interpolation = 'nearest')
121
+ labels = atlas.get_fdata().astype(int).flatten()
122
+ time_series = np.stack([X[labels == label, :].mean(axis = 0) for label in np.sort(np.unique(labels[labels > 0]))], axis = 1)
123
+ time_series = zscore(detrend(time_series, axis = 0, type = 'linear'), axis = 0, ddof = 1)
124
+
125
+ fc = np.corrcoef(time_series.T); n = fc.shape[0]; fc = fc[np.triu_indices(n, k = 1)]
126
+ if not np.isnan(fc).any(): np.savez_compressed(os.path.join(fc_addr, 'HCP_tfMRI', '{}/{}_{}_LR.npz'.format(atlas_name, subject, task)), fc)
127
+
128
+ timepoint = np.arange(X.shape[-1]) * 0.72
129
+
130
+ for subtask in subtask_list:
131
+
132
+ if not os.path.exists(os.path.join(nii_addr, 'HCP_tfMRI', '{}_tfMRI_{}_{}_ev.txt'.format(subject, task, subtask))): continue
133
+
134
+ task_timepoint = np.loadtxt(os.path.join(nii_addr, 'HCP_tfMRI', '{}_tfMRI_{}_{}_ev.txt'.format(subject, task, subtask))).reshape(-1, 3)
135
+ subtask_time_series = np.vstack([time_series[(timepoint > task_timepoint[i, 0] - 1e-3) & (timepoint < task_timepoint[i, 0] + task_timepoint[i, 1] + 1e-3)] for i in range(task_timepoint.shape[0])])
136
+ fc = np.corrcoef(subtask_time_series.T); n = fc.shape[0]; fc = fc[np.triu_indices(n, k = 1)]
137
+ if not np.isnan(fc).any(): np.savez_compressed(os.path.join(fc_addr, 'HCP_tfMRI', '{}/{}_{}_LR_{}.npz'.format(atlas_name, subject, task, subtask)), fc)
138
+
139
+
140
+
141
+ def get_fc_ABIDE(atlas_name, atlas_loc, nii_addr = './nii_data', fc_addr = './fc_data'):
142
+
143
+ os.makedirs(os.path.join(fc_addr, 'ABIDE', atlas_name), exist_ok = True)
144
+
145
+ for filename in os.listdir(os.path.join(nii_addr, 'ABIDE')):
146
+
147
+ prefix = filename[:-20]
148
+
149
+ rfmri_img = nib.load(os.path.join(nii_addr, 'ABIDE', filename))
150
+ rfmri_data = rfmri_img.get_fdata(); X = rfmri_data.reshape(-1, rfmri_data.shape[-1])
151
+ atlas = nib.load(atlas_loc); atlas = resample_to_img(atlas, rfmri_img, interpolation = 'nearest')
152
+ labels = atlas.get_fdata().astype(int).flatten()
153
+ time_series = np.stack([X[labels == label, :].mean(axis = 0) for label in np.sort(np.unique(labels[labels > 0]))], axis = 1)
154
+ time_series = zscore(detrend(time_series, axis = 0, type = 'linear'), axis = 0, ddof = 1)
155
+ fc = np.corrcoef(time_series.T); n = fc.shape[0]; fc = fc[np.triu_indices(n, k = 1)]
156
+ if not np.isnan(fc).any(): np.savez_compressed(os.path.join(fc_addr, 'ABIDE', '{}/{}.npz'.format(atlas_name, prefix)), fc)
157
+
158
+
159
+
160
+ def get_fc_ADNI(atlas_name, atlas_loc, nii_addr = './nii_data', fc_addr = './fc_data'):
161
+
162
+ os.makedirs(os.path.join(fc_addr, 'ADNI', atlas_name), exist_ok = True)
163
+
164
+ for prefix in os.listdir(os.path.join(nii_addr, 'ADNI')):
165
+
166
+ rfmri_img = nib.load(os.path.join(nii_addr, 'ADNI', prefix, 'Filtered_4DVolume.nii'))
167
+ rfmri_data = rfmri_img.get_fdata(); X = rfmri_data.reshape(-1, rfmri_data.shape[-1])
168
+ atlas = nib.load(atlas_loc); atlas = resample_to_img(atlas, rfmri_img, interpolation = 'nearest')
169
+ labels = atlas.get_fdata().astype(int).flatten()
170
+ time_series = np.stack([X[labels == label, :].mean(axis = 0) for label in np.sort(np.unique(labels[labels > 0]))], axis = 1)
171
+ time_series = zscore(detrend(time_series, axis = 0, type = 'linear'), axis = 0, ddof = 1)
172
+ fc = np.corrcoef(time_series.T); n = fc.shape[0]; fc = fc[np.triu_indices(n, k = 1)]
173
+ if not np.isnan(fc).any(): np.savez_compressed(os.path.join(fc_addr, 'ADNI', '{}/{}.npz'.format(atlas_name, prefix)), fc)
174
+
175
+
176
+
177
+ def fc_stability(atlas_name, fc_addr = './fc_data'):
178
+
179
+ subjlist = np.loadtxt('./docs/HCP_subjlist.txt', dtype = str)
180
+ addr = os.path.join(fc_addr, 'HCP_rfMRI', atlas_name)
181
+
182
+ res_list = []
183
+ for sub in subjlist:
184
+ if len([file for file in os.listdir(addr) if sub in file]) > 1:
185
+ fc_corr = np.corrcoef(np.array([np.load(os.path.join(addr, file))['arr_0'] for file in os.listdir(addr) if sub in file]))
186
+ res_list.append(np.mean(fc_corr[np.triu_indices(fc_corr.shape[0], k = 1)]))
187
+
188
+ return np.array(res_list)
189
+
190
+
191
+
192
+ def fingerprinting(atlas_name, fc_addr = './fc_data'):
193
+
194
+ addr = os.path.join(fc_addr, 'HCP_rfMRI', atlas_name)
195
+ subjlist = np.loadtxt('./docs/HCP_subjlist.txt', dtype = str)
196
+ subjlist = [sub for sub in subjlist if [file for file in os.listdir(addr) if sub in file] != []]
197
+
198
+ reference = [np.load(os.path.join(addr, [file for file in os.listdir(addr) if sub in file][0]))['arr_0'] for sub in subjlist]
199
+ res_list = []
200
+
201
+ for sub in subjlist:
202
+ if len([file for file in os.listdir(addr) if sub in file]) == 1: continue
203
+ file_list = [file for file in os.listdir(addr) if sub in file][1:]
204
+ fc_list = [np.load(os.path.join(addr, file))['arr_0'] for file in file_list]
205
+ count = 0
206
+ for idx in range(len(file_list)):
207
+ temp = np.array([np.corrcoef([fc_list[idx], ref])[0, 1] for ref in reference])
208
+ if subjlist[np.where(temp == np.max(temp))[0][0]] == sub: count += 1
209
+ res_list.append(count/len(fc_list))
210
+
211
+ return np.array(res_list)
212
+
213
+
214
+
215
+ def age_group_classification(atlas_name, fc_addr = './fc_data'):
216
+
217
+ subjlist = np.loadtxt('./docs/HCP_subjlist.txt', dtype = str)
218
+ behavior = pd.read_csv('./docs/behavior_HCP.csv').to_dict(orient = 'list')
219
+
220
+ addr = os.path.join(fc_addr, 'HCP_rfMRI', atlas_name)
221
+
222
+ sub_X = []; sub_y = []; mat_X = []; mat_y = []; mat_master = []
223
+ for sub in subjlist:
224
+ target = behavior['Age_Group'][behavior['Subject'].index(int(sub))]
225
+ if np.isnan(target): continue
226
+ sub_X.append(int(sub)); sub_y.append(target)
227
+ file_list = [np.load(os.path.join(addr, file))['arr_0'] for file in os.listdir(addr) if sub in file]
228
+ for f in file_list: mat_X.append(f); mat_y.append(target); mat_master.append(int(sub))
229
+ sub_X = np.array(sub_X); sub_y = np.array(sub_y); mat_X = np.array(mat_X); mat_y = np.array(mat_y); mat_master = np.array(mat_master)
230
+
231
+ skf = StratifiedKFold(n_splits = 10, shuffle = True, random_state = 0)
232
+ acc_list = []
233
+
234
+ for trainsub_idx, testsub_idx in skf.split(sub_X, sub_y):
235
+
236
+ train_sub, test_sub = sub_X[trainsub_idx], sub_X[testsub_idx]
237
+ trainmat_idx = np.array([(train_sub == master).any() for master in mat_master]); testmat_idx = np.array([(test_sub == master).any() for master in mat_master])
238
+ X_train, X_test = mat_X[trainmat_idx], mat_X[testmat_idx]; y_train, y_test = mat_y[trainmat_idx], mat_y[testmat_idx]
239
+
240
+ if X_train.shape[1] > 100:
241
+
242
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
243
+ pca = PCA(n_components = 100, random_state = 0); X_train_pca = pca.fit_transform(X_train_scaled); X_test_pca = pca.transform(X_test_scaled)
244
+
245
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
246
+ clf.fit(X_train_pca, y_train)
247
+
248
+ y_pred = clf.predict(X_test_pca)
249
+ acc_list.append(accuracy_score(y_test, y_pred))
250
+
251
+ else:
252
+
253
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
254
+
255
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
256
+ clf.fit(X_train_scaled, y_train)
257
+
258
+ y_pred = clf.predict(X_test_scaled)
259
+ acc_list.append(accuracy_score(y_test, y_pred))
260
+
261
+ return np.array(acc_list)
262
+
263
+
264
+
265
+ def gender_classification(atlas_name, fc_addr = './fc_data'):
266
+
267
+ subjlist = np.loadtxt('./docs/HCP_subjlist.txt', dtype = str)
268
+ behavior = pd.read_csv('./docs/behavior_HCP.csv').to_dict(orient = 'list')
269
+
270
+ addr = os.path.join(fc_addr, 'HCP_rfMRI', atlas_name)
271
+
272
+ sub_X = []; sub_y = []; mat_X = []; mat_y = []; mat_master = []
273
+ for sub in subjlist:
274
+ target = int(behavior['Gender'][behavior['Subject'].index(int(sub))] == 'M')
275
+ if np.isnan(target): continue
276
+ sub_X.append(int(sub)); sub_y.append(target)
277
+ file_list = [np.load(os.path.join(os.path.join(addr, file)))['arr_0'] for file in os.listdir(addr) if sub in file]
278
+ for f in file_list: mat_X.append(f); mat_y.append(target); mat_master.append(int(sub))
279
+ sub_X = np.array(sub_X); sub_y = np.array(sub_y); mat_X = np.array(mat_X); mat_y = np.array(mat_y); mat_master = np.array(mat_master)
280
+
281
+ skf = StratifiedKFold(n_splits = 10, shuffle = True, random_state = 0)
282
+ acc_list = []
283
+
284
+ for trainsub_idx, testsub_idx in skf.split(sub_X, sub_y):
285
+
286
+ train_sub, test_sub = sub_X[trainsub_idx], sub_X[testsub_idx]
287
+ trainmat_idx = np.array([(train_sub == master).any() for master in mat_master]); testmat_idx = np.array([(test_sub == master).any() for master in mat_master])
288
+ X_train, X_test = mat_X[trainmat_idx], mat_X[testmat_idx]; y_train, y_test = mat_y[trainmat_idx], mat_y[testmat_idx]
289
+
290
+ if X_train.shape[1] > 100:
291
+
292
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
293
+ pca = PCA(n_components = 100, random_state = 0); X_train_pca = pca.fit_transform(X_train_scaled); X_test_pca = pca.transform(X_test_scaled)
294
+
295
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
296
+ clf.fit(X_train_pca, y_train)
297
+
298
+ y_pred = clf.predict(X_test_pca)
299
+ acc_list.append(accuracy_score(y_test, y_pred))
300
+
301
+ else:
302
+
303
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
304
+
305
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
306
+ clf.fit(X_train_scaled, y_train)
307
+
308
+ y_pred = clf.predict(X_test_scaled)
309
+ acc_list.append(accuracy_score(y_test, y_pred))
310
+
311
+ return np.array(acc_list)
312
+
313
+
314
+
315
+ def fluid_intelligence(atlas_name, fc_addr = './fc_data'):
316
+
317
+ subjlist = np.loadtxt('./docs/HCP_subjlist.txt', dtype = str)
318
+ behavior = pd.read_csv('./docs/behavior_HCP.csv').to_dict(orient = 'list')
319
+
320
+ addr = os.path.join(fc_addr, 'HCP_rfMRI', atlas_name)
321
+
322
+ sub_X = []; sub_y = []; mat_X = []; mat_y = []; mat_master = []
323
+ for sub in subjlist:
324
+ target = behavior['CogFluidComp_AgeAdj_Group'][behavior['Subject'].index(int(sub))]
325
+ if np.isnan(target): continue
326
+ sub_X.append(int(sub)); sub_y.append(target)
327
+ file_list = [np.load(os.path.join(addr, file))['arr_0'] for file in os.listdir(addr) if sub in file]
328
+ for f in file_list: mat_X.append(f); mat_y.append(target); mat_master.append(int(sub))
329
+ sub_X = np.array(sub_X); sub_y = np.array(sub_y); mat_X = np.array(mat_X); mat_y = np.array(mat_y); mat_master = np.array(mat_master)
330
+
331
+ skf = StratifiedKFold(n_splits = 10, shuffle = True, random_state = 0)
332
+ acc_list = []
333
+
334
+ for trainsub_idx, testsub_idx in skf.split(sub_X, sub_y):
335
+
336
+ train_sub, test_sub = sub_X[trainsub_idx], sub_X[testsub_idx]
337
+ trainmat_idx = np.array([(train_sub == master).any() for master in mat_master]); testmat_idx = np.array([(test_sub == master).any() for master in mat_master])
338
+ X_train, X_test = mat_X[trainmat_idx], mat_X[testmat_idx]; y_train, y_test = mat_y[trainmat_idx], mat_y[testmat_idx]
339
+
340
+ if X_train.shape[1] > 100:
341
+
342
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
343
+ pca = PCA(n_components = 100, random_state = 0); X_train_pca = pca.fit_transform(X_train_scaled); X_test_pca = pca.transform(X_test_scaled)
344
+
345
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
346
+ clf.fit(X_train_pca, y_train)
347
+
348
+ y_pred = clf.predict(X_test_pca)
349
+ acc_list.append(accuracy_score(y_test, y_pred))
350
+
351
+ else:
352
+
353
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
354
+
355
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
356
+ clf.fit(X_train_scaled, y_train)
357
+
358
+ y_pred = clf.predict(X_test_scaled)
359
+ acc_list.append(accuracy_score(y_test, y_pred))
360
+
361
+ return np.array(acc_list)
362
+
363
+
364
+
365
+ def crystallized_intelligence(atlas_name, fc_addr = './fc_data'):
366
+
367
+ subjlist = np.loadtxt('./docs/HCP_subjlist.txt', dtype = str)
368
+ behavior = pd.read_csv('./docs/behavior_HCP.csv').to_dict(orient = 'list')
369
+
370
+ addr = os.path.join(fc_addr, 'HCP_rfMRI', atlas_name)
371
+
372
+ sub_X = []; sub_y = []; mat_X = []; mat_y = []; mat_master = []
373
+ for sub in subjlist:
374
+ target = behavior['CogCrystalComp_AgeAdj_Group'][behavior['Subject'].index(int(sub))]
375
+ if np.isnan(target): continue
376
+ sub_X.append(int(sub)); sub_y.append(target)
377
+ file_list = [np.load(os.path.join(addr, file))['arr_0'] for file in os.listdir(addr) if sub in file]
378
+ for f in file_list: mat_X.append(f); mat_y.append(target); mat_master.append(int(sub))
379
+ sub_X = np.array(sub_X); sub_y = np.array(sub_y); mat_X = np.array(mat_X); mat_y = np.array(mat_y); mat_master = np.array(mat_master)
380
+
381
+ skf = StratifiedKFold(n_splits = 10, shuffle = True, random_state = 0)
382
+ acc_list = []
383
+
384
+ for trainsub_idx, testsub_idx in skf.split(sub_X, sub_y):
385
+
386
+ train_sub, test_sub = sub_X[trainsub_idx], sub_X[testsub_idx]
387
+ trainmat_idx = np.array([(train_sub == master).any() for master in mat_master]); testmat_idx = np.array([(test_sub == master).any() for master in mat_master])
388
+ X_train, X_test = mat_X[trainmat_idx], mat_X[testmat_idx]; y_train, y_test = mat_y[trainmat_idx], mat_y[testmat_idx]
389
+
390
+ if X_train.shape[1] > 100:
391
+
392
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
393
+ pca = PCA(n_components = 100, random_state = 0); X_train_pca = pca.fit_transform(X_train_scaled); X_test_pca = pca.transform(X_test_scaled)
394
+
395
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
396
+ clf.fit(X_train_pca, y_train)
397
+
398
+ y_pred = clf.predict(X_test_pca)
399
+ acc_list.append(accuracy_score(y_test, y_pred))
400
+
401
+ else:
402
+
403
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
404
+
405
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
406
+ clf.fit(X_train_scaled, y_train)
407
+
408
+ y_pred = clf.predict(X_test_scaled)
409
+ acc_list.append(accuracy_score(y_test, y_pred))
410
+
411
+ return np.array(acc_list)
412
+
413
+
414
+
415
+ def general_intelligence(atlas_name, fc_addr = './fc_data'):
416
+
417
+ subjlist = np.loadtxt('./docs/HCP_subjlist.txt', dtype = str)
418
+ behavior = pd.read_csv('./docs/behavior_HCP.csv').to_dict(orient = 'list')
419
+
420
+ addr = os.path.join(fc_addr, 'HCP_rfMRI', atlas_name)
421
+
422
+ sub_X = []; sub_y = []; mat_X = []; mat_y = []; mat_master = []
423
+ for sub in subjlist:
424
+ target = behavior['CogTotalComp_AgeAdj_Group'][behavior['Subject'].index(int(sub))]
425
+ if np.isnan(target): continue
426
+ sub_X.append(int(sub)); sub_y.append(target)
427
+ file_list = [np.load(os.path.join(addr, file))['arr_0'] for file in os.listdir(addr) if sub in file]
428
+ for f in file_list: mat_X.append(f); mat_y.append(target); mat_master.append(int(sub))
429
+ sub_X = np.array(sub_X); sub_y = np.array(sub_y); mat_X = np.array(mat_X); mat_y = np.array(mat_y); mat_master = np.array(mat_master)
430
+
431
+ skf = StratifiedKFold(n_splits = 10, shuffle = True, random_state = 0)
432
+ acc_list = []
433
+
434
+ for trainsub_idx, testsub_idx in skf.split(sub_X, sub_y):
435
+
436
+ train_sub, test_sub = sub_X[trainsub_idx], sub_X[testsub_idx]
437
+ trainmat_idx = np.array([(train_sub == master).any() for master in mat_master]); testmat_idx = np.array([(test_sub == master).any() for master in mat_master])
438
+ X_train, X_test = mat_X[trainmat_idx], mat_X[testmat_idx]; y_train, y_test = mat_y[trainmat_idx], mat_y[testmat_idx]
439
+
440
+ if X_train.shape[1] > 100:
441
+
442
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
443
+ pca = PCA(n_components = 100, random_state = 0); X_train_pca = pca.fit_transform(X_train_scaled); X_test_pca = pca.transform(X_test_scaled)
444
+
445
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
446
+ clf.fit(X_train_pca, y_train)
447
+
448
+ y_pred = clf.predict(X_test_pca)
449
+ acc_list.append(accuracy_score(y_test, y_pred))
450
+
451
+ else:
452
+
453
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
454
+
455
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
456
+ clf.fit(X_train_scaled, y_train)
457
+
458
+ y_pred = clf.predict(X_test_scaled)
459
+ acc_list.append(accuracy_score(y_test, y_pred))
460
+
461
+ return np.array(acc_list)
462
+
463
+
464
+
465
+ def cognitive_task_7way(atlas_name, fc_addr = './fc_data'):
466
+
467
+ subjlist = np.loadtxt('./docs/HCP_subjlist.txt', dtype = str)
468
+ addr = os.path.join(fc_addr, 'HCP_tfMRI', atlas_name)
469
+ task = ['WM', 'GAMBLING', 'MOTOR', 'LANGUAGE', 'SOCIAL', 'RELATIONAL', 'EMOTION']
470
+
471
+ mat_X = []; mat_y = []; mat_master = []
472
+ for sub in subjlist:
473
+ for t in task:
474
+ if not os.path.exists(os.path.join(addr, '{}_{}_LR.npz'.format(sub, t))): continue
475
+ mat_X.append(np.load(os.path.join(addr, '{}_{}_LR.npz'.format(sub, t)))['arr_0']); mat_y.append(task.index(t)); mat_master.append(sub)
476
+ mat_X = np.array(mat_X); mat_y = np.array(mat_y); mat_master = np.array(mat_master)
477
+
478
+ kf = KFold(n_splits = 10, shuffle = True, random_state = 0)
479
+ acc_list = []
480
+
481
+ for trainsub_idx, testsub_idx in kf.split(subjlist):
482
+
483
+ train_sub, test_sub = subjlist[trainsub_idx], subjlist[testsub_idx]
484
+ trainmat_idx = np.array([(train_sub == master).any() for master in mat_master]); testmat_idx = np.array([(test_sub == master).any() for master in mat_master])
485
+ X_train, X_test = mat_X[trainmat_idx], mat_X[testmat_idx]; y_train, y_test = mat_y[trainmat_idx], mat_y[testmat_idx]
486
+
487
+ if X_train.shape[1] > 100:
488
+
489
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
490
+ pca = PCA(n_components = 100, random_state = 0); X_train_pca = pca.fit_transform(X_train_scaled); X_test_pca = pca.transform(X_test_scaled)
491
+
492
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
493
+ clf.fit(X_train_pca, y_train)
494
+
495
+ y_pred = clf.predict(X_test_pca)
496
+ acc_list.append(accuracy_score(y_test, y_pred))
497
+
498
+ else:
499
+
500
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
501
+
502
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
503
+ clf.fit(X_train_scaled, y_train)
504
+
505
+ y_pred = clf.predict(X_test_scaled)
506
+ acc_list.append(accuracy_score(y_test, y_pred))
507
+
508
+ return np.array(acc_list)
509
+
510
+
511
+
512
+ def cognitive_task_24way(atlas_name, fc_addr = './fc_data'):
513
+
514
+ subjlist = np.loadtxt('./docs/HCP_subjlist.txt', dtype = str)
515
+ addr = os.path.join(fc_addr, 'HCP_tfMRI', atlas_name)
516
+ task = {
517
+ '0bk_body': 'WM', '0bk_faces': 'WM', '0bk_places': 'WM', '0bk_tools': 'WM', '2bk_body': 'WM', '2bk_faces': 'WM', '2bk_places': 'WM', '2bk_tools': 'WM',
518
+ 'win': 'GAMBLING', 'loss': 'GAMBLING',
519
+ 'cue': 'MOTOR', 'lf': 'MOTOR', 'rf': 'MOTOR', 'lh': 'MOTOR', 'rh': 'MOTOR', 't': 'MOTOR',
520
+ 'story': 'LANGUAGE', 'math': 'LANGUAGE',
521
+ 'mental': 'SOCIAL', 'rnd': 'SOCIAL',
522
+ 'relation': 'RELATIONAL', 'match': 'RELATIONAL',
523
+ 'fear': 'EMOTION', 'neut': 'EMOTION'
524
+ }
525
+
526
+ mat_X = []; mat_y = []; mat_master = []
527
+ for sub in subjlist:
528
+ for t in list(task.keys()):
529
+ if not os.path.exists(os.path.join(addr, '{}_{}_LR_{}.npz'.format(sub, task[t], t))): continue
530
+ mat_X.append(np.load(os.path.join(addr, '{}_{}_LR_{}.npz'.format(sub, task[t], t)))['arr_0']); mat_y.append(list(task.keys()).index(t)); mat_master.append(sub)
531
+ mat_X = np.array(mat_X); mat_y = np.array(mat_y); mat_master = np.array(mat_master)
532
+
533
+ kf = KFold(n_splits = 10, shuffle = True, random_state = 0)
534
+ acc_list = []
535
+
536
+ for trainsub_idx, testsub_idx in kf.split(subjlist):
537
+
538
+ train_sub, test_sub = subjlist[trainsub_idx], subjlist[testsub_idx]
539
+ trainmat_idx = np.array([(train_sub == master).any() for master in mat_master]); testmat_idx = np.array([(test_sub == master).any() for master in mat_master])
540
+ X_train, X_test = mat_X[trainmat_idx], mat_X[testmat_idx]; y_train, y_test = mat_y[trainmat_idx], mat_y[testmat_idx]
541
+
542
+ if X_train.shape[1] > 100:
543
+
544
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
545
+ pca = PCA(n_components = 100, random_state = 0); X_train_pca = pca.fit_transform(X_train_scaled); X_test_pca = pca.transform(X_test_scaled)
546
+
547
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
548
+ clf.fit(X_train_pca, y_train)
549
+
550
+ y_pred = clf.predict(X_test_pca)
551
+ acc_list.append(accuracy_score(y_test, y_pred))
552
+
553
+ else:
554
+
555
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
556
+
557
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
558
+ clf.fit(X_train_scaled, y_train)
559
+
560
+ y_pred = clf.predict(X_test_scaled)
561
+ acc_list.append(accuracy_score(y_test, y_pred))
562
+
563
+ return np.array(acc_list)
564
+
565
+
566
+
567
+ def autism_diagnosis(atlas_name, fc_addr = './fc_data'):
568
+
569
+ behavior = pd.read_csv('./docs/behavior_ABIDE.csv').to_dict(orient = 'list')
570
+ addr = os.path.join(fc_addr, 'ABIDE', atlas_name)
571
+
572
+ mat_X = []; mat_y = []
573
+ for file in os.listdir(addr):
574
+ target = behavior['DX_GROUP'][behavior['FILE_ID'].index(file[:-4])]
575
+ if np.isnan(target): continue
576
+ mat_X.append(np.load(os.path.join(addr, file))['arr_0']); mat_y.append(target)
577
+ mat_X = np.array(mat_X); mat_y = np.array(mat_y)
578
+
579
+ skf = StratifiedKFold(n_splits = 10, shuffle = True, random_state = 0)
580
+ acc_list = []
581
+
582
+ for trainmat_idx, testmat_idx in skf.split(mat_X, mat_y):
583
+
584
+ X_train, X_test = mat_X[trainmat_idx], mat_X[testmat_idx]; y_train, y_test = mat_y[trainmat_idx], mat_y[testmat_idx]
585
+
586
+ if X_train.shape[1] > 100:
587
+
588
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
589
+ pca = PCA(n_components = 100, random_state = 0); X_train_pca = pca.fit_transform(X_train_scaled); X_test_pca = pca.transform(X_test_scaled)
590
+
591
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
592
+ clf.fit(X_train_pca, y_train)
593
+
594
+ y_pred = clf.predict(X_test_pca)
595
+ acc_list.append(accuracy_score(y_test, y_pred))
596
+
597
+ else:
598
+
599
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
600
+
601
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
602
+ clf.fit(X_train_scaled, y_train)
603
+
604
+ y_pred = clf.predict(X_test_scaled)
605
+ acc_list.append(accuracy_score(y_test, y_pred))
606
+
607
+ return np.array(acc_list)
608
+
609
+
610
+
611
+ def autism_cross_site(atlas_name, fc_addr = './fc_data'):
612
+
613
+ behavior = pd.read_csv('./docs/behavior_ABIDE.csv').to_dict(orient = 'list')
614
+ addr = os.path.join(fc_addr, 'ABIDE', atlas_name)
615
+
616
+ mat_X = []; mat_y = []; mat_master = []
617
+ for file in os.listdir(addr):
618
+ target = behavior['DX_GROUP'][behavior['FILE_ID'].index(file[:-4])]
619
+ site = behavior['SITE_ID'][behavior['FILE_ID'].index(file[:-4])]
620
+ if np.isnan(target): continue
621
+ mat_X.append(np.load(os.path.join(addr, file))['arr_0']); mat_y.append(target); mat_master.append(site)
622
+ mat_X = np.array(mat_X); mat_y = np.array(mat_y); mat_master = np.array(mat_master, dtype = str)
623
+
624
+ acc_list = []
625
+
626
+ for holdout_site in np.unique(mat_master):
627
+
628
+ trainmat_idx = np.array([(master != holdout_site) for master in mat_master]); testmat_idx = np.array([(master == holdout_site) for master in mat_master])
629
+ X_train, X_test = mat_X[trainmat_idx], mat_X[testmat_idx]; y_train, y_test = mat_y[trainmat_idx], mat_y[testmat_idx]
630
+
631
+ if X_train.shape[1] > 100:
632
+
633
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
634
+ pca = PCA(n_components = 100, random_state = 0); X_train_pca = pca.fit_transform(X_train_scaled); X_test_pca = pca.transform(X_test_scaled)
635
+
636
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
637
+ clf.fit(X_train_pca, y_train)
638
+
639
+ y_pred = clf.predict(X_test_pca)
640
+ acc_list.append(accuracy_score(y_test, y_pred))
641
+
642
+ else:
643
+
644
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
645
+
646
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
647
+ clf.fit(X_train_scaled, y_train)
648
+
649
+ y_pred = clf.predict(X_test_scaled)
650
+ acc_list.append(accuracy_score(y_test, y_pred))
651
+
652
+ return np.array(acc_list)
653
+
654
+
655
+
656
+ def AD_diagnosis(atlas_name, fc_addr = './fc_data'):
657
+
658
+ behavior = pd.read_csv('./docs/behavior_ADNI.csv').to_dict(orient = 'list')
659
+ addr = os.path.join(fc_addr, 'ADNI', atlas_name)
660
+
661
+ mat_X = []; mat_y = []
662
+ for file in os.listdir(addr):
663
+ target = behavior['Research Group'][behavior['Subject ID'].index(file[:-4])]
664
+ if target == 'CN': target_idx = 0
665
+ elif target == 'MCI': target_idx = 1
666
+ else: target_idx = 2
667
+ mat_X.append(np.load(os.path.join(addr, file))['arr_0']); mat_y.append(target_idx)
668
+ mat_X = np.array(mat_X); mat_y = np.array(mat_y)
669
+
670
+ skf = StratifiedKFold(n_splits = 10, shuffle = True, random_state = 0)
671
+ acc_list = []
672
+
673
+ for trainmat_idx, testmat_idx in skf.split(mat_X, mat_y):
674
+
675
+ X_train, X_test = mat_X[trainmat_idx], mat_X[testmat_idx]; y_train, y_test = mat_y[trainmat_idx], mat_y[testmat_idx]
676
+
677
+ if X_train.shape[1] > 100:
678
+
679
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
680
+ pca = PCA(n_components = 100, random_state = 0); X_train_pca = pca.fit_transform(X_train_scaled); X_test_pca = pca.transform(X_test_scaled)
681
+
682
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
683
+ clf.fit(X_train_pca, y_train)
684
+
685
+ y_pred = clf.predict(X_test_pca)
686
+ acc_list.append(accuracy_score(y_test, y_pred))
687
+
688
+ else:
689
+
690
+ scaler = StandardScaler(); X_train_scaled = scaler.fit_transform(X_train); X_test_scaled = scaler.transform(X_test)
691
+
692
+ clf = SVC(kernel = 'linear', class_weight = 'balanced')
693
+ clf.fit(X_train_scaled, y_train)
694
+
695
+ y_pred = clf.predict(X_test_scaled)
696
+ acc_list.append(accuracy_score(y_test, y_pred))
697
+
698
+ return np.array(acc_list)
699
+
700
+
701
+
702
+ def downstream_all(atlas_name, fc_addr = './fc_data'):
703
+
704
+ print('--- {} downstream report ---'.format(atlas_name))
705
+
706
+ res = gender_classification(atlas_name, fc_addr)
707
+ print('Gender classification: {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
708
+
709
+ res = fluid_intelligence(atlas_name, fc_addr)
710
+ print('Fluid intelligence: {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
711
+
712
+ res = cognitive_task_7way(atlas_name, fc_addr)
713
+ print('Cognitive task (7-way): {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
714
+
715
+ res = cognitive_task_24way(atlas_name, fc_addr)
716
+ print('Cognitive task (24-way): {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
717
+
718
+ res = autism_diagnosis(atlas_name, fc_addr)
719
+ print('Autism diagnosis: {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
720
+
721
+ res = AD_diagnosis(atlas_name, fc_addr)
722
+ print('AD diagnosis: {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
723
+
724
+ res = fc_stability(atlas_name, fc_addr)
725
+ print('FC stability: {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
726
+
727
+ res = fingerprinting(atlas_name, fc_addr)
728
+ print('Fingerprinting: {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
729
+
730
+ res = age_group_classification(atlas_name, fc_addr)
731
+ print('Age group classification: {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
732
+
733
+ res = crystallized_intelligence(atlas_name, fc_addr)
734
+ print('Crystallized intelligence: {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
735
+
736
+ res = general_intelligence(atlas_name, fc_addr)
737
+ print('General intelligence: {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
738
+
739
+ res = autism_cross_site(atlas_name, fc_addr)
740
+ print('Autism cross-site: {:.3f}±{:.3f}'.format(np.mean(res), np.std(res)))
AtlaScore/downstream/fc_data/fc_data.zip ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2635230a3252baf502aa451b5d5289cc1c6d5fc41c476faba3a916eb4c0e707e
3
+ size 215604832
AtlaScore/similarity/compute_adj.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import nibabel as nib
3
+ from scipy.ndimage import generate_binary_structure, binary_dilation
4
+
5
+
6
+ def calculate_label_adjacency_bg(atlas_file, exclude_zero=True):
7
+ if atlas_file.endswith('nii.gz'):
8
+ nii = nib.load(atlas_file)
9
+ data = nii.get_fdata().astype(np.int32)
10
+ else:
11
+ data = np.load(atlas_file)
12
+
13
+ unique_labels = np.unique(data)
14
+ bg_label = np.min(unique_labels)
15
+ print('background value: ', bg_label)
16
+
17
+ if exclude_zero:
18
+ unique_labels = unique_labels[unique_labels != bg_label]
19
+
20
+ adjacency_dict = {label: set() for label in unique_labels}
21
+
22
+ struct = generate_binary_structure(3, 3)
23
+
24
+ for label in unique_labels:
25
+ mask = (data == label)
26
+
27
+ dilated = binary_dilation(mask, structure=struct)
28
+ border = dilated & ~mask
29
+
30
+ adjacent_labels = np.unique(data[border])
31
+ if exclude_zero:
32
+ adjacent_labels = adjacent_labels[adjacent_labels != 0]
33
+
34
+ adjacency_dict[label].update(adjacent_labels)
35
+
36
+ adjacency_dict = {k: list(v) for k, v in adjacency_dict.items()}
37
+
38
+ return adjacency_dict
39
+
40
+
41
+
42
+ def get_adjacent_voxels(atlas_file, adjacency_dict):
43
+ if atlas_file.endswith('nii.gz'):
44
+ nii = nib.load(atlas_file)
45
+ data = nii.get_fdata().astype(np.int32)
46
+ else:
47
+ data = np.load(atlas_file)
48
+ label_voxels = {}
49
+ for label in adjacency_dict.keys():
50
+ label_voxels[label] = np.array(np.where(data == label)).T
51
+
52
+ adj_voxel_dict = {}
53
+
54
+ print(f"total of {len(adjacency_dict)} label adjacency relationship:")
55
+ for label, neighbors in adjacency_dict.items():
56
+ print(f"Processing label {label}, {len(neighbors)} neighbors")
57
+
58
+ adjacent_voxels = []
59
+ for n in neighbors:
60
+ if n in label_voxels:
61
+ adjacent_voxels.extend(label_voxels[n])
62
+
63
+ adj_voxel_dict[label] = np.array(adjacent_voxels) if adjacent_voxels else np.array([])
64
+
65
+ print(f"Label {label} neighbor: {len(adj_voxel_dict[label])}")
66
+
67
+ return adj_voxel_dict
AtlaScore/similarity/eva.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import nibabel as nib
2
+ import numpy as np
3
+ import pyzstd,io
4
+ import pickle
5
+ import cupy as cp
6
+ from compute_adj import calculate_label_adjacency_bg, get_adjacent_voxels
7
+
8
+ def load_zstd_file(file_path):
9
+ with open(file_path, 'rb') as f:
10
+ decompressed_data = pyzstd.decompress(f.read())
11
+ buffer = io.BytesIO(decompressed_data)
12
+ return np.load(buffer)
13
+
14
+
15
+ def load_dict_pickle(file_path):
16
+ with open(file_path, 'rb') as f:
17
+ return pickle.load(f)
18
+
19
+
20
+ def evaluate(input_file, label_file, adj_dict):
21
+
22
+ if input_file.endswith('.zst'):
23
+ input_matrix = load_zstd_file(input_file)
24
+ else:
25
+ input_matrix = nib.load(input_file).get_fdata()
26
+ input_matrix = input_matrix[:,:,:,:300]
27
+ # print(input_matrix.shape) # (96, 96, 96, 60)
28
+
29
+ # img_label = nib.load(label_file)
30
+ if label_file.endswith('nii.gz'):
31
+ label_matrix = nib.load(label_file)
32
+ label_matrix = label_matrix.get_fdata()
33
+ else:
34
+ label_matrix = np.load(label_file)
35
+ # print(f'Unique labels in {label_file}:', np.unique(label_matrix))
36
+
37
+ unique_labels = np.unique(label_matrix)
38
+ bg = np.min(unique_labels)
39
+ print('background value: ', bg)
40
+ unique_labels = unique_labels[unique_labels > bg]
41
+ print('roi number:',len(unique_labels))
42
+ fc_means = {}
43
+ voxel_counts = {}
44
+ silhouette_scores = {}
45
+
46
+ for label in unique_labels:
47
+ voxel_indices = np.argwhere(label_matrix == label)
48
+ if voxel_indices.shape[0] < 2:
49
+ fc_means[label] = np.nan
50
+ voxel_counts[label] = len(voxel_indices)
51
+ silhouette_scores[label] = np.nan
52
+ continue
53
+ time_series = input_matrix[voxel_indices[:, 0], voxel_indices[:, 1], voxel_indices[:, 2], :]
54
+ n_voxels = time_series.shape[0]
55
+
56
+ fc_mean, fc_mat = calculate_fc_mean(time_series)
57
+ fc_means[label] = fc_mean
58
+ voxel_counts[label] = len(voxel_indices)
59
+
60
+ dissimilarity = 1 - fc_mat
61
+ w_i = np.nanmean(dissimilarity, axis=1)
62
+ adj_voxel_indices = adj_dict[label]
63
+ if adj_voxel_indices.shape[0] == 0:
64
+ silhouette_scores[label] = np.nan
65
+ continue
66
+ adj_time_series = input_matrix[adj_voxel_indices[:, 0], adj_voxel_indices[:, 1], adj_voxel_indices[:, 2], :]
67
+
68
+ time_series_gpu = cp.asarray(time_series)
69
+ adj_time_series_gpu = cp.asarray(adj_time_series)
70
+ time_series_std = (time_series_gpu - cp.mean(time_series_gpu, axis=1, keepdims=True)) / cp.std(time_series_gpu, axis=1, keepdims=True)
71
+ adj_time_series_std = (adj_time_series_gpu - cp.mean(adj_time_series_gpu, axis=1, keepdims=True)) / cp.std(adj_time_series_gpu, axis=1, keepdims=True)
72
+ cross_fc_gpu = cp.dot(time_series_std.astype(cp.float32), adj_time_series_std.T.astype(cp.float32)) / time_series_gpu.shape[1]
73
+ cross_fc = cross_fc_gpu.get()
74
+ cp.get_default_memory_pool().free_all_blocks()
75
+ cross_dissimilarity = 1 - cross_fc
76
+ b_i = np.nanmean(cross_dissimilarity, axis=1)
77
+ silhouette = np.zeros(n_voxels)
78
+ valid_mask = (w_i != 0) | (b_i != 0)
79
+ silhouette[valid_mask] = (b_i[valid_mask] - w_i[valid_mask]) / np.maximum(w_i[valid_mask], b_i[valid_mask])
80
+ silhouette_scores[label] = np.nanmean(silhouette)
81
+
82
+ weighted_sum_fc = 0.0
83
+ valid_voxels = 0
84
+ for label in fc_means:
85
+ if not np.isnan(fc_means[label]):
86
+ weighted_sum_fc += fc_means[label] * voxel_counts[label]
87
+ valid_voxels += voxel_counts[label]
88
+ weighted_mean_fc = weighted_sum_fc / valid_voxels if valid_voxels > 0 else np.nan
89
+
90
+ weighted_sum_silhouette = 0.0
91
+ valid_voxels = 0
92
+ for label in silhouette_scores:
93
+ if not np.isnan(silhouette_scores[label]):
94
+ weighted_sum_silhouette += silhouette_scores[label] * voxel_counts[label]
95
+ valid_voxels += voxel_counts[label]
96
+ silhouette_avg = weighted_sum_silhouette / valid_voxels if valid_voxels > 0 else np.nan
97
+
98
+ print(f'Homogeneity: {weighted_mean_fc:.3f}\n')
99
+ print(f'Silhouette Score: {silhouette_avg: .3f}\n')
100
+
101
+ return weighted_mean_fc, silhouette_avg
102
+
103
+ def calculate_fc_mean(time_series):
104
+ if time_series.shape[0] < 2:
105
+ return np.nan, np.nan
106
+
107
+ time_series_gpu = cp.asarray(time_series)
108
+ fc_matrix = cp.corrcoef(time_series_gpu)
109
+ fc_matrix = fc_matrix.get()
110
+
111
+ if fc_matrix.ndim != 2 or fc_matrix.shape[0] != fc_matrix.shape[1]:
112
+ return np.nan, np.nan
113
+
114
+ lower_triangle_indices = np.tril_indices(fc_matrix.shape[0], -1)
115
+ lower_triangle_values = fc_matrix[lower_triangle_indices]
116
+
117
+ positive_fc_values = lower_triangle_values[lower_triangle_values > 0]
118
+ mean_fc = np.mean(positive_fc_values) if positive_fc_values.size > 0 else 0
119
+ # mean_fc = np.nanmean(lower_triangle_values)
120
+ return mean_fc, fc_matrix
121
+
122
+
123
+
124
+ if __name__ == "__main__":
125
+ # fmri data
126
+ data_file_path = r'/path/to/your/data'
127
+ # your atlas
128
+ label_file_path = r'/path/to/your/atlas'
129
+ adjacency = calculate_label_adjacency_bg(label_file_path)
130
+ adj_dict = get_adjacent_voxels(label_file_path, adjacency)
131
+ homogeneity, silhouette = evaluate(data_file_path, label_file_path, adj_dict)
AtlaScore/similarity/eva_DCBC.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import scipy
2
+ from scipy.sparse import csr_matrix
3
+ import torch as pt
4
+ import cupy as cp
5
+ import numpy as np
6
+ import os
7
+ import pickle
8
+ from pathlib import Path
9
+ import nibabel as nib
10
+
11
+
12
+ def compute_var_cov_pt(data, cond='all', mean_centering=True):
13
+ """ Compute the variance and covariance for a given data matrix.
14
+ (PyTorch GPU version)
15
+
16
+ Args:
17
+ data: subject's connectivity profile, shape [N * k]
18
+ N - the size of vertices (voxel)
19
+ k - the size of activation conditions
20
+ cond: specify the subset of activation conditions to evaluation
21
+ (e.g condition column [1,2,3,4]), if not given, default to
22
+ use all conditions
23
+ mean_centering: boolean value to determine whether the given subject
24
+ data should be mean centered
25
+
26
+ Returns: cov - the covariance matrix of current subject data, shape [N * N]
27
+ var - the variance matrix of current subject data, shape [N * N]
28
+ """
29
+ if mean_centering:
30
+ data = data - pt.mean(data, dim=1, keepdim=True) # mean centering
31
+ # specify the condition index used to compute correlation, otherwise use all conditions
32
+ if cond != 'all':
33
+ data = data[:, cond]
34
+ elif cond == 'all':
35
+ data = data
36
+ else:
37
+ raise TypeError("Invalid condition type input! cond must be either 'all'"
38
+ " or the column indices of expected task conditions")
39
+ k = data.shape[1]
40
+ cov = pt.matmul(data, data.T) / (k - 1)
41
+ # sd = data.std(dim=1).reshape(-1, 1) # standard deviation
42
+ sd = pt.sqrt(pt.sum(data ** 2, dim=1, keepdim=True) / (k - 1))
43
+ var = pt.matmul(sd, sd.T)
44
+ return cov, var
45
+
46
+ def compute_var_cov_np(data, cond='all', mean_centering=True):
47
+ """ Compute the variance and covariance for a given data matrix.
48
+ (Numpy CPU version)
49
+
50
+ Args:
51
+ data: subject's connectivity profile, shape [N * k]
52
+ N - the size of vertices (voxel)
53
+ k - the size of activation conditions
54
+ cond: specify the subset of activation conditions to evaluation
55
+ (e.g condition column [1,2,3,4]), if not given, default to
56
+ use all conditions
57
+ mean_centering: boolean value to determine whether the given subject
58
+ data should be mean centered
59
+
60
+ Returns: cov - the covariance matrix of current subject data, shape [N * N]
61
+ var - the variance matrix of current subject data, shape [N * N]
62
+ """
63
+ if mean_centering:
64
+ mean = data.mean(axis=1)
65
+ data = data - mean[:, np.newaxis] # mean centering
66
+ else:
67
+ data = data
68
+
69
+ # specify the condition index used to compute correlation,
70
+ # otherwise use all conditions
71
+ if cond != 'all':
72
+ data = data[:, cond]
73
+ elif cond == 'all':
74
+ data = data
75
+ else:
76
+ raise TypeError("Invalid condition type input! cond must be either 'all'"
77
+ " or the column indices of expected task conditions")
78
+
79
+ k = data.shape[1]
80
+ sd = np.sqrt(np.sum(np.square(data), axis=1) / (k-1)) # standard deviation
81
+ sd = np.reshape(sd, (sd.shape[0], 1))
82
+ var = np.matmul(sd, sd.transpose())
83
+ cov = np.matmul(data, data.transpose()) / (k-1)
84
+ return cov, var
85
+
86
+ def compute_var_cov_cp(data, cond='all', mean_centering=True):
87
+ """ Compute the variance and covariance for a given data matrix.
88
+ (Numpy CPU version)
89
+
90
+ Args:
91
+ data: subject's connectivity profile, shape [N * k]
92
+ N - the size of vertices (voxel)
93
+ k - the size of activation conditions
94
+ cond: specify the subset of activation conditions to evaluation
95
+ (e.g condition column [1,2,3,4]), if not given, default to
96
+ use all conditions
97
+ mean_centering: boolean value to determine whether the given subject
98
+ data should be mean centered
99
+
100
+ Returns: cov - the covariance matrix of current subject data, shape [N * N]
101
+ var - the variance matrix of current subject data, shape [N * N]
102
+ """
103
+ if mean_centering:
104
+ mean = data.mean(axis=1)
105
+ data = data - mean[:, cp.newaxis] # mean centering
106
+ else:
107
+ data = data
108
+
109
+ # specify the condition index used to compute correlation,
110
+ # otherwise use all conditions
111
+ if cond != 'all':
112
+ data = data[:, cond]
113
+ elif cond == 'all':
114
+ data = data
115
+ else:
116
+ raise TypeError("Invalid condition type input! cond must be either 'all'"
117
+ " or the column indices of expected task conditions")
118
+ data = cp.asarray(data)
119
+ k = data.shape[1]
120
+ sd = cp.sqrt(cp.sum(cp.square(data), axis=1) / (k-1)) # standard deviation
121
+ sd = cp.reshape(sd, (sd.shape[0], 1))
122
+ var = cp.matmul(sd, sd.transpose())
123
+ cov = cp.matmul(data, data.transpose()) / (k-1)
124
+ return cov, var
125
+
126
+ def delete_rows_csr(mat, indices):
127
+ """
128
+ Remove the rows denoted by ``indices`` form the CSR sparse matrix ``mat``.
129
+ """
130
+ if not isinstance(mat, scipy.sparse.csr_matrix):
131
+ raise ValueError("works only for CSR format -- use .tocsr() first")
132
+ indices = list(indices)
133
+ mask = np.ones(mat.shape[0], dtype=bool)
134
+ mask[indices] = False
135
+ return mat[mask]
136
+
137
+
138
+ def delete_cols_csr(mat, indices):
139
+ """
140
+ Remove the cols denoted by ``indices`` form the CSR sparse matrix ``mat``.
141
+ """
142
+ if not isinstance(mat, scipy.sparse.csr_matrix):
143
+ raise ValueError("works only for CSR format -- use .tocsr() first")
144
+ indices = list(indices)
145
+ mask = np.ones(mat.shape[1], dtype=bool)
146
+ mask[indices] = False
147
+ return mat[:, mask]
148
+
149
+
150
+ def ecbc(data, dist, parcellation):
151
+ """
152
+ The public function that handle the main DCBC evaluation routine
153
+
154
+ :param parcellation: The cortical parcellation to evaluate
155
+ :return: dict T that contain all needed DCBC evaluation results
156
+ """
157
+ maxDist = 35
158
+ binWidth = 1
159
+ weighting = True
160
+ numBins = int(np.floor(maxDist / binWidth))
161
+ h = 'L'
162
+
163
+ D = dict()
164
+
165
+ dist = csr_matrix(dist)
166
+ dist = dist.tocsr()
167
+
168
+ print(f'Evaluating {h} hemisphere for subject')
169
+
170
+ # remove nan value and medial wall from subject data
171
+ nanIdx = np.union1d(np.unique(np.where(np.isnan(data))[0]), np.where(parcellation == 0)[0])
172
+ data = np.delete(data, nanIdx, axis=0)
173
+ cov, var = compute_var_cov_cp(data) # This line can be changed to use compute_corr()
174
+
175
+ # remove the nan value and medial wall from dist file
176
+ this_dist = delete_rows_csr(dist, nanIdx)
177
+ this_dist = delete_cols_csr(this_dist, nanIdx)
178
+ row, col, distance = scipy.sparse.find(this_dist)
179
+
180
+ parcellation = cp.asarray(parcellation)
181
+ row = cp.asarray(row)
182
+ col = cp.asarray(col)
183
+ distance = cp.asarray(distance)
184
+
185
+ # making parcellation matrix without medial wall and nan value
186
+ par = cp.delete(parcellation, nanIdx, axis=0)
187
+ num_within, num_between, corr_within, corr_between = [], [], [], []
188
+ for i in range(numBins):
189
+ inBin = cp.where((distance > i * binWidth) & (distance <= (i + 1) * binWidth))[0]
190
+
191
+ # lookup the row/col index of within and between vertices
192
+ within = cp.where((par[row[inBin]] == par[col[inBin]]) == True)[0]
193
+ between = cp.where((par[row[inBin]] == par[col[inBin]]) == False)[0]
194
+
195
+ # retrieve and append the number of vertices for within/between in current bin
196
+ num_within = cp.append(num_within, within.shape[0])
197
+ num_between = cp.append(num_between, between.shape[0])
198
+
199
+ # Compute and append averaged within- and between-parcel correlations in current bin
200
+ this_corr_within = cp.nanmean(cov[row[inBin[within]], col[inBin[within]]]) / cp.nanmean(var[row[inBin[within]], col[inBin[within]]])
201
+ this_corr_between = cp.nanmean(cov[row[inBin[between]], col[inBin[between]]]) / cp.nanmean(var[row[inBin[between]], col[inBin[between]]])
202
+ corr_within = cp.append(corr_within, this_corr_within)
203
+ corr_between = cp.append(corr_between, this_corr_between)
204
+
205
+ del inBin
206
+
207
+ if weighting:
208
+ weight = 1/(1/num_within + 1/num_between)
209
+ weight = weight / cp.sum(weight)
210
+ DCBC = cp.nansum(cp.multiply((corr_within - corr_between), weight))
211
+ else:
212
+ DCBC = cp.nansum(corr_within - corr_between)
213
+ weight = cp.nan
214
+
215
+ D = {
216
+ "binWidth": binWidth,
217
+ "maxDist": maxDist,
218
+ "hemisphere": h,
219
+ "num_within": num_within,
220
+ "num_between": num_between,
221
+ "corr_within": corr_within,
222
+ "corr_between": corr_between,
223
+ "weight": weight,
224
+ "DCBC": DCBC
225
+ }
226
+
227
+ return D
228
+
229
+
230
+
231
+ if __name__ == "__main__":
232
+ hemisphere = 'L'
233
+ geodesic = np.load('/path/to/your/dist/file') # npz file
234
+ dist = geodesic['arr_0']
235
+ print(f'Geodesic distance shape: {dist.shape}')
236
+
237
+ parcellation = nib.load('/path/to/your/atlas/on/surface').darrays[0].data
238
+ print(f'Parcellation shape: {parcellation.shape}')
239
+
240
+ data = nib.load('/path/to/your/fmri/on/surface')
241
+ surf = [x.data for x in data.darrays]
242
+ surf = np.array(surf).T
243
+ print(f'FMRI data shape: {surf.shape}')
244
+
245
+ dcbc = ecbc(surf, dist, parcellation)
246
+ print(dcbc['DCBC'])
DCA/abalation_fmri.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import glob
3
+ import numpy as np
4
+ import nibabel as nib
5
+ import torch
6
+ import torch.nn.functional as F
7
+ from sklearn.cluster import KMeans
8
+ from scipy.optimize import linear_sum_assignment
9
+ from scipy.sparse import csr_matrix, diags, eye
10
+ from scipy.sparse.linalg import eigsh
11
+ from utils import process_nifti_file,large_constrcut,build_spatial_graph_and_weights,sparse_spectral_clustering
12
+
13
+ # ------------------------ Main ------------------------
14
+ if __name__=='__main__':
15
+ data_dir = r'./data/fmri'
16
+ mask_dir = r'./data/mask'
17
+ # out_graph_dir = [todo: your out path]
18
+ # out_km_dir = [todo: your out path]
19
+ os.makedirs(out_graph_dir, exist_ok=True)
20
+ os.makedirs(out_km_dir, exist_ok=True)
21
+
22
+ with open(r'./data/sub_test.txt','r') as f:
23
+ subs = [s.strip() for s in f if s.strip()]
24
+
25
+ for subj in subs:
26
+ print('Subject', subj)
27
+ mask = nib.load(f'{mask_dir}/{subj}.nii.gz').get_fdata().astype(int)
28
+ dis_mask = (mask==1)|(mask==11)
29
+ dis_mask = large_constrcut(dis_mask)
30
+ vol = nib.load(f'{data_dir}/{subj}_FWHM3.nii.gz').get_fdata().astype(np.float32)
31
+ vol = np.transpose(vol,(3,0,1,2)) # (T,X,Y,Z)
32
+ T,D,H,W = vol.shape[0], *vol.shape[1:]
33
+ ts = vol.reshape(T, -1).T # (N, T)
34
+ valid_idx = np.where(dis_mask.flatten())[0]
35
+ feats = ts[valid_idx]
36
+
37
+ import itertools
38
+ mask = torch.tensor(dis_mask)
39
+ valid_idx = torch.nonzero(mask == 1)
40
+ index_map = -torch.ones(D, H, W, dtype=torch.long)
41
+ index_map[mask == 1] = torch.arange(valid_idx.shape[0])
42
+
43
+ offsets = torch.tensor(
44
+ [
45
+ [dx, dy, dz]
46
+ for dx, dy, dz in itertools.product((-1, 0, 1), repeat=3)
47
+ if not (dx == dy == dz == 0)
48
+ ],
49
+ dtype=torch.int8,
50
+ )
51
+
52
+ edge_list = []
53
+ for i, coord in enumerate(valid_idx):
54
+ for offset in offsets:
55
+ neighbor = coord + offset
56
+ x, y, z = neighbor.tolist()
57
+ if 0 <= x < D and 0 <= y < H and 0 <= z < W:
58
+ j = index_map[x, y, z].item()
59
+ if j >= 0:
60
+ edge_list.append([i, j])
61
+
62
+ ei = torch.tensor(edge_list).t().contiguous() # [2, E]
63
+
64
+ ew = build_spatial_graph_and_weights(ei, torch.tensor(feats))
65
+
66
+ valid = np.nonzero(dis_mask.flatten())[0]
67
+
68
+ labels_graph = sparse_spectral_clustering(torch.tensor(ei), torch.tensor(ew), len(valid), k=100)
69
+ out_vol = np.zeros(D*H*W, dtype=int)
70
+ out_vol[valid] = labels_graph+1
71
+ out3 = out_vol.reshape(D,H,W)
72
+ np.save(f'{out_graph_dir}/{subj}_graph.npy', out3)
73
+
74
+ # Direct KMeans clustering
75
+ km = KMeans(n_clusters=100, n_init=10)
76
+ labels_km = km.fit_predict(feats)
77
+ out_vol_km = np.zeros(D*H*W, dtype=int)
78
+ out_vol_km[valid] = labels_km+1
79
+ out3_km = out_vol_km.reshape(D,H,W)
80
+ np.save(f'{out_km_dir}/{subj}_kmeans.npy', out3_km)
81
+
DCA/data/data_preparation.ipynb ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "id": "e38996d5",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "import numpy as np\n",
11
+ "import nibabel as nib\n",
12
+ "from nibabel.processing import resample_from_to"
13
+ ]
14
+ },
15
+ {
16
+ "cell_type": "code",
17
+ "execution_count": 2,
18
+ "id": "ac2a1dd8",
19
+ "metadata": {},
20
+ "outputs": [],
21
+ "source": [
22
+ "affine_target = np.array([\n",
23
+ " [-2, 0, 0, 96], \n",
24
+ " [ 0, 2, 0, -112],\n",
25
+ " [ 0, 0, 2, -90],\n",
26
+ " [ 0, 0, 0, 1]\n",
27
+ "])"
28
+ ]
29
+ },
30
+ {
31
+ "cell_type": "markdown",
32
+ "id": "eee0a15e",
33
+ "metadata": {},
34
+ "source": [
35
+ "##### prepare fmri data"
36
+ ]
37
+ },
38
+ {
39
+ "cell_type": "code",
40
+ "execution_count": null,
41
+ "id": "e1da73fd",
42
+ "metadata": {},
43
+ "outputs": [],
44
+ "source": [
45
+ "fmri_img = nib.load('./MNI152_fmri_data.nii.gz') # TBD\n",
46
+ "\n",
47
+ "fmri_data = fmri_img.get_fdata(); affine = fmri_img.affine; header = fmri_img.header.copy()\n",
48
+ "fmri_cropped = fmri_data[..., :300]; header.set_data_shape(fmri_cropped.shape); cropped_img = nib.Nifti1Image(fmri_cropped, affine, header)\n",
49
+ "resampled_fmri = resample_from_to(cropped_img, ((96, 96, 96, 300), affine_target), order = 3) # if fmri data has 2mm isotropic spatial resolution, use order = 0 for quicker resampling\n",
50
+ "\n",
51
+ "nib.save(resampled_fmri, './prepared_rfmri_data.nii.gz') # TBD"
52
+ ]
53
+ },
54
+ {
55
+ "cell_type": "markdown",
56
+ "id": "c54ff8b2",
57
+ "metadata": {},
58
+ "source": [
59
+ "##### prepare tissue mask"
60
+ ]
61
+ },
62
+ {
63
+ "cell_type": "code",
64
+ "execution_count": null,
65
+ "id": "795e404d",
66
+ "metadata": {},
67
+ "outputs": [],
68
+ "source": [
69
+ "aseg_img = nib.load('./MNI152_aparc+aseg.nii.gz') # TBD\n",
70
+ "aseg_data = aseg_img.get_fdata()\n",
71
+ "\n",
72
+ "res = np.zeros_like(aseg_data)\n",
73
+ "res += 1 * ((aseg_data >= 1000) & (aseg_data <= 1035)).astype(int); res += 11 * ((aseg_data >= 2000) & (aseg_data <= 2035)).astype(int)\n",
74
+ "res += 2 * (aseg_data == 2).astype(int); res += 12 * (aseg_data == 41).astype(int)\n",
75
+ "for i in [10, 11, 12, 13, 17, 18, 26, 27, 28, 75, 96]: res += 3 * (aseg_data == i).astype(int)\n",
76
+ "for i in [49, 50, 51, 52, 53, 54, 58, 59, 60, 76, 97]: res += 13 * (aseg_data == i).astype(int)\n",
77
+ "res += 20 * ((aseg_data >= 251) & (aseg_data <= 255)).astype(int)\n",
78
+ "\n",
79
+ "new_img = nib.Nifti1Image(res, affine = aseg_img.affine)\n",
80
+ "resampled_img = resample_from_to(new_img, ((96, 96, 96), affine_target), order = 0)\n",
81
+ "\n",
82
+ "nib.save(resampled_img, './prepared_tissue_mask.nii.gz') # TBD"
83
+ ]
84
+ }
85
+ ],
86
+ "metadata": {
87
+ "kernelspec": {
88
+ "display_name": "connectome",
89
+ "language": "python",
90
+ "name": "python3"
91
+ },
92
+ "language_info": {
93
+ "codemirror_mode": {
94
+ "name": "ipython",
95
+ "version": 3
96
+ },
97
+ "file_extension": ".py",
98
+ "mimetype": "text/x-python",
99
+ "name": "python",
100
+ "nbconvert_exporter": "python",
101
+ "pygments_lexer": "ipython3",
102
+ "version": "3.12.2"
103
+ }
104
+ },
105
+ "nbformat": 4,
106
+ "nbformat_minor": 5
107
+ }
DCA/data/fmri/101915_FWHM3.nii.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c1412cf0d0c3e618de05a5ca9134fd7598ba0efab0ccd922c69dbd22ff0eb467
3
+ size 246573686
DCA/data/fmri/101915_FWHM6.nii.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ab71fa6a8f329425daaa8f14a8fba7296a6eb2136944886dcb733c275aa54463
3
+ size 245852861
DCA/data/fmri/101915_raw.nii.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:07836b9803a8dbede7e0fe226b1301d486c8a15a92fa5cb9b6c8951156f82c3d
3
+ size 254082341
DCA/data/mask/101915_tissue_mask.nii.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cf712ff0ab0838aff49771feee9fc90854246b0bb7216d9edd36a4fdbb0868ab
3
+ size 151082
DCA/data/sub_test.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ 101915
DCA/main.py ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import print_function, division
2
+ import argparse
3
+ import os
4
+ os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"
5
+ os.environ["OPENBLAS_NUM_THREADS"] = "16"
6
+ os.environ["OMP_NUM_THREADS"] = "16"
7
+ os.environ["GOTO_NUM_THREADS"] = "16"
8
+
9
+ os.environ["NUMEXPR_NUM_THREADS"] = "16"
10
+ os.environ['CUDA_VISIBLE_DEVICES'] = "5"
11
+
12
+ import numpy as np
13
+ import torch
14
+ import torch.nn.functional as F
15
+ import torch.optim as optim
16
+ import itertools
17
+
18
+ import argparse
19
+ from utils import large_constrcut,build_spatial_graph_and_weights,sparse_spectral_clustering,match_labels,validate
20
+ from model import DCA,MySwinUNETR
21
+ import time
22
+ import nibabel as nib
23
+ import torch.nn as nn
24
+ import warnings
25
+ import argparse
26
+ from torch.nn.parameter import Parameter
27
+
28
+ warnings.filterwarnings("ignore")
29
+
30
+
31
+ def train_DCA(swin,origin,background_mask,evaluation_data,data_dir):
32
+
33
+ model = DCA(
34
+ swin,
35
+ n_z=args.n_z,
36
+ n_clusters=args.n_clusters,
37
+ background_mask=background_mask,
38
+ ).to(device)
39
+ start = time.time()
40
+
41
+ for name, param in model.swinunetr.named_parameters():
42
+ if 'c3d' in name or 'out' in name:
43
+ param.requires_grad = True
44
+ else:
45
+ param.requires_grad = False
46
+
47
+ optimizer = optim.Adam([
48
+ {'params': [
49
+ p for n, p in model.swinunetr.named_parameters()
50
+ if p.requires_grad
51
+ ],
52
+ 'lr': args.lr},
53
+ ])
54
+
55
+ data = torch.from_numpy(origin).float()
56
+ data = data.unsqueeze(0).to(device)
57
+ data.requires_grad_(True)
58
+
59
+ D, H, W = background_mask.shape
60
+ mask = torch.tensor(background_mask).to(device)
61
+ valid_idx = torch.nonzero(mask == 0)
62
+ index_map = -torch.ones(D, H, W, dtype=torch.long)
63
+ index_map[mask == 0] = torch.arange(valid_idx.shape[0])
64
+ # 6-neighbour
65
+ # offsets = torch.tensor([
66
+ # [0, 0, 1], [0, 0, -1],
67
+ # [0, 1, 0], [0, -1, 0],
68
+ # [1, 0, 0], [-1, 0, 0],
69
+ # ]).to(device)
70
+
71
+ # 26-neighbour
72
+ offsets = torch.tensor(
73
+ [
74
+ [dx, dy, dz]
75
+ for dx, dy, dz in itertools.product((-1, 0, 1), repeat=3)
76
+ if not (dx == dy == dz == 0) # exclude the centre voxel
77
+ ],
78
+ dtype=torch.int8,
79
+ ).to(device)
80
+
81
+ edge_list = []
82
+ for i, coord in enumerate(valid_idx):
83
+ for offset in offsets:
84
+ neighbor = coord + offset
85
+ x, y, z = neighbor.tolist()
86
+ if 0 <= x < D and 0 <= y < H and 0 <= z < W:
87
+ j = index_map[x, y, z].item()
88
+ if j >= 0:
89
+ edge_list.append([i, j])
90
+
91
+ edge_index = torch.tensor(edge_list).t().contiguous().to(device) # [2, E]
92
+
93
+
94
+ model.train()
95
+ print('start tunning')
96
+ best_h = 0
97
+ best_s = 0
98
+ for epoch in range(args.epoch):
99
+ optimizer.zero_grad()
100
+ x_bar, tmp_s, z,hidden = model(data,epoch)
101
+
102
+ ## valid flatten
103
+ mask_flat = background_mask.flatten()
104
+ valid_mask = mask_flat == 0
105
+ valid_mask = torch.tensor(valid_mask).to(device)
106
+
107
+ hidden_permuted = hidden.permute(0, 2, 3, 4, 1)
108
+ if not hidden_permuted.is_contiguous():
109
+ hidden_permuted = hidden_permuted.contiguous()
110
+ hidden_flat = hidden_permuted.view(-1, hidden.shape[1])
111
+ recon_permuted = x_bar.permute(0, 2, 3, 4, 1)
112
+ if not recon_permuted.is_contiguous():
113
+ recon_permuted = recon_permuted.contiguous()
114
+ recon_flat = recon_permuted.view(-1, x_bar.shape[1])
115
+
116
+ valid_indices = torch.nonzero(valid_mask, as_tuple=True)[0]
117
+ valid_voxels = torch.index_select(hidden_flat, dim=0, index=valid_indices)
118
+ valid_recon = torch.index_select(recon_flat, dim=0, index=valid_indices)
119
+
120
+ edge_weight = build_spatial_graph_and_weights(
121
+ edge_index, # [96, 96, 96]
122
+ valid_voxels
123
+ )
124
+
125
+ labels = sparse_spectral_clustering(edge_index.detach().cpu(), edge_weight.detach().cpu(), (torch.max(edge_index)+1).item(), args.n_clusters)
126
+
127
+ if epoch > 0:
128
+ labels = match_labels(prev_labels, labels, args.n_clusters)
129
+ prev_labels = labels.copy()
130
+
131
+ kl_loss = model.total_loss(data, x_bar, tmp_s, target=torch.tensor(labels).long().to(device))
132
+
133
+ loss = kl_loss
134
+ print('epoch:',epoch)
135
+ # print('reconstr_loss',recon)
136
+ print('kl_loss',kl_loss)
137
+
138
+ loss.backward()
139
+ optimizer.step()
140
+ label_3d = np.full(background_mask.shape, -1) # Initialize with -1 to mark background areas
141
+ # y_pred = target_distribution(tmp_s).argmax(1).cpu()
142
+ label_3d[background_mask == 0] = labels
143
+ if args.vali :
144
+ homogeneity = validate(data_dir, label_3d+1) #input numpy
145
+ if best_h < homogeneity:
146
+ best_h = homogeneity
147
+ bset_s = label_3d
148
+ label_3d = bset_s
149
+
150
+ # edge_weight = build_spatial_graph_and_weights(
151
+ # edge_index,
152
+ # valid_voxels
153
+ # )
154
+ # labels = weighted_bfs_connected_clustering(edge_index.detach(), edge_weight.detach(), (torch.max(edge_index)+1).item(), args.n_clusters)
155
+
156
+ end = time.time()
157
+ print('Running time: ', end-start)
158
+ return label_3d
159
+
160
+
161
+ if __name__ == "__main__":
162
+
163
+ parser = argparse.ArgumentParser(
164
+ description='DCA training',
165
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
166
+
167
+ parser.add_argument('--lr', type=float, default=0.005)
168
+ parser.add_argument('--n_clusters','-k', default=100, type=int) #38
169
+ parser.add_argument('--n_z', default=256, type=int)
170
+ parser.add_argument('--epoch','-e', default=8, type=int)
171
+ parser.add_argument('--dis_mask',default=None)
172
+ parser.add_argument('--vali','-v',default=True) # For small Memory, choose False and set smaller epoch about 8 to avoid overfit.
173
+
174
+
175
+ args = parser.parse_args()
176
+ print(args)
177
+ args.cuda = torch.cuda.is_available()
178
+ print("use cuda: {}".format(args.cuda))
179
+ print("gpu counts:", torch.cuda.device_count())
180
+ torch.cuda.empty_cache()
181
+ device = torch.device("cuda" if args.cuda else "cpu")
182
+
183
+ subj_list_file = r'data/sub_test.txt'
184
+
185
+ with open(subj_list_file, 'r') as f:
186
+ subj_ids = f.read().splitlines()
187
+
188
+ # import random
189
+ # subj_ids_copy = subj_ids[:] #shuffle
190
+ # random.shuffle(subj_ids_copy)
191
+
192
+ # Loop over each subject ID in the list
193
+ for idx, subj_id in enumerate(subj_ids):
194
+ k_cluster = args.n_clusters
195
+ args.n_clusters = k_cluster
196
+ print(f"/n[ {idx+1}/{len(subj_ids)} ] Processing subject {subj_id} …")
197
+
198
+ result_file = fr'results/demo/hcp_{subj_id}_{k_cluster}.npy'
199
+ if os.path.isfile(result_file):
200
+ print(f" -> {result_file} already exists, skip.")
201
+ continue
202
+
203
+ data_dir = fr'data/fmri/{subj_id}_FWHM3.nii.gz'
204
+ dis_mask_dir = fr'data/mask/101915_tissue_mask.nii.gz'
205
+
206
+ dis_mask = nib.load(dis_mask_dir).get_fdata()
207
+ dis_mask = (dis_mask==1) | (dis_mask==11)
208
+ # 1: left grey matter
209
+ # 2: left white matter
210
+ # 3: left subcortex
211
+ # 11: right grey matter
212
+ # 12: right white matter
213
+ # 13: right subcortex
214
+ # 20: corpus callosum
215
+ dis_mask = large_constrcut(dis_mask) #processing isolate points
216
+
217
+ original_volume = nib.load(data_dir).get_fdata().astype('float32')
218
+ original_volume = np.transpose(original_volume, (3, 0, 1, 2))
219
+ evaluation_data = original_volume
220
+
221
+ background_mask = (dis_mask == 0)
222
+ background_mask = np.broadcast_to(background_mask, original_volume.shape)
223
+ nb_vals = original_volume[~background_mask]
224
+ if nb_vals.min() != nb_vals.max():
225
+ mean, std = nb_vals.mean(), nb_vals.std()
226
+ original_volume[~background_mask] = (nb_vals - mean) / std
227
+ original_volume[background_mask] = 0
228
+ normalized_original = original_volume
229
+
230
+ checkpoint_path = 'data/swin_model_epoch_30.pth'
231
+ model = MySwinUNETR(img_size=(96,96,96), in_channels=300,
232
+ out_channels=300, feature_size=48,
233
+ emb_size=256, use_checkpoint=False).to(device)
234
+ if os.path.isfile(checkpoint_path):
235
+ ckpt = torch.load(checkpoint_path, map_location=device)
236
+ model.load_state_dict(ckpt['model_state_dict'])
237
+ print(f" -> checkpoint loaded ({checkpoint_path})")
238
+
239
+ label_3d = train_DCA(model,normalized_original,background_mask[0],evaluation_data,data_dir)
240
+
241
+
242
+ np.save(result_file, label_3d+1)
243
+ print(f" -> saved {result_file}")
DCA/model.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+
3
+ import torch.nn as nn
4
+ from torch.nn.parameter import Parameter
5
+ import torch.nn.functional as F
6
+ import torch.optim as optim
7
+ # pip install monai
8
+ from monai.networks.nets import SwinUNETR
9
+ import importlib.util
10
+ spec = importlib.util.spec_from_file_location('SwinUNETR', 'swin_unetr.py')
11
+ my_module = importlib.util.module_from_spec(spec)
12
+ spec.loader.exec_module(my_module)
13
+ SwinUNETR = my_module.SwinUNETR
14
+
15
+ class MySwinUNETR(SwinUNETR):
16
+ def forward(self, x_in):
17
+ hidden_states_out = self.swinViT(x_in, self.normalize)
18
+ enc0 = self.encoder1(x_in)
19
+ enc1 = self.encoder2(hidden_states_out[0])
20
+ enc2 = self.encoder3(hidden_states_out[1])
21
+ enc3 = self.encoder4(hidden_states_out[2])
22
+ dec4 = self.encoder10(hidden_states_out[4])
23
+ dec3 = self.decoder5(dec4, hidden_states_out[3])
24
+ dec2 = self.decoder4(dec3, enc3)
25
+ dec1 = self.decoder3(dec2, enc2)
26
+ dec0 = self.decoder2(dec1, enc1)
27
+ out = self.decoder1(dec0, enc0)
28
+ out = self.c3d(out)
29
+ logits = self.out(out)
30
+ return logits, out
31
+
32
+ class DCA(nn.Module):
33
+ def __init__(self,
34
+ model,
35
+ n_z,
36
+ n_clusters,
37
+ background_mask,
38
+ ):
39
+ super(DCA, self).__init__()
40
+ # self.pretrain_path = pretrain_path
41
+ self.n_clusters = n_clusters
42
+
43
+ self.swinunetr = model
44
+ self.background_mask = background_mask
45
+ self.D = Parameter(torch.Tensor(n_clusters, n_z),requires_grad=True)
46
+ nn.init.xavier_uniform_(self.D)
47
+
48
+
49
+ def forward(self, x, epoch):
50
+ x_bar, hidden = self.swinunetr(x)
51
+ z = hidden
52
+ B, C, D, H, W = z.shape
53
+ z_perm = z.permute(0,2,3,4,1).reshape(-1, C) # (B*D*H*W, C)
54
+ mask_flat = torch.from_numpy(self.background_mask).flatten().to(z.device) # (D*H*W,)
55
+ z_features = z_perm[~mask_flat.repeat(B)]
56
+ feature_distances = torch.cdist(z_features, self.D)
57
+ s = - feature_distances
58
+ return x_bar, s, z_features,z
59
+
60
+ def orthogonality_loss(self,D):
61
+
62
+ K = D.size(0)
63
+ G = D @ D.t() # shape [K, K]
64
+ G_off = G - torch.eye(K, device=D.device, dtype=D.dtype)
65
+ loss = (G_off.sum() / (K * (K - 1))).sqrt()
66
+ return loss
67
+
68
+ def masked_mse_loss(self, pred, target, mask):
69
+ mask = torch.from_numpy(mask)
70
+ if mask.dim() != pred.dim(): # (H, W, D)
71
+ mask = mask.unsqueeze(0) # Add batch dimension to mask (1, C, H, W, D)
72
+ mask = mask.expand(pred.size(1), -1, -1, -1) # Repeat mask for each batch (B, C, H, W, D)
73
+ mask = mask.unsqueeze(0) # Add batch dimension to mask (1, C, H, W, D)
74
+ mask = mask.expand(pred.size(0), -1, -1, -1, -1)
75
+ diff = pred - target
76
+ masked_diff = diff[~mask] # Select only the non-background areas (where mask is False)
77
+ if masked_diff.numel() == 0:
78
+ return torch.tensor(0.0, requires_grad=True, device=pred.device)
79
+ return torch.mean(masked_diff**2)
80
+
81
+ def total_loss(self, x, x_bar, pred, target):
82
+
83
+ loss1 = F.cross_entropy(pred, target) #Since target is hard label, minimizing the KL divergence is equivalent to minimizing the cross‐entropy.
84
+
85
+ # reconstr_loss = self.masked_mse_loss(x_bar, x, self.background_mask)
86
+ # orth_loss = self.orthogonality_loss(self.D)
87
+ return loss1
88
+
DCA/req_trim.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ scikit-learn
2
+ tensorboard
3
+ monai
4
+ matplotlib
5
+ torch_geometric
6
+ nibabel
7
+ pyzstd
8
+ pandas
9
+ einops
10
+ cupy-cuda12x
DCA/requirements.txt ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ absl-py==2.2.2
2
+ aiohappyeyeballs==2.6.1
3
+ aiohttp==3.11.18
4
+ aiosignal==1.3.2
5
+ async-timeout==5.0.1
6
+ attrs==25.3.0
7
+ certifi==2025.4.26
8
+ charset-normalizer==3.4.2
9
+ contourpy==1.3.0
10
+ cycler==0.12.1
11
+ einops==0.8.1
12
+ filelock==3.18.0
13
+ fonttools==4.58.0
14
+ frozenlist==1.6.0
15
+ fsspec==2025.3.2
16
+ grpcio==1.71.0
17
+ idna==3.10
18
+ importlib_metadata==8.7.0
19
+ importlib_resources==6.5.2
20
+ Jinja2==3.1.6
21
+ joblib==1.5.0
22
+ kiwisolver==1.4.7
23
+ Markdown==3.8
24
+ MarkupSafe==3.0.2
25
+ matplotlib==3.9.4
26
+ monai==1.4.0
27
+ mpmath==1.3.0
28
+ multidict==6.4.3
29
+ networkx==3.2.1
30
+ nibabel==5.3.2
31
+ numpy==1.26.4
32
+ nvidia-cublas-cu12==12.6.4.1
33
+ nvidia-cuda-cupti-cu12==12.6.80
34
+ nvidia-cuda-nvrtc-cu12==12.6.77
35
+ nvidia-cuda-runtime-cu12==12.6.77
36
+ nvidia-cudnn-cu12==9.5.1.17
37
+ nvidia-cufft-cu12==11.3.0.4
38
+ nvidia-cufile-cu12==1.11.1.6
39
+ nvidia-curand-cu12==10.3.7.77
40
+ nvidia-cusolver-cu12==11.7.1.2
41
+ nvidia-cusparse-cu12==12.5.4.2
42
+ nvidia-cusparselt-cu12==0.6.3
43
+ nvidia-nccl-cu12==2.26.2
44
+ nvidia-nvjitlink-cu12==12.6.85
45
+ nvidia-nvtx-cu12==12.6.77
46
+ packaging==25.0
47
+ pandas==2.2.3
48
+ pillow==11.2.1
49
+ propcache==0.3.1
50
+ protobuf==6.30.2
51
+ psutil==7.0.0
52
+ pyparsing==3.2.3
53
+ python-dateutil==2.9.0.post0
54
+ pytz==2025.2
55
+ pyzstd==0.17.0
56
+ requests==2.32.3
57
+ scikit-learn==1.6.1
58
+ scipy==1.13.1
59
+ six==1.17.0
60
+ sympy==1.14.0
61
+ tensorboard==2.19.0
62
+ tensorboard-data-server==0.7.2
63
+ threadpoolctl==3.6.0
64
+ torch==2.7.0
65
+ torch-geometric==2.6.1
66
+ torchaudio==2.7.0
67
+ torchvision==0.22.0
68
+ tqdm==4.67.1
69
+ triton==3.3.0
70
+ typing_extensions==4.13.2
71
+ tzdata==2025.2
72
+ urllib3==2.4.0
73
+ Werkzeug==3.1.3
74
+ yarl==1.20.0
75
+ zipp==3.21.0
DCA/results/demo/hcp_101915_100.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:951f1c252353e01b0df1f3f04b469595393cedce07bc693c158ccf067ffeb7c4
3
+ size 7078016
DCA/swin_unetr.py ADDED
@@ -0,0 +1,1060 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) MONAI Consortium
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software
7
+ # distributed under the License is distributed on an "AS IS" BASIS,
8
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ # See the License for the specific language governing permissions and
10
+ # limitations under the License.
11
+
12
+ from __future__ import annotations
13
+
14
+ import itertools
15
+ from collections.abc import Sequence
16
+
17
+ import numpy as np
18
+ import torch
19
+ import torch.nn as nn
20
+ import torch.nn.functional as F
21
+ import torch.utils.checkpoint as checkpoint
22
+ from torch.nn import LayerNorm
23
+
24
+ from monai.networks.blocks import MLPBlock as Mlp
25
+ from monai.networks.blocks import PatchEmbed, UnetOutBlock, UnetrBasicBlock, UnetrUpBlock
26
+ from monai.networks.layers import DropPath, trunc_normal_
27
+ from monai.utils import ensure_tuple_rep, look_up_option, optional_import
28
+
29
+ rearrange, _ = optional_import("einops", name="rearrange")
30
+
31
+ __all__ = [
32
+ "SwinUNETR",
33
+ "window_partition",
34
+ "window_reverse",
35
+ "WindowAttention",
36
+ "SwinTransformerBlock",
37
+ "PatchMerging",
38
+ "PatchMergingV2",
39
+ "MERGING_MODE",
40
+ "BasicLayer",
41
+ "SwinTransformer",
42
+ ]
43
+
44
+
45
+ class SwinUNETR(nn.Module):
46
+ """
47
+ Swin UNETR based on: "Hatamizadeh et al.,
48
+ Swin UNETR: Swin Transformers for Semantic Segmentation of Brain Tumors in MRI Images
49
+ <https://arxiv.org/abs/2201.01266>"
50
+ """
51
+
52
+ def __init__(
53
+ self,
54
+ img_size: Sequence[int] | int,
55
+ in_channels: int,
56
+ out_channels: int,
57
+ depths: Sequence[int] = (2, 2, 2, 2),
58
+ num_heads: Sequence[int] = (3, 6, 12, 24),
59
+ feature_size: int = 24,
60
+ norm_name: tuple | str = "instance",
61
+ drop_rate: float = 0.0,
62
+ attn_drop_rate: float = 0.0,
63
+ dropout_path_rate: float = 0.0,
64
+ normalize: bool = True,
65
+ use_checkpoint: bool = False,
66
+ spatial_dims: int = 3,
67
+ downsample="merging",
68
+ use_v2=False,
69
+ emb_size=256
70
+ ) -> None:
71
+ """
72
+ Args:
73
+ img_size: dimension of input image.
74
+ in_channels: dimension of input channels.
75
+ out_channels: dimension of output channels.
76
+ feature_size: dimension of network feature size.
77
+ depths: number of layers in each stage.
78
+ num_heads: number of attention heads.
79
+ norm_name: feature normalization type and arguments.
80
+ drop_rate: dropout rate.
81
+ attn_drop_rate: attention dropout rate.
82
+ dropout_path_rate: drop path rate.
83
+ normalize: normalize output intermediate features in each stage.
84
+ use_checkpoint: use gradient checkpointing for reduced memory usage.
85
+ spatial_dims: number of spatial dims.
86
+ downsample: module used for downsampling, available options are `"mergingv2"`, `"merging"` and a
87
+ user-specified `nn.Module` following the API defined in :py:class:`monai.networks.nets.PatchMerging`.
88
+ The default is currently `"merging"` (the original version defined in v0.9.0).
89
+ use_v2: using swinunetr_v2, which adds a residual convolution block at the beggining of each swin stage.
90
+
91
+ Examples::
92
+
93
+ # for 3D single channel input with size (96,96,96), 4-channel output and feature size of 48.
94
+ >>> net = SwinUNETR(img_size=(96,96,96), in_channels=1, out_channels=4, feature_size=48)
95
+
96
+ # for 3D 4-channel input with size (128,128,128), 3-channel output and (2,4,2,2) layers in each stage.
97
+ >>> net = SwinUNETR(img_size=(128,128,128), in_channels=4, out_channels=3, depths=(2,4,2,2))
98
+
99
+ # for 2D single channel input with size (96,96), 2-channel output and gradient checkpointing.
100
+ >>> net = SwinUNETR(img_size=(96,96), in_channels=3, out_channels=2, use_checkpoint=True, spatial_dims=2)
101
+
102
+ """
103
+
104
+ super().__init__()
105
+
106
+ img_size = ensure_tuple_rep(img_size, spatial_dims)
107
+ patch_size = ensure_tuple_rep(2, spatial_dims)
108
+ window_size = ensure_tuple_rep(7, spatial_dims)
109
+
110
+ if spatial_dims not in (2, 3):
111
+ raise ValueError("spatial dimension should be 2 or 3.")
112
+
113
+ for m, p in zip(img_size, patch_size):
114
+ for i in range(5):
115
+ if m % np.power(p, i + 1) != 0:
116
+ raise ValueError("input image size (img_size) should be divisible by stage-wise image resolution.")
117
+
118
+ if not (0 <= drop_rate <= 1):
119
+ raise ValueError("dropout rate should be between 0 and 1.")
120
+
121
+ if not (0 <= attn_drop_rate <= 1):
122
+ raise ValueError("attention dropout rate should be between 0 and 1.")
123
+
124
+ if not (0 <= dropout_path_rate <= 1):
125
+ raise ValueError("drop path rate should be between 0 and 1.")
126
+
127
+ if feature_size % 12 != 0:
128
+ raise ValueError("feature_size should be divisible by 12.")
129
+
130
+ self.normalize = normalize
131
+
132
+ self.swinViT = SwinTransformer(
133
+ in_chans=in_channels,
134
+ embed_dim=feature_size,
135
+ window_size=window_size,
136
+ patch_size=patch_size,
137
+ depths=depths,
138
+ num_heads=num_heads,
139
+ mlp_ratio=4.0,
140
+ qkv_bias=True,
141
+ drop_rate=drop_rate,
142
+ attn_drop_rate=attn_drop_rate,
143
+ drop_path_rate=dropout_path_rate,
144
+ norm_layer=nn.LayerNorm,
145
+ use_checkpoint=use_checkpoint,
146
+ spatial_dims=spatial_dims,
147
+ downsample=look_up_option(downsample, MERGING_MODE) if isinstance(downsample, str) else downsample,
148
+ use_v2=use_v2,
149
+ )
150
+
151
+ self.encoder1 = UnetrBasicBlock(
152
+ spatial_dims=spatial_dims,
153
+ in_channels=in_channels,
154
+ out_channels=feature_size,
155
+ kernel_size=3,
156
+ stride=1,
157
+ norm_name=norm_name,
158
+ res_block=True,
159
+ )
160
+
161
+ self.encoder2 = UnetrBasicBlock(
162
+ spatial_dims=spatial_dims,
163
+ in_channels=feature_size,
164
+ out_channels=feature_size,
165
+ kernel_size=3,
166
+ stride=1,
167
+ norm_name=norm_name,
168
+ res_block=True,
169
+ )
170
+
171
+ self.encoder3 = UnetrBasicBlock(
172
+ spatial_dims=spatial_dims,
173
+ in_channels=2 * feature_size,
174
+ out_channels=2 * feature_size,
175
+ kernel_size=3,
176
+ stride=1,
177
+ norm_name=norm_name,
178
+ res_block=True,
179
+ )
180
+
181
+ self.encoder4 = UnetrBasicBlock(
182
+ spatial_dims=spatial_dims,
183
+ in_channels=4 * feature_size,
184
+ out_channels=4 * feature_size,
185
+ kernel_size=3,
186
+ stride=1,
187
+ norm_name=norm_name,
188
+ res_block=True,
189
+ )
190
+
191
+ self.encoder10 = UnetrBasicBlock(
192
+ spatial_dims=spatial_dims,
193
+ in_channels=16 * feature_size,
194
+ out_channels=16 * feature_size,
195
+ kernel_size=3,
196
+ stride=1,
197
+ norm_name=norm_name,
198
+ res_block=True,
199
+ )
200
+
201
+ self.decoder5 = UnetrUpBlock(
202
+ spatial_dims=spatial_dims,
203
+ in_channels=16 * feature_size,
204
+ out_channels=8 * feature_size,
205
+ kernel_size=3,
206
+ upsample_kernel_size=2,
207
+ norm_name=norm_name,
208
+ res_block=True,
209
+ )
210
+
211
+ self.decoder4 = UnetrUpBlock(
212
+ spatial_dims=spatial_dims,
213
+ in_channels=feature_size * 8,
214
+ out_channels=feature_size * 4,
215
+ kernel_size=3,
216
+ upsample_kernel_size=2,
217
+ norm_name=norm_name,
218
+ res_block=True,
219
+ )
220
+
221
+ self.decoder3 = UnetrUpBlock(
222
+ spatial_dims=spatial_dims,
223
+ in_channels=feature_size * 4,
224
+ out_channels=feature_size * 2,
225
+ kernel_size=3,
226
+ upsample_kernel_size=2,
227
+ norm_name=norm_name,
228
+ res_block=True,
229
+ )
230
+ self.decoder2 = UnetrUpBlock(
231
+ spatial_dims=spatial_dims,
232
+ in_channels=feature_size * 2,
233
+ out_channels=feature_size,
234
+ kernel_size=3,
235
+ upsample_kernel_size=2,
236
+ norm_name=norm_name,
237
+ res_block=True,
238
+ )
239
+
240
+ self.decoder1 = UnetrUpBlock(
241
+ spatial_dims=spatial_dims,
242
+ in_channels=feature_size,
243
+ out_channels=feature_size,
244
+ kernel_size=3,
245
+ upsample_kernel_size=2,
246
+ norm_name=norm_name,
247
+ res_block=True,
248
+ )
249
+ self.c3d = nn.Conv3d(feature_size, emb_size, kernel_size=1)
250
+ self.out = UnetOutBlock(spatial_dims=spatial_dims, in_channels=emb_size, out_channels=out_channels)
251
+
252
+ def load_from(self, weights):
253
+ with torch.no_grad():
254
+ self.swinViT.patch_embed.proj.weight.copy_(weights["state_dict"]["module.patch_embed.proj.weight"])
255
+ self.swinViT.patch_embed.proj.bias.copy_(weights["state_dict"]["module.patch_embed.proj.bias"])
256
+ for bname, block in self.swinViT.layers1[0].blocks.named_children():
257
+ block.load_from(weights, n_block=bname, layer="layers1")
258
+ self.swinViT.layers1[0].downsample.reduction.weight.copy_(
259
+ weights["state_dict"]["module.layers1.0.downsample.reduction.weight"]
260
+ )
261
+ self.swinViT.layers1[0].downsample.norm.weight.copy_(
262
+ weights["state_dict"]["module.layers1.0.downsample.norm.weight"]
263
+ )
264
+ self.swinViT.layers1[0].downsample.norm.bias.copy_(
265
+ weights["state_dict"]["module.layers1.0.downsample.norm.bias"]
266
+ )
267
+ for bname, block in self.swinViT.layers2[0].blocks.named_children():
268
+ block.load_from(weights, n_block=bname, layer="layers2")
269
+ self.swinViT.layers2[0].downsample.reduction.weight.copy_(
270
+ weights["state_dict"]["module.layers2.0.downsample.reduction.weight"]
271
+ )
272
+ self.swinViT.layers2[0].downsample.norm.weight.copy_(
273
+ weights["state_dict"]["module.layers2.0.downsample.norm.weight"]
274
+ )
275
+ self.swinViT.layers2[0].downsample.norm.bias.copy_(
276
+ weights["state_dict"]["module.layers2.0.downsample.norm.bias"]
277
+ )
278
+ for bname, block in self.swinViT.layers3[0].blocks.named_children():
279
+ block.load_from(weights, n_block=bname, layer="layers3")
280
+ self.swinViT.layers3[0].downsample.reduction.weight.copy_(
281
+ weights["state_dict"]["module.layers3.0.downsample.reduction.weight"]
282
+ )
283
+ self.swinViT.layers3[0].downsample.norm.weight.copy_(
284
+ weights["state_dict"]["module.layers3.0.downsample.norm.weight"]
285
+ )
286
+ self.swinViT.layers3[0].downsample.norm.bias.copy_(
287
+ weights["state_dict"]["module.layers3.0.downsample.norm.bias"]
288
+ )
289
+ for bname, block in self.swinViT.layers4[0].blocks.named_children():
290
+ block.load_from(weights, n_block=bname, layer="layers4")
291
+ self.swinViT.layers4[0].downsample.reduction.weight.copy_(
292
+ weights["state_dict"]["module.layers4.0.downsample.reduction.weight"]
293
+ )
294
+ self.swinViT.layers4[0].downsample.norm.weight.copy_(
295
+ weights["state_dict"]["module.layers4.0.downsample.norm.weight"]
296
+ )
297
+ self.swinViT.layers4[0].downsample.norm.bias.copy_(
298
+ weights["state_dict"]["module.layers4.0.downsample.norm.bias"]
299
+ )
300
+
301
+ def forward(self, x_in):
302
+
303
+ hidden_states_out = self.swinViT(x_in, self.normalize)
304
+ enc0 = self.encoder1(x_in)
305
+ enc1 = self.encoder2(hidden_states_out[0])
306
+ enc2 = self.encoder3(hidden_states_out[1])
307
+ enc3 = self.encoder4(hidden_states_out[2])
308
+ dec4 = self.encoder10(hidden_states_out[4])
309
+ dec3 = self.decoder5(dec4, hidden_states_out[3])
310
+ dec2 = self.decoder4(dec3, enc3)
311
+ dec1 = self.decoder3(dec2, enc2)
312
+ dec0 = self.decoder2(dec1, enc1)
313
+ out = self.decoder1(dec0, enc0)
314
+ out = self.c3d(out)
315
+ logits = self.out(out)
316
+ return logits
317
+
318
+
319
+ def window_partition(x, window_size):
320
+ """window partition operation based on: "Liu et al.,
321
+ Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
322
+ <https://arxiv.org/abs/2103.14030>"
323
+ https://github.com/microsoft/Swin-Transformer
324
+
325
+ Args:
326
+ x: input tensor.
327
+ window_size: local window size.
328
+ """
329
+ x_shape = x.size()
330
+ if len(x_shape) == 5:
331
+ b, d, h, w, c = x_shape
332
+ x = x.view(
333
+ b,
334
+ d // window_size[0],
335
+ window_size[0],
336
+ h // window_size[1],
337
+ window_size[1],
338
+ w // window_size[2],
339
+ window_size[2],
340
+ c,
341
+ )
342
+ windows = (
343
+ x.permute(0, 1, 3, 5, 2, 4, 6, 7).contiguous().view(-1, window_size[0] * window_size[1] * window_size[2], c)
344
+ )
345
+ elif len(x_shape) == 4:
346
+ b, h, w, c = x.shape
347
+ x = x.view(b, h // window_size[0], window_size[0], w // window_size[1], window_size[1], c)
348
+ windows = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size[0] * window_size[1], c)
349
+ return windows
350
+
351
+
352
+ def window_reverse(windows, window_size, dims):
353
+ """window reverse operation based on: "Liu et al.,
354
+ Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
355
+ <https://arxiv.org/abs/2103.14030>"
356
+ https://github.com/microsoft/Swin-Transformer
357
+
358
+ Args:
359
+ windows: windows tensor.
360
+ window_size: local window size.
361
+ dims: dimension values.
362
+ """
363
+ if len(dims) == 4:
364
+ b, d, h, w = dims
365
+ x = windows.view(
366
+ b,
367
+ d // window_size[0],
368
+ h // window_size[1],
369
+ w // window_size[2],
370
+ window_size[0],
371
+ window_size[1],
372
+ window_size[2],
373
+ -1,
374
+ )
375
+ x = x.permute(0, 1, 4, 2, 5, 3, 6, 7).contiguous().view(b, d, h, w, -1)
376
+
377
+ elif len(dims) == 3:
378
+ b, h, w = dims
379
+ x = windows.view(b, h // window_size[0], w // window_size[1], window_size[0], window_size[1], -1)
380
+ x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(b, h, w, -1)
381
+ return x
382
+
383
+
384
+ def get_window_size(x_size, window_size, shift_size=None):
385
+ """Computing window size based on: "Liu et al.,
386
+ Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
387
+ <https://arxiv.org/abs/2103.14030>"
388
+ https://github.com/microsoft/Swin-Transformer
389
+
390
+ Args:
391
+ x_size: input size.
392
+ window_size: local window size.
393
+ shift_size: window shifting size.
394
+ """
395
+
396
+ use_window_size = list(window_size)
397
+ if shift_size is not None:
398
+ use_shift_size = list(shift_size)
399
+ for i in range(len(x_size)):
400
+ if x_size[i] <= window_size[i]:
401
+ use_window_size[i] = x_size[i]
402
+ if shift_size is not None:
403
+ use_shift_size[i] = 0
404
+
405
+ if shift_size is None:
406
+ return tuple(use_window_size)
407
+ else:
408
+ return tuple(use_window_size), tuple(use_shift_size)
409
+
410
+
411
+ class WindowAttention(nn.Module):
412
+ """
413
+ Window based multi-head self attention module with relative position bias based on: "Liu et al.,
414
+ Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
415
+ <https://arxiv.org/abs/2103.14030>"
416
+ https://github.com/microsoft/Swin-Transformer
417
+ """
418
+
419
+ def __init__(
420
+ self,
421
+ dim: int,
422
+ num_heads: int,
423
+ window_size: Sequence[int],
424
+ qkv_bias: bool = False,
425
+ attn_drop: float = 0.0,
426
+ proj_drop: float = 0.0,
427
+ ) -> None:
428
+ """
429
+ Args:
430
+ dim: number of feature channels.
431
+ num_heads: number of attention heads.
432
+ window_size: local window size.
433
+ qkv_bias: add a learnable bias to query, key, value.
434
+ attn_drop: attention dropout rate.
435
+ proj_drop: dropout rate of output.
436
+ """
437
+
438
+ super().__init__()
439
+ self.dim = dim
440
+ self.window_size = window_size
441
+ self.num_heads = num_heads
442
+ head_dim = dim // num_heads
443
+ self.scale = head_dim**-0.5
444
+ mesh_args = torch.meshgrid.__kwdefaults__
445
+
446
+ if len(self.window_size) == 3:
447
+ self.relative_position_bias_table = nn.Parameter(
448
+ torch.zeros(
449
+ (2 * self.window_size[0] - 1) * (2 * self.window_size[1] - 1) * (2 * self.window_size[2] - 1),
450
+ num_heads,
451
+ )
452
+ )
453
+ coords_d = torch.arange(self.window_size[0])
454
+ coords_h = torch.arange(self.window_size[1])
455
+ coords_w = torch.arange(self.window_size[2])
456
+ if mesh_args is not None:
457
+ coords = torch.stack(torch.meshgrid(coords_d, coords_h, coords_w, indexing="ij"))
458
+ else:
459
+ coords = torch.stack(torch.meshgrid(coords_d, coords_h, coords_w))
460
+ coords_flatten = torch.flatten(coords, 1)
461
+ relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :]
462
+ relative_coords = relative_coords.permute(1, 2, 0).contiguous()
463
+ relative_coords[:, :, 0] += self.window_size[0] - 1
464
+ relative_coords[:, :, 1] += self.window_size[1] - 1
465
+ relative_coords[:, :, 2] += self.window_size[2] - 1
466
+ relative_coords[:, :, 0] *= (2 * self.window_size[1] - 1) * (2 * self.window_size[2] - 1)
467
+ relative_coords[:, :, 1] *= 2 * self.window_size[2] - 1
468
+ elif len(self.window_size) == 2:
469
+ self.relative_position_bias_table = nn.Parameter(
470
+ torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), num_heads)
471
+ )
472
+ coords_h = torch.arange(self.window_size[0])
473
+ coords_w = torch.arange(self.window_size[1])
474
+ if mesh_args is not None:
475
+ coords = torch.stack(torch.meshgrid(coords_h, coords_w, indexing="ij"))
476
+ else:
477
+ coords = torch.stack(torch.meshgrid(coords_h, coords_w))
478
+ coords_flatten = torch.flatten(coords, 1)
479
+ relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :]
480
+ relative_coords = relative_coords.permute(1, 2, 0).contiguous()
481
+ relative_coords[:, :, 0] += self.window_size[0] - 1
482
+ relative_coords[:, :, 1] += self.window_size[1] - 1
483
+ relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1
484
+
485
+ relative_position_index = relative_coords.sum(-1)
486
+ self.register_buffer("relative_position_index", relative_position_index)
487
+ self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
488
+ self.attn_drop = nn.Dropout(attn_drop)
489
+ self.proj = nn.Linear(dim, dim)
490
+ self.proj_drop = nn.Dropout(proj_drop)
491
+ trunc_normal_(self.relative_position_bias_table, std=0.02)
492
+ self.softmax = nn.Softmax(dim=-1)
493
+
494
+ def forward(self, x, mask):
495
+ b, n, c = x.shape
496
+ qkv = self.qkv(x).reshape(b, n, 3, self.num_heads, c // self.num_heads).permute(2, 0, 3, 1, 4)
497
+ q, k, v = qkv[0], qkv[1], qkv[2]
498
+ q = q * self.scale
499
+ attn = q @ k.transpose(-2, -1)
500
+ relative_position_bias = self.relative_position_bias_table[
501
+ self.relative_position_index.clone()[:n, :n].reshape(-1) # type: ignore
502
+ ].reshape(n, n, -1)
503
+ relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous()
504
+ attn = attn + relative_position_bias.unsqueeze(0)
505
+ if mask is not None:
506
+ nw = mask.shape[0]
507
+ attn = attn.view(b // nw, nw, self.num_heads, n, n) + mask.unsqueeze(1).unsqueeze(0)
508
+ attn = attn.view(-1, self.num_heads, n, n)
509
+ attn = self.softmax(attn)
510
+ else:
511
+ attn = self.softmax(attn)
512
+
513
+ attn = self.attn_drop(attn).to(v.dtype)
514
+ x = (attn @ v).transpose(1, 2).reshape(b, n, c)
515
+ x = self.proj(x)
516
+ x = self.proj_drop(x)
517
+ return x
518
+
519
+
520
+ class SwinTransformerBlock(nn.Module):
521
+ """
522
+ Swin Transformer block based on: "Liu et al.,
523
+ Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
524
+ <https://arxiv.org/abs/2103.14030>"
525
+ https://github.com/microsoft/Swin-Transformer
526
+ """
527
+
528
+ def __init__(
529
+ self,
530
+ dim: int,
531
+ num_heads: int,
532
+ window_size: Sequence[int],
533
+ shift_size: Sequence[int],
534
+ mlp_ratio: float = 4.0,
535
+ qkv_bias: bool = True,
536
+ drop: float = 0.0,
537
+ attn_drop: float = 0.0,
538
+ drop_path: float = 0.0,
539
+ act_layer: str = "GELU",
540
+ norm_layer: type[LayerNorm] = nn.LayerNorm,
541
+ use_checkpoint: bool = False,
542
+ ) -> None:
543
+ """
544
+ Args:
545
+ dim: number of feature channels.
546
+ num_heads: number of attention heads.
547
+ window_size: local window size.
548
+ shift_size: window shift size.
549
+ mlp_ratio: ratio of mlp hidden dim to embedding dim.
550
+ qkv_bias: add a learnable bias to query, key, value.
551
+ drop: dropout rate.
552
+ attn_drop: attention dropout rate.
553
+ drop_path: stochastic depth rate.
554
+ act_layer: activation layer.
555
+ norm_layer: normalization layer.
556
+ use_checkpoint: use gradient checkpointing for reduced memory usage.
557
+ """
558
+
559
+ super().__init__()
560
+ self.dim = dim
561
+ self.num_heads = num_heads
562
+ self.window_size = window_size
563
+ self.shift_size = shift_size
564
+ self.mlp_ratio = mlp_ratio
565
+ self.use_checkpoint = use_checkpoint
566
+ self.norm1 = norm_layer(dim)
567
+ self.attn = WindowAttention(
568
+ dim,
569
+ window_size=self.window_size,
570
+ num_heads=num_heads,
571
+ qkv_bias=qkv_bias,
572
+ attn_drop=attn_drop,
573
+ proj_drop=drop,
574
+ )
575
+
576
+ self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity()
577
+ self.norm2 = norm_layer(dim)
578
+ mlp_hidden_dim = int(dim * mlp_ratio)
579
+ self.mlp = Mlp(hidden_size=dim, mlp_dim=mlp_hidden_dim, act=act_layer, dropout_rate=drop, dropout_mode="swin")
580
+
581
+ def forward_part1(self, x, mask_matrix):
582
+ x_shape = x.size()
583
+ x = self.norm1(x)
584
+ if len(x_shape) == 5:
585
+ b, d, h, w, c = x.shape
586
+ window_size, shift_size = get_window_size((d, h, w), self.window_size, self.shift_size)
587
+ pad_l = pad_t = pad_d0 = 0
588
+ pad_d1 = (window_size[0] - d % window_size[0]) % window_size[0]
589
+ pad_b = (window_size[1] - h % window_size[1]) % window_size[1]
590
+ pad_r = (window_size[2] - w % window_size[2]) % window_size[2]
591
+ x = F.pad(x, (0, 0, pad_l, pad_r, pad_t, pad_b, pad_d0, pad_d1))
592
+ _, dp, hp, wp, _ = x.shape
593
+ dims = [b, dp, hp, wp]
594
+
595
+ elif len(x_shape) == 4:
596
+ b, h, w, c = x.shape
597
+ window_size, shift_size = get_window_size((h, w), self.window_size, self.shift_size)
598
+ pad_l = pad_t = 0
599
+ pad_b = (window_size[0] - h % window_size[0]) % window_size[0]
600
+ pad_r = (window_size[1] - w % window_size[1]) % window_size[1]
601
+ x = F.pad(x, (0, 0, pad_l, pad_r, pad_t, pad_b))
602
+ _, hp, wp, _ = x.shape
603
+ dims = [b, hp, wp]
604
+
605
+ if any(i > 0 for i in shift_size):
606
+ if len(x_shape) == 5:
607
+ shifted_x = torch.roll(x, shifts=(-shift_size[0], -shift_size[1], -shift_size[2]), dims=(1, 2, 3))
608
+ elif len(x_shape) == 4:
609
+ shifted_x = torch.roll(x, shifts=(-shift_size[0], -shift_size[1]), dims=(1, 2))
610
+ attn_mask = mask_matrix
611
+ else:
612
+ shifted_x = x
613
+ attn_mask = None
614
+ x_windows = window_partition(shifted_x, window_size)
615
+ attn_windows = self.attn(x_windows, mask=attn_mask)
616
+ attn_windows = attn_windows.view(-1, *(window_size + (c,)))
617
+ shifted_x = window_reverse(attn_windows, window_size, dims)
618
+ if any(i > 0 for i in shift_size):
619
+ if len(x_shape) == 5:
620
+ x = torch.roll(shifted_x, shifts=(shift_size[0], shift_size[1], shift_size[2]), dims=(1, 2, 3))
621
+ elif len(x_shape) == 4:
622
+ x = torch.roll(shifted_x, shifts=(shift_size[0], shift_size[1]), dims=(1, 2))
623
+ else:
624
+ x = shifted_x
625
+
626
+ if len(x_shape) == 5:
627
+ if pad_d1 > 0 or pad_r > 0 or pad_b > 0:
628
+ x = x[:, :d, :h, :w, :].contiguous()
629
+ elif len(x_shape) == 4:
630
+ if pad_r > 0 or pad_b > 0:
631
+ x = x[:, :h, :w, :].contiguous()
632
+
633
+ return x
634
+
635
+ def forward_part2(self, x):
636
+ return self.drop_path(self.mlp(self.norm2(x)))
637
+
638
+ def load_from(self, weights, n_block, layer):
639
+ root = f"module.{layer}.0.blocks.{n_block}."
640
+ block_names = [
641
+ "norm1.weight",
642
+ "norm1.bias",
643
+ "attn.relative_position_bias_table",
644
+ "attn.relative_position_index",
645
+ "attn.qkv.weight",
646
+ "attn.qkv.bias",
647
+ "attn.proj.weight",
648
+ "attn.proj.bias",
649
+ "norm2.weight",
650
+ "norm2.bias",
651
+ "mlp.fc1.weight",
652
+ "mlp.fc1.bias",
653
+ "mlp.fc2.weight",
654
+ "mlp.fc2.bias",
655
+ ]
656
+ with torch.no_grad():
657
+ self.norm1.weight.copy_(weights["state_dict"][root + block_names[0]])
658
+ self.norm1.bias.copy_(weights["state_dict"][root + block_names[1]])
659
+ self.attn.relative_position_bias_table.copy_(weights["state_dict"][root + block_names[2]])
660
+ self.attn.relative_position_index.copy_(weights["state_dict"][root + block_names[3]]) # type: ignore
661
+ self.attn.qkv.weight.copy_(weights["state_dict"][root + block_names[4]])
662
+ self.attn.qkv.bias.copy_(weights["state_dict"][root + block_names[5]])
663
+ self.attn.proj.weight.copy_(weights["state_dict"][root + block_names[6]])
664
+ self.attn.proj.bias.copy_(weights["state_dict"][root + block_names[7]])
665
+ self.norm2.weight.copy_(weights["state_dict"][root + block_names[8]])
666
+ self.norm2.bias.copy_(weights["state_dict"][root + block_names[9]])
667
+ self.mlp.linear1.weight.copy_(weights["state_dict"][root + block_names[10]])
668
+ self.mlp.linear1.bias.copy_(weights["state_dict"][root + block_names[11]])
669
+ self.mlp.linear2.weight.copy_(weights["state_dict"][root + block_names[12]])
670
+ self.mlp.linear2.bias.copy_(weights["state_dict"][root + block_names[13]])
671
+
672
+ def forward(self, x, mask_matrix):
673
+ shortcut = x
674
+ if self.use_checkpoint:
675
+ x = checkpoint.checkpoint(self.forward_part1, x, mask_matrix)
676
+ else:
677
+ x = self.forward_part1(x, mask_matrix)
678
+ x = shortcut + self.drop_path(x)
679
+ if self.use_checkpoint:
680
+ x = x + checkpoint.checkpoint(self.forward_part2, x)
681
+ else:
682
+ x = x + self.forward_part2(x)
683
+ return x
684
+
685
+
686
+ class PatchMergingV2(nn.Module):
687
+ """
688
+ Patch merging layer based on: "Liu et al.,
689
+ Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
690
+ <https://arxiv.org/abs/2103.14030>"
691
+ https://github.com/microsoft/Swin-Transformer
692
+ """
693
+
694
+ def __init__(self, dim: int, norm_layer: type[LayerNorm] = nn.LayerNorm, spatial_dims: int = 3) -> None:
695
+ """
696
+ Args:
697
+ dim: number of feature channels.
698
+ norm_layer: normalization layer.
699
+ spatial_dims: number of spatial dims.
700
+ """
701
+
702
+ super().__init__()
703
+ self.dim = dim
704
+ if spatial_dims == 3:
705
+ self.reduction = nn.Linear(8 * dim, 2 * dim, bias=False)
706
+ self.norm = norm_layer(8 * dim)
707
+ elif spatial_dims == 2:
708
+ self.reduction = nn.Linear(4 * dim, 2 * dim, bias=False)
709
+ self.norm = norm_layer(4 * dim)
710
+
711
+ def forward(self, x):
712
+ x_shape = x.size()
713
+ if len(x_shape) == 5:
714
+ b, d, h, w, c = x_shape
715
+ pad_input = (h % 2 == 1) or (w % 2 == 1) or (d % 2 == 1)
716
+ if pad_input:
717
+ x = F.pad(x, (0, 0, 0, w % 2, 0, h % 2, 0, d % 2))
718
+ x = torch.cat(
719
+ [x[:, i::2, j::2, k::2, :] for i, j, k in itertools.product(range(2), range(2), range(2))], -1
720
+ )
721
+
722
+ elif len(x_shape) == 4:
723
+ b, h, w, c = x_shape
724
+ pad_input = (h % 2 == 1) or (w % 2 == 1)
725
+ if pad_input:
726
+ x = F.pad(x, (0, 0, 0, w % 2, 0, h % 2))
727
+ x = torch.cat([x[:, j::2, i::2, :] for i, j in itertools.product(range(2), range(2))], -1)
728
+
729
+ x = self.norm(x)
730
+ x = self.reduction(x)
731
+ return x
732
+
733
+
734
+ class PatchMerging(PatchMergingV2):
735
+ """The `PatchMerging` module previously defined in v0.9.0."""
736
+
737
+ def forward(self, x):
738
+ x_shape = x.size()
739
+ if len(x_shape) == 4:
740
+ return super().forward(x)
741
+ if len(x_shape) != 5:
742
+ raise ValueError(f"expecting 5D x, got {x.shape}.")
743
+ b, d, h, w, c = x_shape
744
+ pad_input = (h % 2 == 1) or (w % 2 == 1) or (d % 2 == 1)
745
+ if pad_input:
746
+ x = F.pad(x, (0, 0, 0, w % 2, 0, h % 2, 0, d % 2))
747
+ x0 = x[:, 0::2, 0::2, 0::2, :]
748
+ x1 = x[:, 1::2, 0::2, 0::2, :]
749
+ x2 = x[:, 0::2, 1::2, 0::2, :]
750
+ x3 = x[:, 0::2, 0::2, 1::2, :]
751
+ x4 = x[:, 1::2, 0::2, 1::2, :]
752
+ x5 = x[:, 0::2, 1::2, 0::2, :]
753
+ x6 = x[:, 0::2, 0::2, 1::2, :]
754
+ x7 = x[:, 1::2, 1::2, 1::2, :]
755
+ x = torch.cat([x0, x1, x2, x3, x4, x5, x6, x7], -1)
756
+ x = self.norm(x)
757
+ x = self.reduction(x)
758
+ return x
759
+
760
+
761
+ MERGING_MODE = {"merging": PatchMerging, "mergingv2": PatchMergingV2}
762
+
763
+
764
+ def compute_mask(dims, window_size, shift_size, device):
765
+ """Computing region masks based on: "Liu et al.,
766
+ Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
767
+ <https://arxiv.org/abs/2103.14030>"
768
+ https://github.com/microsoft/Swin-Transformer
769
+
770
+ Args:
771
+ dims: dimension values.
772
+ window_size: local window size.
773
+ shift_size: shift size.
774
+ device: device.
775
+ """
776
+
777
+ cnt = 0
778
+
779
+ if len(dims) == 3:
780
+ d, h, w = dims
781
+ img_mask = torch.zeros((1, d, h, w, 1), device=device)
782
+ for d in slice(-window_size[0]), slice(-window_size[0], -shift_size[0]), slice(-shift_size[0], None):
783
+ for h in slice(-window_size[1]), slice(-window_size[1], -shift_size[1]), slice(-shift_size[1], None):
784
+ for w in slice(-window_size[2]), slice(-window_size[2], -shift_size[2]), slice(-shift_size[2], None):
785
+ img_mask[:, d, h, w, :] = cnt
786
+ cnt += 1
787
+
788
+ elif len(dims) == 2:
789
+ h, w = dims
790
+ img_mask = torch.zeros((1, h, w, 1), device=device)
791
+ for h in slice(-window_size[0]), slice(-window_size[0], -shift_size[0]), slice(-shift_size[0], None):
792
+ for w in slice(-window_size[1]), slice(-window_size[1], -shift_size[1]), slice(-shift_size[1], None):
793
+ img_mask[:, h, w, :] = cnt
794
+ cnt += 1
795
+
796
+ mask_windows = window_partition(img_mask, window_size)
797
+ mask_windows = mask_windows.squeeze(-1)
798
+ attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)
799
+ attn_mask = attn_mask.masked_fill(attn_mask != 0, float(-100.0)).masked_fill(attn_mask == 0, float(0.0))
800
+
801
+ return attn_mask
802
+
803
+
804
+ class BasicLayer(nn.Module):
805
+ """
806
+ Basic Swin Transformer layer in one stage based on: "Liu et al.,
807
+ Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
808
+ <https://arxiv.org/abs/2103.14030>"
809
+ https://github.com/microsoft/Swin-Transformer
810
+ """
811
+
812
+ def __init__(
813
+ self,
814
+ dim: int,
815
+ depth: int,
816
+ num_heads: int,
817
+ window_size: Sequence[int],
818
+ drop_path: list,
819
+ mlp_ratio: float = 4.0,
820
+ qkv_bias: bool = False,
821
+ drop: float = 0.0,
822
+ attn_drop: float = 0.0,
823
+ norm_layer: type[LayerNorm] = nn.LayerNorm,
824
+ downsample: nn.Module | None = None,
825
+ use_checkpoint: bool = False,
826
+ ) -> None:
827
+ """
828
+ Args:
829
+ dim: number of feature channels.
830
+ depth: number of layers in each stage.
831
+ num_heads: number of attention heads.
832
+ window_size: local window size.
833
+ drop_path: stochastic depth rate.
834
+ mlp_ratio: ratio of mlp hidden dim to embedding dim.
835
+ qkv_bias: add a learnable bias to query, key, value.
836
+ drop: dropout rate.
837
+ attn_drop: attention dropout rate.
838
+ norm_layer: normalization layer.
839
+ downsample: an optional downsampling layer at the end of the layer.
840
+ use_checkpoint: use gradient checkpointing for reduced memory usage.
841
+ """
842
+
843
+ super().__init__()
844
+ self.window_size = window_size
845
+ self.shift_size = tuple(i // 2 for i in window_size)
846
+ self.no_shift = tuple(0 for i in window_size)
847
+ self.depth = depth
848
+ self.use_checkpoint = use_checkpoint
849
+ self.blocks = nn.ModuleList(
850
+ [
851
+ SwinTransformerBlock(
852
+ dim=dim,
853
+ num_heads=num_heads,
854
+ window_size=self.window_size,
855
+ shift_size=self.no_shift if (i % 2 == 0) else self.shift_size,
856
+ mlp_ratio=mlp_ratio,
857
+ qkv_bias=qkv_bias,
858
+ drop=drop,
859
+ attn_drop=attn_drop,
860
+ drop_path=drop_path[i] if isinstance(drop_path, list) else drop_path,
861
+ norm_layer=norm_layer,
862
+ use_checkpoint=use_checkpoint,
863
+ )
864
+ for i in range(depth)
865
+ ]
866
+ )
867
+ self.downsample = downsample
868
+ if callable(self.downsample):
869
+ self.downsample = downsample(dim=dim, norm_layer=norm_layer, spatial_dims=len(self.window_size))
870
+
871
+ def forward(self, x):
872
+ x_shape = x.size()
873
+ if len(x_shape) == 5:
874
+ b, c, d, h, w = x_shape
875
+ window_size, shift_size = get_window_size((d, h, w), self.window_size, self.shift_size)
876
+ x = rearrange(x, "b c d h w -> b d h w c")
877
+ dp = int(np.ceil(d / window_size[0])) * window_size[0]
878
+ hp = int(np.ceil(h / window_size[1])) * window_size[1]
879
+ wp = int(np.ceil(w / window_size[2])) * window_size[2]
880
+ attn_mask = compute_mask([dp, hp, wp], window_size, shift_size, x.device)
881
+ for blk in self.blocks:
882
+ x = blk(x, attn_mask)
883
+ x = x.view(b, d, h, w, -1)
884
+ if self.downsample is not None:
885
+ x = self.downsample(x)
886
+ x = rearrange(x, "b d h w c -> b c d h w")
887
+
888
+ elif len(x_shape) == 4:
889
+ b, c, h, w = x_shape
890
+ window_size, shift_size = get_window_size((h, w), self.window_size, self.shift_size)
891
+ x = rearrange(x, "b c h w -> b h w c")
892
+ hp = int(np.ceil(h / window_size[0])) * window_size[0]
893
+ wp = int(np.ceil(w / window_size[1])) * window_size[1]
894
+ attn_mask = compute_mask([hp, wp], window_size, shift_size, x.device)
895
+ for blk in self.blocks:
896
+ x = blk(x, attn_mask)
897
+ x = x.view(b, h, w, -1)
898
+ if self.downsample is not None:
899
+ x = self.downsample(x)
900
+ x = rearrange(x, "b h w c -> b c h w")
901
+ return x
902
+
903
+
904
+ class SwinTransformer(nn.Module):
905
+ """
906
+ Swin Transformer based on: "Liu et al.,
907
+ Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
908
+ <https://arxiv.org/abs/2103.14030>"
909
+ https://github.com/microsoft/Swin-Transformer
910
+ """
911
+
912
+ def __init__(
913
+ self,
914
+ in_chans: int,
915
+ embed_dim: int,
916
+ window_size: Sequence[int],
917
+ patch_size: Sequence[int],
918
+ depths: Sequence[int],
919
+ num_heads: Sequence[int],
920
+ mlp_ratio: float = 4.0,
921
+ qkv_bias: bool = True,
922
+ drop_rate: float = 0.0,
923
+ attn_drop_rate: float = 0.0,
924
+ drop_path_rate: float = 0.0,
925
+ norm_layer: type[LayerNorm] = nn.LayerNorm,
926
+ patch_norm: bool = False,
927
+ use_checkpoint: bool = False,
928
+ spatial_dims: int = 3,
929
+ downsample="merging",
930
+ use_v2=False,
931
+ ) -> None:
932
+ """
933
+ Args:
934
+ in_chans: dimension of input channels.
935
+ embed_dim: number of linear projection output channels.
936
+ window_size: local window size.
937
+ patch_size: patch size.
938
+ depths: number of layers in each stage.
939
+ num_heads: number of attention heads.
940
+ mlp_ratio: ratio of mlp hidden dim to embedding dim.
941
+ qkv_bias: add a learnable bias to query, key, value.
942
+ drop_rate: dropout rate.
943
+ attn_drop_rate: attention dropout rate.
944
+ drop_path_rate: stochastic depth rate.
945
+ norm_layer: normalization layer.
946
+ patch_norm: add normalization after patch embedding.
947
+ use_checkpoint: use gradient checkpointing for reduced memory usage.
948
+ spatial_dims: spatial dimension.
949
+ downsample: module used for downsampling, available options are `"mergingv2"`, `"merging"` and a
950
+ user-specified `nn.Module` following the API defined in :py:class:`monai.networks.nets.PatchMerging`.
951
+ The default is currently `"merging"` (the original version defined in v0.9.0).
952
+ use_v2: using swinunetr_v2, which adds a residual convolution block at the beginning of each swin stage.
953
+ """
954
+
955
+ super().__init__()
956
+ self.num_layers = len(depths)
957
+ self.embed_dim = embed_dim
958
+ self.patch_norm = patch_norm
959
+ self.window_size = window_size
960
+ self.patch_size = patch_size
961
+ self.patch_embed = PatchEmbed(
962
+ patch_size=self.patch_size,
963
+ in_chans=in_chans,
964
+ embed_dim=embed_dim,
965
+ norm_layer=norm_layer if self.patch_norm else None, # type: ignore
966
+ spatial_dims=spatial_dims,
967
+ )
968
+ self.pos_drop = nn.Dropout(p=drop_rate)
969
+ dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))]
970
+ self.use_v2 = use_v2
971
+ self.layers1 = nn.ModuleList()
972
+ self.layers2 = nn.ModuleList()
973
+ self.layers3 = nn.ModuleList()
974
+ self.layers4 = nn.ModuleList()
975
+ if self.use_v2:
976
+ self.layers1c = nn.ModuleList()
977
+ self.layers2c = nn.ModuleList()
978
+ self.layers3c = nn.ModuleList()
979
+ self.layers4c = nn.ModuleList()
980
+ down_sample_mod = look_up_option(downsample, MERGING_MODE) if isinstance(downsample, str) else downsample
981
+ for i_layer in range(self.num_layers):
982
+ layer = BasicLayer(
983
+ dim=int(embed_dim * 2**i_layer),
984
+ depth=depths[i_layer],
985
+ num_heads=num_heads[i_layer],
986
+ window_size=self.window_size,
987
+ drop_path=dpr[sum(depths[:i_layer]) : sum(depths[: i_layer + 1])],
988
+ mlp_ratio=mlp_ratio,
989
+ qkv_bias=qkv_bias,
990
+ drop=drop_rate,
991
+ attn_drop=attn_drop_rate,
992
+ norm_layer=norm_layer,
993
+ downsample=down_sample_mod,
994
+ use_checkpoint=use_checkpoint,
995
+ )
996
+ if i_layer == 0:
997
+ self.layers1.append(layer)
998
+ elif i_layer == 1:
999
+ self.layers2.append(layer)
1000
+ elif i_layer == 2:
1001
+ self.layers3.append(layer)
1002
+ elif i_layer == 3:
1003
+ self.layers4.append(layer)
1004
+ if self.use_v2:
1005
+ layerc = UnetrBasicBlock(
1006
+ spatial_dims=3,
1007
+ in_channels=embed_dim * 2**i_layer,
1008
+ out_channels=embed_dim * 2**i_layer,
1009
+ kernel_size=3,
1010
+ stride=1,
1011
+ norm_name="instance",
1012
+ res_block=True,
1013
+ )
1014
+ if i_layer == 0:
1015
+ self.layers1c.append(layerc)
1016
+ elif i_layer == 1:
1017
+ self.layers2c.append(layerc)
1018
+ elif i_layer == 2:
1019
+ self.layers3c.append(layerc)
1020
+ elif i_layer == 3:
1021
+ self.layers4c.append(layerc)
1022
+
1023
+ self.num_features = int(embed_dim * 2 ** (self.num_layers - 1))
1024
+
1025
+ def proj_out(self, x, normalize=False):
1026
+ if normalize:
1027
+ x_shape = x.size()
1028
+ if len(x_shape) == 5:
1029
+ n, ch, d, h, w = x_shape
1030
+ x = rearrange(x, "n c d h w -> n d h w c")
1031
+ x = F.layer_norm(x, [ch])
1032
+ x = rearrange(x, "n d h w c -> n c d h w")
1033
+ elif len(x_shape) == 4:
1034
+ n, ch, h, w = x_shape
1035
+ x = rearrange(x, "n c h w -> n h w c")
1036
+ x = F.layer_norm(x, [ch])
1037
+ x = rearrange(x, "n h w c -> n c h w")
1038
+ return x
1039
+
1040
+ def forward(self, x, normalize=True):
1041
+ x0 = self.patch_embed(x)
1042
+ x0 = self.pos_drop(x0)
1043
+ x0_out = self.proj_out(x0, normalize)
1044
+ if self.use_v2:
1045
+ x0 = self.layers1c[0](x0.contiguous())
1046
+ x1 = self.layers1[0](x0.contiguous())
1047
+ x1_out = self.proj_out(x1, normalize)
1048
+ if self.use_v2:
1049
+ x1 = self.layers2c[0](x1.contiguous())
1050
+ x2 = self.layers2[0](x1.contiguous())
1051
+ x2_out = self.proj_out(x2, normalize)
1052
+ if self.use_v2:
1053
+ x2 = self.layers3c[0](x2.contiguous())
1054
+ x3 = self.layers3[0](x2.contiguous())
1055
+ x3_out = self.proj_out(x3, normalize)
1056
+ if self.use_v2:
1057
+ x3 = self.layers4c[0](x3.contiguous())
1058
+ x4 = self.layers4[0](x3.contiguous())
1059
+ x4_out = self.proj_out(x4, normalize)
1060
+ return [x0_out, x1_out, x2_out, x3_out, x4_out]
DCA/utils.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import torch
3
+ import torch.nn as nn
4
+ import matplotlib.pyplot as plt
5
+ import nibabel as nib
6
+ from collections import defaultdict
7
+ from scipy.sparse.linalg import svds
8
+ import torch.nn.functional as F
9
+ import torch.optim as optim
10
+ from sklearn.metrics import normalized_mutual_info_score as nmi_score
11
+ from sklearn.cluster import SpectralClustering
12
+
13
+ from scipy.sparse import csr_matrix
14
+ from scipy.sparse.linalg import eigsh
15
+ from sklearn.cluster import KMeans
16
+ from torch_geometric.utils import to_scipy_sparse_matrix
17
+ from scipy.sparse import identity
18
+ from scipy.sparse.linalg import lobpcg
19
+ from sklearn.cluster import AgglomerativeClustering
20
+
21
+ from scipy import ndimage
22
+ from scipy.optimize import linear_sum_assignment
23
+
24
+
25
+ def weighted_bfs_connected_clustering(edge_index, edge_weight, num_nodes, k, seed=None):
26
+
27
+ if seed is not None:
28
+ np.random.seed(seed)
29
+ random.seed(seed)
30
+
31
+ if torch.is_tensor(edge_index):
32
+ edge_index = edge_index.cpu().numpy()
33
+ if torch.is_tensor(edge_weight):
34
+ edge_weight = edge_weight.cpu().numpy()
35
+
36
+ graph = defaultdict(list)
37
+ E = edge_index.shape[1]
38
+ for idx in range(E):
39
+ i, j = int(edge_index[0, idx]), int(edge_index[1, idx])
40
+ w = float(edge_weight[idx])
41
+ graph[i].append((j, w))
42
+ graph[j].append((i, w))
43
+
44
+ labels = np.full(num_nodes, -1, dtype=int)
45
+ max_size = int(np.ceil(num_nodes / k))
46
+ cluster_sizes = [0] * k
47
+ heaps = [ [] for _ in range(k) ]
48
+
49
+ seeds = np.random.choice(num_nodes, k, replace=False)
50
+ for cid, seed_node in enumerate(seeds):
51
+ labels[seed_node] = cid
52
+ cluster_sizes[cid] += 1
53
+ for nbr, w in graph[seed_node]:
54
+ if labels[nbr] == -1:
55
+ heapq.heappush(heaps[cid], (-w, nbr))
56
+
57
+ assigned = k
58
+
59
+ while assigned < num_nodes:
60
+ made_progress = False
61
+ for cid in range(k):
62
+ if cluster_sizes[cid] >= max_size:
63
+ continue
64
+ heap = heaps[cid]
65
+ while heap:
66
+ neg_w, node = heapq.heappop(heap)
67
+ if labels[node] == -1:
68
+ labels[node] = cid
69
+ cluster_sizes[cid] += 1
70
+ assigned += 1
71
+ for nbr, w in graph[node]:
72
+ if labels[nbr] == -1:
73
+ heapq.heappush(heap, (-w, nbr))
74
+ made_progress = True
75
+ break
76
+ if not made_progress:
77
+ break
78
+
79
+ for node in range(num_nodes):
80
+ if labels[node] == -1:
81
+ nbr_labels = [labels[nbr] for nbr, _ in graph[node] if labels[nbr] != -1]
82
+ if nbr_labels:
83
+ cid = min(nbr_labels, key=lambda x: cluster_sizes[x])
84
+ else:
85
+ cid = int(np.argmin(cluster_sizes))
86
+ labels[node] = cid
87
+ cluster_sizes[cid] += 1
88
+
89
+ return labels
90
+
91
+
92
+
93
+ def match_labels(y_true, y_pred, n_clusters):
94
+
95
+ cost = np.zeros((n_clusters, n_clusters), dtype=int)
96
+ for i in range(n_clusters):
97
+ for j in range(n_clusters):
98
+ cost[i, j] = np.sum((y_true == i) & (y_pred == j))
99
+ row_ind, col_ind = linear_sum_assignment(-cost)
100
+ mapping = dict(zip(col_ind, row_ind))
101
+ return np.vectorize(lambda x: mapping.get(x, x))(y_pred)
102
+
103
+
104
+
105
+ def large_constrcut(mask):
106
+
107
+ binary_mask = (mask > 0).astype(int)
108
+
109
+ structure = ndimage.generate_binary_structure(3, 1)
110
+ labeled_mask, num_labels = ndimage.label(binary_mask, structure=structure)
111
+
112
+ region_sizes = ndimage.sum(binary_mask, labeled_mask, index=np.arange(1, num_labels + 1))
113
+
114
+ if num_labels == 0:
115
+ largest_label = 0
116
+ else:
117
+ largest_label = np.argmax(region_sizes) + 1
118
+ large_mask = (labeled_mask == largest_label).astype(int)
119
+ print('total voxels:', len(np.where(large_mask>0)[0]))
120
+ return large_mask
121
+
122
+
123
+ def build_spatial_graph_and_weights(edge_index,features):
124
+
125
+ src, tgt = edge_index
126
+ feat_src = features[src]
127
+ feat_tgt = features[tgt]
128
+ x_centered = feat_src - feat_src.mean()
129
+ y_centered = feat_tgt - feat_tgt.mean()
130
+ edge_weight = F.cosine_similarity(x_centered, y_centered)
131
+ return edge_weight
132
+
133
+
134
+
135
+ def sparse_spectral_clustering(edge_index, edge_weight, num_nodes, k=2):
136
+
137
+ adj_sparse = to_scipy_sparse_matrix(
138
+ edge_index, edge_weight, num_nodes=num_nodes
139
+ )
140
+
141
+ degree = np.array(adj_sparse.sum(axis=1)).flatten()
142
+ D = csr_matrix((degree, (np.arange(num_nodes), np.arange(num_nodes))), shape=(num_nodes, num_nodes))
143
+ L = D - adj_sparse
144
+
145
+ _, eigenvectors = eigsh(L.astype(np.float64), k=k, which='LM',sigma=0, maxiter=10000)
146
+
147
+ kmeans = KMeans(n_clusters=k)
148
+ labels = kmeans.fit_predict(eigenvectors)
149
+ return labels
150
+
151
+
152
+
153
+ def validate(input_file, label_file):
154
+
155
+ if input_file.endswith('.zst'):
156
+ input_matrix = load_zstd_file(input_file)
157
+ elif input_file.endswith('.npy'):
158
+ input_matrix = np.load(input_file)
159
+ else:
160
+ input_matrix = nib.load(input_file).get_fdata()
161
+ input_matrix = input_matrix[:,:,:,:300]
162
+
163
+ label_matrix = label_file
164
+
165
+ unique_labels = np.unique(label_matrix)
166
+ unique_labels = unique_labels[unique_labels > 0]
167
+ print('roi number:',len(unique_labels))
168
+ fc_means = {}
169
+ voxel_counts = {}
170
+ silhouette_scores = {}
171
+
172
+ for label in unique_labels:
173
+ voxel_indices = np.argwhere(label_matrix == label)
174
+ if voxel_indices.shape[0] < 2:
175
+ fc_means[label] = np.nan
176
+ voxel_counts[label] = len(voxel_indices)
177
+ silhouette_scores[label] = np.nan
178
+ continue
179
+ time_series = input_matrix[voxel_indices[:, 0], voxel_indices[:, 1], voxel_indices[:, 2], :]
180
+ n_voxels = time_series.shape[0]
181
+
182
+ fc_mean, fc_mat = calculate_fc_mean(time_series)
183
+ fc_means[label] = fc_mean
184
+ voxel_counts[label] = len(voxel_indices)
185
+
186
+ weighted_sum_fc = 0.0
187
+ valid_voxels = 0
188
+ for label in fc_means:
189
+ if not np.isnan(fc_means[label]):
190
+ weighted_sum_fc += fc_means[label] * voxel_counts[label]
191
+ valid_voxels += voxel_counts[label]
192
+ weighted_mean_fc = weighted_sum_fc / valid_voxels if valid_voxels > 0 else np.nan
193
+
194
+
195
+ return weighted_mean_fc
196
+
197
+
198
+ def calculate_fc_mean(time_series):
199
+ if time_series.shape[0] < 2:
200
+ return np.nan, np.nan
201
+
202
+ fc_matrix = np.corrcoef(time_series)
203
+
204
+ if fc_matrix.ndim != 2 or fc_matrix.shape[0] != fc_matrix.shape[1]:
205
+ return np.nan, np.nan
206
+
207
+ lower_triangle_indices = np.tril_indices(fc_matrix.shape[0], -1)
208
+ lower_triangle_values = fc_matrix[lower_triangle_indices]
209
+
210
+ # positive_fc_values = lower_triangle_values[lower_triangle_values > 0]
211
+ # mean_fc = np.mean(positive_fc_values) if positive_fc_values.size > 0 else 0
212
+ mean_fc = np.mean(lower_triangle_values)
213
+ return mean_fc, fc_matrix
README.md ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # DCA: Graph-Guided Deep Embedding Clustering for Brain Atlases
3
+ <a href="https://arxiv.org/abs/2509.01426"><img src="https://img.shields.io/badge/Paper-Arxiv-darkred.svg" alt="Paper"></a>
4
+ <a href="https://polyformproject.org/licenses/noncommercial/1.0.0/"><img src="https://img.shields.io/badge/License-PolyForm--NC--1.0.0-blueviolet.svg" alt="License: PolyForm Noncommercial 1.0.0"></a>
5
+
6
+ This repository contains the official implementation of our **NeurIPS 2025** paper (5554, Poster) [**DCA: Graph-Guided Deep Embedding Clustering for Brain Atlases**](https://arxiv.org/abs/2509.01426). The method integrates pretraining and spatial graph-based constraints to generate anatomically and functionally meaningful brain atlases.
7
+
8
+ ![](fig.png)
9
+
10
+
11
+ ## DCA Usage
12
+
13
+ 0. Dependencies
14
+
15
+ We recommend using `Python == 3.9.21`.
16
+
17
+ All required packages are listed in `DCA/req_trim.txt`.
18
+
19
+
20
+ 1. Prepare Data
21
+
22
+
23
+ Use `DCA/data/data_preparation.ipynb` to prepare both fMRI and mask data: fMRI inputs should be resting-state scans normalized to the MNI152 space with at least 300 TRs (note that if TR ≠ 0.72 s, it is recommended to resample temporally to 0.72 s beforehand, as this step is not included in the notebook), and mask inputs should be the corresponding FreeSurfer `aparc+aseg.nii.gz` already registered in MNI152 space.
24
+
25
+ Place preprocessed 4D fMRI volumes in `DCA/data/fmri/`, we have placed a demo fMRI.
26
+
27
+ Place your ROI masks in `DCA/data/mask/`. This implementation supports customization for gray matter, white matter, and subcortex-specific atlases. We have placed a demo mask.
28
+
29
+ Ensure data/sub_test.txt contains the list of subject IDs (one per line), we have placed a demo text.
30
+
31
+ The pretrained model (swin_model_epoch_30.pth) is automatically loaded if present. We conduct pre-training using monai (https://monai.io/) and customize some functions through DCA/swin_unetr.py
32
+
33
+
34
+ 2. Run DCA
35
+
36
+ ```bash
37
+ python main.py
38
+ ```
39
+
40
+ This will generate subject-level brain parcellations using the provided pretrained model. Results will be saved to results/demo/.
41
+
42
+ Command-line Options
43
+
44
+ You can customize key inference settings via arguments in `main.py`. The main options are:
45
+
46
+ - `-k`, `--n_clusters`: Number of parcels to generate (default: `100`)
47
+ - `-e`, `--epoch`: Maximum training epochs (default: `8`)
48
+ - `-v`, `--vali`: Whether to keep the best atlas based homogeneity (default: `True`)
49
+
50
+ Validation requires more computing resources. If `--vali` is set to `False`, we recommend using `--epoch < 10` to avoid overfitting.
51
+
52
+
53
+ 3. Results
54
+
55
+ Output can be found in data/results/demo
56
+
57
+ ## AtlaScore Usage
58
+ ### Downstream
59
+ For all the operation instructions, please see `demo.ipynb`.
60
+
61
+ ### Similarity
62
+ - Provide fMRI data `shape=(x,y,z,t)` and the atlas file `shape=(x,y,z)` to be evaluated, modify the paths in `eva.py`, and run the command `python eva.py`.
63
+ - To evaluate DCBC, you must provide the following files mapped to cortical surface vertices: fMRI data, vertex distance file, and parcellation file. Refer to [Zhi et al.](https://github.com/DiedrichsenLab/DCBC) for more detailed methodological instructions.
64
+
65
+ ## Citations
66
+ If you find our work useful for your research, please consider citing our paper:
67
+ ```bibtex
68
+ @article{wang2025dca,
69
+ title={DCA: Graph-Guided Deep Embedding Clustering for Brain Atlases},
70
+ author={Wang, Mo and Peng, Kaining and Tang, Jingsheng and Wen, Hongkai and Liu, Quanying},
71
+ journal={arXiv preprint arXiv:2509.01426},
72
+ year={2025}
73
+ }
74
+ ```
Release/DCA100.nii.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:55cb73621697360e6107394f51fc0606367c1c43a88d96c8693c0d810d91d8d1
3
+ size 132151
Release/DCA200.nii.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:922ea7b5774ba2ba553767e084efcaef5f96df2921b24db046c5f17716163b9a
3
+ size 142767
Release/DCA360.nii.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ac8661c8883211591f562ce7f1c0e97655bd2db35154d0f23b0d8f5630aba056
3
+ size 152187
Release/DCA400.nii.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4225d5c96e71db74bf5400936047a433e7f500d74c1e3adcaa11e53e921406e3
3
+ size 154316
Release/DCA500.nii.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:771969400101648c0d8b36909999520750136143e8544c2fda8d7e4da31895ba
3
+ size 158566
fig.png ADDED

Git LFS Details

  • SHA256: f6b7fdec1414116f6bce9d41065d69d009f6fbfd5b14ccb080363af7e2a586df
  • Pointer size: 132 Bytes
  • Size of remote file: 5.55 MB