Skip to content

Commit ef0aa12

Browse files
authored
Merge pull request #16 from BIDS-Apps/enh/fs6
Update to FreeSurfer 6.0.0
2 parents 35ff6db + 6789a88 commit ef0aa12

File tree

3 files changed

+63
-50
lines changed

3 files changed

+63
-50
lines changed

Dockerfile

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ FROM ubuntu:trusty
22

33
RUN apt-get update \
44
&& apt-get install -y wget
5-
RUN wget -qO- ftp://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/5.3.0-HCP/freesurfer-Linux-centos4_x86_64-stable-pub-v5.3.0-HCP.tar.gz | tar zxv -C /opt \
5+
RUN wget -qO- https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.0/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.0.tar.gz | tar zxv -C /opt \
66
--exclude='freesurfer/trctrain' \
77
--exclude='freesurfer/subjects/fsaverage_sym' \
88
--exclude='freesurfer/subjects/fsaverage3' \
@@ -30,16 +30,6 @@ RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
3030
RUN apt-get install -y nodejs
3131
RUN npm install -g bids-validator@0.19.8
3232

33-
RUN apt-get update && \
34-
apt-get install -y curl && \
35-
curl -sSL http://neuro.debian.net/lists/trusty.us-ca.full >> /etc/apt/sources.list.d/neurodebian.sources.list && \
36-
apt-key adv --recv-keys --keyserver hkp://pgp.mit.edu:80 0xA5D32F012649A5A9 && \
37-
apt-get update && \
38-
apt-get remove -y curl && \
39-
apt-get install -y fsl-core && \
40-
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
41-
42-
4333
# Configure environment
4434
ENV FSLDIR=/usr/share/fsl/5.0
4535
ENV FSLOUTPUTTYPE=NIFTI_GZ

README.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
This app implements surface reconstruction using Freesurfer. It reconstructs the surface for each subject individually and then
44
creates a study specific template. In case there are multiple sessions the Freesurfer longitudinal pipeline is used (creating subject specific templates) unless instructed to combine data across sessions.
55

6-
The current Freesurfer version is based on: freesurfer-Linux-centos4_x86_64-stable-pub-v5.3.0-HCP.tar.gz
6+
The current Freesurfer version is based on: freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.0.tar.gz
77

88
The output of the pipeline consist of the SUBJECTS_DIR created during the analysis.
99

@@ -28,7 +28,7 @@ This App has the following command line arguments:
2828
bids_dir output_dir {participant,group}
2929

3030
FreeSurfer recon-all + custom template generation.
31-
31+
3232
NOTE: if scripts/IsRunning is present, this pipeline assumes recon-all was
3333
interrupted and removes the directory then re-runs the processing stream.
3434

@@ -48,7 +48,7 @@ This App has the following command line arguments:
4848
in the email you received after registration. To
4949
register (for free) visit
5050
https://surfer.nmr.mgh.harvard.edu/registration.html
51-
51+
5252
optional arguments:
5353
-h, --help show this help message and exit
5454
--participant_label PARTICIPANT_LABEL [PARTICIPANT_LABEL ...]
@@ -69,19 +69,23 @@ This App has the following command line arguments:
6969
from different acquisitions which one should be used?
7070
Corresponds to "acq-<acquisition_label>"
7171
--multiple_sessions {longitudinal, multiday}
72-
For datasets with multiday sessions where you do not
73-
want to use the longitudinal pipeline, i.e., sessions
74-
were back-to-back, set this to multiday, otherwise
72+
For datasets with multiday sessions where you do not
73+
want to use the longitudinal pipeline, i.e., sessions
74+
were back-to-back, set this to multiday, otherwise
7575
sessions with T1w data will be considered independent
7676
sessions for longitudinal analysis.
7777
--refine_pial {T2,FLAIR,None,T1only}
78-
If the dataset contains 3D T2 or T2 FLAIR weighted
78+
If the dataset contains 3D T2 or T2 FLAIR weighted
7979
images (~1x1x1), these can be used to refine the pial
8080
surface. The current default is to look for
8181
appropriate T2s, then look for appropriate FLAIRs
8282
(resolution <1.2mm isovolumetric). If you want to
83-
ignore these, specify None or T1only to generate
83+
ignore these, specify None or T1only to generate
8484
surfaces on the T1 alone.
85+
--hires_mode {auto,enable,disable}
86+
Submilimiter (high resolution) processing. 'auto' -
87+
use only if <1.0mm data detected, 'enable' - force on,
88+
'disable' - force off
8589

8690
To run it in participant level mode (for one participant):
8791

run.py

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ def run(command, env={}, ignore_errors=False):
6464
' T1only to base surfaces on the T1 alone.',
6565
choices=['T2', 'FLAIR', 'None', 'T1only'],
6666
default=['T2'])
67+
parser.add_argument('--hires_mode', help="Submilimiter (high resolution) processing. 'auto' - use only if <1.0mm data detected, 'enable' - force on, 'disable' - force off",
68+
choices=['auto', 'enable', 'disable'],
69+
default='auto')
6770
parser.add_argument('-v', '--version', action='version',
6871
version='BIDS-App example version {}'.format(__version__))
6972

