From f8972dac90f75d7e051723b19e6bb826f1cb696e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 15 Feb 2022 14:21:59 -0600
Subject: [PATCH 001/220] Initial recipe change to include FastSurfer (GPU)
support
Dockerfile building from a PyTorch base image to facilitate running FastSurfer (GPU). Testing this image for FastSurfer - once built as smriprep:fastsurfer_dev - can be performed with the following command:
docker run --gpus all --entrypoint /bin/bash -v /path/to/bids:/data -v /path/to/bids/derivatives/fastsurfer:/output -v /path/to/freesurfer/license:/fs60/license --rm --user `id -u` smriprep:fastsurfer_dev /opt/FastSurfer/run_fastsurfer.sh --fs_license /fs60/license --t1 /data/sourcedata/sub-SUBJECT/ses-SESSION/anat/sub-SUBJECT_ses-SESSION_T1w.nii.gz --sid sub-SUBJECT --sd /output
---
Dockerfile | 76 +++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 64 insertions(+), 12 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index d2d16dba1e..3f889f0c56 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -23,7 +23,19 @@
# SOFTWARE.
# Use Ubuntu 20.04 LTS
-FROM ubuntu:focal-20210416
+#FROM ubuntu:focal-20210416
+
+# Use pytorch official docker image
+FROM pytorch/pytorch:1.2-cuda10.0-cudnn7-runtime
+
+ENV CUDA_VERSION=10.0.130 \
+ CUDA_PKG_VERSION=10-0=10.0.130-1 \
+ NCCL_VERSION=2.4.8 \
+ CUDNN_VERSION=7.6.5.32 \
+ PYTHON_VERSION=3.6 \
+ DEBIAN_FRONTEND="noninteractive" \
+ LANG="C.UTF-8" \
+ LC_ALL="C.UTF-8"
# Prepare environment
RUN apt-get update && \
@@ -36,15 +48,25 @@ RUN apt-get update && \
curl \
git \
libtool \
+ wget \
lsb-release \
pkg-config \
unzip \
+ cmake \
+ gawk \
+ perl-modules \
+ tcsh \
+ time \
+ bzip2 \
+ libx11-6 \
+ libjpeg-dev \
+ bc \
+ libgomp1 \
+ libglu1-mesa \
+ libglu1-mesa-dev \
xvfb && \
- apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+ rm -rf /var/lib/apt/lists/*
-ENV DEBIAN_FRONTEND="noninteractive" \
- LANG="en_US.UTF-8" \
- LC_ALL="en_US.UTF-8"
# Installing freesurfer
RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1.tar.gz \
@@ -68,6 +90,25 @@ RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/frees
--exclude='freesurfer/subjects/V1_average' \
--exclude='freesurfer/trctrain'
+# Install miniconda and needed python packages (for FastSurferCNN)
+#RUN wget -qO ~/miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh && \
+# chmod +x ~/miniconda.sh && \
+# ~/miniconda.sh -b -p /opt/conda && \
+# rm ~/miniconda.sh && \
+RUN /opt/conda/bin/conda install python-dateutil pyyaml numpy scipy matplotlib h5py scikit-image && \
+ /opt/conda/bin/conda install -y -c pytorch cudatoolkit=10.0 "pytorch=1.2.0=py3.6_cuda10.0.130_cudnn7.6.2_0" torchvision=0.4.0 && \
+ /opt/conda/bin/conda install -c conda-forge scikit-sparse nibabel=2.5.1 pillow=8.3.2 && \
+ /opt/conda/bin/conda clean -ya
+ENV PATH /opt/conda/bin:$PATH
+
+# install LaPy for FastSurfer
+RUN python3.6 -m pip install -U git+https://github.com/Deep-MI/LaPy.git#egg=lapy
+
+# Add FastSurfer (copy application code) to docker image
+RUN cd /opt && git clone https://github.com/Deep-MI/FastSurfer.git
+ENV FASTSURFER_HOME=/opt/FastSurfer
+
+
# Simulate SetUpFreeSurfer.sh
ENV FSL_DIR="/opt/fsl-6.0.5.1" \
OS="Linux" \
@@ -166,12 +207,23 @@ ENV FSLDIR="/opt/fsl-6.0.5.1" \
FSLREMOTECALL="" \
FSLGECUDAQ="cuda.q" \
LD_LIBRARY_PATH="/opt/fsl-6.0.5.1/lib:$LD_LIBRARY_PATH"
+# switch back to en-US utf-8
+RUN apt-get update -qq && apt-get install locales && \
+ sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
+ locale-gen
+ENV LANG="en_US.UTF-8" \
+ LC_ALL="en_US.UTF-8" \
+ LANGUAGE="en_US:en"
+RUN ls /etc/ssl/certs/
-# Convert3D (neurodocker build)
-RUN echo "Downloading Convert3D ..." \
- && mkdir -p /opt/convert3d-1.0.0 \
- && curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz/download \
- | tar -xz -C /opt/convert3d-1.0.0 --strip-components 1 \
+
+# Convert3D (neurodocker build) - adapted to allow for local copy of Convert3D
+# my build machine was giving ca-certificates errors for fetching C3D from sourceforge in build
+#RUN echo "Downloading Convert3D ..." \
+# && mkdir -p /opt/convert3d-1.0.0 \
+# && cd /opt/ && curl -fsSL https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz \
+COPY c3d-1.0.0-Linux-x86_64.tar.gz /opt/c3d-1.0.0-Linux-x86_64.tar.gz
+RUN cd /opt/ && mkdir -p /opt/convert3d-1.0.0 && tar -xzf c3d-1.0.0-Linux-x86_64.tar.gz -C /opt/convert3d-1.0.0 --strip-components 1 \
--exclude "c3d-1.0.0-Linux-x86_64/lib" \
--exclude "c3d-1.0.0-Linux-x86_64/share" \
--exclude "c3d-1.0.0-Linux-x86_64/bin/c3d_gui"
@@ -194,7 +246,7 @@ RUN apt-get update -qq \
tcsh \
xfonts-base \
xvfb \
- && apt-get clean \
+ && apt-get clean -y \
&& rm -rf /var/lib/apt/lists/* \
&& curl -sSL --retry 5 -o /tmp/multiarch.deb http://archive.ubuntu.com/ubuntu/pool/main/g/glibc/multiarch-support_2.27-3ubuntu1.2_amd64.deb \
&& dpkg -i /tmp/multiarch.deb \
@@ -205,7 +257,7 @@ RUN apt-get update -qq \
&& curl -sSL --retry 5 -o /tmp/libpng.deb http://snapshot.debian.org/archive/debian-security/20160113T213056Z/pool/updates/main/libp/libpng/libpng12-0_1.2.49-1%2Bdeb7u2_amd64.deb \
&& dpkg -i /tmp/libpng.deb \
&& rm /tmp/libpng.deb \
- && apt-get install -f \
+ && apt-get install -f -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& gsl2_path="$(find / -name 'libgsl.so.19' || printf '')" \
From 1377f4c629542ba8d3ab11f90b9c593ffa29b6cc Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 20 Apr 2022 15:57:11 -0500
Subject: [PATCH 002/220] Added function to test for FastSurfer files in
--fs-subjects-dir
Checks FreeSurfer subjects dir for presence of files in mri/ with names indicating processing with FastSurfer, and returns a boolean fastsurfer_bool to indicate that FastSurfer is being used instead of Freesurfer. For development purposes, this also touches files that are expected outputs of Freesurfer, but not produced by default in FastSurfer. (Addresses #278 & https://github.com/Deep-MI/FastSurfer/issues/21)
---
smriprep/utils/misc.py | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/smriprep/utils/misc.py b/smriprep/utils/misc.py
index 99d1458866..a0988269af 100644
--- a/smriprep/utils/misc.py
+++ b/smriprep/utils/misc.py
@@ -95,3 +95,44 @@ def fs_isRunning(subjects_dir, subject_id, mtime_tol=86400, logger=None):
if logger:
logger.warn(f'Removed "IsRunning*" files found under {subj_dir}')
return subjects_dir
+
+def check_fastsurfer(subjects_dir, subject_id):
+ """
+ Checks FreeSurfer subjects dir for presence of files in mri/ with names indicating processing with FastSurfer,
+ and returns a boolean fastsurfer_bool to indicate that FastSurfer is being used instead of Freesurfer.
+
+ For development purposes, this also touches files that are expected outputs of Freesurfer,
+ but not produced by default in FastSurfer.
+
+ Parameters
+ ----------
+ subjects_dir : os.PathLike or None
+ Existing FreeSurfer subjects directory
+ subject_id : str
+ Subject label
+
+ Returns
+ -------
+ fastsurfer_bool : Boolean
+ subjects_dir : os.PathLike or None
+
+
+ """
+ from pathlib import Path
+
+ if subjects_dir is None:
+ return subjects_dir
+ subj_dir = Path(subjects_dir) / subject_id
+ if not subj_dir.exists():
+
+ return subjects_dir
+
+ fastsurferfiles = tuple(subj_dir.glob("mri/*deep*mgz"))
+ if not fastsurferfiles:
+ fastsurfer_bool = False
+ return fastsurfer_bool, subjects_dir
+ else:
+ fastsurfer_bool = True
+ noCCseglabel = Path(subj_dir / 'mri/aseg.auto_noCCseg.label_intensities.txt')
+ noCCseglabel.touch(exist_ok=False)
+ return fastsurfer_bool, subjects_dir
From 9b6251ff4f1c71f80b80a24a40651cb09a93fd38 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 23 Apr 2022 17:30:49 -0500
Subject: [PATCH 003/220] Add logger for FastSurfer check
Add logger for the check_fastsurfer function to indicate if evidence of FastSurfer surface recon was used to generate the given subjects_dir
---
smriprep/utils/misc.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/smriprep/utils/misc.py b/smriprep/utils/misc.py
index a0988269af..a4d234e202 100644
--- a/smriprep/utils/misc.py
+++ b/smriprep/utils/misc.py
@@ -96,7 +96,7 @@ def fs_isRunning(subjects_dir, subject_id, mtime_tol=86400, logger=None):
logger.warn(f'Removed "IsRunning*" files found under {subj_dir}')
return subjects_dir
-def check_fastsurfer(subjects_dir, subject_id):
+def check_fastsurfer(subjects_dir, subject_id, logger=None):
"""
Checks FreeSurfer subjects dir for presence of files in mri/ with names indicating processing with FastSurfer,
and returns a boolean fastsurfer_bool to indicate that FastSurfer is being used instead of Freesurfer.
@@ -133,6 +133,8 @@ def check_fastsurfer(subjects_dir, subject_id):
return fastsurfer_bool, subjects_dir
else:
fastsurfer_bool = True
+ if logger:
+ logger.warn(f'Evidence of FastSurfer processing found in {subj_dir}')
noCCseglabel = Path(subj_dir / 'mri/aseg.auto_noCCseg.label_intensities.txt')
noCCseglabel.touch(exist_ok=False)
return fastsurfer_bool, subjects_dir
From f301f3ab0d1e037b85625d125db01b95df40f096 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 23 Apr 2022 18:42:55 -0500
Subject: [PATCH 004/220] Add quick fix check for FastSurfer
Adds the check_fastsurfer function call to log FastSurfer outputs detected in subjects_dir and touch mri/aseg.auto_noCCseg.label_intensities.txt to prevent failure in surfaces.py as a temporary fix for https://github.com/nipreps/smriprep/issues/278
---
smriprep/workflows/anatomical.py | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index f0ae4da2e4..f3ba1b400a 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -47,7 +47,7 @@
from niworkflows.utils.misc import fix_multi_T1w_source_name, add_suffix
from niworkflows.anat.ants import init_brain_extraction_wf, init_n4_only_wf
from ..utils.bids import get_outputnode_spec
-from ..utils.misc import apply_lut as _apply_bids_lut, fs_isRunning as _fs_isRunning
+from ..utils.misc import apply_lut as _apply_bids_lut, fs_isRunning as _fs_isRunning, check_fastsurfer as _check_fastsurfer
from .norm import init_anat_norm_wf
from .outputs import init_anat_reports_wf, init_anat_derivatives_wf
from .surfaces import init_surface_recon_wf
@@ -514,7 +514,14 @@ def _check_img(img):
niu.Function(function=_fs_isRunning), overwrite=True, name="fs_isrunning"
)
fs_isrunning.inputs.logger = LOGGER
-
+
+ # check for FastSurfer .mgz files and
+ # touch mri/aseg.auto_noCCseg.label_intensities.txt to prevent failure in surfaces.py (temporary fix)
+ check_fastsurfer = pe.Node(
+ niu.Function(function=_check_fastsurfer), overwrite=True, name="check_fastsurfer"
+ )
+ check_fastsurfer.inputs.logger = LOGGER
+
# 5. Surface reconstruction (--fs-no-reconall not set)
surface_recon_wf = init_surface_recon_wf(
name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires
@@ -522,6 +529,9 @@ def _check_img(img):
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
# fmt:off
workflow.connect([
+ (inputnode, check_fastsurfer, [
+ ('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id')]),
(inputnode, fs_isrunning, [
('subjects_dir', 'subjects_dir'),
('subject_id', 'subject_id')]),
From f90738a8915527594d386b1c87a4e9e3de29aeec Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 23 Apr 2022 18:43:37 -0500
Subject: [PATCH 005/220] Removes fastsurfer_bool
Removes currently unused fastsurfer_bool variable
---
smriprep/utils/misc.py | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/smriprep/utils/misc.py b/smriprep/utils/misc.py
index a4d234e202..e35a15131d 100644
--- a/smriprep/utils/misc.py
+++ b/smriprep/utils/misc.py
@@ -99,10 +99,7 @@ def fs_isRunning(subjects_dir, subject_id, mtime_tol=86400, logger=None):
def check_fastsurfer(subjects_dir, subject_id, logger=None):
"""
Checks FreeSurfer subjects dir for presence of files in mri/ with names indicating processing with FastSurfer,
- and returns a boolean fastsurfer_bool to indicate that FastSurfer is being used instead of Freesurfer.
-
- For development purposes, this also touches files that are expected outputs of Freesurfer,
- but not produced by default in FastSurfer.
+ this also touches files that are expected outputs of Freesurfer, but not produced by default in FastSurfer.
Parameters
----------
@@ -113,7 +110,6 @@ def check_fastsurfer(subjects_dir, subject_id, logger=None):
Returns
-------
- fastsurfer_bool : Boolean
subjects_dir : os.PathLike or None
@@ -124,17 +120,16 @@ def check_fastsurfer(subjects_dir, subject_id, logger=None):
return subjects_dir
subj_dir = Path(subjects_dir) / subject_id
if not subj_dir.exists():
-
return subjects_dir
fastsurferfiles = tuple(subj_dir.glob("mri/*deep*mgz"))
if not fastsurferfiles:
fastsurfer_bool = False
- return fastsurfer_bool, subjects_dir
+ return subjects_dir
else:
fastsurfer_bool = True
if logger:
logger.warn(f'Evidence of FastSurfer processing found in {subj_dir}')
noCCseglabel = Path(subj_dir / 'mri/aseg.auto_noCCseg.label_intensities.txt')
noCCseglabel.touch(exist_ok=False)
- return fastsurfer_bool, subjects_dir
+ return subjects_dir
From 42e6456d753c8cf0561ad5d4d93a2c56777c8d8d Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 23 Apr 2022 19:12:22 -0500
Subject: [PATCH 006/220] Add FastSurfer argument to
Adds FastSurfer argument to support FastSurfer as a surface processing option (https://github.com/nipreps/smriprep/issues/278)
---
smriprep/cli/run.py | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 4a588283f8..a03cb1f489 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -222,6 +222,14 @@ def get_parser():
dest="hires",
help="disable sub-millimeter (hires) reconstruction",
)
+
+ g_surfs_xor.add_argument(
+ "--fastsurfer-recon",
+ action="store_true",
+ dest="run_fastsurfer",
+ help="enable FastSurfer surface preprocessing.",
+ )
+
g_surfs_xor = g_surfs.add_mutually_exclusive_group()
g_surfs_xor.add_argument(
@@ -394,6 +402,17 @@ def _warn_redirect(message, category, filename, lineno, file=None, line=None):
from templateflow import api
from niworkflows.utils.misc import _copy_any
+ dseg_tsv = str(api.get("fsaverage", suffix="dseg", extension=[".tsv"]))
+ _copy_any(
+ dseg_tsv, str(Path(output_dir) / "smriprep" / "desc-aseg_dseg.tsv")
+ )
+ _copy_any(
+ dseg_tsv, str(Path(output_dir) / "smriprep" / "desc-aparcaseg_dseg.tsv")
+ )
+ elif opts.run_fastsurfer:
+ from templateflow import api
+ from niworkflows.utils.misc import _copy_any
+
dseg_tsv = str(api.get("fsaverage", suffix="dseg", extension=[".tsv"]))
_copy_any(
dseg_tsv, str(Path(output_dir) / "smriprep" / "desc-aseg_dseg.tsv")
@@ -584,6 +603,7 @@ def build_workflow(opts, retval):
freesurfer=opts.run_reconall,
fs_subjects_dir=opts.fs_subjects_dir,
hires=opts.hires,
+ fastsurfer=opts.run_fastsurfer,
layout=layout,
longitudinal=opts.longitudinal,
low_mem=opts.low_mem,
From 7502350e47f5a61378390979cf35cc9843010b7c Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 24 Apr 2022 16:58:43 -0500
Subject: [PATCH 007/220] Add FastSurfer citations
Add citations for FastSurfer: 1mm isotropic original paper = fastsurfer, 2022 hires version (NOT YET IMPLEMENTED) = fastsurfer_hires
---
smriprep/data/boilerplate.bib | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/smriprep/data/boilerplate.bib b/smriprep/data/boilerplate.bib
index 76e67fa503..1bf8286e0c 100644
--- a/smriprep/data/boilerplate.bib
+++ b/smriprep/data/boilerplate.bib
@@ -62,6 +62,34 @@ @article{fs_reconall
year = 1999
}
+@article{fastsurfer,
+title = {FastSurfer - A fast and accurate deep learning based neuroimaging pipeline},
+journal = {NeuroImage},
+volume = {219},
+pages = {117012},
+year = {2020},
+issn = {1053-8119},
+doi = {https://doi.org/10.1016/j.neuroimage.2020.117012},
+url = {https://www.sciencedirect.com/science/article/pii/S1053811920304985},
+author = {Leonie Henschel and Sailesh Conjeti and Santiago Estrada and Kersten Diers and Bruce Fischl and Martin Reuter},
+keywords = {Freesurfer, Computational neuroimaging, Deep learning, Structural MRI, Artificial intelligence},
+abstract = {Traditional neuroimage analysis pipelines involve computationally intensive, time-consuming optimization steps, and thus, do not scale well to large cohort studies with thousands or tens of thousands of individuals. In this work we propose a fast and accurate deep learning based neuroimaging pipeline for the automated processing of structural human brain MRI scans, replicating FreeSurfer’s anatomical segmentation including surface reconstruction and cortical parcellation. To this end, we introduce an advanced deep learning architecture capable of whole-brain segmentation into 95 classes. The network architecture incorporates local and global competition via competitive dense blocks and competitive skip pathways, as well as multi-slice information aggregation that specifically tailor network performance towards accurate segmentation of both cortical and subcortical structures. Further, we perform fast cortical surface reconstruction and thickness analysis by introducing a spectral spherical embedding and by directly mapping the cortical labels from the image to the surface. This approach provides a full FreeSurfer alternative for volumetric analysis (in under 1 min) and surface-based thickness analysis (within only around 1 h runtime). For sustainability of this approach we perform extensive validation: we assert high segmentation accuracy on several unseen datasets, measure generalizability and demonstrate increased test-retest reliability, and high sensitivity to group differences in dementia.}
+}
+
+@article{fastsufrer_hires,
+title = {FastSurferVINN: Building resolution-independence into deep learning segmentation methods—A solution for HighRes brain MRI},
+journal = {NeuroImage},
+volume = {251},
+pages = {118933},
+year = {2022},
+issn = {1053-8119},
+doi = {https://doi.org/10.1016/j.neuroimage.2022.118933},
+url = {https://www.sciencedirect.com/science/article/pii/S1053811922000623},
+author = {Leonie Henschel and David Kügler and Martin Reuter},
+keywords = {Computational neuroimaging, Deep learning, Structural MRI, Artificial intelligence, High-resolution},
+abstract = {Leading neuroimaging studies have pushed 3T MRI acquisition resolutions below 1.0 mm for improved structure definition and morphometry. Yet, only few, time-intensive automated image analysis pipelines have been validated for high-resolution (HiRes) settings. Efficient deep learning approaches, on the other hand, rarely support more than one fixed resolution (usually 1.0 mm). Furthermore, the lack of a standard submillimeter resolution as well as limited availability of diverse HiRes data with sufficient coverage of scanner, age, diseases, or genetic variance poses additional, unsolved challenges for training HiRes networks. Incorporating resolution-independence into deep learning-based segmentation, i.e., the ability to segment images at their native resolution across a range of different voxel sizes, promises to overcome these challenges, yet no such approach currently exists. We now fill this gap by introducing a Voxel-size Independent Neural Network (VINN) for resolution-independent segmentation tasks and present FastSurferVINN, which (i) establishes and implements resolution-independence for deep learning as the first method simultaneously supporting 0.7–1.0 mm whole brain segmentation, (ii) significantly outperforms state-of-the-art methods across resolutions, and (iii) mitigates the data imbalance problem present in HiRes datasets. Overall, internal resolution-independence mutually benefits both HiRes and 1.0 mm MRI segmentation. With our rigorously validated FastSurferVINN we distribute a rapid tool for morphometric neuroimage analysis. The VINN architecture, furthermore, represents an efficient resolution-independent segmentation method for wider application.}
+}
+
@article{mindboggle,
author = {Klein, Arno and Ghosh, Satrajit S. and Bao, Forrest S. and Giard, Joachim and Häme, Yrjö and Stavsky, Eliezer and Lee, Noah and Rossa, Brian and Reuter, Martin and Neto, Elias Chaibub and Keshavan, Anisha},
doi = {10.1371/journal.pcbi.1005350},
From 4cf37e55bdb667f82dc6e04c19eb92dc8192d2a6 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 24 Apr 2022 17:08:30 -0500
Subject: [PATCH 008/220] Add FastSurfer
---
docs/installation.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/installation.rst b/docs/installation.rst
index a4c6d204b1..792763546d 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -150,3 +150,4 @@ the ``smriprep`` package:
- `C3D `_ (version 1.0.0)
- FreeSurfer_ (version 6.0.1)
- `bids-validator `_ (version 1.1.0)
+- FastSurfer_ (version 1.0.1)
From c8d0493dd8748aa6dcb7eb4270d5a384f1fc7fe5 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 25 Apr 2022 21:31:52 -0500
Subject: [PATCH 009/220] Add FastSurfer python wrapper
Adds python wrapper for FastSurfer (https://github.com/nipreps/smriprep/issues/278)
---
smriprep/interfaces/fastsurfer.py | 104 ++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
create mode 100644 smriprep/interfaces/fastsurfer.py
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
new file mode 100644
index 0000000000..dda5c36817
--- /dev/null
+++ b/smriprep/interfaces/fastsurfer.py
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
+# vi: set ft=python sts=4 ts=4 sw=4 et:
+"""The FastSufer module provides basic functions for running FastSurfer CNN
+and surface processing.
+
+Examples
+--------
+See the docstrings for the individual classes for 'working' examples.
+
+"""
+from ast import BoolOp
+from genericpath import exists
+import os
+from xmlrpc.client import Boolean
+
+from nipype.interfaces.base import (
+ CommandLine,
+ Directory,
+ CommandLineInputSpec,
+ isdefined,
+ TraitedSpec,
+ File,
+ PackageInfo,
+)
+from nipype.interfaces.base.traits_extension import traits
+__docformat__ = "restructuredtext"
+
+class FastSInputSpec(CommandLineInputSpec):
+ """
+ Required arguments
+ ------------------
+ --sd: Output directory $SUBJECTS_DIR (equivalent to FreeSurfer setup --> $SUBJECTS_DIR/sid/mri; $SUBJECTS_DIR/sid/surf ... will be created).
+ --sid: Subject ID for directory inside $SUBJECTS_DIR to be created ($SUBJECTS_DIR/sid/...)
+ --t1: T1 full head input (not bias corrected, global path). The network was trained with conformed images (UCHAR, 256x256x256, 1 mm voxels and standard slice orientation). These specifications are checked in the eval.py script and the image is automatically conformed if it does not comply.
+ --fs_license: Path to FreeSurfer license key file. Register (for free) at https://surfer.nmr.mgh.harvard.edu/registration.html to obtain it if you do not have FreeSurfer installed so far. Strictly necessary if you use Docker, optional for local install (your local FreeSurfer license will automatically be used)
+
+ Optional arguments
+ ------------------
+
+ Network specific arguments:
+ --seg: Global path with filename of segmentation (where and under which name to store it). Default location: $SUBJECTS_DIR/$sid/mri/aparc.DKTatlas+aseg.deep.mgz
+ --weights_sag: Pretrained weights of sagittal network. Default: ../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ --weights_ax: Pretrained weights of axial network. Default: ../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ --weights_cor: Pretrained weights of coronal network. Default: ../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ --seg_log: Name and location for the log-file for the segmentation (FastSurferCNN). Default: $SUBJECTS_DIR/$sid/scripts/deep-seg.log
+ --clean_seg: Flag to clean up FastSurferCNN segmentation
+ --run_viewagg_on: Define where the view aggregation should be run on. By default, the program checks if you have enough memory to run the view aggregation on the gpu. The total memory is considered for this decision. If this fails, or you actively overwrote the check with setting "--run_viewagg_on cpu", view agg is run on the cpu. Equivalently, if you define "--run_viewagg_on gpu", view agg will be run on the gpu (no memory check will be done).
+ --no_cuda: Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)
+ --batch: Batch size for inference. Default: 16. Lower this to reduce memory requirement
+ --order: Order of interpolation for mri_convert T1 before segmentation (0=nearest, 1=linear(default), 2=quadratic, 3=cubic)
+
+ Surface pipeline arguments:
+ --fstess: Use mri_tesselate instead of marching cube (default) for surface creation
+ --fsqsphere: Use FreeSurfer default instead of novel spectral spherical projection for qsphere
+ --fsaparc: Use FS aparc segmentations in addition to DL prediction (slower in this case and usually the mapped ones from the DL prediction are fine)
+ --surfreg: Create Surface-Atlas (sphere.reg) registration with FreeSurfer (for cross-subject correspondence or other mappings)
+ --parallel: Run both hemispheres in parallel
+ --threads: Set openMP and ITK threads to
+
+ Other:
+ --py: which python version to use. Default: python3.6
+ --seg_only: only run FastSurferCNN (generate segmentation, do not run the surface pipeline)
+ --surf_only: only run the surface pipeline recon_surf. The segmentation created by FastSurferCNN must already exist in this case.
+ """
+ sd = Directory(exists=True, argstr="--sd %s", mandatory=True, desc="Subjects directory")
+ sid = traits.String(exists=True, argstr="--sid %s", mandatory=True, desc="Subject ID")
+ t1 = File(exists=True, mandatory=True, argstr="--t1 %s", desc="T1 full head input (not bias corrected, global path)")
+ fs_license = File(exists=True, mandatory=True, argstr="--fs_license %s", desc="Path to FreeSurfer license key file. Register (for free) at https://surfer.nmr.mgh.harvard.edu/registration.html to obtain it if you do not have FreeSurfer installed so far.")
+ seg = File(exists=True, mandatory=False, argstr="--seg %s", desc="Global path with filename of segmentation (where and under which name to store it)")
+ weights_sag = File(exists=True, mandatory=False, default="../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl", usedefault=False, argstr="--weights_sag %s", desc="Pretrained weights of sagittal network")
+ weights_ax = File(exists=True, mandatory=False, default="../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl", usedefault=False, argstr="--weights_ax %s", desc="Pretrained weights of axial network",)
+ weights_cor = File(exists=True, mandatory=False, default="../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl", usedefault=False, argstr="--weights_cor %s", desc="Pretrained weights of coronal network")
+ seg_log = File(exists=True, mandatory=False, argstr="--seg_log %s", desc="Name and location for the log-file for the segmentation (FastSurferCNN).")
+ clean_seg = traits.Bool(False,mandatory=False, usedefault=False, argstr="--clean_seg", desc="Flag to clean up FastSurferCNN segmentation")
+ run_viewagg_on = File(exists=True, mandatory=False, argstr="--run_viewagg_on %s", desc="Define where the view aggregation should be run on. ")
+ no_cuda = traits.Bool(False,mandatory=False, usedefault=False, argstr="--no_cuda", desc="Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)")
+ batch = traits.Int(16, usedefault=True, mandatory=False, argstr="--batch %d", desc="Batch size for inference. default=16. Lower this to reduce memory requirement")
+ order = traits.Int(1, mandatory=False, argstr = "--order %d", usedefault=True, desc="Order of interpolation for mri_convert T1 before segmentation (0=nearest, 1=linear(default), 2=quadratic, 3=cubic)")
+ fstess = traits.Bool(False, usedefault=False, mandatory=False, argstr="--fstess", desc="Use mri_tesselate instead of marching cube (default) for surface creation")
+ fsqsphere = traits.Bool(False, usedefault=False, mandatory=False, argstr="--fsqsphere", desc="Use FreeSurfer default instead of novel spectral spherical projection for qsphere")
+ fsaparc = traits.Bool(False, usedefault=False, mandatory=False, argstr="--fsaparc", desc="Use FS aparc segmentations in addition to DL prediction (slower in this case and usually the mapped ones from the DL prediction are fine)")
+ surfreg = traits.Bool(True, usedefault=True, mandatory=False, argstr="--surfreg", desc="Create Surface-Atlas (sphere.reg) registration with FreeSurfer (for cross-subject correspondence or other mappings)")
+ parallel = traits.Bool(True, usedefault=True, mandatory=False, argstr="--parallel", desc="Run both hemispheres in parallel")
+ threads = traits.Int(4, usedefault=True, mandatory=False, argstr="--threads %d", desc="Set openMP and ITK threads to")
+ py = traits.String("python3.6", usedefault=True, mandatory=False, argstr="--py %s", desc="which python version to use. default=python3.6")
+ seg_only = traits.Bool(False, usedefault=False, mandatory=False, argstr="--seg_only", desc="only run FastSurferCNN (generate segmentation, do not run the surface pipeline)")
+ surf_only = traits.Bool(False, usedefault=False, mandatory=False, argstr="--surf_only", desc="only run the surface pipeline recon_surf. The segmentation created by FastSurferCNN must already exist in this case.")
+
+class FastSTraitedOutputSpec(TraitedSpec):
+ """
+ Outputs directory within the FastSurfer subjects_dir/subject_id/ with structure equivalent to Freesurfer
+ """
+ outputs = Directory(exists=True, desc="FastSurfer CNN (or VINN when added) + Surface Pipeline equivalent of the Freesurfer recon-all outputs")
+
+class FastSCommand(CommandLine):
+ input_spec = FastSInputSpec
+ output_spec = FastSTraitedOutputSpec
+ _cmd = '/opt/FastSurfer/run_fastsurfer.sh'
+
+ def _list_outputs(self):
+ outputs = self.output_spec().get()
+ return outputs
+
\ No newline at end of file
From 3169bc7d2b21732ba7c1d55697a173f9058c2b9d Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 25 Apr 2022 21:43:45 -0500
Subject: [PATCH 010/220] Update .zenodo.json
Adds affiliation to contributors for work regarding https://github.com/nipreps/smriprep/issues/278
---
.zenodo.json | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/.zenodo.json b/.zenodo.json
index 391b6dad6d..9061e4c9b8 100644
--- a/.zenodo.json
+++ b/.zenodo.json
@@ -46,6 +46,11 @@
"name": "Ghosh, Satrajit",
"orcid": "0000-0002-5312-6729",
"type": "Researcher"
+ },
+
+ "affiliation": "Beckman Institute for Advanced Science & Technology, University of Illinois at Urbana-Champaign, IL, USA",
+ "name": "Camacho, Paul B.",
+ "orcid": "0000-0001-9048-7307"
}
],
"keywords": [
From d5969558213611e20a893d6c3dc3111d88bcfe44 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 25 Apr 2022 21:44:15 -0500
Subject: [PATCH 011/220] Fix typo
Fix typo
---
.zenodo.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.zenodo.json b/.zenodo.json
index 9061e4c9b8..1a9312312a 100644
--- a/.zenodo.json
+++ b/.zenodo.json
@@ -47,7 +47,7 @@
"orcid": "0000-0002-5312-6729",
"type": "Researcher"
},
-
+ {
"affiliation": "Beckman Institute for Advanced Science & Technology, University of Illinois at Urbana-Champaign, IL, USA",
"name": "Camacho, Paul B.",
"orcid": "0000-0001-9048-7307"
From 8feb1725b195fd81ac2dbd68915942ce2e5dc51d Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 16:48:26 -0500
Subject: [PATCH 012/220] Removes fastsurfer_bool for Flake8 check
---
smriprep/utils/misc.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/smriprep/utils/misc.py b/smriprep/utils/misc.py
index e35a15131d..5418b47f81 100644
--- a/smriprep/utils/misc.py
+++ b/smriprep/utils/misc.py
@@ -124,10 +124,8 @@ def check_fastsurfer(subjects_dir, subject_id, logger=None):
fastsurferfiles = tuple(subj_dir.glob("mri/*deep*mgz"))
if not fastsurferfiles:
- fastsurfer_bool = False
return subjects_dir
else:
- fastsurfer_bool = True
if logger:
logger.warn(f'Evidence of FastSurfer processing found in {subj_dir}')
noCCseglabel = Path(subj_dir / 'mri/aseg.auto_noCCseg.label_intensities.txt')
From 94f962ab4020295bcb7f96572f0b269f8c678cd4 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 16:56:53 -0500
Subject: [PATCH 013/220] Update misc.py
---
smriprep/utils/misc.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/smriprep/utils/misc.py b/smriprep/utils/misc.py
index 5418b47f81..14a0cac985 100644
--- a/smriprep/utils/misc.py
+++ b/smriprep/utils/misc.py
@@ -112,16 +112,15 @@ def check_fastsurfer(subjects_dir, subject_id, logger=None):
-------
subjects_dir : os.PathLike or None
-
"""
from pathlib import Path
-
+
if subjects_dir is None:
return subjects_dir
subj_dir = Path(subjects_dir) / subject_id
if not subj_dir.exists():
return subjects_dir
-
+
fastsurferfiles = tuple(subj_dir.glob("mri/*deep*mgz"))
if not fastsurferfiles:
return subjects_dir
From 94d952a317c70ce3202203ca4f15c543bcb67e17 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 16:57:39 -0500
Subject: [PATCH 014/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index dda5c36817..42aba765aa 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -37,7 +37,6 @@ class FastSInputSpec(CommandLineInputSpec):
Optional arguments
------------------
-
Network specific arguments:
--seg: Global path with filename of segmentation (where and under which name to store it). Default location: $SUBJECTS_DIR/$sid/mri/aparc.DKTatlas+aseg.deep.mgz
--weights_sag: Pretrained weights of sagittal network. Default: ../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
@@ -101,4 +100,4 @@ class FastSCommand(CommandLine):
def _list_outputs(self):
outputs = self.output_spec().get()
return outputs
-
\ No newline at end of file
+
From 7f9fe47584e0f6443a966af4aeb7ef7b8a234aaf Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 16:59:00 -0500
Subject: [PATCH 015/220] Update anatomical.py
---
smriprep/workflows/anatomical.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index f3ba1b400a..1227dc6131 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -516,7 +516,8 @@ def _check_img(img):
fs_isrunning.inputs.logger = LOGGER
# check for FastSurfer .mgz files and
- # touch mri/aseg.auto_noCCseg.label_intensities.txt to prevent failure in surfaces.py (temporary fix)
+ # touch mri/aseg.auto_noCCseg.label_intensities.txt
+ # to prevent failure in surfaces.py (temporary fix)
check_fastsurfer = pe.Node(
niu.Function(function=_check_fastsurfer), overwrite=True, name="check_fastsurfer"
)
From 55ea6b0ed25b49fd67f7b00200adccb08c0edfc5 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 17:00:04 -0500
Subject: [PATCH 016/220] Update .zenodo.json
Add researcher type
---
.zenodo.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.zenodo.json b/.zenodo.json
index 1a9312312a..2d106a019d 100644
--- a/.zenodo.json
+++ b/.zenodo.json
@@ -50,7 +50,8 @@
{
"affiliation": "Beckman Institute for Advanced Science & Technology, University of Illinois at Urbana-Champaign, IL, USA",
"name": "Camacho, Paul B.",
- "orcid": "0000-0001-9048-7307"
+ "orcid": "0000-0001-9048-7307",
+ "type": "Researcher"
}
],
"keywords": [
From 4c6828afa294707e3a7de5b2939e8df447b03555 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 17:01:40 -0500
Subject: [PATCH 017/220] Update run.py
Address PEP8 blankspaces flag
---
smriprep/cli/run.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index a03cb1f489..223fdc071d 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -222,14 +222,12 @@ def get_parser():
dest="hires",
help="disable sub-millimeter (hires) reconstruction",
)
-
g_surfs_xor.add_argument(
"--fastsurfer-recon",
action="store_true",
dest="run_fastsurfer",
help="enable FastSurfer surface preprocessing.",
)
-
g_surfs_xor = g_surfs.add_mutually_exclusive_group()
g_surfs_xor.add_argument(
From c77ed1de6bed9ee134f78c0ae390503e42ec833b Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 17:03:50 -0500
Subject: [PATCH 018/220] Update misc.py
Address PEP8
---
smriprep/utils/misc.py | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/smriprep/utils/misc.py b/smriprep/utils/misc.py
index 14a0cac985..2b16fb57fa 100644
--- a/smriprep/utils/misc.py
+++ b/smriprep/utils/misc.py
@@ -96,10 +96,12 @@ def fs_isRunning(subjects_dir, subject_id, mtime_tol=86400, logger=None):
logger.warn(f'Removed "IsRunning*" files found under {subj_dir}')
return subjects_dir
+
def check_fastsurfer(subjects_dir, subject_id, logger=None):
"""
- Checks FreeSurfer subjects dir for presence of files in mri/ with names indicating processing with FastSurfer,
- this also touches files that are expected outputs of Freesurfer, but not produced by default in FastSurfer.
+ Checks FreeSurfer subjects dir for presence of files in mri/ with names \
+ indicating processing with FastSurfer, this also touches files that are \
+ expected outputs of Freesurfer, but not produced by default in FastSurfer.
Parameters
----------
@@ -114,13 +116,13 @@ def check_fastsurfer(subjects_dir, subject_id, logger=None):
"""
from pathlib import Path
-
+
if subjects_dir is None:
return subjects_dir
subj_dir = Path(subjects_dir) / subject_id
if not subj_dir.exists():
return subjects_dir
-
+
fastsurferfiles = tuple(subj_dir.glob("mri/*deep*mgz"))
if not fastsurferfiles:
return subjects_dir
From 595b0010ee8cdd9d9572fe6c12e132f030e44424 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 17:06:13 -0500
Subject: [PATCH 019/220] Address PEP8
Address PEP8
---
smriprep/workflows/anatomical.py | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 1227dc6131..b7b35ac3d9 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -47,7 +47,11 @@
from niworkflows.utils.misc import fix_multi_T1w_source_name, add_suffix
from niworkflows.anat.ants import init_brain_extraction_wf, init_n4_only_wf
from ..utils.bids import get_outputnode_spec
-from ..utils.misc import apply_lut as _apply_bids_lut, fs_isRunning as _fs_isRunning, check_fastsurfer as _check_fastsurfer
+from ..utils.misc import (
+ apply_lut as _apply_bids_lut,
+ fs_isRunning as _fs_isRunning,
+ check_fastsurfer as _check_fastsurfer
+)
from .norm import init_anat_norm_wf
from .outputs import init_anat_reports_wf, init_anat_derivatives_wf
from .surfaces import init_surface_recon_wf
@@ -514,15 +518,15 @@ def _check_img(img):
niu.Function(function=_fs_isRunning), overwrite=True, name="fs_isrunning"
)
fs_isrunning.inputs.logger = LOGGER
-
- # check for FastSurfer .mgz files and
+
+ # check for FastSurfer .mgz files and
# touch mri/aseg.auto_noCCseg.label_intensities.txt
# to prevent failure in surfaces.py (temporary fix)
check_fastsurfer = pe.Node(
niu.Function(function=_check_fastsurfer), overwrite=True, name="check_fastsurfer"
)
check_fastsurfer.inputs.logger = LOGGER
-
+
# 5. Surface reconstruction (--fs-no-reconall not set)
surface_recon_wf = init_surface_recon_wf(
name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires
From 86edc276eed14a80a522f64c6e07a21e257c3a6f Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 17:24:26 -0500
Subject: [PATCH 020/220] Update formatting for PEP8 compliance
---
smriprep/interfaces/fastsurfer.py | 254 ++++++++++++++++++++++++------
1 file changed, 210 insertions(+), 44 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 42aba765aa..2c9267c937 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
-"""The FastSufer module provides basic functions for running FastSurfer CNN
-and surface processing.
+"""The FastSufer module provides basic functions
+for running FastSurfer CNN and surface processing.
Examples
--------
@@ -26,71 +26,238 @@
from nipype.interfaces.base.traits_extension import traits
__docformat__ = "restructuredtext"
+
class FastSInputSpec(CommandLineInputSpec):
"""
Required arguments
------------------
- --sd: Output directory $SUBJECTS_DIR (equivalent to FreeSurfer setup --> $SUBJECTS_DIR/sid/mri; $SUBJECTS_DIR/sid/surf ... will be created).
- --sid: Subject ID for directory inside $SUBJECTS_DIR to be created ($SUBJECTS_DIR/sid/...)
- --t1: T1 full head input (not bias corrected, global path). The network was trained with conformed images (UCHAR, 256x256x256, 1 mm voxels and standard slice orientation). These specifications are checked in the eval.py script and the image is automatically conformed if it does not comply.
- --fs_license: Path to FreeSurfer license key file. Register (for free) at https://surfer.nmr.mgh.harvard.edu/registration.html to obtain it if you do not have FreeSurfer installed so far. Strictly necessary if you use Docker, optional for local install (your local FreeSurfer license will automatically be used)
+ --sd: Output directory $SUBJECTS_DIR
+ --sid: Subject ID for directory inside $SUBJECTS_DIR to be created
+ --t1: T1 full head input (not bias corrected, global path). \
+ The network was trained with conformed images (UCHAR, 256x256x256, \
+ 1 mm voxels and standard slice orientation). \
+ These specifications are checked in the eval.py script and the image \
+ is automatically conformed if it does not comply.
+ --fs_license: Path to FreeSurfer license key file. \
+ Register at https://surfer.nmr.mgh.harvard.edu/registration.html \
+ to obtain it if you do not have FreeSurfer installed so far.
Optional arguments
------------------
Network specific arguments:
- --seg: Global path with filename of segmentation (where and under which name to store it). Default location: $SUBJECTS_DIR/$sid/mri/aparc.DKTatlas+aseg.deep.mgz
- --weights_sag: Pretrained weights of sagittal network. Default: ../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
- --weights_ax: Pretrained weights of axial network. Default: ../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
- --weights_cor: Pretrained weights of coronal network. Default: ../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
- --seg_log: Name and location for the log-file for the segmentation (FastSurferCNN). Default: $SUBJECTS_DIR/$sid/scripts/deep-seg.log
+ --seg: Global path with filename of segmentation \
+ (where and under which name to store it). \
+ Default location: \
+ $SUBJECTS_DIR/$sid/mri/aparc.DKTatlas+aseg.deep.mgz
+ --weights_sag: Pretrained weights of sagittal network. \
+ Default: \
+ ../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ --weights_ax: Pretrained weights of axial network. \
+ Default: \
+ ../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ --weights_cor: Pretrained weights of coronal network. \
+ Default: ../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ --seg_log: Name and location for the log-file for the segmentation (FastSurferCNN). \
+ Default: $SUBJECTS_DIR/$sid/scripts/deep-seg.log
--clean_seg: Flag to clean up FastSurferCNN segmentation
- --run_viewagg_on: Define where the view aggregation should be run on. By default, the program checks if you have enough memory to run the view aggregation on the gpu. The total memory is considered for this decision. If this fails, or you actively overwrote the check with setting "--run_viewagg_on cpu", view agg is run on the cpu. Equivalently, if you define "--run_viewagg_on gpu", view agg will be run on the gpu (no memory check will be done).
+ --run_viewagg_on: Define where the view aggregation should be run on. \
+ By default, the program checks if you have enough memory to run \
+ the view aggregation on the gpu. The total memory is considered for this decision. \
+ If this fails, or you actively overwrote the check with setting \
+ "--run_viewagg_on cpu", view agg is run on the cpu. \
+ Equivalently, if you define "--run_viewagg_on gpu", view agg will be run on the gpu \
+ (no memory check will be done).
--no_cuda: Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)
--batch: Batch size for inference. Default: 16. Lower this to reduce memory requirement
- --order: Order of interpolation for mri_convert T1 before segmentation (0=nearest, 1=linear(default), 2=quadratic, 3=cubic)
+ --order: Order of interpolation for mri_convert T1 before segmentation \
+ (0=nearest, 1=linear(default), 2=quadratic, 3=cubic)
Surface pipeline arguments:
--fstess: Use mri_tesselate instead of marching cube (default) for surface creation
- --fsqsphere: Use FreeSurfer default instead of novel spectral spherical projection for qsphere
- --fsaparc: Use FS aparc segmentations in addition to DL prediction (slower in this case and usually the mapped ones from the DL prediction are fine)
- --surfreg: Create Surface-Atlas (sphere.reg) registration with FreeSurfer (for cross-subject correspondence or other mappings)
+ --fsqsphere: Use FreeSurfer default instead of \
+ novel spectral spherical projection for qsphere
+ --fsaparc: Use FS aparc segmentations in addition to DL prediction \
+ (slower in this case and usually the mapped ones from the DL prediction are fine)
+ --surfreg: Create Surface-Atlas (sphere.reg) registration with FreeSurfer \
+ (for cross-subject correspondence or other mappings)
--parallel: Run both hemispheres in parallel
--threads: Set openMP and ITK threads to
Other:
--py: which python version to use. Default: python3.6
- --seg_only: only run FastSurferCNN (generate segmentation, do not run the surface pipeline)
- --surf_only: only run the surface pipeline recon_surf. The segmentation created by FastSurferCNN must already exist in this case.
+ --seg_only: only run FastSurferCNN
+ (generate segmentation, do not run the surface pipeline)
+ --surf_only: only run the surface pipeline recon_surf. \
+ The segmentation created by FastSurferCNN must already exist in this case.
"""
- sd = Directory(exists=True, argstr="--sd %s", mandatory=True, desc="Subjects directory")
- sid = traits.String(exists=True, argstr="--sid %s", mandatory=True, desc="Subject ID")
- t1 = File(exists=True, mandatory=True, argstr="--t1 %s", desc="T1 full head input (not bias corrected, global path)")
- fs_license = File(exists=True, mandatory=True, argstr="--fs_license %s", desc="Path to FreeSurfer license key file. Register (for free) at https://surfer.nmr.mgh.harvard.edu/registration.html to obtain it if you do not have FreeSurfer installed so far.")
- seg = File(exists=True, mandatory=False, argstr="--seg %s", desc="Global path with filename of segmentation (where and under which name to store it)")
- weights_sag = File(exists=True, mandatory=False, default="../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl", usedefault=False, argstr="--weights_sag %s", desc="Pretrained weights of sagittal network")
- weights_ax = File(exists=True, mandatory=False, default="../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl", usedefault=False, argstr="--weights_ax %s", desc="Pretrained weights of axial network",)
- weights_cor = File(exists=True, mandatory=False, default="../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl", usedefault=False, argstr="--weights_cor %s", desc="Pretrained weights of coronal network")
- seg_log = File(exists=True, mandatory=False, argstr="--seg_log %s", desc="Name and location for the log-file for the segmentation (FastSurferCNN).")
- clean_seg = traits.Bool(False,mandatory=False, usedefault=False, argstr="--clean_seg", desc="Flag to clean up FastSurferCNN segmentation")
- run_viewagg_on = File(exists=True, mandatory=False, argstr="--run_viewagg_on %s", desc="Define where the view aggregation should be run on. ")
- no_cuda = traits.Bool(False,mandatory=False, usedefault=False, argstr="--no_cuda", desc="Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)")
- batch = traits.Int(16, usedefault=True, mandatory=False, argstr="--batch %d", desc="Batch size for inference. default=16. Lower this to reduce memory requirement")
- order = traits.Int(1, mandatory=False, argstr = "--order %d", usedefault=True, desc="Order of interpolation for mri_convert T1 before segmentation (0=nearest, 1=linear(default), 2=quadratic, 3=cubic)")
- fstess = traits.Bool(False, usedefault=False, mandatory=False, argstr="--fstess", desc="Use mri_tesselate instead of marching cube (default) for surface creation")
- fsqsphere = traits.Bool(False, usedefault=False, mandatory=False, argstr="--fsqsphere", desc="Use FreeSurfer default instead of novel spectral spherical projection for qsphere")
- fsaparc = traits.Bool(False, usedefault=False, mandatory=False, argstr="--fsaparc", desc="Use FS aparc segmentations in addition to DL prediction (slower in this case and usually the mapped ones from the DL prediction are fine)")
- surfreg = traits.Bool(True, usedefault=True, mandatory=False, argstr="--surfreg", desc="Create Surface-Atlas (sphere.reg) registration with FreeSurfer (for cross-subject correspondence or other mappings)")
- parallel = traits.Bool(True, usedefault=True, mandatory=False, argstr="--parallel", desc="Run both hemispheres in parallel")
- threads = traits.Int(4, usedefault=True, mandatory=False, argstr="--threads %d", desc="Set openMP and ITK threads to")
- py = traits.String("python3.6", usedefault=True, mandatory=False, argstr="--py %s", desc="which python version to use. default=python3.6")
- seg_only = traits.Bool(False, usedefault=False, mandatory=False, argstr="--seg_only", desc="only run FastSurferCNN (generate segmentation, do not run the surface pipeline)")
- surf_only = traits.Bool(False, usedefault=False, mandatory=False, argstr="--surf_only", desc="only run the surface pipeline recon_surf. The segmentation created by FastSurferCNN must already exist in this case.")
+ sd = Directory(
+ exists=True,
+ argstr="--sd %s",
+ mandatory=True,
+ desc="Subjects directory"
+ )
+ sid = traits.String(
+ exists=True,
+ argstr="--sid %s",
+ mandatory=True,
+ desc="Subject ID"
+ )
+ t1 = File(
+ exists=True,
+ mandatory=True,
+ argstr="--t1 %s",
+ desc="T1 full head input (not bias corrected, global path)"
+ )
+ fs_license = File(
+ exists=True,
+ mandatory=True,
+ argstr="--fs_license %s",
+ desc="Path to FreeSurfer license key file."
+ )
+ seg = File(
+ exists=True,
+ mandatory=False,
+ argstr="--seg %s",
+ desc="Global path with filename of segmentation"
+ )
+ weights_sag = File(
+ exists=True,
+ mandatory=False,
+ default="../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
+ usedefault=False, argstr="--weights_sag %s",
+ desc="Pretrained weights of sagittal network")
+ weights_ax = File(
+ exists=True,
+ mandatory=False,
+ default="../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
+ usedefault=False,
+ argstr="--weights_ax %s",
+ desc="Pretrained weights of axial network",
+ )
+ weights_cor = File(
+ exists=True,
+ mandatory=False,
+ default="../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
+ usedefault=False,
+ argstr="--weights_cor %s",
+ desc="Pretrained weights of coronal network"
+ )
+ seg_log = File(
+ exists=True,
+ mandatory=False,
+ argstr="--seg_log %s",
+ desc="Name and location for the log-file for the segmentation (FastSurferCNN)."
+ )
+ clean_seg = traits.Bool(
+ False,
+ mandatory=False,
+ usedefault=False,
+ argstr="--clean_seg",
+ desc="Flag to clean up FastSurferCNN segmentation"
+ )
+ run_viewagg_on = File(
+ exists=True,
+ mandatory=False,
+ argstr="--run_viewagg_on %s",
+ desc="Define where the view aggregation should be run on. "
+ )
+ no_cuda = traits.Bool(
+ False,
+ mandatory=False,
+ usedefault=False,
+ argstr="--no_cuda",
+ desc="Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)"
+ )
+ batch = traits.Int(
+ 16,
+ usedefault=True,
+ mandatory=False,
+ argstr="--batch %d",
+ desc="Batch size for inference. default=16. Lower this to reduce memory requirement"
+ )
+ order = traits.Int(
+ 1,
+ mandatory=False,
+ argstr = "--order %d",
+ usedefault=True,
+ desc="""Order of interpolation for mri_convert T1 before segmentation
+ (0=nearest, 1=linear(default), 2=quadratic, 3=cubic)"""
+ )
+ fstess = traits.Bool(
+ False,
+ usedefault=False,
+ mandatory=False,
+ argstr="--fstess",
+ desc="Use mri_tesselate instead of marching cube (default) for surface creation"
+ )
+ fsqsphere = traits.Bool(
+ False,
+ usedefault=False,
+ mandatory=False,
+ argstr="--fsqsphere",
+ desc="Use FreeSurfer default instead of novel spectral spherical projection for qsphere"
+ )
+ fsaparc = traits.Bool(
+ False,
+ usedefault=False,
+ mandatory=False,
+ argstr="--fsaparc",
+ desc="Use FS aparc segmentations in addition to DL prediction"
+ )
+ surfreg = traits.Bool(
+ True,
+ usedefault=True,
+ mandatory=False,
+ argstr="--surfreg",
+ desc="""Create Surface-Atlas (sphere.reg) registration with FreeSurfer
+ (for cross-subject correspondence or other mappings)"""
+ )
+ parallel = traits.Bool(
+ True,
+ usedefault=True,
+ mandatory=False,
+ argstr="--parallel",
+ desc="Run both hemispheres in parallel"
+ )
+ threads = traits.Int(
+ 4,
+ usedefault=True,
+ mandatory=False,
+ argstr="--threads %d",
+ desc="Set openMP and ITK threads to"
+ )
+ py = traits.String(
+ "python3.6",
+ usedefault=True,
+ mandatory=False,
+ argstr="--py %s",
+ desc="which python version to use. default=python3.6"
+ )
+ seg_only = traits.Bool(
+ False,
+ usedefault=False,
+ mandatory=False,
+ argstr="--seg_only",
+ desc="only run FastSurferCNN (generate segmentation, do not surface)"
+ )
+ surf_only = traits.Bool(
+ False,
+ usedefault=False,
+ mandatory=False,
+ argstr="--surf_only",
+ desc="only run the surface pipeline recon_surf."
+ )
+
class FastSTraitedOutputSpec(TraitedSpec):
"""
- Outputs directory within the FastSurfer subjects_dir/subject_id/ with structure equivalent to Freesurfer
+ Outputs directory within the FastSurfer subjects_dir/subject_id/ \
+ with structure equivalent to Freesurfer
"""
- outputs = Directory(exists=True, desc="FastSurfer CNN (or VINN when added) + Surface Pipeline equivalent of the Freesurfer recon-all outputs")
+ outputs = Directory(
+ exists=True,
+ desc="FastSurfer CNN + Surface Pipeline equivalent of recon-all outputs")
+
class FastSCommand(CommandLine):
input_spec = FastSInputSpec
@@ -100,4 +267,3 @@ class FastSCommand(CommandLine):
def _list_outputs(self):
outputs = self.output_spec().get()
return outputs
-
From a7c4aa6aa1a5acee9461b40adc0c4ee06cb49968 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 17:46:01 -0500
Subject: [PATCH 021/220] Fix formatting for PEP8 compliance
---
smriprep/interfaces/fastsurfer.py | 250 +++++++++++++++---------------
1 file changed, 126 insertions(+), 124 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 2c9267c937..9bfb3c585e 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
-"""The FastSufer module provides basic functions
+"""The FastSufer module provides basic functions
for running FastSurfer CNN and surface processing.
Examples
@@ -32,231 +32,233 @@ class FastSInputSpec(CommandLineInputSpec):
Required arguments
------------------
--sd: Output directory $SUBJECTS_DIR
- --sid: Subject ID for directory inside $SUBJECTS_DIR to be created
- --t1: T1 full head input (not bias corrected, global path). \
- The network was trained with conformed images (UCHAR, 256x256x256, \
- 1 mm voxels and standard slice orientation). \
- These specifications are checked in the eval.py script and the image \
+ --sid: Subject ID for directory inside $SUBJECTS_DIR to be created
+ --t1: T1 full head input (not bias corrected, global path).
+ The network was trained with conformed images (UCHAR, 256x256x256,
+ 1 mm voxels and standard slice orientation).
+ These specifications are checked in the eval.py script and the image
is automatically conformed if it does not comply.
- --fs_license: Path to FreeSurfer license key file. \
- Register at https://surfer.nmr.mgh.harvard.edu/registration.html \
+ --fs_license: Path to FreeSurfer license key file.
+ Register at https://surfer.nmr.mgh.harvard.edu/registration.html
to obtain it if you do not have FreeSurfer installed so far.
-
+
Optional arguments
------------------
Network specific arguments:
- --seg: Global path with filename of segmentation \
- (where and under which name to store it). \
- Default location: \
+ --seg: Global path with filename of segmentation
+ (where and under which name to store it).
+ Default location:
$SUBJECTS_DIR/$sid/mri/aparc.DKTatlas+aseg.deep.mgz
- --weights_sag: Pretrained weights of sagittal network. \
- Default: \
+ --weights_sag: Pretrained weights of sagittal network.
+ Default:
../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
- --weights_ax: Pretrained weights of axial network. \
- Default: \
+ --weights_ax: Pretrained weights of axial network.
+ Default:
../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
- --weights_cor: Pretrained weights of coronal network. \
+ --weights_cor: Pretrained weights of coronal network.
Default: ../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
- --seg_log: Name and location for the log-file for the segmentation (FastSurferCNN). \
+ --seg_log: Name and location for the log-file for the segmentation (FastSurferCNN).
Default: $SUBJECTS_DIR/$sid/scripts/deep-seg.log
--clean_seg: Flag to clean up FastSurferCNN segmentation
- --run_viewagg_on: Define where the view aggregation should be run on. \
- By default, the program checks if you have enough memory to run \
- the view aggregation on the gpu. The total memory is considered for this decision. \
- If this fails, or you actively overwrote the check with setting \
- "--run_viewagg_on cpu", view agg is run on the cpu. \
- Equivalently, if you define "--run_viewagg_on gpu", view agg will be run on the gpu \
+ --run_viewagg_on: Define where the view aggregation should be run on.
+ By default, the program checks if you have enough memory to run
+ the view aggregation on the gpu. The total memory is considered for this decision.
+ If this fails, or you actively overwrote the check with setting
+ "--run_viewagg_on cpu", view agg is run on the cpu.
+ Equivalently, if you define "--run_viewagg_on gpu", view agg will be run on the gpu
(no memory check will be done).
--no_cuda: Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)
--batch: Batch size for inference. Default: 16. Lower this to reduce memory requirement
- --order: Order of interpolation for mri_convert T1 before segmentation \
+ --order: Order of interpolation for mri_convert T1 before segmentation
(0=nearest, 1=linear(default), 2=quadratic, 3=cubic)
Surface pipeline arguments:
--fstess: Use mri_tesselate instead of marching cube (default) for surface creation
- --fsqsphere: Use FreeSurfer default instead of \
+ --fsqsphere: Use FreeSurfer default instead of
novel spectral spherical projection for qsphere
- --fsaparc: Use FS aparc segmentations in addition to DL prediction \
+ --fsaparc: Use FS aparc segmentations in addition to DL prediction
(slower in this case and usually the mapped ones from the DL prediction are fine)
- --surfreg: Create Surface-Atlas (sphere.reg) registration with FreeSurfer \
+ --surfreg: Create Surface-Atlas (sphere.reg) registration with FreeSurfer
(for cross-subject correspondence or other mappings)
--parallel: Run both hemispheres in parallel
- --threads: Set openMP and ITK threads to
+ --threads: Set openMP and ITK threads
Other:
--py: which python version to use. Default: python3.6
--seg_only: only run FastSurferCNN
(generate segmentation, do not run the surface pipeline)
- --surf_only: only run the surface pipeline recon_surf. \
+ --surf_only: only run the surface pipeline recon_surf.
The segmentation created by FastSurferCNN must already exist in this case.
"""
sd = Directory(
- exists=True,
- argstr="--sd %s",
- mandatory=True,
+ exists=True,
+ argstr="--sd %s",
+ mandatory=True,
desc="Subjects directory"
)
sid = traits.String(
- exists=True,
- argstr="--sid %s",
- mandatory=True,
+ exists=True,
+ argstr="--sid %s",
+ mandatory=True,
desc="Subject ID"
)
t1 = File(
- exists=True,
- mandatory=True,
- argstr="--t1 %s",
+ exists=True,
+ mandatory=True,
+ argstr="--t1 %s",
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
- exists=True,
- mandatory=True,
- argstr="--fs_license %s",
+ exists=True,
+ mandatory=True,
+ argstr="--fs_license %s",
desc="Path to FreeSurfer license key file."
)
seg = File(
- exists=True,
- mandatory=False,
- argstr="--seg %s",
+ exists=True,
+ mandatory=False,
+ argstr="--seg %s",
desc="Global path with filename of segmentation"
)
- weights_sag = File(
- exists=True,
- mandatory=False,
- default="../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
- usedefault=False, argstr="--weights_sag %s",
- desc="Pretrained weights of sagittal network")
+ weights_sag = File(
+ exists=True,
+ mandatory=False,
+ default="../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
+ usedefault=False, argstr="--weights_sag %s",
+ desc="Pretrained weights of sagittal network"
+ )
weights_ax = File(
- exists=True,
- mandatory=False,
- default="../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
- usedefault=False,
- argstr="--weights_ax %s",
- desc="Pretrained weights of axial network",
+ exists=True,
+ mandatory=False,
+ default="../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
+ usedefault=False,
+ argstr="--weights_ax %s",
+ desc="Pretrained weights of axial network"
)
weights_cor = File(
- exists=True,
- mandatory=False,
- default="../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
- usedefault=False,
- argstr="--weights_cor %s",
+ exists=True,
+ mandatory=False,
+ default="../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
+ usedefault=False,
+ argstr="--weights_cor %s",
desc="Pretrained weights of coronal network"
)
seg_log = File(
- exists=True,
- mandatory=False,
- argstr="--seg_log %s",
+ exists=True,
+ mandatory=False,
+ argstr="--seg_log %s",
desc="Name and location for the log-file for the segmentation (FastSurferCNN)."
)
clean_seg = traits.Bool(
False,
- mandatory=False,
- usedefault=False,
- argstr="--clean_seg",
+ mandatory=False,
+ usedefault=False,
+ argstr="--clean_seg",
desc="Flag to clean up FastSurferCNN segmentation"
)
run_viewagg_on = File(
- exists=True,
+ exists=True,
mandatory=False,
- argstr="--run_viewagg_on %s",
- desc="Define where the view aggregation should be run on. "
+ argstr="--run_viewagg_on %s",
+ desc="Define where the view aggregation should be run on."
)
- no_cuda = traits.Bool(
- False,
- mandatory=False,
- usedefault=False,
- argstr="--no_cuda",
+ no_cuda = traits.Bool(
+ False,
+ mandatory=False,
+ usedefault=False,
+ argstr="--no_cuda",
desc="Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)"
)
- batch = traits.Int(
- 16,
- usedefault=True,
- mandatory=False,
- argstr="--batch %d",
+ batch = traits.Int(
+ 16,
+ usedefault=True,
+ mandatory=False,
+ argstr="--batch %d",
desc="Batch size for inference. default=16. Lower this to reduce memory requirement"
)
order = traits.Int(
- 1,
- mandatory=False,
- argstr = "--order %d",
- usedefault=True,
- desc="""Order of interpolation for mri_convert T1 before segmentation
+ 1,
+ mandatory=False,
+ argstr="--order %d",
+ usedefault=True,
+ desc="""Order of interpolation for mri_convert T1 before segmentation
(0=nearest, 1=linear(default), 2=quadratic, 3=cubic)"""
)
fstess = traits.Bool(
- False,
- usedefault=False,
- mandatory=False,
- argstr="--fstess",
+ False,
+ usedefault=False,
+ mandatory=False,
+ argstr="--fstess",
desc="Use mri_tesselate instead of marching cube (default) for surface creation"
)
fsqsphere = traits.Bool(
- False,
- usedefault=False,
- mandatory=False,
- argstr="--fsqsphere",
+ False,
+ usedefault=False,
+ mandatory=False,
+ argstr="--fsqsphere",
desc="Use FreeSurfer default instead of novel spectral spherical projection for qsphere"
)
fsaparc = traits.Bool(
- False,
- usedefault=False,
+ False,
+ usedefault=False,
mandatory=False,
- argstr="--fsaparc",
+ argstr="--fsaparc",
desc="Use FS aparc segmentations in addition to DL prediction"
)
surfreg = traits.Bool(
- True,
- usedefault=True,
- mandatory=False,
- argstr="--surfreg",
+ True,
+ usedefault=True,
+ mandatory=False,
+ argstr="--surfreg",
desc="""Create Surface-Atlas (sphere.reg) registration with FreeSurfer
(for cross-subject correspondence or other mappings)"""
)
parallel = traits.Bool(
- True,
- usedefault=True,
- mandatory=False,
- argstr="--parallel",
+ True,
+ usedefault=True,
+ mandatory=False,
+ argstr="--parallel",
desc="Run both hemispheres in parallel"
)
threads = traits.Int(
- 4,
- usedefault=True,
- mandatory=False,
- argstr="--threads %d",
+ 4,
+ usedefault=True,
+ mandatory=False,
+ argstr="--threads %d",
desc="Set openMP and ITK threads to"
)
py = traits.String(
- "python3.6",
- usedefault=True,
- mandatory=False,
- argstr="--py %s",
+ "python3.6",
+ usedefault=True,
+ mandatory=False,
+ argstr="--py %s",
desc="which python version to use. default=python3.6"
)
seg_only = traits.Bool(
- False,
- usedefault=False,
- mandatory=False,
- argstr="--seg_only",
+ False,
+ usedefault=False,
+ mandatory=False,
+ argstr="--seg_only",
desc="only run FastSurferCNN (generate segmentation, do not surface)"
)
surf_only = traits.Bool(
- False,
- usedefault=False,
- mandatory=False,
- argstr="--surf_only",
+ False,
+ usedefault=False,
+ mandatory=False,
+ argstr="--surf_only",
desc="only run the surface pipeline recon_surf."
)
class FastSTraitedOutputSpec(TraitedSpec):
"""
- Outputs directory within the FastSurfer subjects_dir/subject_id/ \
+ Outputs directory within the FastSurfer subjects_dir/subject_id/
with structure equivalent to Freesurfer
"""
outputs = Directory(
- exists=True,
- desc="FastSurfer CNN + Surface Pipeline equivalent of recon-all outputs")
+ exists=True,
+ desc="FastSurfer CNN + Surface Pipeline equivalent of recon-all outputs"
+ )
class FastSCommand(CommandLine):
From b5cf10a983c408e1f5f27f033dd4ed5946a98b85 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 17:46:40 -0500
Subject: [PATCH 022/220] Fix formatting for PEP8 compliance
---
smriprep/workflows/anatomical.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index b7b35ac3d9..715362893a 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -48,8 +48,8 @@
from niworkflows.anat.ants import init_brain_extraction_wf, init_n4_only_wf
from ..utils.bids import get_outputnode_spec
from ..utils.misc import (
- apply_lut as _apply_bids_lut,
- fs_isRunning as _fs_isRunning,
+ apply_lut as _apply_bids_lut,
+ fs_isRunning as _fs_isRunning,
check_fastsurfer as _check_fastsurfer
)
from .norm import init_anat_norm_wf
From a93fd77a5198e85602a0ae3d3b262221ce0d5c7a Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 17:47:56 -0500
Subject: [PATCH 023/220] Fix formatting for PEP8 compliance
---
smriprep/interfaces/fastsurfer.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 9bfb3c585e..fb2d9b41d2 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -34,7 +34,7 @@ class FastSInputSpec(CommandLineInputSpec):
--sd: Output directory $SUBJECTS_DIR
--sid: Subject ID for directory inside $SUBJECTS_DIR to be created
--t1: T1 full head input (not bias corrected, global path).
- The network was trained with conformed images (UCHAR, 256x256x256,
+ The network was trained with conformed images (UCHAR, 256x256x256,
1 mm voxels and standard slice orientation).
These specifications are checked in the eval.py script and the image
is automatically conformed if it does not comply.
@@ -119,7 +119,7 @@ class FastSInputSpec(CommandLineInputSpec):
mandatory=False,
argstr="--seg %s",
desc="Global path with filename of segmentation"
- )
+ )
weights_sag = File(
exists=True,
mandatory=False,
@@ -210,7 +210,7 @@ class FastSInputSpec(CommandLineInputSpec):
usedefault=True,
mandatory=False,
argstr="--surfreg",
- desc="""Create Surface-Atlas (sphere.reg) registration with FreeSurfer
+ desc="""Create Surface-Atlas (sphere.reg) registration with FreeSurfer
(for cross-subject correspondence or other mappings)"""
)
parallel = traits.Bool(
From 41cfba63ff88e1b1d2a8b23ec5eef11b346e0b1e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 18:37:50 -0500
Subject: [PATCH 024/220] Fix typo
---
smriprep/cli/run.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 223fdc071d..24cbab2e27 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -222,7 +222,7 @@ def get_parser():
dest="hires",
help="disable sub-millimeter (hires) reconstruction",
)
- g_surfs_xor.add_argument(
+ g_surfs.add_argument(
"--fastsurfer-recon",
action="store_true",
dest="run_fastsurfer",
From 8f821d2152e5c7537ea2f9eb881e8425700924e8 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 18:39:54 -0500
Subject: [PATCH 025/220] Revert Convert3D install method from development use
case
---
Dockerfile | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 3f889f0c56..f73bafd2c4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -105,7 +105,7 @@ ENV PATH /opt/conda/bin:$PATH
RUN python3.6 -m pip install -U git+https://github.com/Deep-MI/LaPy.git#egg=lapy
# Add FastSurfer (copy application code) to docker image
-RUN cd /opt && git clone https://github.com/Deep-MI/FastSurfer.git
+RUN cd /opt && git clone https://github.com/Deep-MI/FastSurfer.git
ENV FASTSURFER_HOME=/opt/FastSurfer
@@ -216,12 +216,10 @@ ENV LANG="en_US.UTF-8" \
LANGUAGE="en_US:en"
RUN ls /etc/ssl/certs/
-
-# Convert3D (neurodocker build) - adapted to allow for local copy of Convert3D
-# my build machine was giving ca-certificates errors for fetching C3D from sourceforge in build
-#RUN echo "Downloading Convert3D ..." \
-# && mkdir -p /opt/convert3d-1.0.0 \
-# && cd /opt/ && curl -fsSL https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz \
+# Convert3D (neurodocker build)
+RUN echo "Downloading Convert3D ..." \
+ && mkdir -p /opt/convert3d-1.0.0 \
+ && cd /opt/ && curl -fsSL https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz \
COPY c3d-1.0.0-Linux-x86_64.tar.gz /opt/c3d-1.0.0-Linux-x86_64.tar.gz
RUN cd /opt/ && mkdir -p /opt/convert3d-1.0.0 && tar -xzf c3d-1.0.0-Linux-x86_64.tar.gz -C /opt/convert3d-1.0.0 --strip-components 1 \
--exclude "c3d-1.0.0-Linux-x86_64/lib" \
From e3380019f2776f175767ebde7283b202363c956e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 20:01:27 -0500
Subject: [PATCH 026/220] Fix Convert3D
---
Dockerfile | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index f73bafd2c4..821b6727b6 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -219,9 +219,8 @@ RUN ls /etc/ssl/certs/
# Convert3D (neurodocker build)
RUN echo "Downloading Convert3D ..." \
&& mkdir -p /opt/convert3d-1.0.0 \
- && cd /opt/ && curl -fsSL https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz \
-COPY c3d-1.0.0-Linux-x86_64.tar.gz /opt/c3d-1.0.0-Linux-x86_64.tar.gz
-RUN cd /opt/ && mkdir -p /opt/convert3d-1.0.0 && tar -xzf c3d-1.0.0-Linux-x86_64.tar.gz -C /opt/convert3d-1.0.0 --strip-components 1 \
+ && curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz/download \
+ | tar -xz -C /opt/convert3d-1.0.0 --strip-components 1 \
--exclude "c3d-1.0.0-Linux-x86_64/lib" \
--exclude "c3d-1.0.0-Linux-x86_64/share" \
--exclude "c3d-1.0.0-Linux-x86_64/bin/c3d_gui"
From 16d5f0937c0e4ce6f95f744c54e075a4a7fb3942 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 21:05:42 -0500
Subject: [PATCH 027/220] Pin Jinja2 version to prevent CircleCI build_docs
failure
Fix fail to build docs in CircleCI observed in testing draft changes made to PR #280.
```
#!/bin/bash -eo pipefail
make -C docs SPHINXOPTS="-W" BUILDDIR="_build/no_version_html" html
make: Entering directory '/tmp/gh-pages/docs'
PYTHONPATH=/tmp/gh-pages sphinx-build -b html -d _build/no_version_html/doctrees -W . _build/no_version_html/html
Traceback (most recent call last):
File "/home/circleci/.local/bin/sphinx-build", line 5, in
from sphinx.cmd.build import main
File "/home/circleci/.local/lib/python3.8/site-packages/sphinx/cmd/build.py", line 23, in
from sphinx.application import Sphinx
File "/home/circleci/.local/lib/python3.8/site-packages/sphinx/application.py", line 42, in
from sphinx.highlighting import lexer_classes, lexers
File "/home/circleci/.local/lib/python3.8/site-packages/sphinx/highlighting.py", line 30, in
from sphinx.ext import doctest
File "/home/circleci/.local/lib/python3.8/site-packages/sphinx/ext/doctest.py", line 28, in
from sphinx.builders import Builder
File "/home/circleci/.local/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 24, in
from sphinx.io import read_doc
File "/home/circleci/.local/lib/python3.8/site-packages/sphinx/io.py", line 42, in
from sphinx.util.rst import append_epilog, docinfo_re, prepend_prolog
File "/home/circleci/.local/lib/python3.8/site-packages/sphinx/util/rst.py", line 22, in
from jinja2 import environmentfilter
ImportError: cannot import name 'environmentfilter' from 'jinja2' (/home/circleci/.local/lib/python3.8/site-packages/jinja2/__init__.py)
make: *** [Makefile:61: html] Error 1
make: Leaving directory '/tmp/gh-pages/docs'
Exited with code exit status 2
CircleCI received exit code 2
```
From suggested fix for similar behavior: https://github.com/mkdocs/mkdocs/issues/2799
---
docs/requirements.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 3d2ac3a34a..aa1c4a6999 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -11,3 +11,4 @@ sphinx >= 2.1.2, < 3
sphinx_rtd_theme
sphinxcontrib-apidoc ~= 0.3.0
templateflow
+jinja2==3.0.3
From 6973ddd34a34532747e67a6ae40a86e660cf7871 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 21:14:22 -0500
Subject: [PATCH 028/220] Fix docstring
Fix docstring list end without a blank line error
---
smriprep/interfaces/fastsurfer.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index fb2d9b41d2..3fa54d3bd8 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -28,9 +28,10 @@
class FastSInputSpec(CommandLineInputSpec):
- """
+ r"""
Required arguments
------------------
+
--sd: Output directory $SUBJECTS_DIR
--sid: Subject ID for directory inside $SUBJECTS_DIR to be created
--t1: T1 full head input (not bias corrected, global path).
@@ -44,6 +45,7 @@ class FastSInputSpec(CommandLineInputSpec):
Optional arguments
------------------
+
Network specific arguments:
--seg: Global path with filename of segmentation
(where and under which name to store it).
@@ -89,6 +91,7 @@ class FastSInputSpec(CommandLineInputSpec):
(generate segmentation, do not run the surface pipeline)
--surf_only: only run the surface pipeline recon_surf.
The segmentation created by FastSurferCNN must already exist in this case.
+
"""
sd = Directory(
exists=True,
From d35eb072613715965b1b855142075397786801af Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 21:34:10 -0500
Subject: [PATCH 029/220] Update example of commandline FastSurfer usage to
docstring
Update example of commandline FastSurfer usage to docstring, formatting of input spec docstring
---
smriprep/interfaces/fastsurfer.py | 154 +++++++++++++++++++-----------
1 file changed, 97 insertions(+), 57 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 3fa54d3bd8..f6a04f555d 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -28,69 +28,98 @@
class FastSInputSpec(CommandLineInputSpec):
- r"""
+ """
Required arguments
- ------------------
+ ==================
- --sd: Output directory $SUBJECTS_DIR
- --sid: Subject ID for directory inside $SUBJECTS_DIR to be created
- --t1: T1 full head input (not bias corrected, global path).
- The network was trained with conformed images (UCHAR, 256x256x256,
- 1 mm voxels and standard slice orientation).
- These specifications are checked in the eval.py script and the image
- is automatically conformed if it does not comply.
- --fs_license: Path to FreeSurfer license key file.
- Register at https://surfer.nmr.mgh.harvard.edu/registration.html
- to obtain it if you do not have FreeSurfer installed so far.
+ sd
+ Output directory $SUBJECTS_DIR
+ sid
+ Subject ID for directory inside $SUBJECTS_DIR to be created
+ t1
+ T1 full head input (not bias corrected, global path).
+ The network was trained with conformed images (UCHAR, 256x256x256,
+ 1 mm voxels and standard slice orientation).
+ These specifications are checked in the eval.py script and the image
+ is automatically conformed if it does not comply.
+ fs_license
+ Path to FreeSurfer license key file.
+ Register at https://surfer.nmr.mgh.harvard.edu/registration.html
+ to obtain it if you do not have FreeSurfer installed so far.
Optional arguments
- ------------------
+ ==================
+
+ Network specific arguments
+ --------------------------
+
+ seg
+ Global path with filename of segmentation
+ (where and under which name to store it).
+ Default location
+ $SUBJECTS_DIR/$sid/mri/aparc.DKTatlas+aseg.deep.mgz
+ weights_sag
+ Pretrained weights of sagittal network.
+ Default
+ ../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ weights_ax
+ Pretrained weights of axial network.
+ Default
+ ../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ weights_cor
+ Pretrained weights of coronal network.
+ Default ../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ seg_log
+ Name and location for the log-file for the segmentation (FastSurferCNN).
+ Default $SUBJECTS_DIR/$sid/scripts/deep-seg.log
+ clean_seg
+ Flag to clean up FastSurferCNN segmentation
+ run_viewagg_on
+ Define where the view aggregation should be run on.
+ By default, the program checks if you have enough memory to run
+ the view aggregation on the gpu. The total memory is considered for this decision.
+ If this fails, or you actively overwrote the check with setting
+ "run_viewagg_on cpu", view agg is run on the cpu.
+ Equivalently, if you define "--run_viewagg_on gpu", view agg will be run on the gpu
+ (no memory check will be done).
+ no_cuda
+ Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)
+ batch
+ Batch size for inference. Default: 16. Lower this to reduce memory requirement
+ order
+ Order of interpolation for mri_convert T1 before segmentation
+ (0=nearest, 1=linear(default), 2=quadratic, 3=cubic)
- Network specific arguments:
- --seg: Global path with filename of segmentation
- (where and under which name to store it).
- Default location:
- $SUBJECTS_DIR/$sid/mri/aparc.DKTatlas+aseg.deep.mgz
- --weights_sag: Pretrained weights of sagittal network.
- Default:
- ../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
- --weights_ax: Pretrained weights of axial network.
- Default:
- ../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
- --weights_cor: Pretrained weights of coronal network.
- Default: ../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
- --seg_log: Name and location for the log-file for the segmentation (FastSurferCNN).
- Default: $SUBJECTS_DIR/$sid/scripts/deep-seg.log
- --clean_seg: Flag to clean up FastSurferCNN segmentation
- --run_viewagg_on: Define where the view aggregation should be run on.
- By default, the program checks if you have enough memory to run
- the view aggregation on the gpu. The total memory is considered for this decision.
- If this fails, or you actively overwrote the check with setting
- "--run_viewagg_on cpu", view agg is run on the cpu.
- Equivalently, if you define "--run_viewagg_on gpu", view agg will be run on the gpu
- (no memory check will be done).
- --no_cuda: Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)
- --batch: Batch size for inference. Default: 16. Lower this to reduce memory requirement
- --order: Order of interpolation for mri_convert T1 before segmentation
- (0=nearest, 1=linear(default), 2=quadratic, 3=cubic)
+ Surface pipeline arguments
+ --------------------------
- Surface pipeline arguments:
- --fstess: Use mri_tesselate instead of marching cube (default) for surface creation
- --fsqsphere: Use FreeSurfer default instead of
- novel spectral spherical projection for qsphere
- --fsaparc: Use FS aparc segmentations in addition to DL prediction
- (slower in this case and usually the mapped ones from the DL prediction are fine)
- --surfreg: Create Surface-Atlas (sphere.reg) registration with FreeSurfer
- (for cross-subject correspondence or other mappings)
- --parallel: Run both hemispheres in parallel
- --threads: Set openMP and ITK threads
+ fstess
+ Use mri_tesselate instead of marching cube (default) for surface creation
+ fsqsphere
+ Use FreeSurfer default instead of
+ novel spectral spherical projection for qsphere
+ fsaparc
+ Use FS aparc segmentations in addition to DL prediction
+ (slower in this case and usually the mapped ones from the DL prediction are fine)
+ surfreg
+ Create Surface-Atlas (sphere.reg) registration with FreeSurfer
+ (for cross-subject correspondence or other mappings)
+ parallel
+ Run both hemispheres in parallel
+ threads
+ Set openMP and ITK threads
- Other:
- --py: which python version to use. Default: python3.6
- --seg_only: only run FastSurferCNN
- (generate segmentation, do not run the surface pipeline)
- --surf_only: only run the surface pipeline recon_surf.
- The segmentation created by FastSurferCNN must already exist in this case.
+ Other
+ ----
+
+ py
+ which python version to use. Default: python3.6
+ seg_only
+ only run FastSurferCNN
+ (generate segmentation, do not run the surface pipeline)
+ surf_only
+ only run the surface pipeline recon_surf.
+ The segmentation created by FastSurferCNN must already exist in this case.
"""
sd = Directory(
@@ -256,7 +285,8 @@ class FastSInputSpec(CommandLineInputSpec):
class FastSTraitedOutputSpec(TraitedSpec):
"""
Outputs directory within the FastSurfer subjects_dir/subject_id/
- with structure equivalent to Freesurfer
+ with structure equivalent to Freesurfer
+
"""
outputs = Directory(
exists=True,
@@ -265,6 +295,16 @@ class FastSTraitedOutputSpec(TraitedSpec):
class FastSCommand(CommandLine):
+ """
+ Wraps FastSurfer command for segmentation and surface processing.
+
+ Example basic commandline usage::
+
+ $ /opt/FastSurfer/run_fastsurfer.sh --fs_license /fs60/license \
+ --t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
+ --sid sub- --sd /output
+
+ """
input_spec = FastSInputSpec
output_spec = FastSTraitedOutputSpec
_cmd = '/opt/FastSurfer/run_fastsurfer.sh'
From 1acc95f3de1ded788f2a525a10ed552aec6aca23 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 21:48:26 -0500
Subject: [PATCH 030/220] Fix docstring formatting
---
smriprep/interfaces/fastsurfer.py | 38 ++++++++++++++++---------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index f6a04f555d..e903f34b79 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -28,7 +28,7 @@
class FastSInputSpec(CommandLineInputSpec):
- """
+ r"""
Required arguments
==================
@@ -38,8 +38,8 @@ class FastSInputSpec(CommandLineInputSpec):
Subject ID for directory inside $SUBJECTS_DIR to be created
t1
T1 full head input (not bias corrected, global path).
- The network was trained with conformed images (UCHAR, 256x256x256,
- 1 mm voxels and standard slice orientation).
+ The 'network was trained with conformed images
+ (UCHAR, 256x256x256, 1 mm voxels and standard slice orientation).
These specifications are checked in the eval.py script and the image
is automatically conformed if it does not comply.
fs_license
@@ -57,21 +57,22 @@ class FastSInputSpec(CommandLineInputSpec):
Global path with filename of segmentation
(where and under which name to store it).
Default location
- $SUBJECTS_DIR/$sid/mri/aparc.DKTatlas+aseg.deep.mgz
+ ``$SUBJECTS_DIR/$sid/mri/aparc.DKTatlas+aseg.deep.mgz``
weights_sag
Pretrained weights of sagittal network.
Default
- ../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ '../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl'
weights_ax
Pretrained weights of axial network.
Default
- ../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ '../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl'
weights_cor
Pretrained weights of coronal network.
- Default ../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl
+ Default
+ '../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl'
seg_log
Name and location for the log-file for the segmentation (FastSurferCNN).
- Default $SUBJECTS_DIR/$sid/scripts/deep-seg.log
+ Default '$SUBJECTS_DIR/$sid/scripts/deep-seg.log'
clean_seg
Flag to clean up FastSurferCNN segmentation
run_viewagg_on
@@ -79,22 +80,22 @@ class FastSInputSpec(CommandLineInputSpec):
By default, the program checks if you have enough memory to run
the view aggregation on the gpu. The total memory is considered for this decision.
If this fails, or you actively overwrote the check with setting
- "run_viewagg_on cpu", view agg is run on the cpu.
- Equivalently, if you define "--run_viewagg_on gpu", view agg will be run on the gpu
+ ``run_viewagg_on cpu``, view agg is run on the cpu.
+ Equivalently, if you define ``--run_viewagg_on gpu``, view agg will be run on the gpu
(no memory check will be done).
no_cuda
Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)
batch
- Batch size for inference. Default: 16. Lower this to reduce memory requirement
+ Batch size for inference. Default 16. Lower this to reduce memory requirement
order
Order of interpolation for mri_convert T1 before segmentation
- (0=nearest, 1=linear(default), 2=quadratic, 3=cubic)
+ ``(0=nearest, 1=linear(default), 2=quadratic, 3=cubic)``
Surface pipeline arguments
--------------------------
fstess
- Use mri_tesselate instead of marching cube (default) for surface creation
+ Use ``mri_tesselate`` instead of marching cube (default) for surface creation
fsqsphere
Use FreeSurfer default instead of
novel spectral spherical projection for qsphere
@@ -102,7 +103,7 @@ class FastSInputSpec(CommandLineInputSpec):
Use FS aparc segmentations in addition to DL prediction
(slower in this case and usually the mapped ones from the DL prediction are fine)
surfreg
- Create Surface-Atlas (sphere.reg) registration with FreeSurfer
+ Create Surface-Atlas ``sphere.reg`` registration with FreeSurfer
(for cross-subject correspondence or other mappings)
parallel
Run both hemispheres in parallel
@@ -113,12 +114,13 @@ class FastSInputSpec(CommandLineInputSpec):
----
py
- which python version to use. Default: python3.6
+ which python version to use.
+ Default ``python3.6``
seg_only
only run FastSurferCNN
(generate segmentation, do not run the surface pipeline)
surf_only
- only run the surface pipeline recon_surf.
+ only run the surface pipeline ``recon_surf``.
The segmentation created by FastSurferCNN must already exist in this case.
"""
@@ -283,7 +285,7 @@ class FastSInputSpec(CommandLineInputSpec):
class FastSTraitedOutputSpec(TraitedSpec):
- """
+ r"""
Outputs directory within the FastSurfer subjects_dir/subject_id/
with structure equivalent to Freesurfer
@@ -295,7 +297,7 @@ class FastSTraitedOutputSpec(TraitedSpec):
class FastSCommand(CommandLine):
- """
+ r"""
Wraps FastSurfer command for segmentation and surface processing.
Example basic commandline usage::
From a0e2c713d2e973dd20a9076a8ff2f016f4b00f77 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 21:55:55 -0500
Subject: [PATCH 031/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index e903f34b79..c21889bded 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -40,7 +40,7 @@ class FastSInputSpec(CommandLineInputSpec):
T1 full head input (not bias corrected, global path).
The 'network was trained with conformed images
(UCHAR, 256x256x256, 1 mm voxels and standard slice orientation).
- These specifications are checked in the eval.py script and the image
+ These specifications are checked in the ``eval.py`` script and the image
is automatically conformed if it does not comply.
fs_license
Path to FreeSurfer license key file.
@@ -52,7 +52,6 @@ class FastSInputSpec(CommandLineInputSpec):
Network specific arguments
--------------------------
-
seg
Global path with filename of segmentation
(where and under which name to store it).
@@ -93,7 +92,6 @@ class FastSInputSpec(CommandLineInputSpec):
Surface pipeline arguments
--------------------------
-
fstess
Use ``mri_tesselate`` instead of marching cube (default) for surface creation
fsqsphere
@@ -112,7 +110,6 @@ class FastSInputSpec(CommandLineInputSpec):
Other
----
-
py
which python version to use.
Default ``python3.6``
From 609d00c8694c86a48ec5f48bc815d429be1c3cc1 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 22:02:19 -0500
Subject: [PATCH 032/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index c21889bded..bc369d5d72 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -1,13 +1,10 @@
# -*- coding: utf-8 -*-
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
-"""The FastSufer module provides basic functions
+"""
+The FastSufer module provides basic functions
for running FastSurfer CNN and surface processing.
-Examples
---------
-See the docstrings for the individual classes for 'working' examples.
-
"""
from ast import BoolOp
from genericpath import exists
@@ -24,7 +21,6 @@
PackageInfo,
)
from nipype.interfaces.base.traits_extension import traits
-__docformat__ = "restructuredtext"
class FastSInputSpec(CommandLineInputSpec):
From 67682428b7e0ee0c381c53909f9338829d8183a8 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 22:11:31 -0500
Subject: [PATCH 033/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index bc369d5d72..4ba1ce4a08 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -41,7 +41,6 @@ class FastSInputSpec(CommandLineInputSpec):
fs_license
Path to FreeSurfer license key file.
Register at https://surfer.nmr.mgh.harvard.edu/registration.html
- to obtain it if you do not have FreeSurfer installed so far.
Optional arguments
==================
From 62ffc166a97226e481eaff65d1dcab87ed671753 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 22:17:01 -0500
Subject: [PATCH 034/220] Fix docstrings formatting
---
smriprep/interfaces/fastsurfer.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 4ba1ce4a08..6a287b3f49 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -29,9 +29,9 @@ class FastSInputSpec(CommandLineInputSpec):
==================
sd
- Output directory $SUBJECTS_DIR
+ Output directory
sid
- Subject ID for directory inside $SUBJECTS_DIR to be created
+ Subject ID for directory inside ``sd`` to be created
t1
T1 full head input (not bias corrected, global path).
The 'network was trained with conformed images
@@ -40,7 +40,7 @@ class FastSInputSpec(CommandLineInputSpec):
is automatically conformed if it does not comply.
fs_license
Path to FreeSurfer license key file.
- Register at https://surfer.nmr.mgh.harvard.edu/registration.html
+ Register at `https://surfer.nmr.mgh.harvard.edu/registration.html`_
Optional arguments
==================
@@ -55,15 +55,15 @@ class FastSInputSpec(CommandLineInputSpec):
weights_sag
Pretrained weights of sagittal network.
Default
- '../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl'
+ ``../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
weights_ax
Pretrained weights of axial network.
Default
- '../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl'
+ ``../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
weights_cor
Pretrained weights of coronal network.
Default
- '../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl'
+ ``../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
seg_log
Name and location for the log-file for the segmentation (FastSurferCNN).
Default '$SUBJECTS_DIR/$sid/scripts/deep-seg.log'
From 1c55f0df7e07c9d3a45ae4b40067e1b37a4c9d29 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 22:21:21 -0500
Subject: [PATCH 035/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 6a287b3f49..6679b35143 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -40,7 +40,7 @@ class FastSInputSpec(CommandLineInputSpec):
is automatically conformed if it does not comply.
fs_license
Path to FreeSurfer license key file.
- Register at `https://surfer.nmr.mgh.harvard.edu/registration.html`_
+
Optional arguments
==================
@@ -85,6 +85,7 @@ class FastSInputSpec(CommandLineInputSpec):
Order of interpolation for mri_convert T1 before segmentation
``(0=nearest, 1=linear(default), 2=quadratic, 3=cubic)``
+
Surface pipeline arguments
--------------------------
fstess
@@ -103,6 +104,7 @@ class FastSInputSpec(CommandLineInputSpec):
threads
Set openMP and ITK threads
+
Other
----
py
@@ -115,6 +117,7 @@ class FastSInputSpec(CommandLineInputSpec):
only run the surface pipeline ``recon_surf``.
The segmentation created by FastSurferCNN must already exist in this case.
+
"""
sd = Directory(
exists=True,
From d0f0f5db700ee8adf162fe25271e6909a035e88e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 22:25:17 -0500
Subject: [PATCH 036/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 6679b35143..d1f2a23b97 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -294,13 +294,14 @@ class FastSTraitedOutputSpec(TraitedSpec):
class FastSCommand(CommandLine):
r"""
Wraps FastSurfer command for segmentation and surface processing.
-
+
Example basic commandline usage::
$ /opt/FastSurfer/run_fastsurfer.sh --fs_license /fs60/license \
--t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
--sid sub- --sd /output
+
"""
input_spec = FastSInputSpec
output_spec = FastSTraitedOutputSpec
From b65c03d2a026d154c0dc09c5de5859af27a5fda1 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 22:30:56 -0500
Subject: [PATCH 037/220] Add code block
---
smriprep/interfaces/fastsurfer.py | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index d1f2a23b97..5320d7df8d 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -295,12 +295,13 @@ class FastSCommand(CommandLine):
r"""
Wraps FastSurfer command for segmentation and surface processing.
- Example basic commandline usage::
-
- $ /opt/FastSurfer/run_fastsurfer.sh --fs_license /fs60/license \
- --t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
- --sid sub- --sd /output
+ Example basic commandline usage
+ .. code-block:: bash
+
+ /opt/FastSurfer/run_fastsurfer.sh --fs_license /fs60/license \
+ --t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
+ --sid sub- --sd /output
"""
input_spec = FastSInputSpec
From 8fc81390fbf23d22193672ed5077cd4890ad360b Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 26 Apr 2022 22:34:21 -0500
Subject: [PATCH 038/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 5320d7df8d..34f840b064 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -295,10 +295,9 @@ class FastSCommand(CommandLine):
r"""
Wraps FastSurfer command for segmentation and surface processing.
- Example basic commandline usage
-
.. code-block:: bash
-
+
+ #Example basic commandline usage
/opt/FastSurfer/run_fastsurfer.sh --fs_license /fs60/license \
--t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
--sid sub- --sd /output
From 3322cd201e32ced6e43b6b38ecbd829016905efe Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 27 Apr 2022 18:33:06 -0500
Subject: [PATCH 039/220] Adds FastSurfer recon workflow
Adds FastSurfer recon workflow per discussion in https://github.com/nipreps/smriprep/pull/280
---
smriprep/workflows/surfaces.py | 275 ++++++++++++++++++++++++++++++++-
1 file changed, 274 insertions(+), 1 deletion(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index dff00b790d..ffe65ff55d 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -24,7 +24,8 @@
Surface preprocessing workflows.
**sMRIPrep** uses FreeSurfer to reconstruct surfaces from T1w/T2w
-structural images.
+structural images or FastSurfer for a machine learning-accelerated
+alternative using only T1w structural images.
"""
from nipype.pipeline import engine as pe
@@ -36,6 +37,7 @@
)
from ..interfaces.freesurfer import ReconAll
+from ..interfaces import fastsurfer as fastsurf
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
from niworkflows.interfaces.freesurfer import (
@@ -48,7 +50,278 @@
)
from niworkflows.interfaces.surf import NormalizeSurf
+def init_fastsurf_recon_wf(*, omp_nthreads, name="fastsurf_recon_wf"):
+ r"""
+ Reconstruct anatomical surfaces using FastSurfer CNN and ``recon_surf``,
+ an alternative to FreeSurfer's ``recon-all``.
+
+ First, FastSurfer CNN creates a segmentation using the T1w structural image.
+ This is followed by FastSurfer ``recon_surf`` processing of the surface,
+ along with surface registration to support cross-subject comparison
+ using the ``--surfeg`` argument to FastSurfer.
+
+ For example, a subject with only one session with a T1w image
+ would be processed by the following command::
+
+ $ /opt/FastSurfer/run_fastsurfer.sh --fs_license /path/to/freesurfer/license \
+ --t1 /sub-/anat/sub-_T1w.nii.gz \
+ --sid sub- --sd /fastsurfer --surfreg
+
+ Similar to the Freesurfer workflow second phase, we then
+ import an externally computed skull-stripping mask.
+ This workflow refines the external brainmask using the internal mask
+ implicit the FastSurfer's ``aseg.mgz`` segmentation,
+ to reconcile ANTs' and FreeSurfer's brain masks.
+
+ First, the ``aseg.mgz`` mask from FastSurfer is refined in two
+ steps, using binary morphological operations:
+
+ 1. With a binary closing operation the sulci are included
+ into the mask. This results in a smoother brain mask
+ that does not exclude deep, wide sulci.
+
+ 2. Fill any holes (typically, there could be a hole next to
+ the pineal gland and the corpora quadrigemina if the great
+ cerebral brain is segmented out).
+
+ Second, the brain mask is grown, including pixels that have a high likelihood
+ to the GM tissue distribution:
+
+ 3. Dilate and substract the brain mask, defining the region to search for candidate
+ pixels that likely belong to cortical GM.
+
+ 4. Pixels found in the search region that are labeled as GM by ANTs
+ (during ``antsBrainExtraction.sh``) are directly added to the new mask.
+
+ 5. Otherwise, estimate GM tissue parameters locally in patches of ``ww`` size,
+ and test the likelihood of the pixel to belong in the GM distribution.
+
+ This procedure is inspired on mindboggle's solution to the problem:
+ https://github.com/nipy/mindboggle/blob/7f91faaa7664d820fe12ccc52ebaf21d679795e2/mindboggle/guts/segment.py#L1660
+
+ Memory annotations for FastSurfer are based off `their documentation
+ `_.
+ They recommend 8GB CPU RAM and 8GB NVIDIA GPU RAM to run a single batch.
+
+ Workflow Graph
+ .. workflow::
+ :graph2use: orig
+ :simple_form: yes
+
+ from smriprep.workflows.surfaces import init_fastsurf_recon_wf
+ wf = init_fastsurf_recon_wf(omp_nthreads=1)
+
+ Required arguments
+ ==================
+ sd
+ Output directory
+ sid
+ Subject ID for directory inside ``sd`` to be created
+ t1
+ T1 full head input (not bias corrected, global path).
+ The 'network was trained with conformed images
+ (UCHAR, 256x256x256, 1 mm voxels and standard slice orientation).
+ These specifications are checked in the ``eval.py`` script and the image
+ is automatically conformed if it does not comply.
+ fs_license
+ Path to FreeSurfer license key file.
+
+ Optional arguments
+ ==================
+
+ Network specific arguments
+ --------------------------
+ seg
+ Global path with filename of segmentation
+ (where and under which name to store it).
+ Default location
+ ``$SUBJECTS_DIR/$sid/mri/aparc.DKTatlas+aseg.deep.mgz``
+ weights_sag
+ Pretrained weights of sagittal network.
+ Default
+ ``../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
+ weights_ax
+ Pretrained weights of axial network.
+ Default
+ ``../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
+ weights_cor
+ Pretrained weights of coronal network.
+ Default
+ ``../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
+ seg_log
+ Name and location for the log-file for the segmentation (FastSurferCNN).
+ Default '$SUBJECTS_DIR/$sid/scripts/deep-seg.log'
+ clean_seg
+ Flag to clean up FastSurferCNN segmentation
+ run_viewagg_on
+ Define where the view aggregation should be run on.
+ By default, the program checks if you have enough memory to run
+ the view aggregation on the gpu. The total memory is considered for this decision.
+ If this fails, or you actively overwrote the check with setting
+ ``run_viewagg_on cpu``, view agg is run on the cpu.
+ Equivalently, if you define ``--run_viewagg_on gpu``, view agg will be run on the gpu
+ (no memory check will be done).
+ no_cuda
+ Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)
+ batch
+ Batch size for inference. Default 16. Lower this to reduce memory requirement
+ order
+ Order of interpolation for mri_convert T1 before segmentation
+ ``(0=nearest, 1=linear(default), 2=quadratic, 3=cubic)``
+
+ Surface pipeline arguments
+ --------------------------
+ fstess
+ Use ``mri_tesselate`` instead of marching cube (default) for surface creation
+ fsqsphere
+ Use FreeSurfer default instead of
+ novel spectral spherical projection for qsphere
+ fsaparc
+ Use FS aparc segmentations in addition to DL prediction
+ (slower in this case and usually the mapped ones from the DL prediction are fine)
+ surfreg
+ Create Surface-Atlas ``sphere.reg`` registration with FreeSurfer
+ (for cross-subject correspondence or other mappings)
+ parallel
+ Run both hemispheres in parallel
+ threads
+ Set openMP and ITK threads
+
+ Other
+ ----
+ py
+ which python version to use.
+ Default ``python3.6``
+ seg_only
+ only run FastSurferCNN
+ (generate segmentation, do not run the surface pipeline)
+ surf_only
+ only run the surface pipeline ``recon_surf``.
+ The segmentation created by FastSurferCNN must already exist in this case.
+
+
+ """
+ workflow = Workflow(name=name)
+ workflow.__desc__ = """\
+Brain surfaces were reconstructed using `recon-surf` [FastSurfer (fastsurfer_version},
+@fastsurfer], and the brain mask estimated
+previously was refined with a custom variation of the method to reconcile
+ANTs-derived and FastSurfer-derived segmentations of the cortical
+gray-matter of Mindboggle [RRID:SCR_002438, @mindboggle].
+""".format(
+ fastsurfer_version="1.0.1"
+ )
+
+ inputnode = pe.Node(
+ niu.IdentityInterface(
+ fields=[
+ "t1w",
+ "skullstripped_t1",
+ "corrected_t1",
+ "ants_segs",
+ "subjects_dir",
+ "subject_id",
+ ]
+ ),
+ name="inputnode",
+ )
+ outputnode = pe.Node(
+ niu.IdentityInterface(
+ fields=[
+ "subjects_dir",
+ "subject_id",
+ "t1w2fsnative_xfm",
+ "fsnative2t1w_xfm",
+ "surfaces",
+ "out_brainmask",
+ "out_aseg",
+ "out_aparc",
+ ]
+ ),
+ name="outputnode",
+ )
+
+ #placeholder, create and import FastSurfDetectInputs
+ fastsurf_recon_config = pe.Node(fastsurf.FastSurfDetectInputs(), name="fastsurf_recon_config")
+
+ fov_check = pe.Node(niu.Function(function=_check_cw256), name="fov_check")
+
+ fsnative2t1w_xfm = pe.Node(
+ RobustRegister(auto_sens=True, est_int_scale=True), name="fsnative2t1w_xfm")
+ t1w2fsnative_xfm = pe.Node(
+ LTAConvert(out_lta=True, invert=True), name="t1w2fsnative_xfm")
+
+ gifti_surface_wf = init_gifti_surface_wf()
+ aseg_to_native_wf = init_segs_to_native_wf()
+ aparc_to_native_wf = init_segs_to_native_wf(segmentation="aparc_aseg")
+ refine = pe.Node(RefineBrainMask(), name="refine")
+ #change below to make FastSurfer specific
+ fastsurfsource = pe.Node(nio.FreeSurferSource(), name="fs_datasource")
+
+ fastsurf_recon = pe.Node(
+ fastsurf.FastSCommand(threads=omp_nthreads),
+ name="fastsurf_recon",
+ n_procs=omp_nthreads,
+ mem_gb=5,
+ )
+ fastsurf_recon.interface._can_resume = False
+ fastsurf_recon.interface._always_run = True
+
+ skull_strip_extern = pe.Node(FSInjectBrainExtracted(), name="skull_strip_extern")
+
+ fsnative2t1w_xfm = pe.Node(
+ RobustRegister(auto_sens=True, est_int_scale=True), name="fsnative2t1w_xfm"
+ )
+ t1w2fsnative_xfm = pe.Node(
+ LTAConvert(out_lta=True, invert=True), name="t1w2fsnative_xfm"
+ )
+
+ # fmt:off
+ workflow.connect([
+ # Configuration
+ (inputnode, fastsurf_recon_config, [('t1w', 't1w_list')]),
+ # Passing subjects_dir / subject_id enforces serial order
+ (inputnode, fastsurf_recon, [('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id')]),
+ (fastsurf_recon, skull_strip_extern, [('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id')]),
+ (skull_strip_extern, gifti_surface_wf, [
+ ('outputnode.subjects_dir', 'inputnode.subjects_dir'),
+ ('outputnode.subject_id', 'inputnode.subject_id')]),
+ # Reconstruction phases
+ (inputnode, fastsurf_recon, [('t1w', 'T1_files')]),
+ (inputnode, fov_check, [('t1w', 'in_files')]),
+ (fov_check, fastsurf_recon, [('out', 'flags')]),
+ (inputnode, skull_strip_extern, [('skullstripped_t1', 'in_brain')]),
+ # Construct transform from FreeSurfer conformed image to sMRIPrep
+ # reoriented image
+ (inputnode, fsnative2t1w_xfm, [('t1w', 'target_file')]),
+ (fastsurf_recon, fsnative2t1w_xfm, [('T1', 'source_file')]),
+ (fsnative2t1w_xfm, gifti_surface_wf, [
+ ('out_reg_file', 'inputnode.fsnative2t1w_xfm')]),
+ (fsnative2t1w_xfm, t1w2fsnative_xfm, [('out_reg_file', 'in_lta')]),
+ # Refine ANTs mask, deriving new mask from FS' aseg
+ (inputnode, refine, [('corrected_t1', 'in_anat'),
+ ('ants_segs', 'in_ants')]),
+ (inputnode, aseg_to_native_wf, [('corrected_t1', 'inputnode.in_file')]),
+ (fsnative2t1w_xfm, aseg_to_native_wf, [('out_reg_file', 'inputnode.fsnative2t1w_xfm')]),
+ (inputnode, aparc_to_native_wf, [('corrected_t1', 'inputnode.in_file')]),
+ (fsnative2t1w_xfm, aparc_to_native_wf, [('out_reg_file', 'inputnode.fsnative2t1w_xfm')]),
+ (aseg_to_native_wf, refine, [('outputnode.out_file', 'in_aseg')]),
+
+ # Output
+ (gifti_surface_wf, outputnode, [('outputnode.surfaces', 'surfaces')]),
+ (t1w2fsnative_xfm, outputnode, [('out_lta', 't1w2fsnative_xfm')]),
+ (fsnative2t1w_xfm, outputnode, [('out_reg_file', 'fsnative2t1w_xfm')]),
+ (refine, outputnode, [('out_file', 'out_brainmask')]),
+ (aseg_to_native_wf, outputnode, [('outputnode.out_file', 'out_aseg')]),
+ (aparc_to_native_wf, outputnode, [('outputnode.out_file', 'out_aparc')]),
+ ])
+ # fmt:on
+
+ return workflow
+
def init_surface_recon_wf(*, omp_nthreads, hires, name="surface_recon_wf"):
r"""
Reconstruct anatomical surfaces using FreeSurfer's ``recon-all``.
From 9d58df91173f74c5419aabb9ab1ec41aa206c688 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 27 Apr 2022 18:51:58 -0500
Subject: [PATCH 040/220] Add logging of hires if FastSurfer for future use of
VINN
---
smriprep/workflows/surfaces.py | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index ffe65ff55d..bc342b2661 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -49,8 +49,11 @@
RefineBrainMask,
)
from niworkflows.interfaces.surf import NormalizeSurf
+from nipype import logging
-def init_fastsurf_recon_wf(*, omp_nthreads, name="fastsurf_recon_wf"):
+LOGGER = logging.getLogger("nipype.workflow")
+
+def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
r"""
Reconstruct anatomical surfaces using FastSurfer CNN and ``recon_surf``,
an alternative to FreeSurfer's ``recon-all``.
@@ -240,6 +243,11 @@ def init_fastsurf_recon_wf(*, omp_nthreads, name="fastsurf_recon_wf"):
),
name="outputnode",
)
+
+ #null for now, placeholder for FastSurfer VINN hires support
+ if hires:
+ if logger:
+ logger.warn(f'High-resolution {hires} specified, but not currently supported. Ignoring for now')
#placeholder, create and import FastSurfDetectInputs
fastsurf_recon_config = pe.Node(fastsurf.FastSurfDetectInputs(), name="fastsurf_recon_config")
From f93e688d51373b822154592b18f21d710ba65d09 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 27 Apr 2022 18:56:49 -0500
Subject: [PATCH 041/220] Initial draft of including FastSurfer recon wf
---
smriprep/workflows/anatomical.py | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 715362893a..e8d8dde2ac 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -54,7 +54,7 @@
)
from .norm import init_anat_norm_wf
from .outputs import init_anat_reports_wf, init_anat_derivatives_wf
-from .surfaces import init_surface_recon_wf
+from .surfaces import init_surface_recon_wf, init_fastsurf_recon_wf
LOGGER = logging.getLogger("nipype.workflow")
@@ -125,6 +125,10 @@ def init_anat_preproc_wf(
longitudinal : :obj:`bool`
Create unbiased structural template, regardless of number of inputs
(may increase runtime)
+ fastsurfer : :obj:`bool`
+ Enable FastSurfer surface reconstruction (shorter runtime than
+ the FreeSurfer workflow). Uses similar input variables and output
+ file structure as FreeSurfer.
t1w : :obj:`list`
List of T1-weighted structural images.
omp_nthreads : :obj:`int`
@@ -521,14 +525,20 @@ def _check_img(img):
# check for FastSurfer .mgz files and
# touch mri/aseg.auto_noCCseg.label_intensities.txt
- # to prevent failure in surfaces.py (temporary fix)
+ # to prevent failure in surfaces.py (temporary fix - DEPRECATED)
check_fastsurfer = pe.Node(
niu.Function(function=_check_fastsurfer), overwrite=True, name="check_fastsurfer"
)
check_fastsurfer.inputs.logger = LOGGER
+ #Select which surface reconstruction workflow based on CLI arguments
+ if freesurfer:
+ recon_wf = init_surface_recon_wf()
+ elif fastsurfer:
+ recon_wf = init_fastsurf_recon_wf()
+
# 5. Surface reconstruction (--fs-no-reconall not set)
- surface_recon_wf = init_surface_recon_wf(
+ surface_recon_wf = recon_wf(
name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires
)
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
From 2e8957360d5e9fe41c572519100800185c702956 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 27 Apr 2022 19:07:26 -0500
Subject: [PATCH 042/220] Draft FastSurferSource
---
smriprep/interfaces/fastsurfer.py | 201 ++++++++++++++++++++++++++++++
1 file changed, 201 insertions(+)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 34f840b064..30927668cb 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -17,6 +17,8 @@
CommandLineInputSpec,
isdefined,
TraitedSpec,
+ BaseInterface,
+ BaseInterfaceInputSpec,
File,
PackageInfo,
)
@@ -290,6 +292,205 @@ class FastSTraitedOutputSpec(TraitedSpec):
desc="FastSurfer CNN + Surface Pipeline equivalent of recon-all outputs"
)
+
+class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
+ sd = Directory(
+ exists=True, mandatory=True, desc="FastSurfer subjects directory."
+ )
+ sid = Str(mandatory=True, desc="Subject name for whom to retrieve data")
+ t1
+
+
+class FastSurfSourceOutputSpec(TraitedSpec):
+ T1 = File(exists=True, desc="Intensity normalized whole-head volume", loc="mri")
+ aseg = File(
+ exists=True,
+ loc="mri",
+ desc="Volumetric map of regions from automatic segmentation",
+ )
+ brain = File(exists=True, desc="Intensity normalized brain-only volume", loc="mri")
+ brainmask = File(exists=True, desc="Skull-stripped (brain-only) volume", loc="mri")
+ filled = File(exists=True, desc="Subcortical mass volume", loc="mri")
+ norm = File(exists=True, desc="Normalized skull-stripped volume", loc="mri")
+ nu = File(exists=True, desc="Non-uniformity corrected whole-head volume", loc="mri")
+ orig = File(exists=True, desc="Base image conformed to Freesurfer space", loc="mri")
+ rawavg = File(
+ exists=True, desc="Volume formed by averaging input images", loc="mri"
+ )
+ ribbon = OutputMultiPath(
+ File(exists=True),
+ desc="Volumetric maps of cortical ribbons",
+ loc="mri",
+ altkey="*ribbon",
+ )
+ wm = File(exists=True, desc="Segmented white-matter volume", loc="mri")
+ wmparc = File(
+ exists=True,
+ loc="mri",
+ desc="Aparc parcellation projected into subcortical white matter",
+ )
+ curv = OutputMultiPath(
+ File(exists=True), desc="Maps of surface curvature", loc="surf"
+ )
+ avg_curv = OutputMultiPath(
+ File(exists=True),
+ desc="Average atlas curvature, sampled to subject",
+ loc="surf",
+ )
+ inflated = OutputMultiPath(
+ File(exists=True), desc="Inflated surface meshes", loc="surf"
+ )
+ pial = OutputMultiPath(
+ File(exists=True), desc="Gray matter/pia mater surface meshes", loc="surf"
+ )
+ area_pial = OutputMultiPath(
+ File(exists=True),
+ desc="Mean area of triangles each vertex on the pial surface is "
+ "associated with",
+ loc="surf",
+ altkey="area.pial",
+ )
+ curv_pial = OutputMultiPath(
+ File(exists=True),
+ desc="Curvature of pial surface",
+ loc="surf",
+ altkey="curv.pial",
+ )
+ smoothwm = OutputMultiPath(
+ File(exists=True), loc="surf", desc="Smoothed original surface meshes"
+ )
+ sphere = OutputMultiPath(
+ File(exists=True), desc="Spherical surface meshes", loc="surf"
+ )
+ sulc = OutputMultiPath(
+ File(exists=True), desc="Surface maps of sulcal depth", loc="surf"
+ )
+ thickness = OutputMultiPath(
+ File(exists=True), loc="surf", desc="Surface maps of cortical thickness"
+ )
+ volume = OutputMultiPath(
+ File(exists=True), desc="Surface maps of cortical volume", loc="surf"
+ )
+ white = OutputMultiPath(
+ File(exists=True), desc="White/gray matter surface meshes", loc="surf"
+ )
+ jacobian_white = OutputMultiPath(
+ File(exists=True),
+ desc="Distortion required to register to spherical atlas",
+ loc="surf",
+ )
+ graymid = OutputMultiPath(
+ File(exists=True),
+ desc="Graymid/midthickness surface meshes",
+ loc="surf",
+ altkey=["graymid", "midthickness"],
+ )
+ label = OutputMultiPath(
+ File(exists=True),
+ desc="Volume and surface label files",
+ loc="label",
+ altkey="*label",
+ )
+ annot = OutputMultiPath(
+ File(exists=True), desc="Surface annotation files", loc="label", altkey="*annot"
+ )
+ aparc_aseg = OutputMultiPath(
+ File(exists=True),
+ loc="mri",
+ altkey="aparc*aseg",
+ desc="Aparc parcellation projected into aseg volume",
+ )
+ sphere_reg = OutputMultiPath(
+ File(exists=True),
+ loc="surf",
+ altkey="sphere.reg",
+ desc="Spherical registration file",
+ )
+ aseg_stats = OutputMultiPath(
+ File(exists=True),
+ loc="stats",
+ altkey="aseg",
+ desc="Automated segmentation statistics file",
+ )
+ wmparc_stats = OutputMultiPath(
+ File(exists=True),
+ loc="stats",
+ altkey="wmparc",
+ desc="White matter parcellation statistics file",
+ )
+ aparc_stats = OutputMultiPath(
+ File(exists=True),
+ loc="stats",
+ altkey="aparc",
+ desc="Aparc parcellation statistics files",
+ )
+ BA_stats = OutputMultiPath(
+ File(exists=True),
+ loc="stats",
+ altkey="BA",
+ desc="Brodmann Area statistics files",
+ )
+ curv_stats = OutputMultiPath(
+ File(exists=True), loc="stats", altkey="curv", desc="Curvature statistics files"
+ )
+ entorhinal_exvivo_stats = OutputMultiPath(
+ File(exists=True),
+ loc="stats",
+ altkey="entorhinal_exvivo",
+ desc="Entorhinal exvivo statistics files",
+ )
+
+
+class FastSurferSource(IOBase):
+ """Generates FastSurfer subject info from their directories.
+
+ """
+
+ input_spec = FSSourceInputSpec
+ output_spec = FSSourceOutputSpec
+ _always_run = True
+ _additional_metadata = ["loc", "altkey"]
+
+ def _get_files(self, path, key, dirval, altkey=None):
+ globsuffix = ""
+ if dirval == "mri":
+ globsuffix = ".mgz"
+ elif dirval == "stats":
+ globsuffix = ".stats"
+ globprefix = ""
+ if dirval in ("surf", "label", "stats"):
+ if self.inputs.hemi != "both":
+ globprefix = self.inputs.hemi + "."
+ else:
+ globprefix = "?h."
+ if key in ("aseg_stats", "wmparc_stats"):
+ globprefix = ""
+ elif key == "ribbon":
+ if self.inputs.hemi != "both":
+ globprefix = self.inputs.hemi + "."
+ else:
+ globprefix = "*"
+ keys = ensure_list(altkey) if altkey else [key]
+ globfmt = os.path.join(path, dirval, "".join((globprefix, "{}", globsuffix)))
+ return [
+ os.path.abspath(f) for key in keys for f in glob.glob(globfmt.format(key))
+ ]
+
+ def _list_outputs(self):
+ subjects_dir = self.inputs.subjects_dir
+ subject_path = os.path.join(subjects_dir, self.inputs.subject_id)
+ output_traits = self._outputs()
+ outputs = output_traits.get()
+ for k in list(outputs.keys()):
+ val = self._get_files(
+ subject_path,
+ k,
+ output_traits.traits()[k].loc,
+ output_traits.traits()[k].altkey,
+ )
+ if val:
+ outputs[k] = simplify_list(val)
+ return outputs
class FastSCommand(CommandLine):
r"""
From e5dab42eb8921cfece09d9449de5cb9be81e2ecf Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 27 Apr 2022 19:22:34 -0500
Subject: [PATCH 043/220] Separate surface workflows for FastSurfer and
FreeSurfer
---
smriprep/workflows/anatomical.py | 155 ++++++++++++++++++++-----------
1 file changed, 101 insertions(+), 54 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index e8d8dde2ac..f68002bf10 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -534,62 +534,109 @@ def _check_img(img):
#Select which surface reconstruction workflow based on CLI arguments
if freesurfer:
recon_wf = init_surface_recon_wf()
+ applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
+ # 5. Surface reconstruction (--fs-no-reconall not set)
+ surface_recon_wf = recon_wf(
+ name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires
+ )
+ # fmt:off
+ workflow.connect([
+ (inputnode, check_fastsurfer, [
+ ('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id')]),
+ (inputnode, fs_isrunning, [
+ ('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id')]),
+ (inputnode, surface_recon_wf, [
+ ('t2w', 'inputnode.t2w'),
+ ('flair', 'inputnode.flair'),
+ ('subject_id', 'inputnode.subject_id')]),
+ (fs_isrunning, surface_recon_wf, [('out', 'inputnode.subjects_dir')]),
+ (anat_validate, surface_recon_wf, [('out_file', 'inputnode.t1w')]),
+ (brain_extraction_wf, surface_recon_wf, [
+ (('outputnode.out_file', _pop), 'inputnode.skullstripped_t1'),
+ ('outputnode.out_segm', 'inputnode.ants_segs'),
+ (('outputnode.bias_corrected', _pop), 'inputnode.corrected_t1')]),
+ (brain_extraction_wf, applyrefined, [
+ (('outputnode.bias_corrected', _pop), 'in_file')]),
+ (surface_recon_wf, applyrefined, [
+ ('outputnode.out_brainmask', 'mask_file')]),
+ (surface_recon_wf, outputnode, [
+ ('outputnode.subjects_dir', 'subjects_dir'),
+ ('outputnode.subject_id', 'subject_id'),
+ ('outputnode.t1w2fsnative_xfm', 't1w2fsnative_xfm'),
+ ('outputnode.fsnative2t1w_xfm', 'fsnative2t1w_xfm'),
+ ('outputnode.surfaces', 'surfaces'),
+ ('outputnode.out_aseg', 't1w_aseg'),
+ ('outputnode.out_aparc', 't1w_aparc')]),
+ (applyrefined, buffernode, [('out_file', 't1w_brain')]),
+ (surface_recon_wf, buffernode, [
+ ('outputnode.out_brainmask', 't1w_mask')]),
+ (surface_recon_wf, anat_reports_wf, [
+ ('outputnode.subject_id', 'inputnode.subject_id'),
+ ('outputnode.subjects_dir', 'inputnode.subjects_dir')]),
+ (surface_recon_wf, anat_derivatives_wf, [
+ ('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
+ ('outputnode.out_aparc', 'inputnode.t1w_fs_aparc'),
+ ]),
+ (outputnode, anat_derivatives_wf, [
+ ('t1w2fsnative_xfm', 'inputnode.t1w2fsnative_xfm'),
+ ('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
+ ('surfaces', 'inputnode.surfaces'),
+ ]),
+ ])
+ # fmt:on
+
elif fastsurfer:
recon_wf = init_fastsurf_recon_wf()
-
- # 5. Surface reconstruction (--fs-no-reconall not set)
- surface_recon_wf = recon_wf(
- name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires
- )
- applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
- # fmt:off
- workflow.connect([
- (inputnode, check_fastsurfer, [
- ('subjects_dir', 'subjects_dir'),
- ('subject_id', 'subject_id')]),
- (inputnode, fs_isrunning, [
- ('subjects_dir', 'subjects_dir'),
- ('subject_id', 'subject_id')]),
- (inputnode, surface_recon_wf, [
- ('t2w', 'inputnode.t2w'),
- ('flair', 'inputnode.flair'),
- ('subject_id', 'inputnode.subject_id')]),
- (fs_isrunning, surface_recon_wf, [('out', 'inputnode.subjects_dir')]),
- (anat_validate, surface_recon_wf, [('out_file', 'inputnode.t1w')]),
- (brain_extraction_wf, surface_recon_wf, [
- (('outputnode.out_file', _pop), 'inputnode.skullstripped_t1'),
- ('outputnode.out_segm', 'inputnode.ants_segs'),
- (('outputnode.bias_corrected', _pop), 'inputnode.corrected_t1')]),
- (brain_extraction_wf, applyrefined, [
- (('outputnode.bias_corrected', _pop), 'in_file')]),
- (surface_recon_wf, applyrefined, [
- ('outputnode.out_brainmask', 'mask_file')]),
- (surface_recon_wf, outputnode, [
- ('outputnode.subjects_dir', 'subjects_dir'),
- ('outputnode.subject_id', 'subject_id'),
- ('outputnode.t1w2fsnative_xfm', 't1w2fsnative_xfm'),
- ('outputnode.fsnative2t1w_xfm', 'fsnative2t1w_xfm'),
- ('outputnode.surfaces', 'surfaces'),
- ('outputnode.out_aseg', 't1w_aseg'),
- ('outputnode.out_aparc', 't1w_aparc')]),
- (applyrefined, buffernode, [('out_file', 't1w_brain')]),
- (surface_recon_wf, buffernode, [
- ('outputnode.out_brainmask', 't1w_mask')]),
- (surface_recon_wf, anat_reports_wf, [
- ('outputnode.subject_id', 'inputnode.subject_id'),
- ('outputnode.subjects_dir', 'inputnode.subjects_dir')]),
- (surface_recon_wf, anat_derivatives_wf, [
- ('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
- ('outputnode.out_aparc', 'inputnode.t1w_fs_aparc'),
- ]),
- (outputnode, anat_derivatives_wf, [
- ('t1w2fsnative_xfm', 'inputnode.t1w2fsnative_xfm'),
- ('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
- ('surfaces', 'inputnode.surfaces'),
- ]),
- ])
- # fmt:on
-
+ applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
+ # 5. Surface reconstruction (--fs-no-reconall not set)
+ fastsurf_recon_wf = recon_wf(
+ name="fastsurf_recon_wf", omp_nthreads=omp_nthreads, hires=hires
+ )
+ # fmt:off
+ workflow.connect([
+ #replace check_fastsurfer with check for only CNN segmentation outputs or full outputs
+ (inputnode, check_fastsurfer, [
+ ('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id')]),
+ (inputnode, fastsurf_recon_wf, [
+ ('subject_id', 'inputnode.subject_id')]),
+ (anat_validate, fastsurf_recon_wf, [('out_file', 'inputnode.t1w')]),
+ (brain_extraction_wf, fastsurf_recon_wf, [
+ (('outputnode.out_file', _pop), 'inputnode.skullstripped_t1'),
+ ('outputnode.out_segm', 'inputnode.ants_segs'),
+ (('outputnode.bias_corrected', _pop), 'inputnode.corrected_t1')]),
+ (brain_extraction_wf, applyrefined, [
+ (('outputnode.bias_corrected', _pop), 'in_file')]),
+ (fastsurf_recon_wf, applyrefined, [
+ ('outputnode.out_brainmask', 'mask_file')]),
+ (fastsurf_recon_wf, outputnode, [
+ ('outputnode.subjects_dir', 'subjects_dir'),
+ ('outputnode.subject_id', 'subject_id'),
+ ('outputnode.t1w2fsnative_xfm', 't1w2fsnative_xfm'),
+ ('outputnode.fsnative2t1w_xfm', 'fsnative2t1w_xfm'),
+ ('outputnode.surfaces', 'surfaces'),
+ ('outputnode.out_aseg', 't1w_aseg'),
+ ('outputnode.out_aparc', 't1w_aparc')]),
+ (applyrefined, buffernode, [('out_file', 't1w_brain')]),
+ (fastsurf_recon_wf, buffernode, [
+ ('outputnode.out_brainmask', 't1w_mask')]),
+ (fastsurf_recon_wf, anat_reports_wf, [
+ ('outputnode.subject_id', 'inputnode.subject_id'),
+ ('outputnode.subjects_dir', 'inputnode.subjects_dir')]),
+ (fastsurf_recon_wf, anat_derivatives_wf, [
+ ('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
+ ('outputnode.out_aparc', 'inputnode.t1w_fs_aparc'),
+ ]),
+ (outputnode, anat_derivatives_wf, [
+ ('t1w2fsnative_xfm', 'inputnode.t1w2fsnative_xfm'),
+ ('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
+ ('surfaces', 'inputnode.surfaces'),
+ ]),
+ ])
+ # fmt:on
+
return workflow
From de510df4f46e3361d0edfdfb38609906ff058c6c Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 27 Apr 2022 19:24:21 -0500
Subject: [PATCH 044/220] Include fastsurfer CLI argument
---
smriprep/workflows/anatomical.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index f68002bf10..c5c07c1648 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -65,6 +65,7 @@ def init_anat_preproc_wf(
freesurfer,
hires,
longitudinal,
+ fastsurfer,
t1w,
omp_nthreads,
output_dir,
@@ -101,6 +102,7 @@ def init_anat_preproc_wf(
freesurfer=True,
hires=True,
longitudinal=False,
+ fastsurfer=False,
t1w=['t1w.nii.gz'],
omp_nthreads=1,
output_dir='.',
From eddfeae3081a9fafb4e211ebb0e669df9b512465 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 28 Apr 2022 15:18:57 -0500
Subject: [PATCH 045/220] Format IO specs
---
smriprep/interfaces/fastsurfer.py | 123 +++++++++++++++++++++++-------
1 file changed, 97 insertions(+), 26 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 30927668cb..ae91518f5e 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -295,27 +295,70 @@ class FastSTraitedOutputSpec(TraitedSpec):
class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
sd = Directory(
- exists=True, mandatory=True, desc="FastSurfer subjects directory."
+ exists=True,
+ argstr="--sd %s",
+ mandatory=True,
+ desc="Subjects directory"
+ )
+ sid = traits.String(
+ exists=True,
+ argstr="--sid %s",
+ mandatory=True,
+ desc="Subject ID"
+ )
+ t1 = = File(
+ exists=True,
+ mandatory=True,
+ argstr="--t1 %s",
+ desc="T1 full head input (not bias corrected, global path)"
)
- sid = Str(mandatory=True, desc="Subject name for whom to retrieve data")
- t1
class FastSurfSourceOutputSpec(TraitedSpec):
- T1 = File(exists=True, desc="Intensity normalized whole-head volume", loc="mri")
+ T1 = File(
+ exists=True,
+ desc="Intensity normalized whole-head volume",
+ loc="mri"
+ )
aseg = File(
exists=True,
loc="mri",
desc="Volumetric map of regions from automatic segmentation",
)
- brain = File(exists=True, desc="Intensity normalized brain-only volume", loc="mri")
- brainmask = File(exists=True, desc="Skull-stripped (brain-only) volume", loc="mri")
- filled = File(exists=True, desc="Subcortical mass volume", loc="mri")
- norm = File(exists=True, desc="Normalized skull-stripped volume", loc="mri")
- nu = File(exists=True, desc="Non-uniformity corrected whole-head volume", loc="mri")
- orig = File(exists=True, desc="Base image conformed to Freesurfer space", loc="mri")
+ brain = File(
+ exists=True,
+ desc="Intensity normalized brain-only volume",
+ loc="mri"
+ )
+ brainmask = File(
+ exists=True,
+ desc="Skull-stripped (brain-only) volume",
+ loc="mri"
+ )
+ filled = File(
+ exists=True,
+ desc="Subcortical mass volume",
+ loc="mri"
+ )
+ norm = File(
+ exists=True,
+ desc="Normalized skull-stripped volume",
+ loc="mri"
+ )
+ nu = File(
+ exists=True,
+ desc="Non-uniformity corrected whole-head volume",
+ loc="mri"
+ )
+ orig = File(
+ exists=True,
+ desc="Base image conformed to Freesurfer space",
+ loc="mri"
+ )
rawavg = File(
- exists=True, desc="Volume formed by averaging input images", loc="mri"
+ exists=True,
+ desc="Volume formed by averaging input images",
+ loc="mri"
)
ribbon = OutputMultiPath(
File(exists=True),
@@ -323,25 +366,35 @@ class FastSurfSourceOutputSpec(TraitedSpec):
loc="mri",
altkey="*ribbon",
)
- wm = File(exists=True, desc="Segmented white-matter volume", loc="mri")
+ wm = File(
+ exists=True,
+ desc="Segmented white-matter volume",
+ loc="mri"
+ )
wmparc = File(
exists=True,
loc="mri",
desc="Aparc parcellation projected into subcortical white matter",
)
curv = OutputMultiPath(
- File(exists=True), desc="Maps of surface curvature", loc="surf"
+ File(exists=True),
+ desc="Maps of surface curvature",
+ loc="surf"
)
avg_curv = OutputMultiPath(
File(exists=True),
- desc="Average atlas curvature, sampled to subject",
+ desc="Average atlas curvature,sampled to subject",
loc="surf",
)
inflated = OutputMultiPath(
- File(exists=True), desc="Inflated surface meshes", loc="surf"
+ File(exists=True),
+ desc="Inflated surface meshes",
+ loc="surf"
)
pial = OutputMultiPath(
- File(exists=True), desc="Gray matter/pia mater surface meshes", loc="surf"
+ File(exists=True),
+ desc="Gray matter/pia mater surface meshes",
+ loc="surf"
)
area_pial = OutputMultiPath(
File(exists=True),
@@ -357,22 +410,34 @@ class FastSurfSourceOutputSpec(TraitedSpec):
altkey="curv.pial",
)
smoothwm = OutputMultiPath(
- File(exists=True), loc="surf", desc="Smoothed original surface meshes"
+ File(exists=True),
+ loc="surf",
+ desc="Smoothed original surface meshes"
)
sphere = OutputMultiPath(
- File(exists=True), desc="Spherical surface meshes", loc="surf"
+ File(exists=True),
+ desc="Spherical surface meshes",
+ loc="surf"
)
sulc = OutputMultiPath(
- File(exists=True), desc="Surface maps of sulcal depth", loc="surf"
+ File(exists=True),
+ desc="Surface maps of sulcal depth",
+ loc="surf"
)
thickness = OutputMultiPath(
- File(exists=True), loc="surf", desc="Surface maps of cortical thickness"
+ File(exists=True),
+ loc="surf",
+ desc="Surface maps of cortical thickness"
)
volume = OutputMultiPath(
- File(exists=True), desc="Surface maps of cortical volume", loc="surf"
+ File(exists=True),
+ desc="Surface maps of cortical volume",
+ loc="surf"
)
white = OutputMultiPath(
- File(exists=True), desc="White/gray matter surface meshes", loc="surf"
+ File(exists=True),
+ desc="White/gray matter surface meshes",
+ loc="surf"
)
jacobian_white = OutputMultiPath(
File(exists=True),
@@ -392,7 +457,10 @@ class FastSurfSourceOutputSpec(TraitedSpec):
altkey="*label",
)
annot = OutputMultiPath(
- File(exists=True), desc="Surface annotation files", loc="label", altkey="*annot"
+ File(exists=True),
+ desc="Surface annotation files",
+ loc="label",
+ altkey="*annot"
)
aparc_aseg = OutputMultiPath(
File(exists=True),
@@ -431,7 +499,10 @@ class FastSurfSourceOutputSpec(TraitedSpec):
desc="Brodmann Area statistics files",
)
curv_stats = OutputMultiPath(
- File(exists=True), loc="stats", altkey="curv", desc="Curvature statistics files"
+ File(exists=True),
+ loc="stats",
+ altkey="curv",
+ desc="Curvature statistics files"
)
entorhinal_exvivo_stats = OutputMultiPath(
File(exists=True),
@@ -446,8 +517,8 @@ class FastSurferSource(IOBase):
"""
- input_spec = FSSourceInputSpec
- output_spec = FSSourceOutputSpec
+ input_spec = FastSurfSourceInputSpec
+ output_spec = FastSurfSourceOutputSpec
_always_run = True
_additional_metadata = ["loc", "altkey"]
From b2e53765c0f2c826bf54f13217832ea859ffd10e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 28 Apr 2022 16:46:08 -0500
Subject: [PATCH 046/220] DRAFT: Adds more of output traits
---
smriprep/interfaces/fastsurfer.py | 67 +++++++++++++++++++++----------
1 file changed, 45 insertions(+), 22 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index ae91518f5e..f83e90589d 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -306,12 +306,18 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
mandatory=True,
desc="Subject ID"
)
- t1 = = File(
+ t1 = File(
exists=True,
mandatory=True,
argstr="--t1 %s",
desc="T1 full head input (not bias corrected, global path)"
)
+ fs_license = File(
+ exists=True,
+ mandatory=True,
+ argstr="--fs_license %s",
+ desc="Path to FreeSurfer license key file."
+ )
class FastSurfSourceOutputSpec(TraitedSpec):
@@ -376,6 +382,18 @@ class FastSurfSourceOutputSpec(TraitedSpec):
loc="mri",
desc="Aparc parcellation projected into subcortical white matter",
)
+ mni_log = OutputMultiPath(
+ File(exists=True),
+ desc="Non-uniformity correction log",
+ loc="mri",
+ altkey="mri_nu_correct.mni"
+ )
+ mni_log_bak = OutputMultiPath(
+ File(exists=True),
+ desc="Non-uniformity correction log bak",
+ loc="mri",
+ altkey="mri_nu_correct.mni"
+ )
curv = OutputMultiPath(
File(exists=True),
desc="Maps of surface curvature",
@@ -468,6 +486,12 @@ class FastSurfSourceOutputSpec(TraitedSpec):
altkey="aparc*aseg",
desc="Aparc parcellation projected into aseg volume",
)
+ aparc_aseg = OutputMultiPath(
+ File(exists=True),
+ loc="mri",
+ altkey="aparc*aseg",
+ desc="Aparc parcellation from DKT atlas projected into aseg volume",
+ )
sphere_reg = OutputMultiPath(
File(exists=True),
loc="surf",
@@ -483,32 +507,32 @@ class FastSurfSourceOutputSpec(TraitedSpec):
wmparc_stats = OutputMultiPath(
File(exists=True),
loc="stats",
- altkey="wmparc",
+ altkey="wmparc.DKTatlas.mapped",
desc="White matter parcellation statistics file",
)
aparc_stats = OutputMultiPath(
File(exists=True),
loc="stats",
- altkey="aparc",
+ altkey="aparc.DKTatlas.mapped",
desc="Aparc parcellation statistics files",
)
- BA_stats = OutputMultiPath(
- File(exists=True),
- loc="stats",
- altkey="BA",
- desc="Brodmann Area statistics files",
- )
curv_stats = OutputMultiPath(
File(exists=True),
loc="stats",
altkey="curv",
desc="Curvature statistics files"
)
- entorhinal_exvivo_stats = OutputMultiPath(
+ w_g_stats = OutputMultiPath(
+ File(exists=True),
+ loc="stats",
+ altkey="w*g.pct",
+ desc="White minus gray statistics files"
+ )
+ aseg_presurf_stats = OutputMultiPath(
File(exists=True),
loc="stats",
- altkey="entorhinal_exvivo",
- desc="Entorhinal exvivo statistics files",
+ altkey="aseg.presurf.hypos",
+ desc="Automated segmentation pre-surface recon statistics files"
)
@@ -526,21 +550,20 @@ def _get_files(self, path, key, dirval, altkey=None):
globsuffix = ""
if dirval == "mri":
globsuffix = ".mgz"
+ if key in ("mni_log"):
+ globsuffix = ".mgz"
+ elif key in ("mni_log_bak"):
+ globsuffix = ".log.bak"
elif dirval == "stats":
globsuffix = ".stats"
globprefix = ""
if dirval in ("surf", "label", "stats"):
- if self.inputs.hemi != "both":
- globprefix = self.inputs.hemi + "."
- else:
- globprefix = "?h."
- if key in ("aseg_stats", "wmparc_stats"):
- globprefix = ""
+ globprefix = "?h."
+ if key in ("aseg_stats", "aseg_presurf_stats". "wmparc_stats"):
+ globprefix = ""
elif key == "ribbon":
- if self.inputs.hemi != "both":
- globprefix = self.inputs.hemi + "."
- else:
- globprefix = "*"
+ globprefix = "*"
+ if key in ():
keys = ensure_list(altkey) if altkey else [key]
globfmt = os.path.join(path, dirval, "".join((globprefix, "{}", globsuffix)))
return [
From db2aeec855548e24e8fa4753eb251842d09b4913 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 28 Apr 2022 18:23:05 -0500
Subject: [PATCH 047/220] Debug Convert3D download and install failure in CI
---
Dockerfile | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 821b6727b6..f16586c158 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -207,15 +207,7 @@ ENV FSLDIR="/opt/fsl-6.0.5.1" \
FSLREMOTECALL="" \
FSLGECUDAQ="cuda.q" \
LD_LIBRARY_PATH="/opt/fsl-6.0.5.1/lib:$LD_LIBRARY_PATH"
-# switch back to en-US utf-8
-RUN apt-get update -qq && apt-get install locales && \
- sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
- locale-gen
-ENV LANG="en_US.UTF-8" \
- LC_ALL="en_US.UTF-8" \
- LANGUAGE="en_US:en"
-RUN ls /etc/ssl/certs/
-
+
# Convert3D (neurodocker build)
RUN echo "Downloading Convert3D ..." \
&& mkdir -p /opt/convert3d-1.0.0 \
@@ -226,6 +218,15 @@ RUN echo "Downloading Convert3D ..." \
--exclude "c3d-1.0.0-Linux-x86_64/bin/c3d_gui"
ENV C3DPATH="/opt/convert3d-1.0.0" \
PATH="/opt/convert3d-1.0.0/bin:$PATH"
+
+# switch back to en-US utf-8
+RUN apt-get update -qq && apt-get install locales && \
+ sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
+ locale-gen
+ENV LANG="en_US.UTF-8" \
+ LC_ALL="en_US.UTF-8" \
+ LANGUAGE="en_US:en"
+RUN ls /etc/ssl/certs/
# AFNI latest (neurodocker build)
RUN apt-get update -qq \
From 48c7193484efd7d42230a767b02638fb071400ea Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 28 Apr 2022 19:01:51 -0500
Subject: [PATCH 048/220] Include DKTatlas outputs, other files
---
smriprep/interfaces/fastsurfer.py | 79 +++++++++++++++++++++++++++++--
1 file changed, 74 insertions(+), 5 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index f83e90589d..9584e24848 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -358,7 +358,12 @@ class FastSurfSourceOutputSpec(TraitedSpec):
)
orig = File(
exists=True,
- desc="Base image conformed to Freesurfer space",
+ desc="Base image conformed to FastSurfer space",
+ loc="mri"
+ )
+ orig_nu = File(
+ exists=True,
+ desc="Base image conformed to Fastsurfer space and nonuniformity corrected",
loc="mri"
)
rawavg = File(
@@ -377,11 +382,23 @@ class FastSurfSourceOutputSpec(TraitedSpec):
desc="Segmented white-matter volume",
loc="mri"
)
+ wm_asegedit = OutputMultiPath(
+ File(exists=True),
+ desc="Edited white matter volume post-aseg",
+ loc="mri",
+ altkey="mri_nu_correct.mni"
+ )
wmparc = File(
exists=True,
loc="mri",
desc="Aparc parcellation projected into subcortical white matter",
)
+ wmparc_mapped = OutputMultiPath(
+ exists=True,
+ loc="mri",
+ desc="DKT atlas mapped Aparc into subcortical white matter",
+ altkey="wmparc.DKTatlas.mapped"
+ )
mni_log = OutputMultiPath(
File(exists=True),
desc="Non-uniformity correction log",
@@ -468,6 +485,18 @@ class FastSurfSourceOutputSpec(TraitedSpec):
loc="surf",
altkey=["graymid", "midthickness"],
)
+ defects = OutputMultiPath(
+ File(exists=True),
+ desc="Defects",
+ loc="surf",
+ altkey=["defect_borders", "defect_chull", "defect_labels"],
+ )
+ nofix = OutputMultiPath(
+ File(exists=True),
+ desc="Pre-tessellation original surface",
+ loc="surf",
+ altkey=["nofix"],
+ )
label = OutputMultiPath(
File(exists=True),
desc="Volume and surface label files",
@@ -480,24 +509,60 @@ class FastSurfSourceOutputSpec(TraitedSpec):
loc="label",
altkey="*annot"
)
+ aparc_ctab = OutputMultiPath(
+ File(exists=True),
+ loc="label",
+ altkey="aparc.annot.mapped.ctab",
+ desc="Aparc parcellation annotation ctab file",
+ )
+ mapped_024 = OutputMultiPath(
+ File(exists=True),
+ loc="label",
+ altkey="mapped*024",
+ desc="Mapped label files",
+ )
+ cortex = OutputMultiPath(
+ File(exists=True),
+ loc="label",
+ altkey="cortex",
+ desc="Cortex class label files",
+ )
aparc_aseg = OutputMultiPath(
File(exists=True),
loc="mri",
- altkey="aparc*aseg",
+ altkey="aparc?aseg",
desc="Aparc parcellation projected into aseg volume",
)
- aparc_aseg = OutputMultiPath(
+ aparc_dkt_aseg = OutputMultiPath(
File(exists=True),
loc="mri",
- altkey="aparc*aseg",
+ altkey="aparc.DKTatlas*aseg*",
desc="Aparc parcellation from DKT atlas projected into aseg volume",
)
+ segment_dat = OutputMultiPath(
+ File(exists=True),
+ loc="mri",
+ altkey="segment_dat",
+ desc="Segmentation .dat files",
+ )
+ filled_pretess = OutputMultiPath(
+ File(exists=True),
+ loc="mri",
+ altkey="filled*pretess*",
+ desc="Pre-tessellation filled volume files",
+ )
sphere_reg = OutputMultiPath(
File(exists=True),
loc="surf",
altkey="sphere.reg",
desc="Spherical registration file",
)
+ preaparc = OutputMultiPath(
+ File(exists=True),
+ loc="surf",
+ altkey="preaparc",
+ desc="Pre-Aparc files",
+ )
aseg_stats = OutputMultiPath(
File(exists=True),
loc="stats",
@@ -563,7 +628,11 @@ def _get_files(self, path, key, dirval, altkey=None):
globprefix = ""
elif key == "ribbon":
globprefix = "*"
- if key in ():
+ elif key == "aparc_ctab":
+ globprefix = ""
+ globsuffix = ""
+ elif key in ("nofix", "defects", "preaparc"):
+ globsuffix = "*"
keys = ensure_list(altkey) if altkey else [key]
globfmt = os.path.join(path, dirval, "".join((globprefix, "{}", globsuffix)))
return [
From 93e9ee5980956c3e8e48c366cf8e0c70b194091c Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 28 Apr 2022 19:04:46 -0500
Subject: [PATCH 049/220] Fix conditional for surface workflows
Removes unwanted blank line before `elif`
---
smriprep/workflows/anatomical.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index c5c07c1648..36b2fe70f9 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -588,7 +588,6 @@ def _check_img(img):
]),
])
# fmt:on
-
elif fastsurfer:
recon_wf = init_fastsurf_recon_wf()
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
From 9e8e22f0cf9d4431852aa528a1e90c2b61e569d4 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 28 Apr 2022 19:07:56 -0500
Subject: [PATCH 050/220] Increase mem for FastSurfer recon
Fixes memory requirement for FastSurfer recon
---
smriprep/workflows/surfaces.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index bc342b2661..9c5e37852d 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -270,7 +270,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
fastsurf.FastSCommand(threads=omp_nthreads),
name="fastsurf_recon",
n_procs=omp_nthreads,
- mem_gb=5,
+ mem_gb=12,
)
fastsurf_recon.interface._can_resume = False
fastsurf_recon.interface._always_run = True
From ca039f03e63f2ce4394c99d0b809280831a3e89c Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 10:34:52 -0500
Subject: [PATCH 051/220] Change URL to debug Convert3D install
Removes `/download` at the end of Convert3D URL to debug error in curl output and CircleCI build image test
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index f16586c158..7be40112c1 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -211,7 +211,7 @@ ENV FSLDIR="/opt/fsl-6.0.5.1" \
# Convert3D (neurodocker build)
RUN echo "Downloading Convert3D ..." \
&& mkdir -p /opt/convert3d-1.0.0 \
- && curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz/download \
+ && curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz \
| tar -xz -C /opt/convert3d-1.0.0 --strip-components 1 \
--exclude "c3d-1.0.0-Linux-x86_64/lib" \
--exclude "c3d-1.0.0-Linux-x86_64/share" \
From f417766a157ae60b4ede2aff2518e20802fd2c9e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 10:45:03 -0500
Subject: [PATCH 052/220] Fix formatting on FastSCommand docstring
Debug build_docs error
> Warning, treated as error:
> /tmp/gh-pages/smriprep/interfaces/fastsurfer.py:docstring of smriprep.interfaces.fastsurfer.FastSCommand:44:Definition list ends without a blank line; unexpected unindent`
---
smriprep/interfaces/fastsurfer.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 34f840b064..4037d25e74 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -302,6 +302,7 @@ class FastSCommand(CommandLine):
--t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
--sid sub- --sd /output
+
"""
input_spec = FastSInputSpec
output_spec = FastSTraitedOutputSpec
@@ -309,4 +310,5 @@ class FastSCommand(CommandLine):
def _list_outputs(self):
outputs = self.output_spec().get()
+
return outputs
From 444d476f88f8fad0b9f62b5931daa5c40ed60b13 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 12:06:04 -0500
Subject: [PATCH 053/220] Added FastSurfer workflow
---
smriprep/workflows/surfaces.py | 38 ++++++++++++++--------------------
1 file changed, 16 insertions(+), 22 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 9c5e37852d..f66053c52d 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -249,25 +249,19 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
if logger:
logger.warn(f'High-resolution {hires} specified, but not currently supported. Ignoring for now')
- #placeholder, create and import FastSurfDetectInputs
- fastsurf_recon_config = pe.Node(fastsurf.FastSurfDetectInputs(), name="fastsurf_recon_config")
-
- fov_check = pe.Node(niu.Function(function=_check_cw256), name="fov_check")
-
fsnative2t1w_xfm = pe.Node(
- RobustRegister(auto_sens=True, est_int_scale=True), name="fsnative2t1w_xfm")
- t1w2fsnative_xfm = pe.Node(
- LTAConvert(out_lta=True, invert=True), name="t1w2fsnative_xfm")
+ RobustRegister(auto_sens=True, est_int_scale=True), name="fsnative2t1w_xfm")
+ t1w2fsnative_xfm = pe.Node(
+ LTAConvert(out_lta=True, invert=True), name="t1w2fsnative_xfm")
gifti_surface_wf = init_gifti_surface_wf()
aseg_to_native_wf = init_segs_to_native_wf()
aparc_to_native_wf = init_segs_to_native_wf(segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
- #change below to make FastSurfer specific
- fastsurfsource = pe.Node(nio.FreeSurferSource(), name="fs_datasource")
+ #temporary fix fs_license value to /fs60/license
fastsurf_recon = pe.Node(
- fastsurf.FastSCommand(threads=omp_nthreads),
+ fastsurf.FastSCommand(threads=omp_nthreads,fs_license="/fs60/license"),
name="fastsurf_recon",
n_procs=omp_nthreads,
mem_gb=12,
@@ -283,23 +277,20 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
t1w2fsnative_xfm = pe.Node(
LTAConvert(out_lta=True, invert=True), name="t1w2fsnative_xfm"
)
+
# fmt:off
workflow.connect([
# Configuration
- (inputnode, fastsurf_recon_config, [('t1w', 't1w_list')]),
- # Passing subjects_dir / subject_id enforces serial order
- (inputnode, fastsurf_recon, [('subjects_dir', 'subjects_dir'),
- ('subject_id', 'subject_id')]),
- (fastsurf_recon, skull_strip_extern, [('subjects_dir', 'subjects_dir'),
- ('subject_id', 'subject_id')]),
+ (inputnode, recon_config, [('t1w', 't1w_list')]),
+ (inputnode, fastsurf_recon, [('subjects_dir', 'sd'),
+ ('subject_id', 'sid'),
+ ('t1w', 't1')]),
+ (fastsurf_recon, skull_strip_extern, [('sd', 'subjects_dir'),
+ ('sid', 'subject_id')]),
(skull_strip_extern, gifti_surface_wf, [
('outputnode.subjects_dir', 'inputnode.subjects_dir'),
('outputnode.subject_id', 'inputnode.subject_id')]),
- # Reconstruction phases
- (inputnode, fastsurf_recon, [('t1w', 'T1_files')]),
- (inputnode, fov_check, [('t1w', 'in_files')]),
- (fov_check, fastsurf_recon, [('out', 'flags')]),
(inputnode, skull_strip_extern, [('skullstripped_t1', 'in_brain')]),
# Construct transform from FreeSurfer conformed image to sMRIPrep
# reoriented image
@@ -794,7 +785,10 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
)
outputnode = pe.Node(niu.IdentityInterface(["surfaces"]), name="outputnode")
- get_surfaces = pe.Node(nio.FreeSurferSource(), name="get_surfaces")
+ if freesurfer:
+ get_surfaces = pe.Node(nio.FreeSurferSource(), name="get_surfaces")
+ elif fastsurfer:
+ get_surfaces = pe.Node(fastsurf.FastSurferSource(), name="get_surfaces")
midthickness = pe.MapNode(
MakeMidthickness(thickness=True, distance=0.5, out_name="midthickness"),
From 327cef0358bf787a92f43ade4bfc9fa288185bda Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 12:06:30 -0500
Subject: [PATCH 054/220] Adds FastSurfer detailed outputs to FastSCommand
output_spec
---
smriprep/interfaces/fastsurfer.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 9584e24848..8b37ae5994 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -654,7 +654,8 @@ def _list_outputs(self):
if val:
outputs[k] = simplify_list(val)
return outputs
-
+
+
class FastSCommand(CommandLine):
r"""
Wraps FastSurfer command for segmentation and surface processing.
@@ -668,7 +669,7 @@ class FastSCommand(CommandLine):
"""
input_spec = FastSInputSpec
- output_spec = FastSTraitedOutputSpec
+ output_spec = FastSurfSourceOutputSpec
_cmd = '/opt/FastSurfer/run_fastsurfer.sh'
def _list_outputs(self):
From 2a70ac9bf21cf175044593a9bc54e33a6d1f9b65 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 12:26:23 -0500
Subject: [PATCH 055/220] Fix formatting for PEP8
---
smriprep/interfaces/fastsurfer.py | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index ac2ba3037a..1d914f32cc 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -31,12 +31,12 @@ class FastSInputSpec(CommandLineInputSpec):
==================
sd
- Output directory
+ Output directory
sid
Subject ID for directory inside ``sd`` to be created
t1
T1 full head input (not bias corrected, global path).
- The 'network was trained with conformed images
+ The 'network was trained with conformed images
(UCHAR, 256x256x256, 1 mm voxels and standard slice orientation).
These specifications are checked in the ``eval.py`` script and the image
is automatically conformed if it does not comply.
@@ -64,7 +64,7 @@ class FastSInputSpec(CommandLineInputSpec):
``../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
weights_cor
Pretrained weights of coronal network.
- Default
+ Default
``../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
seg_log
Name and location for the log-file for the segmentation (FastSurferCNN).
@@ -110,7 +110,7 @@ class FastSInputSpec(CommandLineInputSpec):
Other
----
py
- which python version to use.
+ which python version to use.
Default ``python3.6``
seg_only
only run FastSurferCNN
@@ -292,7 +292,7 @@ class FastSTraitedOutputSpec(TraitedSpec):
desc="FastSurfer CNN + Surface Pipeline equivalent of recon-all outputs"
)
-
+
class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
sd = Directory(
exists=True,
@@ -360,7 +360,7 @@ class FastSurfSourceOutputSpec(TraitedSpec):
exists=True,
desc="Base image conformed to FastSurfer space",
loc="mri"
- )
+ )
orig_nu = File(
exists=True,
desc="Base image conformed to Fastsurfer space and nonuniformity corrected",
@@ -654,8 +654,8 @@ def _list_outputs(self):
if val:
outputs[k] = simplify_list(val)
return outputs
-
-
+
+
class FastSCommand(CommandLine):
r"""
Wraps FastSurfer command for segmentation and surface processing.
@@ -675,5 +675,5 @@ class FastSCommand(CommandLine):
def _list_outputs(self):
outputs = self.output_spec().get()
-
+
return outputs
From 7e2d53c4da6313acf82fd91d4e45e83fcf3de128 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 12:27:32 -0500
Subject: [PATCH 056/220] Fix formatting for PEP8
---
smriprep/workflows/anatomical.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 36b2fe70f9..509eca18f4 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -533,7 +533,7 @@ def _check_img(img):
)
check_fastsurfer.inputs.logger = LOGGER
- #Select which surface reconstruction workflow based on CLI arguments
+ # Select which surface reconstruction workflow based on CLI arguments
if freesurfer:
recon_wf = init_surface_recon_wf()
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
@@ -597,7 +597,7 @@ def _check_img(img):
)
# fmt:off
workflow.connect([
- #replace check_fastsurfer with check for only CNN segmentation outputs or full outputs
+ # replace check_fastsurfer with check for only CNN segmentation outputs or full outputs
(inputnode, check_fastsurfer, [
('subjects_dir', 'subjects_dir'),
('subject_id', 'subject_id')]),
@@ -637,7 +637,7 @@ def _check_img(img):
]),
])
# fmt:on
-
+
return workflow
From e52fd53c8d1d868c4f4d5e951ba4bc1523b4fb36 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 12:37:10 -0500
Subject: [PATCH 057/220] Fix formatting for PEP8
---
smriprep/workflows/surfaces.py | 31 +++++++++++++++----------------
1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index f66053c52d..53c06eec98 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -53,13 +53,14 @@
LOGGER = logging.getLogger("nipype.workflow")
+
def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
r"""
Reconstruct anatomical surfaces using FastSurfer CNN and ``recon_surf``,
an alternative to FreeSurfer's ``recon-all``.
First, FastSurfer CNN creates a segmentation using the T1w structural image.
- This is followed by FastSurfer ``recon_surf`` processing of the surface,
+ This is followed by FastSurfer ``recon_surf`` processing of the surface,
along with surface registration to support cross-subject comparison
using the ``--surfeg`` argument to FastSurfer.
@@ -101,7 +102,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
This procedure is inspired on mindboggle's solution to the problem:
https://github.com/nipy/mindboggle/blob/7f91faaa7664d820fe12ccc52ebaf21d679795e2/mindboggle/guts/segment.py#L1660
-
+
Memory annotations for FastSurfer are based off `their documentation
`_.
They recommend 8GB CPU RAM and 8GB NVIDIA GPU RAM to run a single batch.
@@ -117,12 +118,12 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
Required arguments
==================
sd
- Output directory
+ Output directory
sid
Subject ID for directory inside ``sd`` to be created
t1
T1 full head input (not bias corrected, global path).
- The 'network was trained with conformed images
+ The 'network was trained with conformed images
(UCHAR, 256x256x256, 1 mm voxels and standard slice orientation).
These specifications are checked in the ``eval.py`` script and the image
is automatically conformed if it does not comply.
@@ -149,7 +150,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
``../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
weights_cor
Pretrained weights of coronal network.
- Default
+ Default
``../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
seg_log
Name and location for the log-file for the segmentation (FastSurferCNN).
@@ -193,7 +194,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
Other
----
py
- which python version to use.
+ which python version to use.
Default ``python3.6``
seg_only
only run FastSurferCNN
@@ -243,14 +244,14 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
),
name="outputnode",
)
-
+
#null for now, placeholder for FastSurfer VINN hires support
if hires:
if logger:
- logger.warn(f'High-resolution {hires} specified, but not currently supported. Ignoring for now')
+ logger.warn(f'High-resolution {hires} specified, not currently supported, ignoring.')
fsnative2t1w_xfm = pe.Node(
- RobustRegister(auto_sens=True, est_int_scale=True), name="fsnative2t1w_xfm")
+ RobustRegister(auto_sens=True, est_int_scale=True), name="fsnative2t1w_xfm")
t1w2fsnative_xfm = pe.Node(
LTAConvert(out_lta=True, invert=True), name="t1w2fsnative_xfm")
@@ -259,9 +260,9 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
aparc_to_native_wf = init_segs_to_native_wf(segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
- #temporary fix fs_license value to /fs60/license
+ # temporary fix fs_license value to /fs60/license
fastsurf_recon = pe.Node(
- fastsurf.FastSCommand(threads=omp_nthreads,fs_license="/fs60/license"),
+ fastsurf.FastSCommand(threads=omp_nthreads, fs_license="/fs60/license"),
name="fastsurf_recon",
n_procs=omp_nthreads,
mem_gb=12,
@@ -277,7 +278,6 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
t1w2fsnative_xfm = pe.Node(
LTAConvert(out_lta=True, invert=True), name="t1w2fsnative_xfm"
)
-
# fmt:off
workflow.connect([
@@ -288,9 +288,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
('t1w', 't1')]),
(fastsurf_recon, skull_strip_extern, [('sd', 'subjects_dir'),
('sid', 'subject_id')]),
- (skull_strip_extern, gifti_surface_wf, [
- ('outputnode.subjects_dir', 'inputnode.subjects_dir'),
- ('outputnode.subject_id', 'inputnode.subject_id')]),
+ (skull_strip_extern, gifti_surface_wf, [('outputnode.subjects_dir', 'inputnode.subjects_dir'),
+ ('outputnode.subject_id', 'inputnode.subject_id')]),
(inputnode, skull_strip_extern, [('skullstripped_t1', 'in_brain')]),
# Construct transform from FreeSurfer conformed image to sMRIPrep
# reoriented image
@@ -320,7 +319,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
return workflow
-
+
def init_surface_recon_wf(*, omp_nthreads, hires, name="surface_recon_wf"):
r"""
Reconstruct anatomical surfaces using FreeSurfer's ``recon-all``.
From 6545c6dc0c1b08aec6325957fbe3a4b18bffde35 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 14:02:27 -0500
Subject: [PATCH 058/220] Fix formatting for PEP8
---
smriprep/workflows/surfaces.py | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 53c06eec98..d0d5bc11c4 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -245,7 +245,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
name="outputnode",
)
- #null for now, placeholder for FastSurfer VINN hires support
+ # null for now, placeholder for FastSurfer VINN hires support
if hires:
if logger:
logger.warn(f'High-resolution {hires} specified, not currently supported, ignoring.')
@@ -288,8 +288,9 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
('t1w', 't1')]),
(fastsurf_recon, skull_strip_extern, [('sd', 'subjects_dir'),
('sid', 'subject_id')]),
- (skull_strip_extern, gifti_surface_wf, [('outputnode.subjects_dir', 'inputnode.subjects_dir'),
- ('outputnode.subject_id', 'inputnode.subject_id')]),
+ (skull_strip_extern, gifti_surface_wf, [
+ ('outputnode.subjects_dir', 'inputnode.subjects_dir'),
+ ('outputnode.subject_id', 'inputnode.subject_id')]),
(inputnode, skull_strip_extern, [('skullstripped_t1', 'in_brain')]),
# Construct transform from FreeSurfer conformed image to sMRIPrep
# reoriented image
@@ -302,9 +303,11 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
(inputnode, refine, [('corrected_t1', 'in_anat'),
('ants_segs', 'in_ants')]),
(inputnode, aseg_to_native_wf, [('corrected_t1', 'inputnode.in_file')]),
- (fsnative2t1w_xfm, aseg_to_native_wf, [('out_reg_file', 'inputnode.fsnative2t1w_xfm')]),
+ (fsnative2t1w_xfm, aseg_to_native_wf, [
+ ('out_reg_file', 'inputnode.fsnative2t1w_xfm')]),
(inputnode, aparc_to_native_wf, [('corrected_t1', 'inputnode.in_file')]),
- (fsnative2t1w_xfm, aparc_to_native_wf, [('out_reg_file', 'inputnode.fsnative2t1w_xfm')]),
+ (fsnative2t1w_xfm, aparc_to_native_wf, [
+ ('out_reg_file', 'inputnode.fsnative2t1w_xfm')]),
(aseg_to_native_wf, refine, [('outputnode.out_file', 'in_aseg')]),
# Output
@@ -503,7 +506,6 @@ def init_surface_recon_wf(*, omp_nthreads, hires, name="surface_recon_wf"):
autorecon_resume_wf = init_autorecon_resume_wf(omp_nthreads=omp_nthreads)
gifti_surface_wf = init_gifti_surface_wf()
-
aseg_to_native_wf = init_segs_to_native_wf()
aparc_to_native_wf = init_segs_to_native_wf(segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
From 8d608b5706a5cbd1751d97a63fb80fed23160a19 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 14:03:07 -0500
Subject: [PATCH 059/220] Fix formatting for PEP8
---
smriprep/workflows/surfaces.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index d0d5bc11c4..1f7d39e0b3 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -287,7 +287,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
('subject_id', 'sid'),
('t1w', 't1')]),
(fastsurf_recon, skull_strip_extern, [('sd', 'subjects_dir'),
- ('sid', 'subject_id')]),
+ ('sid', 'subject_id')]),
(skull_strip_extern, gifti_surface_wf, [
('outputnode.subjects_dir', 'inputnode.subjects_dir'),
('outputnode.subject_id', 'inputnode.subject_id')]),
From 2f2560caeb264e5a79e1489732679f4dda8dac88 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 14:15:55 -0500
Subject: [PATCH 060/220] Debug convert3d install
Install `locales` before installing convert3d
---
Dockerfile | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 7be40112c1..e41daed03f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -45,6 +45,7 @@ RUN apt-get update && \
build-essential \
bzip2 \
ca-certificates \
+ locales \
curl \
git \
libtool \
@@ -219,9 +220,8 @@ RUN echo "Downloading Convert3D ..." \
ENV C3DPATH="/opt/convert3d-1.0.0" \
PATH="/opt/convert3d-1.0.0/bin:$PATH"
-# switch back to en-US utf-8
-RUN apt-get update -qq && apt-get install locales && \
- sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
+# switch back to en-US utf-8 apt-get update -qq && apt-get install locales && \
+RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
locale-gen
ENV LANG="en_US.UTF-8" \
LC_ALL="en_US.UTF-8" \
From 126b0b58e5228cedda775aef2e3910f190574f67 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 14:19:37 -0500
Subject: [PATCH 061/220] Fix typo in _get_files
Replace erroneous `.` with `,`
---
smriprep/interfaces/fastsurfer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 1d914f32cc..c3bc19db13 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -624,7 +624,7 @@ def _get_files(self, path, key, dirval, altkey=None):
globprefix = ""
if dirval in ("surf", "label", "stats"):
globprefix = "?h."
- if key in ("aseg_stats", "aseg_presurf_stats". "wmparc_stats"):
+ if key in ("aseg_stats", "aseg_presurf_stats", "wmparc_stats"):
globprefix = ""
elif key == "ribbon":
globprefix = "*"
From a5f1690462d7c8742d60998088217c206b3d8570 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 14:25:11 -0500
Subject: [PATCH 062/220] Add OutputMultiPath import
---
smriprep/interfaces/fastsurfer.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index c3bc19db13..b6af6c7363 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -15,6 +15,7 @@
CommandLine,
Directory,
CommandLineInputSpec,
+ OutputMultiPath,
isdefined,
TraitedSpec,
BaseInterface,
From 3613a05ac4e9a40d0315fd50d5813250b2aa2c89 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 14:29:21 -0500
Subject: [PATCH 063/220] Add import IOBase
---
smriprep/interfaces/fastsurfer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index b6af6c7363..7aa7bc4ff7 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -24,7 +24,7 @@
PackageInfo,
)
from nipype.interfaces.base.traits_extension import traits
-
+from nipype.interfaces.io import IOBase
class FastSInputSpec(CommandLineInputSpec):
r"""
From 9bab1314aff95a1f2e8a71de9e3aab375ca8dcff Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 14:43:40 -0500
Subject: [PATCH 064/220] Fix docstring for FastSCommand
---
smriprep/interfaces/fastsurfer.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 7aa7bc4ff7..3af3149a79 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -36,9 +36,9 @@ class FastSInputSpec(CommandLineInputSpec):
sid
Subject ID for directory inside ``sd`` to be created
t1
- T1 full head input (not bias corrected, global path).
+ T1 full head input, not bias corrected, global path.
The 'network was trained with conformed images
- (UCHAR, 256x256x256, 1 mm voxels and standard slice orientation).
+ UCHAR, 256 x 256 x 256, 1 mm voxels and standard slice orientation.
These specifications are checked in the ``eval.py`` script and the image
is automatically conformed if it does not comply.
fs_license
@@ -663,18 +663,18 @@ class FastSCommand(CommandLine):
.. code-block:: bash
- #Example basic commandline usage
+ # Example basic commandline usage \
/opt/FastSurfer/run_fastsurfer.sh --fs_license /fs60/license \
--t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
--sid sub- --sd /output
"""
+
input_spec = FastSInputSpec
output_spec = FastSurfSourceOutputSpec
_cmd = '/opt/FastSurfer/run_fastsurfer.sh'
def _list_outputs(self):
outputs = self.output_spec().get()
-
return outputs
From 83214078396366d1d42b143292fddcc202fb4075 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 14:55:29 -0500
Subject: [PATCH 065/220] Remove code-block to debug docstring error
---
smriprep/interfaces/fastsurfer.py | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 3af3149a79..a6ac071174 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -659,16 +659,12 @@ def _list_outputs(self):
class FastSCommand(CommandLine):
r"""
- Wraps FastSurfer command for segmentation and surface processing.
+ Wraps FastSurfer command for segmentation and surface processing::
- .. code-block:: bash
-
- # Example basic commandline usage \
- /opt/FastSurfer/run_fastsurfer.sh --fs_license /fs60/license \
+ $ /opt/FastSurfer/run_fastsurfer.sh --fs_license /fs60/license \
--t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
--sid sub- --sd /output
-
"""
input_spec = FastSInputSpec
From 4753d3254f15f1b003054462136192e1f581e467 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 20:27:22 -0500
Subject: [PATCH 066/220] Switch to FastSurfer dev image for Ubuntu 20.04
Changes from pytorch image based on Ubuntu 16.04 to Ubuntu 20.04 base image modified from the dev branch of FastSurfer (https://github.com/Deep-MI/FastSurfer/blob/0749f38e656ed0da977c408b4383db88e1a8b563/Docker/Dockerfile) to resolve ca-certificates errors in build
---
Dockerfile | 204 ++++++++++++++++++++++++++---------------------------
1 file changed, 99 insertions(+), 105 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index e41daed03f..ae5dacd6be 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -22,93 +22,93 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-# Use Ubuntu 20.04 LTS
-#FROM ubuntu:focal-20210416
-
-# Use pytorch official docker image
-FROM pytorch/pytorch:1.2-cuda10.0-cudnn7-runtime
-
-ENV CUDA_VERSION=10.0.130 \
- CUDA_PKG_VERSION=10-0=10.0.130-1 \
- NCCL_VERSION=2.4.8 \
- CUDNN_VERSION=7.6.5.32 \
- PYTHON_VERSION=3.6 \
- DEBIAN_FRONTEND="noninteractive" \
- LANG="C.UTF-8" \
- LC_ALL="C.UTF-8"
-
-# Prepare environment
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- apt-utils \
- autoconf \
- build-essential \
- bzip2 \
- ca-certificates \
- locales \
- curl \
- git \
- libtool \
- wget \
- lsb-release \
- pkg-config \
- unzip \
- cmake \
- gawk \
- perl-modules \
- tcsh \
- time \
- bzip2 \
- libx11-6 \
- libjpeg-dev \
- bc \
- libgomp1 \
- libglu1-mesa \
- libglu1-mesa-dev \
- xvfb && \
- rm -rf /var/lib/apt/lists/*
-
-
-# Installing freesurfer
-RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1.tar.gz \
- | tar zxv --no-same-owner -C /opt \
- --exclude='freesurfer/diffusion' \
- --exclude='freesurfer/docs' \
- --exclude='freesurfer/fsfast' \
- --exclude='freesurfer/lib/cuda' \
- --exclude='freesurfer/lib/qt' \
- --exclude='freesurfer/matlab' \
- --exclude='freesurfer/mni/share/man' \
- --exclude='freesurfer/subjects/fsaverage_sym' \
- --exclude='freesurfer/subjects/fsaverage3' \
- --exclude='freesurfer/subjects/fsaverage4' \
- --exclude='freesurfer/subjects/cvs_avg35' \
- --exclude='freesurfer/subjects/cvs_avg35_inMNI152' \
- --exclude='freesurfer/subjects/bert' \
- --exclude='freesurfer/subjects/lh.EC_average' \
- --exclude='freesurfer/subjects/rh.EC_average' \
- --exclude='freesurfer/subjects/sample-*.mgz' \
- --exclude='freesurfer/subjects/V1_average' \
- --exclude='freesurfer/trctrain'
-
-# Install miniconda and needed python packages (for FastSurferCNN)
-#RUN wget -qO ~/miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh && \
-# chmod +x ~/miniconda.sh && \
-# ~/miniconda.sh -b -p /opt/conda && \
-# rm ~/miniconda.sh && \
-RUN /opt/conda/bin/conda install python-dateutil pyyaml numpy scipy matplotlib h5py scikit-image && \
- /opt/conda/bin/conda install -y -c pytorch cudatoolkit=10.0 "pytorch=1.2.0=py3.6_cuda10.0.130_cudnn7.6.2_0" torchvision=0.4.0 && \
- /opt/conda/bin/conda install -c conda-forge scikit-sparse nibabel=2.5.1 pillow=8.3.2 && \
- /opt/conda/bin/conda clean -ya
+## Start with ubuntu base as in FastSurfer Docker image
+## https://github.com/Deep-MI/FastSurfer/blob/0749f38e656ed0da977c408b4383db88e1a8b563/Docker/Dockerfile
+
+FROM ubuntu:20.04 AS build
+
+ENV LANG=C.UTF-8
+ARG PYTHON_VERSION=3.8
+ARG CONDA_FILE=Miniconda3-py38_4.11.0-Linux-x86_64.sh
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Install packages needed for build
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ wget \
+ git \
+ ca-certificates \
+ upx \
+ git \
+ file && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+
+# git clone dev branch of FastSurfer
+RUN cd /opt && mkdir /fastsurfer \
+ && git clone -b dev https://github.com/Deep-MI/FastSurfer.git \
+ && cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml \
+ && cp /opt/FastSurfer/Docker/install_fs_pruned.sh /fastsurfer/install_fs_pruned.sh
+
+# Install conda
+RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/miniconda/$CONDA_FILE && \
+ chmod +x ~/miniconda.sh && \
+ ~/miniconda.sh -b -p /opt/conda && \
+ rm ~/miniconda.sh
+
ENV PATH /opt/conda/bin:$PATH
-# install LaPy for FastSurfer
-RUN python3.6 -m pip install -U git+https://github.com/Deep-MI/LaPy.git#egg=lapy
+# Install our dependencies
+RUN conda env create -f /fastsurfer/fastsurfer_env_gpu.yml
+
+# Install conda-pack:
+RUN conda install -c conda-forge conda-pack
+
+# Use conda-pack to create a standalone enviornment in /venv:
+RUN conda-pack -n fastsurfer_gpu -o /tmp/env.tar && \
+ mkdir /venv && cd /venv && tar xf /tmp/env.tar && \
+ rm /tmp/env.tar
-# Add FastSurfer (copy application code) to docker image
-RUN cd /opt && git clone https://github.com/Deep-MI/FastSurfer.git
-ENV FASTSURFER_HOME=/opt/FastSurfer
+# Now that venv in a new location, fix up paths:
+RUN /venv/bin/conda-unpack
+ENV PATH /venv/bin:$PATH
+# setup shell for install command below
+RUN echo "source /venv/bin/activate" >> ~/.bashrc
+SHELL ["/bin/bash", "--login", "-c"]
+
+# install freesurfer and point to new python location
+RUN /fastsurfer/install_fs_pruned.sh /opt --upx && \
+ rm /opt/freesurfer/bin/fspython && \
+ ln -s /venv/bin/python3 /opt/freesurfer/bin/fspython
+
+
+# Install required packages for freesurfer to run
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ tcsh \
+ time \
+ bc \
+ gawk \
+ libgomp1 && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+
+# Add FreeSurfer Environment variables
+ENV OS=Linux \
+ FS_OVERRIDE=0 \
+ FIX_VERTEX_AREA= \
+ SUBJECTS_DIR=/opt/freesurfer/subjects \
+ FSF_OUTPUT_FORMAT=nii.gz \
+ FREESURFER_HOME=/opt/freesurfer \
+ PYTHONUNBUFFERED=0 \
+ PATH=/venv/bin:/opt/freesurfer/bin:$PATH
+
+# make sure we use bash and activate conda env
+# (in case someone starts this interactively)
+RUN echo "source /venv/bin/activate" >> ~/.bashrc
+SHELL ["/bin/bash", "--login", "-c"]
+
+# Copy fastsurfer from git folder
+RUN cp -R /opt/FastSurfer/* /fastsurfer/
# Simulate SetUpFreeSurfer.sh
ENV FSL_DIR="/opt/fsl-6.0.5.1" \
@@ -148,6 +148,7 @@ RUN apt-get update -qq \
libxrender1 \
libxt6 \
sudo \
+ curl \
wget \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
@@ -208,25 +209,17 @@ ENV FSLDIR="/opt/fsl-6.0.5.1" \
FSLREMOTECALL="" \
FSLGECUDAQ="cuda.q" \
LD_LIBRARY_PATH="/opt/fsl-6.0.5.1/lib:$LD_LIBRARY_PATH"
-
+
# Convert3D (neurodocker build)
RUN echo "Downloading Convert3D ..." \
&& mkdir -p /opt/convert3d-1.0.0 \
- && curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz \
+ && curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz/download \
| tar -xz -C /opt/convert3d-1.0.0 --strip-components 1 \
--exclude "c3d-1.0.0-Linux-x86_64/lib" \
--exclude "c3d-1.0.0-Linux-x86_64/share" \
--exclude "c3d-1.0.0-Linux-x86_64/bin/c3d_gui"
ENV C3DPATH="/opt/convert3d-1.0.0" \
PATH="/opt/convert3d-1.0.0/bin:$PATH"
-
-# switch back to en-US utf-8 apt-get update -qq && apt-get install locales && \
-RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
- locale-gen
-ENV LANG="en_US.UTF-8" \
- LC_ALL="en_US.UTF-8" \
- LANGUAGE="en_US:en"
-RUN ls /etc/ssl/certs/
# AFNI latest (neurodocker build)
RUN apt-get update -qq \
@@ -244,20 +237,20 @@ RUN apt-get update -qq \
tcsh \
xfonts-base \
xvfb \
- && apt-get clean -y \
- && rm -rf /var/lib/apt/lists/* \
- && curl -sSL --retry 5 -o /tmp/multiarch.deb http://archive.ubuntu.com/ubuntu/pool/main/g/glibc/multiarch-support_2.27-3ubuntu1.2_amd64.deb \
- && dpkg -i /tmp/multiarch.deb \
- && rm /tmp/multiarch.deb \
- && curl -sSL --retry 5 -o /tmp/libxp6.deb http://mirrors.kernel.org/debian/pool/main/libx/libxp/libxp6_1.0.2-2_amd64.deb \
- && dpkg -i /tmp/libxp6.deb \
- && rm /tmp/libxp6.deb \
- && curl -sSL --retry 5 -o /tmp/libpng.deb http://snapshot.debian.org/archive/debian-security/20160113T213056Z/pool/updates/main/libp/libpng/libpng12-0_1.2.49-1%2Bdeb7u2_amd64.deb \
- && dpkg -i /tmp/libpng.deb \
- && rm /tmp/libpng.deb \
- && apt-get install -f -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
+# && curl -sSL --retry 5 -o /tmp/multiarch.deb http://archive.ubuntu.com/ubuntu/pool/main/g/glibc/multiarch-support_2.27-3ubuntu1.2_amd64.deb \
+# && dpkg -i /tmp/multiarch.deb \
+# && rm /tmp/multiarch.deb \
+# && curl -sSL --retry 5 -o /tmp/libxp6.deb http://mirrors.kernel.org/debian/pool/main/libx/libxp/libxp6_1.0.2-2_amd64.deb \
+# && dpkg -i /tmp/libxp6.deb \
+# && rm /tmp/libxp6.deb \
+# && curl -sSL --retry 5 -o /tmp/libpng.deb http://snapshot.debian.org/archive/debian-security/20160113T213056Z/pool/updates/main/libp/libpng/libpng12-0_1.2.49-1%2Bdeb7u2_amd64.deb \
+# && dpkg -i /tmp/libpng.deb \
+# && rm /tmp/libpng.deb \
+# && apt-get install -f \
+# && apt-get clean \
+# && rm -rf /var/lib/apt/lists/* \
&& gsl2_path="$(find / -name 'libgsl.so.19' || printf '')" \
&& if [ -n "$gsl2_path" ]; then \
ln -sfv "$gsl2_path" "$(dirname $gsl2_path)/libgsl.so.0"; \
@@ -341,6 +334,7 @@ RUN find $HOME -type d -exec chmod go=u {} + && \
rm -rf $HOME/.npm $HOME/.conda $HOME/.empty
ENV IS_DOCKER_8395080871=1
+ENV FASTSURFER_HOME=/fastsurfer
RUN ldconfig
WORKDIR /tmp
From ac5246472a2cefff90c23c52cf609005721bb4af Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 23:47:58 -0500
Subject: [PATCH 067/220] Change FastSurfer directory to match Dockerfile
---
smriprep/interfaces/fastsurfer.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index a6ac071174..2e1863c500 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -661,7 +661,7 @@ class FastSCommand(CommandLine):
r"""
Wraps FastSurfer command for segmentation and surface processing::
- $ /opt/FastSurfer/run_fastsurfer.sh --fs_license /fs60/license \
+ $ /fastsurfer/run_fastsurfer.sh --fs_license /fs60/license \
--t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
--sid sub- --sd /output
@@ -669,7 +669,7 @@ class FastSCommand(CommandLine):
input_spec = FastSInputSpec
output_spec = FastSurfSourceOutputSpec
- _cmd = '/opt/FastSurfer/run_fastsurfer.sh'
+ _cmd = '/fastsurfer/run_fastsurfer.sh'
def _list_outputs(self):
outputs = self.output_spec().get()
From 9a898671464d15b19957023d228d18b18be234ab Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 29 Apr 2022 23:53:32 -0500
Subject: [PATCH 068/220] Fix formatting for PEP8
---
smriprep/interfaces/fastsurfer.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 2e1863c500..ec185baa57 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -26,6 +26,7 @@
from nipype.interfaces.base.traits_extension import traits
from nipype.interfaces.io import IOBase
+
class FastSInputSpec(CommandLineInputSpec):
r"""
Required arguments
@@ -666,7 +667,7 @@ class FastSCommand(CommandLine):
--sid sub- --sd /output
"""
-
+
input_spec = FastSInputSpec
output_spec = FastSurfSourceOutputSpec
_cmd = '/fastsurfer/run_fastsurfer.sh'
From 2a56ff1d2d838baf3ae8a73d40faf6c289f78363 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 10:57:56 -0500
Subject: [PATCH 069/220] Include FastSurfer
Adds parameters and workflows for FastSurfer to base wf
---
smriprep/workflows/base.py | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/smriprep/workflows/base.py b/smriprep/workflows/base.py
index b9b48c841a..976ec59ca2 100644
--- a/smriprep/workflows/base.py
+++ b/smriprep/workflows/base.py
@@ -50,6 +50,7 @@ def init_smriprep_wf(
hires,
layout,
longitudinal,
+ fastsurfer,
low_mem,
omp_nthreads,
output_dir,
@@ -87,6 +88,7 @@ def init_smriprep_wf(
hires=True,
layout=BIDSLayout('.'),
longitudinal=False,
+ fastsurfer=False,
low_mem=False,
omp_nthreads=1,
output_dir='.',
@@ -117,6 +119,8 @@ def init_smriprep_wf(
longitudinal : :obj:`bool`
Treat multiple sessions as longitudinal (may increase runtime)
See sub-workflows for specific differences
+ fastsurfer : :obj:`bool`
+ Enable FastSurfer segmentation and surface reconstruction
low_mem : :obj:`bool`
Write uncompressed .nii files in some cases to reduce memory usage
omp_nthreads : :obj:`int`
@@ -161,7 +165,21 @@ def init_smriprep_wf(
)
if fs_subjects_dir is not None:
fsdir.inputs.subjects_dir = str(fs_subjects_dir.absolute())
-
+
+ if fastsurfer:
+ fastsurfdir = pe.Node(
+ BIDSFreeSurferDir(
+ derivatives=output_dir,
+ freesurfer_home=os.getenv("FREESURFER_HOME"),
+ fastsurfer_home=os.getenv("FASTSURFER_HOME"),
+ spaces=spaces.get_fs_spaces(),
+ ),
+ name="fastsurfdir_run_%s" % run_uuid.replace("-", "_"),
+ run_without_submitting=True,
+ )
+ if fs_subjects_dir is not None:
+ fastsurfdir.inputs.sd = str(fs_subjects_dir.absolute())
+
for subject_id in subject_list:
single_subject_wf = init_single_subject_wf(
debug=debug,
@@ -170,6 +188,7 @@ def init_smriprep_wf(
hires=hires,
layout=layout,
longitudinal=longitudinal,
+ fastsurfer=fastsurfer,
low_mem=low_mem,
name="single_subject_%s_wf" % subject_id,
omp_nthreads=omp_nthreads,
@@ -191,6 +210,10 @@ def init_smriprep_wf(
smriprep_wf.connect(
fsdir, "subjects_dir", single_subject_wf, "inputnode.subjects_dir"
)
+ elif fastsurfer:
+ smriprep_wf.connect(
+ fastsurfdir, "sd", single_subject_wf, "inputnode.subjects_dir"
+ )
else:
smriprep_wf.add_nodes([single_subject_wf])
@@ -205,6 +228,7 @@ def init_single_subject_wf(
hires,
layout,
longitudinal,
+ fastsurfer,
low_mem,
name,
omp_nthreads,
@@ -244,6 +268,7 @@ def init_single_subject_wf(
hires=True,
layout=BIDSLayout('.'),
longitudinal=False,
+ fastsurfer=False,
low_mem=False,
name='single_subject_wf',
omp_nthreads=1,
@@ -271,6 +296,8 @@ def init_single_subject_wf(
longitudinal : :obj:`bool`
Treat multiple sessions as longitudinal (may increase runtime)
See sub-workflows for specific differences
+ fastsurfer : :obj:`bool`
+ Enable FastSurfer segmentation and surface reconstruction
low_mem : :obj:`bool`
Write uncompressed .nii files in some cases to reduce memory usage
name : :obj:`str`
@@ -404,6 +431,7 @@ def init_single_subject_wf(
freesurfer=freesurfer,
hires=hires,
longitudinal=longitudinal,
+ fastsurfer=fastsurfer,
name="anat_preproc_wf",
t1w=subject_data["t1w"],
omp_nthreads=omp_nthreads,
From c65d4c565f5b650b93faa91cddf47d446fd680d4 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:05:08 -0500
Subject: [PATCH 070/220] Add FastSurfer
Returns FreeSurfer style outputs if FastSurfer is enabled
---
smriprep/workflows/outputs.py | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/smriprep/workflows/outputs.py b/smriprep/workflows/outputs.py
index c6def01d0e..4047d4967e 100644
--- a/smriprep/workflows/outputs.py
+++ b/smriprep/workflows/outputs.py
@@ -39,6 +39,8 @@ def init_anat_reports_wf(*, freesurfer, output_dir, name="anat_reports_wf"):
----------
freesurfer : :obj:`bool`
FreeSurfer was enabled
+ fastsurfer : :obj:`bool`
+ FastSurfer was enabled
output_dir : :obj:`str`
Directory in which to save derivatives
name : :obj:`str`
@@ -192,6 +194,27 @@ def init_anat_reports_wf(*, freesurfer, output_dir, name="anat_reports_wf"):
(inputnode, ds_recon_report, [('source_file', 'source_file')])
])
# fmt:on
+ elif fastsurfer:
+ from ..interfaces.reports import FSSurfaceReport
+
+ recon_report = pe.Node(FSSurfaceReport(), name="recon_report")
+ recon_report.interface._always_run = True
+
+ ds_recon_report = pe.Node(
+ DerivativesDataSink(
+ base_directory=output_dir, desc="fastsurf_recon", datatype="figures"
+ ),
+ name="ds_recon_report",
+ run_without_submitting=True,
+ )
+ # fmt:off
+ workflow.connect([
+ (inputnode, recon_report, [('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id')]),
+ (recon_report, ds_recon_report, [('out_report', 'in_file')]),
+ (inputnode, ds_recon_report, [('source_file', 'source_file')])
+ ])
+ # fmt:on
return workflow
@@ -200,6 +223,7 @@ def init_anat_derivatives_wf(
*,
bids_root,
freesurfer,
+ fastsurfer,
num_t1w,
output_dir,
spaces,
@@ -215,6 +239,8 @@ def init_anat_derivatives_wf(
Root path of BIDS dataset
freesurfer : :obj:`bool`
FreeSurfer was enabled
+ fastsurfer : :obj:`bool`
+ FastSurfer was enabled
num_t1w : :obj:`int`
Number of T1w images
output_dir : :obj:`str`
@@ -552,7 +578,7 @@ def init_anat_derivatives_wf(
)
# fmt:on
- if not freesurfer:
+ if (not freesurfer) and (not fastsurfer):
return workflow
from niworkflows.interfaces.nitransforms import ConcatenateXFMs
From 265eb54e8e2ae3aabf7fd352c291a80607f44b27 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:16:33 -0500
Subject: [PATCH 071/220] Change default license directory
---
smriprep/interfaces/fastsurfer.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index ec185baa57..eb555ea5be 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -142,6 +142,7 @@ class FastSInputSpec(CommandLineInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
+ "/opt/freesurfer/license.txt"
exists=True,
mandatory=True,
argstr="--fs_license %s",
@@ -662,7 +663,7 @@ class FastSCommand(CommandLine):
r"""
Wraps FastSurfer command for segmentation and surface processing::
- $ /fastsurfer/run_fastsurfer.sh --fs_license /fs60/license \
+ $ /fastsurfer/run_fastsurfer.sh --fs_license /opt/freesurfer/license \
--t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
--sid sub- --sd /output
From 6237a007ca59f39cd91f2a63b0457761ce0e06bc Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:26:22 -0500
Subject: [PATCH 072/220] Switch check_fastsufer to only return boolean
---
smriprep/utils/misc.py | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/smriprep/utils/misc.py b/smriprep/utils/misc.py
index 2b16fb57fa..297febd80b 100644
--- a/smriprep/utils/misc.py
+++ b/smriprep/utils/misc.py
@@ -112,23 +112,24 @@ def check_fastsurfer(subjects_dir, subject_id, logger=None):
Returns
-------
- subjects_dir : os.PathLike or None
+ fastsurfer_bool : Boolean
"""
from pathlib import Path
+ fastsurfer_bool = False
+
if subjects_dir is None:
- return subjects_dir
+ return fastsurfer_bool
subj_dir = Path(subjects_dir) / subject_id
if not subj_dir.exists():
- return subjects_dir
+ return fastsurfer_bool
fastsurferfiles = tuple(subj_dir.glob("mri/*deep*mgz"))
if not fastsurferfiles:
- return subjects_dir
+ return fastsurfer_bool
else:
if logger:
logger.warn(f'Evidence of FastSurfer processing found in {subj_dir}')
- noCCseglabel = Path(subj_dir / 'mri/aseg.auto_noCCseg.label_intensities.txt')
- noCCseglabel.touch(exist_ok=False)
- return subjects_dir
+ fastsurfer_bool = True
+ return fastsurfer_bool
From 592a54321cd66478303b7de4a3ac7aca763be04e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:26:52 -0500
Subject: [PATCH 073/220] Update description of check_fastsurfer
---
smriprep/utils/misc.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/smriprep/utils/misc.py b/smriprep/utils/misc.py
index 297febd80b..81dd803783 100644
--- a/smriprep/utils/misc.py
+++ b/smriprep/utils/misc.py
@@ -100,8 +100,7 @@ def fs_isRunning(subjects_dir, subject_id, mtime_tol=86400, logger=None):
def check_fastsurfer(subjects_dir, subject_id, logger=None):
"""
Checks FreeSurfer subjects dir for presence of files in mri/ with names \
- indicating processing with FastSurfer, this also touches files that are \
- expected outputs of Freesurfer, but not produced by default in FastSurfer.
+ indicating processing with FastSurfer.
Parameters
----------
From 5737828e1f5771fb38b1785cccefeed64bebd613 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:29:36 -0500
Subject: [PATCH 074/220] Adds FastSurfer reporting
---
smriprep/interfaces/reports.py | 72 +++++++++++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 2 deletions(-)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index 7db4f92c1b..6524f77396 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -37,6 +37,9 @@
)
from nipype.interfaces import freesurfer as fs
from nipype.interfaces.io import FSSourceInputSpec as _FSSourceInputSpec
+from smriprep.interfaces.fastsurfer import FastSurfSourceInputSpec as _FastSurfSourceInputSpec
+from smriprep.interfaces import fastsurfer as fastsurf
+from smriprep.utils.misc import check_fastsurfer
from nipype.interfaces.mixins import reporting
from niworkflows.interfaces.reportlets.base import _SVGReportCapableInputSpec
@@ -48,6 +51,7 @@
\t\tStructural images: {n_t1s:d} T1-weighted {t2w}
\t\tStandard spaces: {output_spaces}
\t\tFreeSurfer reconstruction: {freesurfer_status}
+\t\tFreeSurfer reconstruction: {fastsurfer_status}
\t
"""
@@ -108,13 +112,26 @@ def _run_interface(self, runtime):
def _generate_segment(self):
if not isdefined(self.inputs.subjects_dir):
freesurfer_status = "Not run"
+ fastsurfer_status = "Not run"
else:
- recon = fs.ReconAll(
+ fastsurfer_bool = check_fastsurfer(
+ subjects_dir=self.inputs.subjects_dir,
+ subject_id=self.inputs.subject_id,
+ )
+ if fastsurfer_bool = True:
+ recon = fastsurf.FastSCommand(
+ sd=self.inputs.subjects_dir,
+ sid=self.inputs.subject_id,
+ t1=self.inputs.t1w,
+ )
+ fastsurfer_status = "Run by sMRIPrep"
+ else:
+ recon = fs.ReconAll(
subjects_dir=self.inputs.subjects_dir,
subject_id=self.inputs.subject_id,
T1_files=self.inputs.t1w,
flags="-noskullstrip",
- )
+ )
if recon.cmdline.startswith("echo"):
freesurfer_status = "Pre-existing directory"
else:
@@ -136,6 +153,7 @@ def _generate_segment(self):
t2w=t2w_seg,
output_spaces=output_spaces,
freesurfer_status=freesurfer_status,
+ fastsurfer_status=fastsurfer_status,
)
@@ -166,6 +184,14 @@ class _FSSurfaceReportOutputSpec(reporting.ReportCapableOutputSpec):
pass
+class _FastSurfSurfaceReportInputSpec(_SVGReportCapableInputSpec, _FastSurfSourceInputSpec):
+ pass
+
+
+class _FastSurfSurfaceReportOutputSpec(reporting.ReportCapableOutputSpec):
+ pass
+
+
class FSSurfaceReport(SimpleInterface):
"""Replaces ``ReconAllRPT``, without need of calling recon-all."""
@@ -206,3 +232,45 @@ def _run_interface(self, runtime):
out_file=self._results["out_report"],
)
return runtime
+
+
+class FastSurfSurfaceReport(SimpleInterface):
+ """Replaces ``ReconAllRPT``, without need of calling recon-all."""
+
+ input_spec = _FastSurfSurfaceReportInputSpec
+ output_spec = _FastSurfSurfaceReportOutputSpec
+
+ def _run_interface(self, runtime):
+ from niworkflows.viz.utils import (
+ plot_registration,
+ cuts_from_bbox,
+ compose_view,
+ )
+ from nibabel import load
+
+ rootdir = Path(self.inputs.sd) / self.inputs.sid
+ _anat_file = str(rootdir / "mri" / "brain.mgz")
+ _contour_file = str(rootdir / "mri" / "ribbon.mgz")
+
+ anat = load(_anat_file)
+ contour_nii = load(_contour_file)
+
+ n_cuts = 7
+ cuts = cuts_from_bbox(contour_nii, cuts=n_cuts)
+
+ self._results["out_report"] = str(Path(runtime.cwd) / self.inputs.out_report)
+
+ # Call composer
+ compose_view(
+ plot_registration(
+ anat,
+ "fixed-image",
+ estimate_brightness=True,
+ cuts=cuts,
+ contour=contour_nii,
+ compress=self.inputs.compress_report,
+ ),
+ [],
+ out_file=self._results["out_report"],
+ )
+ return runtime
From 81742b170b12c3d4cc34230050e100d0d8440e2e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:32:17 -0500
Subject: [PATCH 075/220] Fix formatting for PEP8
---
smriprep/interfaces/reports.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index 6524f77396..80501c5caa 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -123,15 +123,15 @@ def _generate_segment(self):
sd=self.inputs.subjects_dir,
sid=self.inputs.subject_id,
t1=self.inputs.t1w,
- )
+ )
fastsurfer_status = "Run by sMRIPrep"
- else:
+ else:
recon = fs.ReconAll(
subjects_dir=self.inputs.subjects_dir,
subject_id=self.inputs.subject_id,
T1_files=self.inputs.t1w,
flags="-noskullstrip",
- )
+ )
if recon.cmdline.startswith("echo"):
freesurfer_status = "Pre-existing directory"
else:
From 79e3c05a82c8df6007ff5311484fcbb94c2a2535 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:32:50 -0500
Subject: [PATCH 076/220] Fix formatting for PEP8
---
smriprep/utils/misc.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/utils/misc.py b/smriprep/utils/misc.py
index 81dd803783..4145517381 100644
--- a/smriprep/utils/misc.py
+++ b/smriprep/utils/misc.py
@@ -117,7 +117,7 @@ def check_fastsurfer(subjects_dir, subject_id, logger=None):
from pathlib import Path
fastsurfer_bool = False
-
+
if subjects_dir is None:
return fastsurfer_bool
subj_dir = Path(subjects_dir) / subject_id
From 954d3a396a6d7780bd438545c48752f8c30801fd Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:36:48 -0500
Subject: [PATCH 077/220] Fix formatting for PEP8
---
smriprep/workflows/base.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/smriprep/workflows/base.py b/smriprep/workflows/base.py
index 976ec59ca2..00cba6cd28 100644
--- a/smriprep/workflows/base.py
+++ b/smriprep/workflows/base.py
@@ -165,9 +165,9 @@ def init_smriprep_wf(
)
if fs_subjects_dir is not None:
fsdir.inputs.subjects_dir = str(fs_subjects_dir.absolute())
-
+
if fastsurfer:
- fastsurfdir = pe.Node(
+ fastsurfdir = pe.Node(
BIDSFreeSurferDir(
derivatives=output_dir,
freesurfer_home=os.getenv("FREESURFER_HOME"),
@@ -175,7 +175,7 @@ def init_smriprep_wf(
spaces=spaces.get_fs_spaces(),
),
name="fastsurfdir_run_%s" % run_uuid.replace("-", "_"),
- run_without_submitting=True,
+ run_without_submitting=True
)
if fs_subjects_dir is not None:
fastsurfdir.inputs.sd = str(fs_subjects_dir.absolute())
From b9d24a8985d44111adac824078fdab96d995508c Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:38:38 -0500
Subject: [PATCH 078/220] Fix formatting for PEP8
---
smriprep/interfaces/reports.py | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index 80501c5caa..8c7cdb7601 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -116,14 +116,13 @@ def _generate_segment(self):
else:
fastsurfer_bool = check_fastsurfer(
subjects_dir=self.inputs.subjects_dir,
- subject_id=self.inputs.subject_id,
- )
+ subject_id=self.inputs.subject_id)
if fastsurfer_bool = True:
recon = fastsurf.FastSCommand(
- sd=self.inputs.subjects_dir,
- sid=self.inputs.subject_id,
- t1=self.inputs.t1w,
- )
+ sd=self.inputs.subjects_dir,
+ sid=self.inputs.subject_id,
+ t1=self.inputs.t1w,
+ )
fastsurfer_status = "Run by sMRIPrep"
else:
recon = fs.ReconAll(
From 58d5be8fd8663d7a25fe0e66804f2a67f2d68696 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:39:43 -0500
Subject: [PATCH 079/220] Fix formatting for PEP8
---
smriprep/workflows/base.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/workflows/base.py b/smriprep/workflows/base.py
index 00cba6cd28..511fe30f80 100644
--- a/smriprep/workflows/base.py
+++ b/smriprep/workflows/base.py
@@ -179,7 +179,7 @@ def init_smriprep_wf(
)
if fs_subjects_dir is not None:
fastsurfdir.inputs.sd = str(fs_subjects_dir.absolute())
-
+
for subject_id in subject_list:
single_subject_wf = init_single_subject_wf(
debug=debug,
@@ -212,7 +212,7 @@ def init_smriprep_wf(
)
elif fastsurfer:
smriprep_wf.connect(
- fastsurfdir, "sd", single_subject_wf, "inputnode.subjects_dir"
+ fastsurfdir, "sd", single_subject_wf, "inputnode.subjects_dir"
)
else:
smriprep_wf.add_nodes([single_subject_wf])
From 067e5054ca315a40ffba4c5f74091b5da40a5178 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 11:43:36 -0500
Subject: [PATCH 080/220] Fix typo
---
smriprep/interfaces/fastsurfer.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index eb555ea5be..53a59dba99 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -142,7 +142,7 @@ class FastSInputSpec(CommandLineInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
- "/opt/freesurfer/license.txt"
+ "/opt/freesurfer/license.txt",
exists=True,
mandatory=True,
argstr="--fs_license %s",
@@ -316,6 +316,7 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
+ "/opt/freesurfer/license.txt",
exists=True,
mandatory=True,
argstr="--fs_license %s",
From 9455019889fb7b8f96807821ff1fe35d6f72c0a0 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 12:52:05 -0500
Subject: [PATCH 081/220] Fix syntax
---
smriprep/interfaces/reports.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index 8c7cdb7601..d6c4255f60 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -114,7 +114,7 @@ def _generate_segment(self):
freesurfer_status = "Not run"
fastsurfer_status = "Not run"
else:
- fastsurfer_bool = check_fastsurfer(
+ fastsurfer_bool == check_fastsurfer(
subjects_dir=self.inputs.subjects_dir,
subject_id=self.inputs.subject_id)
if fastsurfer_bool = True:
From a192fd3b9c751b17b677aab4892d698443bcbe0c Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 12:57:58 -0500
Subject: [PATCH 082/220] Fix variables for FastSurfer reports
---
smriprep/workflows/outputs.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/smriprep/workflows/outputs.py b/smriprep/workflows/outputs.py
index 4047d4967e..5b973c5ba7 100644
--- a/smriprep/workflows/outputs.py
+++ b/smriprep/workflows/outputs.py
@@ -195,9 +195,9 @@ def init_anat_reports_wf(*, freesurfer, output_dir, name="anat_reports_wf"):
])
# fmt:on
elif fastsurfer:
- from ..interfaces.reports import FSSurfaceReport
+ from ..interfaces.reports import FastSurfSurfaceReport
- recon_report = pe.Node(FSSurfaceReport(), name="recon_report")
+ recon_report = pe.Node(FastSurfSurfaceReport(), name="recon_report")
recon_report.interface._always_run = True
ds_recon_report = pe.Node(
@@ -209,8 +209,8 @@ def init_anat_reports_wf(*, freesurfer, output_dir, name="anat_reports_wf"):
)
# fmt:off
workflow.connect([
- (inputnode, recon_report, [('subjects_dir', 'subjects_dir'),
- ('subject_id', 'subject_id')]),
+ (inputnode, recon_report, [('subjects_dir', 'sd'),
+ ('subject_id', 'sid')]),
(recon_report, ds_recon_report, [('out_report', 'in_file')]),
(inputnode, ds_recon_report, [('source_file', 'source_file')])
])
From b00bc95b8f956711983b0f8ed97e7a388742788e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 13:04:23 -0500
Subject: [PATCH 083/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 53a59dba99..a766ef957a 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -668,6 +668,8 @@ class FastSCommand(CommandLine):
--t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
--sid sub- --sd /output
+ Note that T2w and FLAIR are not used for this surface reconstruction
+
"""
input_spec = FastSInputSpec
From a545a0266647ac901450dee95e45821499b32113 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 14:47:25 -0500
Subject: [PATCH 084/220] Fix syntax
---
smriprep/interfaces/reports.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index d6c4255f60..6151eabdd4 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -114,10 +114,10 @@ def _generate_segment(self):
freesurfer_status = "Not run"
fastsurfer_status = "Not run"
else:
- fastsurfer_bool == check_fastsurfer(
+ fastsurfer_bool = check_fastsurfer(
subjects_dir=self.inputs.subjects_dir,
subject_id=self.inputs.subject_id)
- if fastsurfer_bool = True:
+ if fastsurfer_bool == True:
recon = fastsurf.FastSCommand(
sd=self.inputs.subjects_dir,
sid=self.inputs.subject_id,
From 705ce9e636f77a755aa53872e4a1bf32895cd514 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 14:49:47 -0500
Subject: [PATCH 085/220] Fix syntax for PEP8
---
smriprep/interfaces/reports.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index 6151eabdd4..dfc91c0ec4 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -103,6 +103,7 @@ class SubjectSummary(SummaryInterface):
input_spec = _SubjectSummaryInputSpec
output_spec = _SubjectSummaryOutputSpec
+ fastsurfer_bool = False
def _run_interface(self, runtime):
if isdefined(self.inputs.subject_id):
@@ -117,7 +118,7 @@ def _generate_segment(self):
fastsurfer_bool = check_fastsurfer(
subjects_dir=self.inputs.subjects_dir,
subject_id=self.inputs.subject_id)
- if fastsurfer_bool == True:
+ if fastsurfer_bool is True:
recon = fastsurf.FastSCommand(
sd=self.inputs.subjects_dir,
sid=self.inputs.subject_id,
From ee535a0ae203febd8e8a37c71605d4c7148193fd Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 30 Apr 2022 15:16:27 -0500
Subject: [PATCH 086/220] Add fastsurfer input to init_anat_derivatives
---
smriprep/workflows/anatomical.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 509eca18f4..8fb935edad 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -461,6 +461,7 @@ def _check_img(img):
anat_derivatives_wf = init_anat_derivatives_wf(
bids_root=bids_root,
freesurfer=freesurfer,
+ fastsurfer=fastsurfer,
num_t1w=num_t1w,
output_dir=output_dir,
spaces=spaces,
From f03fd6494c38c531a57b4a944f675259923509ac Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 10:39:05 -0500
Subject: [PATCH 087/220] Add FastSurfer parameter to init_anat_reports_wf
---
smriprep/workflows/outputs.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/workflows/outputs.py b/smriprep/workflows/outputs.py
index 5b973c5ba7..840e278809 100644
--- a/smriprep/workflows/outputs.py
+++ b/smriprep/workflows/outputs.py
@@ -31,7 +31,7 @@
BIDS_TISSUE_ORDER = ("GM", "WM", "CSF")
-def init_anat_reports_wf(*, freesurfer, output_dir, name="anat_reports_wf"):
+def init_anat_reports_wf(*, freesurfer, fastsurfer, output_dir, name="anat_reports_wf"):
"""
Set up a battery of datasinks to store reports in the right location.
From 7a76f963678dce11acf792f6967524c7eb9935f1 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 12:24:44 -0500
Subject: [PATCH 088/220] Set FastSurfer parameter default to False
---
smriprep/cli/run.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 24cbab2e27..8bf6ea953d 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -225,6 +225,7 @@ def get_parser():
g_surfs.add_argument(
"--fastsurfer-recon",
action="store_true",
+ default=False,
dest="run_fastsurfer",
help="enable FastSurfer surface preprocessing.",
)
From aa49b700cfcaf34e899f14f5883d90ef6c124d48 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 13:42:47 -0500
Subject: [PATCH 089/220] Switch fs_license to use FS_LICENSE os env var
---
smriprep/interfaces/fastsurfer.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index a766ef957a..cc2dbf1134 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -142,7 +142,7 @@ class FastSInputSpec(CommandLineInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
- "/opt/freesurfer/license.txt",
+ os.environ["FS_LICENSE"],
exists=True,
mandatory=True,
argstr="--fs_license %s",
@@ -316,7 +316,7 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
- "/opt/freesurfer/license.txt",
+ os.environ["FS_LICENSE"],
exists=True,
mandatory=True,
argstr="--fs_license %s",
From 8eae255e6331c468ee4a61a0c7cd484206afaa40 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 13:50:26 -0500
Subject: [PATCH 090/220] Add fastsurfer argument to init_anat_reports_wf
---
smriprep/workflows/anatomical.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 8fb935edad..37b7d8fece 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -244,6 +244,7 @@ def init_anat_preproc_wf(
# Connect reportlets workflows
anat_reports_wf = init_anat_reports_wf(
freesurfer=freesurfer,
+ fastsurfer=fastsurfer,
output_dir=output_dir,
)
# fmt:off
From d2c50a4dd488c7a7bf691fb9f385af4e5a0f4708 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 13:50:47 -0500
Subject: [PATCH 091/220] Add default path for freesurfer license as
/opt/freesurfer/license.txt
---
smriprep/cli/run.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 8bf6ea953d..1911316cc6 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -223,10 +223,10 @@ def get_parser():
help="disable sub-millimeter (hires) reconstruction",
)
g_surfs.add_argument(
- "--fastsurfer-recon",
+ "--fastsurfer",
action="store_true",
default=False,
- dest="run_fastsurfer",
+ dest="fastsurfer",
help="enable FastSurfer surface preprocessing.",
)
g_surfs_xor = g_surfs.add_mutually_exclusive_group()
@@ -331,6 +331,8 @@ def _warn_redirect(message, category, filename, lineno, file=None, line=None):
# Precedence: --fs-license-file, $FS_LICENSE, default_license
if opts.fs_license_file is not None:
os.environ["FS_LICENSE"] = os.path.abspath(opts.fs_license_file)
+ elif os.path.(exists(os.path.abspath("/opt/freesurfer/license.txt"))):
+ os.environ["FS_LICENSE"] = os.path.abspath("/opt/freesurfer/license.txt")
if not check_valid_fs_license():
raise RuntimeError(
@@ -602,7 +604,7 @@ def build_workflow(opts, retval):
freesurfer=opts.run_reconall,
fs_subjects_dir=opts.fs_subjects_dir,
hires=opts.hires,
- fastsurfer=opts.run_fastsurfer,
+ fastsurfer=opts.fastsurfer,
layout=layout,
longitudinal=opts.longitudinal,
low_mem=opts.low_mem,
From 726245316c5d6f71d272cf9c29e820bb5df520b8 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 13:54:42 -0500
Subject: [PATCH 092/220] Fix typo
---
smriprep/cli/run.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 1911316cc6..02ee5e1368 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -331,7 +331,7 @@ def _warn_redirect(message, category, filename, lineno, file=None, line=None):
# Precedence: --fs-license-file, $FS_LICENSE, default_license
if opts.fs_license_file is not None:
os.environ["FS_LICENSE"] = os.path.abspath(opts.fs_license_file)
- elif os.path.(exists(os.path.abspath("/opt/freesurfer/license.txt"))):
+ elif os.path.exists(os.path.abspath("/opt/freesurfer/license.txt")):
os.environ["FS_LICENSE"] = os.path.abspath("/opt/freesurfer/license.txt")
if not check_valid_fs_license():
From 7fbd48953e3b64d6f0e52054c00b4dc63ff46c52 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 14:25:21 -0500
Subject: [PATCH 093/220] Add omp_nthreads and hires arguments to
init_surface_recon_wf
---
smriprep/workflows/anatomical.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 37b7d8fece..d4d1fac6ee 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -537,7 +537,7 @@ def _check_img(img):
# Select which surface reconstruction workflow based on CLI arguments
if freesurfer:
- recon_wf = init_surface_recon_wf()
+ recon_wf = init_surface_recon_wf(name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
# 5. Surface reconstruction (--fs-no-reconall not set)
surface_recon_wf = recon_wf(
@@ -591,7 +591,7 @@ def _check_img(img):
])
# fmt:on
elif fastsurfer:
- recon_wf = init_fastsurf_recon_wf()
+ recon_wf = init_fastsurf_recon_wf(name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
# 5. Surface reconstruction (--fs-no-reconall not set)
fastsurf_recon_wf = recon_wf(
From cb65d08b24f634448b1b5a1398ad56b9035bb338 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 15:10:09 -0500
Subject: [PATCH 094/220] Fix conditionals for FastSurfer in
init_gifti_surface_wf & init_segs_to_native_wf
---
smriprep/workflows/surfaces.py | 35 ++++++++++++++++++++++++----------
1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 1f7d39e0b3..6907d960fe 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -255,7 +255,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
t1w2fsnative_xfm = pe.Node(
LTAConvert(out_lta=True, invert=True), name="t1w2fsnative_xfm")
- gifti_surface_wf = init_gifti_surface_wf()
+ gifti_surface_wf = init_gifti_surface_wf(fastsurfer=True)
aseg_to_native_wf = init_segs_to_native_wf()
aparc_to_native_wf = init_segs_to_native_wf(segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
@@ -282,7 +282,6 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# fmt:off
workflow.connect([
# Configuration
- (inputnode, recon_config, [('t1w', 't1w_list')]),
(inputnode, fastsurf_recon, [('subjects_dir', 'sd'),
('subject_id', 'sid'),
('t1w', 't1')]),
@@ -770,6 +769,8 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
FreeSurfer subject ID
fsnative2t1w_xfm
LTA formatted affine transform file (inverse)
+ fastsurfer
+ Boolean when true uses FastSurferSource for get_surfaces
Outputs
-------
@@ -786,10 +787,14 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
)
outputnode = pe.Node(niu.IdentityInterface(["surfaces"]), name="outputnode")
- if freesurfer:
- get_surfaces = pe.Node(nio.FreeSurferSource(), name="get_surfaces")
- elif fastsurfer:
+ subs_dir = 'subjects_dir'
+ subj = 'subject_id'
+ if fastsurfer:
get_surfaces = pe.Node(fastsurf.FastSurferSource(), name="get_surfaces")
+ subs_dir = 'sd'
+ subj = 'sid'
+ else:
+ get_surfaces = pe.Node(nio.FreeSurferSource(), name="get_surfaces")
midthickness = pe.MapNode(
MakeMidthickness(thickness=True, distance=0.5, out_name="midthickness"),
@@ -813,8 +818,8 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
# fmt:off
workflow.connect([
- (inputnode, get_surfaces, [('subjects_dir', 'subjects_dir'),
- ('subject_id', 'subject_id')]),
+ (inputnode, get_surfaces, [('subjects_dir', subs_dir),
+ ('subject_id', subj)]),
(inputnode, save_midthickness, [('subjects_dir', 'base_directory'),
('subject_id', 'container')]),
# Generate midthickness surfaces and save to FreeSurfer derivatives
@@ -862,6 +867,8 @@ def init_segs_to_native_wf(*, name="segs_to_native", segmentation="aseg"):
FreeSurfer subject ID
fsnative2t1w_xfm
LTA-style affine matrix translating from FreeSurfer-conformed subject space to T1w
+ fastsurfer
+ Boolean when true uses FastSurferSource for get_surfaces
Outputs
-------
@@ -878,7 +885,15 @@ def init_segs_to_native_wf(*, name="segs_to_native", segmentation="aseg"):
)
outputnode = pe.Node(niu.IdentityInterface(["out_file"]), name="outputnode")
# Extract the aseg and aparc+aseg outputs
- fssource = pe.Node(nio.FreeSurferSource(), name="fs_datasource")
+ subs_dir = 'subjects_dir'
+ subj = 'subject_id'
+ if fastsurfer:
+ fssource = pe.Node(fastsurf.FastSurferSource(), name="fs_datasource")
+ subs_dir = 'sd'
+ subj = 'sid'
+ else:
+ fssource = pe.Node(nio.FreeSurferSource(), name="fs_datasource")
+
# Resample from T1.mgz to T1w.nii.gz, applying any offset in fsnative2t1w_xfm,
# and convert to NIfTI while we're at it
resample = pe.Node(
@@ -907,8 +922,8 @@ def _sel(x):
# fmt:off
workflow.connect([
(inputnode, fssource, [
- ('subjects_dir', 'subjects_dir'),
- ('subject_id', 'subject_id')]),
+ ('subjects_dir', subs_dir),
+ ('subject_id', subj)]),
(inputnode, resample, [('in_file', 'target_file'),
('fsnative2t1w_xfm', 'lta_file')]),
(fssource, resample, [(segmentation, 'source_file')]),
From bd9c11ea164bd6a575b4e5e6616c5d7bb7d6f3a9 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 15:11:24 -0500
Subject: [PATCH 095/220] Fix formatting for PEP8
---
smriprep/workflows/anatomical.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index d4d1fac6ee..80a353449c 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -537,7 +537,8 @@ def _check_img(img):
# Select which surface reconstruction workflow based on CLI arguments
if freesurfer:
- recon_wf = init_surface_recon_wf(name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
+ recon_wf = init_surface_recon_wf(
+ name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
# 5. Surface reconstruction (--fs-no-reconall not set)
surface_recon_wf = recon_wf(
@@ -591,7 +592,8 @@ def _check_img(img):
])
# fmt:on
elif fastsurfer:
- recon_wf = init_fastsurf_recon_wf(name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
+ recon_wf = init_fastsurf_recon_wf(
+ name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
# 5. Surface reconstruction (--fs-no-reconall not set)
fastsurf_recon_wf = recon_wf(
From 994d352dd976aed34110344a2e04fb21f4c5fe11 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 15:31:27 -0500
Subject: [PATCH 096/220] Switch fs_license default to
$FREESURFER_HOME/license.txt
---
smriprep/interfaces/fastsurfer.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index cc2dbf1134..0432255d6c 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -142,7 +142,7 @@ class FastSInputSpec(CommandLineInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
- os.environ["FS_LICENSE"],
+ os.environ["FREESUFER_HOME"]+"/license.txt",
exists=True,
mandatory=True,
argstr="--fs_license %s",
@@ -316,7 +316,7 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
- os.environ["FS_LICENSE"],
+ os.environ["FREESUFER_HOME"]+"/license.txt",
exists=True,
mandatory=True,
argstr="--fs_license %s",
From a4fa911e39769ab4a79a13622798106b9790d7aa Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sun, 1 May 2022 15:32:43 -0500
Subject: [PATCH 097/220] Fix formatting for PEP8
---
smriprep/interfaces/fastsurfer.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 0432255d6c..9726889ebf 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -142,7 +142,7 @@ class FastSInputSpec(CommandLineInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
- os.environ["FREESUFER_HOME"]+"/license.txt",
+ os.environ["FREESUFER_HOME"] + "/license.txt",
exists=True,
mandatory=True,
argstr="--fs_license %s",
@@ -316,7 +316,7 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
- os.environ["FREESUFER_HOME"]+"/license.txt",
+ os.environ["FREESUFER_HOME"] + "/license.txt",
exists=True,
mandatory=True,
argstr="--fs_license %s",
From 6d439679769bcbf02b2a6a6bafcace6e4fe80885 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 2 May 2022 10:55:49 -0500
Subject: [PATCH 098/220] Remove os.environ method of setting fs_license
---
smriprep/interfaces/fastsurfer.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 9726889ebf..997917bf54 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -142,7 +142,6 @@ class FastSInputSpec(CommandLineInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
- os.environ["FREESUFER_HOME"] + "/license.txt",
exists=True,
mandatory=True,
argstr="--fs_license %s",
@@ -316,7 +315,6 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
- os.environ["FREESUFER_HOME"] + "/license.txt",
exists=True,
mandatory=True,
argstr="--fs_license %s",
From b19510fcd9afca2dfc7a735b22cc8e261cc9d7e0 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 2 May 2022 11:14:05 -0500
Subject: [PATCH 099/220] Update method for testing fs_license paths
---
smriprep/workflows/surfaces.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 6907d960fe..ce3fda4036 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -50,6 +50,7 @@
)
from niworkflows.interfaces.surf import NormalizeSurf
from nipype import logging
+import os
LOGGER = logging.getLogger("nipype.workflow")
@@ -259,10 +260,15 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
aseg_to_native_wf = init_segs_to_native_wf()
aparc_to_native_wf = init_segs_to_native_wf(segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
+ fs_license_file = "/opt/freesurfer/license.txt"
+ if os.path.exists("/tmp/freesurfer/license.txt"):
+ fs_license_file = "/tmp/freesurfer/license.txt"
+ elif os.environ['FS_LICENSE']:
+ fs_license_file = os.environ['FS_LICENSE']
# temporary fix fs_license value to /fs60/license
fastsurf_recon = pe.Node(
- fastsurf.FastSCommand(threads=omp_nthreads, fs_license="/fs60/license"),
+ fastsurf.FastSCommand(threads=omp_nthreads, fs_license=fs_license_file),
name="fastsurf_recon",
n_procs=omp_nthreads,
mem_gb=12,
From 7444df501d49bf6d427aa820cc6947bc03353fef Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 2 May 2022 11:14:31 -0500
Subject: [PATCH 100/220] Update anatomical.py
---
smriprep/workflows/anatomical.py | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 80a353449c..a10a95cb9c 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -546,9 +546,6 @@ def _check_img(img):
)
# fmt:off
workflow.connect([
- (inputnode, check_fastsurfer, [
- ('subjects_dir', 'subjects_dir'),
- ('subject_id', 'subject_id')]),
(inputnode, fs_isrunning, [
('subjects_dir', 'subjects_dir'),
('subject_id', 'subject_id')]),
@@ -601,12 +598,9 @@ def _check_img(img):
)
# fmt:off
workflow.connect([
- # replace check_fastsurfer with check for only CNN segmentation outputs or full outputs
- (inputnode, check_fastsurfer, [
- ('subjects_dir', 'subjects_dir'),
- ('subject_id', 'subject_id')]),
(inputnode, fastsurf_recon_wf, [
- ('subject_id', 'inputnode.subject_id')]),
+ ('subject_id', 'inputnode.subject_id'),
+ ('subjects_dir', 'inputnode.subjects_dir']),
(anat_validate, fastsurf_recon_wf, [('out_file', 'inputnode.t1w')]),
(brain_extraction_wf, fastsurf_recon_wf, [
(('outputnode.out_file', _pop), 'inputnode.skullstripped_t1'),
From c59e917b52c71841b1ee8e4c18e945431395605a Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 2 May 2022 11:20:22 -0500
Subject: [PATCH 101/220] Fix formatting for PEP8
---
smriprep/workflows/anatomical.py | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index a10a95cb9c..ab9a4a399e 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -600,8 +600,9 @@ def _check_img(img):
workflow.connect([
(inputnode, fastsurf_recon_wf, [
('subject_id', 'inputnode.subject_id'),
- ('subjects_dir', 'inputnode.subjects_dir']),
- (anat_validate, fastsurf_recon_wf, [('out_file', 'inputnode.t1w')]),
+ ('subjects_dir', 'inputnode.subjects_dir')]),
+ (anat_validate, fastsurf_recon_wf, [
+ ('out_file', 'inputnode.t1w')]),
(brain_extraction_wf, fastsurf_recon_wf, [
(('outputnode.out_file', _pop), 'inputnode.skullstripped_t1'),
('outputnode.out_segm', 'inputnode.ants_segs'),
@@ -619,11 +620,11 @@ def _check_img(img):
('outputnode.out_aseg', 't1w_aseg'),
('outputnode.out_aparc', 't1w_aparc')]),
(applyrefined, buffernode, [('out_file', 't1w_brain')]),
- (fastsurf_recon_wf, buffernode, [
- ('outputnode.out_brainmask', 't1w_mask')]),
+ (fastsurf_recon_wf, buffernode, [('outputnode.out_brainmask', 't1w_mask')]),
(fastsurf_recon_wf, anat_reports_wf, [
('outputnode.subject_id', 'inputnode.subject_id'),
- ('outputnode.subjects_dir', 'inputnode.subjects_dir')]),
+ ('outputnode.subjects_dir', 'inputnode.subjects_dir'),
+ ]),
(fastsurf_recon_wf, anat_derivatives_wf, [
('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
('outputnode.out_aparc', 'inputnode.t1w_fs_aparc'),
From 5cbf0ff2568b89cdae772eed4feef483a36d019d Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 2 May 2022 11:55:01 -0500
Subject: [PATCH 102/220] Call check_fastsurfer for conditionals
---
smriprep/workflows/surfaces.py | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index ce3fda4036..41b0274598 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -38,6 +38,7 @@
from ..interfaces.freesurfer import ReconAll
from ..interfaces import fastsurfer as fastsurf
+from ..utils.misc import check_fastsurfer
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
from niworkflows.interfaces.freesurfer import (
@@ -792,10 +793,13 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
name="inputnode",
)
outputnode = pe.Node(niu.IdentityInterface(["surfaces"]), name="outputnode")
-
+ fastsurfer_bool = False
+ fastsurfer_bool = check_fastsurfer(
+ subjects_dir=self.inputs.subjects_dir,
+ subject_id=self.inputs.subject_id)
subs_dir = 'subjects_dir'
subj = 'subject_id'
- if fastsurfer:
+ if fastsurfer_bool is True:
get_surfaces = pe.Node(fastsurf.FastSurferSource(), name="get_surfaces")
subs_dir = 'sd'
subj = 'sid'
@@ -891,9 +895,13 @@ def init_segs_to_native_wf(*, name="segs_to_native", segmentation="aseg"):
)
outputnode = pe.Node(niu.IdentityInterface(["out_file"]), name="outputnode")
# Extract the aseg and aparc+aseg outputs
+ fastsurfer_bool = False
+ fastsurfer_bool = check_fastsurfer(
+ subjects_dir=self.inputs.subjects_dir,
+ subject_id=self.inputs.subject_id)
subs_dir = 'subjects_dir'
subj = 'subject_id'
- if fastsurfer:
+ if fastsurfer_bool is True:
fssource = pe.Node(fastsurf.FastSurferSource(), name="fs_datasource")
subs_dir = 'sd'
subj = 'sid'
From d5b11c3534a17cdc88b126e0a2016438d39839fe Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 2 May 2022 13:25:04 -0500
Subject: [PATCH 103/220] Pass fastsurfer parameter instead of check_fastsurfer
---
smriprep/workflows/surfaces.py | 27 +++++++++------------------
1 file changed, 9 insertions(+), 18 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 41b0274598..7702e109aa 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -38,7 +38,6 @@
from ..interfaces.freesurfer import ReconAll
from ..interfaces import fastsurfer as fastsurf
-from ..utils.misc import check_fastsurfer
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
from niworkflows.interfaces.freesurfer import (
@@ -258,8 +257,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
LTAConvert(out_lta=True, invert=True), name="t1w2fsnative_xfm")
gifti_surface_wf = init_gifti_surface_wf(fastsurfer=True)
- aseg_to_native_wf = init_segs_to_native_wf()
- aparc_to_native_wf = init_segs_to_native_wf(segmentation="aparc_aseg")
+ aseg_to_native_wf = init_segs_to_native_wf(fastsurfer=True)
+ aparc_to_native_wf = init_segs_to_native_wf(fastsurfer=True,segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
fs_license_file = "/opt/freesurfer/license.txt"
if os.path.exists("/tmp/freesurfer/license.txt"):
@@ -511,9 +510,9 @@ def init_surface_recon_wf(*, omp_nthreads, hires, name="surface_recon_wf"):
)
autorecon_resume_wf = init_autorecon_resume_wf(omp_nthreads=omp_nthreads)
- gifti_surface_wf = init_gifti_surface_wf()
- aseg_to_native_wf = init_segs_to_native_wf()
- aparc_to_native_wf = init_segs_to_native_wf(segmentation="aparc_aseg")
+ gifti_surface_wf = init_gifti_surface_wf(fastsurfer=False)
+ aseg_to_native_wf = init_segs_to_native_wf(fastsurfer=False)
+ aparc_to_native_wf = init_segs_to_native_wf(fastsurfer=False,segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
# fmt:off
@@ -777,7 +776,7 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
fsnative2t1w_xfm
LTA formatted affine transform file (inverse)
fastsurfer
- Boolean when true uses FastSurferSource for get_surfaces
+ Boolean to indicate FastSurfer surface processing
Outputs
-------
@@ -793,13 +792,9 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
name="inputnode",
)
outputnode = pe.Node(niu.IdentityInterface(["surfaces"]), name="outputnode")
- fastsurfer_bool = False
- fastsurfer_bool = check_fastsurfer(
- subjects_dir=self.inputs.subjects_dir,
- subject_id=self.inputs.subject_id)
subs_dir = 'subjects_dir'
subj = 'subject_id'
- if fastsurfer_bool is True:
+ if fastsurfer is True:
get_surfaces = pe.Node(fastsurf.FastSurferSource(), name="get_surfaces")
subs_dir = 'sd'
subj = 'sid'
@@ -878,7 +873,7 @@ def init_segs_to_native_wf(*, name="segs_to_native", segmentation="aseg"):
fsnative2t1w_xfm
LTA-style affine matrix translating from FreeSurfer-conformed subject space to T1w
fastsurfer
- Boolean when true uses FastSurferSource for get_surfaces
+ Boolean to indicate FastSurfer processing
Outputs
-------
@@ -895,13 +890,9 @@ def init_segs_to_native_wf(*, name="segs_to_native", segmentation="aseg"):
)
outputnode = pe.Node(niu.IdentityInterface(["out_file"]), name="outputnode")
# Extract the aseg and aparc+aseg outputs
- fastsurfer_bool = False
- fastsurfer_bool = check_fastsurfer(
- subjects_dir=self.inputs.subjects_dir,
- subject_id=self.inputs.subject_id)
subs_dir = 'subjects_dir'
subj = 'subject_id'
- if fastsurfer_bool is True:
+ if fastsurfer is True:
fssource = pe.Node(fastsurf.FastSurferSource(), name="fs_datasource")
subs_dir = 'sd'
subj = 'sid'
From 32a62f351a4fccfa08a3215a8365032e1e65ebc6 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 2 May 2022 13:26:05 -0500
Subject: [PATCH 104/220] Fix formatting for PEP8
---
smriprep/workflows/surfaces.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 7702e109aa..9eeaaec197 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -258,7 +258,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
gifti_surface_wf = init_gifti_surface_wf(fastsurfer=True)
aseg_to_native_wf = init_segs_to_native_wf(fastsurfer=True)
- aparc_to_native_wf = init_segs_to_native_wf(fastsurfer=True,segmentation="aparc_aseg")
+ aparc_to_native_wf = init_segs_to_native_wf(fastsurfer=True, segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
fs_license_file = "/opt/freesurfer/license.txt"
if os.path.exists("/tmp/freesurfer/license.txt"):
@@ -512,7 +512,7 @@ def init_surface_recon_wf(*, omp_nthreads, hires, name="surface_recon_wf"):
autorecon_resume_wf = init_autorecon_resume_wf(omp_nthreads=omp_nthreads)
gifti_surface_wf = init_gifti_surface_wf(fastsurfer=False)
aseg_to_native_wf = init_segs_to_native_wf(fastsurfer=False)
- aparc_to_native_wf = init_segs_to_native_wf(fastsurfer=False,segmentation="aparc_aseg")
+ aparc_to_native_wf = init_segs_to_native_wf(fastsurfer=False, segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
# fmt:off
From c2b3fa6cdd42e1c44c63f3abcc615df25fa07b86 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 2 May 2022 15:10:26 -0500
Subject: [PATCH 105/220] Fix missing parameter for FastSurfer
---
smriprep/workflows/surfaces.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 9eeaaec197..778a114000 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -747,7 +747,7 @@ def _dedup(in_list):
return workflow
-def init_gifti_surface_wf(*, name="gifti_surface_wf"):
+def init_gifti_surface_wf(*, fastsurfer, name="gifti_surface_wf"):
r"""
Prepare GIFTI surfaces from a FreeSurfer subjects directory.
@@ -845,7 +845,7 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
return workflow
-def init_segs_to_native_wf(*, name="segs_to_native", segmentation="aseg"):
+def init_segs_to_native_wf(*, fastsurfer, name="segs_to_native", segmentation="aseg"):
"""
Get a segmentation from FreeSurfer conformed space into native T1w space.
From 62667d487a0c127d2a61e0d3b2745e185bbb0f88 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 3 May 2022 11:53:04 -0500
Subject: [PATCH 106/220] remove duplicate nodes
---
smriprep/workflows/anatomical.py | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index ab9a4a399e..0979a86aad 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -537,13 +537,9 @@ def _check_img(img):
# Select which surface reconstruction workflow based on CLI arguments
if freesurfer:
- recon_wf = init_surface_recon_wf(
+ surface_recon_wf = init_surface_recon_wf(
name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
- # 5. Surface reconstruction (--fs-no-reconall not set)
- surface_recon_wf = recon_wf(
- name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires
- )
# fmt:off
workflow.connect([
(inputnode, fs_isrunning, [
@@ -589,13 +585,9 @@ def _check_img(img):
])
# fmt:on
elif fastsurfer:
- recon_wf = init_fastsurf_recon_wf(
- name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
+ fastsurf_recon_wf = init_fastsurf_recon_wf(
+ name="fastsurf_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
- # 5. Surface reconstruction (--fs-no-reconall not set)
- fastsurf_recon_wf = recon_wf(
- name="fastsurf_recon_wf", omp_nthreads=omp_nthreads, hires=hires
- )
# fmt:off
workflow.connect([
(inputnode, fastsurf_recon_wf, [
From f275c4aef0a2e579bef781a4b34ffe2c99d3fa73 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 3 May 2022 14:15:55 -0500
Subject: [PATCH 107/220] Fix opts fastsurfer typo
---
smriprep/cli/run.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 02ee5e1368..491c897ba3 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -410,7 +410,7 @@ def _warn_redirect(message, category, filename, lineno, file=None, line=None):
_copy_any(
dseg_tsv, str(Path(output_dir) / "smriprep" / "desc-aparcaseg_dseg.tsv")
)
- elif opts.run_fastsurfer:
+ elif fastsurfer:
from templateflow import api
from niworkflows.utils.misc import _copy_any
From 56dff950e8a5d836361f5ca0286003f0f1d386e8 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 3 May 2022 19:54:54 -0500
Subject: [PATCH 108/220] Fix conditional to check opts.fastsurfer
---
smriprep/cli/run.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 491c897ba3..37e5e7607e 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -410,7 +410,7 @@ def _warn_redirect(message, category, filename, lineno, file=None, line=None):
_copy_any(
dseg_tsv, str(Path(output_dir) / "smriprep" / "desc-aparcaseg_dseg.tsv")
)
- elif fastsurfer:
+ elif opts.fastsurfer:
from templateflow import api
from niworkflows.utils.misc import _copy_any
From 86d7aa28d12681f9189c5e8c0e2eb9fa57c30ff9 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 3 May 2022 20:02:55 -0500
Subject: [PATCH 109/220] Revert from FastSurfer Docker style Freesurfer
install
---
Dockerfile | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index ae5dacd6be..191c9dda87 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -76,11 +76,27 @@ ENV PATH /venv/bin:$PATH
RUN echo "source /venv/bin/activate" >> ~/.bashrc
SHELL ["/bin/bash", "--login", "-c"]
-# install freesurfer and point to new python location
-RUN /fastsurfer/install_fs_pruned.sh /opt --upx && \
- rm /opt/freesurfer/bin/fspython && \
- ln -s /venv/bin/python3 /opt/freesurfer/bin/fspython
-
+# install freesurfer from sMRIPrep version
+RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1.tar.gz \
+ | tar zxv --no-same-owner -C /opt \
+ --exclude='freesurfer/diffusion' \
+ --exclude='freesurfer/docs' \
+ --exclude='freesurfer/fsfast' \
+ --exclude='freesurfer/lib/cuda' \
+ --exclude='freesurfer/lib/qt' \
+ --exclude='freesurfer/matlab' \
+ --exclude='freesurfer/mni/share/man' \
+ --exclude='freesurfer/subjects/fsaverage_sym' \
+ --exclude='freesurfer/subjects/fsaverage3' \
+ --exclude='freesurfer/subjects/fsaverage4' \
+ --exclude='freesurfer/subjects/cvs_avg35' \
+ --exclude='freesurfer/subjects/cvs_avg35_inMNI152' \
+ --exclude='freesurfer/subjects/bert' \
+ --exclude='freesurfer/subjects/lh.EC_average' \
+ --exclude='freesurfer/subjects/rh.EC_average' \
+ --exclude='freesurfer/subjects/sample-*.mgz' \
+ --exclude='freesurfer/subjects/V1_average' \
+ --exclude='freesurfer/trctrain'
# Install required packages for freesurfer to run
RUN apt-get update && apt-get install -y --no-install-recommends \
From 6f9701c0c955c7325506c6552a869a218178026f Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 3 May 2022 20:14:25 -0500
Subject: [PATCH 110/220] Update Dockerfile
---
Dockerfile | 1 +
1 file changed, 1 insertion(+)
diff --git a/Dockerfile b/Dockerfile
index 191c9dda87..a8095ea912 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -37,6 +37,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
wget \
git \
ca-certificates \
+ curl \
upx \
git \
file && \
From 8d8381f59d82613d04d6462b8b5a3d7acaf6ada6 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 3 May 2022 21:41:02 -0500
Subject: [PATCH 111/220] Default fastsurfer_status set to "Not run"
---
smriprep/interfaces/reports.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index dfc91c0ec4..57f8d937c6 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -111,6 +111,7 @@ def _run_interface(self, runtime):
return super(SubjectSummary, self)._run_interface(runtime)
def _generate_segment(self):
+ fastsurfer_status = "Not run"
if not isdefined(self.inputs.subjects_dir):
freesurfer_status = "Not run"
fastsurfer_status = "Not run"
From ff60562a7cafddea52dbf0f8d9e311d67e6809ec Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 4 May 2022 09:38:01 -0500
Subject: [PATCH 112/220] Fix docstring for FastSCommand
---
smriprep/interfaces/fastsurfer.py | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 997917bf54..bbe095cf6b 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -659,14 +659,7 @@ def _list_outputs(self):
class FastSCommand(CommandLine):
- r"""
- Wraps FastSurfer command for segmentation and surface processing::
-
- $ /fastsurfer/run_fastsurfer.sh --fs_license /opt/freesurfer/license \
- --t1 /data/sub-/ses-/anat/sub-_ses-_acq-_T1w.nii.gz \
- --sid sub- --sd /output
-
- Note that T2w and FLAIR are not used for this surface reconstruction
+ """Wraps FastSurfer command for segmentation and surface processing
"""
From 9fe2cda429ccfb2dc4edb9837ec7bb4ce658a5c5 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 4 May 2022 09:41:08 -0500
Subject: [PATCH 113/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index bbe095cf6b..1ff88b18a5 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -659,7 +659,7 @@ def _list_outputs(self):
class FastSCommand(CommandLine):
- """Wraps FastSurfer command for segmentation and surface processing
+ """Wraps FastSurfer command for segmentation and surface processing.
"""
From 6fa46e2dc5a0a2330e0ada8baf5af9efd622e2b7 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 4 May 2022 10:09:31 -0500
Subject: [PATCH 114/220] fix docstring for FastSCommand
---
smriprep/interfaces/fastsurfer.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 1ff88b18a5..d73a9b4652 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -659,9 +659,7 @@ def _list_outputs(self):
class FastSCommand(CommandLine):
- """Wraps FastSurfer command for segmentation and surface processing.
-
- """
+ """Wraps FastSurfer command for segmentation and surface processing."""
input_spec = FastSInputSpec
output_spec = FastSurfSourceOutputSpec
From 0b5d07e06a8cbe2a86ada3874bf4e404c466a081 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 4 May 2022 10:28:31 -0500
Subject: [PATCH 115/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index d73a9b4652..a9daf7fda5 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -659,7 +659,10 @@ def _list_outputs(self):
class FastSCommand(CommandLine):
- """Wraps FastSurfer command for segmentation and surface processing."""
+ """
+ Wraps FastSurfer command for segmentation and surface processing
+
+ """
input_spec = FastSInputSpec
output_spec = FastSurfSourceOutputSpec
From d0d753a79a19ca158b826d51e556aaf7242c1234 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 4 May 2022 11:19:01 -0500
Subject: [PATCH 116/220] Fix imports to resolve Flake8 F821 errors
---
smriprep/interfaces/fastsurfer.py | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index a9daf7fda5..ddc080792e 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -6,26 +6,24 @@
for running FastSurfer CNN and surface processing.
"""
-from ast import BoolOp
-from genericpath import exists
import os
-from xmlrpc.client import Boolean
+import glob
from nipype.interfaces.base import (
CommandLine,
Directory,
CommandLineInputSpec,
OutputMultiPath,
- isdefined,
TraitedSpec,
- BaseInterface,
BaseInterfaceInputSpec,
File,
- PackageInfo,
)
from nipype.interfaces.base.traits_extension import traits
from nipype.interfaces.io import IOBase
-
+from nipype.utils.filemanip import (
+ simplify_list,
+ ensure_list,
+)
class FastSInputSpec(CommandLineInputSpec):
r"""
From ab65e0dfe7ade5cdb848bb5545cd4f9c4c6c0021 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 4 May 2022 11:20:04 -0500
Subject: [PATCH 117/220] Fix typo and switch logger to LOGGER
Addresses Flake8 F521 and F821 errors
---
smriprep/workflows/surfaces.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 778a114000..2087645153 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -208,7 +208,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
"""
workflow = Workflow(name=name)
workflow.__desc__ = """\
-Brain surfaces were reconstructed using `recon-surf` [FastSurfer (fastsurfer_version},
+Brain surfaces were reconstructed using `recon-surf` [FastSurfer {fastsurfer_version},
@fastsurfer], and the brain mask estimated
previously was refined with a custom variation of the method to reconcile
ANTs-derived and FastSurfer-derived segmentations of the cortical
@@ -248,8 +248,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# null for now, placeholder for FastSurfer VINN hires support
if hires:
- if logger:
- logger.warn(f'High-resolution {hires} specified, not currently supported, ignoring.')
+ if LOGGER:
+ LOGGER.warn(f'High-resolution {hires} specified, not currently supported, ignoring.')
fsnative2t1w_xfm = pe.Node(
RobustRegister(auto_sens=True, est_int_scale=True), name="fsnative2t1w_xfm")
From 049937d70b2e4247ea3735f07511c6c281a3ae75 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 4 May 2022 11:21:49 -0500
Subject: [PATCH 118/220] Fix indentation for continuation lines Flake8 E122
---
smriprep/interfaces/reports.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index 57f8d937c6..5dfab88408 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -128,11 +128,11 @@ def _generate_segment(self):
fastsurfer_status = "Run by sMRIPrep"
else:
recon = fs.ReconAll(
- subjects_dir=self.inputs.subjects_dir,
- subject_id=self.inputs.subject_id,
- T1_files=self.inputs.t1w,
- flags="-noskullstrip",
- )
+ subjects_dir=self.inputs.subjects_dir,
+ subject_id=self.inputs.subject_id,
+ T1_files=self.inputs.t1w,
+ flags="-noskullstrip",
+ )
if recon.cmdline.startswith("echo"):
freesurfer_status = "Pre-existing directory"
else:
From 04b5888ccd2b06ffbb593c7412671d16a335c78d Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 4 May 2022 13:55:08 -0500
Subject: [PATCH 119/220] Fix Flake8 error E302 expected 2 blank lines, found 1
---
smriprep/interfaces/fastsurfer.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index ddc080792e..ceb524d89f 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -25,6 +25,7 @@
ensure_list,
)
+
class FastSInputSpec(CommandLineInputSpec):
r"""
Required arguments
From d6f24c544e0c34c9d3035e656ffb982fbec2c832 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 4 May 2022 13:56:41 -0500
Subject: [PATCH 120/220] Fix variable names in fs-subjects-dir nodes
---
smriprep/workflows/base.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/smriprep/workflows/base.py b/smriprep/workflows/base.py
index 511fe30f80..3080c904ca 100644
--- a/smriprep/workflows/base.py
+++ b/smriprep/workflows/base.py
@@ -171,14 +171,13 @@ def init_smriprep_wf(
BIDSFreeSurferDir(
derivatives=output_dir,
freesurfer_home=os.getenv("FREESURFER_HOME"),
- fastsurfer_home=os.getenv("FASTSURFER_HOME"),
spaces=spaces.get_fs_spaces(),
),
name="fastsurfdir_run_%s" % run_uuid.replace("-", "_"),
run_without_submitting=True
)
if fs_subjects_dir is not None:
- fastsurfdir.inputs.sd = str(fs_subjects_dir.absolute())
+ fastsurfdir.inputs.subjects_dir = str(fs_subjects_dir.absolute())
for subject_id in subject_list:
single_subject_wf = init_single_subject_wf(
From 280ca53c63395746b94cde45f491d6b1df215a23 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 4 May 2022 17:34:45 -0500
Subject: [PATCH 121/220] Fix conda base env for FastSurfer
---
Dockerfile | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Dockerfile b/Dockerfile
index a8095ea912..d027d8c216 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -308,6 +308,9 @@ RUN ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
echo "conda activate base" >> ~/.bashrc
+# Install FastSurfer dependencies to base
+RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
+
# Set CPATH for packages relying on compiled libs (e.g. indexed_gzip)
ENV PATH="/opt/conda/bin:$PATH" \
CPATH="/opt/conda/include:$CPATH" \
From 9c5d271b0ea2113944dabc26781ed053d9122c8a Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 5 May 2022 21:50:41 -0500
Subject: [PATCH 122/220] Switch to newer Freesurfer 7.2.0 for FastSufer
forward compatibility
---
Dockerfile => Dockerfile_dev | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
rename Dockerfile => Dockerfile_dev (98%)
diff --git a/Dockerfile b/Dockerfile_dev
similarity index 98%
rename from Dockerfile
rename to Dockerfile_dev
index d027d8c216..fc3ba57ebf 100644
--- a/Dockerfile
+++ b/Dockerfile_dev
@@ -22,9 +22,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-## Start with ubuntu base as in FastSurfer Docker image
-## https://github.com/Deep-MI/FastSurfer/blob/0749f38e656ed0da977c408b4383db88e1a8b563/Docker/Dockerfile
-
FROM ubuntu:20.04 AS build
ENV LANG=C.UTF-8
@@ -78,7 +75,7 @@ RUN echo "source /venv/bin/activate" >> ~/.bashrc
SHELL ["/bin/bash", "--login", "-c"]
# install freesurfer from sMRIPrep version
-RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1.tar.gz \
+RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/7.2.0/freesurfer-linux-ubuntu18_amd64-7.2.0.tar.gz \
| tar zxv --no-same-owner -C /opt \
--exclude='freesurfer/diffusion' \
--exclude='freesurfer/docs' \
From d433f3b9955e81ebde0b732f3a1d8b6f4ea8a28d Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 5 May 2022 21:54:20 -0500
Subject: [PATCH 123/220] Creates Dockerfile for stable FastSurfer version,
FreeSurfer 6.0.1 compatibility
---
Dockerfile | 370 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 370 insertions(+)
create mode 100644 Dockerfile
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000..b7553e74dd
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,370 @@
+# sMRIPrep Docker Container Image distribution
+#
+# MIT License
+#
+# Copyright (c) 2021 The NiPreps Developers
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+FROM ubuntu:20.04 AS build
+
+ENV LANG=C.UTF-8
+ARG PYTHON_VERSION=3.8
+ARG CONDA_FILE=Miniconda3-py38_4.11.0-Linux-x86_64.sh
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Install packages needed for build
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ wget \
+ git \
+ ca-certificates \
+ curl \
+ upx \
+ git \
+ file && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+
+# git clone dev branch of FastSurfer
+RUN cd /opt && mkdir /fastsurfer \
+ && git clone -b stable https://github.com/Deep-MI/FastSurfer.git \
+ && cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml \
+ && cp /opt/FastSurfer/Docker/install_fs_pruned.sh /fastsurfer/install_fs_pruned.sh
+
+# Install conda
+RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/miniconda/$CONDA_FILE && \
+ chmod +x ~/miniconda.sh && \
+ ~/miniconda.sh -b -p /opt/conda && \
+ rm ~/miniconda.sh
+
+ENV PATH /opt/conda/bin:$PATH
+
+# Install our dependencies
+RUN conda env create -f /fastsurfer/fastsurfer_env_gpu.yml
+
+# Install conda-pack:
+RUN conda install -c conda-forge conda-pack
+
+# Use conda-pack to create a standalone enviornment in /venv:
+RUN conda-pack -n fastsurfer_gpu -o /tmp/env.tar && \
+ mkdir /venv && cd /venv && tar xf /tmp/env.tar && \
+ rm /tmp/env.tar
+
+# Now that venv in a new location, fix up paths:
+RUN /venv/bin/conda-unpack
+ENV PATH /venv/bin:$PATH
+
+# setup shell for install command below
+RUN echo "source /venv/bin/activate" >> ~/.bashrc
+SHELL ["/bin/bash", "--login", "-c"]
+
+# install freesurfer from sMRIPrep version
+RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1-f53a55a.tar.gz \
+ | tar zxv --no-same-owner -C /opt \
+ --exclude='freesurfer/diffusion' \
+ --exclude='freesurfer/docs' \
+ --exclude='freesurfer/fsfast' \
+ --exclude='freesurfer/lib/cuda' \
+ --exclude='freesurfer/lib/qt' \
+ --exclude='freesurfer/matlab' \
+ --exclude='freesurfer/mni/share/man' \
+ --exclude='freesurfer/subjects/fsaverage_sym' \
+ --exclude='freesurfer/subjects/fsaverage3' \
+ --exclude='freesurfer/subjects/fsaverage4' \
+ --exclude='freesurfer/subjects/cvs_avg35' \
+ --exclude='freesurfer/subjects/cvs_avg35_inMNI152' \
+ --exclude='freesurfer/subjects/bert' \
+ --exclude='freesurfer/subjects/lh.EC_average' \
+ --exclude='freesurfer/subjects/rh.EC_average' \
+ --exclude='freesurfer/subjects/sample-*.mgz' \
+ --exclude='freesurfer/subjects/V1_average' \
+ --exclude='freesurfer/trctrain'
+
+# Install required packages for freesurfer to run
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ tcsh \
+ time \
+ bc \
+ gawk \
+ libgomp1 && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+
+# Add FreeSurfer Environment variables
+ENV OS=Linux \
+ FS_OVERRIDE=0 \
+ FIX_VERTEX_AREA= \
+ SUBJECTS_DIR=/opt/freesurfer/subjects \
+ FSF_OUTPUT_FORMAT=nii.gz \
+ FREESURFER_HOME=/opt/freesurfer \
+ PYTHONUNBUFFERED=0 \
+ PATH=/venv/bin:/opt/freesurfer/bin:$PATH
+
+# make sure we use bash and activate conda env
+# (in case someone starts this interactively)
+RUN echo "source /venv/bin/activate" >> ~/.bashrc
+SHELL ["/bin/bash", "--login", "-c"]
+
+# Copy fastsurfer from git folder
+RUN cp -R /opt/FastSurfer/* /fastsurfer/
+
+# Simulate SetUpFreeSurfer.sh
+ENV FSL_DIR="/opt/fsl-6.0.5.1" \
+ OS="Linux" \
+ FS_OVERRIDE=0 \
+ FIX_VERTEX_AREA="" \
+ FSF_OUTPUT_FORMAT="nii.gz" \
+ FREESURFER_HOME="/opt/freesurfer"
+ENV SUBJECTS_DIR="$FREESURFER_HOME/subjects" \
+ FUNCTIONALS_DIR="$FREESURFER_HOME/sessions" \
+ MNI_DIR="$FREESURFER_HOME/mni" \
+ LOCAL_DIR="$FREESURFER_HOME/local" \
+ MINC_BIN_DIR="$FREESURFER_HOME/mni/bin" \
+ MINC_LIB_DIR="$FREESURFER_HOME/mni/lib" \
+ MNI_DATAPATH="$FREESURFER_HOME/mni/data"
+ENV PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
+ MNI_PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
+ PATH="$FREESURFER_HOME/bin:$FSFAST_HOME/bin:$FREESURFER_HOME/tktools:$MINC_BIN_DIR:$PATH"
+
+# FSL 6.0.5.1
+RUN apt-get update -qq \
+ && apt-get install -y -q --no-install-recommends \
+ bc \
+ dc \
+ file \
+ libfontconfig1 \
+ libfreetype6 \
+ libgl1-mesa-dev \
+ libgl1-mesa-dri \
+ libglu1-mesa-dev \
+ libgomp1 \
+ libice6 \
+ libxcursor1 \
+ libxft2 \
+ libxinerama1 \
+ libxrandr2 \
+ libxrender1 \
+ libxt6 \
+ sudo \
+ curl \
+ wget \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* \
+ && echo "Downloading FSL ..." \
+ && mkdir -p /opt/fsl-6.0.5.1 \
+ && curl -fsSL --retry 5 https://fsl.fmrib.ox.ac.uk/fsldownloads/fsl-6.0.5.1-centos7_64.tar.gz \
+ | tar -xz -C /opt/fsl-6.0.5.1 --strip-components 1 \
+ --exclude "fsl/config" \
+ --exclude "fsl/data/atlases" \
+ --exclude "fsl/data/first" \
+ --exclude "fsl/data/mist" \
+ --exclude "fsl/data/possum" \
+ --exclude "fsl/data/standard/bianca" \
+ --exclude "fsl/data/standard/tissuepriors" \
+ --exclude "fsl/doc" \
+ --exclude "fsl/etc/default_flobs.flobs" \
+ --exclude "fsl/etc/fslconf" \
+ --exclude "fsl/etc/js" \
+ --exclude "fsl/etc/luts" \
+ --exclude "fsl/etc/matlab" \
+ --exclude "fsl/extras" \
+ --exclude "fsl/include" \
+ --exclude "fsl/python" \
+ --exclude "fsl/refdoc" \
+ --exclude "fsl/src" \
+ --exclude "fsl/tcl" \
+ --exclude "fsl/bin/FSLeyes" \
+ && find /opt/fsl-6.0.5.1/bin -type f -not \( \
+ -name "applywarp" -or \
+ -name "bet" -or \
+ -name "bet2" -or \
+ -name "convert_xfm" -or \
+ -name "fast" -or \
+ -name "flirt" -or \
+ -name "fsl_regfilt" -or \
+ -name "fslhd" -or \
+ -name "fslinfo" -or \
+ -name "fslmaths" -or \
+ -name "fslmerge" -or \
+ -name "fslroi" -or \
+ -name "fslsplit" -or \
+ -name "fslstats" -or \
+ -name "imtest" -or \
+ -name "mcflirt" -or \
+ -name "melodic" -or \
+ -name "prelude" -or \
+ -name "remove_ext" -or \
+ -name "susan" -or \
+ -name "topup" -or \
+ -name "zeropad" \) -delete \
+ && find /opt/fsl-6.0.5.1/data/standard -type f -not -name "MNI152_T1_2mm_brain.nii.gz" -delete
+ENV FSLDIR="/opt/fsl-6.0.5.1" \
+ PATH="/opt/fsl-6.0.5.1/bin:$PATH" \
+ FSLOUTPUTTYPE="NIFTI_GZ" \
+ FSLMULTIFILEQUIT="TRUE" \
+ FSLLOCKDIR="" \
+ FSLMACHINELIST="" \
+ FSLREMOTECALL="" \
+ FSLGECUDAQ="cuda.q" \
+ LD_LIBRARY_PATH="/opt/fsl-6.0.5.1/lib:$LD_LIBRARY_PATH"
+
+# Convert3D (neurodocker build)
+RUN echo "Downloading Convert3D ..." \
+ && mkdir -p /opt/convert3d-1.0.0 \
+ && curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz/download \
+ | tar -xz -C /opt/convert3d-1.0.0 --strip-components 1 \
+ --exclude "c3d-1.0.0-Linux-x86_64/lib" \
+ --exclude "c3d-1.0.0-Linux-x86_64/share" \
+ --exclude "c3d-1.0.0-Linux-x86_64/bin/c3d_gui"
+ENV C3DPATH="/opt/convert3d-1.0.0" \
+ PATH="/opt/convert3d-1.0.0/bin:$PATH"
+
+# AFNI latest (neurodocker build)
+RUN apt-get update -qq \
+ && apt-get install -y -q --no-install-recommends \
+ apt-utils \
+ ed \
+ gsl-bin \
+ libglib2.0-0 \
+ libglu1-mesa-dev \
+ libglw1-mesa \
+ libgomp1 \
+ libjpeg62 \
+ libxm4 \
+ netpbm \
+ tcsh \
+ xfonts-base \
+ xvfb \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* \
+# && curl -sSL --retry 5 -o /tmp/multiarch.deb http://archive.ubuntu.com/ubuntu/pool/main/g/glibc/multiarch-support_2.27-3ubuntu1.2_amd64.deb \
+# && dpkg -i /tmp/multiarch.deb \
+# && rm /tmp/multiarch.deb \
+# && curl -sSL --retry 5 -o /tmp/libxp6.deb http://mirrors.kernel.org/debian/pool/main/libx/libxp/libxp6_1.0.2-2_amd64.deb \
+# && dpkg -i /tmp/libxp6.deb \
+# && rm /tmp/libxp6.deb \
+# && curl -sSL --retry 5 -o /tmp/libpng.deb http://snapshot.debian.org/archive/debian-security/20160113T213056Z/pool/updates/main/libp/libpng/libpng12-0_1.2.49-1%2Bdeb7u2_amd64.deb \
+# && dpkg -i /tmp/libpng.deb \
+# && rm /tmp/libpng.deb \
+# && apt-get install -f \
+# && apt-get clean \
+# && rm -rf /var/lib/apt/lists/* \
+ && gsl2_path="$(find / -name 'libgsl.so.19' || printf '')" \
+ && if [ -n "$gsl2_path" ]; then \
+ ln -sfv "$gsl2_path" "$(dirname $gsl2_path)/libgsl.so.0"; \
+ fi \
+ && ldconfig \
+ && echo "Downloading AFNI ..." \
+ && mkdir -p /opt/afni-latest \
+ && curl -fsSL --retry 5 https://afni.nimh.nih.gov/pub/dist/tgz/linux_openmp_64.tgz \
+ | tar -xz -C /opt/afni-latest --strip-components 1 \
+ --exclude "linux_openmp_64/*.gz" \
+ --exclude "linux_openmp_64/funstuff" \
+ --exclude "linux_openmp_64/shiny" \
+ --exclude "linux_openmp_64/afnipy" \
+ --exclude "linux_openmp_64/lib/RetroTS" \
+ --exclude "linux_openmp_64/meica.libs" \
+ # Keep only what we use
+ && find /opt/afni-latest -type f -not \( \
+ -name "3dTshift" -or \
+ -name "3dUnifize" -or \
+ -name "3dAutomask" -or \
+ -name "3dvolreg" \) -delete
+
+ENV PATH="/opt/afni-latest:$PATH" \
+ AFNI_IMSAVE_WARNINGS="NO" \
+ AFNI_PLUGINPATH="/opt/afni-latest"
+
+# Installing ANTs 2.3.3 (NeuroDocker build)
+# Note: the URL says 2.3.4 but it is actually 2.3.3
+ENV ANTSPATH="/opt/ants" \
+ PATH="/opt/ants:$PATH"
+WORKDIR $ANTSPATH
+RUN curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \
+ | tar -xzC $ANTSPATH --strip-components 1
+
+COPY --from=nipreps/miniconda@sha256:4d0dc0fabb794e9fe22ee468ae5f86c2c8c2b4cd9d7b7fdf0c134d9e13838729 /opt/conda /opt/conda
+
+RUN ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
+ echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
+ echo "conda activate base" >> ~/.bashrc
+
+# Install FastSurfer dependencies to base
+RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
+
+# Set CPATH for packages relying on compiled libs (e.g. indexed_gzip)
+ENV PATH="/opt/conda/bin:$PATH" \
+ CPATH="/opt/conda/include:$CPATH" \
+ LD_LIBRARY_PATH="/opt/conda/lib:$LD_LIBRARY_PATH" \
+ LANG="C.UTF-8" \
+ LC_ALL="C.UTF-8" \
+ PYTHONNOUSERSITE=1
+
+# Unless otherwise specified each process should only use one thread - nipype
+# will handle parallelization
+ENV MKL_NUM_THREADS=1 \
+ OMP_NUM_THREADS=1
+
+# Create a shared $HOME directory
+RUN useradd -m -s /bin/bash -G users smriprep
+WORKDIR /home/smriprep
+ENV HOME="/home/smriprep" \
+ LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH"
+
+RUN echo ". /opt/conda/etc/profile.d/conda.sh" >> $HOME/.bashrc && \
+ echo "conda activate base" >> $HOME/.bashrc
+
+# Precaching atlases
+COPY scripts/fetch_templates.py fetch_templates.py
+
+RUN /opt/conda/bin/python fetch_templates.py && \
+ rm fetch_templates.py && \
+ find $HOME/.cache/templateflow -type d -exec chmod go=u {} + && \
+ find $HOME/.cache/templateflow -type f -exec chmod go=u {} +
+
+# Installing sMRIPREP
+COPY . /src/smriprep
+ARG VERSION
+# Force static versioning within container
+RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
+ echo "include smriprep/VERSION" >> /src/smriprep/MANIFEST.in && \
+ /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]"
+
+RUN find $HOME -type d -exec chmod go=u {} + && \
+ find $HOME -type f -exec chmod go=u {} + && \
+ rm -rf $HOME/.npm $HOME/.conda $HOME/.empty
+
+ENV IS_DOCKER_8395080871=1
+ENV FASTSURFER_HOME=/fastsurfer
+
+RUN ldconfig
+WORKDIR /tmp
+ENTRYPOINT ["/opt/conda/bin/smriprep"]
+
+ARG BUILD_DATE
+ARG VCS_REF
+ARG VERSION
+LABEL org.label-schema.build-date=$BUILD_DATE \
+ org.label-schema.name="sMRIPrep" \
+ org.label-schema.description="sMRIPrep - robust structural MRI preprocessing tool" \
+ org.label-schema.url="http://smriprep.org" \
+ org.label-schema.vcs-ref=$VCS_REF \
+ org.label-schema.vcs-url="https://github.com/nipreps/smriprep" \
+ org.label-schema.version=$VERSION \
+ org.label-schema.schema-version="1.0"
From 7a6a6e82467437868227dffa8bf93d89198bfbcb Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 5 May 2022 22:07:30 -0500
Subject: [PATCH 124/220] Remove unnecessary copy instruction
---
Dockerfile | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index b7553e74dd..3963f89042 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -44,8 +44,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
# git clone dev branch of FastSurfer
RUN cd /opt && mkdir /fastsurfer \
&& git clone -b stable https://github.com/Deep-MI/FastSurfer.git \
- && cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml \
- && cp /opt/FastSurfer/Docker/install_fs_pruned.sh /fastsurfer/install_fs_pruned.sh
+ && cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
# Install conda
RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/miniconda/$CONDA_FILE && \
From 960fdeebeaf503c1b5281bcfa0509ad6a71000e8 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 6 May 2022 10:08:00 -0500
Subject: [PATCH 125/220] Revert to python3.6 for FastSurfer 1.0.1
---
Dockerfile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 3963f89042..07db6d35ef 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -25,8 +25,8 @@
FROM ubuntu:20.04 AS build
ENV LANG=C.UTF-8
-ARG PYTHON_VERSION=3.8
-ARG CONDA_FILE=Miniconda3-py38_4.11.0-Linux-x86_64.sh
+ARG PYTHON_VERSION=3.6
+ARG CONDA_FILE=Miniconda3-py37_4.10.3-Linux-x86_64.sh
ENV DEBIAN_FRONTEND=noninteractive
# Install packages needed for build
From f79f21cb92b620deb7266af2299fc120a3157ff2 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 6 May 2022 12:30:34 -0500
Subject: [PATCH 126/220] Remove redundancies in conda envs
---
Dockerfile | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 07db6d35ef..5abfb360a6 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -54,24 +54,24 @@ RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/min
ENV PATH /opt/conda/bin:$PATH
-# Install our dependencies
-RUN conda env create -f /fastsurfer/fastsurfer_env_gpu.yml
-
-# Install conda-pack:
-RUN conda install -c conda-forge conda-pack
+# # Install our dependencies
+# RUN conda env create -f /fastsurfer/fastsurfer_env_gpu.yml
+#
+# # Install conda-pack:
+# RUN conda install -c conda-forge conda-pack
-# Use conda-pack to create a standalone enviornment in /venv:
-RUN conda-pack -n fastsurfer_gpu -o /tmp/env.tar && \
- mkdir /venv && cd /venv && tar xf /tmp/env.tar && \
- rm /tmp/env.tar
+# # Use conda-pack to create a standalone enviornment in /venv:
+# RUN conda-pack -n fastsurfer_gpu -o /tmp/env.tar && \
+# mkdir /venv && cd /venv && tar xf /tmp/env.tar && \
+# rm /tmp/env.tar
-# Now that venv in a new location, fix up paths:
-RUN /venv/bin/conda-unpack
-ENV PATH /venv/bin:$PATH
+# # Now that venv in a new location, fix up paths:
+# RUN /venv/bin/conda-unpack
+# ENV PATH /venv/bin:$PATH
-# setup shell for install command below
-RUN echo "source /venv/bin/activate" >> ~/.bashrc
-SHELL ["/bin/bash", "--login", "-c"]
+# # setup shell for install command below
+# RUN echo "source /venv/bin/activate" >> ~/.bashrc
+# SHELL ["/bin/bash", "--login", "-c"]
# install freesurfer from sMRIPrep version
RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1-f53a55a.tar.gz \
@@ -113,12 +113,12 @@ ENV OS=Linux \
FSF_OUTPUT_FORMAT=nii.gz \
FREESURFER_HOME=/opt/freesurfer \
PYTHONUNBUFFERED=0 \
- PATH=/venv/bin:/opt/freesurfer/bin:$PATH
+ PATH=/opt/freesurfer/bin:$PATH
-# make sure we use bash and activate conda env
-# (in case someone starts this interactively)
-RUN echo "source /venv/bin/activate" >> ~/.bashrc
-SHELL ["/bin/bash", "--login", "-c"]
+# # make sure we use bash and activate conda env
+# # (in case someone starts this interactively)
+# RUN echo "source /venv/bin/activate" >> ~/.bashrc
+# SHELL ["/bin/bash", "--login", "-c"]
# Copy fastsurfer from git folder
RUN cp -R /opt/FastSurfer/* /fastsurfer/
From dc2c5f7c8e06671fcc93ac39de34bdac71c04c5b Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Sat, 7 May 2022 17:16:59 -0500
Subject: [PATCH 127/220] Update Dockerfile
---
Dockerfile | 51 +++++++++++++++++++++++++++------------------------
1 file changed, 27 insertions(+), 24 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 5abfb360a6..fbedb15568 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -22,6 +22,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
+## Start with ubuntu base as in FastSurfer Docker image
+## https://github.com/Deep-MI/FastSurfer/blob/0749f38e656ed0da977c408b4383db88e1a8b563/Docker/Dockerfile
+
FROM ubuntu:20.04 AS build
ENV LANG=C.UTF-8
@@ -54,24 +57,24 @@ RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/min
ENV PATH /opt/conda/bin:$PATH
-# # Install our dependencies
-# RUN conda env create -f /fastsurfer/fastsurfer_env_gpu.yml
-#
-# # Install conda-pack:
-# RUN conda install -c conda-forge conda-pack
+# Install our dependencies
+RUN conda env create -f /fastsurfer/fastsurfer_env_gpu.yml
+
+# Install conda-pack:
+RUN conda install -c conda-forge conda-pack
-# # Use conda-pack to create a standalone enviornment in /venv:
-# RUN conda-pack -n fastsurfer_gpu -o /tmp/env.tar && \
-# mkdir /venv && cd /venv && tar xf /tmp/env.tar && \
-# rm /tmp/env.tar
+# Use conda-pack to create a standalone enviornment in /venv:
+RUN conda-pack -n fastsurfer_gpu -o /tmp/env.tar && \
+ mkdir /venv && cd /venv && tar xf /tmp/env.tar && \
+ rm /tmp/env.tar
-# # Now that venv in a new location, fix up paths:
-# RUN /venv/bin/conda-unpack
-# ENV PATH /venv/bin:$PATH
+# Now that venv in a new location, fix up paths:
+RUN /venv/bin/conda-unpack
+ENV PATH /venv/bin:$PATH
-# # setup shell for install command below
-# RUN echo "source /venv/bin/activate" >> ~/.bashrc
-# SHELL ["/bin/bash", "--login", "-c"]
+# setup shell for install command below
+RUN echo "source /venv/bin/activate" >> ~/.bashrc
+SHELL ["/bin/bash", "--login", "-c"]
# install freesurfer from sMRIPrep version
RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1-f53a55a.tar.gz \
@@ -113,12 +116,12 @@ ENV OS=Linux \
FSF_OUTPUT_FORMAT=nii.gz \
FREESURFER_HOME=/opt/freesurfer \
PYTHONUNBUFFERED=0 \
- PATH=/opt/freesurfer/bin:$PATH
+ PATH=/venv/bin:/opt/freesurfer/bin:$PATH
-# # make sure we use bash and activate conda env
-# # (in case someone starts this interactively)
-# RUN echo "source /venv/bin/activate" >> ~/.bashrc
-# SHELL ["/bin/bash", "--login", "-c"]
+# make sure we use bash and activate conda env
+# (in case someone starts this interactively)
+RUN echo "source /venv/bin/activate" >> ~/.bashrc
+SHELL ["/bin/bash", "--login", "-c"]
# Copy fastsurfer from git folder
RUN cp -R /opt/FastSurfer/* /fastsurfer/
@@ -304,9 +307,6 @@ RUN ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
echo "conda activate base" >> ~/.bashrc
-# Install FastSurfer dependencies to base
-RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
-
# Set CPATH for packages relying on compiled libs (e.g. indexed_gzip)
ENV PATH="/opt/conda/bin:$PATH" \
CPATH="/opt/conda/include:$CPATH" \
@@ -327,7 +327,8 @@ ENV HOME="/home/smriprep" \
LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH"
RUN echo ". /opt/conda/etc/profile.d/conda.sh" >> $HOME/.bashrc && \
- echo "conda activate base" >> $HOME/.bashrc
+ echo "conda activate base" >> $HOME/.bashrc && \
+ echo "$FREESURFER_HOME/SetUpFreeSurfer.sh" >> $HOME/.bashrc
# Precaching atlases
COPY scripts/fetch_templates.py fetch_templates.py
@@ -345,6 +346,8 @@ RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
echo "include smriprep/VERSION" >> /src/smriprep/MANIFEST.in && \
/opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]"
+RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
+
RUN find $HOME -type d -exec chmod go=u {} + && \
find $HOME -type f -exec chmod go=u {} + && \
rm -rf $HOME/.npm $HOME/.conda $HOME/.empty
From bd40cb61a1c42132972d6beb1d09af973969afca Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 9 May 2022 10:36:53 -0500
Subject: [PATCH 128/220] Fix: remove redundant conda build instructions and
venv
---
Dockerfile | 26 +-------------------------
1 file changed, 1 insertion(+), 25 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index fbedb15568..7bcba9426c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -57,25 +57,6 @@ RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/min
ENV PATH /opt/conda/bin:$PATH
-# Install our dependencies
-RUN conda env create -f /fastsurfer/fastsurfer_env_gpu.yml
-
-# Install conda-pack:
-RUN conda install -c conda-forge conda-pack
-
-# Use conda-pack to create a standalone enviornment in /venv:
-RUN conda-pack -n fastsurfer_gpu -o /tmp/env.tar && \
- mkdir /venv && cd /venv && tar xf /tmp/env.tar && \
- rm /tmp/env.tar
-
-# Now that venv in a new location, fix up paths:
-RUN /venv/bin/conda-unpack
-ENV PATH /venv/bin:$PATH
-
-# setup shell for install command below
-RUN echo "source /venv/bin/activate" >> ~/.bashrc
-SHELL ["/bin/bash", "--login", "-c"]
-
# install freesurfer from sMRIPrep version
RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1-f53a55a.tar.gz \
| tar zxv --no-same-owner -C /opt \
@@ -116,12 +97,7 @@ ENV OS=Linux \
FSF_OUTPUT_FORMAT=nii.gz \
FREESURFER_HOME=/opt/freesurfer \
PYTHONUNBUFFERED=0 \
- PATH=/venv/bin:/opt/freesurfer/bin:$PATH
-
-# make sure we use bash and activate conda env
-# (in case someone starts this interactively)
-RUN echo "source /venv/bin/activate" >> ~/.bashrc
-SHELL ["/bin/bash", "--login", "-c"]
+ PATH=/opt/freesurfer/bin:$PATH
# Copy fastsurfer from git folder
RUN cp -R /opt/FastSurfer/* /fastsurfer/
From 0784da5d6af4a0ae636789c80b8dd31acb5b4443 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 24 May 2022 17:54:58 -0500
Subject: [PATCH 129/220] Fix retrieval of FastSurfer dev branch
---
Dockerfile | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 73c02a98c1..fe3b3afcfe 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -27,6 +27,22 @@
FROM ubuntu:focal-20210416
# Prepare environment
+ENV DEBIAN_FRONTEND="noninteractive"
+ENV LANG=C.UTF-8
+ARG PYTHON_VERSION=3.6
+ARG CONDA_FILE=Miniconda3-py37_4.10.3-Linux-x86_64.sh
+ENV DEBIAN_FRONTEND=noninteractive
+# git clone dev branch of FastSurfer
+RUN cd /opt && mkdir /fastsurfer \
+ && git clone -b dev https://github.com/Deep-MI/FastSurfer.git \
+ && cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
+
+# Install conda
+RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/miniconda/$CONDA_FILE && \
+ chmod +x ~/miniconda.sh && \
+ ~/miniconda.sh -b -p /opt/conda && \
+ rm ~/miniconda.sh
+
RUN apt-get update && \
apt-get install -y --no-install-recommends \
apt-utils \
@@ -44,12 +60,6 @@ RUN apt-get update && \
xvfb && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
-
-ENV LANG=C.UTF-8
-ARG PYTHON_VERSION=3.6
-ARG CONDA_FILE=Miniconda3-py37_4.10.3-Linux-x86_64.sh
-ENV DEBIAN_FRONTEND=noninteractive
-
# Installing freesurfer
COPY docker/files/freesurfer7.2-exclude.txt /usr/local/etc/freesurfer7.2-exclude.txt
RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/7.2.0/freesurfer-linux-ubuntu18_amd64-7.2.0.tar.gz \
From ebd3318009ece2e48156f4ee3801643022a39352 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 24 May 2022 18:01:33 -0500
Subject: [PATCH 130/220] Fix layer order
---
Dockerfile | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index fe3b3afcfe..938ce2e6db 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -32,16 +32,6 @@ ENV LANG=C.UTF-8
ARG PYTHON_VERSION=3.6
ARG CONDA_FILE=Miniconda3-py37_4.10.3-Linux-x86_64.sh
ENV DEBIAN_FRONTEND=noninteractive
-# git clone dev branch of FastSurfer
-RUN cd /opt && mkdir /fastsurfer \
- && git clone -b dev https://github.com/Deep-MI/FastSurfer.git \
- && cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
-
-# Install conda
-RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/miniconda/$CONDA_FILE && \
- chmod +x ~/miniconda.sh && \
- ~/miniconda.sh -b -p /opt/conda && \
- rm ~/miniconda.sh
RUN apt-get update && \
apt-get install -y --no-install-recommends \
@@ -60,12 +50,22 @@ RUN apt-get update && \
xvfb && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+# git clone dev branch of FastSurfer
+RUN cd /opt && mkdir /fastsurfer \
+ && git clone -b dev https://github.com/Deep-MI/FastSurfer.git \
+ && cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
+
+# Install conda
+RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/miniconda/$CONDA_FILE && \
+ chmod +x ~/miniconda.sh && \
+ ~/miniconda.sh -b -p /opt/conda && \
+ rm ~/miniconda.sh
+
# Installing freesurfer
COPY docker/files/freesurfer7.2-exclude.txt /usr/local/etc/freesurfer7.2-exclude.txt
RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/7.2.0/freesurfer-linux-ubuntu18_amd64-7.2.0.tar.gz \
| tar zxv --no-same-owner -C /opt --exclude-from=/usr/local/etc/freesurfer7.2-exclude.txt
-
# Install required packages for freesurfer to run
RUN apt-get update && apt-get install -y --no-install-recommends \
tcsh \
From c6e97411385b1435df4ad18bb868b65ea7812594 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 25 May 2022 10:49:30 -0500
Subject: [PATCH 131/220] Fix missing libs
---
Dockerfile | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Dockerfile b/Dockerfile
index 938ce2e6db..ffca4d4d91 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -41,6 +41,9 @@ RUN apt-get update && \
bzip2 \
ca-certificates \
curl \
+ wget \
+ upx \
+ file \
git \
libtool \
lsb-release \
From 532313e9bb7509d3a1eebe0314c33c766a51961a Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 23 Jun 2022 14:02:56 -0500
Subject: [PATCH 132/220] Update arguments for fastsurfer
---
smriprep/cli/run.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 37e5e7607e..1a4ac29da9 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -229,8 +229,10 @@ def get_parser():
dest="fastsurfer",
help="enable FastSurfer surface preprocessing.",
)
- g_surfs_xor = g_surfs.add_mutually_exclusive_group()
-
+ # g_surfs_xor = g_surfs.add_mutually_exclusive_group()
+
+ g_surfs_xor = g_surfs
+
g_surfs_xor.add_argument(
"--fs-no-reconall",
action="store_false",
@@ -414,6 +416,8 @@ def _warn_redirect(message, category, filename, lineno, file=None, line=None):
from templateflow import api
from niworkflows.utils.misc import _copy_any
+ # developer note - remove
+ print(string(fastsurfer))
dseg_tsv = str(api.get("fsaverage", suffix="dseg", extension=[".tsv"]))
_copy_any(
dseg_tsv, str(Path(output_dir) / "smriprep" / "desc-aseg_dseg.tsv")
From 219a4224eb579dee1020c8dd1abf21db7305b2ac Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 23 Jun 2022 14:04:14 -0500
Subject: [PATCH 133/220] Fix support for fastsurfer workflow
---
smriprep/interfaces/fastsurfer.py | 40 +++++++++++++++++--------------
smriprep/interfaces/reports.py | 1 +
2 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index ceb524d89f..d5fcefc209 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -125,24 +125,24 @@ class FastSInputSpec(CommandLineInputSpec):
sd = Directory(
exists=True,
argstr="--sd %s",
- mandatory=True,
+ mandatory=False,
desc="Subjects directory"
)
sid = traits.String(
exists=True,
argstr="--sid %s",
- mandatory=True,
+ mandatory=False,
desc="Subject ID"
)
t1 = File(
exists=True,
- mandatory=True,
+ mandatory=False,
argstr="--t1 %s",
desc="T1 full head input (not bias corrected, global path)"
)
fs_license = File(
exists=True,
- mandatory=True,
+ mandatory=False,
argstr="--fs_license %s",
desc="Path to FreeSurfer license key file."
)
@@ -298,28 +298,21 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
sd = Directory(
exists=True,
argstr="--sd %s",
- mandatory=True,
+ mandatory=False,
desc="Subjects directory"
)
sid = traits.String(
exists=True,
argstr="--sid %s",
- mandatory=True,
+ mandatory=False,
desc="Subject ID"
)
t1 = File(
exists=True,
- mandatory=True,
+ mandatory=False,
argstr="--t1 %s",
desc="T1 full head input (not bias corrected, global path)"
)
- fs_license = File(
- exists=True,
- mandatory=True,
- argstr="--fs_license %s",
- desc="Path to FreeSurfer license key file."
- )
-
class FastSurfSourceOutputSpec(TraitedSpec):
T1 = File(
@@ -600,6 +593,16 @@ class FastSurfSourceOutputSpec(TraitedSpec):
altkey="aseg.presurf.hypos",
desc="Automated segmentation pre-surface recon statistics files"
)
+ sd = Directory(
+ exists=True,
+ argstr="--sd %s",
+ desc="Subjects directory"
+ )
+ sid = traits.String(
+ exists=True,
+ argstr="--sid %s",
+ desc="Subject ID"
+ )
class FastSurferSource(IOBase):
@@ -641,8 +644,9 @@ def _get_files(self, path, key, dirval, altkey=None):
]
def _list_outputs(self):
- subjects_dir = self.inputs.subjects_dir
- subject_path = os.path.join(subjects_dir, self.inputs.subject_id)
+ subjects_dir = self.inputs.sd
+ subject_id = self.inputs.sid
+ subject_path = os.path.join(subjects_dir, subject_id)
output_traits = self._outputs()
outputs = output_traits.get()
for k in list(outputs.keys()):
@@ -663,9 +667,9 @@ class FastSCommand(CommandLine):
"""
- input_spec = FastSInputSpec
+ input_spec = FastSurfSourceInputSpec
output_spec = FastSurfSourceOutputSpec
- _cmd = '/fastsurfer/run_fastsurfer.sh'
+ _cmd = '/fastsurfer/run_fastsurfer.sh --surfreg'
def _list_outputs(self):
outputs = self.output_spec().get()
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index 5dfab88408..2bf90e8816 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -38,6 +38,7 @@
from nipype.interfaces import freesurfer as fs
from nipype.interfaces.io import FSSourceInputSpec as _FSSourceInputSpec
from smriprep.interfaces.fastsurfer import FastSurfSourceInputSpec as _FastSurfSourceInputSpec
+from smriprep.interfaces.fastsurfer import FastSurfSourceOutputSpec as _FastSurfSourceOutputSpec
from smriprep.interfaces import fastsurfer as fastsurf
from smriprep.utils.misc import check_fastsurfer
from nipype.interfaces.mixins import reporting
From 97accf46e67bc2ac5f9e9ca75e91391e9faa16ed Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 23 Jun 2022 14:04:53 -0500
Subject: [PATCH 134/220] Fix workflow for FastSurfer
---
smriprep/workflows/anatomical.py | 28 +++++++++++------------
smriprep/workflows/base.py | 6 ++++-
smriprep/workflows/surfaces.py | 39 +++++++++++++++++++-------------
3 files changed, 42 insertions(+), 31 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 0979a86aad..0e873370f6 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -421,10 +421,10 @@ def _check_img(img):
(('outputnode.bias_corrected', _pop), 'inputnode.moving_image')]),
(buffernode, anat_norm_wf, [('t1w_mask', 'inputnode.moving_mask')]),
(anat_norm_wf, outputnode, [
- ('poutputnode.standardized', 'std_preproc'),
- ('poutputnode.std_mask', 'std_mask'),
- ('poutputnode.std_dseg', 'std_dseg'),
- ('poutputnode.std_tpms', 'std_tpms'),
+ ('outputnode.standardized', 'std_preproc'),
+ ('outputnode.std_mask', 'std_mask'),
+ ('outputnode.std_dseg', 'std_dseg'),
+ ('outputnode.std_tpms', 'std_tpms'),
('outputnode.template', 'template'),
('outputnode.anat2std_xfm', 'anat2std_xfm'),
('outputnode.std2anat_xfm', 'std2anat_xfm'),
@@ -454,11 +454,11 @@ def _check_img(img):
(anat_template_wf, anat_reports_wf, [
('outputnode.out_report', 'inputnode.t1w_conform_report')]),
(anat_norm_wf, anat_reports_wf, [
- ('poutputnode.template', 'inputnode.template')]),
+ ('outputnode.template', 'inputnode.template')]),
])
# fmt:on
- # Write outputs ############################################3
+ # Write outputs #
anat_derivatives_wf = init_anat_derivatives_wf(
bids_root=bids_root,
freesurfer=freesurfer,
@@ -512,7 +512,7 @@ def _check_img(img):
(fast2bids, outputnode, [('out', 't1w_tpms')]),
])
# fmt:on
- if not freesurfer: # Flag --fs-no-reconall is set - return
+ if (not freesurfer) and (not fastsurfer): # Flag --fs-no-reconall is set - return
# fmt:off
workflow.connect([
(brain_extraction_wf, buffernode, [
@@ -536,7 +536,7 @@ def _check_img(img):
check_fastsurfer.inputs.logger = LOGGER
# Select which surface reconstruction workflow based on CLI arguments
- if freesurfer:
+ if freesurfer and (not freesurfer):
surface_recon_wf = init_surface_recon_wf(
name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
@@ -591,8 +591,8 @@ def _check_img(img):
# fmt:off
workflow.connect([
(inputnode, fastsurf_recon_wf, [
- ('subject_id', 'inputnode.subject_id'),
- ('subjects_dir', 'inputnode.subjects_dir')]),
+ ('subject_id', 'inputnode.sid'),
+ ('subjects_dir', 'inputnode.sd')]),
(anat_validate, fastsurf_recon_wf, [
('out_file', 'inputnode.t1w')]),
(brain_extraction_wf, fastsurf_recon_wf, [
@@ -604,8 +604,8 @@ def _check_img(img):
(fastsurf_recon_wf, applyrefined, [
('outputnode.out_brainmask', 'mask_file')]),
(fastsurf_recon_wf, outputnode, [
- ('outputnode.subjects_dir', 'subjects_dir'),
- ('outputnode.subject_id', 'subject_id'),
+ ('inputnode.sd', 'subjects_dir'),
+ ('inputnode.sid', 'subject_id'),
('outputnode.t1w2fsnative_xfm', 't1w2fsnative_xfm'),
('outputnode.fsnative2t1w_xfm', 'fsnative2t1w_xfm'),
('outputnode.surfaces', 'surfaces'),
@@ -614,8 +614,8 @@ def _check_img(img):
(applyrefined, buffernode, [('out_file', 't1w_brain')]),
(fastsurf_recon_wf, buffernode, [('outputnode.out_brainmask', 't1w_mask')]),
(fastsurf_recon_wf, anat_reports_wf, [
- ('outputnode.subject_id', 'inputnode.subject_id'),
- ('outputnode.subjects_dir', 'inputnode.subjects_dir'),
+ ('inputnode.sid', 'inputnode.subject_id'),
+ ('inputnode.sd', 'inputnode.subjects_dir'),
]),
(fastsurf_recon_wf, anat_derivatives_wf, [
('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
diff --git a/smriprep/workflows/base.py b/smriprep/workflows/base.py
index 3080c904ca..7ca9918cd7 100644
--- a/smriprep/workflows/base.py
+++ b/smriprep/workflows/base.py
@@ -167,6 +167,7 @@ def init_smriprep_wf(
fsdir.inputs.subjects_dir = str(fs_subjects_dir.absolute())
if fastsurfer:
+ freesurfer = False
fastsurfdir = pe.Node(
BIDSFreeSurferDir(
derivatives=output_dir,
@@ -211,7 +212,7 @@ def init_smriprep_wf(
)
elif fastsurfer:
smriprep_wf.connect(
- fastsurfdir, "sd", single_subject_wf, "inputnode.subjects_dir"
+ fastsurfdir, "subjects_dir", single_subject_wf, "inputnode.subjects_dir"
)
else:
smriprep_wf.add_nodes([single_subject_wf])
@@ -376,6 +377,9 @@ def init_single_subject_wf(
Path(output_dir) / "smriprep", subject_id, std_spaces, freesurfer
)
+ if fastsurfer:
+ freesurfer = False
+
inputnode = pe.Node(
niu.IdentityInterface(fields=["subjects_dir"]), name="inputnode"
)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 2087645153..08d0efec7f 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -68,8 +68,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
For example, a subject with only one session with a T1w image
would be processed by the following command::
- $ /opt/FastSurfer/run_fastsurfer.sh --fs_license /path/to/freesurfer/license \
- --t1 /sub-/anat/sub-_T1w.nii.gz \
+ $ /opt/FastSurfer/run_fastsurfer.sh --t1 /sub-/anat/sub-_T1w.nii.gz \
--sid sub- --sd /fastsurfer --surfreg
Similar to the Freesurfer workflow second phase, we then
@@ -128,8 +127,6 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
(UCHAR, 256x256x256, 1 mm voxels and standard slice orientation).
These specifications are checked in the ``eval.py`` script and the image
is automatically conformed if it does not comply.
- fs_license
- Path to FreeSurfer license key file.
Optional arguments
==================
@@ -214,18 +211,18 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
ANTs-derived and FastSurfer-derived segmentations of the cortical
gray-matter of Mindboggle [RRID:SCR_002438, @mindboggle].
""".format(
- fastsurfer_version="1.0.1"
+ fastsurfer_version="1.1.0"
)
inputnode = pe.Node(
niu.IdentityInterface(
fields=[
+ "sd",
+ "sid",
"t1w",
"skullstripped_t1",
"corrected_t1",
"ants_segs",
- "subjects_dir",
- "subject_id",
]
),
name="inputnode",
@@ -233,8 +230,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
outputnode = pe.Node(
niu.IdentityInterface(
fields=[
- "subjects_dir",
- "subject_id",
+ "sd",
+ "sid",
"t1w2fsnative_xfm",
"fsnative2t1w_xfm",
"surfaces",
@@ -256,6 +253,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
t1w2fsnative_xfm = pe.Node(
LTAConvert(out_lta=True, invert=True), name="t1w2fsnative_xfm")
+ # inputnode.in_file = inputnode.t1w
gifti_surface_wf = init_gifti_surface_wf(fastsurfer=True)
aseg_to_native_wf = init_segs_to_native_wf(fastsurfer=True)
aparc_to_native_wf = init_segs_to_native_wf(fastsurfer=True, segmentation="aparc_aseg")
@@ -266,9 +264,11 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
elif os.environ['FS_LICENSE']:
fs_license_file = os.environ['FS_LICENSE']
- # temporary fix fs_license value to /fs60/license
+ # recon_conf = pe.Node(
+ # fastsurf.FastSurferSource(), name="recon_conf")
+
fastsurf_recon = pe.Node(
- fastsurf.FastSCommand(threads=omp_nthreads, fs_license=fs_license_file),
+ fastsurf.FastSCommand(),
name="fastsurf_recon",
n_procs=omp_nthreads,
mem_gb=12,
@@ -276,6 +276,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
fastsurf_recon.interface._can_resume = False
fastsurf_recon.interface._always_run = True
+ # fov_check = pe.Node(niu.Function(function=_check_cw256), name="fov_check")
+
skull_strip_extern = pe.Node(FSInjectBrainExtracted(), name="skull_strip_extern")
fsnative2t1w_xfm = pe.Node(
@@ -288,14 +290,17 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# fmt:off
workflow.connect([
# Configuration
- (inputnode, fastsurf_recon, [('subjects_dir', 'sd'),
- ('subject_id', 'sid'),
+ # (inputnode, recon_conf, [('t1w', 't1'),
+ # ('sd', 'sd'),
+ # ('sid', 'sid')]),
+ (inputnode, fastsurf_recon, [('sd', 'sd'),
+ ('sid', 'sid'),
('t1w', 't1')]),
(fastsurf_recon, skull_strip_extern, [('sd', 'subjects_dir'),
('sid', 'subject_id')]),
- (skull_strip_extern, gifti_surface_wf, [
- ('outputnode.subjects_dir', 'inputnode.subjects_dir'),
- ('outputnode.subject_id', 'inputnode.subject_id')]),
+ (fastsurf_recon, gifti_surface_wf, [
+ ('sd', 'inputnode.subjects_dir'),
+ ('sid', 'inputnode.subject_id')]),
(inputnode, skull_strip_extern, [('skullstripped_t1', 'in_brain')]),
# Construct transform from FreeSurfer conformed image to sMRIPrep
# reoriented image
@@ -316,6 +321,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
(aseg_to_native_wf, refine, [('outputnode.out_file', 'in_aseg')]),
# Output
+ (inputnode, outputnode, [('sd', 'sd'),
+ ('sid', 'sid')]),
(gifti_surface_wf, outputnode, [('outputnode.surfaces', 'surfaces')]),
(t1w2fsnative_xfm, outputnode, [('out_lta', 't1w2fsnative_xfm')]),
(fsnative2t1w_xfm, outputnode, [('out_reg_file', 'fsnative2t1w_xfm')]),
From 26647bb11bf18313db51c6266847380d1c1637c6 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 23 Jun 2022 14:06:25 -0500
Subject: [PATCH 135/220] Fix PEP8 compliance
---
smriprep/cli/run.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 1a4ac29da9..02c210e810 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -230,9 +230,9 @@ def get_parser():
help="enable FastSurfer surface preprocessing.",
)
# g_surfs_xor = g_surfs.add_mutually_exclusive_group()
-
+
g_surfs_xor = g_surfs
-
+
g_surfs_xor.add_argument(
"--fs-no-reconall",
action="store_false",
From 0b20fdd24bd4b517dce12a62462cbec456e45e57 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 23 Jun 2022 14:07:22 -0500
Subject: [PATCH 136/220] Fix PEP8 compliance
---
smriprep/interfaces/fastsurfer.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index d5fcefc209..cd611d9991 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -314,6 +314,7 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
+
class FastSurfSourceOutputSpec(TraitedSpec):
T1 = File(
exists=True,
From 5328f39f77a8d5152900e3bc7853615445f59cec Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 23 Jun 2022 14:08:48 -0500
Subject: [PATCH 137/220] Fix PEP8 compliance
---
smriprep/workflows/base.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/workflows/base.py b/smriprep/workflows/base.py
index 7ca9918cd7..0b1bcead4a 100644
--- a/smriprep/workflows/base.py
+++ b/smriprep/workflows/base.py
@@ -378,7 +378,7 @@ def init_single_subject_wf(
)
if fastsurfer:
- freesurfer = False
+ freesurfer = False
inputnode = pe.Node(
niu.IdentityInterface(fields=["subjects_dir"]), name="inputnode"
From 83a4a8e4dc486d5ee4d07dce46fd68015ad72c2a Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 23 Jun 2022 14:09:27 -0500
Subject: [PATCH 138/220] Fix PEP8 compliance
---
smriprep/workflows/surfaces.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 08d0efec7f..8c1365aeb5 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -68,7 +68,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
For example, a subject with only one session with a T1w image
would be processed by the following command::
- $ /opt/FastSurfer/run_fastsurfer.sh --t1 /sub-/anat/sub-_T1w.nii.gz \
+ $ /opt/FastSurfer/run_fastsurfer.sh \
+ --t1 /sub-/anat/sub-_T1w.nii.gz \
--sid sub- --sd /fastsurfer --surfreg
Similar to the Freesurfer workflow second phase, we then
@@ -322,7 +323,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# Output
(inputnode, outputnode, [('sd', 'sd'),
- ('sid', 'sid')]),
+ ('sid', 'sid')]),
(gifti_surface_wf, outputnode, [('outputnode.surfaces', 'surfaces')]),
(t1w2fsnative_xfm, outputnode, [('out_lta', 't1w2fsnative_xfm')]),
(fsnative2t1w_xfm, outputnode, [('out_reg_file', 'fsnative2t1w_xfm')]),
From c0935153c54ffa80f4ddfadabac010a6d7658abf Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 11:48:10 -0500
Subject: [PATCH 139/220] Add FastSurfer
---
Dockerfile | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 55dbf93585..ae684fc952 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -29,7 +29,7 @@ FROM ubuntu:focal-20210416
# Prepare environment
ENV DEBIAN_FRONTEND="noninteractive"
ENV LANG=C.UTF-8
-ARG PYTHON_VERSION=3.6
+ARG PYTHON_VERSION=3.8
ARG CONDA_FILE=Miniconda3-py37_4.10.3-Linux-x86_64.sh
ENV DEBIAN_FRONTEND=noninteractive
@@ -55,7 +55,7 @@ RUN apt-get update && \
# git clone dev branch of FastSurfer
RUN cd /opt && mkdir /fastsurfer \
- && git clone -b dev https://github.com/Deep-MI/FastSurfer.git \
+ && git clone -b v1.1.0 https://github.com/Deep-MI/FastSurfer.git \
&& cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
# Install conda
@@ -267,8 +267,8 @@ WORKDIR $ANTSPATH
RUN curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \
| tar -xzC $ANTSPATH --strip-components 1
-# nipreps/miniconda:py39_0525.0
-COPY --from=nipreps/miniconda@sha256:40fffd37963502dcd8549773559fc21182f52460e59e0ad6398a84faf6055641 /opt/conda /opt/conda
+# nipreps/miniconda:py38_1.4.1
+COPY --from=nipreps/miniconda@sha256:ebbff214e6c9dc50ccc6fdbe679df1ffcbceaa45b47a75d6e34e8a064ef178da /opt/conda /opt/conda
RUN ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
@@ -310,7 +310,7 @@ COPY . /src/smriprep
ARG VERSION
# Force static versioning within container
RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
- echo "include smriprep/VERSION" >> /src/smriprep/MANIFEST.in && \
+ echo "include smriprep/${VERSION}" >> /src/smriprep/MANIFEST.in && \
/opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]"
RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
From e290f8944460f04d6156b04d996d670c1dbecce9 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 11:49:44 -0500
Subject: [PATCH 140/220] Update for compatibility with FastSurfer
---
docker/files/freesurfer7.2-exclude.txt | 327 +------------------------
1 file changed, 1 insertion(+), 326 deletions(-)
diff --git a/docker/files/freesurfer7.2-exclude.txt b/docker/files/freesurfer7.2-exclude.txt
index f1dd98f980..c46bc7f5c1 100644
--- a/docker/files/freesurfer7.2-exclude.txt
+++ b/docker/files/freesurfer7.2-exclude.txt
@@ -61,7 +61,6 @@ freesurfer/average/SVIP_Young_Patient_N12_as_orig.4dfp.ifh
freesurfer/average/SVIP_Young_Patient_N12_as_orig.4dfp.img
freesurfer/average/SVIP_Young_Patient_N12_as_orig.4dfp.img.rec
freesurfer/average/aseg+spmhead+vermis+pons.ixi.gca
-freesurfer/average/colortable_desikan_killiany.txt
freesurfer/average/face.gca
freesurfer/average/label_scales.dat
freesurfer/average/lh.DKTaparc.atlas.acfb40.noaparc.i12.2020-05-13.gcs
@@ -69,7 +68,6 @@ freesurfer/average/lh.DKTatlas100.gcs
freesurfer/average/lh_trans_toSulc.gcs
freesurfer/average/ThalamicNuclei
freesurfer/average/lh.atlas2005_simple.gcs
-freesurfer/average/surf
freesurfer/average/mni152.mni305.cor.subfov1.dat
freesurfer/average/mni152.mni305.cor.subfov2.dat
freesurfer/average/mni152.register.dat
@@ -114,8 +112,6 @@ freesurfer/bin/dcmdjpeg.fs
freesurfer/bin/dcmdrle.fs
freesurfer/bin/dcmsplit
freesurfer/bin/dcmunpack
-freesurfer/bin/deface_subject
-freesurfer/bin/defect-seg
freesurfer/bin/dicom-rename
freesurfer/bin/diffusionUtils
freesurfer/bin/dmri_AnatomiCuts
@@ -185,9 +181,8 @@ freesurfer/bin/fsl_rigid_register
freesurfer/bin/fsl_sub_mgh
freesurfer/bin/fslmaths.fsl
freesurfer/bin/fslorient.fsl
-freesurfer/bin/fslregister
-freesurfer/bin/fslswapdim.fsl
freesurfer/bin/fspalm
+freesurfer/bin/fsr-checkxopts
freesurfer/bin/fsr-coreg
freesurfer/bin/fsr-import
freesurfer/bin/fsvglrun
@@ -226,7 +221,6 @@ freesurfer/bin/inflate_subject_new-rh
freesurfer/bin/inflate_subject_sc
freesurfer/bin/irepifitvol
freesurfer/bin/irepifitvol.glnx64
-freesurfer/bin/is-surface
freesurfer/bin/isanalyze
freesurfer/bin/isnifti
freesurfer/bin/isolate_labels.csh
@@ -270,10 +264,6 @@ freesurfer/bin/make_hemi_mask
freesurfer/bin/make_symmetric
freesurfer/bin/make_upright
freesurfer/bin/makevol
-freesurfer/bin/map_all_labels
-freesurfer/bin/map_all_labels-lh
-freesurfer/bin/map_central_sulcus
-freesurfer/bin/map_to_base
freesurfer/bin/meanval
freesurfer/bin/merge_stats_tables
freesurfer/bin/mergeseg
@@ -284,7 +274,6 @@ freesurfer/bin/mkmnc_index.tcl
freesurfer/bin/mksubjdirs
freesurfer/bin/mksurfatlas
freesurfer/bin/mkxsubjreg
-freesurfer/bin/mni152reg
freesurfer/bin/morph_only_subject
freesurfer/bin/morph_only_subject-lh
freesurfer/bin/morph_only_subject-rh
@@ -296,292 +285,10 @@ freesurfer/bin/morph_subject-rh
freesurfer/bin/morph_subject_on_seychelles
freesurfer/bin/morph_tables-lh
freesurfer/bin/morph_tables-rh
-freesurfer/bin/mri-func2sph
-freesurfer/bin/mri-funcvits
-freesurfer/bin/mri-sph2surf
-freesurfer/bin/mri_align_long.csh
-freesurfer/bin/mri_aparc2wmseg
-freesurfer/bin/mri_apply_autoencoder
-freesurfer/bin/mri_apply_bias
-freesurfer/bin/mri_apply_inu_correction
-freesurfer/bin/mri_aseg_edit_reclassify
-freesurfer/bin/mri_aseg_edit_train
-freesurfer/bin/mri_auto_fill
-freesurfer/bin/mri_average
-freesurfer/bin/mri_bc_sc_bias_correct
-freesurfer/bin/mri_brain_volume
-freesurfer/bin/mri_build_priors
-freesurfer/bin/mri_ca_tissue_parms
-freesurfer/bin/mri_ca_train
-freesurfer/bin/mri_cal_renormalize_gca
-freesurfer/bin/mri_cht2p
-freesurfer/bin/mri_classify
-freesurfer/bin/mri_cnr
-freesurfer/bin/mri_compute_bias
-freesurfer/bin/mri_compute_change_map
-freesurfer/bin/mri_compute_distances
-freesurfer/bin/mri_compute_layer_fractions
-freesurfer/bin/mri_compute_structure_transforms
-freesurfer/bin/mri_compute_volume_fractions
-freesurfer/bin/mri_compute_volume_intensities
-freesurfer/bin/mri_concatenate_gcam
-freesurfer/bin/mri_convert_mdh
-freesurfer/bin/mri_copy_params
-freesurfer/bin/mri_copy_values
-freesurfer/bin/mri_cor2label
-freesurfer/bin/mri_correct_segmentations
-freesurfer/bin/mri_create_t2combined
-freesurfer/bin/mri_create_tests
-freesurfer/bin/mri_cvs_check
-freesurfer/bin/mri_cvs_data_copy
-freesurfer/bin/mri_cvs_register
-freesurfer/bin/mri_cvs_requiredfiles.txt
-freesurfer/bin/mri_dct_align
-freesurfer/bin/mri_dct_align_binary
-freesurfer/bin/mri_dist_surf_label
-freesurfer/bin/mri_distance_transform
-freesurfer/bin/mri_divide_segmentation
-freesurfer/bin/mri_edit_segmentation
-freesurfer/bin/mri_edit_segmentation_with_surfaces
-freesurfer/bin/mri_elastic_energy
-freesurfer/bin/mri_estimate_tissue_parms
-freesurfer/bin/mri_evaluate_morph
-freesurfer/bin/mri_extract
-freesurfer/bin/mri_extract_conditions
-freesurfer/bin/mri_extract_fcd_features
-freesurfer/bin/mri_extract_label
-freesurfer/bin/mri_extract_largest_CC
-freesurfer/bin/mri_fcili
-freesurfer/bin/mri_fdr
-freesurfer/bin/mri_fieldsign
-freesurfer/bin/mri_fit_bias
-freesurfer/bin/mri_fslmat_to_lta
-freesurfer/bin/mri_fuse_intensity_images
-freesurfer/bin/mri_gca_ambiguous
-freesurfer/bin/mri_gcab_train
-freesurfer/bin/mri_gdfglm
-freesurfer/bin/mri_glmfit
-freesurfer/bin/mri_glmfit-sim
-freesurfer/bin/mri_gradient_info
-freesurfer/bin/mri_gtmpvc
-freesurfer/bin/mri_gtmseg
-freesurfer/bin/mri_hausdorff_dist
-freesurfer/bin/mri_head
-freesurfer/bin/mri_hires_register
-freesurfer/bin/mri_histo_eq
-freesurfer/bin/mri_histo_normalize
-freesurfer/bin/mri_ibmc
-freesurfer/bin/mri_interpolate
-freesurfer/bin/mri_jacobian
-freesurfer/bin/mri_joint_density
-freesurfer/bin/mri_label_accuracy
-freesurfer/bin/mri_label_histo
-freesurfer/bin/mri_label_vals
-freesurfer/bin/mri_label_volume
-freesurfer/bin/mri_linear_align
-freesurfer/bin/mri_linear_align_binary
-freesurfer/bin/mri_linear_register
-freesurfer/bin/mri_long_normalize
-freesurfer/bin/mri_make_bem_surfaces
-freesurfer/bin/mri_make_density_map
-freesurfer/bin/mri_make_labels
-freesurfer/bin/mri_make_register
-freesurfer/bin/mri_make_template
-freesurfer/bin/mri_map_cpdat
-freesurfer/bin/mri_maps2csd
-freesurfer/bin/mri_mark_temporal_lobe
-freesurfer/bin/mri_mc
-freesurfer/bin/mri_mcsim
-freesurfer/bin/mri_mergelabels
-freesurfer/bin/mri_mi
-freesurfer/bin/mri_modify
-freesurfer/bin/mri_morphology
-freesurfer/bin/mri_mosaic
-freesurfer/bin/mri_motion_correct
-freesurfer/bin/mri_motion_correct2
-freesurfer/bin/mri_ms_EM
-freesurfer/bin/mri_ms_EM_with_atlas
-freesurfer/bin/mri_ms_LDA
-freesurfer/bin/mri_ms_fitparms
-freesurfer/bin/mri_multiscale_segment
-freesurfer/bin/mri_multispectral_segment
-freesurfer/bin/mri_nl_align
-freesurfer/bin/mri_nl_align_binary
-freesurfer/bin/mri_nlfilter
-freesurfer/bin/mri_paint
-freesurfer/bin/mri_parse_sdcmdir
-freesurfer/bin/mri_parselabel
-freesurfer/bin/mri_partial_ribbon
-freesurfer/bin/mri_path2label
-freesurfer/bin/mri_polv
-freesurfer/bin/mri_probe_ima
-freesurfer/bin/mri_probedicom
-freesurfer/bin/mri_reduce
-freesurfer/bin/mri_refine_seg
-freesurfer/bin/mri_register
-freesurfer/bin/mri_reorient_LR.csh
-freesurfer/bin/mri_rf_label
-freesurfer/bin/mri_rf_long_label
-freesurfer/bin/mri_rf_long_train
-freesurfer/bin/mri_rf_train
-freesurfer/bin/mri_ribbon
-freesurfer/bin/mri_rigid_register
-freesurfer/bin/mri_sbbr
-freesurfer/bin/mri_seg_overlap
-freesurfer/bin/mri_segcentroids
-freesurfer/bin/mri_seghead
-freesurfer/bin/mri_segment_hypothalamic_subunits
-freesurfer/bin/mri_segment_tumor
-freesurfer/bin/mri_segment_wm_damage
-freesurfer/bin/mri_simulate_atrophy
-freesurfer/bin/mri_strip_nonwhite
-freesurfer/bin/mri_strip_subject_info
-freesurfer/bin/mri_surfacemask
-freesurfer/bin/mri_synth_strip
-freesurfer/bin/mri_synthesize
-freesurfer/bin/mri_threshold
-freesurfer/bin/mri_topologycorrection
-freesurfer/bin/mri_train
-freesurfer/bin/mri_train_autoencoder
-freesurfer/bin/mri_transform
-freesurfer/bin/mri_transform_to_COR
-freesurfer/bin/mri_twoclass
-freesurfer/bin/mri_update_gca
-freesurfer/bin/mri_validate_skull_stripped
-freesurfer/bin/mri_vessel_segment
-freesurfer/bin/mri_vol2label
-freesurfer/bin/mri_vol2roi
-freesurfer/bin/mri_volcluster
-freesurfer/bin/mri_volsynth
-freesurfer/bin/mri_warp_convert
-freesurfer/bin/mri_wbc
-freesurfer/bin/mri_wmfilter
-freesurfer/bin/mri_xcorr
-freesurfer/bin/mri_xvolavg
-freesurfer/bin/mri_z2p
-freesurfer/bin/mris2rgb
-freesurfer/bin/mris_AA_shrinkwrap
-freesurfer/bin/mris_BA_segment
-freesurfer/bin/mris_add_template
-freesurfer/bin/mris_annot_diff
-freesurfer/bin/mris_annot_to_segmentation
-freesurfer/bin/mris_aseg_distance
-freesurfer/bin/mris_average_curvature
-freesurfer/bin/mris_average_parcellation
-freesurfer/bin/mris_ca_deform
-freesurfer/bin/mris_ca_train
-freesurfer/bin/mris_classify_thickness
-freesurfer/bin/mris_compute_acorr
-freesurfer/bin/mris_compute_layer_intensities
-freesurfer/bin/mris_compute_lgi
-freesurfer/bin/mris_compute_optimal_kernel
-freesurfer/bin/mris_compute_overlap
-freesurfer/bin/mris_compute_parc_overlap
-freesurfer/bin/mris_compute_volume_fractions
-freesurfer/bin/mris_congeal
-freesurfer/bin/mris_copy_header
-freesurfer/bin/mris_curvature2image
-freesurfer/bin/mris_deform
-freesurfer/bin/mris_density
-freesurfer/bin/mris_distance_map
-freesurfer/bin/mris_distance_to_label
-freesurfer/bin/mris_distance_transform
-freesurfer/bin/mris_entropy
-freesurfer/bin/mris_errors
-freesurfer/bin/mris_extract_patches
-freesurfer/bin/mris_extract_values
-freesurfer/bin/mris_exvivo_surfaces
-freesurfer/bin/mris_fbirn_annot
-freesurfer/bin/mris_fill
-freesurfer/bin/mris_find_flat_regions
-freesurfer/bin/mris_flatten
-freesurfer/bin/mris_fwhm
-freesurfer/bin/mris_gradient
-freesurfer/bin/mris_hausdorff_dist
-freesurfer/bin/mris_image2vtk
-freesurfer/bin/mris_info
-freesurfer/bin/mris_init_global_tractography
-freesurfer/bin/mris_intensity_profile
-freesurfer/bin/mris_interpolate_warp
-freesurfer/bin/mris_label_area
-freesurfer/bin/mris_label_calc
-freesurfer/bin/mris_label_mode
-freesurfer/bin/mris_longitudinal_surfaces
-freesurfer/bin/mris_make_average_surface
-freesurfer/bin/mris_make_face_parcellation
-freesurfer/bin/mris_make_map_surfaces
-freesurfer/bin/mris_make_surfaces
-freesurfer/bin/mris_make_template
-freesurfer/bin/mris_map_cuts
-freesurfer/bin/mris_mef_surfaces
-freesurfer/bin/mris_merge_parcellations
-freesurfer/bin/mris_mesh_subdivide
-freesurfer/bin/mris_morph_stats
-freesurfer/bin/mris_ms_refine
-freesurfer/bin/mris_ms_surface_CNR
-freesurfer/bin/mris_multimodal
-freesurfer/bin/mris_multimodal_surface_placement
-freesurfer/bin/mris_multiscale_stats
-freesurfer/bin/mris_niters2fwhm
-freesurfer/bin/mris_nudge
-freesurfer/bin/mris_parcellate_connectivity
-freesurfer/bin/mris_pmake
-freesurfer/bin/mris_preproc
-freesurfer/bin/mris_profileClustering
-freesurfer/bin/mris_refine_surfaces
-freesurfer/bin/mris_register_label_map
-freesurfer/bin/mris_register_to_label
-freesurfer/bin/mris_register_to_volume
-freesurfer/bin/mris_remove_negative_vertices
-freesurfer/bin/mris_remove_variance
-freesurfer/bin/mris_resample
-freesurfer/bin/mris_rescale
-freesurfer/bin/mris_reverse
-freesurfer/bin/mris_rf_label
-freesurfer/bin/mris_rf_train
-freesurfer/bin/mris_rotate
-freesurfer/bin/mris_sample_label
-freesurfer/bin/mris_sample_parc
-freesurfer/bin/mris_seg2annot
-freesurfer/bin/mris_segment
-freesurfer/bin/mris_segment_vals
-freesurfer/bin/mris_segmentation_stats
-freesurfer/bin/mris_shrinkwrap
-freesurfer/bin/mris_simulate_atrophy
-freesurfer/bin/mris_smooth_intracortical
-freesurfer/bin/mris_surf2vtk
-freesurfer/bin/mris_surface_change
-freesurfer/bin/mris_surface_to_vol_distances
-freesurfer/bin/mris_svm_classify
-freesurfer/bin/mris_svm_train
-freesurfer/bin/mris_talairach
-freesurfer/bin/mris_thickness_comparison
-freesurfer/bin/mris_transform
-freesurfer/bin/mris_translate_annotation
-freesurfer/bin/mris_transmantle_dysplasia_paths
-freesurfer/bin/mris_twoclass
-freesurfer/bin/mris_volmask_novtk
-freesurfer/bin/mris_volmask_vtk
-freesurfer/bin/mris_volsmooth
-freesurfer/bin/mris_volume
-freesurfer/bin/mris_w_to_curv
-freesurfer/bin/mris_warp
-freesurfer/bin/mris_wm_volume
-freesurfer/bin/mrisp_write
-freesurfer/bin/ms_refine_subject
-freesurfer/bin/nmovie_qt
-freesurfer/bin/oct_register_mosaic
-freesurfer/bin/oct_rf_train
-freesurfer/bin/oct_train
-freesurfer/bin/optseq2
-freesurfer/bin/orientLAS
-freesurfer/bin/parc_atlas_jackknife_test
-freesurfer/bin/plot_structure_stats.tcl
freesurfer/bin/polyorder
freesurfer/bin/predict_v1.sh
freesurfer/bin/print_unique_labels.csh
freesurfer/bin/progressbar.tcl
-freesurfer/bin/qatools.py
freesurfer/bin/qdec_glmfit
freesurfer/bin/qt.conf
freesurfer/bin/quantifyBrainstemStructures.sh
@@ -645,26 +352,10 @@ freesurfer/bin/segment_subject_talmgh
freesurfer/bin/segpons
freesurfer/bin/setlabelstat
freesurfer/bin/sfa2fieldsign
-freesurfer/bin/show_tal
-freesurfer/bin/skip_long_make_checks
-freesurfer/bin/slicedelay
-freesurfer/bin/slicetimer.fsl
-freesurfer/bin/sphere_subject
-freesurfer/bin/sphere_subject-lh
-freesurfer/bin/sphere_subject-rh
-freesurfer/bin/spherical_st
-freesurfer/bin/spm_t_to_b
-freesurfer/bin/spmmat2register
-freesurfer/bin/spmregister
-freesurfer/bin/sratio
-freesurfer/bin/stat_normalize
freesurfer/bin/stattablediff
freesurfer/bin/stem2fname
freesurfer/bin/stim_polar
freesurfer/bin/streamlineFilter
-freesurfer/bin/surf2vol
-freesurfer/bin/surfreg
-freesurfer/bin/swi_preprocess
freesurfer/bin/swi_process
freesurfer/bin/t4img_4dfp
freesurfer/bin/t4imgs_4dfp
@@ -672,8 +363,6 @@ freesurfer/bin/tal_QC_AZS
freesurfer/bin/tal_compare
freesurfer/bin/talairach2
freesurfer/bin/talairach_mgh
-freesurfer/bin/talsegprob
-freesurfer/bin/template
freesurfer/bin/testOrientationPlanesFromParcellation
freesurfer/bin/test_recon-all.csh
freesurfer/bin/test_tutorials.sh
@@ -705,8 +394,6 @@ freesurfer/bin/vol2symsurf
freesurfer/bin/vsm-smooth
freesurfer/bin/wfilemask
freesurfer/bin/wm-anat-snr
-freesurfer/bin/wmedits2surf
-freesurfer/bin/wmsaseg
freesurfer/bin/xcerebralseg
freesurfer/bin/xcorr
freesurfer/bin/xfmrot
@@ -720,18 +407,6 @@ freesurfer/bin/SegmentSubfieldsT1Longitudinal
freesurfer/bin/SegmentThalamicNuclei
freesurfer/bin/Spline3_test
freesurfer/bin/anatomiCutsUtils
-freesurfer/bin/annot2std
-freesurfer/bin/aparc2feat
-freesurfer/bin/aparc_stats_aseg
-freesurfer/bin/aparcstats2table
-freesurfer/bin/aparcstatsdiff
-freesurfer/bin/apas2aseg
-freesurfer/bin/applyMorph
-freesurfer/bin/aseg2feat
-freesurfer/bin/asegstats2table
-freesurfer/bin/asegstatsdiff
-freesurfer/bin/bblabel
-freesurfer/bin/bbmask
freesurfer/bin/bedpostx_mgh
freesurfer/bin/bet.fsl
freesurfer/bin/beta2sxa
From 5e5f56d495664480a0546f7906896b4b15a9d82c Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 11:50:53 -0500
Subject: [PATCH 141/220] Update for FastSurfer compatibility
---
smriprep/workflows/base.py | 2 +-
smriprep/workflows/surfaces.py | 11 +++++------
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/smriprep/workflows/base.py b/smriprep/workflows/base.py
index 0b1bcead4a..7ca9918cd7 100644
--- a/smriprep/workflows/base.py
+++ b/smriprep/workflows/base.py
@@ -378,7 +378,7 @@ def init_single_subject_wf(
)
if fastsurfer:
- freesurfer = False
+ freesurfer = False
inputnode = pe.Node(
niu.IdentityInterface(fields=["subjects_dir"]), name="inputnode"
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 8c1365aeb5..277b7aa6a8 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -68,8 +68,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
For example, a subject with only one session with a T1w image
would be processed by the following command::
- $ /opt/FastSurfer/run_fastsurfer.sh \
- --t1 /sub-/anat/sub-_T1w.nii.gz \
+ $ /opt/FastSurfer/run_fastsurfer.sh --t1 /sub-/anat/sub-_T1w.nii.gz \
--sid sub- --sd /fastsurfer --surfreg
Similar to the Freesurfer workflow second phase, we then
@@ -297,9 +296,9 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
(inputnode, fastsurf_recon, [('sd', 'sd'),
('sid', 'sid'),
('t1w', 't1')]),
- (fastsurf_recon, skull_strip_extern, [('sd', 'subjects_dir'),
- ('sid', 'subject_id')]),
- (fastsurf_recon, gifti_surface_wf, [
+ (inputnode, skull_strip_extern, [('sd', 'subjects_dir'),
+ ('sid', 'subject_id')]),
+ (inputnode, gifti_surface_wf, [
('sd', 'inputnode.subjects_dir'),
('sid', 'inputnode.subject_id')]),
(inputnode, skull_strip_extern, [('skullstripped_t1', 'in_brain')]),
@@ -323,7 +322,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# Output
(inputnode, outputnode, [('sd', 'sd'),
- ('sid', 'sid')]),
+ ('sid', 'sid')]),
(gifti_surface_wf, outputnode, [('outputnode.surfaces', 'surfaces')]),
(t1w2fsnative_xfm, outputnode, [('out_lta', 't1w2fsnative_xfm')]),
(fsnative2t1w_xfm, outputnode, [('out_reg_file', 'fsnative2t1w_xfm')]),
From 15cbfb9aef355dae17bb5cf2ed5a6948d6bb42ac Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 11:51:43 -0500
Subject: [PATCH 142/220] Add compatibility with FastSurfer
---
smriprep/interfaces/fastsurfer.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index cd611d9991..d5fcefc209 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -314,7 +314,6 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
-
class FastSurfSourceOutputSpec(TraitedSpec):
T1 = File(
exists=True,
From 25c2305e953832a2bc0e5d0f6f4be949b6eff784 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 11:52:14 -0500
Subject: [PATCH 143/220] Add files via upload
---
smriprep/cli/run.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 02c210e810..1a4ac29da9 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -230,9 +230,9 @@ def get_parser():
help="enable FastSurfer surface preprocessing.",
)
# g_surfs_xor = g_surfs.add_mutually_exclusive_group()
-
+
g_surfs_xor = g_surfs
-
+
g_surfs_xor.add_argument(
"--fs-no-reconall",
action="store_false",
From 239b01a2e15ed45277fea189eff21e636b60be4b Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 11:53:48 -0500
Subject: [PATCH 144/220] Update run.py
---
smriprep/cli/run.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 1a4ac29da9..02c210e810 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -230,9 +230,9 @@ def get_parser():
help="enable FastSurfer surface preprocessing.",
)
# g_surfs_xor = g_surfs.add_mutually_exclusive_group()
-
+
g_surfs_xor = g_surfs
-
+
g_surfs_xor.add_argument(
"--fs-no-reconall",
action="store_false",
From fcd66b42663bb627688cabbad0415ce341ba6596 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 11:54:21 -0500
Subject: [PATCH 145/220] PEP8 compliance
---
smriprep/interfaces/fastsurfer.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index d5fcefc209..cd611d9991 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -314,6 +314,7 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
+
class FastSurfSourceOutputSpec(TraitedSpec):
T1 = File(
exists=True,
From d6c16ce8aaea73969b4877330c058f2b5bf9d26d Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 11:54:55 -0500
Subject: [PATCH 146/220] PEP8 compliance
---
smriprep/workflows/base.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/workflows/base.py b/smriprep/workflows/base.py
index 7ca9918cd7..0b1bcead4a 100644
--- a/smriprep/workflows/base.py
+++ b/smriprep/workflows/base.py
@@ -378,7 +378,7 @@ def init_single_subject_wf(
)
if fastsurfer:
- freesurfer = False
+ freesurfer = False
inputnode = pe.Node(
niu.IdentityInterface(fields=["subjects_dir"]), name="inputnode"
From 84938f4ff02ea30bfd6fb984c14676cb760198c9 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 11:55:42 -0500
Subject: [PATCH 147/220] PEP8 compliance
---
smriprep/workflows/surfaces.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 277b7aa6a8..861e622075 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -68,7 +68,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
For example, a subject with only one session with a T1w image
would be processed by the following command::
- $ /opt/FastSurfer/run_fastsurfer.sh --t1 /sub-/anat/sub-_T1w.nii.gz \
+ $ /opt/FastSurfer/run_fastsurfer.sh \
+ --t1 /sub-/anat/sub-_T1w.nii.gz \
--sid sub- --sd /fastsurfer --surfreg
Similar to the Freesurfer workflow second phase, we then
@@ -322,7 +323,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# Output
(inputnode, outputnode, [('sd', 'sd'),
- ('sid', 'sid')]),
+ ('sid', 'sid')]),
(gifti_surface_wf, outputnode, [('outputnode.surfaces', 'surfaces')]),
(t1w2fsnative_xfm, outputnode, [('out_lta', 't1w2fsnative_xfm')]),
(fsnative2t1w_xfm, outputnode, [('out_reg_file', 'fsnative2t1w_xfm')]),
From 051580eda1b716384885b88c15c356d36d19ae40 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 16:14:51 -0500
Subject: [PATCH 148/220] Fix Flake8 compliance
---
smriprep/workflows/surfaces.py | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 861e622075..a82d2296ce 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -259,11 +259,12 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
aseg_to_native_wf = init_segs_to_native_wf(fastsurfer=True)
aparc_to_native_wf = init_segs_to_native_wf(fastsurfer=True, segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
- fs_license_file = "/opt/freesurfer/license.txt"
- if os.path.exists("/tmp/freesurfer/license.txt"):
- fs_license_file = "/tmp/freesurfer/license.txt"
- elif os.environ['FS_LICENSE']:
- fs_license_file = os.environ['FS_LICENSE']
+ # fs_license_file variable not used, uncomment if this changes!
+ # fs_license_file = "/opt/freesurfer/license.txt"
+ # if os.path.exists("/tmp/freesurfer/license.txt"):
+ # fs_license_file = "/tmp/freesurfer/license.txt"
+ # elif os.environ['FS_LICENSE']:
+ # fs_license_file = os.environ['FS_LICENSE']
# recon_conf = pe.Node(
# fastsurf.FastSurferSource(), name="recon_conf")
From a95b94f1851c35cbc67668c7e2f034160245e4d8 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 16:18:15 -0500
Subject: [PATCH 149/220] Remove print command artifact from dev testing
---
smriprep/cli/run.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 02c210e810..34a3f61f86 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -416,8 +416,6 @@ def _warn_redirect(message, category, filename, lineno, file=None, line=None):
from templateflow import api
from niworkflows.utils.misc import _copy_any
- # developer note - remove
- print(string(fastsurfer))
dseg_tsv = str(api.get("fsaverage", suffix="dseg", extension=[".tsv"]))
_copy_any(
dseg_tsv, str(Path(output_dir) / "smriprep" / "desc-aseg_dseg.tsv")
From ab0fe2f19aa538e726e17e77291d9790c60bd912 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 5 Jul 2022 16:19:20 -0500
Subject: [PATCH 150/220] Comment out unused import
---
smriprep/interfaces/reports.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index 2bf90e8816..7349df6d2a 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -38,7 +38,7 @@
from nipype.interfaces import freesurfer as fs
from nipype.interfaces.io import FSSourceInputSpec as _FSSourceInputSpec
from smriprep.interfaces.fastsurfer import FastSurfSourceInputSpec as _FastSurfSourceInputSpec
-from smriprep.interfaces.fastsurfer import FastSurfSourceOutputSpec as _FastSurfSourceOutputSpec
+# from smriprep.interfaces.fastsurfer import FastSurfSourceOutputSpec as _FastSurfSourceOutputSpec
from smriprep.interfaces import fastsurfer as fastsurf
from smriprep.utils.misc import check_fastsurfer
from nipype.interfaces.mixins import reporting
From fbcd2e490f8965141df15a7babab1c6be80c076c Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 6 Jul 2022 11:26:04 -0500
Subject: [PATCH 151/220] Update FastSurfer, Freesurfer versions
---
docs/installation.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/installation.rst b/docs/installation.rst
index 792763546d..b701726dbb 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -148,6 +148,6 @@ the ``smriprep`` package:
- ANTs_ (version 2.2.0 - NeuroDocker build)
- AFNI_ (version Debian-16.2.07)
- `C3D `_ (version 1.0.0)
-- FreeSurfer_ (version 6.0.1)
+- FreeSurfer_ (version 7.2.0)
- `bids-validator `_ (version 1.1.0)
-- FastSurfer_ (version 1.0.1)
+- FastSurfer_ (version 1.1.0)
From a32ce8b945859f49d82fc471edabecdbe5338eab Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 6 Jul 2022 11:27:02 -0500
Subject: [PATCH 152/220] Delete unused Dockerfile
---
Dockerfile_dev | 370 -------------------------------------------------
1 file changed, 370 deletions(-)
delete mode 100644 Dockerfile_dev
diff --git a/Dockerfile_dev b/Dockerfile_dev
deleted file mode 100644
index fc3ba57ebf..0000000000
--- a/Dockerfile_dev
+++ /dev/null
@@ -1,370 +0,0 @@
-# sMRIPrep Docker Container Image distribution
-#
-# MIT License
-#
-# Copyright (c) 2021 The NiPreps Developers
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-FROM ubuntu:20.04 AS build
-
-ENV LANG=C.UTF-8
-ARG PYTHON_VERSION=3.8
-ARG CONDA_FILE=Miniconda3-py38_4.11.0-Linux-x86_64.sh
-ENV DEBIAN_FRONTEND=noninteractive
-
-# Install packages needed for build
-RUN apt-get update && apt-get install -y --no-install-recommends \
- wget \
- git \
- ca-certificates \
- curl \
- upx \
- git \
- file && \
- apt clean && \
- rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
-
-# git clone dev branch of FastSurfer
-RUN cd /opt && mkdir /fastsurfer \
- && git clone -b dev https://github.com/Deep-MI/FastSurfer.git \
- && cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml \
- && cp /opt/FastSurfer/Docker/install_fs_pruned.sh /fastsurfer/install_fs_pruned.sh
-
-# Install conda
-RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/miniconda/$CONDA_FILE && \
- chmod +x ~/miniconda.sh && \
- ~/miniconda.sh -b -p /opt/conda && \
- rm ~/miniconda.sh
-
-ENV PATH /opt/conda/bin:$PATH
-
-# Install our dependencies
-RUN conda env create -f /fastsurfer/fastsurfer_env_gpu.yml
-
-# Install conda-pack:
-RUN conda install -c conda-forge conda-pack
-
-# Use conda-pack to create a standalone enviornment in /venv:
-RUN conda-pack -n fastsurfer_gpu -o /tmp/env.tar && \
- mkdir /venv && cd /venv && tar xf /tmp/env.tar && \
- rm /tmp/env.tar
-
-# Now that venv in a new location, fix up paths:
-RUN /venv/bin/conda-unpack
-ENV PATH /venv/bin:$PATH
-
-# setup shell for install command below
-RUN echo "source /venv/bin/activate" >> ~/.bashrc
-SHELL ["/bin/bash", "--login", "-c"]
-
-# install freesurfer from sMRIPrep version
-RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/7.2.0/freesurfer-linux-ubuntu18_amd64-7.2.0.tar.gz \
- | tar zxv --no-same-owner -C /opt \
- --exclude='freesurfer/diffusion' \
- --exclude='freesurfer/docs' \
- --exclude='freesurfer/fsfast' \
- --exclude='freesurfer/lib/cuda' \
- --exclude='freesurfer/lib/qt' \
- --exclude='freesurfer/matlab' \
- --exclude='freesurfer/mni/share/man' \
- --exclude='freesurfer/subjects/fsaverage_sym' \
- --exclude='freesurfer/subjects/fsaverage3' \
- --exclude='freesurfer/subjects/fsaverage4' \
- --exclude='freesurfer/subjects/cvs_avg35' \
- --exclude='freesurfer/subjects/cvs_avg35_inMNI152' \
- --exclude='freesurfer/subjects/bert' \
- --exclude='freesurfer/subjects/lh.EC_average' \
- --exclude='freesurfer/subjects/rh.EC_average' \
- --exclude='freesurfer/subjects/sample-*.mgz' \
- --exclude='freesurfer/subjects/V1_average' \
- --exclude='freesurfer/trctrain'
-
-# Install required packages for freesurfer to run
-RUN apt-get update && apt-get install -y --no-install-recommends \
- tcsh \
- time \
- bc \
- gawk \
- libgomp1 && \
- apt clean && \
- rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
-
-# Add FreeSurfer Environment variables
-ENV OS=Linux \
- FS_OVERRIDE=0 \
- FIX_VERTEX_AREA= \
- SUBJECTS_DIR=/opt/freesurfer/subjects \
- FSF_OUTPUT_FORMAT=nii.gz \
- FREESURFER_HOME=/opt/freesurfer \
- PYTHONUNBUFFERED=0 \
- PATH=/venv/bin:/opt/freesurfer/bin:$PATH
-
-# make sure we use bash and activate conda env
-# (in case someone starts this interactively)
-RUN echo "source /venv/bin/activate" >> ~/.bashrc
-SHELL ["/bin/bash", "--login", "-c"]
-
-# Copy fastsurfer from git folder
-RUN cp -R /opt/FastSurfer/* /fastsurfer/
-
-# Simulate SetUpFreeSurfer.sh
-ENV FSL_DIR="/opt/fsl-6.0.5.1" \
- OS="Linux" \
- FS_OVERRIDE=0 \
- FIX_VERTEX_AREA="" \
- FSF_OUTPUT_FORMAT="nii.gz" \
- FREESURFER_HOME="/opt/freesurfer"
-ENV SUBJECTS_DIR="$FREESURFER_HOME/subjects" \
- FUNCTIONALS_DIR="$FREESURFER_HOME/sessions" \
- MNI_DIR="$FREESURFER_HOME/mni" \
- LOCAL_DIR="$FREESURFER_HOME/local" \
- MINC_BIN_DIR="$FREESURFER_HOME/mni/bin" \
- MINC_LIB_DIR="$FREESURFER_HOME/mni/lib" \
- MNI_DATAPATH="$FREESURFER_HOME/mni/data"
-ENV PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
- MNI_PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
- PATH="$FREESURFER_HOME/bin:$FSFAST_HOME/bin:$FREESURFER_HOME/tktools:$MINC_BIN_DIR:$PATH"
-
-# FSL 6.0.5.1
-RUN apt-get update -qq \
- && apt-get install -y -q --no-install-recommends \
- bc \
- dc \
- file \
- libfontconfig1 \
- libfreetype6 \
- libgl1-mesa-dev \
- libgl1-mesa-dri \
- libglu1-mesa-dev \
- libgomp1 \
- libice6 \
- libxcursor1 \
- libxft2 \
- libxinerama1 \
- libxrandr2 \
- libxrender1 \
- libxt6 \
- sudo \
- curl \
- wget \
- && apt-get clean \
- && rm -rf /var/lib/apt/lists/* \
- && echo "Downloading FSL ..." \
- && mkdir -p /opt/fsl-6.0.5.1 \
- && curl -fsSL --retry 5 https://fsl.fmrib.ox.ac.uk/fsldownloads/fsl-6.0.5.1-centos7_64.tar.gz \
- | tar -xz -C /opt/fsl-6.0.5.1 --strip-components 1 \
- --exclude "fsl/config" \
- --exclude "fsl/data/atlases" \
- --exclude "fsl/data/first" \
- --exclude "fsl/data/mist" \
- --exclude "fsl/data/possum" \
- --exclude "fsl/data/standard/bianca" \
- --exclude "fsl/data/standard/tissuepriors" \
- --exclude "fsl/doc" \
- --exclude "fsl/etc/default_flobs.flobs" \
- --exclude "fsl/etc/fslconf" \
- --exclude "fsl/etc/js" \
- --exclude "fsl/etc/luts" \
- --exclude "fsl/etc/matlab" \
- --exclude "fsl/extras" \
- --exclude "fsl/include" \
- --exclude "fsl/python" \
- --exclude "fsl/refdoc" \
- --exclude "fsl/src" \
- --exclude "fsl/tcl" \
- --exclude "fsl/bin/FSLeyes" \
- && find /opt/fsl-6.0.5.1/bin -type f -not \( \
- -name "applywarp" -or \
- -name "bet" -or \
- -name "bet2" -or \
- -name "convert_xfm" -or \
- -name "fast" -or \
- -name "flirt" -or \
- -name "fsl_regfilt" -or \
- -name "fslhd" -or \
- -name "fslinfo" -or \
- -name "fslmaths" -or \
- -name "fslmerge" -or \
- -name "fslroi" -or \
- -name "fslsplit" -or \
- -name "fslstats" -or \
- -name "imtest" -or \
- -name "mcflirt" -or \
- -name "melodic" -or \
- -name "prelude" -or \
- -name "remove_ext" -or \
- -name "susan" -or \
- -name "topup" -or \
- -name "zeropad" \) -delete \
- && find /opt/fsl-6.0.5.1/data/standard -type f -not -name "MNI152_T1_2mm_brain.nii.gz" -delete
-ENV FSLDIR="/opt/fsl-6.0.5.1" \
- PATH="/opt/fsl-6.0.5.1/bin:$PATH" \
- FSLOUTPUTTYPE="NIFTI_GZ" \
- FSLMULTIFILEQUIT="TRUE" \
- FSLLOCKDIR="" \
- FSLMACHINELIST="" \
- FSLREMOTECALL="" \
- FSLGECUDAQ="cuda.q" \
- LD_LIBRARY_PATH="/opt/fsl-6.0.5.1/lib:$LD_LIBRARY_PATH"
-
-# Convert3D (neurodocker build)
-RUN echo "Downloading Convert3D ..." \
- && mkdir -p /opt/convert3d-1.0.0 \
- && curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz/download \
- | tar -xz -C /opt/convert3d-1.0.0 --strip-components 1 \
- --exclude "c3d-1.0.0-Linux-x86_64/lib" \
- --exclude "c3d-1.0.0-Linux-x86_64/share" \
- --exclude "c3d-1.0.0-Linux-x86_64/bin/c3d_gui"
-ENV C3DPATH="/opt/convert3d-1.0.0" \
- PATH="/opt/convert3d-1.0.0/bin:$PATH"
-
-# AFNI latest (neurodocker build)
-RUN apt-get update -qq \
- && apt-get install -y -q --no-install-recommends \
- apt-utils \
- ed \
- gsl-bin \
- libglib2.0-0 \
- libglu1-mesa-dev \
- libglw1-mesa \
- libgomp1 \
- libjpeg62 \
- libxm4 \
- netpbm \
- tcsh \
- xfonts-base \
- xvfb \
- && apt-get clean \
- && rm -rf /var/lib/apt/lists/* \
-# && curl -sSL --retry 5 -o /tmp/multiarch.deb http://archive.ubuntu.com/ubuntu/pool/main/g/glibc/multiarch-support_2.27-3ubuntu1.2_amd64.deb \
-# && dpkg -i /tmp/multiarch.deb \
-# && rm /tmp/multiarch.deb \
-# && curl -sSL --retry 5 -o /tmp/libxp6.deb http://mirrors.kernel.org/debian/pool/main/libx/libxp/libxp6_1.0.2-2_amd64.deb \
-# && dpkg -i /tmp/libxp6.deb \
-# && rm /tmp/libxp6.deb \
-# && curl -sSL --retry 5 -o /tmp/libpng.deb http://snapshot.debian.org/archive/debian-security/20160113T213056Z/pool/updates/main/libp/libpng/libpng12-0_1.2.49-1%2Bdeb7u2_amd64.deb \
-# && dpkg -i /tmp/libpng.deb \
-# && rm /tmp/libpng.deb \
-# && apt-get install -f \
-# && apt-get clean \
-# && rm -rf /var/lib/apt/lists/* \
- && gsl2_path="$(find / -name 'libgsl.so.19' || printf '')" \
- && if [ -n "$gsl2_path" ]; then \
- ln -sfv "$gsl2_path" "$(dirname $gsl2_path)/libgsl.so.0"; \
- fi \
- && ldconfig \
- && echo "Downloading AFNI ..." \
- && mkdir -p /opt/afni-latest \
- && curl -fsSL --retry 5 https://afni.nimh.nih.gov/pub/dist/tgz/linux_openmp_64.tgz \
- | tar -xz -C /opt/afni-latest --strip-components 1 \
- --exclude "linux_openmp_64/*.gz" \
- --exclude "linux_openmp_64/funstuff" \
- --exclude "linux_openmp_64/shiny" \
- --exclude "linux_openmp_64/afnipy" \
- --exclude "linux_openmp_64/lib/RetroTS" \
- --exclude "linux_openmp_64/meica.libs" \
- # Keep only what we use
- && find /opt/afni-latest -type f -not \( \
- -name "3dTshift" -or \
- -name "3dUnifize" -or \
- -name "3dAutomask" -or \
- -name "3dvolreg" \) -delete
-
-ENV PATH="/opt/afni-latest:$PATH" \
- AFNI_IMSAVE_WARNINGS="NO" \
- AFNI_PLUGINPATH="/opt/afni-latest"
-
-# Installing ANTs 2.3.3 (NeuroDocker build)
-# Note: the URL says 2.3.4 but it is actually 2.3.3
-ENV ANTSPATH="/opt/ants" \
- PATH="/opt/ants:$PATH"
-WORKDIR $ANTSPATH
-RUN curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \
- | tar -xzC $ANTSPATH --strip-components 1
-
-COPY --from=nipreps/miniconda@sha256:4d0dc0fabb794e9fe22ee468ae5f86c2c8c2b4cd9d7b7fdf0c134d9e13838729 /opt/conda /opt/conda
-
-RUN ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
- echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
- echo "conda activate base" >> ~/.bashrc
-
-# Install FastSurfer dependencies to base
-RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
-
-# Set CPATH for packages relying on compiled libs (e.g. indexed_gzip)
-ENV PATH="/opt/conda/bin:$PATH" \
- CPATH="/opt/conda/include:$CPATH" \
- LD_LIBRARY_PATH="/opt/conda/lib:$LD_LIBRARY_PATH" \
- LANG="C.UTF-8" \
- LC_ALL="C.UTF-8" \
- PYTHONNOUSERSITE=1
-
-# Unless otherwise specified each process should only use one thread - nipype
-# will handle parallelization
-ENV MKL_NUM_THREADS=1 \
- OMP_NUM_THREADS=1
-
-# Create a shared $HOME directory
-RUN useradd -m -s /bin/bash -G users smriprep
-WORKDIR /home/smriprep
-ENV HOME="/home/smriprep" \
- LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH"
-
-RUN echo ". /opt/conda/etc/profile.d/conda.sh" >> $HOME/.bashrc && \
- echo "conda activate base" >> $HOME/.bashrc
-
-# Precaching atlases
-COPY scripts/fetch_templates.py fetch_templates.py
-
-RUN /opt/conda/bin/python fetch_templates.py && \
- rm fetch_templates.py && \
- find $HOME/.cache/templateflow -type d -exec chmod go=u {} + && \
- find $HOME/.cache/templateflow -type f -exec chmod go=u {} +
-
-# Installing sMRIPREP
-COPY . /src/smriprep
-ARG VERSION
-# Force static versioning within container
-RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
- echo "include smriprep/VERSION" >> /src/smriprep/MANIFEST.in && \
- /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]"
-
-RUN find $HOME -type d -exec chmod go=u {} + && \
- find $HOME -type f -exec chmod go=u {} + && \
- rm -rf $HOME/.npm $HOME/.conda $HOME/.empty
-
-ENV IS_DOCKER_8395080871=1
-ENV FASTSURFER_HOME=/fastsurfer
-
-RUN ldconfig
-WORKDIR /tmp
-ENTRYPOINT ["/opt/conda/bin/smriprep"]
-
-ARG BUILD_DATE
-ARG VCS_REF
-ARG VERSION
-LABEL org.label-schema.build-date=$BUILD_DATE \
- org.label-schema.name="sMRIPrep" \
- org.label-schema.description="sMRIPrep - robust structural MRI preprocessing tool" \
- org.label-schema.url="http://smriprep.org" \
- org.label-schema.vcs-ref=$VCS_REF \
- org.label-schema.vcs-url="https://github.com/nipreps/smriprep" \
- org.label-schema.version=$VERSION \
- org.label-schema.schema-version="1.0"
From dfda2351ff8955d995d0072c0eeeeca3e89475de Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 6 Jul 2022 11:42:34 -0500
Subject: [PATCH 153/220] Add explicit in-tree-build argument to pip, debug
conda
Testing this option in anticipation of the default behavior of pip changing. Attempt to fix conda environment not resolving in CircleCI build.
---
Dockerfile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index ae684fc952..fc74b2253d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -30,7 +30,7 @@ FROM ubuntu:focal-20210416
ENV DEBIAN_FRONTEND="noninteractive"
ENV LANG=C.UTF-8
ARG PYTHON_VERSION=3.8
-ARG CONDA_FILE=Miniconda3-py37_4.10.3-Linux-x86_64.sh
+ARG CONDA_FILE=Miniconda3-py38_4.12.0-Linux-x86_64.sh
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
@@ -311,7 +311,7 @@ ARG VERSION
# Force static versioning within container
RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
echo "include smriprep/${VERSION}" >> /src/smriprep/MANIFEST.in && \
- /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]"
+ /opt/conda/bin/python -m pip install --use-feature=in-tree-build --no-cache-dir "/src/smriprep[all]"
RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
From f031a40e63e1ffd7a0aaa0c94f08e90c341ef967 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 8 Jul 2022 13:28:46 -0500
Subject: [PATCH 154/220] Update fastsurfer.py
---
smriprep/interfaces/fastsurfer.py | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index cd611d9991..ff2e4622e3 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -620,9 +620,7 @@ def _get_files(self, path, key, dirval, altkey=None):
globsuffix = ""
if dirval == "mri":
globsuffix = ".mgz"
- if key in ("mni_log"):
- globsuffix = ".mgz"
- elif key in ("mni_log_bak"):
+ if key in ("mni_log_bak"):
globsuffix = ".log.bak"
elif dirval == "stats":
globsuffix = ".stats"
@@ -645,9 +643,7 @@ def _get_files(self, path, key, dirval, altkey=None):
]
def _list_outputs(self):
- subjects_dir = self.inputs.sd
- subject_id = self.inputs.sid
- subject_path = os.path.join(subjects_dir, subject_id)
+ subject_path = os.path.join(self.inputs.sd, self.inputs.sid)
output_traits = self._outputs()
outputs = output_traits.get()
for k in list(outputs.keys()):
From d17aa7bd32d1af6e635ecf5ca796142f63c9ab58 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 8 Jul 2022 13:42:26 -0500
Subject: [PATCH 155/220] Comment out unused import os package
---
smriprep/workflows/surfaces.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index a82d2296ce..8b209b8760 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -50,7 +50,7 @@
)
from niworkflows.interfaces.surf import NormalizeSurf
from nipype import logging
-import os
+# import os
LOGGER = logging.getLogger("nipype.workflow")
From 8e1f998104894a73d61f247cffdd9da6af0fe382 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 1 Aug 2022 10:24:53 -0500
Subject: [PATCH 156/220] Update smriprep/interfaces/fastsurfer.py
Fixes interfaces compatibility with nipype
Co-authored-by: Chris Markiewicz
---
smriprep/interfaces/fastsurfer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index ff2e4622e3..27f1f5e0a0 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -134,7 +134,7 @@ class FastSInputSpec(CommandLineInputSpec):
mandatory=False,
desc="Subject ID"
)
- t1 = File(
+ T1_files = File(
exists=True,
mandatory=False,
argstr="--t1 %s",
From 26409f416b85c136610651bb3975dea8cc0df353 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 1 Aug 2022 10:31:02 -0500
Subject: [PATCH 157/220] Apply suggestions from code review
Uses more of the nipype-wrapped FreeSurfer tools to increase compatibility and simplify code
Co-authored-by: Chris Markiewicz
---
smriprep/interfaces/fastsurfer.py | 80 +++++--------------------------
1 file changed, 11 insertions(+), 69 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 27f1f5e0a0..0fdc55a9ba 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -122,16 +122,16 @@ class FastSInputSpec(CommandLineInputSpec):
"""
- sd = Directory(
+ subjects_dir = Directory(
exists=True,
argstr="--sd %s",
- mandatory=False,
- desc="Subjects directory"
+ hash_files=False,
+ desc="Subjects directory",
+ genfile=True,
)
- sid = traits.String(
- exists=True,
+ subject_id = traits.String(
argstr="--sid %s",
- mandatory=False,
+ mandatory=True,
desc="Subject ID"
)
T1_files = File(
@@ -142,15 +142,13 @@ class FastSInputSpec(CommandLineInputSpec):
)
fs_license = File(
exists=True,
- mandatory=False,
argstr="--fs_license %s",
desc="Path to FreeSurfer license key file."
)
seg = File(
exists=True,
- mandatory=False,
argstr="--seg %s",
- desc="Global path with filename of segmentation"
+ desc="Pre-computed segmentation file"
)
weights_sag = File(
exists=True,
@@ -282,18 +280,6 @@ class FastSInputSpec(CommandLineInputSpec):
)
-class FastSTraitedOutputSpec(TraitedSpec):
- r"""
- Outputs directory within the FastSurfer subjects_dir/subject_id/
- with structure equivalent to Freesurfer
-
- """
- outputs = Directory(
- exists=True,
- desc="FastSurfer CNN + Surface Pipeline equivalent of recon-all outputs"
- )
-
-
class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
sd = Directory(
exists=True,
@@ -606,67 +592,23 @@ class FastSurfSourceOutputSpec(TraitedSpec):
)
-class FastSurferSource(IOBase):
+class FastSurferSource(FreeSurferSource):
"""Generates FastSurfer subject info from their directories.
"""
- input_spec = FastSurfSourceInputSpec
output_spec = FastSurfSourceOutputSpec
- _always_run = True
- _additional_metadata = ["loc", "altkey"]
-
- def _get_files(self, path, key, dirval, altkey=None):
- globsuffix = ""
- if dirval == "mri":
- globsuffix = ".mgz"
- if key in ("mni_log_bak"):
- globsuffix = ".log.bak"
- elif dirval == "stats":
- globsuffix = ".stats"
- globprefix = ""
- if dirval in ("surf", "label", "stats"):
- globprefix = "?h."
- if key in ("aseg_stats", "aseg_presurf_stats", "wmparc_stats"):
- globprefix = ""
- elif key == "ribbon":
- globprefix = "*"
- elif key == "aparc_ctab":
- globprefix = ""
- globsuffix = ""
- elif key in ("nofix", "defects", "preaparc"):
- globsuffix = "*"
- keys = ensure_list(altkey) if altkey else [key]
- globfmt = os.path.join(path, dirval, "".join((globprefix, "{}", globsuffix)))
- return [
- os.path.abspath(f) for key in keys for f in glob.glob(globfmt.format(key))
- ]
-
- def _list_outputs(self):
- subject_path = os.path.join(self.inputs.sd, self.inputs.sid)
- output_traits = self._outputs()
- outputs = output_traits.get()
- for k in list(outputs.keys()):
- val = self._get_files(
- subject_path,
- k,
- output_traits.traits()[k].loc,
- output_traits.traits()[k].altkey,
- )
- if val:
- outputs[k] = simplify_list(val)
- return outputs
-class FastSCommand(CommandLine):
+class FastSurfer(CommandLine):
"""
Wraps FastSurfer command for segmentation and surface processing
"""
- input_spec = FastSurfSourceInputSpec
+ input_spec = FastSInputSpec
output_spec = FastSurfSourceOutputSpec
- _cmd = '/fastsurfer/run_fastsurfer.sh --surfreg'
+ _cmd = 'run_fastsurfer.sh --surfreg'
def _list_outputs(self):
outputs = self.output_spec().get()
From 21d3eff7f74970428513f5a72bdca2da178d5ea1 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 1 Aug 2022 10:35:34 -0500
Subject: [PATCH 158/220] Update smriprep/cli/run.py
Fix consistency of logic for location of freesurfer license file
Co-authored-by: Chris Markiewicz
---
smriprep/cli/run.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 34a3f61f86..3f9c803d3b 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -331,10 +331,11 @@ def _warn_redirect(message, category, filename, lineno, file=None, line=None):
warnings.showwarning = _warn_redirect
# Precedence: --fs-license-file, $FS_LICENSE, default_license
+ default_license = os.path.join(os.getenv("FREESURFER_HOME", ""), "license.txt")
if opts.fs_license_file is not None:
os.environ["FS_LICENSE"] = os.path.abspath(opts.fs_license_file)
- elif os.path.exists(os.path.abspath("/opt/freesurfer/license.txt")):
- os.environ["FS_LICENSE"] = os.path.abspath("/opt/freesurfer/license.txt")
+ elif "FS_LICENSE" not in os.environ and os.path.exists(default_license):
+ os.environ["FS_LICENSE"] = default_license
if not check_valid_fs_license():
raise RuntimeError(
From db5943126a1d5f8698dea45c3debfe64b0674b51 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 1 Aug 2022 10:48:40 -0500
Subject: [PATCH 159/220] Fix logic in surface recon workflow selection
---
smriprep/workflows/anatomical.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 0e873370f6..2c0ec7631b 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -536,7 +536,7 @@ def _check_img(img):
check_fastsurfer.inputs.logger = LOGGER
# Select which surface reconstruction workflow based on CLI arguments
- if freesurfer and (not freesurfer):
+ if freesurfer and (not fastsurfer):
surface_recon_wf = init_surface_recon_wf(
name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
From 0e12ed82debdec169725376e4d64e4c76361f67d Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 1 Aug 2022 10:51:58 -0500
Subject: [PATCH 160/220] Revert to previous outputnode for existing FreeSurfer
compatibility
---
smriprep/workflows/anatomical.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 2c0ec7631b..00b3ac58b8 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -421,10 +421,10 @@ def _check_img(img):
(('outputnode.bias_corrected', _pop), 'inputnode.moving_image')]),
(buffernode, anat_norm_wf, [('t1w_mask', 'inputnode.moving_mask')]),
(anat_norm_wf, outputnode, [
- ('outputnode.standardized', 'std_preproc'),
- ('outputnode.std_mask', 'std_mask'),
- ('outputnode.std_dseg', 'std_dseg'),
- ('outputnode.std_tpms', 'std_tpms'),
+ ('poutputnode.standardized', 'std_preproc'),
+ ('poutputnode.std_mask', 'std_mask'),
+ ('poutputnode.std_dseg', 'std_dseg'),
+ ('poutputnode.std_tpms', 'std_tpms'),
('outputnode.template', 'template'),
('outputnode.anat2std_xfm', 'anat2std_xfm'),
('outputnode.std2anat_xfm', 'std2anat_xfm'),
@@ -454,7 +454,7 @@ def _check_img(img):
(anat_template_wf, anat_reports_wf, [
('outputnode.out_report', 'inputnode.t1w_conform_report')]),
(anat_norm_wf, anat_reports_wf, [
- ('outputnode.template', 'inputnode.template')]),
+ ('poutputnode.template', 'inputnode.template')]),
])
# fmt:on
From b89254d69ea27157cfadeb90c4f5702b464ded67 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 1 Aug 2022 11:22:09 -0500
Subject: [PATCH 161/220] Update smriprep/workflows/anatomical.py
Remove unnecessary parentheses
Co-authored-by: Chris Markiewicz
---
smriprep/workflows/anatomical.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 00b3ac58b8..cc96891441 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -512,7 +512,7 @@ def _check_img(img):
(fast2bids, outputnode, [('out', 't1w_tpms')]),
])
# fmt:on
- if (not freesurfer) and (not fastsurfer): # Flag --fs-no-reconall is set - return
+ if not freesurfer and not fastsurfer: # Flag --fs-no-reconall is set - return
# fmt:off
workflow.connect([
(brain_extraction_wf, buffernode, [
From 25c639984924cf4aa2840faf42d61cbaa37c4312 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 1 Aug 2022 16:42:20 -0500
Subject: [PATCH 162/220] Deduplicating get_surfaces and fssource
Removes unnecessary variables and conditionals to simplify
---
smriprep/workflows/surfaces.py | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index d57960d7b4..578c122760 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -802,14 +802,8 @@ def init_gifti_surface_wf(*, fastsurfer, name="gifti_surface_wf"):
name="inputnode",
)
outputnode = pe.Node(niu.IdentityInterface(["surfaces"]), name="outputnode")
- subs_dir = 'subjects_dir'
- subj = 'subject_id'
- if fastsurfer is True:
- get_surfaces = pe.Node(fastsurf.FastSurferSource(), name="get_surfaces")
- subs_dir = 'sd'
- subj = 'sid'
- else:
- get_surfaces = pe.Node(nio.FreeSurferSource(), name="get_surfaces")
+
+ get_surfaces = pe.Node(nio.FreeSurferSource(), name="get_surfaces")
midthickness = pe.MapNode(
MakeMidthickness(thickness=True, distance=0.5, out_name="midthickness"),
@@ -900,14 +894,7 @@ def init_segs_to_native_wf(*, fastsurfer, name="segs_to_native", segmentation="a
)
outputnode = pe.Node(niu.IdentityInterface(["out_file"]), name="outputnode")
# Extract the aseg and aparc+aseg outputs
- subs_dir = 'subjects_dir'
- subj = 'subject_id'
- if fastsurfer is True:
- fssource = pe.Node(fastsurf.FastSurferSource(), name="fs_datasource")
- subs_dir = 'sd'
- subj = 'sid'
- else:
- fssource = pe.Node(nio.FreeSurferSource(), name="fs_datasource")
+ fssource = pe.Node(nio.FreeSurferSource(), name="fs_datasource")
# Resample from T1.mgz to T1w.nii.gz, applying any offset in fsnative2t1w_xfm,
# and convert to NIfTI while we're at it
From 0ea24731fd7fb72d601815db2253dc6f1eebc46e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 1 Aug 2022 16:48:23 -0500
Subject: [PATCH 163/220] Remove unnecessary FastSurfer report class
---
smriprep/interfaces/reports.py | 54 +---------------------------------
1 file changed, 1 insertion(+), 53 deletions(-)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index 7349df6d2a..979afaeba0 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -37,8 +37,6 @@
)
from nipype.interfaces import freesurfer as fs
from nipype.interfaces.io import FSSourceInputSpec as _FSSourceInputSpec
-from smriprep.interfaces.fastsurfer import FastSurfSourceInputSpec as _FastSurfSourceInputSpec
-# from smriprep.interfaces.fastsurfer import FastSurfSourceOutputSpec as _FastSurfSourceOutputSpec
from smriprep.interfaces import fastsurfer as fastsurf
from smriprep.utils.misc import check_fastsurfer
from nipype.interfaces.mixins import reporting
@@ -184,15 +182,7 @@ class _FSSurfaceReportInputSpec(_SVGReportCapableInputSpec, _FSSourceInputSpec):
class _FSSurfaceReportOutputSpec(reporting.ReportCapableOutputSpec):
pass
-
-
-class _FastSurfSurfaceReportInputSpec(_SVGReportCapableInputSpec, _FastSurfSourceInputSpec):
- pass
-
-
-class _FastSurfSurfaceReportOutputSpec(reporting.ReportCapableOutputSpec):
- pass
-
+
class FSSurfaceReport(SimpleInterface):
"""Replaces ``ReconAllRPT``, without need of calling recon-all."""
@@ -234,45 +224,3 @@ def _run_interface(self, runtime):
out_file=self._results["out_report"],
)
return runtime
-
-
-class FastSurfSurfaceReport(SimpleInterface):
- """Replaces ``ReconAllRPT``, without need of calling recon-all."""
-
- input_spec = _FastSurfSurfaceReportInputSpec
- output_spec = _FastSurfSurfaceReportOutputSpec
-
- def _run_interface(self, runtime):
- from niworkflows.viz.utils import (
- plot_registration,
- cuts_from_bbox,
- compose_view,
- )
- from nibabel import load
-
- rootdir = Path(self.inputs.sd) / self.inputs.sid
- _anat_file = str(rootdir / "mri" / "brain.mgz")
- _contour_file = str(rootdir / "mri" / "ribbon.mgz")
-
- anat = load(_anat_file)
- contour_nii = load(_contour_file)
-
- n_cuts = 7
- cuts = cuts_from_bbox(contour_nii, cuts=n_cuts)
-
- self._results["out_report"] = str(Path(runtime.cwd) / self.inputs.out_report)
-
- # Call composer
- compose_view(
- plot_registration(
- anat,
- "fixed-image",
- estimate_brightness=True,
- cuts=cuts,
- contour=contour_nii,
- compress=self.inputs.compress_report,
- ),
- [],
- out_file=self._results["out_report"],
- )
- return runtime
From 4431be208ad4c0178e4db6cc3f52d7615373d64c Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 1 Aug 2022 16:55:44 -0500
Subject: [PATCH 164/220] Add FASTSURFER_HOME to PATH
---
Dockerfile | 1 +
1 file changed, 1 insertion(+)
diff --git a/Dockerfile b/Dockerfile
index fc74b2253d..35df9931a0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -325,6 +325,7 @@ ENV FREESURFER="/opt/freesurfer"
ENV IS_DOCKER_8395080871=1
ENV FASTSURFER_HOME=/fastsurfer
+ENV PATH="/fastsurfer:/$PATH"
RUN ldconfig
WORKDIR /tmp
From 75754021627c58f5d449a7c7700cacb8221c7f74 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 1 Aug 2022 17:05:01 -0500
Subject: [PATCH 165/220] Update default python version and remove unused
default values for input spec
Update default python version to 3.8 per FastSurfer v1.1.0 defaults, remove default values for FastSInputSpec when default is not used
---
smriprep/interfaces/fastsurfer.py | 18 +++---------------
1 file changed, 3 insertions(+), 15 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 0fdc55a9ba..1c9fc13fd8 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -112,7 +112,7 @@ class FastSInputSpec(CommandLineInputSpec):
----
py
which python version to use.
- Default ``python3.6``
+ Default ``python3.8``
seg_only
only run FastSurferCNN
(generate segmentation, do not run the surface pipeline)
@@ -153,23 +153,18 @@ class FastSInputSpec(CommandLineInputSpec):
weights_sag = File(
exists=True,
mandatory=False,
- default="../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
- usedefault=False, argstr="--weights_sag %s",
+ argstr="--weights_sag %s",
desc="Pretrained weights of sagittal network"
)
weights_ax = File(
exists=True,
mandatory=False,
- default="../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
- usedefault=False,
argstr="--weights_ax %s",
desc="Pretrained weights of axial network"
)
weights_cor = File(
exists=True,
mandatory=False,
- default="../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl",
- usedefault=False,
argstr="--weights_cor %s",
desc="Pretrained weights of coronal network"
)
@@ -182,7 +177,6 @@ class FastSInputSpec(CommandLineInputSpec):
clean_seg = traits.Bool(
False,
mandatory=False,
- usedefault=False,
argstr="--clean_seg",
desc="Flag to clean up FastSurferCNN segmentation"
)
@@ -195,7 +189,6 @@ class FastSInputSpec(CommandLineInputSpec):
no_cuda = traits.Bool(
False,
mandatory=False,
- usedefault=False,
argstr="--no_cuda",
desc="Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)"
)
@@ -216,21 +209,18 @@ class FastSInputSpec(CommandLineInputSpec):
)
fstess = traits.Bool(
False,
- usedefault=False,
mandatory=False,
argstr="--fstess",
desc="Use mri_tesselate instead of marching cube (default) for surface creation"
)
fsqsphere = traits.Bool(
False,
- usedefault=False,
mandatory=False,
argstr="--fsqsphere",
desc="Use FreeSurfer default instead of novel spectral spherical projection for qsphere"
)
fsaparc = traits.Bool(
False,
- usedefault=False,
mandatory=False,
argstr="--fsaparc",
desc="Use FS aparc segmentations in addition to DL prediction"
@@ -258,7 +248,7 @@ class FastSInputSpec(CommandLineInputSpec):
desc="Set openMP and ITK threads to"
)
py = traits.String(
- "python3.6",
+ "python3.8",
usedefault=True,
mandatory=False,
argstr="--py %s",
@@ -266,14 +256,12 @@ class FastSInputSpec(CommandLineInputSpec):
)
seg_only = traits.Bool(
False,
- usedefault=False,
mandatory=False,
argstr="--seg_only",
desc="only run FastSurferCNN (generate segmentation, do not surface)"
)
surf_only = traits.Bool(
False,
- usedefault=False,
mandatory=False,
argstr="--surf_only",
desc="only run the surface pipeline recon_surf."
From 415163c319e1de234ecd188ec44183f5c1940e13 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 11:28:52 -0500
Subject: [PATCH 166/220] Sub-class FastSurerSourceOutputSpec from
FSSourceOutputSpec
Simplify by subclassing from existing nipype io FreeSurfer wrapper per https://github.com/nipreps/smriprep/pull/280#discussion_r931247417
---
smriprep/interfaces/fastsurfer.py | 188 +-----------------------------
1 file changed, 2 insertions(+), 186 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 1c9fc13fd8..abfb9c6396 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -19,7 +19,7 @@
File,
)
from nipype.interfaces.base.traits_extension import traits
-from nipype.interfaces.io import IOBase
+from nipype.interfaces.io import IOBase, FSSourceOutputSpec
from nipype.utils.filemanip import (
simplify_list,
ensure_list,
@@ -288,80 +288,18 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
-
-class FastSurfSourceOutputSpec(TraitedSpec):
- T1 = File(
- exists=True,
- desc="Intensity normalized whole-head volume",
- loc="mri"
- )
- aseg = File(
- exists=True,
- loc="mri",
- desc="Volumetric map of regions from automatic segmentation",
- )
- brain = File(
- exists=True,
- desc="Intensity normalized brain-only volume",
- loc="mri"
- )
- brainmask = File(
- exists=True,
- desc="Skull-stripped (brain-only) volume",
- loc="mri"
- )
- filled = File(
- exists=True,
- desc="Subcortical mass volume",
- loc="mri"
- )
- norm = File(
- exists=True,
- desc="Normalized skull-stripped volume",
- loc="mri"
- )
- nu = File(
- exists=True,
- desc="Non-uniformity corrected whole-head volume",
- loc="mri"
- )
- orig = File(
- exists=True,
- desc="Base image conformed to FastSurfer space",
- loc="mri"
- )
+class FastSurferSourceOutputSpec(FSSourceOutputSpec):
orig_nu = File(
exists=True,
desc="Base image conformed to Fastsurfer space and nonuniformity corrected",
loc="mri"
)
- rawavg = File(
- exists=True,
- desc="Volume formed by averaging input images",
- loc="mri"
- )
- ribbon = OutputMultiPath(
- File(exists=True),
- desc="Volumetric maps of cortical ribbons",
- loc="mri",
- altkey="*ribbon",
- )
- wm = File(
- exists=True,
- desc="Segmented white-matter volume",
- loc="mri"
- )
wm_asegedit = OutputMultiPath(
File(exists=True),
desc="Edited white matter volume post-aseg",
loc="mri",
altkey="mri_nu_correct.mni"
)
- wmparc = File(
- exists=True,
- loc="mri",
- desc="Aparc parcellation projected into subcortical white matter",
- )
wmparc_mapped = OutputMultiPath(
exists=True,
loc="mri",
@@ -380,80 +318,6 @@ class FastSurfSourceOutputSpec(TraitedSpec):
loc="mri",
altkey="mri_nu_correct.mni"
)
- curv = OutputMultiPath(
- File(exists=True),
- desc="Maps of surface curvature",
- loc="surf"
- )
- avg_curv = OutputMultiPath(
- File(exists=True),
- desc="Average atlas curvature,sampled to subject",
- loc="surf",
- )
- inflated = OutputMultiPath(
- File(exists=True),
- desc="Inflated surface meshes",
- loc="surf"
- )
- pial = OutputMultiPath(
- File(exists=True),
- desc="Gray matter/pia mater surface meshes",
- loc="surf"
- )
- area_pial = OutputMultiPath(
- File(exists=True),
- desc="Mean area of triangles each vertex on the pial surface is "
- "associated with",
- loc="surf",
- altkey="area.pial",
- )
- curv_pial = OutputMultiPath(
- File(exists=True),
- desc="Curvature of pial surface",
- loc="surf",
- altkey="curv.pial",
- )
- smoothwm = OutputMultiPath(
- File(exists=True),
- loc="surf",
- desc="Smoothed original surface meshes"
- )
- sphere = OutputMultiPath(
- File(exists=True),
- desc="Spherical surface meshes",
- loc="surf"
- )
- sulc = OutputMultiPath(
- File(exists=True),
- desc="Surface maps of sulcal depth",
- loc="surf"
- )
- thickness = OutputMultiPath(
- File(exists=True),
- loc="surf",
- desc="Surface maps of cortical thickness"
- )
- volume = OutputMultiPath(
- File(exists=True),
- desc="Surface maps of cortical volume",
- loc="surf"
- )
- white = OutputMultiPath(
- File(exists=True),
- desc="White/gray matter surface meshes",
- loc="surf"
- )
- jacobian_white = OutputMultiPath(
- File(exists=True),
- desc="Distortion required to register to spherical atlas",
- loc="surf",
- )
- graymid = OutputMultiPath(
- File(exists=True),
- desc="Graymid/midthickness surface meshes",
- loc="surf",
- altkey=["graymid", "midthickness"],
- )
defects = OutputMultiPath(
File(exists=True),
desc="Defects",
@@ -466,18 +330,6 @@ class FastSurfSourceOutputSpec(TraitedSpec):
loc="surf",
altkey=["nofix"],
)
- label = OutputMultiPath(
- File(exists=True),
- desc="Volume and surface label files",
- loc="label",
- altkey="*label",
- )
- annot = OutputMultiPath(
- File(exists=True),
- desc="Surface annotation files",
- loc="label",
- altkey="*annot"
- )
aparc_ctab = OutputMultiPath(
File(exists=True),
loc="label",
@@ -496,12 +348,6 @@ class FastSurfSourceOutputSpec(TraitedSpec):
altkey="cortex",
desc="Cortex class label files",
)
- aparc_aseg = OutputMultiPath(
- File(exists=True),
- loc="mri",
- altkey="aparc?aseg",
- desc="Aparc parcellation projected into aseg volume",
- )
aparc_dkt_aseg = OutputMultiPath(
File(exists=True),
loc="mri",
@@ -520,42 +366,12 @@ class FastSurfSourceOutputSpec(TraitedSpec):
altkey="filled*pretess*",
desc="Pre-tessellation filled volume files",
)
- sphere_reg = OutputMultiPath(
- File(exists=True),
- loc="surf",
- altkey="sphere.reg",
- desc="Spherical registration file",
- )
preaparc = OutputMultiPath(
File(exists=True),
loc="surf",
altkey="preaparc",
desc="Pre-Aparc files",
)
- aseg_stats = OutputMultiPath(
- File(exists=True),
- loc="stats",
- altkey="aseg",
- desc="Automated segmentation statistics file",
- )
- wmparc_stats = OutputMultiPath(
- File(exists=True),
- loc="stats",
- altkey="wmparc.DKTatlas.mapped",
- desc="White matter parcellation statistics file",
- )
- aparc_stats = OutputMultiPath(
- File(exists=True),
- loc="stats",
- altkey="aparc.DKTatlas.mapped",
- desc="Aparc parcellation statistics files",
- )
- curv_stats = OutputMultiPath(
- File(exists=True),
- loc="stats",
- altkey="curv",
- desc="Curvature statistics files"
- )
w_g_stats = OutputMultiPath(
File(exists=True),
loc="stats",
From ac9aa3387996c82a77d631b4737e832fe4844ede Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 12:50:52 -0500
Subject: [PATCH 167/220] De-duplicating surface_recon_wf
---
smriprep/workflows/anatomical.py | 101 ++++++++++++-------------------
1 file changed, 39 insertions(+), 62 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index cc96891441..31292938e6 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -539,7 +539,6 @@ def _check_img(img):
if freesurfer and (not fastsurfer):
surface_recon_wf = init_surface_recon_wf(
name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
- applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
# fmt:off
workflow.connect([
(inputnode, fs_isrunning, [
@@ -550,85 +549,63 @@ def _check_img(img):
('flair', 'inputnode.flair'),
('subject_id', 'inputnode.subject_id')]),
(fs_isrunning, surface_recon_wf, [('out', 'inputnode.subjects_dir')]),
- (anat_validate, surface_recon_wf, [('out_file', 'inputnode.t1w')]),
- (brain_extraction_wf, surface_recon_wf, [
- (('outputnode.out_file', _pop), 'inputnode.skullstripped_t1'),
- ('outputnode.out_segm', 'inputnode.ants_segs'),
- (('outputnode.bias_corrected', _pop), 'inputnode.corrected_t1')]),
- (brain_extraction_wf, applyrefined, [
- (('outputnode.bias_corrected', _pop), 'in_file')]),
- (surface_recon_wf, applyrefined, [
- ('outputnode.out_brainmask', 'mask_file')]),
- (surface_recon_wf, outputnode, [
- ('outputnode.subjects_dir', 'subjects_dir'),
- ('outputnode.subject_id', 'subject_id'),
- ('outputnode.t1w2fsnative_xfm', 't1w2fsnative_xfm'),
- ('outputnode.fsnative2t1w_xfm', 'fsnative2t1w_xfm'),
- ('outputnode.surfaces', 'surfaces'),
- ('outputnode.out_aseg', 't1w_aseg'),
- ('outputnode.out_aparc', 't1w_aparc')]),
- (applyrefined, buffernode, [('out_file', 't1w_brain')]),
- (surface_recon_wf, buffernode, [
- ('outputnode.out_brainmask', 't1w_mask')]),
(surface_recon_wf, anat_reports_wf, [
('outputnode.subject_id', 'inputnode.subject_id'),
('outputnode.subjects_dir', 'inputnode.subjects_dir')]),
- (surface_recon_wf, anat_derivatives_wf, [
- ('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
- ('outputnode.out_aparc', 'inputnode.t1w_fs_aparc'),
- ]),
- (outputnode, anat_derivatives_wf, [
- ('t1w2fsnative_xfm', 'inputnode.t1w2fsnative_xfm'),
- ('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
- ('surfaces', 'inputnode.surfaces'),
]),
])
# fmt:on
elif fastsurfer:
- fastsurf_recon_wf = init_fastsurf_recon_wf(
- name="fastsurf_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
- applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
+ surface_recon_wf = init_fastsurf_recon_wf(
+ name="surface_recon_wf", omp_nthreads=omp_nthreads, hires=hires)
# fmt:off
workflow.connect([
- (inputnode, fastsurf_recon_wf, [
+ (inputnode, surface_recon_wf, [
('subject_id', 'inputnode.sid'),
('subjects_dir', 'inputnode.sd')]),
- (anat_validate, fastsurf_recon_wf, [
- ('out_file', 'inputnode.t1w')]),
- (brain_extraction_wf, fastsurf_recon_wf, [
- (('outputnode.out_file', _pop), 'inputnode.skullstripped_t1'),
- ('outputnode.out_segm', 'inputnode.ants_segs'),
- (('outputnode.bias_corrected', _pop), 'inputnode.corrected_t1')]),
- (brain_extraction_wf, applyrefined, [
- (('outputnode.bias_corrected', _pop), 'in_file')]),
- (fastsurf_recon_wf, applyrefined, [
+ (surface_recon_wf, applyrefined, [
('outputnode.out_brainmask', 'mask_file')]),
- (fastsurf_recon_wf, outputnode, [
- ('inputnode.sd', 'subjects_dir'),
- ('inputnode.sid', 'subject_id'),
- ('outputnode.t1w2fsnative_xfm', 't1w2fsnative_xfm'),
- ('outputnode.fsnative2t1w_xfm', 'fsnative2t1w_xfm'),
- ('outputnode.surfaces', 'surfaces'),
- ('outputnode.out_aseg', 't1w_aseg'),
- ('outputnode.out_aparc', 't1w_aparc')]),
- (applyrefined, buffernode, [('out_file', 't1w_brain')]),
- (fastsurf_recon_wf, buffernode, [('outputnode.out_brainmask', 't1w_mask')]),
- (fastsurf_recon_wf, anat_reports_wf, [
+ (surface_recon_wf, anat_reports_wf, [
('inputnode.sid', 'inputnode.subject_id'),
('inputnode.sd', 'inputnode.subjects_dir'),
]),
- (fastsurf_recon_wf, anat_derivatives_wf, [
- ('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
- ('outputnode.out_aparc', 'inputnode.t1w_fs_aparc'),
- ]),
- (outputnode, anat_derivatives_wf, [
- ('t1w2fsnative_xfm', 'inputnode.t1w2fsnative_xfm'),
- ('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
- ('surfaces', 'inputnode.surfaces'),
- ]),
])
# fmt:on
+ #Identical connections
+ applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
+ workflow.connect([
+ (anat_validate, surface_recon_wf, [('out_file', 'inputnode.t1w')]),
+ (brain_extraction_wf, surface_recon_wf, [
+ (('outputnode.out_file', _pop), 'inputnode.skullstripped_t1'),
+ ('outputnode.out_segm', 'inputnode.ants_segs'),
+ (('outputnode.bias_corrected', _pop), 'inputnode.corrected_t1')]),
+ (brain_extraction_wf, applyrefined, [
+ (('outputnode.bias_corrected', _pop), 'in_file')]),
+ (surface_recon_wf, applyrefined, [
+ ('outputnode.out_brainmask', 'mask_file')]),
+ (surface_recon_wf, outputnode, [
+ ('outputnode.subjects_dir', 'subjects_dir'),
+ ('outputnode.subject_id', 'subject_id'),
+ ('outputnode.t1w2fsnative_xfm', 't1w2fsnative_xfm'),
+ ('outputnode.fsnative2t1w_xfm', 'fsnative2t1w_xfm'),
+ ('outputnode.surfaces', 'surfaces'),
+ ('outputnode.out_aseg', 't1w_aseg'),
+ ('outputnode.out_aparc', 't1w_aparc')]),
+ (applyrefined, buffernode, [('out_file', 't1w_brain')]),
+ (surface_recon_wf, buffernode, [
+ ('outputnode.out_brainmask', 't1w_mask')]),
+ (surface_recon_wf, anat_derivatives_wf, [
+ ('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
+ ('outputnode.out_aparc', 'inputnode.t1w_fs_aparc'),
+ ]),
+ (outputnode, anat_derivatives_wf, [
+ ('t1w2fsnative_xfm', 'inputnode.t1w2fsnative_xfm'),
+ ('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
+ ('surfaces', 'inputnode.surfaces'),
+ ]),
+ ])
+
return workflow
From 313576e58f4f8adb2e82eb74f1daf19270c63153 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 14:35:56 -0500
Subject: [PATCH 168/220] PEP8 compliance
---
smriprep/workflows/anatomical.py | 64 ++++++++++++++++----------------
1 file changed, 32 insertions(+), 32 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 31292938e6..ebe4ad7ad1 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -551,7 +551,7 @@ def _check_img(img):
(fs_isrunning, surface_recon_wf, [('out', 'inputnode.subjects_dir')]),
(surface_recon_wf, anat_reports_wf, [
('outputnode.subject_id', 'inputnode.subject_id'),
- ('outputnode.subjects_dir', 'inputnode.subjects_dir')]),
+ ('outputnode.subjects_dir', 'inputnode.subjects_dir'),
]),
])
# fmt:on
@@ -572,39 +572,39 @@ def _check_img(img):
])
# fmt:on
- #Identical connections
+ # Identical connections
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
workflow.connect([
- (anat_validate, surface_recon_wf, [('out_file', 'inputnode.t1w')]),
- (brain_extraction_wf, surface_recon_wf, [
- (('outputnode.out_file', _pop), 'inputnode.skullstripped_t1'),
- ('outputnode.out_segm', 'inputnode.ants_segs'),
- (('outputnode.bias_corrected', _pop), 'inputnode.corrected_t1')]),
- (brain_extraction_wf, applyrefined, [
- (('outputnode.bias_corrected', _pop), 'in_file')]),
- (surface_recon_wf, applyrefined, [
- ('outputnode.out_brainmask', 'mask_file')]),
- (surface_recon_wf, outputnode, [
- ('outputnode.subjects_dir', 'subjects_dir'),
- ('outputnode.subject_id', 'subject_id'),
- ('outputnode.t1w2fsnative_xfm', 't1w2fsnative_xfm'),
- ('outputnode.fsnative2t1w_xfm', 'fsnative2t1w_xfm'),
- ('outputnode.surfaces', 'surfaces'),
- ('outputnode.out_aseg', 't1w_aseg'),
- ('outputnode.out_aparc', 't1w_aparc')]),
- (applyrefined, buffernode, [('out_file', 't1w_brain')]),
- (surface_recon_wf, buffernode, [
- ('outputnode.out_brainmask', 't1w_mask')]),
- (surface_recon_wf, anat_derivatives_wf, [
- ('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
- ('outputnode.out_aparc', 'inputnode.t1w_fs_aparc'),
- ]),
- (outputnode, anat_derivatives_wf, [
- ('t1w2fsnative_xfm', 'inputnode.t1w2fsnative_xfm'),
- ('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
- ('surfaces', 'inputnode.surfaces'),
- ]),
- ])
+ (anat_validate, surface_recon_wf, [('out_file', 'inputnode.t1w')]),
+ (brain_extraction_wf, surface_recon_wf, [
+ (('outputnode.out_file', _pop), 'inputnode.skullstripped_t1'),
+ ('outputnode.out_segm', 'inputnode.ants_segs'),
+ (('outputnode.bias_corrected', _pop), 'inputnode.corrected_t1')]),
+ (brain_extraction_wf, applyrefined, [
+ (('outputnode.bias_corrected', _pop), 'in_file')]),
+ (surface_recon_wf, applyrefined, [
+ ('outputnode.out_brainmask', 'mask_file')]),
+ (surface_recon_wf, outputnode, [
+ ('outputnode.subjects_dir', 'subjects_dir'),
+ ('outputnode.subject_id', 'subject_id'),
+ ('outputnode.t1w2fsnative_xfm', 't1w2fsnative_xfm'),
+ ('outputnode.fsnative2t1w_xfm', 'fsnative2t1w_xfm'),
+ ('outputnode.surfaces', 'surfaces'),
+ ('outputnode.out_aseg', 't1w_aseg'),
+ ('outputnode.out_aparc', 't1w_aparc')]),
+ (applyrefined, buffernode, [('out_file', 't1w_brain')]),
+ (surface_recon_wf, buffernode, [
+ ('outputnode.out_brainmask', 't1w_mask')]),
+ (surface_recon_wf, anat_derivatives_wf, [
+ ('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
+ ('outputnode.out_aparc', 'inputnode.t1w_fs_aparc'),
+ ]),
+ (outputnode, anat_derivatives_wf, [
+ ('t1w2fsnative_xfm', 'inputnode.t1w2fsnative_xfm'),
+ ('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
+ ('surfaces', 'inputnode.surfaces'),
+ ]),
+ ])
return workflow
From e4d7e4df3d7f4b03ebde9c50763c3c6740738321 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 14:36:29 -0500
Subject: [PATCH 169/220] PEP8 compliance
---
smriprep/workflows/surfaces.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 578c122760..11c933ccac 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -802,7 +802,7 @@ def init_gifti_surface_wf(*, fastsurfer, name="gifti_surface_wf"):
name="inputnode",
)
outputnode = pe.Node(niu.IdentityInterface(["surfaces"]), name="outputnode")
-
+
get_surfaces = pe.Node(nio.FreeSurferSource(), name="get_surfaces")
midthickness = pe.MapNode(
From 5d015edaf65a348fc891bc9d1636069b1050cf49 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 14:36:59 -0500
Subject: [PATCH 170/220] PEP8 compliance
---
smriprep/interfaces/fastsurfer.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index abfb9c6396..72a0180682 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -288,6 +288,7 @@ class FastSurfSourceInputSpec(BaseInterfaceInputSpec):
desc="T1 full head input (not bias corrected, global path)"
)
+
class FastSurferSourceOutputSpec(FSSourceOutputSpec):
orig_nu = File(
exists=True,
From 6643b936a7b3ef0e9788fb16c8629ff9826ff798 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 14:37:33 -0500
Subject: [PATCH 171/220] PEP8 compliance
---
smriprep/interfaces/reports.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/reports.py b/smriprep/interfaces/reports.py
index 979afaeba0..0ba0a77e81 100644
--- a/smriprep/interfaces/reports.py
+++ b/smriprep/interfaces/reports.py
@@ -182,7 +182,7 @@ class _FSSurfaceReportInputSpec(_SVGReportCapableInputSpec, _FSSourceInputSpec):
class _FSSurfaceReportOutputSpec(reporting.ReportCapableOutputSpec):
pass
-
+
class FSSurfaceReport(SimpleInterface):
"""Replaces ``ReconAllRPT``, without need of calling recon-all."""
From 573f0b392e54f708ae7468c41b7c3a278d147116 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 14:39:36 -0500
Subject: [PATCH 172/220] PEP8 compliance
---
smriprep/workflows/anatomical.py | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index ebe4ad7ad1..1e7e05b1cd 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -597,14 +597,13 @@ def _check_img(img):
('outputnode.out_brainmask', 't1w_mask')]),
(surface_recon_wf, anat_derivatives_wf, [
('outputnode.out_aseg', 'inputnode.t1w_fs_aseg'),
- ('outputnode.out_aparc', 'inputnode.t1w_fs_aparc'),
- ]),
+ ('outputnode.out_aparc', 'inputnode.t1w_fs_aparc')]),
(outputnode, anat_derivatives_wf, [
('t1w2fsnative_xfm', 'inputnode.t1w2fsnative_xfm'),
('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
('surfaces', 'inputnode.surfaces'),
- ]),
- ])
+ ]),
+ ])
return workflow
From 9bdb72cb15371b5fd22a7b7e9371dd5467264540 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 14:44:12 -0500
Subject: [PATCH 173/220] Revert to FSSurfaceReport for FastSurfer
---
smriprep/workflows/outputs.py | 23 +----------------------
1 file changed, 1 insertion(+), 22 deletions(-)
diff --git a/smriprep/workflows/outputs.py b/smriprep/workflows/outputs.py
index 840e278809..de9ee569f3 100644
--- a/smriprep/workflows/outputs.py
+++ b/smriprep/workflows/outputs.py
@@ -173,7 +173,7 @@ def init_anat_reports_wf(*, freesurfer, fastsurfer, output_dir, name="anat_repor
])
# fmt:on
- if freesurfer:
+ if freesurfer or fastsurfer:
from ..interfaces.reports import FSSurfaceReport
recon_report = pe.Node(FSSurfaceReport(), name="recon_report")
@@ -194,27 +194,6 @@ def init_anat_reports_wf(*, freesurfer, fastsurfer, output_dir, name="anat_repor
(inputnode, ds_recon_report, [('source_file', 'source_file')])
])
# fmt:on
- elif fastsurfer:
- from ..interfaces.reports import FastSurfSurfaceReport
-
- recon_report = pe.Node(FastSurfSurfaceReport(), name="recon_report")
- recon_report.interface._always_run = True
-
- ds_recon_report = pe.Node(
- DerivativesDataSink(
- base_directory=output_dir, desc="fastsurf_recon", datatype="figures"
- ),
- name="ds_recon_report",
- run_without_submitting=True,
- )
- # fmt:off
- workflow.connect([
- (inputnode, recon_report, [('subjects_dir', 'sd'),
- ('subject_id', 'sid')]),
- (recon_report, ds_recon_report, [('out_report', 'in_file')]),
- (inputnode, ds_recon_report, [('source_file', 'source_file')])
- ])
- # fmt:on
return workflow
From 4247e712db019b174bf6a4f91e0e2aadc7a6c8db Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 14:51:15 -0500
Subject: [PATCH 174/220] Import FreeSurferSource
---
smriprep/interfaces/fastsurfer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 72a0180682..f1a2c4970f 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -19,7 +19,7 @@
File,
)
from nipype.interfaces.base.traits_extension import traits
-from nipype.interfaces.io import IOBase, FSSourceOutputSpec
+from nipype.interfaces.io import IOBase, FSSourceOutputSpec, FreeSurferSource
from nipype.utils.filemanip import (
simplify_list,
ensure_list,
From 5cacac2d9b304d353754dbae737d465307ea9061 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 14:57:43 -0500
Subject: [PATCH 175/220] Fix typo
---
smriprep/interfaces/fastsurfer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index f1a2c4970f..1a0d2d2157 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -402,7 +402,7 @@ class FastSurferSource(FreeSurferSource):
"""
- output_spec = FastSurfSourceOutputSpec
+ output_spec = FastSurferSourceOutputSpec
class FastSurfer(CommandLine):
From dde9494cf0bd5ae23701e395a58e233199f58806 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 15:00:50 -0500
Subject: [PATCH 176/220] Fix typo
---
smriprep/interfaces/fastsurfer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 1a0d2d2157..f922ddc460 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -412,7 +412,7 @@ class FastSurfer(CommandLine):
"""
input_spec = FastSInputSpec
- output_spec = FastSurfSourceOutputSpec
+ output_spec = FastSurferSourceOutputSpec
_cmd = 'run_fastsurfer.sh --surfreg'
def _list_outputs(self):
From 73cfea85e730c99f3736264d8864a59be4094e32 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 3 Aug 2022 15:07:30 -0500
Subject: [PATCH 177/220] Attempt to fix docstring error in build_docs
Attempt to fix docstring error from build_docs workflow in CircleCI:
```
Warning, treated as error:
/tmp/gh-pages/smriprep/interfaces/fastsurfer.py:docstring of smriprep.interfaces.fastsurfer.FastSurfer:35:Definition list ends without a blank line; unexpected unindent.
make: *** [Makefile:61: html] Error 2
make: Leaving directory '/tmp/gh-pages/docs'
Exited with code exit status 2
```
---
smriprep/interfaces/fastsurfer.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index f922ddc460..f384e40520 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -406,8 +406,7 @@ class FastSurferSource(FreeSurferSource):
class FastSurfer(CommandLine):
- """
- Wraps FastSurfer command for segmentation and surface processing
+ """Wraps FastSurfer command for segmentation and surface processing.
"""
From 2cbd94a8dfaf9e49d897844455f00dfea73f36a8 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 4 Aug 2022 10:33:31 -0500
Subject: [PATCH 178/220] Revert from FastSurfer v FreeSurfer specific string
vars to nipype convention
---
smriprep/workflows/surfaces.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 11c933ccac..4ba035c982 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -827,8 +827,8 @@ def init_gifti_surface_wf(*, fastsurfer, name="gifti_surface_wf"):
# fmt:off
workflow.connect([
- (inputnode, get_surfaces, [('subjects_dir', subs_dir),
- ('subject_id', subj)]),
+ (inputnode, get_surfaces, [('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id')]),
(inputnode, save_midthickness, [('subjects_dir', 'base_directory'),
('subject_id', 'container')]),
# Generate midthickness surfaces and save to FreeSurfer derivatives
@@ -924,8 +924,8 @@ def _sel(x):
# fmt:off
workflow.connect([
(inputnode, fssource, [
- ('subjects_dir', subs_dir),
- ('subject_id', subj)]),
+ ('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id')]),
(inputnode, resample, [('in_file', 'target_file'),
('fsnative2t1w_xfm', 'lta_file')]),
(fssource, resample, [(segmentation, 'source_file')]),
From 3a535c945b1083ca298ae0c59ffbf4e4eb876396 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Fri, 12 Aug 2022 09:27:59 -0500
Subject: [PATCH 179/220] Update python version
---
Dockerfile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 35df9931a0..bad467012e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -29,8 +29,8 @@ FROM ubuntu:focal-20210416
# Prepare environment
ENV DEBIAN_FRONTEND="noninteractive"
ENV LANG=C.UTF-8
-ARG PYTHON_VERSION=3.8
-ARG CONDA_FILE=Miniconda3-py38_4.12.0-Linux-x86_64.sh
+ARG PYTHON_VERSION=3.9
+ARG CONDA_FILE=Miniconda3-py39_4.12.0-Linux-x86_64.sh
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
@@ -267,8 +267,8 @@ WORKDIR $ANTSPATH
RUN curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \
| tar -xzC $ANTSPATH --strip-components 1
-# nipreps/miniconda:py38_1.4.1
-COPY --from=nipreps/miniconda@sha256:ebbff214e6c9dc50ccc6fdbe679df1ffcbceaa45b47a75d6e34e8a064ef178da /opt/conda /opt/conda
+# nipreps/miniconda:py39_0525.0
+COPY --from=nipreps/miniconda@sha256:40fffd37963502dcd8549773559fc21182f52460e59e0ad6398a84faf6055641 /opt/conda /opt/conda
RUN ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
From 4a4f7a02f4d297fba60894ef55f38626cbc12103 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 15 Aug 2022 14:25:48 -0500
Subject: [PATCH 180/220] Revert miniconda version for FastSurfer
compatibility, update nibabel
---
Dockerfile | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index bad467012e..37254577c9 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -29,8 +29,8 @@ FROM ubuntu:focal-20210416
# Prepare environment
ENV DEBIAN_FRONTEND="noninteractive"
ENV LANG=C.UTF-8
-ARG PYTHON_VERSION=3.9
-ARG CONDA_FILE=Miniconda3-py39_4.12.0-Linux-x86_64.sh
+ARG PYTHON_VERSION=3.8
+ARG CONDA_FILE=Miniconda3-py38_4.11.0-Linux-x86_64.sh
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
@@ -311,7 +311,8 @@ ARG VERSION
# Force static versioning within container
RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
echo "include smriprep/${VERSION}" >> /src/smriprep/MANIFEST.in && \
- /opt/conda/bin/python -m pip install --use-feature=in-tree-build --no-cache-dir "/src/smriprep[all]"
+ /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]" && \
+ /opt/conda/bin/python -m pip install nibabel==4.0.1
RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
From 18c4117a70bf29561c6fd2b9ff741b2fe072f751 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 15 Aug 2022 17:38:03 -0500
Subject: [PATCH 181/220] Nibabel==4.0.1 install after fastsurfer environment
update
---
Dockerfile | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 37254577c9..fa083310c4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -311,11 +311,12 @@ ARG VERSION
# Force static versioning within container
RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
echo "include smriprep/${VERSION}" >> /src/smriprep/MANIFEST.in && \
- /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]" && \
- /opt/conda/bin/python -m pip install nibabel==4.0.1
+ /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]"
RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
+RUN /opt/conda/bin/python -m pip install nibabel==4.0.1
+
RUN find $HOME -type d -exec chmod go=u {} + && \
find $HOME -type f -exec chmod go=u {} + && \
rm -rf $HOME/.npm $HOME/.conda $HOME/.empty
From 0a1ec70b4268c69e825d55511977168d6620f9d2 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 16 Aug 2022 09:14:46 -0500
Subject: [PATCH 182/220] Switch to python 3.8
---
Dockerfile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index fa083310c4..34d3da4790 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -267,8 +267,8 @@ WORKDIR $ANTSPATH
RUN curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \
| tar -xzC $ANTSPATH --strip-components 1
-# nipreps/miniconda:py39_0525.0
-COPY --from=nipreps/miniconda@sha256:40fffd37963502dcd8549773559fc21182f52460e59e0ad6398a84faf6055641 /opt/conda /opt/conda
+# nipreps/miniconda:py38_1.4.1
+COPY --from=nipreps/miniconda@sha256:ebbff214e6c9dc50ccc6fdbe679df1ffcbceaa45b47a75d6e34e8a064ef178da /opt/conda /opt/conda
RUN ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
From 98c3a879276fe48cebbe2d833c4505c1f65df609 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 18 Aug 2022 11:59:44 -0500
Subject: [PATCH 183/220] Upgrade to latest FastSurfer release v1.1.1
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 34d3da4790..d0b8b75029 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -55,7 +55,7 @@ RUN apt-get update && \
# git clone dev branch of FastSurfer
RUN cd /opt && mkdir /fastsurfer \
- && git clone -b v1.1.0 https://github.com/Deep-MI/FastSurfer.git \
+ && git clone -b v1.1.1 https://github.com/Deep-MI/FastSurfer.git \
&& cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
# Install conda
From 9b517ecec6ccdfd9eb9d58e321dc70b92b531edb Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 18 Aug 2022 12:00:50 -0500
Subject: [PATCH 184/220] Update FastSurfer version
---
docs/installation.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/installation.rst b/docs/installation.rst
index b701726dbb..ca33878c3b 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -150,4 +150,4 @@ the ``smriprep`` package:
- `C3D `_ (version 1.0.0)
- FreeSurfer_ (version 7.2.0)
- `bids-validator `_ (version 1.1.0)
-- FastSurfer_ (version 1.1.0)
+- FastSurfer_ (version 1.1.1)
From b18e4401a9e7645cfc54a25b6b7b1be9a58857c7 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 1 Sep 2022 09:58:56 -0500
Subject: [PATCH 185/220] Switch to Nibabel 4.0.2
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index d0b8b75029..80f041c945 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -315,7 +315,7 @@ RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
-RUN /opt/conda/bin/python -m pip install nibabel==4.0.1
+RUN /opt/conda/bin/python -m pip install nibabel==4.0.2
RUN find $HOME -type d -exec chmod go=u {} + && \
find $HOME -type f -exec chmod go=u {} + && \
From de08d591708dfa00e45017dbd51530d100278112 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 1 Sep 2022 10:38:14 -0500
Subject: [PATCH 186/220] Install nibabel via conda
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 80f041c945..0325a5d30a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -315,7 +315,7 @@ RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
-RUN /opt/conda/bin/python -m pip install nibabel==4.0.2
+RUN conda install nibabel==4.0.2
RUN find $HOME -type d -exec chmod go=u {} + && \
find $HOME -type f -exec chmod go=u {} + && \
From 1a041cad9f4b71363e5822fc5ec617edab45491b Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 1 Sep 2022 10:58:39 -0500
Subject: [PATCH 187/220] Attempt to resolve CircleCI build error
https://app.circleci.com/pipelines/github/nipreps/smriprep/478/workflows/6a6f52b3-035f-4d9c-b122-698c27a9b5f3/jobs/2281
---
Dockerfile | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 0325a5d30a..68843d76eb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -311,12 +311,11 @@ ARG VERSION
# Force static versioning within container
RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
echo "include smriprep/${VERSION}" >> /src/smriprep/MANIFEST.in && \
- /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]"
+ /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]" && \
+ /opt/conda/bin/python -m pip install --no-cache-dir nibabel==4.0.2
RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
-RUN conda install nibabel==4.0.2
-
RUN find $HOME -type d -exec chmod go=u {} + && \
find $HOME -type f -exec chmod go=u {} + && \
rm -rf $HOME/.npm $HOME/.conda $HOME/.empty
From 0c49007fa538b1f9cdb57f7a6da461d7556f4c23 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 1 Sep 2022 11:19:54 -0500
Subject: [PATCH 188/220] De-duplicating workflow
---
smriprep/workflows/anatomical.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 1e7e05b1cd..5857389c3d 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -563,8 +563,6 @@ def _check_img(img):
(inputnode, surface_recon_wf, [
('subject_id', 'inputnode.sid'),
('subjects_dir', 'inputnode.sd')]),
- (surface_recon_wf, applyrefined, [
- ('outputnode.out_brainmask', 'mask_file')]),
(surface_recon_wf, anat_reports_wf, [
('inputnode.sid', 'inputnode.subject_id'),
('inputnode.sd', 'inputnode.subjects_dir'),
From 73116bb838a0590e0c3083704249a281b75023f4 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 1 Sep 2022 11:21:27 -0500
Subject: [PATCH 189/220] Remove unused package imports (Flake8 compliance)
---
smriprep/interfaces/fastsurfer.py | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index f384e40520..1390c47da1 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -6,24 +6,16 @@
for running FastSurfer CNN and surface processing.
"""
-import os
-import glob
-
from nipype.interfaces.base import (
CommandLine,
Directory,
CommandLineInputSpec,
OutputMultiPath,
- TraitedSpec,
BaseInterfaceInputSpec,
File,
)
from nipype.interfaces.base.traits_extension import traits
-from nipype.interfaces.io import IOBase, FSSourceOutputSpec, FreeSurferSource
-from nipype.utils.filemanip import (
- simplify_list,
- ensure_list,
-)
+from nipype.interfaces.io import FSSourceOutputSpec, FreeSurferSource
class FastSInputSpec(CommandLineInputSpec):
From aedf22041b00e8c7c6fbaa7b0088f66b2a8d4f3b Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 22 Sep 2022 09:47:43 -0500
Subject: [PATCH 190/220] Update FastSurfer version
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 68843d76eb..f3c953cf1d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -55,7 +55,7 @@ RUN apt-get update && \
# git clone dev branch of FastSurfer
RUN cd /opt && mkdir /fastsurfer \
- && git clone -b v1.1.1 https://github.com/Deep-MI/FastSurfer.git \
+ && git clone -b v1.1.2 https://github.com/Deep-MI/FastSurfer.git \
&& cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
# Install conda
From 1094e04da858ea3d0387b263b9c9c73681cc5d5f Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 22 Sep 2022 09:48:05 -0500
Subject: [PATCH 191/220] Update installation.rst
---
docs/installation.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/installation.rst b/docs/installation.rst
index ca33878c3b..2f8240f3a0 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -150,4 +150,4 @@ the ``smriprep`` package:
- `C3D `_ (version 1.0.0)
- FreeSurfer_ (version 7.2.0)
- `bids-validator `_ (version 1.1.0)
-- FastSurfer_ (version 1.1.1)
+- FastSurfer_ (version 1.1.2)
From 87940c933ce0acffffdf6bdfd30206a823ecfda8 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 18 Oct 2022 13:38:25 -0500
Subject: [PATCH 192/220] Fix error for Flake8
---
smriprep/workflows/surfaces.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 7760dc600f..5e9ebb8917 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -38,7 +38,6 @@
from ..interfaces.freesurfer import ReconAll
from ..interfaces import fastsurfer as fastsurf
-from ..interfaces.surf import NormalizeSurf
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
From 1c1fc21e6f8c7ce2cbc918f4edce6590036ee3ed Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 18 Oct 2022 14:37:26 -0500
Subject: [PATCH 193/220] Fix typo in FastSurfer version
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index f3c953cf1d..f1ea552bfb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -55,7 +55,7 @@ RUN apt-get update && \
# git clone dev branch of FastSurfer
RUN cd /opt && mkdir /fastsurfer \
- && git clone -b v1.1.2 https://github.com/Deep-MI/FastSurfer.git \
+ && git clone -b v.1.1.2 https://github.com/Deep-MI/FastSurfer.git \
&& cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
# Install conda
From 1bdf326543dadb88afc29a2edaef27832610f9c6 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 19 Oct 2022 09:14:23 -0500
Subject: [PATCH 194/220] Change nibabel version after installing FastSurfer
dependencies
---
Dockerfile | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index f1ea552bfb..787eea59c0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -311,10 +311,12 @@ ARG VERSION
# Force static versioning within container
RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
echo "include smriprep/${VERSION}" >> /src/smriprep/MANIFEST.in && \
- /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]" && \
- /opt/conda/bin/python -m pip install --no-cache-dir nibabel==4.0.2
+ /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]"
-RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
+RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
+
+# Installing nibabel version 4.0.2
+RUN /opt/conda/bin/python -m pip install --no-cache-dir nibabel==4.0.2
RUN find $HOME -type d -exec chmod go=u {} + && \
find $HOME -type f -exec chmod go=u {} + && \
From 96edd2a097a3a915890c9b01602f3dbb242b356a Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 9 Jan 2023 10:11:56 -0600
Subject: [PATCH 195/220] Test FreeSurfer license path fix
---
smriprep/cli/run.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 3f9c803d3b..d486979711 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -331,11 +331,11 @@ def _warn_redirect(message, category, filename, lineno, file=None, line=None):
warnings.showwarning = _warn_redirect
# Precedence: --fs-license-file, $FS_LICENSE, default_license
- default_license = os.path.join(os.getenv("FREESURFER_HOME", ""), "license.txt")
+ # default_license = os.path.join(os.getenv("FREESURFER_HOME", ""), "license.txt")
if opts.fs_license_file is not None:
os.environ["FS_LICENSE"] = os.path.abspath(opts.fs_license_file)
- elif "FS_LICENSE" not in os.environ and os.path.exists(default_license):
- os.environ["FS_LICENSE"] = default_license
+ # elif "FS_LICENSE" not in os.environ and os.path.exists(default_license):
+ # os.environ["FS_LICENSE"] = default_license
if not check_valid_fs_license():
raise RuntimeError(
From dbb647b3aefb18b465fe0575c1e56cdbd9574a6a Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 9 Jan 2023 15:19:30 -0600
Subject: [PATCH 196/220] Update Dockerfile
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 787eea59c0..68dce053ec 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -328,7 +328,7 @@ ENV FREESURFER="/opt/freesurfer"
ENV IS_DOCKER_8395080871=1
ENV FASTSURFER_HOME=/fastsurfer
-ENV PATH="/fastsurfer:/$PATH"
+ENV PATH="$PATH:/fastsurfer"
RUN ldconfig
WORKDIR /tmp
From e9673a710760ac4b8f345603cde52103d69aeb34 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 9 Jan 2023 16:04:01 -0600
Subject: [PATCH 197/220] Update run.py
---
smriprep/cli/run.py | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index d486979711..574a9e176a 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -222,23 +222,21 @@ def get_parser():
dest="hires",
help="disable sub-millimeter (hires) reconstruction",
)
- g_surfs.add_argument(
- "--fastsurfer",
- action="store_true",
- default=False,
- dest="fastsurfer",
- help="enable FastSurfer surface preprocessing.",
- )
- # g_surfs_xor = g_surfs.add_mutually_exclusive_group()
-
- g_surfs_xor = g_surfs
+ g_surfs_xor = g_surfs.add_mutually_exclusive_group()
g_surfs_xor.add_argument(
"--fs-no-reconall",
action="store_false",
dest="run_reconall",
help="disable FreeSurfer surface preprocessing.",
)
+ g_surfs_xor.add_argument(
+ "--fastsurfer",
+ action="store_true",
+ default=False,
+ dest="fastsurfer",
+ help="enable FastSurfer surface preprocessing.",
+ )
g_other = parser.add_argument_group("Other options")
g_other.add_argument(
From 8bcb69c3ece51f031a4908ca3547d90fee5df06d Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 10 Jan 2023 11:35:09 -0600
Subject: [PATCH 198/220] Update run.py
---
smriprep/cli/run.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 574a9e176a..2db66800f7 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -329,11 +329,8 @@ def _warn_redirect(message, category, filename, lineno, file=None, line=None):
warnings.showwarning = _warn_redirect
# Precedence: --fs-license-file, $FS_LICENSE, default_license
- # default_license = os.path.join(os.getenv("FREESURFER_HOME", ""), "license.txt")
if opts.fs_license_file is not None:
os.environ["FS_LICENSE"] = os.path.abspath(opts.fs_license_file)
- # elif "FS_LICENSE" not in os.environ and os.path.exists(default_license):
- # os.environ["FS_LICENSE"] = default_license
if not check_valid_fs_license():
raise RuntimeError(
From 92c2bbce5b61418f5365ecf6f96e9a0f214c80e7 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 12 Jan 2023 13:50:10 -0600
Subject: [PATCH 199/220] Update to FastSurfer v2.0.0
Uses the now recommended FastSurferVINN for better performance on sub-millimeter isotropic voxel size T1w
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 68dce053ec..bfc0ab8ee7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -55,7 +55,7 @@ RUN apt-get update && \
# git clone dev branch of FastSurfer
RUN cd /opt && mkdir /fastsurfer \
- && git clone -b v.1.1.2 https://github.com/Deep-MI/FastSurfer.git \
+ && git clone -b v.2.0.0 https://github.com/Deep-MI/FastSurfer.git \
&& cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
# Install conda
From 45d2b5465b8ead66aef230930bf69ab449037df4 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 12 Jan 2023 14:06:32 -0600
Subject: [PATCH 200/220] Fix typo in FastSurfer git clone
---
Dockerfile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index bfc0ab8ee7..7b83c49fec 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -53,9 +53,9 @@ RUN apt-get update && \
xvfb && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
-# git clone dev branch of FastSurfer
+# git clone stable branch of FastSurfer
RUN cd /opt && mkdir /fastsurfer \
- && git clone -b v.2.0.0 https://github.com/Deep-MI/FastSurfer.git \
+ && git clone -b v2.0.0 https://github.com/Deep-MI/FastSurfer.git \
&& cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
# Install conda
From e026c6dc24537cd68b5b4ebd0581c67a45c5d2a4 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 30 Jan 2023 12:46:03 -0600
Subject: [PATCH 201/220] Update FastSurfer version
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 7b83c49fec..8fa16cd057 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -55,7 +55,7 @@ RUN apt-get update && \
# git clone stable branch of FastSurfer
RUN cd /opt && mkdir /fastsurfer \
- && git clone -b v2.0.0 https://github.com/Deep-MI/FastSurfer.git \
+ && git clone -b v2.0.1 https://github.com/Deep-MI/FastSurfer.git \
&& cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
# Install conda
From e5fbb1c580a883b5b2ecb785f991b2989575a77f Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 30 Jan 2023 12:55:23 -0600
Subject: [PATCH 202/220] Update Dockerfile
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 8fa16cd057..f92d866e62 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -310,7 +310,7 @@ COPY . /src/smriprep
ARG VERSION
# Force static versioning within container
RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
- echo "include smriprep/${VERSION}" >> /src/smriprep/MANIFEST.in && \
+ echo "include smriprep/VERSION" >> /src/smriprep/MANIFEST.in && \
/opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]"
RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
From 22632588d26bcbc489416900f714df145d0968d5 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Mon, 30 Jan 2023 12:57:17 -0600
Subject: [PATCH 203/220] Remove unnecessary SetUpFreeSurfer.sh from bashrc
---
Dockerfile | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index f92d866e62..cf1e0cf49f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -294,8 +294,7 @@ ENV HOME="/home/smriprep" \
LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH"
RUN echo ". /opt/conda/etc/profile.d/conda.sh" >> $HOME/.bashrc && \
- echo "conda activate base" >> $HOME/.bashrc && \
- echo "$FREESURFER_HOME/SetUpFreeSurfer.sh" >> $HOME/.bashrc
+ echo "conda activate base" >> $HOME/.bashrc
# Precaching atlases
COPY scripts/fetch_templates.py fetch_templates.py
From 539fe07a9eeff8a89a4a256d6c649b80da5aa0e0 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 31 Jan 2023 13:12:25 -0600
Subject: [PATCH 204/220] Update FastSurfer version
---
docs/installation.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/installation.rst b/docs/installation.rst
index 2f8240f3a0..148241d396 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -150,4 +150,4 @@ the ``smriprep`` package:
- `C3D `_ (version 1.0.0)
- FreeSurfer_ (version 7.2.0)
- `bids-validator `_ (version 1.1.0)
-- FastSurfer_ (version 1.1.2)
+- FastSurfer_ (version 2.0.1)
From 5c4e68026d1d54e54b53a0e090b2902df5ebc064 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 15 Feb 2023 14:30:49 -0600
Subject: [PATCH 205/220] Restore FS_LICENSE generation from B64
From commit #5090a7d
---
.circleci/config.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index ee19ec4219..ebff48d5fc 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -191,7 +191,7 @@ jobs:
command: |
mkdir -p /tmp/fslicense
cd /tmp/fslicense
- echo "${FS_LICENSE_CONTENT}" | base64 -d | sh
+ echo "cHJpbnRmICJrcnp5c3p0b2YuZ29yZ29sZXdza2lAZ21haWwuY29tXG41MTcyXG4gKkN2dW12RVYzelRmZ1xuRlM1Si8yYzFhZ2c0RVxuIiA+IGxpY2Vuc2UudHh0Cg==" | base64 -d | sh
- persist_to_workspace:
root: /tmp
paths:
From 8f2f0cab9548e01ad7728fb76741aa286b7ad8a2 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 16 Feb 2023 10:15:27 -0600
Subject: [PATCH 206/220] Remove branch tags
---
smriprep/workflows/anatomical.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index 1b80e6548d..e0f8c2f851 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -584,8 +584,6 @@ def _check_img(img):
# Identical connections
applyrefined = pe.Node(fsl.ApplyMask(), name="applyrefined")
-<<<<<<< pcamach2-fastsurfer-patch
-=======
if t2w:
t2w_template_wf = init_anat_template_wf(
@@ -637,7 +635,7 @@ def _check_img(img):
# fmt:on
# fmt:off
->>>>>>> master
+
workflow.connect([
(anat_validate, surface_recon_wf, [('out_file', 'inputnode.t1w')]),
(brain_extraction_wf, surface_recon_wf, [
From 721ab2c6d3dbba45cc57d05381c8c509c2ff42b7 Mon Sep 17 00:00:00 2001
From: pcamach2
Date: Tue, 21 Feb 2023 15:24:49 -0600
Subject: [PATCH 207/220] Merge remote-tracking branch 'origin/master' into
pcamach2-fastsurfer-patch
---
.circleci/config.yml | 320 +++++----
.circleci/ds005_outputs.txt | 1 +
.circleci/ds005_run.sh | 3 +-
.circleci/ds054_run.sh | 3 +-
.dockerignore | 18 -
.github/workflows/pythonpackage.yml | 2 +-
.vscode/settings.json | 3 +
CHANGES.rst | 13 +
Dockerfile | 71 +-
...xclude.txt => freesurfer7.3.2-exclude.txt} | 617 +++++++++++++-----
setup.cfg | 2 +-
smriprep/data/io_spec.json | 6 +
smriprep/interfaces/workbench.py | 144 ++++
smriprep/utils/bids.py | 2 +-
smriprep/workflows/anatomical.py | 13 +-
smriprep/workflows/outputs.py | 19 +
smriprep/workflows/surfaces.py | 166 +++++
17 files changed, 1026 insertions(+), 377 deletions(-)
create mode 100644 .vscode/settings.json
rename docker/files/{freesurfer7.2-exclude.txt => freesurfer7.3.2-exclude.txt} (64%)
create mode 100644 smriprep/interfaces/workbench.py
diff --git a/.circleci/config.yml b/.circleci/config.yml
index ebff48d5fc..2dc7fd974e 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,3 +1,45 @@
+# reusable anchors
+_machine_defaults: &machine_defaults
+ environment:
+ TZ: "/usr/share/zoneinfo/America/Los_Angeles"
+ SCRATCH: "/scratch"
+ machine:
+ image: ubuntu-2204:current
+ docker_layer_caching: true
+ working_directory: /tmp/src/smriprep
+ resource_class: large
+
+_python_defaults: &python_defaults
+ docker:
+ - image: cimg/python:3.10.9
+ working_directory: /tmp/src/smriprep
+
+_docker_auth: &docker_auth
+ name: Docker authentication
+ command: |
+ if [[ -n $DOCKER_PAT ]]; then
+ echo "$DOCKER_PAT" | docker login -u $DOCKER_USER --password-stdin
+ fi
+
+_setup_docker_registry: &setup_docker_registry
+ name: Set up Docker registry
+ command: |
+ if [[ -f /tmp/images/registry.tar.gz ]]; then
+ echo "Loading saved registry image"
+ docker load < /tmp/images/registry.tar.gz
+ else
+ echo "Pulling registry image from DockerHub"
+ docker pull registry:2
+ fi
+ docker run -d -p 5000:5000 --restart=always --name=registry \
+ -v /tmp/docker:/var/lib/registry registry:2
+
+_pull_from_registry: &pull_from_registry
+ name: Pull and tag image from local registry
+ command: |
+ docker pull localhost:5000/smriprep
+ docker tag localhost:5000/smriprep nipreps/smriprep:latest
+
docs_deploy: &docs
docker:
- image: node:8.10.0
@@ -33,49 +75,39 @@ docs_deploy: &docs
command: gh-pages --dotfiles --message "doc(update) [skip ci]" --dist docs/_build/html
version: 2.1
+aliases:
+ - &src "/tmp/src/smriprep"
orbs:
docker: circleci/docker@2.1.4
jobs:
build:
- machine:
- image: ubuntu-2004:202107-02
- working_directory: /tmp/src/smriprep
- environment:
- TZ: "/usr/share/zoneinfo/America/Los_Angeles"
- SCRATCH: "/scratch"
+ <<: *machine_defaults
steps:
+ - checkout:
+ path: *src
- restore_cache:
keys:
- - build-v3-{{ .Branch }}-{{ epoch }}
- - build-v3-{{ .Branch }}-
- - build-v3-master-
+ - build-v0-{{ .Branch }}-{{ .Revision }}
+ - build-v0--{{ .Revision }}
+ - build-v0-{{ .Branch }}-
+ - build-v0-master-
+ - build-v0-
paths:
- /tmp/docker
- /tmp/images
- docker/install-docker-credential-helper
+ - run: *docker_auth
+ - run: *setup_docker_registry
- run:
- name: Docker authentication
+ name: Save docker registry
command: |
- if [[ -n $DOCKER_PAT ]]; then
- echo "$DOCKER_PAT" | docker login -u $DOCKER_USER --password-stdin
- fi
- - run:
- name: Set up Docker registry
- command: |
- if [[ -f /tmp/images/registry.tar.gz ]]; then
- echo "Loading saved registry image"
- docker load < /tmp/images/registry.tar.gz
- else
- echo "Pulling registry image from DockerHub"
- docker pull registry:2
+ if [[ ! -f /tmp/images/registry.tar.gz ]]; then
mkdir -p /tmp/images
docker save registry:2 | gzip > /tmp/images/registry.tar.gz
fi
- docker run -d -p 5000:5000 --restart=always --name=registry \
- -v /tmp/docker:/var/lib/registry registry:2
- run:
- name: Pull images
+ name: Pull Ubuntu/jammy image
command: |
set +e
docker pull localhost:5000/ubuntu
@@ -83,24 +115,33 @@ jobs:
set -e
if [[ "$success" = "0" ]]; then
echo "Pulling from local registry"
- docker tag localhost:5000/ubuntu ubuntu:xenial-20201030
- docker pull localhost:5000/smriprep
+ docker tag localhost:5000/ubuntu ubuntu:jammy-20221130
+ else
+ echo "Pulling from Docker Hub"
+ docker pull ubuntu:jammy-20221130
+ docker tag ubuntu:jammy-20221130 localhost:5000/ubuntu
+ docker push localhost:5000/ubuntu
+ fi
+ - run:
+ name: Pull sMRIPrep Docker image
+ command: |
+ set +e
+ docker pull localhost:5000/smriprep
+ success=$?
+ set -e
+ if [[ "$success" = "0" ]]; then
+ echo "Pulled from local registry"
docker tag localhost:5000/smriprep nipreps/smriprep:latest
docker tag localhost:5000/smriprep nipreps/smriprep
else
echo "Pulling from Docker Hub"
- docker pull ubuntu:xenial-20201030
- docker tag ubuntu:xenial-20201030 localhost:5000/ubuntu
- docker push localhost:5000/ubuntu
docker pull nipreps/smriprep:latest
fi
- - checkout
- run:
name: Build Docker image
no_output_timeout: 60m
command: |
- export PY3=$(pyenv versions | grep '3\.' |
- sed -e 's/.* 3\./3./' -e 's/ .*//')
+ export PY3=$( pyenv versions | awk '/^\* 3/ { print $2 }' )
pyenv local $PY3
# Get version, update files.
THISVERSION=$( python3 get_version.py )
@@ -120,6 +161,20 @@ jobs:
--build-arg VERSION="${CIRCLE_TAG:-$THISVERSION}" . \
&& e=0 && break || sleep 15
done && [ "$e" -eq "0" ]
+ - run:
+ name: Check Docker image
+ command: |
+ export PY3=$( pyenv versions | awk '/^\* 3/ { print $2 }' )
+ pyenv local $PY3
+ # Get version, update files.
+ THISVERSION=$( python3 get_version.py )
+ BUILT_VERSION=$( docker run --rm nipreps/smriprep:latest --version )
+ BUILT_VERSION=${BUILT_VERSION%$'\r'}
+ BUILT_VERSION=${BUILT_VERSION#*"smriprep v"}
+ echo "VERSION: \"$THISVERSION\""
+ echo "BUILT: \"$BUILT_VERSION\""
+ set -e
+ test "$BUILT_VERSION" = "$THISVERSION"
- run:
name: Docker push to local registry
@@ -133,7 +188,7 @@ jobs:
docker exec -it registry /bin/registry garbage-collect --delete-untagged \
/etc/docker/registry/config.yml
- save_cache:
- key: build-v3-{{ .Branch }}-{{ epoch }}
+ key: build-v0-{{ .Branch }}-{{ .Revision }}
paths:
- /tmp/docker
- /tmp/images
@@ -145,8 +200,7 @@ jobs:
- .force
get_data:
- docker:
- - image: circleci/python:3.8.5
+ <<: *python_defaults
working_directory: /home/circleci/data
steps:
- restore_cache:
@@ -239,49 +293,25 @@ jobs:
- /home/circleci/.local
test_wrapper:
- machine:
- image: ubuntu-2004:202107-02
+ <<: *machine_defaults
steps:
- attach_workspace:
at: /tmp
- restore_cache:
keys:
- - build-v3-{{ .Branch }}-{{ epoch }}
- - build-v3-{{ .Branch }}-
- - build-v3-master-
+ - build-v0-{{ .Branch }}-{{ .Revision }}
paths:
- /tmp/docker
- /tmp/images
- docker/install-docker-credential-helper
- - run:
- name: Docker authentication
- command: |
- if [[ -n $DOCKER_PAT ]]; then
- echo "$DOCKER_PAT" | docker login -u $DOCKER_USER --password-stdin
- fi
- - run:
- name: Set up Docker registry
- command: |
- if [[ -f /tmp/images/registry.tar.gz ]]; then
- echo "Loading saved registry image"
- docker load < /tmp/images/registry.tar.gz
- else
- echo "Pulling registry image from DockerHub"
- docker pull registry:2
- fi
- docker run -d -p 5000:5000 --restart=always --name=registry \
- -v /tmp/docker:/var/lib/registry registry:2
- - run:
- name: Pull images from local registry
- command: |
- docker pull localhost:5000/smriprep
- docker tag localhost:5000/smriprep nipreps/smriprep:latest
+ - run: *docker_auth
+ - run: *setup_docker_registry
+ - run: *pull_from_registry
- checkout
- run:
name: Test smriprep-wrapper (Python 2)
command: |
- export PY2=$(pyenv versions | grep '2\.' |
- sed -e 's/.* 2\./2./' -e 's/ .*//')
+ export PY2=$( pyenv versions | awk '/^\* 2/ { print $2 }' )
pyenv local $PY2
echo -n "Python version: "
python --version
@@ -294,8 +324,7 @@ jobs:
- run:
name: Test smriprep-wrapper (Python 3)
command: |
- export PY3=$(pyenv versions | grep '3\.' |
- sed -e 's/.* 3\./3./' -e 's/ .*//')
+ export PY3=$( pyenv versions | awk '/^\* 3/ { print $2 }' )
pyenv local $PY3
echo -n "Python version: "
python --version
@@ -306,8 +335,7 @@ jobs:
smriprep-docker -i nipreps/smriprep:latest --version
test_deploy_pypi:
- docker:
- - image: circleci/python:3.8.5
+ <<: *python_defaults
working_directory: /tmp/src/smriprep
steps:
- checkout
@@ -389,8 +417,7 @@ jobs:
path: /tmp/src/smriprep/wrapper/dist
ds005:
- machine:
- image: ubuntu-2004:202107-02
+ <<: *machine_defaults
working_directory: /tmp/ds005
environment:
- FS_LICENSE: /tmp/fslicense/license.txt
@@ -407,9 +434,7 @@ jobs:
fi
- restore_cache:
keys:
- - build-v3-{{ .Branch }}-{{ epoch }}
- - build-v3-{{ .Branch }}-
- - build-v3-master-
+ - build-v0-{{ .Branch }}-{{ .Revision }}
paths:
- /tmp/docker
- /tmp/images
@@ -420,36 +445,15 @@ jobs:
- run:
name: Install codecov
command: |
- pyenv install 3.8.5
- pyenv global 3.8.5
- python --version
- python -m pip install -U pip
- python -m pip install -U codecov
- pyenv rehash
+ export PY3=$( pyenv versions | awk '/^\* 3/ { print $2 }' )
+ pyenv local $PY3
+ pip install --upgrade pip
+ pip install --upgrade codecov
+ pyenv rehash
- docker/install-docker-credential-helper
- - run:
- name: Docker authentication
- command: |
- if [[ -n $DOCKER_PAT ]]; then
- echo "$DOCKER_PAT" | docker login -u $DOCKER_USER --password-stdin
- fi
- - run:
- name: Set up Docker registry
- command: |
- if [[ -f /tmp/images/registry.tar.gz ]]; then
- echo "Loading saved registry image"
- docker load < /tmp/images/registry.tar.gz
- else
- echo "Pulling registry image from DockerHub"
- docker pull registry:2
- fi
- docker run -d -p 5000:5000 --restart=always --name=registry \
- -v /tmp/docker:/var/lib/registry registry:2
- - run:
- name: Pull images from local registry
- command: |
- docker pull localhost:5000/smriprep
- docker tag localhost:5000/smriprep nipreps/smriprep:latest
+ - run: *docker_auth
+ - run: *setup_docker_registry
+ - run: *pull_from_registry
- restore_cache:
keys:
- ds005-anat-v9-{{ .Branch }}-{{ epoch }}
@@ -501,10 +505,11 @@ jobs:
name: Combine coverage and submit
working_directory: /tmp/src/smriprep
command: |
- pyenv local 3.8.5
- which python
- python --version
- codecov --file coverage.xml --flags ds005 -e CIRCLE_JOB
+ export PY3=$( pyenv versions | awk '/^\* 3/ { print $2 }' )
+ pyenv local $PY3
+ which python
+ python --version
+ codecov --file coverage.xml --flags ds005 -e CIRCLE_JOB
- run:
name: Clean-up temporary directory of reportlets and fsdir_run_XXX nodes
when: always
@@ -558,9 +563,7 @@ jobs:
path: /tmp/ds005/derivatives
destination: fasttrack
ds054:
- machine:
- image: ubuntu-2004:202107-02
- working_directory: /tmp/ds054
+ <<: *machine_defaults
environment:
- FS_LICENSE: /tmp/fslicense/license.txt
steps:
@@ -576,9 +579,7 @@ jobs:
fi
- restore_cache:
keys:
- - build-v3-{{ .Branch }}-{{ epoch }}
- - build-v3-{{ .Branch }}-
- - build-v3-master-
+ - build-v0-{{ .Branch }}-{{ .Revision }}
paths:
- /tmp/docker
- /tmp/images
@@ -589,36 +590,15 @@ jobs:
- run:
name: Install codecov
command: |
- pyenv install 3.8.5
- pyenv global 3.8.5
- python --version
- python -m pip install -U pip
- python -m pip install -U codecov
- pyenv rehash
+ export PY3=$( pyenv versions | awk '/^\* 3/ { print $2 }' )
+ pyenv local $PY3
+ pip install --upgrade pip
+ pip install --upgrade codecov
+ pyenv rehash
- docker/install-docker-credential-helper
- - run:
- name: Docker authentication
- command: |
- if [[ -n $DOCKER_PAT ]]; then
- echo "$DOCKER_PAT" | docker login -u $DOCKER_USER --password-stdin
- fi
- - run:
- name: Set up Docker registry
- command: |
- if [[ -f /tmp/images/registry.tar.gz ]]; then
- echo "Loading saved registry image"
- docker load < /tmp/images/registry.tar.gz
- else
- echo "Pulling registry image from DockerHub"
- docker pull registry:2
- fi
- docker run -d -p 5000:5000 --restart=always --name=registry \
- -v /tmp/docker:/var/lib/registry registry:2
- - run:
- name: Pull images from local registry
- command: |
- docker pull localhost:5000/smriprep
- docker tag localhost:5000/smriprep nipreps/smriprep:latest
+ - run: *docker_auth
+ - run: *setup_docker_registry
+ - run: *pull_from_registry
- restore_cache:
keys:
- ds054-anat-v9-{{ .Branch }}-{{ epoch }}
@@ -672,10 +652,11 @@ jobs:
name: Submit coverage
working_directory: /tmp/src/smriprep
command: |
- pyenv local 3.8.5
- which python
- python --version
- codecov --file coverage.xml --flags ds054 -e CIRCLE_JOB
+ export PY3=$( pyenv versions | awk '/^\* 3/ { print $2 }' )
+ pyenv local $PY3
+ which python
+ python --version
+ codecov --file coverage.xml --flags ds054 -e CIRCLE_JOB
- run:
name: Clean-up temporary directory of reportlets
when: always
@@ -720,8 +701,7 @@ jobs:
destination: fasttrack-derivatives
build_docs:
- docker:
- - image: circleci/python:3.8.5
+ <<: *python_defaults
working_directory: /tmp/gh-pages
environment:
- FSLOUTPUTTYPE: NIFTI
@@ -780,8 +760,7 @@ jobs:
destination: versioned
deploy_pypi:
- docker:
- - image: circleci/python:3.8.5
+ <<: *python_defaults
working_directory: /tmp/src/smriprep
steps:
- checkout
@@ -813,10 +792,16 @@ jobs:
twine upload dist/smriprep* wrapper/dist/smriprep*
deploy_docker:
- machine:
- image: ubuntu-2004:202107-02
- working_directory: /tmp/src/smriprep
+ <<: *machine_defaults
+ working_directory: *src
steps:
+ - run:
+ name: Check whether image should be deployed to Docker Hub
+ command: |
+ if [[ "$CIRCLE_PROJECT_USERNAME" != "nipreps" ]]; then
+ echo "Nothing to deploy for $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME."
+ circleci step halt
+ fi
- restore_cache:
keys:
- build-v3-{{ .Branch }}-{{ epoch }}
@@ -824,30 +809,17 @@ jobs:
- build-v3-master-
paths:
- /tmp/docker
- - run:
- name: Set-up a Docker registry
- command: |
- docker run -d -p 5000:5000 --restart=always --name=registry \
- -v /tmp/docker:/var/lib/registry registry:2
- - run:
- name: Pull images from local registry
- command: |
- docker pull localhost:5000/smriprep
- docker tag localhost:5000/smriprep nipreps/smriprep:latest
+ - /tmp/images
+ - docker/install-docker-credential-helper
+ - run: *docker_auth
+ - run: *setup_docker_registry
+ - run: *pull_from_registry
- run:
name: Deploy to Docker Hub
no_output_timeout: 40m
command: |
- if [[ -n "$DOCKER_PAT" ]]; then
- echo "$DOCKER_PAT" | docker login -u $DOCKER_USER --password-stdin
- docker tag nipreps/smriprep nipreps/smriprep:unstable
- docker push nipreps/smriprep:unstable
- if [[ -n "$CIRCLE_TAG" ]]; then
- docker push nipreps/smriprep:latest
- docker tag nipreps/smriprep nipreps/smriprep:$CIRCLE_TAG
- docker push nipreps/smriprep:$CIRCLE_TAG
- fi
- fi
+ docker tag nipreps/smriprep nipreps/smriprep:${CIRCLE_BRANCH#docker/}
+ docker push nipreps/smriprep:${CIRCLE_BRANCH#docker/}
deploy_docs_tag:
<<: *docs
diff --git a/.circleci/ds005_outputs.txt b/.circleci/ds005_outputs.txt
index d2ba64d3b7..2d2de7b970 100644
--- a/.circleci/ds005_outputs.txt
+++ b/.circleci/ds005_outputs.txt
@@ -16,6 +16,7 @@ smriprep/sub-01/anat/sub-01_desc-brain_mask.json
smriprep/sub-01/anat/sub-01_desc-brain_mask.nii.gz
smriprep/sub-01/anat/sub-01_desc-preproc_T1w.json
smriprep/sub-01/anat/sub-01_desc-preproc_T1w.nii.gz
+smriprep/sub-01/anat/sub-01_desc-ribbon_mask.nii.gz
smriprep/sub-01/anat/sub-01_dseg.nii.gz
smriprep/sub-01/anat/sub-01_from-fsnative_to-T1w_mode-image_xfm.txt
smriprep/sub-01/anat/sub-01_from-T1w_to-fsnative_mode-image_xfm.txt
diff --git a/.circleci/ds005_run.sh b/.circleci/ds005_run.sh
index 054ccd1668..864ea87f52 100644
--- a/.circleci/ds005_run.sh
+++ b/.circleci/ds005_run.sh
@@ -4,10 +4,11 @@ docker run -it -e FMRIPREP_DEV=1 -u $(id -u) \
-v /tmp/fslicense:/tmp/fslicense:ro \
-v /tmp/ds005:/tmp/ds005 \
-v /tmp/templateflow:/home/smriprep/.cache/templateflow \
+ -v /tmp/src/smriprep/docker/multiproc.coveragerc:/tmp/multiproc.coveragerc:ro \
-v /tmp/src/smriprep/.circleci/nipype.cfg:/home/smriprep/.nipype/nipype.cfg \
-e FMRIPREP_DEV=1 -u $(id -u) \
-e COVERAGE_FILE=/tmp/ds005/work/.coverage \
- -e COVERAGE_RCFILE=/src/smriprep/docker/multiproc.coveragerc \
+ -e COVERAGE_RCFILE=/tmp/multiproc.coveragerc \
--entrypoint=coverage \
nipreps/smriprep:latest \
run -m smriprep \
diff --git a/.circleci/ds054_run.sh b/.circleci/ds054_run.sh
index 0a74700fb0..b984a44b21 100644
--- a/.circleci/ds054_run.sh
+++ b/.circleci/ds054_run.sh
@@ -4,10 +4,11 @@ docker run --rm -it -e FMRIPREP_DEV=1 -u $(id -u) \
-v /tmp/fslicense:/tmp/fslicense:ro \
-v /tmp/ds054:/tmp/ds054 \
-v /tmp/templateflow:/home/smriprep/.cache/templateflow \
+ -v /tmp/src/smriprep/docker/multiproc.coveragerc:/tmp/multiproc.coveragerc:ro \
-v /tmp/src/smriprep/.circleci/nipype.cfg:/home/smriprep/.nipype/nipype.cfg \
-e FMRIPREP_DEV=1 -u $(id -u) \
-e COVERAGE_FILE=/tmp/ds054/work/.coverage \
- -e COVERAGE_RCFILE=/src/smriprep/docker/multiproc.coveragerc \
+ -e COVERAGE_RCFILE=/tmp/multiproc.coveragerc \
--entrypoint=coverage \
nipreps/smriprep:latest \
run -m smriprep \
diff --git a/.dockerignore b/.dockerignore
index 5abdfc1df8..5dbcd18830 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -15,30 +15,12 @@ smriprep.egg-info
pip-wheel-metadata/**/*
pip-wheel-metadata
-# housekeeping tools
-get_version.py
-update_changes.sh
-tox.ini
-
# pip installs
src/**/*
src/
-# git
-.gitignore
-.git/**/*
-.git
-
# other
work/**/*
work
out/**/*
out/
-
-# CI, etc.
-.circleci
-.circleci/**/*
-.zenodo.json
-.travis.yml
-.readthedocs.yml
-CONTRIBUTING.md
diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml
index a327504d94..66ecd24b87 100644
--- a/.github/workflows/pythonpackage.yml
+++ b/.github/workflows/pythonpackage.yml
@@ -66,7 +66,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: [3.7, 3.8, 3.9, "3.10"]
+ python-version: [3.8, 3.9, "3.10"]
install: [repo]
include:
- python-version: "3.10"
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000..5b94359216
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "esbonio.server.enabled": false
+}
\ No newline at end of file
diff --git a/CHANGES.rst b/CHANGES.rst
index 65e135c06d..62eed444ae 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,3 +1,16 @@
+0.11.0 (To be determined)
+=========================
+New feature release in the 0.11.x series.
+
+This series supports fMRIPrep 23.0.x.
+
+This release drops support for Python 3.7.
+
+* ENH: Add cortical ribbon workflow (#322)
+* ENH: Merge T2w images and coregister to T1w template (#319)
+* MAINT: Rotate CircleCI secrets and setup up org-level context (#315)
+* CI: Update build to match fMRIPrep (#323)
+
0.10.0 (November 30, 2022)
==========================
New feature release in the 0.10.x series.
diff --git a/Dockerfile b/Dockerfile
index cf1e0cf49f..ca552556c4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,7 +2,7 @@
#
# MIT License
#
-# Copyright (c) 2022 The NiPreps Developers
+# Copyright (c) 2023 The NiPreps Developers
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -22,10 +22,16 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-## Start with ubuntu base as in FastSurfer Docker image
-## https://github.com/Deep-MI/FastSurfer/blob/0749f38e656ed0da977c408b4383db88e1a8b563/Docker/Dockerfile
+FROM python:slim AS src
+RUN pip install build
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends git
+COPY . /src/fmriprep
+RUN python -m build /src/fmriprep
+
+# Use Ubuntu 22.04 LTS
+FROM ubuntu:jammy-20221130
-FROM ubuntu:focal-20210416
# Prepare environment
ENV DEBIAN_FRONTEND="noninteractive"
ENV LANG=C.UTF-8
@@ -45,6 +51,7 @@ RUN apt-get update && \
upx \
file \
git \
+ gnupg \
libtool \
lsb-release \
netbase \
@@ -65,9 +72,9 @@ RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/min
rm ~/miniconda.sh
# Installing freesurfer
-COPY docker/files/freesurfer7.2-exclude.txt /usr/local/etc/freesurfer7.2-exclude.txt
-RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/7.2.0/freesurfer-linux-ubuntu18_amd64-7.2.0.tar.gz \
- | tar zxv --no-same-owner -C /opt --exclude-from=/usr/local/etc/freesurfer7.2-exclude.txt
+COPY docker/files/freesurfer7.3.2-exclude.txt /usr/local/etc/freesurfer7.3.2-exclude.txt
+RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/7.3.2/freesurfer-linux-ubuntu22_amd64-7.3.2.tar.gz \
+ | tar zxv --no-same-owner -C /opt --exclude-from=/usr/local/etc/freesurfer7.3.2-exclude.txt
# Install required packages for freesurfer to run
RUN apt-get update && apt-get install -y --no-install-recommends \
@@ -192,17 +199,9 @@ ENV FSLDIR="/opt/fsl-6.0.5.1" \
FSLGECUDAQ="cuda.q" \
LD_LIBRARY_PATH="/opt/fsl-6.0.5.1/lib:$LD_LIBRARY_PATH"
-# Convert3D (neurodocker build)
-RUN echo "Downloading Convert3D ..." \
- && mkdir -p /opt/convert3d-1.0.0 \
- && curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz/download \
- | tar -xz -C /opt/convert3d-1.0.0 --strip-components 1 \
- --exclude "c3d-1.0.0-Linux-x86_64/lib" \
- --exclude "c3d-1.0.0-Linux-x86_64/share" \
- --exclude "c3d-1.0.0-Linux-x86_64/bin/c3d_gui"
-ENV C3DPATH="/opt/convert3d-1.0.0" \
- PATH="/opt/convert3d-1.0.0/bin:$PATH"
-
+# Configure PPA for libpng12
+RUN GNUPGHOME=/tmp gpg --keyserver hkps://keyserver.ubuntu.com --no-default-keyring --keyring /usr/share/keyrings/linuxuprising.gpg --recv 0xEA8CACC073C3DB2A \
+ && echo "deb [signed-by=/usr/share/keyrings/linuxuprising.gpg] https://ppa.launchpadcontent.net/linuxuprising/libpng12/ubuntu jammy main" > /etc/apt/sources.list.d/linuxuprising.list
# AFNI latest (neurodocker build)
RUN apt-get update -qq \
&& apt-get install -y -q --no-install-recommends \
@@ -214,6 +213,7 @@ RUN apt-get update -qq \
libglw1-mesa \
libgomp1 \
libjpeg62 \
+ libpng12-0 \
libxm4 \
netpbm \
tcsh \
@@ -227,9 +227,6 @@ RUN apt-get update -qq \
&& curl -sSL --retry 5 -o /tmp/libxp6.deb http://mirrors.kernel.org/debian/pool/main/libx/libxp/libxp6_1.0.2-2_amd64.deb \
&& dpkg -i /tmp/libxp6.deb \
&& rm /tmp/libxp6.deb \
- && curl -sSL --retry 5 -o /tmp/libpng.deb http://snapshot.debian.org/archive/debian-security/20160113T213056Z/pool/updates/main/libp/libpng/libpng12-0_1.2.49-1%2Bdeb7u2_amd64.deb \
- && dpkg -i /tmp/libpng.deb \
- && rm /tmp/libpng.deb \
&& apt-get install -f \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
@@ -267,8 +264,19 @@ WORKDIR $ANTSPATH
RUN curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \
| tar -xzC $ANTSPATH --strip-components 1
-# nipreps/miniconda:py38_1.4.1
-COPY --from=nipreps/miniconda@sha256:ebbff214e6c9dc50ccc6fdbe679df1ffcbceaa45b47a75d6e34e8a064ef178da /opt/conda /opt/conda
+WORKDIR /opt
+RUN curl -sSLO https://www.humanconnectome.org/storage/app/media/workbench/workbench-linux64-v1.5.0.zip && \
+ unzip workbench-linux64-v1.5.0.zip && \
+ rm workbench-linux64-v1.5.0.zip && \
+ rm -rf /opt/workbench/libs_linux64_software_opengl /opt/workbench/plugins_linux64 && \
+ strip --remove-section=.note.ABI-tag /opt/workbench/libs_linux64/libQt5Core.so.5
+ # ABI tags can interfere when running on Singularity
+
+ENV PATH="/opt/workbench/bin_linux64:$PATH" \
+ LD_LIBRARY_PATH="/opt/workbench/lib_linux64:$LD_LIBRARY_PATH"
+
+# nipreps/miniconda:py39_4.12.0rc0
+COPY --from=nipreps/miniconda@sha256:5aa4d2bb46e7e56fccf6e93ab3ff765add74e79f96ffa00449504b4869790cb9 /opt/conda /opt/conda
RUN ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
@@ -282,6 +290,15 @@ ENV PATH="/opt/conda/bin:$PATH" \
LC_ALL="C.UTF-8" \
PYTHONNOUSERSITE=1
+RUN conda install -y -n base \
+ -c anaconda \
+ -c conda-forge \
+ convert3d=1.3.0 \
+ && sync \
+ && conda clean -afy; sync \
+ && rm -rf ~/.conda ~/.cache/pip/*; sync \
+ && ldconfig
+
# Unless otherwise specified each process should only use one thread - nipype
# will handle parallelization
ENV MKL_NUM_THREADS=1 \
@@ -305,12 +322,8 @@ RUN /opt/conda/bin/python fetch_templates.py && \
find $HOME/.cache/templateflow -type f -exec chmod go=u {} +
# Installing sMRIPREP
-COPY . /src/smriprep
-ARG VERSION
-# Force static versioning within container
-RUN echo "${VERSION}" > /src/smriprep/smriprep/VERSION && \
- echo "include smriprep/VERSION" >> /src/smriprep/MANIFEST.in && \
- /opt/conda/bin/python -m pip install --no-cache-dir "/src/smriprep[all]"
+COPY --from=src /src/fmriprep/dist/*.whl .
+RUN /opt/conda/bin/python -m pip install --no-cache-dir $( ls *.whl )[all]
RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
diff --git a/docker/files/freesurfer7.2-exclude.txt b/docker/files/freesurfer7.3.2-exclude.txt
similarity index 64%
rename from docker/files/freesurfer7.2-exclude.txt
rename to docker/files/freesurfer7.3.2-exclude.txt
index 87aa246352..65a2524119 100644
--- a/docker/files/freesurfer7.2-exclude.txt
+++ b/docker/files/freesurfer7.3.2-exclude.txt
@@ -1,3 +1,4 @@
+freesurfer/average/3T18yoSchwartzReactN32_as_orig.4dfp.hdr
freesurfer/average/3T18yoSchwartzReactN32_as_orig.4dfp.ifh
freesurfer/average/3T18yoSchwartzReactN32_as_orig.4dfp.img
freesurfer/average/3T18yoSchwartzReactN32_as_orig.4dfp.img.rec
@@ -12,26 +13,63 @@ freesurfer/average/711-2B_as_mni_average_305_mask.4dfp.img.rec
freesurfer/average/711-2C_as_mni_average_305.4dfp.hdr
freesurfer/average/711-2C_as_mni_average_305.4dfp.img.rec
freesurfer/average/711-2C_as_mni_average_305.4dfp.mat
-freesurfer/average/RB_all_2008-03-26.mni152.2mm.lta
-freesurfer/average/RB_all_2016-05-10.vc700.gca
-freesurfer/average/RB_all_2019_10_25.talxfm.mni305.gca
-freesurfer/average/lh.DKTatlas40.gcs
-freesurfer/average/lh.atlas2002_simple.gcs
-freesurfer/average/lh.average.tif
+freesurfer/average/aseg+spmhead+vermis+pons.ixi.gca
freesurfer/average/BrainstemSS
-freesurfer/average/Yeo_Brainmap_MNI152
-freesurfer/average/samseg
freesurfer/average/Buckner_JNeurophysiol11_MNI152
-freesurfer/average/Yeo_JNeurophysiol11_MNI152
freesurfer/average/Choi_JNeurophysiol12_MNI152
-freesurfer/average/mult-comp-cor
+freesurfer/average/colortable_desikan_killiany.txt
+freesurfer/average/face.gca
freesurfer/average/HippoSF
+freesurfer/average/label_scales.dat
+freesurfer/average/lh.atlas2002_simple.gcs
+freesurfer/average/lh.atlas2005_simple.gcs
+freesurfer/average/lh.average.curvature.filled.buckner40.tif
+freesurfer/average/lh.average.CURVATURE.tif
+freesurfer/average/lh.average.tif
+freesurfer/average/lh.curvature.buckner40.filled.desikan_killiany.2010-03-25.gcs
+freesurfer/average/lh.destrieux.simple.2009-07-29.gcs
+freesurfer/average/lh.DKTaparc.atlas.acfb40.noaparc.i12.2020-05-13.gcs
+freesurfer/average/lh.DKTatlas100.gcs
+freesurfer/average/lh.DKTatlas40.gcs
+freesurfer/average/lh_trans_toSulc.gcs
+freesurfer/average/mideface-atlas
+freesurfer/average/mni152.mni305.cor.subfov1.dat
+freesurfer/average/mni152.mni305.cor.subfov2.dat
+freesurfer/average/mni152.register.dat
+freesurfer/average/mni305.cor.readme
+freesurfer/average/mni305.cor.subfov1.mgz
+freesurfer/average/mni305.cor.subfov1.reg
+freesurfer/average/mni305.cor.subfov2.mgz
+freesurfer/average/mni305.cor.subfov2.reg
+freesurfer/average/mni305.mask.cor.mgz
+freesurfer/average/mni_average_305.4dfp.hdr
+freesurfer/average/mni_average_305.4dfp.ifh
+freesurfer/average/mni_average_305.4dfp.img
+freesurfer/average/mni_average_305.4dfp.img.rec
+freesurfer/average/mult-comp-cor
+freesurfer/average/pons.mni152.2mm.mgz
+freesurfer/average/RB_all_2008-03-26.mni152.2mm.lta
+freesurfer/average/RB_all_2016-05-10.vc700.gca
+freesurfer/average/RB_all_2019_10_25.talxfm.mni305.gca
freesurfer/average/RB_all_withskull_2016-05-10.vc700.gca
freesurfer/average/RB_all_withskull_2019_10_22.talxfm.mni305.gca
+freesurfer/average/rh.atlas2002_simple.gcs
+freesurfer/average/rh.atlas2005_simple.gcs
+freesurfer/average/rh.average.curvature.filled.buckner40.tif
+freesurfer/average/rh.average.CURVATURE.tif
+freesurfer/average/rh.average.tif
+freesurfer/average/rh.curvature.buckner40.filled.desikan_killiany.2010-03-25.gcs
+freesurfer/average/rh.destrieux.simple.2009-07-29.gcs
+freesurfer/average/rh.DKTaparc.atlas.acfb40.noaparc.i12.2020-05-13.gcs
+freesurfer/average/rh.DKTatlas100.gcs
+freesurfer/average/rh.DKTatlas40.gcs
+freesurfer/average/rh_trans_toSulc.gcs
freesurfer/average/RLB700_atlas_as_orig.4dfp.hdr
freesurfer/average/RLB700_atlas_as_orig.4dfp.ifh
freesurfer/average/RLB700_atlas_as_orig.4dfp.img
freesurfer/average/RLB700_atlas_as_orig.4dfp.img.rec
+freesurfer/average/samseg
+freesurfer/average/surf
freesurfer/average/SVIP_Adult_Comp_N24_as_orig.4dfp.hdr
freesurfer/average/SVIP_Adult_Comp_N24_as_orig.4dfp.ifh
freesurfer/average/SVIP_Adult_Comp_N24_as_orig.4dfp.img
@@ -60,47 +98,45 @@ freesurfer/average/SVIP_Young_Patient_N12_as_orig.4dfp.hdr
freesurfer/average/SVIP_Young_Patient_N12_as_orig.4dfp.ifh
freesurfer/average/SVIP_Young_Patient_N12_as_orig.4dfp.img
freesurfer/average/SVIP_Young_Patient_N12_as_orig.4dfp.img.rec
-freesurfer/average/aseg+spmhead+vermis+pons.ixi.gca
-freesurfer/average/face.gca
-freesurfer/average/label_scales.dat
-freesurfer/average/lh.DKTaparc.atlas.acfb40.noaparc.i12.2020-05-13.gcs
-freesurfer/average/lh.DKTatlas100.gcs
-freesurfer/average/lh_trans_toSulc.gcs
-freesurfer/average/ThalamicNuclei
-freesurfer/average/lh.atlas2005_simple.gcs
-freesurfer/average/mni152.mni305.cor.subfov1.dat
-freesurfer/average/mni152.mni305.cor.subfov2.dat
-freesurfer/average/mni152.register.dat
-freesurfer/average/mni305.cor.readme
-freesurfer/average/mni305.cor.subfov1.mgz
-freesurfer/average/mni305.cor.subfov1.reg
-freesurfer/average/mni305.cor.subfov2.mgz
-freesurfer/average/mni305.cor.subfov2.reg
-freesurfer/average/mni305.mask.cor.mgz
-freesurfer/average/mni_average_305.4dfp.hdr
-freesurfer/average/mni_average_305.4dfp.ifh
-freesurfer/average/mni_average_305.4dfp.img
-freesurfer/average/mni_average_305.4dfp.img.rec
-freesurfer/average/pons.mni152.2mm.mgz
-freesurfer/average/rh.DKTaparc.atlas.acfb40.noaparc.i12.2020-05-13.gcs
-freesurfer/average/rh.DKTatlas100.gcs
-freesurfer/average/rh.DKTatlas40.gcs
-freesurfer/average/rh.atlas2002_simple.gcs
-freesurfer/average/rh.atlas2005_simple.gcs
-freesurfer/average/rh.average.CURVATURE.tif
-freesurfer/average/rh.average.curvature.filled.buckner40.tif
-freesurfer/average/rh.average.tif
-freesurfer/average/rh.curvature.buckner40.filled.desikan_killiany.2010-03-25.gcs
-freesurfer/average/rh.destrieux.simple.2009-07-29.gcs
-freesurfer/average/rh_trans_toSulc.gcs
freesurfer/average/talairach_mixed_with_skull.gca
+freesurfer/average/ThalamicNuclei
freesurfer/average/tissue_parms.txt
freesurfer/average/wmsa_new_eesmith.gca
-freesurfer/average/3T18yoSchwartzReactN32_as_orig.4dfp.hdr
-freesurfer/average/lh.average.CURVATURE.tif
-freesurfer/average/lh.average.curvature.filled.buckner40.tif
-freesurfer/average/lh.curvature.buckner40.filled.desikan_killiany.2010-03-25.gcs
-freesurfer/average/lh.destrieux.simple.2009-07-29.gcs
+freesurfer/average/Yeo_Brainmap_MNI152
+freesurfer/average/Yeo_JNeurophysiol11_MNI152
+freesurfer/bin/3dvolreg.afni
+freesurfer/bin/4dfptoanalyze
+freesurfer/bin/anatomiCutsUtils
+freesurfer/bin/annot2std
+freesurfer/bin/aparc2feat
+freesurfer/bin/aparcstats2table
+freesurfer/bin/aparc_stats_aseg
+freesurfer/bin/aparcstatsdiff
+freesurfer/bin/apas2aseg
+freesurfer/bin/applyMorph
+freesurfer/bin/aseg2feat
+freesurfer/bin/asegstats2table
+freesurfer/bin/asegstatsdiff
+freesurfer/bin/bblabel
+freesurfer/bin/bbmask
+freesurfer/bin/bedpostx_mgh
+freesurfer/bin/beta2sxa
+freesurfer/bin/bet.fsl
+freesurfer/bin/biasfield
+freesurfer/bin/bmedits2surf
+freesurfer/bin/brec
+freesurfer/bin/brec.awk
+freesurfer/bin/browse-minc-header.tcl
+freesurfer/bin/bugr
+freesurfer/bin/build_desikan_killiany_gcs.csh
+freesurfer/bin/cblumwmgyri
+freesurfer/bin/checkMCR.sh
+freesurfer/bin/check_recons.sh
+freesurfer/bin/check_siemens_dir
+freesurfer/bin/check_subject
+freesurfer/bin/clear_fs_env.csh
+freesurfer/bin/compute_interrater_variability.csh
+freesurfer/bin/compute_label_vals.csh
freesurfer/bin/compute_label_volumes.csh
freesurfer/bin/connectgraph
freesurfer/bin/cor_to_minc
@@ -114,8 +150,8 @@ freesurfer/bin/dcmsplit
freesurfer/bin/dcmunpack
freesurfer/bin/dicom-rename
freesurfer/bin/diffusionUtils
-freesurfer/bin/dmri_AnatomiCuts
freesurfer/bin/dmri_ac.sh
+freesurfer/bin/dmri_AnatomiCuts
freesurfer/bin/dmri_bset
freesurfer/bin/dmri_coloredFA
freesurfer/bin/dmri_extractSurfaceMeasurements
@@ -129,6 +165,10 @@ freesurfer/bin/dmri_neighboringRegions
freesurfer/bin/dmri_paths
freesurfer/bin/dmri_pathstats
freesurfer/bin/dmri_projectEndPoints
+freesurfer/bin/dmrirc.example
+freesurfer/bin/dmrirc.long.example
+freesurfer/bin/dmrirc.long.multiscan.example
+freesurfer/bin/dmrirc.multiscan.example
freesurfer/bin/dmri_saveHistograms
freesurfer/bin/dmri_spline
freesurfer/bin/dmri_stats_ac
@@ -137,10 +177,6 @@ freesurfer/bin/dmri_train
freesurfer/bin/dmri_trk2trk
freesurfer/bin/dmri_violinPlots
freesurfer/bin/dmri_vox2vox
-freesurfer/bin/dmrirc.example
-freesurfer/bin/dmrirc.long.example
-freesurfer/bin/dmrirc.long.multiscan.example
-freesurfer/bin/dmrirc.multiscan.example
freesurfer/bin/dt_recon
freesurfer/bin/epidewarp.fsl
freesurfer/bin/exportGcam
@@ -148,43 +184,43 @@ freesurfer/bin/feat2segstats
freesurfer/bin/feat2surf
freesurfer/bin/findsession
freesurfer/bin/fix_subject
-freesurfer/bin/fix_subject-lh
-freesurfer/bin/fix_subject-rh
freesurfer/bin/fix_subject_corrected
freesurfer/bin/fix_subject_corrected-lh
freesurfer/bin/fix_subject_corrected-rh
+freesurfer/bin/fix_subject-lh
freesurfer/bin/fix_subject_on_seychelles
+freesurfer/bin/fix_subject-rh
freesurfer/bin/fixup_mni_paths
freesurfer/bin/flip_4dfp
-freesurfer/bin/flirt.newdefault.20080811.sch
freesurfer/bin/flirt.fsl
+freesurfer/bin/flirt.newdefault.20080811.sch
freesurfer/bin/fname2ext
freesurfer/bin/fname2stem
freesurfer/bin/freesurfer
freesurfer/bin/freeview
-freesurfer/bin/fsPrintHelp
-freesurfer/bin/fs_install_mcr
-freesurfer/bin/fs_lib_check
-freesurfer/bin/fs_run_from_mcr
-freesurfer/bin/fs_spmreg.glnxa64
-freesurfer/bin/fs_temp_file
-freesurfer/bin/fs_tutorial_data
-freesurfer/bin/fs_update
freesurfer/bin/fscalc
freesurfer/bin/fscalc.fsl
freesurfer/bin/fsdcmdecompress
freesurfer/bin/fsfget
freesurfer/bin/fsfirst.fsl
+freesurfer/bin/fs_install_mcr
freesurfer/bin/fsl.5.0.2.xyztrans.sch
+freesurfer/bin/fs_lib_check
freesurfer/bin/fsl_label2voxel
-freesurfer/bin/fsl_rigid_register
-freesurfer/bin/fsl_sub_mgh
freesurfer/bin/fslmaths.fsl
freesurfer/bin/fslorient.fsl
+freesurfer/bin/fslregister
+freesurfer/bin/fsl_rigid_register
+freesurfer/bin/fsl_sub_mgh
+freesurfer/bin/fslswapdim.fsl
freesurfer/bin/fspalm
-freesurfer/bin/fsr-checkxopts
+freesurfer/bin/fsPrintHelp
freesurfer/bin/fsr-coreg
freesurfer/bin/fsr-import
+freesurfer/bin/fs_run_from_mcr
+freesurfer/bin/fs_spmreg.glnxa64
+freesurfer/bin/fs_tutorial_data
+freesurfer/bin/fs_update
freesurfer/bin/fsvglrun
freesurfer/bin/fvcompare
freesurfer/bin/gca-apply
@@ -195,7 +231,6 @@ freesurfer/bin/gcatrainskull
freesurfer/bin/gdcmconv.fs
freesurfer/bin/gems_compute_binary_atlas_probs
freesurfer/bin/get_label_thickness
-freesurfer/bin/grad_unwarp
freesurfer/bin/groupstats
freesurfer/bin/groupstatsdiff
freesurfer/bin/gtmseg
@@ -211,12 +246,12 @@ freesurfer/bin/histo_synthesize
freesurfer/bin/ico_supersample
freesurfer/bin/id.xfm
freesurfer/bin/inflate_subject
-freesurfer/bin/inflate_subject-lh
-freesurfer/bin/inflate_subject-rh
freesurfer/bin/inflate_subject3
+freesurfer/bin/inflate_subject-lh
freesurfer/bin/inflate_subject_new
freesurfer/bin/inflate_subject_new-lh
freesurfer/bin/inflate_subject_new-rh
+freesurfer/bin/inflate_subject-rh
freesurfer/bin/inflate_subject_sc
freesurfer/bin/irepifitvol
freesurfer/bin/irepifitvol.glnx64
@@ -224,6 +259,7 @@ freesurfer/bin/isanalyze
freesurfer/bin/isnifti
freesurfer/bin/isolate_labels.csh
freesurfer/bin/isolate_labels_keeporigval.csh
+freesurfer/bin/is-surface
freesurfer/bin/jkgcatrain
freesurfer/bin/label2flat
freesurfer/bin/label2patch
@@ -231,16 +267,17 @@ freesurfer/bin/label_area
freesurfer/bin/label_border
freesurfer/bin/label_child
freesurfer/bin/label_elderly_subject
+freesurfer/bin/labels_disjoint
+freesurfer/bin/labels_intersect
freesurfer/bin/label_subject
freesurfer/bin/label_subject_flash
freesurfer/bin/label_subject_mixed
-freesurfer/bin/labels_disjoint
-freesurfer/bin/labels_intersect
freesurfer/bin/labels_union
freesurfer/bin/list_otl_labels
freesurfer/bin/listsubj
freesurfer/bin/long_create_base_sigma
freesurfer/bin/long_create_orig
+freesurfer/bin/longmc
freesurfer/bin/long_mris_slopes
freesurfer/bin/long_qdec_table
freesurfer/bin/long_stats_combine
@@ -248,10 +285,8 @@ freesurfer/bin/long_stats_slopes
freesurfer/bin/long_stats_tps
freesurfer/bin/long_submit_jobs
freesurfer/bin/long_submit_postproc
-freesurfer/bin/longmc
freesurfer/bin/lpcregister
freesurfer/bin/lta_diff
-freesurfer/bin/make-segvol-table
freesurfer/bin/make_average_subcort
freesurfer/bin/make_average_subject
freesurfer/bin/make_average_surface
@@ -260,12 +295,13 @@ freesurfer/bin/make_cortex_label
freesurfer/bin/make_exvivo_filled
freesurfer/bin/make_folding_atlas
freesurfer/bin/make_hemi_mask
+freesurfer/bin/make-segvol-table
freesurfer/bin/make_symmetric
freesurfer/bin/make_upright
freesurfer/bin/makevol
freesurfer/bin/meanval
-freesurfer/bin/merge_stats_tables
freesurfer/bin/mergeseg
+freesurfer/bin/merge_stats_tables
freesurfer/bin/minc2seqinfo
freesurfer/bin/mkheadsurf
freesurfer/bin/mkima_index.tcl
@@ -280,14 +316,297 @@ freesurfer/bin/morph_rgb-lh
freesurfer/bin/morph_rgb-rh
freesurfer/bin/morph_subject
freesurfer/bin/morph_subject-lh
-freesurfer/bin/morph_subject-rh
freesurfer/bin/morph_subject_on_seychelles
+freesurfer/bin/morph_subject-rh
freesurfer/bin/morph_tables-lh
freesurfer/bin/morph_tables-rh
+freesurfer/bin/mri_align_long.csh
+freesurfer/bin/mri_aparc2wmseg
+freesurfer/bin/mri_apply_autoencoder
+freesurfer/bin/mri_apply_bias
+freesurfer/bin/mri_apply_inu_correction
+freesurfer/bin/mri_aseg_edit_reclassify
+freesurfer/bin/mri_aseg_edit_train
+freesurfer/bin/mri_auto_fill
+freesurfer/bin/mri_average
+freesurfer/bin/mri_bc_sc_bias_correct
+freesurfer/bin/mri_brain_volume
+freesurfer/bin/mri_build_priors
+freesurfer/bin/mri_cal_renormalize_gca
+freesurfer/bin/mri_ca_tissue_parms
+freesurfer/bin/mri_ca_train
+freesurfer/bin/mri_cht2p
+freesurfer/bin/mri_classify
+freesurfer/bin/mri_cnr
+freesurfer/bin/mri_compute_bias
+freesurfer/bin/mri_compute_change_map
+freesurfer/bin/mri_compute_distances
+freesurfer/bin/mri_compute_layer_fractions
+freesurfer/bin/mri_compute_structure_transforms
+freesurfer/bin/mri_compute_volume_fractions
+freesurfer/bin/mri_compute_volume_intensities
+freesurfer/bin/mri_concatenate_gcam
+freesurfer/bin/mri_convert_mdh
+freesurfer/bin/mri_copy_params
+freesurfer/bin/mri_copy_values
+freesurfer/bin/mri_cor2label
+freesurfer/bin/mri_correct_segmentations
+freesurfer/bin/mri_create_t2combined
+freesurfer/bin/mri_create_tests
+freesurfer/bin/mri_cvs_check
+freesurfer/bin/mri_cvs_data_copy
+freesurfer/bin/mri_cvs_register
+freesurfer/bin/mri_cvs_requiredfiles.txt
+freesurfer/bin/mri_dct_align
+freesurfer/bin/mri_dct_align_binary
+freesurfer/bin/mri_distance_transform
+freesurfer/bin/mri_dist_surf_label
+freesurfer/bin/mri_divide_segmentation
+freesurfer/bin/mri_edit_segmentation
+freesurfer/bin/mri_edit_segmentation_with_surfaces
+freesurfer/bin/mri_elastic_energy
+freesurfer/bin/mri_estimate_tissue_parms
+freesurfer/bin/mri_evaluate_morph
+freesurfer/bin/mri_extract
+freesurfer/bin/mri_extract_conditions
+freesurfer/bin/mri_extract_fcd_features
+freesurfer/bin/mri_extract_label
+freesurfer/bin/mri_extract_largest_CC
+freesurfer/bin/mri_fcili
+freesurfer/bin/mri_fdr
+freesurfer/bin/mri_fieldsign
+freesurfer/bin/mri_fit_bias
+freesurfer/bin/mri_fslmat_to_lta
+freesurfer/bin/mri-func2sph
+freesurfer/bin/mri-funcvits
+freesurfer/bin/mri_fuse_intensity_images
+freesurfer/bin/mri_gca_ambiguous
+freesurfer/bin/mri_gcab_train
+freesurfer/bin/mri_gdfglm
+freesurfer/bin/mri_glmfit
+freesurfer/bin/mri_glmfit-sim
+freesurfer/bin/mri_gradient_info
+freesurfer/bin/mri_gtmpvc
+freesurfer/bin/mri_gtmseg
+freesurfer/bin/mri_hausdorff_dist
+freesurfer/bin/mri_head
+freesurfer/bin/mri_hires_register
+freesurfer/bin/mri_histo_eq
+freesurfer/bin/mri_histo_normalize
+freesurfer/bin/mri_ibmc
+freesurfer/bin/mri_interpolate
+freesurfer/bin/mri_jacobian
+freesurfer/bin/mri_joint_density
+freesurfer/bin/mri_label_accuracy
+freesurfer/bin/mri_label_histo
+freesurfer/bin/mri_label_vals
+freesurfer/bin/mri_label_volume
+freesurfer/bin/mri_linear_align
+freesurfer/bin/mri_linear_align_binary
+freesurfer/bin/mri_linear_register
+freesurfer/bin/mri_long_normalize
+freesurfer/bin/mri_make_bem_surfaces
+freesurfer/bin/mri_make_density_map
+freesurfer/bin/mri_make_labels
+freesurfer/bin/mri_make_register
+freesurfer/bin/mri_make_template
+freesurfer/bin/mri_map_cpdat
+freesurfer/bin/mri_maps2csd
+freesurfer/bin/mri_mark_temporal_lobe
+freesurfer/bin/mri_mc
+freesurfer/bin/mri_mcsim
+freesurfer/bin/mri_mergelabels
+freesurfer/bin/mri_mi
+freesurfer/bin/mri_modify
+freesurfer/bin/mri_morphology
+freesurfer/bin/mri_mosaic
+freesurfer/bin/mri_motion_correct
+freesurfer/bin/mri_motion_correct2
+freesurfer/bin/mri_ms_EM
+freesurfer/bin/mri_ms_EM_with_atlas
+freesurfer/bin/mri_ms_fitparms
+freesurfer/bin/mri_ms_LDA
+freesurfer/bin/mri_multiscale_segment
+freesurfer/bin/mri_multispectral_segment
+freesurfer/bin/mri_nl_align
+freesurfer/bin/mri_nl_align_binary
+freesurfer/bin/mri_nlfilter
+freesurfer/bin/mri_paint
+freesurfer/bin/mri_parselabel
+freesurfer/bin/mri_parse_sdcmdir
+freesurfer/bin/mri_partial_ribbon
+freesurfer/bin/mri_path2label
+freesurfer/bin/mri_polv
+freesurfer/bin/mri_probedicom
+freesurfer/bin/mri_probe_ima
+freesurfer/bin/mri_reduce
+freesurfer/bin/mri_refine_seg
+freesurfer/bin/mri_register
+freesurfer/bin/mri_reorient_LR.csh
+freesurfer/bin/mri_rf_label
+freesurfer/bin/mri_rf_long_label
+freesurfer/bin/mri_rf_long_train
+freesurfer/bin/mri_rf_train
+freesurfer/bin/mri_ribbon
+freesurfer/bin/mri_rigid_register
+freesurfer/bin/mris2rgb
+freesurfer/bin/mris_AA_shrinkwrap
+freesurfer/bin/mris_add_template
+freesurfer/bin/mris_annot_diff
+freesurfer/bin/mris_annot_to_segmentation
+freesurfer/bin/mris_aseg_distance
+freesurfer/bin/mris_average_curvature
+freesurfer/bin/mris_average_parcellation
+freesurfer/bin/mris_BA_segment
+freesurfer/bin/mri_sbbr
+freesurfer/bin/mris_ca_deform
+freesurfer/bin/mris_ca_train
+freesurfer/bin/mris_classify_thickness
+freesurfer/bin/mris_compute_acorr
+freesurfer/bin/mris_compute_layer_intensities
+freesurfer/bin/mris_compute_lgi
+freesurfer/bin/mris_compute_optimal_kernel
+freesurfer/bin/mris_compute_overlap
+freesurfer/bin/mris_compute_parc_overlap
+freesurfer/bin/mris_compute_volume_fractions
+freesurfer/bin/mris_congeal
+freesurfer/bin/mris_copy_header
+freesurfer/bin/mris_curvature2image
+freesurfer/bin/mris_deform
+freesurfer/bin/mris_density
+freesurfer/bin/mris_distance_map
+freesurfer/bin/mris_distance_to_label
+freesurfer/bin/mris_distance_transform
+freesurfer/bin/mri_segcentroids
+freesurfer/bin/mri_seghead
+freesurfer/bin/mri_segment_hypothalamic_subunits
+freesurfer/bin/mri_segment_tumor
+freesurfer/bin/mri_segment_wm_damage
+freesurfer/bin/mri_seg_overlap
+freesurfer/bin/mris_entropy
+freesurfer/bin/mris_errors
+freesurfer/bin/mris_extract_patches
+freesurfer/bin/mris_extract_values
+freesurfer/bin/mris_exvivo_surfaces
+freesurfer/bin/mris_fbirn_annot
+freesurfer/bin/mris_fill
+freesurfer/bin/mris_find_flat_regions
+freesurfer/bin/mris_flatten
+freesurfer/bin/mris_fwhm
+freesurfer/bin/mris_gradient
+freesurfer/bin/mris_hausdorff_dist
+freesurfer/bin/mris_image2vtk
+freesurfer/bin/mri_simulate_atrophy
+freesurfer/bin/mris_info
+freesurfer/bin/mris_init_global_tractography
+freesurfer/bin/mris_intensity_profile
+freesurfer/bin/mris_interpolate_warp
+freesurfer/bin/mris_label_area
+freesurfer/bin/mris_label_calc
+freesurfer/bin/mris_label_mode
+freesurfer/bin/mris_longitudinal_surfaces
+freesurfer/bin/mris_make_average_surface
+freesurfer/bin/mris_make_face_parcellation
+freesurfer/bin/mris_make_map_surfaces
+freesurfer/bin/mris_make_surfaces
+freesurfer/bin/mris_make_template
+freesurfer/bin/mris_map_cuts
+freesurfer/bin/mris_mef_surfaces
+freesurfer/bin/mris_merge_parcellations
+freesurfer/bin/mris_mesh_subdivide
+freesurfer/bin/mris_morph_stats
+freesurfer/bin/mris_ms_refine
+freesurfer/bin/mris_ms_surface_CNR
+freesurfer/bin/mris_multimodal
+freesurfer/bin/mris_multimodal_surface_placement
+freesurfer/bin/mris_multiscale_stats
+freesurfer/bin/mris_niters2fwhm
+freesurfer/bin/mris_nudge
+freesurfer/bin/mris_parcellate_connectivity
+freesurfer/bin/mri-sph2surf
+freesurfer/bin/mris_pmake
+freesurfer/bin/mris_preproc
+freesurfer/bin/mris_profileClustering
+freesurfer/bin/mrisp_write
+freesurfer/bin/mris_refine_surfaces
+freesurfer/bin/mris_register_label_map
+freesurfer/bin/mris_register_to_label
+freesurfer/bin/mris_register_to_volume
+freesurfer/bin/mris_remove_negative_vertices
+freesurfer/bin/mris_remove_variance
+freesurfer/bin/mris_resample
+freesurfer/bin/mris_rescale
+freesurfer/bin/mris_reverse
+freesurfer/bin/mris_rf_label
+freesurfer/bin/mris_rf_train
+freesurfer/bin/mris_rotate
+freesurfer/bin/mris_sample_label
+freesurfer/bin/mris_sample_parc
+freesurfer/bin/mris_seg2annot
+freesurfer/bin/mris_segment
+freesurfer/bin/mris_segmentation_stats
+freesurfer/bin/mris_segment_vals
+freesurfer/bin/mris_shrinkwrap
+freesurfer/bin/mris_simulate_atrophy
+freesurfer/bin/mris_smooth_intracortical
+freesurfer/bin/mris_surf2vtk
+freesurfer/bin/mris_surface_change
+freesurfer/bin/mris_surface_to_vol_distances
+freesurfer/bin/mris_svm_classify
+freesurfer/bin/mris_svm_train
+freesurfer/bin/mris_talairach
+freesurfer/bin/mris_thickness_comparison
+freesurfer/bin/mris_transform
+freesurfer/bin/mris_translate_annotation
+freesurfer/bin/mris_transmantle_dysplasia_paths
+freesurfer/bin/mri_strip_nonwhite
+freesurfer/bin/mri_strip_subject_info
+freesurfer/bin/mris_twoclass
+freesurfer/bin/mri_surfacemask
+freesurfer/bin/mris_volmask_novtk
+freesurfer/bin/mris_volmask_vtk
+freesurfer/bin/mris_volsmooth
+freesurfer/bin/mris_volume
+freesurfer/bin/mris_warp
+freesurfer/bin/mris_wm_volume
+freesurfer/bin/mris_w_to_curv
+freesurfer/bin/mri_synthesize
+freesurfer/bin/mri_synthstrip
+freesurfer/bin/mri_threshold
+freesurfer/bin/mri_topologycorrection
+freesurfer/bin/mri_train
+freesurfer/bin/mri_train_autoencoder
+freesurfer/bin/mri_transform
+freesurfer/bin/mri_transform_to_COR
+freesurfer/bin/mri_twoclass
+freesurfer/bin/mri_update_gca
+freesurfer/bin/mri_validate_skull_stripped
+freesurfer/bin/mri_vessel_segment
+freesurfer/bin/mri_vol2label
+freesurfer/bin/mri_vol2roi
+freesurfer/bin/mri_volcluster
+freesurfer/bin/mri_volsynth
+freesurfer/bin/mri_warp_convert
+freesurfer/bin/mri_wbc
+freesurfer/bin/mri_wmfilter
+freesurfer/bin/mri_xcorr
+freesurfer/bin/mri_xvolavg
+freesurfer/bin/mri_z2p
+freesurfer/bin/ms_refine_subject
+freesurfer/bin/nmovie_qt
+freesurfer/bin/oct_register_mosaic
+freesurfer/bin/oct_rf_train
+freesurfer/bin/oct_train
+freesurfer/bin/optseq2
+freesurfer/bin/orientLAS
+freesurfer/bin/parc_atlas_jackknife_test
+freesurfer/bin/plot_structure_stats.tcl
freesurfer/bin/polyorder
freesurfer/bin/predict_v1.sh
freesurfer/bin/print_unique_labels.csh
freesurfer/bin/progressbar.tcl
+freesurfer/bin/qatools.py
+freesurfer/bin/qdec
freesurfer/bin/qdec_glmfit
freesurfer/bin/qt.conf
freesurfer/bin/quantifyBrainstemStructures.sh
@@ -299,58 +618,74 @@ freesurfer/bin/rcbf-prep
freesurfer/bin/rebuild_gca_atlas.csh
freesurfer/bin/recon-all-exvivo
freesurfer/bin/recon-all.makefile
-freesurfer/bin/reg-feat2anat
-freesurfer/bin/reg-mni305.2mm
freesurfer/bin/regdat2xfm
-freesurfer/bin/register.csh
+freesurfer/bin/reg-feat2anat
freesurfer/bin/register_child
+freesurfer/bin/register.csh
freesurfer/bin/register_elderly_subject
freesurfer/bin/register_subject
freesurfer/bin/register_subject_flash
freesurfer/bin/register_subject_mixed
+freesurfer/bin/reg-mni305.2mm
freesurfer/bin/reinflate_subject
freesurfer/bin/reinflate_subject-lh
freesurfer/bin/reinflate_subject-rh
freesurfer/bin/remove_talairach
-freesurfer/bin/renormalize_T1_subject
freesurfer/bin/renormalize_subject
freesurfer/bin/renormalize_subject_keep_editting
+freesurfer/bin/renormalize_T1_subject
freesurfer/bin/repair_siemens_file
freesurfer/bin/reregister_subject_mixed
freesurfer/bin/rtview
+freesurfer/bin/run_mris_preproc
freesurfer/bin/run-qdec-glm
+freesurfer/bin/run_samseg_long
freesurfer/bin/run_SegmentSubfieldsT1Longitudinal.sh
freesurfer/bin/run_SegmentSubject.sh
-freesurfer/bin/run_SegmentThalamicNuclei.sh
-freesurfer/bin/run_mris_preproc
-freesurfer/bin/run_samseg_long
-freesurfer/bin/run_segmentSubjectT1T2_autoEstimateAlveusML.sh
freesurfer/bin/run_segmentSubjectT1_autoEstimateAlveusML.sh
+freesurfer/bin/run_segmentSubjectT1T2_autoEstimateAlveusML.sh
freesurfer/bin/run_segmentSubjectT2_autoEstimateAlveusML.sh
+freesurfer/bin/run_SegmentThalamicNuclei.sh
freesurfer/bin/samseg
-freesurfer/bin/samseg-long
freesurfer/bin/samseg2recon
+freesurfer/bin/samseg-long
freesurfer/bin/sbtiv
freesurfer/bin/seg2filled
freesurfer/bin/segmentBS.sh
-freesurfer/bin/segmentHA_T1.sh
freesurfer/bin/segmentHA_T1_long.sh
+freesurfer/bin/segmentHA_T1.sh
freesurfer/bin/segmentHA_T2.sh
-freesurfer/bin/segmentSubject
-freesurfer/bin/segmentSubjectT1T2_autoEstimateAlveusML
-freesurfer/bin/segmentSubjectT1_autoEstimateAlveusML
-freesurfer/bin/segmentSubjectT2_autoEstimateAlveusML
-freesurfer/bin/segmentThalamicNuclei.sh
freesurfer/bin/segment_monkey
+freesurfer/bin/SegmentSubfieldsT1Longitudinal
freesurfer/bin/segment_subject
+freesurfer/bin/segmentSubject
freesurfer/bin/segment_subject_notal
freesurfer/bin/segment_subject_notal2
freesurfer/bin/segment_subject_old_skull_strip
freesurfer/bin/segment_subject_sc
+freesurfer/bin/segmentSubjectT1_autoEstimateAlveusML
+freesurfer/bin/segmentSubjectT1T2_autoEstimateAlveusML
+freesurfer/bin/segmentSubjectT2_autoEstimateAlveusML
freesurfer/bin/segment_subject_talmgh
+freesurfer/bin/SegmentThalamicNuclei
+freesurfer/bin/segmentThalamicNuclei.sh
freesurfer/bin/segpons
freesurfer/bin/setlabelstat
freesurfer/bin/sfa2fieldsign
+freesurfer/bin/show_tal
+freesurfer/bin/skip_long_make_checks
+freesurfer/bin/slicedelay
+freesurfer/bin/slicetimer.fsl
+freesurfer/bin/sphere_subject
+freesurfer/bin/sphere_subject-lh
+freesurfer/bin/sphere_subject-rh
+freesurfer/bin/spherical_st
+freesurfer/bin/Spline3_test
+freesurfer/bin/spmmat2register
+freesurfer/bin/spmregister
+freesurfer/bin/spm_t_to_b
+freesurfer/bin/sratio
+freesurfer/bin/stat_normalize
freesurfer/bin/stattablediff
freesurfer/bin/stem2fname
freesurfer/bin/stim_polar
@@ -358,10 +693,12 @@ freesurfer/bin/streamlineFilter
freesurfer/bin/swi_process
freesurfer/bin/t4img_4dfp
freesurfer/bin/t4imgs_4dfp
-freesurfer/bin/tal_QC_AZS
-freesurfer/bin/tal_compare
freesurfer/bin/talairach2
freesurfer/bin/talairach_mgh
+freesurfer/bin/tal_compare
+freesurfer/bin/tal_QC_AZS
+freesurfer/bin/talsegprob
+freesurfer/bin/template
freesurfer/bin/testOrientationPlanesFromParcellation
freesurfer/bin/test_recon-all.csh
freesurfer/bin/test_tutorials.sh
@@ -379,12 +716,12 @@ freesurfer/bin/tractstats2table
freesurfer/bin/train-gcs-atlas
freesurfer/bin/tridec
freesurfer/bin/trk_tools
-freesurfer/bin/unpack_ima.tcl
freesurfer/bin/unpack_ima1.tcl
-freesurfer/bin/unpack_mnc.tcl
freesurfer/bin/unpackimadir
freesurfer/bin/unpackimadir2
+freesurfer/bin/unpack_ima.tcl
freesurfer/bin/unpackmincdir
+freesurfer/bin/unpack_mnc.tcl
freesurfer/bin/unpacksdcmdir
freesurfer/bin/usbtree
freesurfer/bin/vol2segavg
@@ -396,37 +733,15 @@ freesurfer/bin/wm-anat-snr
freesurfer/bin/xcerebralseg
freesurfer/bin/xcorr
freesurfer/bin/xfmrot
-freesurfer/bin/xhemi-tal
freesurfer/bin/xhemireg
+freesurfer/bin/xhemi-tal
freesurfer/bin/xsanatreg
freesurfer/bin/zero_lt_4dfp
-freesurfer/bin/3dvolreg.afni
-freesurfer/bin/4dfptoanalyze
-freesurfer/bin/SegmentSubfieldsT1Longitudinal
-freesurfer/bin/SegmentThalamicNuclei
-freesurfer/bin/Spline3_test
-freesurfer/bin/anatomiCutsUtils
-freesurfer/bin/bedpostx_mgh
-freesurfer/bin/bet.fsl
-freesurfer/bin/beta2sxa
-freesurfer/bin/biasfield
-freesurfer/bin/bmedits2surf
-freesurfer/bin/brec
-freesurfer/bin/brec.awk
-freesurfer/bin/browse-minc-header.tcl
-freesurfer/bin/bugr
-freesurfer/bin/build_desikan_killiany_gcs.csh
-freesurfer/bin/cblumwmgyri
-freesurfer/bin/checkMCR.sh
-freesurfer/bin/check_recons.sh
-freesurfer/bin/check_siemens_dir
-freesurfer/bin/check_subject
-freesurfer/bin/clear_fs_env.csh
-freesurfer/bin/compute_interrater_variability.csh
-freesurfer/bin/compute_label_vals.csh
-freesurfer/bin/qdec
+freesurfer/DefectLUT.txt
freesurfer/diffusion
freesurfer/docs/xml
+freesurfer/FreeSurferEnv.csh
+freesurfer/FreeSurferEnv.sh
freesurfer/fsfast
freesurfer/lib/bem/ic0.tri
freesurfer/lib/bem/ic1.tri
@@ -443,9 +758,22 @@ freesurfer/lib/tcl
freesurfer/lib/tktools
freesurfer/lib/vtk
freesurfer/matlab
+freesurfer/mni-1.4
+freesurfer/mni/bin/autocrop
+freesurfer/mni/bin/check_scale
+freesurfer/mni/bin/correct_field
+freesurfer/mni/bin/crispify
+freesurfer/mni/bin/dcm2mnc
+freesurfer/mni/bin/Display
+freesurfer/mni/bin/ecattominc
+freesurfer/mni/bin/evaluate_field
+freesurfer/mni/bin/extracttag
+freesurfer/mni/bin/field2imp
+freesurfer/mni/bin/imp2field
+freesurfer/mni/bin/invert_raw_image
+freesurfer/mni/bin/make_model
freesurfer/mni/bin/make_phantom
freesurfer/mni/bin/make_template
-freesurfer/mni/bin/minc_modify_header
freesurfer/mni/bin/mincaverage
freesurfer/mni/bin/mincbbox
freesurfer/mni/bin/mincblur
@@ -464,6 +792,7 @@ freesurfer/mni/bin/minclookup
freesurfer/mni/bin/mincmakescalar
freesurfer/mni/bin/mincmakevector
freesurfer/mni/bin/mincmath
+freesurfer/mni/bin/minc_modify_header
freesurfer/mni/bin/mincpik
freesurfer/mni/bin/mincresample
freesurfer/mni/bin/mincreshape
@@ -504,33 +833,28 @@ freesurfer/mni/bin/xfmconcat
freesurfer/mni/bin/xfminvert
freesurfer/mni/bin/xfmtool
freesurfer/mni/bin/zscore_vol
-freesurfer/mni/bin/Display
-freesurfer/mni/bin/autocrop
-freesurfer/mni/bin/check_scale
-freesurfer/mni/bin/correct_field
-freesurfer/mni/bin/crispify
-freesurfer/mni/bin/dcm2mnc
-freesurfer/mni/bin/ecattominc
-freesurfer/mni/bin/evaluate_field
-freesurfer/mni/bin/extracttag
-freesurfer/mni/bin/field2imp
-freesurfer/mni/bin/imp2field
-freesurfer/mni/bin/invert_raw_image
-freesurfer/mni/bin/make_model
freesurfer/mni/data
freesurfer/mni/etc
freesurfer/mni/include
-freesurfer/mni/share/N3
+freesurfer/mni/mni.srcbuild.June2015.tgz
freesurfer/mni/share/man
freesurfer/mni/share/mni_autoreg
-freesurfer/mni/mni.srcbuild.June2015.tgz
-freesurfer/mni-1.4
+freesurfer/mni/share/N3
freesurfer/models
-freesurfer/python/lib/python3.6/test
+freesurfer/python/lib/python3.8/test
+freesurfer/python/lib/python3.8/site-packages/caffe2
+freesurfer/python/lib/python3.8/site-packages/sklearn
+freesurfer/python/lib/python3.8/site-packages/tensorflow
+freesurfer/python/lib/python3.8/site-packages/torch
+freesurfer/python/lib/python3.8/site-packages/**/tests
freesurfer/python/**/__pycache__
freesurfer/python/share
+freesurfer/SegmentNoLUT.txt
freesurfer/sessions
-freesurfer/subjects/V1_average
+freesurfer/SetUpFreeSurfer.csh
+freesurfer/SetUpFreeSurfer.sh
+freesurfer/Simple_surface_labels2009.txt
+freesurfer/sources.sh
freesurfer/subjects/bert
freesurfer/subjects/cvs_avg35
freesurfer/subjects/cvs_avg35_inMNI152
@@ -538,18 +862,11 @@ freesurfer/subjects/fsaverage3
freesurfer/subjects/fsaverage4
freesurfer/subjects/fsaverage_sym
freesurfer/subjects/lh.EC_average
-freesurfer/subjects/rh.EC_average
freesurfer/subjects/README
+freesurfer/subjects/rh.EC_average
freesurfer/subjects/sample-001.mgz
freesurfer/subjects/sample-002.mgz
+freesurfer/subjects/V1_average
+freesurfer/tkmeditParcColorsCMA
freesurfer/tktools
freesurfer/trctrain
-freesurfer/DefectLUT.txt
-freesurfer/FreeSurferEnv.csh
-freesurfer/FreeSurferEnv.sh
-freesurfer/SegmentNoLUT.txt
-freesurfer/SetUpFreeSurfer.csh
-freesurfer/SetUpFreeSurfer.sh
-freesurfer/Simple_surface_labels2009.txt
-freesurfer/sources.sh
-freesurfer/tkmeditParcColorsCMA
diff --git a/setup.cfg b/setup.cfg
index fe39252631..21a5d11f6e 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -17,7 +17,7 @@ classifiers =
Programming Language :: Python :: 3.10
[options]
-python_requires = >=3.7
+python_requires = >=3.8
install_requires =
indexed_gzip >= 0.8.8
lockfile
diff --git a/smriprep/data/io_spec.json b/smriprep/data/io_spec.json
index a366b1344b..5d386b0293 100644
--- a/smriprep/data/io_spec.json
+++ b/smriprep/data/io_spec.json
@@ -77,6 +77,12 @@
"hemi": ["L", "R"],
"extension": "shape.gii",
"suffix": ["thickness", "sulc", "curv"]
+ },
+ "anat_ribbon": {
+ "datatype": "anat",
+ "desc": "ribbon",
+ "suffix": "mask",
+ "extension": "nii.gz"
}
}
},
diff --git a/smriprep/interfaces/workbench.py b/smriprep/interfaces/workbench.py
new file mode 100644
index 0000000000..a5f647ef97
--- /dev/null
+++ b/smriprep/interfaces/workbench.py
@@ -0,0 +1,144 @@
+from nipype.interfaces.base import CommandLineInputSpec, File, TraitedSpec, traits
+from nipype.interfaces.workbench.base import WBCommand
+
+
+class CreateSignedDistanceVolumeInputSpec(CommandLineInputSpec):
+ surf_file = File(
+ exists=True,
+ mandatory=True,
+ argstr="%s",
+ position=0,
+ desc="Input surface GIFTI file (.surf.gii)",
+ )
+ ref_file = File(
+ exists=True,
+ mandatory=True,
+ argstr="%s",
+ position=1,
+ desc="NIfTI volume in the desired output space (dims, spacing, origin)",
+ )
+ out_file = File(
+ name_source=["surf_file"],
+ name_template="%s_distvol.nii.gz",
+ argstr="%s",
+ position=2,
+ desc="Name of output volume containing signed distances",
+ )
+ out_mask = File(
+ name_source=["surf_file"],
+ name_template="%s_distmask.nii.gz",
+ argstr="-roi-out %s",
+ desc="Name of file to store a mask where the ``out_file`` has a computed value",
+ )
+ fill_value = traits.Float(
+ 0.0,
+ mandatory=False,
+ usedefault=True,
+ argstr="-fill-value %f",
+ desc="value to put in all voxels that don't get assigned a distance",
+ )
+ exact_limit = traits.Float(
+ 5.0,
+ usedefault=True,
+ argstr="-exact-limit %f",
+ desc="distance for exact output in mm",
+ )
+ approx_limit = traits.Float(
+ 20.0,
+ usedefault=True,
+ argstr="-approx-limit %f",
+ desc="distance for approximate output in mm",
+ )
+ approx_neighborhood = traits.Int(
+ 2,
+ usedefault=True,
+ argstr="-approx-neighborhood %d",
+ desc="size of neighborhood cube measured from center to face in voxels, default 2 = 5x5x5",
+ )
+ winding_method = traits.Enum(
+ "EVEN_ODD",
+ "NEGATIVE",
+ "NONZERO",
+ "NORMALS",
+ argstr="-winding %s",
+ usedefault=True,
+ desc="winding method for point inside surface test",
+ )
+
+
+class CreateSignedDistanceVolumeOutputSpec(TraitedSpec):
+ out_file = File(desc="Name of output volume containing signed distances")
+ out_mask = File(
+ desc="Name of file to store a mask where the ``out_file`` has a computed value"
+ )
+
+
+class CreateSignedDistanceVolume(WBCommand):
+ """Create signed distance volume from surface
+
+ Computes the signed distance function of the surface. Exact distance is
+ calculated by finding the closest point on any surface triangle to the
+ center of the voxel. Approximate distance is calculated starting with
+ these distances, using dijkstra's method with a neighborhood of voxels.
+ Specifying too small of an exact distance may produce unexpected results.
+
+ The NORMALS winding method uses the normals of triangles and edges, or the
+ closest triangle hit by a ray from the point. This method may be
+ slightly faster, but is only reliable for a closed surface that does not
+ cross through itself. All other methods count entry (positive) and exit
+ (negative) crossings of a vertical ray from the point, then counts as
+ inside if the total is odd, negative, or nonzero, respectively.
+
+ Command help string::
+
+ CREATE SIGNED DISTANCE VOLUME FROM SURFACE
+
+ wb_command -create-signed-distance-volume
+ - the input surface
+ - a volume in the desired output space (dims, spacing, origin)
+ - output - the output volume
+
+ [-roi-out] - output an roi volume of where the output has a computed
+ value
+ - output - the output roi volume
+
+ [-fill-value] - specify a value to put in all voxels that don't get
+ assigned a distance
+ - value to fill with (default 0)
+
+ [-exact-limit] - specify distance for exact output
+ - distance in mm (default 5)
+
+ [-approx-limit] - specify distance for approximate output
+ - distance in mm (default 20)
+
+ [-approx-neighborhood] - voxel neighborhood for approximate calculation
+ - size of neighborhood cube measured from center to face, in
+ voxels (default 2 = 5x5x5)
+
+ [-winding] - winding method for point inside surface test
+ - name of the method (default EVEN_ODD)
+
+ Computes the signed distance function of the surface. Exact distance is
+ calculated by finding the closest point on any surface triangle to the
+ center of the voxel. Approximate distance is calculated starting with
+ these distances, using dijkstra's method with a neighborhood of voxels.
+ Specifying too small of an exact distance may produce unexpected results.
+ Valid specifiers for winding methods are as follows:
+
+ EVEN_ODD (default)
+ NEGATIVE
+ NONZERO
+ NORMALS
+
+ The NORMALS method uses the normals of triangles and edges, or the
+ closest triangle hit by a ray from the point. This method may be
+ slightly faster, but is only reliable for a closed surface that does not
+ cross through itself. All other methods count entry (positive) and exit
+ (negative) crossings of a vertical ray from the point, then counts as
+ inside if the total is odd, negative, or nonzero, respectively.
+ """
+
+ input_spec = CreateSignedDistanceVolumeInputSpec
+ output_spec = CreateSignedDistanceVolumeOutputSpec
+ _cmd = "wb_command -create-signed-distance-volume"
diff --git a/smriprep/utils/bids.py b/smriprep/utils/bids.py
index bc3ceb9bb1..e796b83028 100644
--- a/smriprep/utils/bids.py
+++ b/smriprep/utils/bids.py
@@ -40,7 +40,7 @@ def get_outputnode_spec():
'anat2std_xfm', 'std2anat_xfm',
't1w_aseg', 't1w_aparc',
't1w2fsnative_xfm', 'fsnative2t1w_xfm',
- 'surfaces', 'morphometrics']
+ 'surfaces', 'morphometrics', 'anat_ribbon']
"""
spec = loads(Path(pkgrf("smriprep", "data/io_spec.json")).read_text())["queries"]
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index e0f8c2f851..4c15155a5b 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -55,7 +55,8 @@
)
from .norm import init_anat_norm_wf
from .outputs import init_anat_reports_wf, init_anat_derivatives_wf
-from .surfaces import init_surface_recon_wf, init_fastsurf_recon_wf
+from .surfaces import init_surface_recon_wf, init_fastsurf_recon_wf, init_anat_ribbon_wf
+
LOGGER = logging.getLogger("nipype.workflow")
@@ -634,6 +635,8 @@ def _check_img(img):
])
# fmt:on
+ # Anatomical ribbon file using HCP signed-distance volume method
+ anat_ribbon_wf = init_anat_ribbon_wf()
# fmt:off
workflow.connect([
@@ -655,6 +658,11 @@ def _check_img(img):
('outputnode.morphometrics', 'morphometrics'),
('outputnode.out_aseg', 't1w_aseg'),
('outputnode.out_aparc', 't1w_aparc')]),
+ (surface_recon_wf, anat_ribbon_wf, [
+ ('outputnode.surfaces', 'inputnode.surfaces'),
+ ('outputnode.out_brainmask', 'inputnode.t1w_mask')]),
+ (anat_ribbon_wf, outputnode, [
+ ("outputnode.anat_ribbon", "anat_ribbon")]),
(applyrefined, buffernode, [('out_file', 't1w_brain')]),
(surface_recon_wf, buffernode, [
('outputnode.out_brainmask', 't1w_mask')]),
@@ -667,6 +675,9 @@ def _check_img(img):
('surfaces', 'inputnode.surfaces'),
('morphometrics', 'inputnode.morphometrics'),
]),
+ (anat_ribbon_wf, anat_derivatives_wf, [
+ ("outputnode.anat_ribbon", "inputnode.anat_ribbon"),
+ ]),
])
return workflow
diff --git a/smriprep/workflows/outputs.py b/smriprep/workflows/outputs.py
index 09c32fe465..872130c32f 100644
--- a/smriprep/workflows/outputs.py
+++ b/smriprep/workflows/outputs.py
@@ -272,6 +272,8 @@ def init_anat_derivatives_wf(
GIFTI surfaces (gray/white boundary, midthickness, pial, inflated)
morphometrics
GIFTIs of cortical thickness, curvature, and sulcal depth
+ anat_ribbon
+ Cortical ribbon volume in T1w space
t1w_fs_aseg
FreeSurfer's aseg segmentation, in native T1w space
t1w_fs_aparc
@@ -299,6 +301,7 @@ def init_anat_derivatives_wf(
"fsnative2t1w_xfm",
"surfaces",
"morphometrics",
+ "anat_ribbon",
"t1w_fs_aseg",
"t1w_fs_aparc",
]
@@ -642,6 +645,19 @@ def init_anat_derivatives_wf(
name="ds_morphs",
run_without_submitting=True,
)
+ # Ribbon volume
+ ds_anat_ribbon = pe.Node(
+ DerivativesDataSink(
+ base_directory=output_dir,
+ desc="ribbon",
+ suffix="mask",
+ extension=".nii.gz",
+ compress=True,
+ ),
+ name="ds_anat_ribbon",
+ run_without_submitting=True,
+ )
+
# Parcellations
ds_t1w_fsaseg = pe.Node(
DerivativesDataSink(
@@ -680,6 +696,9 @@ def init_anat_derivatives_wf(
('source_files', 'source_file')]),
(inputnode, ds_t1w_fsparc, [('t1w_fs_aparc', 'in_file'),
('source_files', 'source_file')]),
+ (inputnode, ds_anat_ribbon, [('anat_ribbon', 'in_file'),
+ ('source_files', 'source_file')]),
+
])
# fmt:on
return workflow
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 5e9ebb8917..17eee8c6ae 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -31,6 +31,7 @@
from nipype.pipeline import engine as pe
from nipype.interfaces.base import Undefined
from nipype.interfaces import (
+ fsl,
io as nio,
utility as niu,
freesurfer as fs,
@@ -335,6 +336,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# fmt:on
return workflow
+from ..interfaces.workbench import CreateSignedDistanceVolume
def init_surface_recon_wf(*, omp_nthreads, hires, name="surface_recon_wf"):
@@ -956,6 +958,164 @@ def _sel(x):
return workflow
+def init_anat_ribbon_wf(name="anat_ribbon_wf"):
+ DEFAULT_MEMORY_MIN_GB = 0.01
+ workflow = pe.Workflow(name=name)
+
+ inputnode = pe.Node(
+ niu.IdentityInterface(
+ fields=[
+ "surfaces",
+ "t1w_mask",
+ ]
+ ),
+ name="inputnode",
+ )
+ outputnode = pe.Node(
+ niu.IdentityInterface(
+ fields=[
+ "anat_ribbon",
+ ]
+ ),
+ name="outputnode",
+ )
+
+ # 0, 1 = wm; 2, 3 = pial; 6, 7 = mid
+ # note that order of lh / rh within each surf type is not guaranteed due to use
+ # of unsorted glob by FreeSurferSource prior, but we can do a sort
+ # to ensure consistent ordering
+ select_wm = pe.Node(
+ niu.Select(index=[0, 1]),
+ name="select_wm",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ run_without_submitting=True,
+ )
+
+ select_pial = pe.Node(
+ niu.Select(index=[2, 3]),
+ name="select_pial",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ run_without_submitting=True,
+ )
+
+ select_midthick = pe.Node(
+ niu.Select(index=[6, 7]),
+ name="select_midthick",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ run_without_submitting=True,
+ )
+
+ create_wm_distvol = pe.MapNode(
+ CreateSignedDistanceVolume(),
+ iterfield=["surf_file"],
+ name="create_wm_distvol",
+ )
+
+ create_pial_distvol = pe.MapNode(
+ CreateSignedDistanceVolume(),
+ iterfield=["surf_file"],
+ name="create_pial_distvol",
+ )
+
+ thresh_wm_distvol = pe.MapNode(
+ fsl.maths.MathsCommand(args="-thr 0 -bin -mul 255"),
+ iterfield=["in_file"],
+ name="thresh_wm_distvol",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ )
+
+ uthresh_pial_distvol = pe.MapNode(
+ fsl.maths.MathsCommand(args="-uthr 0 -abs -bin -mul 255"),
+ iterfield=["in_file"],
+ name="uthresh_pial_distvol",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ )
+
+ bin_wm_distvol = pe.MapNode(
+ fsl.maths.UnaryMaths(operation="bin"),
+ iterfield=["in_file"],
+ name="bin_wm_distvol",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ )
+
+ bin_pial_distvol = pe.MapNode(
+ fsl.maths.UnaryMaths(operation="bin"),
+ iterfield=["in_file"],
+ name="bin_pial_distvol",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ )
+
+ split_wm_distvol = pe.Node(
+ niu.Split(splits=[1, 1]),
+ name="split_wm_distvol",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ run_without_submitting=True,
+ )
+
+ merge_wm_distvol_no_flatten = pe.Node(
+ niu.Merge(2),
+ no_flatten=True,
+ name="merge_wm_distvol_no_flatten",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ run_without_submitting=True,
+ )
+
+ make_ribbon_vol = pe.MapNode(
+ fsl.maths.MultiImageMaths(op_string="-mas %s -mul 255"),
+ iterfield=["in_file", "operand_files"],
+ name="make_ribbon_vol",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ )
+
+ bin_ribbon_vol = pe.MapNode(
+ fsl.maths.UnaryMaths(operation="bin"),
+ iterfield=["in_file"],
+ name="bin_ribbon_vol",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ )
+
+ split_squeeze_ribbon_vol = pe.Node(
+ niu.Split(splits=[1, 1], squeeze=True),
+ name="split_squeeze_ribbon",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ run_without_submitting=True,
+ )
+
+ combine_ribbon_vol_hemis = pe.Node(
+ fsl.maths.BinaryMaths(operation="add"),
+ name="combine_ribbon_vol_hemis",
+ mem_gb=DEFAULT_MEMORY_MIN_GB,
+ )
+
+ # make HCP-style ribbon volume in T1w space
+ workflow.connect(
+ [
+ (inputnode, select_wm, [("surfaces", "inlist")]),
+ (inputnode, select_pial, [("surfaces", "inlist")]),
+ (inputnode, select_midthick, [("surfaces", "inlist")]),
+ (select_wm, create_wm_distvol, [(("out", _sorted_by_basename), "surf_file")]),
+ (inputnode, create_wm_distvol, [("t1w_mask", "ref_file")]),
+ (select_pial, create_pial_distvol, [(("out", _sorted_by_basename), "surf_file")]),
+ (inputnode, create_pial_distvol, [("t1w_mask", "ref_file")]),
+ (create_wm_distvol, thresh_wm_distvol, [("out_file", "in_file")]),
+ (create_pial_distvol, uthresh_pial_distvol, [("out_file", "in_file")]),
+ (thresh_wm_distvol, bin_wm_distvol, [("out_file", "in_file")]),
+ (uthresh_pial_distvol, bin_pial_distvol, [("out_file", "in_file")]),
+ (bin_wm_distvol, split_wm_distvol, [("out_file", "inlist")]),
+ (split_wm_distvol, merge_wm_distvol_no_flatten, [("out1", "in1")]),
+ (split_wm_distvol, merge_wm_distvol_no_flatten, [("out2", "in2")]),
+ (bin_pial_distvol, make_ribbon_vol, [("out_file", "in_file")]),
+ (merge_wm_distvol_no_flatten, make_ribbon_vol, [("out", "operand_files")]),
+ (make_ribbon_vol, bin_ribbon_vol, [("out_file", "in_file")]),
+ (bin_ribbon_vol, split_squeeze_ribbon_vol, [("out_file", "inlist")]),
+ (split_squeeze_ribbon_vol, combine_ribbon_vol_hemis, [("out1", "in_file")]),
+ (split_squeeze_ribbon_vol, combine_ribbon_vol_hemis, [("out2", "operand_file")]),
+ (combine_ribbon_vol_hemis, outputnode, [("out_file", "anat_ribbon")]),
+ ]
+ )
+ return workflow
+
+
def _check_cw256(in_files, default_flags):
import numpy as np
from nibabel.funcs import concat_images
@@ -968,3 +1128,9 @@ def _check_cw256(in_files, default_flags):
if np.any(fov > 256):
flags.append("-cw256")
return flags
+
+
+def _sorted_by_basename(inlist):
+ from os.path import basename
+
+ return sorted(inlist, key=lambda x: str(basename(x)))
From 7154e1b9ce3f8380fb31f6a00e9f16de1c70313f Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 21 Feb 2023 16:24:21 -0600
Subject: [PATCH 208/220] Add checkpoints for FastSurfer from FastSurfer
Dockerfile
https://github.com/Deep-MI/FastSurfer/blob/stable/Docker/Dockerfile
---
Dockerfile | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Dockerfile b/Dockerfile
index ca552556c4..0928316517 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -342,6 +342,10 @@ ENV IS_DOCKER_8395080871=1
ENV FASTSURFER_HOME=/fastsurfer
ENV PATH="$PATH:/fastsurfer"
+# Download all remote network checkpoints already
+ENV PYTHONPATH=/fastsurfer:$PYTHONPATH
+RUN cd /fastsurfer ; python3 FastSurferCNN/download_checkpoints.py --all
+
RUN ldconfig
WORKDIR /tmp
ENTRYPOINT ["/opt/conda/bin/smriprep"]
From d2feae9df9b4e6e921d4cb0c53b525e8623b4ab4 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 21 Feb 2023 17:16:07 -0600
Subject: [PATCH 209/220] Switch order of conda env updates
Install FastSurfer dependencies in conda environment before installing smriprep wheels
---
Dockerfile | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 0928316517..70136e3c2e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -321,12 +321,13 @@ RUN /opt/conda/bin/python fetch_templates.py && \
find $HOME/.cache/templateflow -type d -exec chmod go=u {} + && \
find $HOME/.cache/templateflow -type f -exec chmod go=u {} +
+# Installing FastSurfer gpu dependencies
+RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
+
# Installing sMRIPREP
COPY --from=src /src/fmriprep/dist/*.whl .
RUN /opt/conda/bin/python -m pip install --no-cache-dir $( ls *.whl )[all]
-RUN conda env update -n base --file /fastsurfer/fastsurfer_env_gpu.yml
-
# Installing nibabel version 4.0.2
RUN /opt/conda/bin/python -m pip install --no-cache-dir nibabel==4.0.2
From d0e8a3f190b9d5fc5f6a5caf56c150d78c133e78 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 22 Feb 2023 09:37:30 -0600
Subject: [PATCH 210/220] Update FastSurfer to v2.0.4
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 70136e3c2e..363bfa603c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -62,7 +62,7 @@ RUN apt-get update && \
# git clone stable branch of FastSurfer
RUN cd /opt && mkdir /fastsurfer \
- && git clone -b v2.0.1 https://github.com/Deep-MI/FastSurfer.git \
+ && git clone -b v2.0.4 https://github.com/Deep-MI/FastSurfer.git \
&& cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
# Install conda
From d869a165bd3f748830c955b663e48839aee6b20d Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 23 Feb 2023 14:53:08 -0600
Subject: [PATCH 211/220] Reorder FastSurfer directory copy and remove unused
git clone
---
Dockerfile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 363bfa603c..4947f1d6da 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -64,7 +64,10 @@ RUN apt-get update && \
RUN cd /opt && mkdir /fastsurfer \
&& git clone -b v2.0.4 https://github.com/Deep-MI/FastSurfer.git \
&& cp /opt/FastSurfer/fastsurfer_env_gpu.yml /fastsurfer/fastsurfer_env_gpu.yml
-
+
+# Copy fastsurfer from git folder
+RUN cp -R /opt/FastSurfer/* /fastsurfer/ && rm -rf /opt/FastSurfer
+
# Install conda
RUN wget --no-check-certificate -qO ~/miniconda.sh https://repo.continuum.io/miniconda/$CONDA_FILE && \
chmod +x ~/miniconda.sh && \
@@ -96,9 +99,6 @@ ENV OS=Linux \
PYTHONUNBUFFERED=0 \
PATH=/opt/freesurfer/bin:$PATH
-# Copy fastsurfer from git folder
-RUN cp -R /opt/FastSurfer/* /fastsurfer/
-
# Simulate SetUpFreeSurfer.sh
ENV FSL_DIR="/opt/fsl-6.0.5.1" \
OS="Linux" \
From b6f083a0a756532841ad4faf083f7bc5acc53d77 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 21 Mar 2023 16:45:43 -0500
Subject: [PATCH 212/220] Debugging FastSurfer Workflow
---
smriprep/interfaces/fastsurfer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 1390c47da1..8244740cb5 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -3,7 +3,7 @@
# vi: set ft=python sts=4 ts=4 sw=4 et:
"""
The FastSufer module provides basic functions
-for running FastSurfer CNN and surface processing.
+for running FastSurfer VINN and surface processing.
"""
from nipype.interfaces.base import (
From 5d820555aa7ba29400a7d97d975d675846b6778e Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 21 Mar 2023 16:46:18 -0500
Subject: [PATCH 213/220] Debugging FastSurfer Workflow
---
smriprep/workflows/anatomical.py | 6 ++---
smriprep/workflows/surfaces.py | 44 +++++++++++++++++---------------
2 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index ba07b0b3d0..329945f34c 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -621,9 +621,9 @@ def _check_img(img):
workflow.connect([
(inputnode, t2w_template_wf, [('t2w', 'inputnode.anat_files')]),
(t2w_template_wf, bbreg, [('outputnode.anat_ref', 'source_file')]),
- (surface_recon_wf, bbreg, [
- ('outputnode.subject_id', 'subject_id'),
- ('outputnode.subjects_dir', 'subjects_dir'),
+ (inputnode, bbreg, [
+ ('inputnode.subject_id', 'subject_id'),
+ ('inputnode.subjects_dir', 'subjects_dir'),
]),
(bbreg, coreg_xfms, [('out_lta_file', 'in1')]),
(surface_recon_wf, coreg_xfms, [('outputnode.fsnative2t1w_xfm', 'in2')]),
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 514e3192d8..fdb0ce0944 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -59,10 +59,10 @@
def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
r"""
- Reconstruct anatomical surfaces using FastSurfer CNN and ``recon_surf``,
+ Reconstruct anatomical surfaces using FastSurfer VINN and ``recon_surf``,
an alternative to FreeSurfer's ``recon-all``.
- First, FastSurfer CNN creates a segmentation using the T1w structural image.
+ First, FastSurfer VINN creates a segmentation using the T1w structural image.
This is followed by FastSurfer ``recon_surf`` processing of the surface,
along with surface registration to support cross-subject comparison
using the ``--surfeg`` argument to FastSurfer.
@@ -144,20 +144,20 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
weights_sag
Pretrained weights of sagittal network.
Default
- ``../checkpoints/Sagittal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
+ ``../checkpoints/Sagittal_Weights_FastSurferVINN/ckpts/Epoch_30_training_state.pkl``
weights_ax
Pretrained weights of axial network.
Default
- ``../checkpoints/Axial_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
+ ``../checkpoints/Axial_Weights_FastSurferVINN/ckpts/Epoch_30_training_state.pkl``
weights_cor
Pretrained weights of coronal network.
Default
- ``../checkpoints/Coronal_Weights_FastSurferCNN/ckpts/Epoch_30_training_state.pkl``
+ ``../checkpoints/Coronal_Weights_FastSurferVINN/ckpts/Epoch_30_training_state.pkl``
seg_log
- Name and location for the log-file for the segmentation (FastSurferCNN).
+ Name and location for the log-file for the segmentation (FastSurferVINN).
Default '$SUBJECTS_DIR/$sid/scripts/deep-seg.log'
clean_seg
- Flag to clean up FastSurferCNN segmentation
+ Flag to clean up FastSurferVINN segmentation
run_viewagg_on
Define where the view aggregation should be run on.
By default, the program checks if you have enough memory to run
@@ -167,7 +167,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
Equivalently, if you define ``--run_viewagg_on gpu``, view agg will be run on the gpu
(no memory check will be done).
no_cuda
- Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)
+ Flag to disable CUDA usage in FastSurferVINN (no GPU usage, inference on CPU)
batch
Batch size for inference. Default 16. Lower this to reduce memory requirement
order
@@ -198,11 +198,11 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
which python version to use.
Default ``python3.6``
seg_only
- only run FastSurferCNN
+ only run FastSurferVINN
(generate segmentation, do not run the surface pipeline)
surf_only
only run the surface pipeline ``recon_surf``.
- The segmentation created by FastSurferCNN must already exist in this case.
+ The segmentation created by FastSurferVINN must already exist in this case.
"""
@@ -214,7 +214,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
ANTs-derived and FastSurfer-derived segmentations of the cortical
gray-matter of Mindboggle [RRID:SCR_002438, @mindboggle].
""".format(
- fastsurfer_version="1.1.0"
+ fastsurfer_version="2.0.4"
)
inputnode = pe.Node(
@@ -233,19 +233,22 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
outputnode = pe.Node(
niu.IdentityInterface(
fields=[
- "sd",
- "sid",
+ "subjects_dir",
+ "subject_id",
"t1w2fsnative_xfm",
"fsnative2t1w_xfm",
"surfaces",
"out_brainmask",
"out_aseg",
"out_aparc",
+ "morphometrics",
]
),
name="outputnode",
)
+ # outputnode = pe.Node(niu.IdentityInterface(["surfaces", "morphometrics"]), name="outputnode")
+
# null for now, placeholder for FastSurfer VINN hires support
if hires:
if LOGGER:
@@ -272,7 +275,7 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# fastsurf.FastSurferSource(), name="recon_conf")
fastsurf_recon = pe.Node(
- fastsurf.FastSCommand(),
+ fastsurf.FastSurfer(),
name="fastsurf_recon",
n_procs=omp_nthreads,
mem_gb=12,
@@ -297,9 +300,9 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# (inputnode, recon_conf, [('t1w', 't1'),
# ('sd', 'sd'),
# ('sid', 'sid')]),
- (inputnode, fastsurf_recon, [('sd', 'sd'),
- ('sid', 'sid'),
- ('t1w', 't1')]),
+ (inputnode, fastsurf_recon, [('sd', 'subjects_dir'),
+ ('sid', 'subject_id'),
+ ('t1w', 'T1_files')]),
(inputnode, skull_strip_extern, [('sd', 'subjects_dir'),
('sid', 'subject_id')]),
(inputnode, gifti_surface_wf, [
@@ -325,9 +328,10 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
(aseg_to_native_wf, refine, [('outputnode.out_file', 'in_aseg')]),
# Output
- (inputnode, outputnode, [('sd', 'sd'),
- ('sid', 'sid')]),
- (gifti_surface_wf, outputnode, [('outputnode.surfaces', 'surfaces')]),
+ (inputnode, outputnode, [('sd', 'subjects_dir'),
+ ('sid', 'subject_id')]),
+ (gifti_surface_wf, outputnode, [('outputnode.surfaces', 'surfaces'),
+ ('outputnode.morphometrics', 'morphometrics')]),
(t1w2fsnative_xfm, outputnode, [('out_lta', 't1w2fsnative_xfm')]),
(fsnative2t1w_xfm, outputnode, [('out_reg_file', 'fsnative2t1w_xfm')]),
(refine, outputnode, [('out_file', 'out_brainmask')]),
From 9b891fa63fc8a6be58afda473055658a44aeda8b Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Tue, 21 Mar 2023 16:46:44 -0500
Subject: [PATCH 214/220] Debugging FastSurfer Workflow
---
smriprep/cli/run.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 2db66800f7..68a2ba5740 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -230,6 +230,7 @@ def get_parser():
dest="run_reconall",
help="disable FreeSurfer surface preprocessing.",
)
+ # Dev note: we might need to make this not xor?
g_surfs_xor.add_argument(
"--fastsurfer",
action="store_true",
From e810a7c4d6db8eacd2c8b62ac5c559e8bccd87c9 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Wed, 17 May 2023 14:47:35 -0500
Subject: [PATCH 215/220] Include mri_mc for FastSurfer compatibility
---
docker/files/freesurfer7.3.2-exclude.txt | 1 -
1 file changed, 1 deletion(-)
diff --git a/docker/files/freesurfer7.3.2-exclude.txt b/docker/files/freesurfer7.3.2-exclude.txt
index a817a062b1..eb274ef2a5 100644
--- a/docker/files/freesurfer7.3.2-exclude.txt
+++ b/docker/files/freesurfer7.3.2-exclude.txt
@@ -420,7 +420,6 @@ freesurfer/bin/mri_make_template
freesurfer/bin/mri_map_cpdat
freesurfer/bin/mri_maps2csd
freesurfer/bin/mri_mark_temporal_lobe
-freesurfer/bin/mri_mc
freesurfer/bin/mri_mcsim
freesurfer/bin/mri_mergelabels
freesurfer/bin/mri_mi
From 3cee8428ec902ade013910cd4c0feeb6654ce8c9 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 18 May 2023 11:24:55 -0500
Subject: [PATCH 216/220] Remove exclusion of files needed for FastSurfer
v2.0.4
---
docker/files/freesurfer7.3.2-exclude.txt | 18 ------------------
1 file changed, 18 deletions(-)
diff --git a/docker/files/freesurfer7.3.2-exclude.txt b/docker/files/freesurfer7.3.2-exclude.txt
index eb274ef2a5..09714a0bc1 100644
--- a/docker/files/freesurfer7.3.2-exclude.txt
+++ b/docker/files/freesurfer7.3.2-exclude.txt
@@ -4,20 +4,10 @@ freesurfer/average/3T18yoSchwartzReactN32_as_orig.4dfp.img
freesurfer/average/3T18yoSchwartzReactN32_as_orig.4dfp.img.rec
freesurfer/average/3T18yoSchwartzReactN32_as_orig.4dfp.mat
freesurfer/average/3T18yoSchwartzReactN32_as_orig.lst
-freesurfer/average/711-2B_as_mni_average_305.4dfp.hdr
-freesurfer/average/711-2B_as_mni_average_305.4dfp.ifh
-freesurfer/average/711-2B_as_mni_average_305.4dfp.img
-freesurfer/average/711-2B_as_mni_average_305.4dfp.img.rec
-freesurfer/average/711-2B_as_mni_average_305_mask.4dfp.hdr
-freesurfer/average/711-2B_as_mni_average_305_mask.4dfp.img.rec
-freesurfer/average/711-2C_as_mni_average_305.4dfp.hdr
-freesurfer/average/711-2C_as_mni_average_305.4dfp.img.rec
-freesurfer/average/711-2C_as_mni_average_305.4dfp.mat
freesurfer/average/aseg+spmhead+vermis+pons.ixi.gca
freesurfer/average/BrainstemSS
freesurfer/average/Buckner_JNeurophysiol11_MNI152
freesurfer/average/Choi_JNeurophysiol12_MNI152
-freesurfer/average/colortable_desikan_killiany.txt
freesurfer/average/face.gca
freesurfer/average/HippoSF
freesurfer/average/label_scales.dat
@@ -41,7 +31,6 @@ freesurfer/average/mni305.cor.subfov1.mgz
freesurfer/average/mni305.cor.subfov1.reg
freesurfer/average/mni305.cor.subfov2.mgz
freesurfer/average/mni305.cor.subfov2.reg
-freesurfer/average/mni305.mask.cor.mgz
freesurfer/average/mni_average_305.4dfp.hdr
freesurfer/average/mni_average_305.4dfp.ifh
freesurfer/average/mni_average_305.4dfp.img
@@ -503,7 +492,6 @@ freesurfer/bin/mris_gradient
freesurfer/bin/mris_hausdorff_dist
freesurfer/bin/mris_image2vtk
freesurfer/bin/mri_simulate_atrophy
-freesurfer/bin/mris_info
freesurfer/bin/mris_init_global_tractography
freesurfer/bin/mris_intensity_profile
freesurfer/bin/mris_interpolate_warp
@@ -547,7 +535,6 @@ freesurfer/bin/mris_rf_label
freesurfer/bin/mris_rf_train
freesurfer/bin/mris_rotate
freesurfer/bin/mris_sample_label
-freesurfer/bin/mris_sample_parc
freesurfer/bin/mris_seg2annot
freesurfer/bin/mris_segment
freesurfer/bin/mris_segmentation_stats
@@ -748,11 +735,9 @@ freesurfer/bin/xhemireg
freesurfer/bin/xhemi-tal
freesurfer/bin/xsanatreg
freesurfer/bin/zero_lt_4dfp
-freesurfer/DefectLUT.txt
freesurfer/diffusion
freesurfer/docs/xml
freesurfer/FreeSurferEnv.csh
-freesurfer/FreeSurferEnv.sh
freesurfer/fsfast
freesurfer/lib/bem/ic0.tri
freesurfer/lib/bem/ic1.tri
@@ -860,11 +845,8 @@ freesurfer/python/lib/python3.8/site-packages/torch
freesurfer/python/lib/python3.8/site-packages/**/tests
freesurfer/python/**/__pycache__
freesurfer/python/share
-freesurfer/SegmentNoLUT.txt
freesurfer/sessions
freesurfer/SetUpFreeSurfer.csh
-freesurfer/SetUpFreeSurfer.sh
-freesurfer/Simple_surface_labels2009.txt
freesurfer/sources.sh
freesurfer/subjects/bert
freesurfer/subjects/cvs_avg35
From 456b03ae2080dd5eb5307ff7e538847d9d330e24 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 18 May 2023 11:25:30 -0500
Subject: [PATCH 217/220] Remove repeated package installations
---
Dockerfile | 6 ------
1 file changed, 6 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 5eb677fa29..54a0d7005c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -128,7 +128,6 @@ RUN apt-get update -qq \
libgl1-mesa-dev \
libgl1-mesa-dri \
libglu1-mesa-dev \
- libgomp1 \
libice6 \
libxcursor1 \
libxft2 \
@@ -207,21 +206,16 @@ RUN GNUPGHOME=/tmp gpg --keyserver hkps://keyserver.ubuntu.com --no-default-keyr
# AFNI latest (neurodocker build)
RUN apt-get update -qq \
&& apt-get install -y -q --no-install-recommends \
- apt-utils \
ed \
gsl-bin \
libglib2.0-0 \
- libglu1-mesa-dev \
libglw1-mesa \
- libgomp1 \
libjpeg62 \
libpng12-0 \
libxm4 \
libxp6 \
netpbm \
- tcsh \
xfonts-base \
- xvfb \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& curl -sSL --retry 5 -o /tmp/multiarch.deb http://archive.ubuntu.com/ubuntu/pool/main/g/glibc/multiarch-support_2.27-3ubuntu1.5_amd64.deb \
From b5a1bb77c216f857f7c0e704636ea31639d835d8 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 18 May 2023 11:35:13 -0500
Subject: [PATCH 218/220] Debugging workflows for FastSurfer
---
smriprep/workflows/anatomical.py | 33 ++++++-----------
smriprep/workflows/base.py | 2 +-
smriprep/workflows/surfaces.py | 63 ++++++++++++--------------------
3 files changed, 37 insertions(+), 61 deletions(-)
diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py
index c99afebceb..78e4ecdb64 100644
--- a/smriprep/workflows/anatomical.py
+++ b/smriprep/workflows/anatomical.py
@@ -33,7 +33,7 @@
)
from nipype.interfaces.ants.base import Info as ANTsInfo
-from nipype.interfaces.ants import DenoiseImage, N4BiasFieldCorrection
+from nipype.interfaces.ants import N4BiasFieldCorrection
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
from niworkflows.interfaces.fixes import FixHeaderApplyTransforms as ApplyTransforms
@@ -576,11 +576,11 @@ def _check_img(img):
# fmt:off
workflow.connect([
(inputnode, surface_recon_wf, [
- ('subject_id', 'inputnode.sid'),
- ('subjects_dir', 'inputnode.sd')]),
+ ('subject_id', 'inputnode.subject_id'),
+ ('subjects_dir', 'inputnode.subjects_dir')]),
(surface_recon_wf, anat_reports_wf, [
- ('inputnode.sid', 'inputnode.subject_id'),
- ('inputnode.sd', 'inputnode.subjects_dir'),
+ ('outputnode.subject_id', 'inputnode.subject_id'),
+ ('outputnode.subjects_dir', 'inputnode.subjects_dir'),
]),
])
# fmt:on
@@ -622,8 +622,8 @@ def _check_img(img):
(inputnode, t2w_template_wf, [('t2w', 'inputnode.anat_files')]),
(t2w_template_wf, bbreg, [('outputnode.anat_ref', 'source_file')]),
(inputnode, bbreg, [
- ('inputnode.subject_id', 'subject_id'),
- ('inputnode.subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id'),
+ ('subjects_dir', 'subjects_dir'),
]),
(bbreg, coreg_xfms, [('out_lta_file', 'in1')]),
(surface_recon_wf, coreg_xfms, [('outputnode.fsnative2t1w_xfm', 'in2')]),
@@ -771,28 +771,19 @@ def init_anat_template_wf(
name="outputnode",
)
- # 0. Denoise and reorient T1w image(s) to RAS and resample to common voxel space
+ # 0. Reorient T1w image(s) to RAS and resample to common voxel space
anat_ref_dimensions = pe.Node(TemplateDimensions(), name="anat_ref_dimensions")
- denoise = pe.MapNode(
- DenoiseImage(noise_model="Rician", num_threads=omp_nthreads),
- iterfield="input_image",
- name="denoise",
- )
anat_conform = pe.MapNode(Conform(), iterfield="in_file", name="anat_conform")
# fmt:off
workflow.connect([
(inputnode, anat_ref_dimensions, [('anat_files', 't1w_list')]),
- (anat_ref_dimensions, denoise, [('t1w_valid_list', 'input_image')]),
(anat_ref_dimensions, anat_conform, [
+ ('t1w_valid_list', 'in_file'),
('target_zooms', 'target_zooms'),
- ('target_shape', 'target_shape'),
- ]),
- (denoise, anat_conform, [('output_image', 'in_file')]),
- (anat_ref_dimensions, outputnode, [
- ('out_report', 'out_report'),
- ('t1w_valid_list', 'anat_valid_list'),
- ]),
+ ('target_shape', 'target_shape')]),
+ (anat_ref_dimensions, outputnode, [('out_report', 'out_report'),
+ ('t1w_valid_list', 'anat_valid_list')]),
])
# fmt:on
diff --git a/smriprep/workflows/base.py b/smriprep/workflows/base.py
index 184b6ac546..d3720398a7 100644
--- a/smriprep/workflows/base.py
+++ b/smriprep/workflows/base.py
@@ -200,7 +200,7 @@ def init_smriprep_wf(
subject_id=subject_id,
bids_filters=bids_filters,
)
-
+
single_subject_wf.config["execution"]["crashdump_dir"] = os.path.join(
output_dir, "smriprep", "sub-" + subject_id, "log", run_uuid
)
diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py
index 222823a43e..cd2dbf76f1 100644
--- a/smriprep/workflows/surfaces.py
+++ b/smriprep/workflows/surfaces.py
@@ -63,16 +63,14 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
an alternative to FreeSurfer's ``recon-all``.
First, FastSurfer VINN creates a segmentation using the T1w structural image.
- This is followed by FastSurfer ``recon_surf`` processing of the surface,
- along with surface registration to support cross-subject comparison
- using the ``--surfeg`` argument to FastSurfer.
+ This is followed by FastSurfer ``recon_surf`` processing of the surface.
For example, a subject with only one session with a T1w image
would be processed by the following command::
$ /opt/FastSurfer/run_fastsurfer.sh \
--t1 /sub-/anat/sub-_T1w.nii.gz \
- --sid sub- --sd /fastsurfer --surfreg
+ --sid sub- --sd /fastsurfer
Similar to the Freesurfer workflow second phase, we then
import an externally computed skull-stripping mask.
@@ -184,8 +182,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
fsaparc
Use FS aparc segmentations in addition to DL prediction
(slower in this case and usually the mapped ones from the DL prediction are fine)
- surfreg
- Create Surface-Atlas ``sphere.reg`` registration with FreeSurfer
+ no_surfreg
+ Skip creating Surface-Atlas ``sphere.reg`` registration with FreeSurfer
(for cross-subject correspondence or other mappings)
parallel
Run both hemispheres in parallel
@@ -220,8 +218,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
inputnode = pe.Node(
niu.IdentityInterface(
fields=[
- "sd",
- "sid",
+ "subjects_dir",
+ "subject_id",
"t1w",
"skullstripped_t1",
"corrected_t1",
@@ -249,11 +247,6 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# outputnode = pe.Node(niu.IdentityInterface(["surfaces", "morphometrics"]), name="outputnode")
- # null for now, placeholder for FastSurfer VINN hires support
- if hires:
- if LOGGER:
- LOGGER.warn(f'High-resolution {hires} specified, not currently supported, ignoring.')
-
fsnative2t1w_xfm = pe.Node(
RobustRegister(auto_sens=True, est_int_scale=True), name="fsnative2t1w_xfm")
t1w2fsnative_xfm = pe.Node(
@@ -264,15 +257,9 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
aseg_to_native_wf = init_segs_to_native_wf(fastsurfer=True)
aparc_to_native_wf = init_segs_to_native_wf(fastsurfer=True, segmentation="aparc_aseg")
refine = pe.Node(RefineBrainMask(), name="refine")
- # fs_license_file variable not used, uncomment if this changes!
- # fs_license_file = "/opt/freesurfer/license.txt"
- # if os.path.exists("/tmp/freesurfer/license.txt"):
- # fs_license_file = "/tmp/freesurfer/license.txt"
- # elif os.environ['FS_LICENSE']:
- # fs_license_file = os.environ['FS_LICENSE']
- # recon_conf = pe.Node(
- # fastsurf.FastSurferSource(), name="recon_conf")
+ recon_conf = pe.Node(
+ fastsurf.FastSurferSource(), name="recon_conf")
fastsurf_recon = pe.Node(
fastsurf.FastSurfer(),
@@ -283,8 +270,6 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
fastsurf_recon.interface._can_resume = False
fastsurf_recon.interface._always_run = True
- # fov_check = pe.Node(niu.Function(function=_check_cw256), name="fov_check")
-
skull_strip_extern = pe.Node(FSInjectBrainExtracted(), name="skull_strip_extern")
fsnative2t1w_xfm = pe.Node(
@@ -296,19 +281,16 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
# fmt:off
workflow.connect([
- # Configuration
- # (inputnode, recon_conf, [('t1w', 't1'),
- # ('sd', 'sd'),
- # ('sid', 'sid')]),
- (inputnode, fastsurf_recon, [('sd', 'subjects_dir'),
- ('sid', 'subject_id'),
+ (inputnode, fastsurf_recon, [('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id'), # ]),
('t1w', 'T1_files')]),
- (inputnode, skull_strip_extern, [('sd', 'subjects_dir'),
- ('sid', 'subject_id')]),
- (inputnode, gifti_surface_wf, [
- ('sd', 'inputnode.subjects_dir'),
- ('sid', 'inputnode.subject_id')]),
- (inputnode, skull_strip_extern, [('skullstripped_t1', 'in_brain')]),
+ # (inputnode, skull_strip_extern, [('subjects_dir', 'subjects_dir'),
+ # ('subject_id', 'subject_id')]),
+ # (inputnode, skull_strip_extern, [('skullstripped_t1', 'in_brain')]),
+ (fastsurf_recon, gifti_surface_wf, [
+ ('subjects_dir', 'inputnode.subjects_dir'),
+ ('subject_id', 'inputnode.subject_id')]),
+ # (inputnode, skull_strip_extern, [('skullstripped_t1', 'in_brain')]),
# Construct transform from FreeSurfer conformed image to sMRIPrep
# reoriented image
(inputnode, fsnative2t1w_xfm, [('t1w', 'target_file')]),
@@ -320,6 +302,9 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
(inputnode, refine, [('corrected_t1', 'in_anat'),
('ants_segs', 'in_ants')]),
(inputnode, aseg_to_native_wf, [('corrected_t1', 'inputnode.in_file')]),
+ (fastsurf_recon, aseg_to_native_wf, [
+ ('subjects_dir', 'inputnode.subjects_dir'),
+ ('subject_id', 'inputnode.subject_id')]),
(fsnative2t1w_xfm, aseg_to_native_wf, [
('out_reg_file', 'inputnode.fsnative2t1w_xfm')]),
(inputnode, aparc_to_native_wf, [('corrected_t1', 'inputnode.in_file')]),
@@ -328,8 +313,8 @@ def init_fastsurf_recon_wf(*, omp_nthreads, hires, name="fastsurf_recon_wf"):
(aseg_to_native_wf, refine, [('outputnode.out_file', 'in_aseg')]),
# Output
- (inputnode, outputnode, [('sd', 'subjects_dir'),
- ('sid', 'subject_id')]),
+ (inputnode, outputnode, [('subjects_dir', 'subjects_dir'),
+ ('subject_id', 'subject_id')]),
(gifti_surface_wf, outputnode, [('outputnode.surfaces', 'surfaces'),
('outputnode.morphometrics', 'morphometrics')]),
(t1w2fsnative_xfm, outputnode, [('out_lta', 't1w2fsnative_xfm')]),
@@ -1136,7 +1121,7 @@ def init_anat_ribbon_wf(name="anat_ribbon_wf"):
def init_morph_grayords_wf(
grayord_density: ty.Literal['91k', '170k'],
- name: str = "morph_grayords_wf",
+ name: str = "bold_grayords_wf",
):
"""
Sample Grayordinates files onto the fsLR atlas.
@@ -1156,7 +1141,7 @@ def init_morph_grayords_wf(
grayord_density : :obj:`str`
Either `91k` or `170k`, representing the total of vertices or *grayordinates*.
name : :obj:`str`
- Unique name for the subworkflow (default: ``"morph_grayords_wf"``)
+ Unique name for the subworkflow (default: ``"bold_grayords_wf"``)
Inputs
------
From ff91fead2ccc86237251a62c574074f00ee2f74c Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 18 May 2023 11:35:46 -0500
Subject: [PATCH 219/220] Add files via upload
---
smriprep/cli/run.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py
index 68a2ba5740..2db66800f7 100644
--- a/smriprep/cli/run.py
+++ b/smriprep/cli/run.py
@@ -230,7 +230,6 @@ def get_parser():
dest="run_reconall",
help="disable FreeSurfer surface preprocessing.",
)
- # Dev note: we might need to make this not xor?
g_surfs_xor.add_argument(
"--fastsurfer",
action="store_true",
From ef1054c725de8759086e67ff37c935e25cd634b4 Mon Sep 17 00:00:00 2001
From: pcamach2 <49655443+pcamach2@users.noreply.github.com>
Date: Thu, 18 May 2023 11:36:45 -0500
Subject: [PATCH 220/220] Change inputs and defaults to match FastSurfer v2.0.4
CLI
---
smriprep/interfaces/fastsurfer.py | 40 +++++++++++--------------------
1 file changed, 14 insertions(+), 26 deletions(-)
diff --git a/smriprep/interfaces/fastsurfer.py b/smriprep/interfaces/fastsurfer.py
index 8244740cb5..9833eaf483 100644
--- a/smriprep/interfaces/fastsurfer.py
+++ b/smriprep/interfaces/fastsurfer.py
@@ -23,9 +23,9 @@ class FastSInputSpec(CommandLineInputSpec):
Required arguments
==================
- sd
+ subjects_dir
Output directory
- sid
+ subject_id
Subject ID for directory inside ``sd`` to be created
t1
T1 full head input, not bias corrected, global path.
@@ -73,12 +73,9 @@ class FastSInputSpec(CommandLineInputSpec):
Equivalently, if you define ``--run_viewagg_on gpu``, view agg will be run on the gpu
(no memory check will be done).
no_cuda
- Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU)
+ Flag to disable CUDA usage in FastSurferCNN (no GPU usage, inference on CPU).
batch
- Batch size for inference. Default 16. Lower this to reduce memory requirement
- order
- Order of interpolation for mri_convert T1 before segmentation
- ``(0=nearest, 1=linear(default), 2=quadratic, 3=cubic)``
+ Batch size for inference. Default 16. Lower this to reduce memory requirement.
Surface pipeline arguments
@@ -87,12 +84,12 @@ class FastSInputSpec(CommandLineInputSpec):
Use ``mri_tesselate`` instead of marching cube (default) for surface creation
fsqsphere
Use FreeSurfer default instead of
- novel spectral spherical projection for qsphere
+ ndovel spectral spherical projection for qsphere
fsaparc
Use FS aparc segmentations in addition to DL prediction
(slower in this case and usually the mapped ones from the DL prediction are fine)
- surfreg
- Create Surface-Atlas ``sphere.reg`` registration with FreeSurfer
+ no_surfreg
+ Skip creating Surface-Atlas ``sphere.reg`` registration with FreeSurfer
(for cross-subject correspondence or other mappings)
parallel
Run both hemispheres in parallel
@@ -191,14 +188,6 @@ class FastSInputSpec(CommandLineInputSpec):
argstr="--batch %d",
desc="Batch size for inference. default=16. Lower this to reduce memory requirement"
)
- order = traits.Int(
- 1,
- mandatory=False,
- argstr="--order %d",
- usedefault=True,
- desc="""Order of interpolation for mri_convert T1 before segmentation
- (0=nearest, 1=linear(default), 2=quadratic, 3=cubic)"""
- )
fstess = traits.Bool(
False,
mandatory=False,
@@ -217,12 +206,11 @@ class FastSInputSpec(CommandLineInputSpec):
argstr="--fsaparc",
desc="Use FS aparc segmentations in addition to DL prediction"
)
- surfreg = traits.Bool(
- True,
- usedefault=True,
+ no_surfreg = traits.Bool(
+ False,
mandatory=False,
- argstr="--surfreg",
- desc="""Create Surface-Atlas (sphere.reg) registration with FreeSurfer
+ argstr="--no_surfreg",
+ desc="""Skip creating Surface-Atlas (sphere.reg) registration with FreeSurfer
(for cross-subject correspondence or other mappings)"""
)
parallel = traits.Bool(
@@ -377,12 +365,12 @@ class FastSurferSourceOutputSpec(FSSourceOutputSpec):
altkey="aseg.presurf.hypos",
desc="Automated segmentation pre-surface recon statistics files"
)
- sd = Directory(
+ subjects_dir = Directory(
exists=True,
argstr="--sd %s",
desc="Subjects directory"
)
- sid = traits.String(
+ subject_id = traits.String(
exists=True,
argstr="--sid %s",
desc="Subject ID"
@@ -404,7 +392,7 @@ class FastSurfer(CommandLine):
input_spec = FastSInputSpec
output_spec = FastSurferSourceOutputSpec
- _cmd = 'run_fastsurfer.sh --surfreg'
+ _cmd = 'run_fastsurfer.sh'
def _list_outputs(self):
outputs = self.output_spec().get()