Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Improvement] add synthseg option to anatomical_segmentation #211

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/nf-scil/segmentation/fastseg/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ process SEGMENTATION_FASTSEG {
'scilus/scilus:2.0.2' }"

input:
tuple val(meta), path(image), path(lesion)
tuple val(meta), path(image), path(lesion) /* optional, input = [] */

output:
tuple val(meta), path("*mask_wm.nii.gz") , emit: wm_mask
Expand Down
44 changes: 34 additions & 10 deletions subworkflows/nf-scil/anatomical_segmentation/main.nf
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// ** Importing modules from nf-scil ** //
include { SEGMENTATION_FASTSEG } from '../../../modules/nf-scil/segmentation/fastseg/main'
include { SEGMENTATION_FREESURFERSEG } from '../../../modules/nf-scil/segmentation/freesurferseg/main'
include { SEGMENTATION_SYNTHSEG } from '../../../modules/nf-scil/segmentation/synthseg/main'

params.run_synthseg = params.run_synthseg ?: false

workflow ANATOMICAL_SEGMENTATION {

Expand All @@ -15,6 +18,10 @@ workflow ANATOMICAL_SEGMENTATION {

ch_versions = Channel.empty()

if ( ch_image && ch_freesurferseg ) {
error('Both input channels cannot be passed simultaneously')
}

if ( ch_freesurferseg ) {
// ** Freesurfer segmentation ** //
SEGMENTATION_FREESURFERSEG ( ch_freesurferseg )
Expand All @@ -28,18 +35,35 @@ workflow ANATOMICAL_SEGMENTATION {
gm_map = Channel.empty()
csf_map = Channel.empty()
}

else {
// ** FSL fast segmentation ** //
SEGMENTATION_FASTSEG ( ch_image )
ch_versions = ch_versions.mix(SEGMENTATION_FASTSEG.out.versions.first())
if ( params.run_synthseg ) {
// ** Freesurfer synthseg segmentation ** //
SEGMENTATION_SYNTHSEG ( ch_image )
ch_versions = ch_versions.mix(SEGMENTATION_SYNTHSEG.out.versions.first())

// ** Setting outputs ** //
wm_mask = SEGMENTATION_FASTSEG.out.wm_mask
gm_mask = SEGMENTATION_FASTSEG.out.gm_mask
csf_mask = SEGMENTATION_FASTSEG.out.csf_mask
wm_map = SEGMENTATION_FASTSEG.out.wm_map
gm_map = SEGMENTATION_FASTSEG.out.gm_map
csf_map = SEGMENTATION_FASTSEG.out.csf_map
// ** Setting outputs ** //
wm_mask = SEGMENTATION_SYNTHSEG.out.wm_mask
gm_mask = SEGMENTATION_SYNTHSEG.out.gm_mask
csf_mask = SEGMENTATION_SYNTHSEG.out.csf_mask
wm_map = Channel.empty()
gm_map = Channel.empty()
csf_map = Channel.empty()
}

else {
// ** FSL fast segmentation ** //
SEGMENTATION_FASTSEG ( ch_image )
ch_versions = ch_versions.mix(SEGMENTATION_FASTSEG.out.versions.first())

// ** Setting outputs ** //
wm_mask = SEGMENTATION_FASTSEG.out.wm_mask
gm_mask = SEGMENTATION_FASTSEG.out.gm_mask
csf_mask = SEGMENTATION_FASTSEG.out.csf_mask
wm_map = SEGMENTATION_FASTSEG.out.wm_map
gm_map = SEGMENTATION_FASTSEG.out.gm_map
csf_map = SEGMENTATION_FASTSEG.out.csf_map
}
}

emit:
Expand Down
15 changes: 12 additions & 3 deletions subworkflows/nf-scil/anatomical_segmentation/meta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ description: |
and CSF masks/maps.
2) Channel with FreeSurfer's parcellations files will result in using Scilpy's tools to produce
WM, GM, and CSF masks (probability maps are not produced with this option).
3) Given the synthseg related parameter in entry, will use synthseg instead of FSL FAST, producing
WM, GM and CSF masks.
Typical next steps after this subworkflow would be to combine the resulting masks/maps with fODF
data to perform TRACKING.
keywords:
Expand All @@ -17,6 +19,7 @@ keywords:
components:
- segmentation/fastseg
- segmentation/freesurferseg
- segmentation/synthseg
input:
- ch_image:
type: file
Expand All @@ -33,6 +36,12 @@ input:
parcellations into masks.
Structure: [ val(meta), path(aparc_aseg), path(wm_parc) ]
pattern: "*.mgz"
- ch_lesion:
type: file
description: |
The optional input channel containing a Nifti lesion volume to correct the white matter with a lesion mask. The lesion mask must be a binary masks.
Structure: [ val(meta), path(image) ]
pattern: "*.{nii,nii.gz}"
output:
- wm_mask:
type: file
Expand All @@ -59,21 +68,21 @@ output:
type: file
description: |
Channel containing WM probability maps. Will be only outputted if FSL's fast segmentation
is used and not with FreeSurfer's parcellation files.
is used and not with Synthseg and FreeSurfer's parcellation files.
Structure: [ val(meta), path(wm_maps) ]
pattern: "*.{nii,nii.gz}"
- gm_maps:
type: file
description: |
Channel containing GM probability maps. Will be only outputted if FSL's fast segmentation
is used and not with FreeSurfer's parcellation files.
is used and not with Synthseg and FreeSurfer's parcellation files.
Structure: [ val(meta), path(gm_maps) ]
pattern: "*.{nii,nii.gz}"
- csf_maps:
type: file
description: |
Channel containing CSF probability maps. Will be only outputted if FSL's fast segmentation
is used and not with FreeSurfer's parcellation files.
is used and not with Synthseg and FreeSurfer's parcellation files.
Structure: [ val(meta), path(csf_maps) ]
pattern: "*.{nii,nii.gz}"
- versions:
Expand Down
63 changes: 55 additions & 8 deletions subworkflows/nf-scil/anatomical_segmentation/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ nextflow_workflow {
name "Test Subworkflow ANATOMICAL_SEGMENTATION"
script "../main.nf"
workflow "ANATOMICAL_SEGMENTATION"
config "./nextflow.config"

tag "subworkflows"
tag "subworkflows_nfcore"
Expand All @@ -12,6 +11,7 @@ nextflow_workflow {
tag "segmentation"
tag "segmentation/fastseg"
tag "segmentation/freesurferseg"
tag "segmentation/synthseg"

tag "load_test_data"

Expand All @@ -28,16 +28,16 @@ nextflow_workflow {
}

test("anatomical_segmentation - fslfast") {

config "./nextflow.config"
when {
workflow {
"""
ch_split_test_data = LOAD_DATA.out.test_data_directory
.branch{
t1w: it.simpleName == "T1w"
T1w: it.simpleName == "T1w"
freesurfer: it.simpleName == "freesurfer_nifti"
}
input[0] = ch_split_test_data.t1w.map{
input[0] = ch_split_test_data.T1w.map{
test_data_directory -> [
[ id:'test' ],
file("\${test_data_directory}/T1w.nii.gz", checkIfExists: true),
Expand All @@ -51,19 +51,27 @@ nextflow_workflow {
then {
assertAll(
{ assert workflow.success},
{ assert snapshot(workflow.out).match()}
{ assert snapshot(
niftiMD5SUM(workflow.out.wm_mask.get(0).get(1)),
niftiMD5SUM(workflow.out.gm_mask.get(0).get(1)),
niftiMD5SUM(workflow.out.csf_mask.get(0).get(1)),
niftiMD5SUM(workflow.out.wm_map.get(0).get(1)),
niftiMD5SUM(workflow.out.gm_map.get(0).get(1)),
niftiMD5SUM(workflow.out.csf_map.get(0).get(1)),
workflow.out.versions
).match()}
)
}
}

test("anatomical_segmentation - freesurferseg") {

config "./nextflow.config"
when {
workflow {
"""
ch_split_test_data = LOAD_DATA.out.test_data_directory
.branch{
t1w: it.simpleName == "T1w"
T1w: it.simpleName == "T1w"
freesurfer: it.simpleName == "freesurfer_nifti"
}
input[0] = []
Expand All @@ -81,7 +89,46 @@ nextflow_workflow {
then {
assertAll(
{ assert workflow.success },
{ assert snapshot(workflow.out).match() }
{ assert snapshot(
niftiMD5SUM(workflow.out.wm_mask.get(0).get(1)),
niftiMD5SUM(workflow.out.gm_mask.get(0).get(1)),
niftiMD5SUM(workflow.out.csf_mask.get(0).get(1)),
workflow.out.versions
).match() }
)
}
}

test("anatomical_segmentation - synthseg") {
config "./nextflow_synthseg.config"
when {
workflow {
"""
ch_split_test_data = LOAD_DATA.out.test_data_directory
.branch{
T1w: it.simpleName == "T1w"
freesurfer: it.simpleName == "freesurfer_nifti"
}
input[0] = ch_split_test_data.T1w.map{
test_data_directory -> [
[ id:'test', single_end:false ], // meta map
file("\${test_data_directory}/anat/anat_image.nii.gz", checkIfExists: true),
[]
]}
input[1] = []
"""
}
}

then {
assertAll(
{ assert workflow.success},
{ assert snapshot(
niftiMD5SUM(workflow.out.wm_mask.get(0).get(1)),
niftiMD5SUM(workflow.out.gm_mask.get(0).get(1)),
niftiMD5SUM(workflow.out.csf_mask.get(0).get(1)),
workflow.out.versions
).match()}
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
process {

publishDir = { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" }

}

params {
run_synthseg = true
}
Loading