#! /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; } }