Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

optimize.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- 00002 @COPYRIGHT : 00003 Copyright 1993,1994,1995 David MacDonald, 00004 Peter Neelin, Louis Collins, 00005 McConnell Brain Imaging Centre, 00006 Montreal Neurological Institute, McGill University. 00007 Permission to use, copy, modify, and distribute this 00008 software and its documentation for any purpose and without 00009 fee is hereby granted, provided that the above copyright 00010 notice appear in all copies. The author and McGill University 00011 make no representations about the suitability of this 00012 software for any purpose. It is provided "as is" without 00013 express or implied warranty. 00014 ---------------------------------------------------------------------------- */ 00015 00016 #include <volume_io/internal_volume_io.h> 00017 #include <bicpl/trans.h> 00018 #include <bicpl/numerical.h> 00019 00020 #ifndef lint 00021 static char rcsid[] = "$Header: /software/source//libraries/bicpl/Transforms/optimize.c,v 1.15 2000/02/06 15:30:50 stever Exp $"; 00022 #endif 00023 00024 #define FUNCTION_TOLERANCE 1e-6 00025 #define INITIAL_SIMPLEX_SIZE 3.0 00026 #define MAX_ITERS 300 00027 00028 typedef struct 00029 { 00030 int ndim; 00031 int npoints; 00032 Real *center; 00033 Real **pts1; 00034 Real **pts2; 00035 } function_data; 00036 00037 /* ----------------------------- MNI Header ----------------------------------- 00038 @NAME : lsq_objective 00039 @INPUT : lt - a transformation matrix 00040 pts1 00041 pts2 00042 npoints 00043 @OUTPUT : 00044 @RETURNS : sum of square error 00045 @DESCRIPTION: Transforms the pts2 and takes the sum squared distance from 00046 pts1. 00047 @GLOBALS : 00048 @CALLS : 00049 @CREATED : 00050 @MODIFIED : 00051 00052 ---------------------------------------------------------------------------- */ 00053 00054 private Real lsq_objective( 00055 Transform *lt, 00056 Real **pts1, 00057 Real **pts2, 00058 int npoints ) 00059 { 00060 int i, j; 00061 Real sum, error2, delta; 00062 Real newpt[N_DIMENSIONS]; 00063 00064 sum = 0.0; 00065 00066 for_less( i, 0, npoints ) /* for all of the points */ 00067 { 00068 transform_point( lt, pts2[i][X], pts2[i][Y], pts2[i][Z], 00069 &newpt[X], &newpt[Y], &newpt[Z] ); 00070 00071 error2 = 0.0; /* compare it to pts2, summing the squared error */ 00072 00073 for_less( j, 0, N_DIMENSIONS ) 00074 { 00075 delta = newpt[j] - pts1[i][j]; 00076 error2 += delta * delta; 00077 } 00078 00079 sum += error2; 00080 } 00081 00082 return( sum); 00083 } 00084 00085 /* ----------------------------- MNI Header ----------------------------------- 00086 @NAME : fit_function 00087 @INPUT : func_data - info for evaluation the fit function 00088 params - a variable length array of real 00089 @OUTPUT : 00090 @RETURNS : a Real value of the user requested objective function, 00091 measuring the similarity between two data sets. 00092 @DESCRIPTION: This function 00093 is passed to the general purpose amoeba routine to be called 00094 as the function to minimize. 00095 @METHOD : 00096 @GLOBALS : 00097 @CALLS : 00098 @CREATED : 00099 @MODIFIED : 00100 ---------------------------------------------------------------------------- */ 00101 00102 private Real fit_function( 00103 void *func_data, 00104 float params[] ) 00105 { 00106 Transform transform; 00107 int i; 00108 Real r; 00109 Real trans[3]; 00110 Real cent[3]; 00111 Real rots[3]; 00112 Real scale[3]; 00113 Real shear[3]; 00114 function_data *data; 00115 00116 data = (function_data *) func_data; 00117 00118 for_less( i, 0, 3 ) { 00119 trans[i] = (Real) params[i+0]; /* set translations */ 00120 rots[i] = (Real) params[i+3]; /* set rotations */ 00121 scale[i] = (Real) params[i+6]; /* set scales */ 00122 } 00123 00124 for_less( i, 0, 3 ) /* set shears */ 00125 shear[i] = 0.0; 00126 00127 if( data->ndim == 10 ) 00128 shear[0] = (Real) params[9]; 00129 00130 for_less( i, 0, 3 ) 00131 cent[i] = data->center[i]; /* global CENTER used here */ 00132 00133 build_transformation_matrix( &transform, cent, trans, scale, shear, rots ); 00134 00135 /* call the needed objective function */ 00136 00137 r = lsq_objective( &transform, data->pts1, data->pts2, data->npoints ); 00138 00139 return(r); 00140 } 00141 00142 00143 /* ----------------------------- MNI Header ----------------------------------- 00144 @NAME : optimize_simplex 00145 get the parameters necessary to map point set 1 to point set 2 00146 using the simplex optimization algorithm. 00147 @INPUT : pts1,pts2 - two sets of 3D coordinates 00148 npoints - number of points in the two lists 00149 trans_type = TRANS_LSQ9 or TRANS_LSQ10 00150 center - array of center of rotation/scaling 00151 @OUTPUT : translation 00152 scales 00153 shears 00154 rotations 00155 @RETURNS : TRUE if ok, FALSE if error. 00156 @DESCRIPTION: 00157 @METHOD : uses the ameoba simplex algorithm from numerical recipes. 00158 @GLOBALS : 00159 @CALLS : 00160 @CREATED : September 2, 1993 Louis 00161 @MODIFIED : July 4, 1995 D. MacDonald - removed recipes-style code 00162 ---------------------------------------------------------------------------- */ 00163 00164 public BOOLEAN optimize_simplex( 00165 Real **pts1, 00166 Real **pts2, 00167 int npoints, 00168 Trans_type trans_type, 00169 Real center[], 00170 Real translations[], 00171 Real scales[], 00172 Real shears[], 00173 Real rotations[] ) 00174 { 00175 Real initial_guess[10], solution[10], initial_step[10]; 00176 int i, ndim, iters; 00177 function_data func_data; 00178 amoeba_struct amoeba; 00179 00180 switch (trans_type) /* check to see if trans_type is OK */ 00181 { 00182 case TRANS_LSQ9: 00183 ndim = 9; 00184 break; 00185 case TRANS_LSQ10: 00186 ndim = 10; 00187 break; 00188 default: 00189 print_error( "Unknown type of transformation requested (%d)\n", 00190 trans_type); 00191 print_error( "Error in line %d, file %s\n",__LINE__, __FILE__); 00192 return( FALSE ); 00193 } 00194 00195 /*--- initialize the function data for the function to be minimized */ 00196 00197 func_data.pts1 = pts1; 00198 func_data.pts2 = pts2; 00199 func_data.npoints = npoints; 00200 func_data.center = center; 00201 func_data.ndim = ndim; 00202 00203 /*--- initialize the 9 or 10 parameters of the function, the starting 00204 point for the minimization */ 00205 00206 initial_guess[0] = translations[0]; 00207 initial_guess[1] = translations[1]; 00208 initial_guess[2] = translations[2]; 00209 00210 initial_guess[3] = rotations[0]; 00211 initial_guess[4] = rotations[1]; 00212 initial_guess[5] = rotations[2]; 00213 00214 initial_guess[6] = scales[0]; 00215 initial_guess[7] = scales[1]; 00216 initial_guess[8] = scales[2]; 00217 00218 if( ndim == 10 ) /* one rotation about the x-axis (LR-axis) */ 00219 initial_guess[9] = shears[0]; 00220 00221 /*--- initialize the step sizes for the amoeba minimization */ 00222 00223 initial_step[0] = INITIAL_SIMPLEX_SIZE; 00224 initial_step[1] = INITIAL_SIMPLEX_SIZE; 00225 initial_step[2] = INITIAL_SIMPLEX_SIZE; 00226 00227 initial_step[3] = INITIAL_SIMPLEX_SIZE * DEG_TO_RAD; 00228 initial_step[4] = INITIAL_SIMPLEX_SIZE * DEG_TO_RAD; 00229 initial_step[5] = INITIAL_SIMPLEX_SIZE * DEG_TO_RAD; 00230 00231 initial_step[6] = INITIAL_SIMPLEX_SIZE / 30.0; 00232 initial_step[7] = INITIAL_SIMPLEX_SIZE / 30.0; 00233 initial_step[8] = INITIAL_SIMPLEX_SIZE / 30.0; 00234 00235 if( ndim == 10 ) 00236 initial_step[9] = INITIAL_SIMPLEX_SIZE * DEG_TO_RAD; 00237 00238 /*--- perform the amoeba minimization */ 00239 00240 initialize_amoeba( &amoeba, ndim, initial_guess, initial_step, 00241 fit_function, (void *) &func_data, FUNCTION_TOLERANCE ); 00242 00243 for_less( iters, 0, MAX_ITERS ) 00244 { 00245 if( !perform_amoeba( &amoeba ) ) 00246 break; 00247 } 00248 00249 (void) get_amoeba_parameters( &amoeba, solution ); 00250 00251 terminate_amoeba( &amoeba ); 00252 00253 /*--- copy optimized results */ 00254 00255 for_less( i, 0, 3 ) 00256 { 00257 translations[i] = solution[i+0]; 00258 rotations[i] = solution[i+3]; 00259 scales[i] = solution[i+6]; 00260 } 00261 00262 if( ndim == 10 ) 00263 shears[0] = solution[9]; 00264 00265 return( TRUE ); 00266 }

Generated on Wed Jul 28 09:10:57 2004 for BICPL by doxygen 1.3.7