Mercurial > hg > minc-tools
changeset 2514:d96afe437734
improved accuracy for non-linear transformation of slices
author | claude <claude> |
---|---|
date | Tue, 06 Jul 2010 19:01:06 +0000 |
parents | 42770fead03b |
children | 3725eeeef3f1 |
files | ChangeLog INSTALL.minc NEWS volume_io/MNI_formats/grid_transforms.c |
diffstat | 4 files changed, 82 insertions(+), 79 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ +2010-07-06 Claude Lepage <claude@bic.mni.mcgill.ca> + * Improved convergence and accuracy for application of non-linear + transformation + 2010-06-28 Andrew L Janke <a.janke@gmail.com> - * Added progs/xfm/xfm2def.c and progs/xfm/xfm2def.man1 + * Added progs/xfm/xfm2def.c and progs/xfm/xfm2def.man1 2010-05-23 Andrew L Janke <a.janke@gmail.com> * changed all calls to H5Acreate2 to the H5Acreate macro
--- a/INSTALL.minc +++ b/INSTALL.minc @@ -23,6 +23,7 @@ ./configure --with-build-path=/usr/local <options> +3. Use NetCDF 4.X and HDF5 1.8.X for minc-2.1.X. Compiling ---------
--- a/NEWS +++ b/NEWS @@ -1,12 +1,16 @@ New in Release 2.1.00 --------------------- +* Improved convergence and accuracy for application of non-linear + transformation +* Set default volume_io caching to none * Added pod2man for man page generation of help for perl scripts * Added minccmp and xfm2def * Added checks for outfiles to minccalc * Added taking first time point for 4D files, -test_size and -sagittal_offset_perc to mincpik -* ported some HDF calls to 1.8.x +* ported some HDF calls to 1.8.x (must now use 1.8.X; 1.6.X no + longer supported from now on) * Added libtoolize/glibtoolize logic in autogen.sh (thanks Sean) * Fixed bug in multidim_array_is_alloced for correct check of memory allocation of image data. Return volume=NULL when memory
--- a/volume_io/MNI_formats/grid_transforms.c +++ b/volume_io/MNI_formats/grid_transforms.c @@ -23,6 +23,7 @@ #define INVERSE_FUNCTION_TOLERANCE 0.01 #define INVERSE_DELTA_TOLERANCE 1.0e-5 + #define MAX_INVERSE_ITERATIONS 20 static void evaluate_grid_volume( @@ -251,10 +252,7 @@ Real error_x, error_y, error_z, error, smallest_e; Real ftol; - ftol = 0.05; - grid_transform_point( transform, x, y, z, &tx, &ty, &tz ); - tx = x - (tx - x); ty = y - (ty - y); tz = z - (tz - z); @@ -273,11 +271,16 @@ best_y = ty; best_z = tz; - while( ++tries < NUMBER_TRIES && smallest_e > ftol ) - { - tx += 0.67 * error_x; - ty += 0.67 * error_y; - tz += 0.67 * error_z; + // Volume volume = (Volume) transform->displacement_volume; + // ftol = 0.05; // good for MNI space at 1mm (grid 2mm or 4mm) + // ftol = 0.001; // good for big brain slice (grid at 0.125, voxel at 0.01mm + // Make the error a fraction of the initial residual. + ftol = 0.05 * smallest_e + 0.0001; + + while( ++tries < NUMBER_TRIES && smallest_e > ftol ) { + tx += 0.95 * error_x; + ty += 0.95 * error_y; + tz += 0.95 * error_z; grid_transform_point( transform, tx, ty, tz, &gx, &gy, &gz ); @@ -287,8 +290,7 @@ error = FABS(error_x) + FABS(error_y) + FABS(error_z); - if( error < smallest_e ) - { + if( error < smallest_e ) { smallest_e = error; best_x = tx; best_y = ty; @@ -348,82 +350,76 @@ /*--- find which of 4 dimensions is the vector dimension */ - for_less( vector_dim, 0, FOUR_DIMS ) - { - for_less( d, 0, N_DIMENSIONS ) - { + for_less( vector_dim, 0, FOUR_DIMS ) { + for_less( d, 0, N_DIMENSIONS ) { if( volume->spatial_axes[d] == vector_dim ) break; } - if( d == N_DIMENSIONS ) break; } get_volume_sizes( volume, sizes ); - bound = (Real) degrees_continuity / 2.0; - - /*--- if near the edges, reduce the degrees of continuity */ + /*--- if a 2-d slice, do best interpolation in the plane */ - for_less( d, 0, FOUR_DIMS ) - { - if( d != vector_dim ) - { - while( degrees_continuity >= -1 && - (voxel[d] < bound || - voxel[d] > (Real) sizes[d] - 1.0 - bound || - bound == (Real) sizes[d] - 1.0 - bound ) ) - { - --degrees_continuity; - if( degrees_continuity == 1 ) - degrees_continuity = 0; - bound = (Real) degrees_continuity / 2.0; - } - } + int is_2dslice = -1; + for_less( d, 0, FOUR_DIMS ) { + if( d == vector_dim ) continue; + if( sizes[d] == 1 ) { + is_2dslice = d; + } } + for_less( d, 0, FOUR_DIMS ) { + if( d == vector_dim || d == is_2dslice ) continue; + if( degrees_continuity+2 > sizes[d] ) degrees_continuity = sizes[d] - 2; + } + + bound = (Real) degrees_continuity / 2.0; + /*--- check to fill in the first derivative */ - if( degrees_continuity < 0 && deriv_x != NULL ) - { - for_less( v, 0, N_COMPONENTS ) - { + if( degrees_continuity < 0 && deriv_x != NULL ) { + for_less( v, 0, N_COMPONENTS ) { deriv_x[v] = 0.0; deriv_y[v] = 0.0; deriv_z[v] = 0.0; } } - /*--- if outside */ + /*--- check if outside */ - if( degrees_continuity == -2 ) - { - for_less( v, 0, N_COMPONENTS ) - values[v] = 0.0; - + for( d = 0; d < FOUR_DIMS; d++ ) { + if( d == vector_dim ) continue; + if( voxel[d] < -0.5 || voxel[d] > sizes[d]-0.5 ) { + for_less( v, 0, N_COMPONENTS ) { + values[v] = 0.0; + } return; + } } /*--- determine the starting positions in the volume to grab control vertices */ id = 0; - for_less( d, 0, FOUR_DIMS ) - { - if( d != vector_dim ) - { + for_less( d, 0, FOUR_DIMS ) { + if( d == vector_dim ) continue; + if( d == is_2dslice ) { + pos = 0.0; + start[d] = 0; + end[d] = 1; + } else { pos = voxel[d] - bound; - start[d] = FLOOR( pos ); - if( voxel[d] == (Real) sizes[d] - 1.0 - bound ) - { - --start[d]; - fraction[id] = 1.0; + start[d] = FLOOR( pos ); + if( start[d] < 0 ) { + start[d] = 0; + } else if( start[d]+degrees_continuity+1 >= sizes[d] ) { + start[d] = sizes[d] - degrees_continuity - 2; } - else - fraction[id] = pos - (Real) start[d]; - end[d] = start[d] + degrees_continuity + 2; + fraction[id] = pos - (double) start[d]; ++id; } } @@ -434,12 +430,10 @@ end[vector_dim] = N_COMPONENTS; inc_so_far = N_COMPONENTS; - for_down( d, FOUR_DIMS-1, 0 ) - { - if( d != vector_dim ) - { + for_down( d, FOUR_DIMS-1, 0 ) { + if( d != vector_dim ) { inc[d] = inc_so_far; - inc_so_far *= degrees_continuity + 2; + inc_so_far *= ( end[d] - start[d] ); } } @@ -466,14 +460,10 @@ ind0 = 0; - for_less( v0, start0, end0 ) - { - for_less( v1, start1, end1 ) - { - for_less( v2, start2, end2 ) - { - for_less( v3, start3, end3 ) - { + for_less( v0, start0, end0 ) { + for_less( v1, start1, end1 ) { + for_less( v2, start2, end2 ) { + for_less( v3, start3, end3 ) { GET_VALUE_4D_TYPED( coefs[ind0], (Real), volume, v0, v1, v2, v3 ); ind0 += inc3; @@ -487,16 +477,19 @@ /*--- interpolate values */ - if( degrees_continuity == -1 ) - { + if( degrees_continuity == -1 ) { for_less( v, 0, N_COMPONENTS ) values[v] = coefs[v]; - } - else - { - evaluate_interpolating_spline( N_DIMENSIONS, fraction, - degrees_continuity + 2, - N_COMPONENTS, coefs, 0, values_derivs ); + } else { + if( is_2dslice == -1 ) { + evaluate_interpolating_spline( N_DIMENSIONS, fraction, + degrees_continuity + 2, + N_COMPONENTS, coefs, 0, values_derivs ); + } else { + evaluate_interpolating_spline( N_DIMENSIONS-1, fraction, + degrees_continuity + 2, + N_COMPONENTS, coefs, 0, values_derivs ); + } /*--- extract values and derivatives from values_derivs */ @@ -505,8 +498,9 @@ else derivs_per_value = 1; - for_less( v, 0, N_COMPONENTS ) + for_less( v, 0, N_COMPONENTS ) { values[v] = values_derivs[v*derivs_per_value]; + } if( deriv_x != NULL ) {