|
| 1 | + |
| 2 | +process REGISTRATION_COBRALABANTS { |
| 3 | + tag "$meta.id" |
| 4 | + label 'process_medium' |
| 5 | + |
| 6 | + container "scilus/scilus:2.2.1" |
| 7 | + |
| 8 | + input: |
| 9 | + tuple val(meta), path(fixed_image), path(moving_image), path(mask), path(moving_mask, optional: true) |
| 10 | + |
| 11 | + output: |
| 12 | + tuple val(meta), path("*_warped.nii.gz") , emit: image_warped |
| 13 | + tuple val(meta), path("*_forward1_affine.mat") , emit: forward_affine, optional: true |
| 14 | + tuple val(meta), path("*_forward0_warp.nii.gz") , emit: forward_warp, optional: true |
| 15 | + tuple val(meta), path("*_backward1_warp.nii.gz") , emit: backward_warp, optional: true |
| 16 | + tuple val(meta), path("*_backward0_affine.mat") , emit: backward_affine, optional: true |
| 17 | + tuple val(meta), path("*_forward*.{nii.gz,mat}", arity: '1..2') , emit: forward_image_transform |
| 18 | + tuple val(meta), path("*_backward*.{nii.gz,mat}", arity: '1..2') , emit: backward_image_transform |
| 19 | + tuple val(meta), path("*_backward*.{nii.gz,mat}", arity: '1..2') , emit: forward_tractogram_transform |
| 20 | + tuple val(meta), path("*_forward*.{nii.gz,mat}", arity: '1..2') , emit: backward_tractogram_transform |
| 21 | + tuple val(meta), path("*_registration_ants_mqc.gif") , emit: mqc, optional: true |
| 22 | + path "versions.yml" , emit: versions |
| 23 | + |
| 24 | + when: |
| 25 | + task.ext.when == null || task.ext.when |
| 26 | + |
| 27 | + script: |
| 28 | + def args = task.ext.args ?: '' |
| 29 | + def prefix = task.ext.prefix ?: "${meta.id}" |
| 30 | + def suffix_qc = task.ext.suffix_qc ?: "" |
| 31 | + def run_qc = task.ext.run_qc as Boolean || false |
| 32 | + |
| 33 | + if ( mask ) args += " --fixed-mask $mask" |
| 34 | + if ( moving_mask ) args += " --moving-mask $moving_mask" |
| 35 | + if ( task.ext.initial_transform ) args += " --initial-transform $task.ext.initial_transform" |
| 36 | + if ( task.ext.float ) args += " --float" |
| 37 | + if ( task.ext.histogram_matching ) args += " --histogram-matching" |
| 38 | + if ( task.ext.rough ) args += " --rough" |
| 39 | + if ( task.ext.fast ) args += " --fast" |
| 40 | + if ( task.ext.mask_extract ) args += " --mask-extract" |
| 41 | + if ( task.ext.keep_mask_after_extract ) args += " --keep-mask-after-extract" |
| 42 | + if ( task.ext.resampled_linear_output ) args += " --resampled-linear-output $task.ext.resampled_linear_output" |
| 43 | + if ( task.ext.linear_type ) args += " --linear-type $task.ext.linear_type" |
| 44 | + if ( task.ext.close ) args += " --close" |
| 45 | + if ( task.ext.convergence != '1e-6' ) args += " --convergence $task.ext.convergence" |
| 46 | + if ( task.ext.skip_linear ) args += " --skip-linear" |
| 47 | + if ( task.ext.linear_metric != 'Mattes' ) args += " --linear-metric $task.ext.linear_metric" |
| 48 | + if ( task.ext.linear_shrink_factors ) args += " --linear-shrink-factors $task.ext.linear_shrink_factors" |
| 49 | + if ( task.ext.linear_smoothing_sigmas ) args += " --linear-smoothing-sigmas $task.ext.linear_smoothing_sigmas" |
| 50 | + if ( task.ext.linear_convergence ) args += " --linear-convergence $task.ext.linear_convergence" |
| 51 | + if ( task.ext.final_iterations_linear != '50' ) args += " --final-iterations-linear $task.ext.final_iterations_linear" |
| 52 | + if ( task.ext.kmeans_transformed_linear ) args += " --kmeans-transformed-linear" |
| 53 | + if ( task.ext.skip_nonlinear ) args += " --skip-nonlinear" |
| 54 | + if ( task.ext.syn_control != '0.4,4,0' ) args += " --syn-control $task.ext.syn_control" |
| 55 | + if ( task.ext.syn_metric != 'CC[4]' ) args += " --syn-metric $task.ext.syn_metric" |
| 56 | + if ( task.ext.syn_shrink_factors ) args += " --syn-shrink-factors $task.ext.syn_shrink_factors" |
| 57 | + if ( task.ext.syn_smoothing_sigmas ) args += " --syn-smoothing-sigmas $task.ext.syn_smoothing_sigmas" |
| 58 | + if ( task.ext.syn_convergence ) args += " --syn-convergence $task.ext.syn_convergence" |
| 59 | + if ( task.ext.final_iterations_nonlinear != '20' ) args += " --final-iterations-nonlinear $task.ext.final_iterations_nonlinear" |
| 60 | + if ( task.ext.winsorize_image_intensities ) args += " --winsorize-image-intensities $task.ext.winsorize_image_intensities" |
| 61 | + if ( task.ext.clobber ) args += " --clobber" |
| 62 | + if ( task.ext.verbose == false ) args += " --no-verbose" |
| 63 | + if ( task.ext.debug ) args += " --debug" |
| 64 | + |
| 65 | + """ |
| 66 | + export ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS=$task.cpus |
| 67 | + export OMP_NUM_THREADS=1 |
| 68 | + export OPENBLAS_NUM_THREADS=1 |
| 69 | +
|
| 70 | + moving_id=\$(basename $moving_image .nii.gz) |
| 71 | + moving_id=\${moving_id#${meta.id}_*} |
| 72 | +
|
| 73 | + antsRegistration_affine_SyN.sh $args --resampled-output ${prefix}_\${moving_id}_warped.nii.gz $moving_image $fixed_image output |
| 74 | +
|
| 75 | + if [ ${task.ext.skip_linear} == false ]; then |
| 76 | + mv output0GenericAffine.mat ${prefix}_forward1_affine.mat |
| 77 | + fi |
| 78 | +
|
| 79 | + if [ ${task.ext.skip_nonlinear} == false ]; then |
| 80 | + mv output1InverseWarp.nii.gz ${prefix}_backward1_warp.nii.gz |
| 81 | + mv output1Warp.nii.gz ${prefix}_forward0_warp.nii.gz |
| 82 | + fi |
| 83 | +
|
| 84 | + antsApplyTransforms -d 3 -t [${prefix}_forward1_affine.mat,1] \ |
| 85 | + -o Linear[${prefix}_backward0_affine.mat] |
| 86 | +
|
| 87 | + ### ** QC ** ### |
| 88 | + if $run_qc; then |
| 89 | + mv $fixed_image fixed_image.nii.gz |
| 90 | + extract_dim=\$(mrinfo fixed_image.nii.gz -size) |
| 91 | + read sagittal_dim coronal_dim axial_dim <<< "\${extract_dim}" |
| 92 | +
|
| 93 | + # Get the middle slice |
| 94 | + coronal_dim=\$((\$coronal_dim / 2)) |
| 95 | + axial_dim=\$((\$axial_dim / 2)) |
| 96 | + sagittal_dim=\$((\$sagittal_dim / 2)) |
| 97 | +
|
| 98 | + # Get fixed ID, moving ID already computed |
| 99 | + fixed_id=\$(basename $fixed_image .nii.gz) |
| 100 | + fixed_id=\${fixed_id#${meta.id}_*} |
| 101 | +
|
| 102 | + # Set viz params. |
| 103 | + viz_params="--display_slice_number --display_lr --size 256 256" |
| 104 | + # Iterate over images. |
| 105 | + for image in fixed_image warped; do |
| 106 | + mrconvert *\${image}.nii.gz *\${image}_viz.nii.gz -stride -1,2,3 |
| 107 | + scil_viz_volume_screenshot *\${image}_viz.nii.gz \${image}_coronal.png \ |
| 108 | + --slices \$coronal_dim --axis coronal \$viz_params |
| 109 | + scil_viz_volume_screenshot *\${image}_viz.nii.gz \${image}_sagittal.png \ |
| 110 | + --slices \$sagittal_dim --axis sagittal \$viz_params |
| 111 | + scil_viz_volume_screenshot *\${image}_viz.nii.gz \${image}_axial.png \ |
| 112 | + --slices \$axial_dim --axis axial \$viz_params |
| 113 | +
|
| 114 | + if [ \$image != fixed_image ]; then |
| 115 | + title="Warped \${moving_id^^}" |
| 116 | + else |
| 117 | + title="Reference \${fixed_id^^}" |
| 118 | + fi |
| 119 | +
|
| 120 | + convert +append \${image}_coronal*.png \${image}_axial*.png \ |
| 121 | + \${image}_sagittal*.png \${image}_mosaic.png |
| 122 | + convert -annotate +20+230 "\${title}" -fill white -pointsize 30 \ |
| 123 | + \${image}_mosaic.png \${image}_mosaic.png |
| 124 | +
|
| 125 | + # Clean up. |
| 126 | + rm \${image}_coronal*.png \${image}_sagittal*.png \${image}_axial*.png |
| 127 | + done |
| 128 | +
|
| 129 | + # Create GIF. |
| 130 | + convert -delay 10 -loop 0 -morph 10 \ |
| 131 | + warped_mosaic.png fixed_image_mosaic.png warped_mosaic.png \ |
| 132 | + ${prefix}_${suffix_qc}_registration_ants_mqc.gif |
| 133 | +
|
| 134 | + # Clean up. |
| 135 | + rm *_mosaic.png |
| 136 | + fi |
| 137 | +
|
| 138 | + cat <<-END_VERSIONS > versions.yml |
| 139 | + "${task.process}": |
| 140 | + ants: \$(antsRegistration --version | grep "Version" | sed -E 's/.*: v?([0-9.a-zA-Z-]+).*/\\1/') |
| 141 | + imagemagick: \$(convert -version | grep "Version:" | sed -E 's/.*ImageMagick ([0-9.-]+).*/\\1/') |
| 142 | + mrtrix: \$(mrinfo -version 2>&1 | grep "== mrinfo" | sed -E 's/== mrinfo ([0-9.]+).*/\\1/') |
| 143 | + scilpy: \$(uv pip -q -n list | grep scilpy | tr -s ' ' | cut -d' ' -f2) |
| 144 | + END_VERSIONS |
| 145 | + """ |
| 146 | + |
| 147 | + stub: |
| 148 | + def prefix = task.ext.prefix ?: "${meta.id}" |
| 149 | + def suffix_qc = task.ext.suffix_qc ?: "" |
| 150 | + def run_qc = task.ext.run_qc as Boolean || false |
| 151 | + |
| 152 | + """ |
| 153 | + set +e |
| 154 | + function handle_code () { |
| 155 | + local code=\$? |
| 156 | + ignore=( 1 ) |
| 157 | + [[ " \${ignore[@]} " =~ " \$code " ]] || exit \$code |
| 158 | + } |
| 159 | +
|
| 160 | + # Local trap to ignore awaited non-zero exit codes |
| 161 | + { |
| 162 | + trap 'handle_code' ERR |
| 163 | + antsRegistrationSyNQuick.sh -h |
| 164 | + } |
| 165 | +
|
| 166 | + antsApplyTransforms -h |
| 167 | + convert -help . |
| 168 | + scil_viz_volume_screenshot -h |
| 169 | +
|
| 170 | + touch ${prefix}_t1_warped.nii.gz |
| 171 | + touch ${prefix}_forward1_affine.mat |
| 172 | + touch ${prefix}_forward0_warp.nii.gz |
| 173 | + touch ${prefix}_backward1_warp.nii.gz |
| 174 | + touch ${prefix}_backward0_affine.mat |
| 175 | +
|
| 176 | + if $run_qc; then |
| 177 | + touch ${prefix}_${suffix_qc}_registration_ants_mqc.gif |
| 178 | + fi |
| 179 | +
|
| 180 | + cat <<-END_VERSIONS > versions.yml |
| 181 | + "${task.process}": |
| 182 | + ants: \$(antsRegistration --version | grep "Version" | sed -E 's/.*: v?([0-9.a-zA-Z-]+).*/\\1/') |
| 183 | + imagemagick: \$(convert -version | grep "Version:" | sed -E 's/.*ImageMagick ([0-9.-]+).*/\\1/') |
| 184 | + mrtrix: \$(mrinfo -version 2>&1 | grep "== mrinfo" | sed -E 's/== mrinfo ([0-9.]+).*/\\1/') |
| 185 | + scilpy: \$(uv pip -q -n list | grep scilpy | tr -s ' ' | cut -d' ' -f2) |
| 186 | + END_VERSIONS |
| 187 | + """ |
| 188 | +} |
0 commit comments