-
Notifications
You must be signed in to change notification settings - Fork 1
/
fsrecon_batch
executable file
·188 lines (140 loc) · 5.02 KB
/
fsrecon_batch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/python
import os
import sys
import pyxnat
import zipfile
import argparse
import tempfile
import subprocess as sub
from multiprocessing.pool import ThreadPool
scantypes = ['MPRAGE','SPGR']
##################################
# Arguments
##################################
def parse_args():
parser = argparse.ArgumentParser(description='Process fs-recons en mass')
# input
parser.add_argument('--project','-p',
metavar='id',
help='Project ID (within XNAT)',
required=True)
parser.add_argument('--outdir', '-o',
metavar='dir',
help='Output dir',
required=True)
parser.add_argument('--nthreads','-n',
metavar='n', type=int,
help='Number of threads to run simultaneously',
required=True)
parser.add_argument('sessfile',
metavar='sessfile',
type=argparse.FileType('r'),
help='Input session list file')
args = parser.parse_args()
return args
##################################
# XNAT
##################################
def get_xnat():
return pyxnat.Interface()
def get_project(id):
return get_xnat().select.project(id)
def get_scans(project,subjid):
subject = project.subject(subjid)
if not subject.exists():
print "{}: ERROR, subject not found in project".format(subjid)
sys.exit()
# get all MR sessions for subject
mr_sess_labels = [x.label()
for x in subject.experiments().get('type')
if x.datatype()=='xnat:mrSessionData']
if len(mr_sess_labels)==0:
print "{}: ERROR, no MR sessions found for subject. ".format(subjid)
sys.exit()
# take first one
mr_sess_label = mr_sess_labels[0]
return subject.experiment(mr_sess_label).scans()
##################################
# Helpers
##################################
def get_dicom(dir):
for root, dirs, files in os.walk(dir):
for file in sorted(files):
if file.endswith('.dcm'):
return os.path.join(root,file)
def download_zip(project, sessid):
dldir = tempfile.mkdtemp()
found = False
for scantype in scantypes:
print "{}: looking for {} scans... ".format(sessid, scantype)
dlfile = "{}_{}_{}".format(project, sessid, scantype)
dlpath = os.path.join(dldir, dlfile)
proj = get_project(project)
if not proj.exists():
print "{}: ERROR, project {} not found".format(sessid, project)
sys.exit()
scans = get_scans(proj, sessid)
try:
# download zip file
scans.download(dldir,type=scantype, name=dlfile)
print "{}: downloaded file {}".format(sessid, dlpath)
return dlpath+'.zip'
found=True
except:
# the above command creates a broken file, let's remove
dlpathname = dlpath+'.zip'
if os.path.exists(dlpathname):
os.remove(dlpathname)
print "{}: no {} scans found".format(sessid, scantype)
if not found:
print "{}: no scans found.".format(sessid)
sys.exit()
##################################
# Thread process
##################################
def fsrecon(project, sessid, outdir='.'):
# download data
dlfile = download_zip(project, sessid)
# unzip
print "{}: unzipping file...".format(sessid)
tdir = tempfile.mkdtemp()
zf = zipfile.ZipFile(dlfile)
zf.extractall(tdir)
# find dicom
dicom = get_dicom(tdir)
# recon-all
print "{}: running recon-all...".format(sessid)
reconall = 'recon-all -qcache -all -hippo-subfields -s {} -sd {} -i {}'
#recondir = '/space/bic/subjects/fs-recons'
cmdstr = reconall.format(sessid, outdir, dicom)
print "{}: {}".format(sessid, cmdstr)
logfilename = os.path.join(outdir,'{}.fsrecon.log'.format(sessid))
logfile = open(logfilename, 'a')
proc = sub.Popen(cmdstr,
shell = True,
executable='/bin/bash',
stdout = logfile,
stderr = logfile)
# block processing until finished
stdout,_ = proc.communicate()
# push output to log
#logfile.write(stdout)
#logfile.close()
# check for errors
if proc.poll():
print '{}: recon-all encountered errors'.format(sessid)
else:
print '{}: recon-all finished successfully!'.format(sessid)
##################################
# Main
##################################
if __name__ == '__main__':
args = parse_args()
sessions = [l.strip() for l in args.sessfile.readlines()
if l.strip() != '']
task_pool = ThreadPool(processes=args.nthreads)
for sessid in sessions:
#fsrecon(args.project,sessid,args.outdir)
task_pool.apply_async(fsrecon, (args.project,sessid,args.outdir))
task_pool.close()
task_pool.join()