Skip to content

Commit 86c3f5c

Browse files
authored
Merge pull request #1 from arnaudbore/first_release
First release
2 parents 8120217 + 8753e91 commit 86c3f5c

File tree

3 files changed

+347
-0
lines changed

3 files changed

+347
-0
lines changed

USAGE

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
register_flow pipeline
2+
=====================
3+
4+
Register t1, metrics and tractograms to template space.
5+
We suggest to use https://github.com/scilus/combine_flows to create input.
6+
7+
USAGE
8+
9+
nextflow run main.nf [OPTIONAL_ARGUMENTS] --input --template
10+
11+
DESCRIPTION
12+
13+
--input=/path/to/[root] Root folder containing multiple subjects
14+
[root]
15+
├── S1
16+
│ │── *t1.nii.gz (orig space)
17+
| └── metrics (optional)
18+
| │ └── *.nii.gz
19+
| └── tractograms (optional)
20+
| └── *.trks
21+
└── S2
22+
└── *
23+
24+
--template=/path/to/template_t1.nii.gz Path to a nifti T1 template used for registration.
25+
It has to be named template_t1.nii.gz
26+
27+
OPTIONAL ARGUMENTS (current value)
28+
--linear_registration If set, it will use linear registration instead of non linear registration ($linear_registration).
29+
30+
--quick_registration If set, it will use antsRegistrationSyNQuick.sh instead of antsRegistrationSyN.sh for registration ($quick_registration).
31+
32+
--output_dir Specify a new output directory to avoid overwriting results (when dealing with multiple input labels) ($output_dir).
33+
34+
--processes_register Number of processes for registration task ($processes_register).
35+
36+
--processes The number of parallel processes to launch ($cpu_count).
37+
Only affects the local scheduler.
38+
39+
AVAILABLE PROFILES (using -profile option (e.g. -profile fully_reproducible))
40+
41+
macos When this profile is used, TractoFlow will modify a parameter (scratch) for MacOS users.
42+
43+
fully_reproducible When this profile is used, all the parameters will be set to have 100% reproducible results.
44+
45+
46+
NOTES
47+
48+
To set the number of parallel processes to launch, please use:
49+
'nextflow run -qs {nb_processes}'.
50+
51+
The intermediate working directory is, by default, set to './work'.
52+
To change it, use the '-w WORK_DIR' argument.
53+
54+
The default config file is connectoflow/nextflow.config.
55+
Use '-C config_file.config' to specify a non-default configuration file.
56+
The '-C config_file.config' must be inserted after the nextflow call
57+
like 'nextflow -C config_file.config run ...'.

