Skip to content

Commit

Permalink
Merge pull request #173 from ThoumyreStanislas/module_easy_reg
Browse files Browse the repository at this point in the history
[Module][WIP]Module easyreg
  • Loading branch information
arnaudbore authored Sep 12, 2024
2 parents b0e8e00 + 2f85490 commit cce5bce
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 3 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,13 @@ jobs:
fail-fast: false
matrix:
path: [ "${{ fromJson(needs.nf-test-changes.outputs.paths) }}" ]
profile: [ "docker" ]
exclude:
- path: subworkflows/nf-scil/load_test_data
include:
- profile: docker
- runner: scilus-nf-scil-runners
- runner: scilus-nf-scil-bigmem-runners
path: modules/nf-scil/registration/easyreg
exclude:
- path: subworkflows/nf-scil/load_test_data
uses: ./.github/workflows/nf-test_module.yml
with:
profile: ${{ matrix.profile }}
Expand Down
6 changes: 6 additions & 0 deletions modules/nf-scil/registration/easyreg/environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: "registration_easyreg"
channels:
- Docker
- Apptainer
dependencies:
- "Freesurfer"
82 changes: 82 additions & 0 deletions modules/nf-scil/registration/easyreg/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@


process REGISTRATION_EASYREG {
tag "$meta.id"
label 'process_single'
label 'process_high'

container "freesurfer/freesurfer:7.4.1"

input:
tuple val(meta), path(reference), path(floating), path(ref_segmentation), path(flo_segmentation)

output:
tuple val(meta), path("*_reference_segmentation.nii.gz") , emit: ref_seg
tuple val(meta), path("*_floating_segmentation.nii.gz") , emit: flo_seg
tuple val(meta), path("*_reference_registered.nii.gz") , emit: ref_reg
tuple val(meta), path("*_floating_registered.nii.gz") , emit: flo_reg
tuple val(meta), path("*_forward_field.nii.gz") , emit: fwd_field, optional: true
tuple val(meta), path("*_backward_field.nii.gz") , emit: bak_field, optional: true
path "versions.yml" , emit: versions

when:
task.ext.when == null || task.ext.when

script:
def prefix = task.ext.prefix ?: "${meta.id}"
def field = task.ext.field ? "--fwd_field ${prefix}_forward_field.nii.gz --bak_field ${prefix}_backward_field.nii.gz " : ""
def threads = task.ext.threads ? "--threads " + task.ext.threads : ""
def affine = task.ext.affine ? "--affine_only " : ""

"""
export ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS=1
export OMP_NUM_THREADS=1
export OPENBLAS_NUM_THREADS=1
if [[ -f "$ref_segmentation" ]];
then
reference_segmentation=$ref_segmentation
else
reference_segmentation="${prefix}_reference_segmentation.nii.gz"
fi
if [[ -f "$flo_segmentation" ]];
then
floating_segmentation=$flo_segmentation
else
floating_segmentation="${prefix}_floating_segmentation.nii.gz"
fi
mri_easyreg \
--ref $reference --flo $floating \
--ref_seg \${reference_segmentation} \
--flo_seg \${floating_segmentation} \
--flo_reg ${prefix}_floating_registered.nii.gz \
--ref_reg ${prefix}_reference_registered.nii.gz \
$field $threads $affine
cat <<-END_VERSIONS > versions.yml
"${task.process}":
freesurfer: 7.4.1
END_VERSIONS
"""

stub:
def prefix = task.ext.prefix ?: "${meta.id}"

"""
mri_easyreg -h
touch ${prefix}_reference_segmentation.nii.gz
touch ${prefix}_floating_segmentation.nii.gz
touch ${prefix}_reference_registered.nii.gz
touch ${prefix}_floating_registered.nii.gz
touch ${prefix}_forward_field.nii.gz
touch ${prefix}_backward_field.nii.gz
cat <<-END_VERSIONS > versions.yml
"${task.process}":
freesurfer: 7.4.1
END_VERSIONS
"""
}
91 changes: 91 additions & 0 deletions modules/nf-scil/registration/easyreg/meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
name: "registration_easyreg"
description: Image registration and SynthSeg v2 segmentation with easyreg from freesurfer
keywords:
- nifti
- registration
- segmentation
- easyreg
- freesurfer
tools:
- "Freesurfer":
description: "Software package for the analysis and visualization of structural and functional neuroimaging data."
homepage: "https://surfer.nmr.mgh.harvard.edu/fswiki"

input:
- meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'sample1', single_end:false ]`
- reference:
type: file
description: the reference image in .nii(.gz) or .mgz format (note that, since the method is symmetric, the choice of reference vs floating is arbitrary).
pattern: "*.{nii,nii.gz,mgz}"

- floating:
type: file
description: the floating image in .nii(.gz) or .mgz format.
pattern: "*.{nii,nii.gz,mgz}"

- ref_segmentation:
type: file
description: file with the SynthSeg v2 (non-robust) segmentation + parcellation of the reference image.
If it does not exist, EasyReg will create it. If it already exists (e.g., from a previous EasyReg run), then EasyReg will read it from disk (which is faster than segmenting).
pattern: "*.{nii,nii.gz}"

- flo_segmentation:
type: file
description: file with the SynthSeg v2 (non-robust) segmentation + parcellation of the floating image.
If it does not exist, EasyReg will create it. If it already exists (e.g., from a previous EasyReg run), then EasyReg will read it from disk (which is faster than segmenting).
pattern: "*.{nii,nii.gz}"

output:
- meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'sample1', single_end:false ]`
- ref_seg:
type: file
description: file with the SynthSeg v2 (non-robust) segmentation + parcellation of the reference image.
pattern: "*_reference_segmentation.nii.gz"

