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 synthbet option to preproc_t1 #169

Open
wants to merge 9 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
50 changes: 36 additions & 14 deletions subworkflows/nf-scil/preproc_t1/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@ include { DENOISING_NLMEANS } from '../../../modules/nf-scil/denoising/nlmeans/m
include { PREPROC_N4 } from '../../../modules/nf-scil/preproc/n4/main'
include { IMAGE_RESAMPLE } from '../../../modules/nf-scil/image/resample/main'
include { BETCROP_ANTSBET } from '../../../modules/nf-scil/betcrop/antsbet/main'
include { BETCROP_SYNTHBET} from '../../../modules/nf-scil/betcrop/synthbet/main'
include { BETCROP_CROPVOLUME as BETCROP_CROPVOLUME_T1 } from '../../../modules/nf-scil/betcrop/cropvolume/main'
include { BETCROP_CROPVOLUME as BETCROP_CROPVOLUME_MASK } from '../../../modules/nf-scil/betcrop/cropvolume/main'

params.run_synthbet = params.run_synthbet ?: false

workflow PREPROC_T1 {

take:
ch_image // channel: [ val(meta), [ image ] ]
ch_template // channel: [ val(meta), [ template ] ]
ch_probability_map // channel: [ val(meta), [ probability_map ] ]
ch_template // channel: [ val(meta), [ template ] ] , optional
ch_probability_map // channel: [ val(meta), [ probability_map ] ] , optional
ch_mask_nlmeans // channel: [ val(meta), [ mask ] ] , optional
ch_ref_n4 // channel: [ val(meta), [ ref, ref_mask ] ] , optional
ch_ref_resample // channel: [ val(meta), [ ref ] ] , optional
ch_weights // channel: [ val(meta), [ weights ] ] , optional

main:

Expand All @@ -36,28 +40,46 @@ workflow PREPROC_T1 {
ch_versions = ch_versions.mix(IMAGE_RESAMPLE.out.versions.first())

// ** Brain extraction ** //
ch_bet = IMAGE_RESAMPLE.out.image.join(ch_template).join(ch_probability_map)
BETCROP_ANTSBET ( ch_bet )
ch_versions = ch_versions.mix(BETCROP_ANTSBET.out.versions.first())
if ( params.run_synthbet) {
ch_bet = IMAGE_RESAMPLE.out.image.join(ch_weights)
BETCROP_SYNTHBET ( ch_bet )
ch_versions = ch_versions.mix(BETCROP_SYNTHBET.out.versions.first())

// ** Setting BET output ** //
image_bet = BETCROP_SYNTHBET.out.bet_image
mask_bet = BETCROP_SYNTHBET.out.brain_mask
}

else {
ch_template = ch_template.ifEmpty(Channel.error('Template is required for ANTS registration'))
ch_probability_map = ch_probability_map.ifEmpty(Channel.error('Probability map is required for ANTS registration'))
ch_bet = IMAGE_RESAMPLE.out.image.join(ch_template).join(ch_probability_map)
BETCROP_ANTSBET ( ch_bet )
ch_versions = ch_versions.mix(BETCROP_ANTSBET.out.versions.first())

// ** Setting BET output ** //
image_bet = BETCROP_ANTSBET.out.t1
mask_bet = BETCROP_ANTSBET.out.mask
}

// ** crop image ** //
ch_crop = BETCROP_ANTSBET.out.t1.map{it + [[]]}
ch_crop = image_bet.map{it + [[]]}
BETCROP_CROPVOLUME_T1 ( ch_crop )
ch_versions = ch_versions.mix(BETCROP_CROPVOLUME_T1.out.versions.first())

// ** crop mask ** //
ch_crop_mask = BETCROP_ANTSBET.out.mask.join(BETCROP_CROPVOLUME_T1.out.bounding_box)
ch_crop_mask = mask_bet.join(BETCROP_CROPVOLUME_T1.out.bounding_box)
BETCROP_CROPVOLUME_MASK ( ch_crop_mask )
ch_versions = ch_versions.mix(BETCROP_CROPVOLUME_MASK.out.versions.first())

emit:
image_nlmeans = DENOISING_NLMEANS.out.image // channel: [ val(meta), [ image ] ]
image_N4 = PREPROC_N4.out.image // channel: [ val(meta), [ image ] ]
image_resample = IMAGE_RESAMPLE.out.image // channel: [ val(meta), [ image ] ]
image_bet = BETCROP_ANTSBET.out.t1 // channel: [ val(meta), [ t1 ] ]
mask_bet = BETCROP_ANTSBET.out.mask // channel: [ val(meta), [ mask ] ]
image_nlmeans = DENOISING_NLMEANS.out.image // channel: [ val(meta), [ image ] ]
image_N4 = PREPROC_N4.out.image // channel: [ val(meta), [ image ] ]
image_resample = IMAGE_RESAMPLE.out.image // channel: [ val(meta), [ image ] ]
image_bet = image_bet // channel: [ val(meta), [ t1 ] ]
mask_bet = mask_bet // channel: [ val(meta), [ mask ] ]
crop_box = BETCROP_CROPVOLUME_T1.out.bounding_box // channel: [ val(meta), [ bounding_box ] ]
mask_final = BETCROP_CROPVOLUME_MASK.out.image // channel: [ val(meta), [ mask ] ]
mask_final = BETCROP_CROPVOLUME_MASK.out.image // channel: [ val(meta), [ image ] ]
t1_final = BETCROP_CROPVOLUME_T1.out.image // channel: [ val(meta), [ image ] ]
versions = ch_versions // channel: [ versions.yml ]
versions = ch_versions // channel: [ versions.yml ]
}
14 changes: 13 additions & 1 deletion subworkflows/nf-scil/preproc_t1/meta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ description: |
Resamples the T1 to an isotropic spatial resolution. The default is 1mm, a standard in humans which
usually facilitate registration with corrected DWI images.
This spatial resolution is modifiable in the configuration file.
Brain Extraction (bet, ANTs).
Brain Extraction (bet, ANTs, freesurfer).
Isolates the brain tissue voxels from the remaining image. Also creates a binary brain mask.
This brain extraction is required for the T1 to DWI Registration.
Cropping (scil).
Expand All @@ -42,6 +42,7 @@ components:
- preproc/n4
- image/resample
- betcrop/antsbet
- betcrop/synthbet
- betcrop/cropvolume

input:
Expand Down Expand Up @@ -81,6 +82,17 @@ input:
The input channel containing the reference for the resampling. Optional
Structure: [ val(meta), path(ref) ]
pattern: "*.{nii,nii.gz}"
- ch_weights:
type: file
description: |
The input channel containing an alternative model weights for synthbet. Optional
Structure: [ val(meta), path (weights)]
pattern: "*.pt"
- val_synth:
type: boolean
description: |
Boolean input specifying which BET method is employed. Optional: defaults at false (ANTs)
pattern: "true"
output:
- image_nlmeans:
type: file
Expand Down
104 changes: 102 additions & 2 deletions subworkflows/nf-scil/preproc_t1/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ nextflow_workflow {
tag "preproc/n4"
tag "image/resample"
tag "betcrop/antsbet"
tag "betcrop/synthbet"
tag "betcrop/cropvolume"

tag "load_test_data"
Expand Down Expand Up @@ -69,14 +70,29 @@ nextflow_workflow {
[ id:'test', single_end:false ],
[]
]}
input[6] = ch_split_test_data.antsbet.map{
test_data_directory -> [
[ id:'test', single_end:false ],
[]
]}
"""
}
}

then {
assertAll(
{ assert workflow.success},
{ assert snapshot(workflow.out).match()}
{ assert snapshot(
niftiMD5SUM(workflow.out.image_nlmeans.get(0).get(1)),
niftiMD5SUM(workflow.out.image_N4.get(0).get(1)),
niftiMD5SUM(workflow.out.image_resample.get(0).get(1)),
niftiMD5SUM(workflow.out.image_bet.get(0).get(1)),
niftiMD5SUM(workflow.out.mask_bet.get(0).get(1)),
file(workflow.out.crop_box.get(0).get(1)),
niftiMD5SUM(workflow.out.mask_final.get(0).get(1)),
niftiMD5SUM(workflow.out.t1_final.get(0).get(1)),
workflow.out.versions
).match()}
)
}
}
Expand Down Expand Up @@ -123,14 +139,98 @@ nextflow_workflow {
[ id:'test', single_end:false ],
file("\${test_data_directory}/t1_unaligned.nii.gz")
]}
input[6] = ch_split_test_data.antsbet.map{
test_data_directory -> [
[ id:'test', single_end:false ],
[]
]}
"""
}
}