main.nf

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
#!/usr/bin/env nextflow
2+
3+
if(params.help) {
4+
usage = file("$baseDir/USAGE")
5+
cpu_count = Runtime.runtime.availableProcessors()
6+
7+
bindings = ["quick_registration":"$params.quick_registration",
8+
"linear_registration":"$params.linear_registration",
9+
"output_dir":"$params.output_dir",
10+
"processes_register":"$params.processes_register",
11+
"cpu_count":"$cpu_count"]
12+
13+
engine = new groovy.text.SimpleTemplateEngine()
14+
template = engine.createTemplate(usage.text).make(bindings)
15+
16+
print template.toString()
17+
return
18+
}
19+
20+
log.info "Run Registration to template space"
21+
log.info "============================="
22+
log.info ""
23+
24+
log.info ""
25+
log.info "Start time: $workflow.start"
26+
log.info ""
27+
28+
log.debug "[Command-line]"
29+
log.debug "$workflow.commandLine"
30+
log.debug ""
31+
32+
log.info "[Git Info]"
33+
log.info "$workflow.repository - $workflow.revision [$workflow.commitId]"
34+
log.info ""
35+
36+
log.info "[Inputs]"
37+
log.info "Root: $params.input"
38+
log.info "Template: $params.template"
39+
log.info "Output directory: $params.output_dir"
40+
log.info ""
41+
42+
log.info "Number of processes per tasks"
43+
log.info "============================="
44+
log.info "Template registration: $params.processes_register"
45+
log.info ""
46+
47+
root = file(params.input)
48+
/* Watch out, files are ordered alphabetically in channel */
49+
Channel
50+
.fromPath("$root/**/*t1.nii.gz",
51+
maxDepth:1)
52+
.map{[it.parent.name, it]}
53+
.into{in_t1; subjects_for_count}
54+
55+
in_trks = Channel
56+
.fromFilePairs("$root/**/tractograms/*.trk",
57+
size: -1,
58+
maxDepth:2) {it.parent.parent.name}
59+
60+
if (!params.template.contains("template_t1.nii.gz")) {
61+
error "Error ~ Template filename should be named template_t1.nii.gz."}
62+
63+
Channel.fromPath(file(params.template))
64+
.into{template_for_registration;template_for_transformation_trks;template_for_transformation_metrics; template_check_name}
65+
66+
in_metrics = Channel
67+
.fromFilePairs("$root/**/metrics/*.nii.gz",
68+
size: -1,
69+
maxDepth:2) {it.parent.parent.name}
70+
71+
subjects_for_count.count()
72+
.subscribe{a -> if (a == 0)
73+
error "Error ~ No subjects found. Please check the naming convention, your --input path."}
74+
75+
if (!params.template){
76+
error "Error ~ Please set the template to use."
77+
}
78+
79+
80+
in_t1.combine(template_for_registration).set{anats_for_registration}
81+
82+
process Register_T1_to_template {
83+
cpus params.processes_register
84+
memory '2 GB'
85+
publishDir = params.registration
86+
87+
input:
88+
set sid, file(anat), file(template) from anats_for_registration
89+
90+
output:
91+
set sid, "${sid}__output0GenericAffine.mat", "${sid}__output1Warp.nii.gz", "${sid}__output1InverseWarp.nii.gz" into nonlinear_transformation_for_trks, nonlinear_transformation_for_metrics optional true
92+
set sid, "${sid}__output0GenericAffine.mat" into linear_transformation_for_trks, linear_transformation_for_metrics optional true
93+
set sid, "${sid}__outputWarped.nii.gz" into t1_to_template
94+
95+
script:
96+
"""
97+
${params.script_registration} -d 3 -m ${anat} -f ${template} -n ${task.cpus} -o "${sid}__output" -t ${params.transfo}
98+
"""
99+
}
100+
101+
process Get_T1_Template_Space{
102+
cpus 1
103+
publishDir = params.outdir_t1
104+
105+
input:
106+
set sid, file(t1_warped) from t1_to_template
107+
108+
output:
109+
file "${sid}__t1_to_template.nii.gz"
110+
111+
script:
112+
"""
113+
mv ${t1_warped} ${sid}__t1_to_template.nii.gz
114+
"""
115+
}
116+
117+
Channel.empty()
118+
.into{nonlinear_metrics_transformation_for_metrics; linear_metrics_transformation_for_metrics}
119+
120+
if(params.linear_registration){
121+
in_metrics
122+
.transpose()
123+
.combine(template_for_transformation_metrics)
124+
.combine(linear_transformation_for_metrics, by: 0)
125+
.set{linear_metrics_transformation_for_metrics}
126+
}
127+
else{
128+
in_metrics
129+
.transpose()
130+
.combine(template_for_transformation_metrics)
131+
.combine(nonlinear_transformation_for_metrics, by: 0)
132+
.set{nonlinear_metrics_transformation_for_metrics}
133+
}
134+
135+
process Linear_Registration_Metrics_to_template {
136+
cpus 1
137+
publishDir = params.registration_metrics
138+
139+
input:
140+
set sid, file(metric), file(template), file(transfo) from linear_metrics_transformation_for_metrics
141+
142+
output:
143+
file "*_to_template.nii.gz"
144+
145+
script:
146+
if (params.linear_registration)
147+
"""
148+
if [[ "$metric" == *"nufo"* ]]; then
149+
antsApplyTransforms -d 3 -i $metric -r $template -t $transfo -o ${metric.getSimpleName()}_to_template.nii.gz -n NearestNeighbor
150+
else
151+
antsApplyTransforms -d 3 -i $metric -r $template -t $transfo -o ${metric.getSimpleName()}_to_template.nii.gz
152+
fi
153+
"""
154+
}
155+
156+
process NonLinear_Registration_Metrics_to_template {
157+
cpus 1
158+
publishDir = params.registration_metrics
159+
160+
input:
161+
set sid, file(metric), file(template), file(transfo), file(warp), file(inverse_warp) from nonlinear_metrics_transformation_for_metrics
162+
163+
output:
164+
file "*_to_template.nii.gz"
165+
166+
script:
167+
"""
168+
antsApplyTransforms -d 3 -i $metric -r $template -t $warp $transfo -o ${metric.getSimpleName()}_to_template.nii.gz
169+
"""
170+
}
171+
172+
Channel.empty()
173+
.into{linear_trks_transformation_for_trks; nonlinear_trks_transformation_for_trks}
174+
175+
if(params.linear_registration){
176+
in_trks
177+
.transpose()
178+
.combine(template_for_transformation_trks)
179+
.combine(linear_transformation_for_trks, by: 0)
180+
.set{linear_trks_transformation_for_trks}
181+
}
182+
else{
183+
in_trks
184+
.transpose()
185+
.combine(template_for_transformation_trks)
186+
.combine(nonlinear_transformation_for_trks, by: 0)
187+
.set{nonlinear_trks_transformation_for_trks}
188+
}
189+
190+
process Linear_Registration_Tractograms_to_template {
191+
cpus 1
192+
publishDir = params.registration_trks
193+
194+
input:
195+
set sid, file(tractogram), file(template), file(transfo) from linear_trks_transformation_for_trks
196+
197+
output:
198+
file "*_to_template.trk"
199+
200+
script:
201+
"""
202+
scil_apply_transform_to_tractogram.py ${tractogram} ${template} ${transfo} ${tractogram.getSimpleName()}_to_template.trk --inverse
203+
"""
204+
}
205+
206+
process NonLinear_Registration_Tractograms_to_template {
207+
cpus 1
208+
publishDir = params.registration_trks
209+
210+
input:
211+
set sid, file(tractogram), file(template), file(transfo), file(warp), file(inverse_warp) from nonlinear_trks_transformation_for_trks
212+
213+
output:
214+
file "*_to_template.trk"
215+
216+
script:
217+
"""
218+
scil_apply_transform_to_tractogram.py ${tractogram} ${template} ${transfo} ${tractogram.getSimpleName()}_to_template.trk --inverse --inverse --in_deformation ${inverse_warp}
219+
"""
220+
}