- flo_seg:
type: file
description: file with the SynthSeg v2 (non-robust) segmentation + parcellation of the floating image.
pattern: "*_floating_segmentation.nii.gz"

- ref_reg:
type: file
description: this is the file where the deformed (registered) reference image is written.
pattern: "*_reference_registered.nii.gz"

- flo_reg:
type: file
description: this is the file where the deformed (registered) floating image is written.
pattern: "*_floating_registered.nii.gz"

- fwd_field:
type: file
description:
this is the file where the forward deformation field is written. The deformation includes both the affine and nonlinear components.
Must be a nifti (.nii/.nii.gz) or .mgz file; it is encoded as the real world (RAS) coordinates of the target location for each voxel.
pattern: "*_forward_field.nii.gz"

- bak_field:
type: file
description: this is the file where the backward deformation field is written. It must also be a nifty or mgz file.
pattern: "*_backward_field.nii.gz"

- versions:
type: file
description: File containing software versions
pattern: "versions.yml"

authors:
- "@ThoumyreStanislas"
maintainers:
- "@ThoumyreStanislas"
72 changes: 72 additions & 0 deletions modules/nf-scil/registration/easyreg/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
nextflow_process {

name "Test Process REGISTRATION_EASYREG"
script "../main.nf"
process "REGISTRATION_EASYREG"

tag "modules"
tag "modules_nfcore"
tag "registration"
tag "registration/easyreg"

tag "subworkflows"
tag "subworkflows/load_test_data"


setup {
run("LOAD_TEST_DATA", alias: "LOAD_DATA") {
script "../../../../../subworkflows/nf-scil/load_test_data/main.nf"
process {
"""
input[0] = Channel.from( [ "freesurfer.zip", "registration.zip" ] )
input[1] = "test.load-test-data"
"""
}
}
}

test("registration - easyreg") {
config "./nextflow.config"
when {
process {
"""
ch_split_test_data = LOAD_DATA.out.test_data_directory
.branch{
t1: it.simpleName == "freesurfer"
b0: it.simpleName == "registration"
}
ch_t1 = ch_split_test_data.t1.map{
test_data_directory -> [
[ id:'test' ],
file("\${test_data_directory}/t1.nii.gz")
]
}
ch_b0 = ch_split_test_data.b0.map{
test_data_directory -> [
[ id:'test' ],
file("\${test_data_directory}/b0.nii.gz"),
[],
[]
]
}
input[0] = ch_t1
.join(ch_b0)
"""
}
}
then {
assertAll(
{ assert process.success },
{ assert snapshot(
file(process.out.ref_seg.get(0).get(1)).name,
file(process.out.flo_seg.get(0).get(1)).name,
niftiMD5SUM(process.out.ref_reg.get(0).get(1), 6),
niftiMD5SUM(process.out.flo_reg.get(0).get(1), 6),
niftiMD5SUM(process.out.fwd_field.get(0).get(1), 6),
niftiMD5SUM(process.out.bak_field.get(0).get(1), 6),
process.out.versions
).match() }
)
}
}
}
20 changes: 20 additions & 0 deletions modules/nf-scil/registration/easyreg/tests/main.nf.test.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"registration - easyreg": {
"content": [
"test_reference_segmentation.nii.gz",
"test_floating_segmentation.nii.gz",
"test_reference_registered.nii.gz:md5:header,c5e41f89848f91c53a9a7be44970d4b1,data,1501221fe23cd62bfdafb33367cadf4d",
"test_floating_registered.nii.gz:md5:header,ec5893cd9ea024e630c4444bd914c331,data,d75ae3fc935cd5cc70ea6797a4c70775",
"test_forward_field.nii.gz:md5:header,0db0a80786ff39864cc17506ed1a0146,data,e4fa6c626729cbf236c34680e5c76df4",
"test_backward_field.nii.gz:md5:header,74c92ee4cd3c4abfecf3da6cdb1d4650,data,8f26afa5c3de21469466213498542486",
[
"versions.yml:md5,4661210880c42a986923e8257f64c760"
]
],
"meta": {
"nf-test": "0.9.0-rc1",
"nextflow": "24.04.4"
},
"timestamp": "2024-09-12T16:01:24.00559"
}
}
9 changes: 9 additions & 0 deletions modules/nf-scil/registration/easyreg/tests/nextflow.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
process {
memory = '10G'
withName: "REGISTRATION_EASYREG" {
publishDir = { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" }
ext.field = true
ext.affine = true
ext.threads = 1
}
}
2 changes: 2 additions & 0 deletions modules/nf-scil/registration/easyreg/tests/tags.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
registration/easyreg:
- "modules/nf-scil/registration/easyreg/**"

0 comments on commit cce5bce

Please sign in to comment.