@@ -100,7 +103,7 @@ def run(command, env={}, ignore_errors=False):
100103
if not os.path.exists(os.path.join(output_dir, "rh.EC_average")):
101104
run("cp -rf " + os.path.join(os.environ["SUBJECTS_DIR"], "rh.EC_average") + " " + os.path.join(output_dir, "rh.EC_average"),
102105
ignore_errors=True)
103-
106+
104107
for subject_label in subjects_to_analyze:
105108

106109
# Check for multiple sessions to combine as a multiday session or as a longitudinal stream
@@ -122,11 +125,17 @@ def run(command, env={}, ignore_errors=False):
122125
if len(sessions) > 0 and longitudinal_study == True:
123126
# Running each session separately, prior to doing longitudinal pipeline
124127
for session_label in sessions:
125-
input_args = " ".join(["-i %s"%f for f in glob(os.path.join(args.bids_dir,
126-
"sub-%s"%subject_label,
127-
"ses-%s"%session_label,
128-
"anat",
129-
"%s_T1w.nii*"%acq_tpl))])
128+
T1s = glob(os.path.join(args.bids_dir,
129+
"sub-%s"%subject_label,
130+
"ses-%s"%session_label,
131+
"anat",
132+
"%s_T1w.nii*"%acq_tpl))
133+
input_args = ""
134+
for T1 in T1s:
135+
if (round(max(nibabel.load(T1).header.get_zooms()),1) < 1.0 and args.hires_mode == "auto") or args.hires_mode == "enable":
136+
input_args += " -hires"
137+
input_args += " -i %s"%T1
138+
130139
T2s = glob(os.path.join(args.bids_dir, "sub-%s"%subject_label,
131140
"ses-%s"%session_label, "anat",
132141
"*_T2w.nii*"))
@@ -144,14 +153,13 @@ def run(command, env={}, ignore_errors=False):
144153
input_args += " " + " ".join(["-FLAIR %s"%FLAIR])
145154
input_args += " -FLAIRpial"
146155

