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

[Module] Freesurfer synthregistration #54

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0b60476
Change org_path
anroy1 Aug 31, 2024
e33d495
initial module commit
anroy1 Jan 9, 2024
bc367df
manage output format for ants and include init transform as output
anroy1 Jan 14, 2024
972abf6
quick fix
anroy1 Jan 19, 2024
4258f52
test fix 1
anroy1 Jan 26, 2024
d2d0e4a
2nd fix for tests
anroy1 Jan 26, 2024
41131a8
quick fix
anroy1 Feb 13, 2024
d82ae82
test naming fix
anroy1 Feb 21, 2024
7c274d0
fix scilpy fetcher path
anroy1 Feb 22, 2024
1f34c3a
fix tests parameters
anroy1 Feb 22, 2024
41f8859
[WIP] modify module and test to manage freesurfer license
anroy1 Mar 1, 2024
b51f537
fix test data, freesurfer license
anroy1 Apr 9, 2024
bacd6cb
[WIP] improve test
anroy1 Apr 10, 2024
496ac48
Adjust nextflow config and output format
anroy1 Apr 16, 2024
b632962
Swith transform format to freesurfer standard
anroy1 Apr 20, 2024
077f420
run prettier
anroy1 Apr 25, 2024
98209d4
Remove license as module do not require it and update parameters with…
anroy1 May 9, 2024
d47cbed
Switch transform output to fs .nii.gz format
anroy1 May 14, 2024
ce493f8
Migrate tests to nf-tests
anroy1 Jun 1, 2024
1cfe90d
fix nf-tests
anroy1 Jun 5, 2024
2aff22f
Remove pytests
anroy1 Jun 5, 2024
6df7ba4
Run prettier
anroy1 Jun 5, 2024
2967f20
Modify tests config for remote tests
anroy1 Jun 5, 2024
d094e65
Fix test assertion for name only
anroy1 Jun 5, 2024
b95c032
Rerun tests and fix linting
anroy1 Jun 6, 2024
3299ec0
adjust process parameters for tests locally
anroy1 Jun 11, 2024
afd5884
[wip] fix alex comments 1/2
anroy1 Jun 13, 2024
6c8468b
Add precisions regarding convertion on meta.yml
anroy1 Jun 14, 2024
b46749c
Handling threads in script
anroy1 Aug 7, 2024
48e5584
change container version
anroy1 Aug 8, 2024
614dd42
Use nifti md5sum assertion
anroy1 Aug 15, 2024
a1f8f2d
test with niftiMD5SUM
anroy1 Sep 7, 2024
6984f7a
Revert "Change org_path"
anroy1 Sep 7, 2024
ecc4482
fix test
anroy1 Sep 17, 2024
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
3 changes: 3 additions & 0 deletions .test_data/heavy/freesurfer/license.txt
Git LFS file not shown
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
name: "registration_synthregistration"
channels:
- Docker
- Apptainer
dependencies:
- "Freesurfer:synthmorph"
63 changes: 63 additions & 0 deletions modules/nf-scil/registration/synthregistration/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
process REGISTRATION_SYNTHREGISTRATION {
tag "$meta.id"
label 'process_single'

container "freesurfer/synthmorph:3"
containerOptions "--entrypoint ''"

input:
tuple val(meta), path(moving), path(fixed)

output:
tuple val(meta), path("*__output_warped.nii.gz"), emit: warped_image
tuple val(meta), path("*__deform_warp.nii.gz"), emit: deform_transform
tuple val (meta), path("*__init_warp.lta"), emit: init_transform
path "versions.yml" , emit: versions

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

script:
def args = task.ext.args ?: ''
def prefix = task.ext.prefix ?: "${meta.id}"

def init = task.ext.init ? "-m " + task.ext.init : "-m affine"
def warp = task.ext.warp ? "-m " + task.ext.warp : "-m deform"
def header = task.ext.header ? "-H" : ""
def gpu = task.ext.gpu ? "-g" : ""
def lambda = task.ext.lambda ? "-r " + task.ext.lambda : ""
def steps = task.ext.steps ? "-n " + task.ext.steps : ""
def extent = task.ext.extent ? "-e " + task.ext.extent : ""
def weight = task.ext.weight ? "-w " + task.ext.weight : ""

"""
export ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS=1
export OMP_NUM_THREADS=1
export OPENBLAS_NUM_THREADS=1

mri_synthmorph -j $task.cpus ${init} -t ${prefix}__init_warp.lta $moving $fixed
mri_synthmorph -j $task.cpus ${warp} ${gpu} ${lambda} ${steps} ${extent} ${weight} -i ${prefix}__init_warp.lta -t ${prefix}__deform_warp.nii.gz -o ${prefix}__output_warped.nii.gz $moving $fixed

cat <<-END_VERSIONS > versions.yml
"${task.process}":
Freesurfer: 7.4
END_VERSIONS
"""

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

"""
mri_synthmorph -h

touch ${prefix}__output_warped.nii.gz
touch ${prefix}__deform_warp.nii.gz
touch ${prefix}__init_warp.lta

cat <<-END_VERSIONS > versions.yml
"${task.process}":
Freesurfer: 7.4
END_VERSIONS
"""
}
58 changes: 58 additions & 0 deletions modules/nf-scil/registration/synthregistration/meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
name: "registration_synthregistration"
description: Perform registration using SynthMorph from Freesurfer. Outputs transforms in Freesurfer format .lta for affine and .nii.gz (synthmorph also supports .mgz) for deform, both in RAS orientation, which can be converted for ANTs with respectively lta_convert and mri_warp_convert, which support a wide range of conversion formats and orientations. Conversion can be processed using the registration/convert module which can be used successively to this one.
keywords:
- registration
- Brain imaging
- MRI
tools:
- "Freesurfer":
description: "Freesurfer Synthmorph"
homepage: "https://martinos.org/malte/synthmorph/"