nextflow.config

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
process {
2+
tag = {"$sid"}
3+
publishDir = {"./results_registration/$sid/$task.process"}
4+
errorStrategy = { task.attempt <= 3 ? 'retry' : 'ignore' }
5+
maxRetries = 3
6+
maxErrors = -1
7+
scratch = true
8+
stageInMode = 'copy'
9+
stageOutMode = 'rsync'
10+
}
11+
12+
params {
13+
help=false
14+
root=false
15+
template=false
16+
output_dir="./results_registration/"
17+
18+
params.outdir_t1=[path: {"./$params.output_dir/$sid/"}]
19+
params.registration_metrics=[path: {"./$params.output_dir/$sid/Metrics_into_template_space/"}]
20+
params.registration_trks=[path: {"./$params.output_dir/$sid/Trks_into_template_space/"}]
21+
params.registration=[path: {"./$params.output_dir/$sid/Non-Linear_Registration_To_Template/"}]
22+
23+
// **Transformation** //
24+
transfo="s"
25+
script_registration="antsRegistrationSyN.sh"
26+
linear_registration=false
27+
quick_registration=false
28+
29+
// **Number of processes per tasks**//
30+
processes_register=4
31+
32+
//**Process control**//
33+
processes = false
34+
}
35+
36+
if(params.linear_registration)
37+
{
38+
params.transfo="a"
39+
params.registration=[path: {"./$params.output_dir/$sid/Linear_Registration_To_Template/"}]
40+
}
41+
42+
if(params.quick_registration)
43+
{
44+
params.script_registration="antsRegistrationSyNQuick.sh"
45+
}
46+
47+
if(params.processes) {
48+
if(params.processes > Runtime.runtime.availableProcessors()) {
49+
throw new RuntimeException("Number of processes higher than available CPUs.")
50+
}
51+
else if(params.processes < 1) {
52+
throw new RuntimeException("When set, number of processes must be >= 1 " +
53+
"and smaller or equal to the number of CPUs.")
54+
}
55+
else {
56+
executor.$local.cpus = params.processes
57+
}
58+
}
59+
60+
singularity.autoMounts = true
61+
62+
profiles {
63+
fully_reproducible {
64+
params.processes_register=1
65+
}
66+
67+
macos {
68+
process.scratch="/tmp"
69+
}
70+
}

0 commit comments

Comments
 (0)