147-
148156
fsid = "sub-%s_ses-%s"%(subject_label, session_label)
149157
timepoints.append(fsid)
150-
cmd = "recon-all -subjid %s -sd %s %s -all -openmp %d"%(fsid,
158+
cmd = "recon-all -subjid %s -sd %s %s -all -parallel -openmp %d"%(fsid,
151159
output_dir,
152160
input_args,
153161
args.n_cpus)
154-
resume_cmd = "recon-all -subjid %s -sd %s -all -openmp %d"%(fsid,
162+
resume_cmd = "recon-all -subjid %s -sd %s -all -parallel -openmp %d"%(fsid,
155163
output_dir,
156164
args.n_cpus)
157165

@@ -172,16 +180,16 @@ def run(command, env={}, ignore_errors=False):
172180
input_args = " ".join(["-tp %s"%tp for tp in timepoints])
173181
fsid = "sub-%s"%subject_label
174182
stages = " ".join(["-" + stage for stage in args.stages])
175-
cmd = "recon-all -base %s -sd %s %s %s -openmp %d"%(fsid,
183+
cmd = "recon-all -base %s -sd %s %s %s -parallel -openmp %d"%(fsid,
176184
output_dir,
177185
input_args,
178186
stages,
179187
args.n_cpus)
180-
resume_cmd = "recon-all -base %s -sd %s %s -openmp %d"%(fsid,
188+
resume_cmd = "recon-all -base %s -sd %s %s -parallel -openmp %d"%(fsid,
181189
output_dir,
182190
stages,
183191
args.n_cpus)
184-
192+
185193
if os.path.isfile(os.path.join(output_dir, fsid,"scripts/IsRunning.lh+rh")):
186194
rmtree(os.path.join(output_dir, fsid))
187195
print("DELETING OUTPUT SUBJECT DIR AND RE-RUNNING COMMAND:")
@@ -194,17 +202,17 @@ def run(command, env={}, ignore_errors=False):
194202
else:
195203
print(cmd)
196204
run(cmd)
197-
205+
198206
for tp in timepoints:
199207
# longitudinally process all timepoints
200208
fsid = "sub-%s"%subject_label
201209
stages = " ".join(["-" + stage for stage in args.stages])
202-
cmd = "recon-all -long %s %s -sd %s %s -openmp %d"%(tp,
210+
cmd = "recon-all -long %s %s -sd %s %s -parallel -openmp %d"%(tp,
203211
fsid,
204212
output_dir,
205213
stages,
206214
args.n_cpus)
207-
215+
208216
if os.path.isfile(os.path.join(output_dir, tp + ".long." + fsid,"scripts/IsRunning.lh+rh")):
209217
rmtree(os.path.join(output_dir, tp + ".long." + fsid))
210218
print("DELETING OUTPUT SUBJECT DIR AND RE-RUNNING COMMAND:")
@@ -213,11 +221,17 @@ def run(command, env={}, ignore_errors=False):
213221

214222
elif len(sessions) > 0 and longitudinal_study == False:
215223
# grab all T1s/T2s from multiple sessions and combine
216-
input_args = " ".join(["-i %s"%f for f in glob(os.path.join(args.bids_dir,
217-
"sub-%s"%subject_label,
218-
"ses-*",
219-
"anat",
220-
"%s_T1w.nii*"%acq_tpl))])
224+
T1s = glob(os.path.join(args.bids_dir,
225+
"sub-%s"%subject_label,
226+
"ses-*",
227+
"anat",
228+
"%s_T1w.nii*"%acq_tpl))
229+
input_args = ""
230+
for T1 in T1s:
231+
if (round(max(nibabel.load(T1).header.get_zooms()),1) < 1.0 and args.hires_mode == "auto") or args.hires_mode == "enable":
232+
input_args += " -hires"
233+
input_args += " -i %s"%T1
234+
221235
T2s = glob(os.path.join(args.bids_dir,
222236
"sub-%s"%subject_label,
223237
"ses-*",
@@ -237,16 +251,16 @@ def run(command, env={}, ignore_errors=False):
237251
for FLAIR in FLAIRs:
238252
if max(nibabel.load(FLAIR).header.get_zooms()) < 1.2:
239253
input_args += " " + " ".join(["-FLAIR %s"%FLAIR])
240-
input_args += " -FLAIRpial"
254+
input_args += " -FLAIRpial"
241255

242256
fsid = "sub-%s"%subject_label
243257
stages = " ".join(["-" + stage for stage in args.stages])
244-
cmd = "recon-all -subjid %s -sd %s %s %s -openmp %d"%(fsid,
258+
cmd = "recon-all -subjid %s -sd %s %s %s -parallel -openmp %d"%(fsid,
245259
output_dir,
246260
input_args,
247261
stages,
248262
args.n_cpus)
249-
resume_cmd = "recon-all -subjid %s -sd %s %s -openmp %d"%(fsid,
263+
resume_cmd = "recon-all -subjid %s -sd %s %s -parallel -openmp %d"%(fsid,
250264
output_dir,
251265
stages,
252266
args.n_cpus)
@@ -266,10 +280,15 @@ def run(command, env={}, ignore_errors=False):
266280

267281
else:
268282
# grab all T1s/T2s from single session (no ses-* directories)
269-
input_args = " ".join(["-i %s"%f for f in glob(os.path.join(args.bids_dir,
270-
"sub-%s"%subject_label,
271-
"anat",
272-
"%s_T1w.nii*"%acq_tpl))])
283+
T1s = glob(os.path.join(args.bids_dir,
284+
"sub-%s"%subject_label,
285+
"anat",
286+
"%s_T1w.nii*"%acq_tpl))
287+
input_args = ""
288+
for T1 in T1s:
289+
if (round(max(nibabel.load(T1).header.get_zooms()),1) < 1.0 and args.hires_mode == "auto") or args.hires_mode == "enable":
290+
input_args += " -hires"
291+
input_args += " -i %s"%T1
273292
T2s = glob(os.path.join(args.bids_dir, "sub-%s"%subject_label, "anat",
274293
"*_T2w.nii*"))
275294
FLAIRs = glob(os.path.join(args.bids_dir, "sub-%s"%subject_label, "anat",
@@ -283,16 +302,16 @@ def run(command, env={}, ignore_errors=False):
283302
for FLAIR in FLAIRs:
284303
if max(nibabel.load(FLAIR).header.get_zooms()) < 1.2:
285304
input_args += " " + " ".join(["-FLAIR %s"%FLAIR])
286-
input_args += " -FLAIRpial"
305+
input_args += " -FLAIRpial"
287306

288307
fsid = "sub-%s"%subject_label
289308
stages = " ".join(["-" + stage for stage in args.stages])
290-
cmd = "recon-all -subjid %s -sd %s %s %s -openmp %d"%(fsid,
309+
cmd = "recon-all -subjid %s -sd %s %s %s -parallel -openmp %d"%(fsid,
291310
output_dir,
292311
input_args,
293312
stages,
294313
args.n_cpus)
295-
resume_cmd = "recon-all -subjid %s -sd %s %s -openmp %d"%(fsid,
314+
resume_cmd = "recon-all -subjid %s -sd %s %s -parallel -openmp %d"%(fsid,
296315
output_dir,
297316
stages,
298317
args.n_cpus)
@@ -309,7 +328,7 @@ def run(command, env={}, ignore_errors=False):
309328
else:
310329
print(cmd)
311330
run(cmd)
312-
331+
313332
elif args.analysis_level == "group": # running group level
314333
if len(subjects_to_analyze) > 1:
315334
# generate study specific template

0 commit comments

Comments
 (0)