then {
assertAll(
{ assert workflow.success},
{ assert snapshot(
niftiMD5SUM(workflow.out.image_nlmeans.get(0).get(1)),
niftiMD5SUM(workflow.out.image_N4.get(0).get(1)),
niftiMD5SUM(workflow.out.image_resample.get(0).get(1)),
niftiMD5SUM(workflow.out.image_bet.get(0).get(1)),
niftiMD5SUM(workflow.out.mask_bet.get(0).get(1)),
workflow.out.crop_box,
niftiMD5SUM(workflow.out.mask_final.get(0).get(1)),
niftiMD5SUM(workflow.out.t1_final.get(0).get(1)),
workflow.out.versions
).match()}
)
}
}

test("preproc_t1_synthbet") {
config "./nextflow_synthbet.config"

when {
workflow {
"""
ch_split_test_data = LOAD_DATA.out.test_data_directory
.branch{
antsbet: it.simpleName == "antsbet"
others: it.simpleName == "others"
}
input[0] = ch_split_test_data.antsbet.map{
test_data_directory -> [
[ id:'test', single_end:false ],
file("\${test_data_directory}/t1_unaligned.nii.gz")
]}
input[1] = ch_split_test_data.antsbet.map{
test_data_directory -> [
[ id:'test', single_end:false ],
[]
]}
input[2] = ch_split_test_data.antsbet.map{
test_data_directory -> [
[ id:'test', single_end:false ],
[]
]}
input[3] = ch_split_test_data.antsbet.map{
test_data_directory -> [
[ id:'test', single_end:false ],
[]
]}
input[4] = ch_split_test_data.others.map{
test_data_directory -> [
[ id:'test', single_end:false ],
[],
[]
]}
input[5] = ch_split_test_data.antsbet.map{
test_data_directory -> [
[ id:'test', single_end:false ],
[]
]}
input[6] = ch_split_test_data.antsbet.map{
test_data_directory -> [
[ id:'test', single_end:false ],
[]
]}
"""
}
}

then {
assertAll(
{ assert workflow.success},
{ assert snapshot(workflow.out).match()}
{ assert snapshot(
niftiMD5SUM(workflow.out.image_nlmeans.get(0).get(1)),
niftiMD5SUM(workflow.out.image_N4.get(0).get(1)),
niftiMD5SUM(workflow.out.image_resample.get(0).get(1)),
niftiMD5SUM(workflow.out.image_bet.get(0).get(1)),
niftiMD5SUM(workflow.out.mask_bet.get(0).get(1)),
workflow.out.crop_box,
niftiMD5SUM(workflow.out.mask_final.get(0).get(1)),
niftiMD5SUM(workflow.out.t1_final.get(0).get(1)),
workflow.out.versions
).match()}
)
}
}
Expand Down
Loading
Loading