input:
- meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'test', single_end:false ]`

- moving:
type: file
description: Nifti volume moving for registration
pattern: "*.{nii,nii.gz}"

- fixed:
type: file
description: Nifti volume fixed for registration
pattern: "*.{nii,nii.gz}"

output:
- meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'test', single_end:false ]`

- init_transform:
anroy1 marked this conversation as resolved.
Show resolved Hide resolved
type: file
description: Affine transform for initialization
pattern: "*.{lta}"

- deform_transform:
type: file
description: Deform transformation
pattern: "*.{nii.gz}"

- warped_image:
type: file
description: Warped image
pattern: "*.{nii,.nii.gz}"

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

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

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

tag "modules"
tag "modules_nfcore"
tag "registration"
tag "registration/synthregistration"

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" ] )
input[1] = "test.load-test-data"
"""
}
}
}

test("registration - synthregistration") {
config "./nextflow.config"
when {
process {
"""
input[0] = LOAD_DATA.out.test_data_directory
.map{ test_data_directory -> [
[ id:'test', single_end:false ],
file("\${test_data_directory}/t1.nii.gz"),
file("\${test_data_directory}/fa.nii.gz")
]}
"""
}
}
then {
assertAll(
{ assert process.success },
{ assert snapshot(
niftiMD5SUM(process.out.warped_image.get(0).get(1)),
niftiMD5SUM(process.out.deform_transform.get(0).get(1)),
process.out.init_transform,
process.out.versions
).match() }
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"registration - synthregistration": {
"content": [
"test__output_warped.nii.gz:md5:header,a1c8a7cfd88d5b632700819988507e8b,data,2526d950d4d6786c40faf5285e2f08af",
"test__deform_warp.nii.gz:md5:header,4a9989cf78e087331c587e0d656ee96f,data,3dcaa6acc0ee1a933d8792d9c2fc740d",
[
[
{
"id": "test",
"single_end": false
},
"test__init_warp.lta:md5,eb15bf7f338f1d5bd71227c40b6dbc68"
]
],
[
"versions.yml:md5,49fb9c85da9f696926d1ab46ef0968fb"
]
],
"meta": {
"nf-test": "0.9.0-rc1",
"nextflow": "24.04.4"
},
"timestamp": "2024-09-17T20:25:42.083995"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
process {
withName: "REGISTRATION_SYNTHREGISTRATION" {
publishDir = { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" }
memory = 20
ext.init = "affine"
ext.warp = "deform"
ext.threads = 1
ext.lambda = 0.9
ext.steps = 9
}
}
2 changes: 2 additions & 0 deletions modules/nf-scil/registration/synthregistration/tests/tags.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
registration/synthregistration:
- "modules/nf-scil/registration/synthregistration/**"
Loading