Accurate non-linear registration of cortical and subcortical labelling from Mindboggle 101 to the symmetric MNI-ICBM2009c atlas followed by manual editing. ants_nl_registration.sh #! /bin/bash if [ $# -eq 3 ];then src=$1 trg=$2 outp=$3 elif [ $# -eq 5 ];then src=$1 trg=$2 src_mask=$3 trg_mask=$4 outp=$5 else echo "Usage $0 [source mask] [target mask] " echo "Output will be 0_NL.xfm and 0NL_inverse.xfm with corresponding grid files" exit 1 fi if [ ! -z $trg_mask ];then mask="-x [${src_mask},${trg_mask}] " fi antsRegistration -v -d 3 --float 1 \ --output "[${outp}]" \ --use-histogram-matching 0 --winsorize-image-intensities "[0.005,0.995]" \ --transform "SyN[0.7,3,0]" \ --metric "CC[${src},${trg},1,4]" \ --convergence "[50x50x30,1e-6,10]" \ --shrink-factors 4x2x1 --smoothing-sigmas 2x1x0vox \ ${mask} --minc bestlinreg_s2 #! /usr/bin/env perl # # linear fitting using parameters optimised by Claude Lepage, # using a brain mask for the source and the target. This was # greatly inspired by best1stepnlreg.pl by Steve Robbins. # # Claude Lepage - claude@bic.mni.mcgill.ca # Andrew Janke - rotor@cmr.uq.edu.au # Center for Magnetic Resonance # The University of Queensland # http://www.cmr.uq.edu.au/~rotor # # Copyright Andrew Janke, The University of Queensland. # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, # provided that the above copyright notice appear in all copies. The # author and the University of Queensland make no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. use strict; use warnings "all"; use Getopt::Tabular; use File::Basename; use File::Temp qw/ tempdir /; my @conf = ( { type => "blur", trans => [qw/-est_translations/], blur_fwhm => 16, steps => [qw/8 8 8/], tolerance => 0.01, simplex => 32 }, { type => "blur", trans => undef, blur_fwhm => 8, steps => [qw/4 4 4/], tolerance => 0.004, simplex => 16 }, { type => "blur", trans => undef, blur_fwhm => 4, steps => [qw/4 4 4/], tolerance => 0.004, simplex => 8 }, { type => "dxyz", trans => undef, blur_fwhm => 8, steps => [qw/4 4 4/], tolerance => 0.004, simplex => 4 }, { type => "dxyz", trans => undef, blur_fwhm => 4, steps => [qw/4 4 4/], tolerance => 0.004, simplex => 2 } ); my($Help, $Usage, $me); my(@opt_table, %opt, $source, $target, $outxfm, $outfile, @args, $tmpdir); $me = &basename($0); %opt = ( 'verbose' => 1, 'clobber' => 0, 'fake' => 0, 'init_xfm' => undef, 'source_mask' => undef, 'target_mask' => undef, 'lsqtype' => "-lsq9", 'work_dir' => undef, 'sec_source' => undef, 'sec_target' => undef, 'cost_function' => '-xcorr', 'noshear' => 0, 'noscale' => 0, 'norot' => 0, 'noshift' => 0, 'close' => 0, ); $Help = < 1, CLEANUP => 1 ); $opt{work_dir}=$tmpdir unless $opt{work_dir}; # set up filename base my($i, $s_base, $t_base, $tmp_xfm, $tmp_source, $tmp_target, $prev_xfm, $tmp_sec_source, $tmp_sec_target); $s_base = &basename($source); $s_base =~ s/\.mnc(.gz)?$//; $s_base = 's_'.$s_base; $t_base = &basename($target); $t_base =~ s/\.mnc(.gz)?$//; $t_base = 't_'.$t_base; # Mask the source and target once before blurring. Both masks must exist. my $source_masked = $source; my $target_masked = $target; # initial transformation supplied by the user, applied to both the # source image and its mask. #if( defined $opt{init_xfm} ) { # my $source_resampled = "${tmpdir}/${s_base}_resampled.mnc"; # &do_cmd( 'mincresample', # '-clobber', # '-like', $target_masked, # '-transform', $opt{init_xfm}, # $source_masked, $source_resampled ); # $source_masked = $source_resampled; # #apply it to the mask, if it's defined # if(defined($opt{source_mask})) # { # my $mask_resampled = "${tmpdir}/${s_base}_mask_resampled.mnc"; # &do_cmd( 'mincresample', '-clobber', '-like', $target_masked, # '-nearest_neighbour', '-transform', $opt{init_xfm}, # $opt{source_mask}, $mask_resampled ); # $opt{source_mask} = $mask_resampled; # } #} $prev_xfm = undef; # a fitting we shall go... for ($i=0; $i<=$#conf; $i++){ # set up intermediate files $tmp_xfm = "$tmpdir/$s_base\_$i.xfm"; $tmp_source = "$opt{work_dir}/$s_base\_$conf[$i]{blur_fwhm}"; $tmp_target = "$opt{work_dir}/$t_base\_$conf[$i]{blur_fwhm}"; $tmp_source = "$opt{work_dir}/$s_base\_$conf[$i]{blur_fwhm}"; $tmp_target = "$opt{work_dir}/$t_base\_$conf[$i]{blur_fwhm}"; if($opt{close}) { next if($conf[$i]{blur_fwhm}>8); $conf[$i]{simplex}=1; $conf[$i]{steps}=[qw/2 2 2/]; } print STDOUT "-+-------------------------[$i]-------------------------\n". " | steps: @{$conf[$i]{steps}}\n". " | blur_fwhm: $conf[$i]{blur_fwhm}\n". " | simplex: $conf[$i]{simplex}\n". " | source: $tmp_source\_$conf[$i]{type}.mnc\n". " | target: $tmp_target\_$conf[$i]{type}.mnc\n". " | xfm: $tmp_xfm\n". "-+-----------------------------------------------------\n". "\n"; # blur the masked source and target images my @grad_opt = (); push( @grad_opt, '-gradient' ) if( $conf[$i]{type} eq "dxyz" ); if($conf[$i]{blur_fwhm}>0) # actually this should be 1 { if(!-e "$tmp_source\_$conf[$i]{type}.mnc") { &do_cmd('mincblur', '-clobber', '-no_apodize', '-fwhm', $conf[$i]{blur_fwhm}, @grad_opt, $source_masked, $tmp_source); } if(!-e "$tmp_target\_$conf[$i]{type}.mnc") { &do_cmd('mincblur', '-clobber', '-no_apodize', '-fwhm', $conf[$i]{blur_fwhm}, @grad_opt, $target_masked, $tmp_target); } if(defined($opt{sec_source}) && defined($opt{sec_target}) ) { $tmp_sec_source = "$opt{work_dir}/sec_$s_base\_$conf[$i]{blur_fwhm}"; $tmp_sec_target = "$opt{work_dir}/sec_$t_base\_$conf[$i]{blur_fwhm}"; if(! -e "$tmp_sec_source\_$conf[$i]{type}.mnc") { &do_cmd('mincblur', '-clobber', '-no_apodize', '-fwhm', $conf[$i]{blur_fwhm}, @grad_opt, $opt{sec_source}, $tmp_sec_source); } if(! -e "$tmp_sec_target\_$conf[$i]{type}.mnc") { &do_cmd('mincblur', '-clobber', '-no_apodize', '-fwhm', $conf[$i]{blur_fwhm}, @grad_opt, $opt{sec_target}, $tmp_sec_target); } $tmp_sec_source="$tmp_sec_source\_$conf[$i]{type}.mnc"; $tmp_sec_target="$tmp_sec_target\_$conf[$i]{type}.mnc"; } } else { # noop if(!-e "$tmp_source\_$conf[$i]{type}.mnc") { do_cmd('ln','-s',$source_masked,"$tmp_source\_$conf[$i]{type}.mnc"); } if(!-e "$tmp_target\_$conf[$i]{type}.mnc") { &do_cmd('ln', '-s', $target_masked, "$tmp_target\_$conf[$i]{type}.mnc"); } if(defined($opt{sec_source}) && defined($opt{sec_target}) ) { $tmp_sec_source =$opt{sec_source}; $tmp_sec_target =$opt{sec_target}; } } # set up registration @args = ('minctracc', '-clobber', $opt{lsqtype}, '-step', @{$conf[$i]{steps}}, '-simplex', $conf[$i]{simplex}, '-tol', $conf[$i]{tolerance}); # Initial transformation will be computed from the from Principal axis # transformation (PAT). push(@args, @{$conf[$i]{trans}}) if( defined $conf[$i]{trans} && !$opt{init_xfm} ); # Current transformation at this step if( defined $prev_xfm ) { push(@args, '-transformation', $prev_xfm ) ; } elsif( defined $opt{init_xfm} ) { push(@args, '-transformation', $opt{init_xfm} ) ; #push(@args, '-est_center' ) ; } elsif($opt{close}) { push(@args, '-identity') ; } # masks (even if the blurred image is masked, it's still preferable # to use the mask in minctracc) push(@args, '-source_mask', $opt{source_mask} ) if defined($opt{source_mask}); push(@args, '-model_mask', $opt{target_mask}) if defined($opt{target_mask}); if($tmp_sec_source && $tmp_sec_target ) { push(@args, $opt{cost_function}, "$tmp_source\_$conf[$i]{type}.mnc", "$tmp_target\_$conf[$i]{type}.mnc"); push(@args, '-feature_vol',$tmp_sec_source,$tmp_sec_target,'xcorr',1.0); } else { push(@args, $opt{cost_function},"$tmp_source\_$conf[$i]{type}.mnc", "$tmp_target\_$conf[$i]{type}.mnc"); } push @args,'-w_shear',0,0,0 if $opt{noshear}; push @args,'-w_scales',0,0,0 if $opt{noscale}; push @args,'-w_translations',0,0,0 if $opt{noshift}; push @args,'-w_rotations',0,0,0 if $opt{norot}; # add files and run registration push(@args, $tmp_xfm); &do_cmd(@args); $prev_xfm = $tmp_xfm; } # Concatenate transformations if an initial transformation was given. #if( defined $opt{init_xfm} ) { # &do_cmd( 'xfmconcat', $prev_xfm, $opt{init_xfm}, $outxfm ); #} else { do_cmd( 'mv', '-f', $prev_xfm, $outxfm ); #} # resample if required if(defined($outfile)){ print STDOUT "-+- creating $outfile using $outxfm\n". &do_cmd( 'mincresample', '-clobber', '-like', $target, '-transformation', $outxfm, $source, $outfile ); } sub do_cmd { print STDOUT "@_\n" if $opt{verbose}; if(!$opt{fake}){ system(@_) == 0 or die; } } linear_registration.sh bestlinreg_s2 DKT_Atlas.mnc mni_icbm152_t1_tal_nlin_sym_09c.mnc DKT2icbm.xfm --lsq9 resampling.sh itk_resample DKT_Atlas.mnc --like mni_icbm152_t1_tal_nlin_sym_09c.mnc --transform DKT2icbmnl.xfm DKT_Atlas_icbm_nl.mnc --label --clobber CerebrA_LabelDetails.csv Mindboggle ID,Label Name,CerebrA ID,,Notes,Dice Kappa ,,RH Labels,LH Labels,, 2002,Caudal Anterior Cingulate,30,81,,0.79 2003,Caudal Middle Frontal,42,93,Improved distinction from Precentral ,0.73 2005,Cuneus,43,94,,0.67 2006,Entorhinal,36,87,Improved delimitation ,0.78 2007,Fusiform,24,75,,0.77 2008,Inferior Parietal,10,61,,0.75 2009,Inferior temporal,3,54,Removed dorsal part MT,0.72 2010,Isthmus Cingulate,33,84,,0.79 2011,Lateral Occipital,34,85,,0.76 2012,Lateral Orbitofrontal,7,58,,0.8 2013,Lingual,12,63,,0.75 2014,Medial Orbitofrontal,15,66,,0.72 2015,Middle Temporal,28,79,Added dorsal part,0.72 2016,Parahippocampal,18,69,,0.86 2017,Paracentral,16,67,,0.77 2018,Pars Opercularis,32,83,,0.77 2019,Pars Orbitalis,44,95,,0.8 2020,Pars Triangularis,22,73,,0.76 2021,Pericalcarine,6,57,,0.6 2022,Postcentral,13,64,,0.82 2023,Posterior Cingulate,47,98,,0.8 2024,Precentral,35,86,,0.84 2025,Precuneus,31,82,,0.8 2026,Rostral Anterior Cingulate,8,59,,0.72 2027,Rostral Middle Frontal,1,52,Improved delimitation from CMF,0.74 2028,Superior Frontal,38,89,,0.82 2029,Superior Parietal,9,60,Improved delimitation from Precuneus and IP,0.72 2030,Superior Temporal,45,96,Added dorsal part limiting with IP and Supramarginal,0.87 2031,Supramarginal,51,102,,0.81 2034,Transverse Temporal,14,65,,0.85 2035,Insula,23,74,,0.88 16,Brainstem,11,62,"Completed filling, removed labelled voxels out of actual brainstem and removed CWM labels in brainstem area. ",0.65 14,Third Ventricle,29,80,,0.68 15,Fourth Ventricle,37,88,Missing label. Manually delimited using CSF threshold. ,0.39 85,Optic Chiasm,17,68,Almost inexistent label and out of place in original labelling Completed OC and tracts (originally labelled as Ventral Diencephalon),0 43,Lateral Ventricle,41,92,Improved continuity of labelled voxels,0.89 44,Inferior Lateral Ventricle,5,56,,0.12 45,Cerebellum Gray Matter,46,97,"Completed filling using threshold for CGM, removed cerebellum labels out of area (within brainstem and vermis area)",0.83 46,Cerebellum White Matter,39,90,"Improved according threshold for CWM, removed labels in brainstem and vermis. ",0.73 49,Thalamus,40,91,,0.97 50,Caudate,49,100,Completed filling using threshold ,0.84 51,Putamen,21,72,Corrected uniformity using threshold,0.87 52,Pallidum,27,78,Improved delimitation between putamen and pallidum,0.83 53,Hippocampus,48,99,,0.69 54,Amygdala,19,70,,0.64 58,Accumbens Area,4,55,,0.76 60,Ventral Diencephalon,26,77,,0.93 92,Basal Forebrain,25,76,,0.82 630,Vermal lobules I-V,50,101,Improved delimitation with other vermal lobules and cerebellar hemispheres,0.66 631,Vermal lobules VI-VII,2,53,Improved delimitation with other vermal lobules and cerebellar hemispheres,0.38 632,Vermal lobules VIII-X,20,71,Improved delimitation with other vermal lobules and cerebellar hemispheres,0.44