IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 1188


Ignore:
Timestamp:
Jul 6, 2004, 6:05:29 PM (22 years ago)
Author:
gusciora
Message:

...

Location:
trunk/psLib/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/dataManip/psMinimize.c

    r1185 r1188  
    2525#include <math.h>
    2626
    27 #define MAX_LMM_NUM_ITERATIONS 500
     27#define MAX_LMM_ITERATIONS 100
     28#define MAX_MINIMIZE_ITERATIONS 100
    2829typedef struct
    2930{
     
    3839    float (*d_evalModel) (const psVector *, const psVector *, int);
    3940}
    40 psModelData;
    41 // The first argument to evalModel() and
    42 // d_evalModel() specifies the data point.
    43 // It must have the same size as the second
    44 // dimension of *domain.
    45 // The second argument must have the same size
    46 // as *initialGuess and *paramMask.
    47 
     41psMinChi2Data;
    4842
    4943typedef struct
     
    5650    float (*d_evalModel) (const psVector *, const psVector *, int);
    5751}
    58 psModelData2;
     52psMinimizeData;
    5953
    6054
    6155/******************************************************************************
    62 p_psMinFunc(*v, *params): This routine calls the user supplied function to
    63 be minimized.  The "v" argument of this function corresponds to the
    64 parameters of the function to be minimized.
    65  
    66  
     56p_psMinFunc(*params, *funcData): We use the GSL-supplied function
     57gsl_multimin_fdfminimizer_iterate() to minimize an arbitary function supplied
     58by the user.  The GSL function requires the user-supplied function to be in
     59a different format than the psLib format.  The purpose of this procedure is
     60to serve as a GSL-format wrapper for the psLib user-supplied function which
     61is to be minimized.
     62    *params: The parameters of the function to be minimized.  These will be
     63 varied by GSL in order to minimize the function.
     64    *funcData: a psLib struct which contains the data point to be minimized,
     65 the function and derivative function pointers, an initial guess at
     66 the parameters, an option parameter mask, etc.
    6767 *****************************************************************************/
    68 double p_psMinFunc(const gsl_vector *v,
    69                    void *params)
     68double p_psMinFunc(const gsl_vector *params,
     69                   void *funcData)
    7070{
    7171    int i;    // Loop index variable.
    7272    int j;    // Loop index variable.
    7373    float tmpf;    // Temporary floating point variable.
    74     const psVector *restrict coord   = ((psModelData2 *) params)->coord;
    75     const psVector *restrict mask     = ((psModelData2 *) params)->paramMask;
    76     psVector *restrict initialGuess = ((psModelData2 *)params)->initialGuess;
     74    const psVector *restrict coord   = ((psMinimizeData *) funcData)->coord;
     75    const psVector *restrict mask     = ((psMinimizeData *) funcData)->paramMask;
     76    psVector *restrict initialGuess = ((psMinimizeData *)funcData)->initialGuess;
    7777    float (*evalModel)(const psVector *, const psVector *) =
    78         ((psModelData2 *) params)->evalModel;
     78        ((psMinimizeData *) funcData)->evalModel;
    7979    psVector *inputParameterList = NULL;
    8080
     81    // The GSL routines will call this function with the masked parameters
     82    // removed.  However, the user-supplied function (to be modified) does not
     83    // have those parameters removed.  Here will create a new parameter list
     84    // with the masked parameters added (we expand initialGuess).
    8185    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
    82 
    8386    if (mask != NULL) {
    8487        j = 0;
     
    8790                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
    8891            } else {
    89                 inputParameterList->data.F32[i] = gsl_vector_get(v, j++);
    90             }
    91         }
    92     } else {
    93         for (i=0;i<initialGuess->n;i++) {
    94             inputParameterList->data.F32[i] = gsl_vector_get(v, i);
    95         }
    96     }
    97     //printf("HMMM: (%.1f %.1f %.1f %.1f)\n",
    98     //       inputParameterList->data.F32[0],
    99     //       inputParameterList->data.F32[1],
    100     //       coord->data.F32[0],
    101     //       coord->data.F32[1]);
    102 
     92                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
     93            }
     94        }
     95    } else {
     96        for (i=0;i<initialGuess->n;i++) {
     97            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
     98        }
     99    }
     100
     101    // Call the user-supplied function.
    103102    tmpf = evalModel(inputParameterList, coord);
     103
     104    // Free allocated memory and return the value of the function.
    104105    psFree(inputParameterList);
    105     //printf("Called p_psMinFunc()\n");
    106106    return(tmpf);
    107107}
    108108
    109 void p_psMinFuncDeriv(const gsl_vector *v,
    110                       void *params,
     109/******************************************************************************
     110p_psMinFuncDeriv(*params, *funcData): We use the GSL-supplied function
     111gsl_multimin_fdfminimizer_iterate() to minimize an arbitary function supplied
     112by the user.  The GSL function requires the user-supplied function to be in
     113a different format than the psLib format.  The purpose of this procedure is
     114to serve as a GSL-format wrapper for the psLib user-supplied function which
     115is to be minimized.
     116    *params: The parameters of the function to be minimized.  These will be
     117 varied by GSL in order to minimize the function.
     118    *funcData: a psLib struct which contains the data point to be minimized,
     119 the function and derivative function pointers, an initial guess at
     120 the parameters, an option parameter mask, etc.
     121    *df: we calculate the derivative of the function w.r.t. to each parameter
     122 in "params" and return those derivatives in this psVector.
     123 *****************************************************************************/
     124void p_psMinFuncDeriv(const gsl_vector *params,
     125                      void *funcData,
    111126                      gsl_vector *df)
    112127{
     
    114129    int j;    // Loop index variable.
    115130    float tmpf;    // Temporary floating point variable.
    116     const psVector *restrict coord   = ((psModelData2 *) params)->coord;
    117     const psVector *restrict mask     = ((psModelData2 *) params)->paramMask;
    118     psVector *restrict initialGuess = ((psModelData2 *)params)->initialGuess;
     131    const psVector *restrict coord   = ((psMinimizeData *) funcData)->coord;
     132    const psVector *restrict mask     = ((psMinimizeData *) funcData)->paramMask;
     133    psVector *restrict initialGuess = ((psMinimizeData *)funcData)->initialGuess;
    119134    float (*d_evalModel)(const psVector *, const psVector *, int) =
    120         ((psModelData2 *) params)->d_evalModel;
     135        ((psMinimizeData *) funcData)->d_evalModel;
    121136    psVector *inputParameterList = NULL;
    122137
     138    // The GSL routines will call this function with the masked parameters
     139    // removed.  However, the user-supplied function (to be modified) does not
     140    // have those parameters removed.  Here will create a new parameter list
     141    // with the masked parameters added (we expand initialGuess).
    123142    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
    124 
    125143    if (mask != NULL) {
    126144        j = 0;
     
    129147                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
    130148            } else {
    131                 inputParameterList->data.F32[i] = gsl_vector_get(v, j++);
    132             }
    133         }
    134     } else {
    135         for (i=0;i<initialGuess->n;i++) {
    136             inputParameterList->data.F32[i] = gsl_vector_get(v, i);
    137         }
    138     }
    139 
     149                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
     150            }
     151        }
     152    } else {
     153        for (i=0;i<initialGuess->n;i++) {
     154            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
     155        }
     156    }
     157
     158    // Evaluate the derivative w.r.t. each parameter.
     159    // NOTE: we can probably remove the calls for masked parameters.
    140160    for (i=0;i<initialGuess->n;i++) {
    141161        tmpf = d_evalModel(inputParameterList, coord, i);
    142162        gsl_vector_set(df, i, tmpf);
    143163    }
     164
     165    // Free allocated memory.
    144166    psFree(inputParameterList);
    145167}
    146168
    147 /* Compute both f and df together. */
    148 void p_psMinFuncFuncDeriv(const gsl_vector *x,
    149                           void *params,
     169/******************************************************************************
     170    Compute both p_psMinFunc and p_psMinFuncDeriv together.
     171 *****************************************************************************/
     172void p_psMinFuncFuncDeriv(const gsl_vector *params,
     173                          void *funcData,
    150174                          double *f,
    151175                          gsl_vector *df)
    152176{
    153     *f = p_psMinFunc(x, params);
    154     p_psMinFuncDeriv(x, params, df);
     177    *f = p_psMinFunc(params, funcData);
     178    p_psMinFuncDeriv(params, funcData, df);
    155179}
    156180
     
    161185This routine must minimize an arbitrary function; it must determine the set
    162186of parameters of that function such that the
    163  
    164187 *****************************************************************************/
    165188psVector *
     
    175198    int iter = 0;
    176199    gsl_multimin_function_fdf f;
    177     double *xInit = NULL;
    178200    const gsl_multimin_fdfminimizer_type *T;
    179201    gsl_multimin_fdfminimizer *s;
    180     psModelData2 inputData;
     202    psMinimizeData inputData;
    181203    gsl_vector *x;
    182204
     
    188210    inputData.paramCount = 0;
    189211
    190     printf("psMinimize(): initialGuess->n is %d\n", initialGuess->n);
    191     printf("psMinimize(): coord->n is %d\n", coord->n);
    192     printf("psMinimize(): coord is (%.1f, %.1f)\n", coord->data.F32[0],
    193            coord->data.F32[1]);
    194 
     212    // If the user supplied a parameter mask, then count the number of
     213    // non-masked elements.  This will be used later in allocating a vector
     214    // for the parameters.
    195215    if (paramMask != NULL) {
    196216        for (i=0;i<paramMask->n;i++) {
     
    204224
    205225    // The initial guess at the parameters for the function are written into
    206     // the vector inputParameterList.  If the paramMask is not NULL, then those
    207     // parameters are masked out.
    208 
    209     xInit = (double *) psAlloc(inputData.paramCount * sizeof(double));
     226    // the vector inputParameterList.  If the paramMask is not NULL, then
     227    // masked parameters are masked out.
     228    x = gsl_vector_alloc(inputData.paramCount);
    210229    if (paramMask != NULL) {
    211230        j = 0;
    212231        for (i=0;i<initialGuess->n;i++) {
    213232            if (paramMask->data.U8[i] == 0) {
    214                 xInit[j++] = initialGuess->data.F32[i];
    215             }
    216         }
    217     } else {
    218         for (i=0;i<initialGuess->n;i++) {
    219             xInit[i] = initialGuess->data.F32[i];
     233                gsl_vector_set(x, j++, initialGuess->data.F32[i]);
     234            }
     235        }
     236    } else {
     237        for (i=0;i<initialGuess->n;i++) {
     238            gsl_vector_set(x, i, initialGuess->data.F32[i]);
    220239        }
    221240    }
     
    224243    f.fdf = &p_psMinFuncFuncDeriv;
    225244    f.n = inputData.paramCount;
    226     // GUS: is this correct?
    227     //f.params = xInit;
    228245    f.params = &inputData;
    229246
    230 
    231     printf("inputData.paramCount is %d\n", inputData.paramCount);
    232     x = gsl_vector_alloc(inputData.paramCount);
    233     for (i=0;i<inputData.paramCount;i++) {
    234         gsl_vector_set(x, i, xInit[i]);
    235     }
    236247    T = gsl_multimin_fdfminimizer_conjugate_fr;
    237248    s = gsl_multimin_fdfminimizer_alloc(T, inputData.paramCount);
    238 
    239249    gsl_multimin_fdfminimizer_set(s, &f, x, 0.01, 1e-4);
    240 
    241250    do {
    242251        iter++;
     
    251260            printf ("Minimum found at:\n");
    252261
    253     } while (status == GSL_CONTINUE && iter < 100);
     262    } while (status == GSL_CONTINUE && iter < MAX_MINIMIZE_ITERATIONS);
    254263
    255264    // In the above steps we had removed the masked elements from the
     
    270279        }
    271280    }
    272     psFree(xInit);
    273281    return(initialGuess);
    274282}
     
    278286
    279287
    280 // The first argument to evalModel() and
    281 // d_evalModel() specifies the data point.
    282 // It must have the same size as the second
    283 // dimension of *domain.
    284 // The second argument must have the same size
    285 // as *initialGuess and *paramMask.
     288// The first argument to evalModel() and d_evalModel() specifies the data
     289// point.  It must have the same size as the second dimension of *domain.
     290// The second argument must have the same size as *initialGuess and
     291// *paramMask.
    286292
    287293/******************************************************************************
    288  ******************************************************************************
    289 gsl_function_f(x, params, f): This function serves as a standardized wrapper
    290 for the user supplied function which is to be minimized.  The GSL
    291 minimization routines have no knowledge of the user-supplied function.  They
    292 only call this routine, which then calls the user-supplied function.  The
    293 arguments are:
    294  
     294p_psMinChi2Func(*x, *funcData, *outdata): We use the GSL-supplied function
     295gsl_multifit_fdfsolver_iterate() to determine the function parameters that
     296best fit the supllied set of data points.  That GSL function requires the
     297user-supplied function to be in a different format than the psLib format.
     298The purpose of this procedure is to serve as a GSL-format wrapper for the
     299psLib user-supplied function which is to be minimized.
    295300    x: These are the parameters which are to be varied by GSL in order to
    296301 minimized chi2 over the data set.
    297     params: this data structure contains the input values over which the
     302    funcData: this data structure contains the input values over which the
    298303 function will be evaluated, the expected value of the function at
    299304 those points, the amount of error tolerable at those points, a mask
     
    302307    outData: The function is evaluated at each point, then subtract the
    303308 expected value and divide by the error.
    304  ******************************************************************************
    305309 *****************************************************************************/
    306 int gsl_function_f(const gsl_vector *x,
    307                    void *params,
    308                    gsl_vector *outData)
     310int p_psMinChi2Func(const gsl_vector *params,
     311                    void *funcData,
     312                    gsl_vector *outData)
    309313{
    310314    int i;    // Loop index variable.
    311315    int j;    // Loop index variable.
    312316    float tmpf;    // Temporary floating point variable.
    313     const psImage *restrict  domain   = ((psModelData *)params)->domain;
    314     const psVector *restrict data     = ((psModelData *)params)->data;
    315     const psVector *restrict errors   = ((psModelData *) params)->errors;
    316     const psVector *restrict mask     = ((psModelData *) params)->paramMask;
    317     psVector *restrict initialGuess = ((psModelData *)params)->initialGuess;
    318     float (*evalModel)(const psVector *, const psVector *) = ((psModelData *) params)->evalModel;
     317    const psImage *restrict  domain   = ((psMinChi2Data *)funcData)->domain;
     318    const psVector *restrict data     = ((psMinChi2Data *)funcData)->data;
     319    const psVector *restrict errors   = ((psMinChi2Data *) funcData)->errors;
     320    const psVector *restrict mask     = ((psMinChi2Data *) funcData)->paramMask;
     321    psVector *restrict initialGuess = ((psMinChi2Data *)funcData)->initialGuess;
     322    float (*evalModel)(const psVector *, const psVector *) = ((psMinChi2Data *) funcData)->evalModel;
    319323    psVector *inputParameterList = NULL;
    320324    psVector *tmpVecPtr = NULL;
     
    326330    // have those parameters removed.  Here will create a new parameter list
    327331    // with the masked parameters added (we expand initialGuess).
     332
    328333    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
    329 
    330334    if (mask != NULL) {
    331335        j = 0;
     
    334338                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
    335339            } else {
    336                 inputParameterList->data.F32[i] = gsl_vector_get(x, j++);
    337             }
    338         }
    339     } else {
    340         for (i=0;i<initialGuess->n;i++) {
    341             inputParameterList->data.F32[i] = gsl_vector_get(x, i);
    342         }
    343     }
    344 
     340                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
     341            }
     342        }
     343    } else {
     344        for (i=0;i<initialGuess->n;i++) {
     345            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
     346        }
     347    }
     348
     349    // Evaluate the function at each data point.
    345350    for (i=0;i<domain->numRows;i++) {
    346351        for (j=0;j<domain->numCols;j++) {
     
    353358    }
    354359
     360    // Free allocated memory.
    355361    psFree(inputParameterList);
    356362    psFree(tmpVecPtr);
     363
    357364    return GSL_SUCCESS;
    358365}
    359366
    360 int gsl_function_df(const gsl_vector *x,
    361                     void *params,
    362                     gsl_matrix *J)
    363 {
    364     const psImage *restrict domain   = ((psModelData *)params)->domain;
    365     const psVector *restrict errors   = ((psModelData *) params)->errors;
    366     const psVector *restrict mask     = ((psModelData *) params)->paramMask;
    367     psVector *restrict initialGuess = ((psModelData *)params)->initialGuess;
     367int p_psMinChi2FuncDeriv(const gsl_vector *params,
     368                         void *funcData,
     369                         gsl_matrix *J)
     370{
     371    const psImage *restrict domain   = ((psMinChi2Data *)funcData)->domain;
     372    const psVector *restrict errors   = ((psMinChi2Data *) funcData)->errors;
     373    const psVector *restrict mask     = ((psMinChi2Data *) funcData)->paramMask;
     374    psVector *restrict initialGuess = ((psMinChi2Data *)funcData)->initialGuess;
    368375    psVector *inputParameterList = NULL;
    369376    psVector *tmpVecPtr = NULL;
    370     float (*d_evalModel)(const psVector *, const psVector *, int) = ((psModelData *) params)->d_evalModel;
     377    float (*d_evalModel)(const psVector *, const psVector *, int) = ((psMinChi2Data *) funcData)->d_evalModel;
    371378
    372379    size_t i;
     
    380387    // have those parameters removed.  Here will create a new parameter list
    381388    // with the masked parameters added (we expand initialGuess).
     389
    382390    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
    383 
    384391    if (mask != NULL) {
    385392        j = 0;
     
    388395                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
    389396            } else {
    390                 inputParameterList->data.F32[i] = gsl_vector_get(x, j++);
    391             }
    392         }
    393     } else {
    394         for (i=0;i<initialGuess->n;i++) {
    395             inputParameterList->data.F32[i] = gsl_vector_get(x, i);
    396         }
    397     }
    398 
     397                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
     398            }
     399        }
     400    } else {
     401        for (i=0;i<initialGuess->n;i++) {
     402            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
     403        }
     404    }
     405
     406    // Evaluate the derivtaive at each data point, and w.r.t. each parameter.
    399407    for (i=0;i<domain->numRows;i++) {
    400408        for (j=0;j<tmpVecPtr->n;j++) {
     
    413421}
    414422
    415 int gsl_my_function_fdf(const gsl_vector *x,
    416                         void *params,
    417                         gsl_vector *f,
    418                         gsl_matrix *J)
    419 {
    420     gsl_function_f(x, params, f);
    421     gsl_function_df(x, params, J);
     423
     424int p_psMinChi2FuncFuncDeriv(const gsl_vector *params,
     425                             void *funcData,
     426                             gsl_vector *f,
     427                             gsl_matrix *J)
     428{
     429    p_psMinChi2Func(params, funcData, f);
     430    p_psMinChi2FuncDeriv(params, funcData, J);
    422431
    423432    return GSL_SUCCESS;
     
    451460    // minimization.
    452461    gsl_multifit_fdfsolver *s; // GSL data structure.
    453     psModelData inputData;
     462    psMinChi2Data inputData;
    454463    float chiSqOld = 0.0;
    455464
     
    464473    inputData.d_evalModel = DevalModel;
    465474
     475    // If the user supplied a parameter mask, then count the number of
     476    // non-masked elements.  This will be used later in allocating a vector
     477    // for the parameters.
    466478    if (paramMask != NULL) {
    467479        for (i=0;i<paramMask->n;i++) {
     
    477489    // the vector inputParameterList.  If the paramMask is not NULL, then those
    478490    // parameters are masked out.
    479 
    480491    xInit = (double *) psAlloc(inputData.paramCount * sizeof(double));
    481492    if (paramMask != NULL) {
     
    504515    // and the data structures those functions use.
    505516
    506     f.f = &gsl_function_f;
    507     f.df = &gsl_function_df;
    508     f.fdf = &gsl_my_function_fdf;
     517    f.f = &p_psMinChi2Func;
     518    f.df = &p_psMinChi2FuncDeriv;
     519    f.fdf = &p_psMinChi2FuncFuncDeriv;
    509520    f.n = numData;
    510521    f.p = inputData.paramCount;
     
    542553        chiSqOld = *chiSq;
    543554
    544     } while (status == GSL_CONTINUE && iter < MAX_LMM_NUM_ITERATIONS);
     555    } while (status == GSL_CONTINUE && iter < MAX_LMM_ITERATIONS);
    545556
    546557
  • trunk/psLib/src/math/psMinimize.c

    r1185 r1188  
    2525#include <math.h>
    2626
    27 #define MAX_LMM_NUM_ITERATIONS 500
     27#define MAX_LMM_ITERATIONS 100
     28#define MAX_MINIMIZE_ITERATIONS 100
    2829typedef struct
    2930{
     
    3839    float (*d_evalModel) (const psVector *, const psVector *, int);
    3940}
    40 psModelData;
    41 // The first argument to evalModel() and
    42 // d_evalModel() specifies the data point.
    43 // It must have the same size as the second
    44 // dimension of *domain.
    45 // The second argument must have the same size
    46 // as *initialGuess and *paramMask.
    47 
     41psMinChi2Data;
    4842
    4943typedef struct
     
    5650    float (*d_evalModel) (const psVector *, const psVector *, int);
    5751}
    58 psModelData2;
     52psMinimizeData;
    5953
    6054
    6155/******************************************************************************
    62 p_psMinFunc(*v, *params): This routine calls the user supplied function to
    63 be minimized.  The "v" argument of this function corresponds to the
    64 parameters of the function to be minimized.
    65  
    66  
     56p_psMinFunc(*params, *funcData): We use the GSL-supplied function
     57gsl_multimin_fdfminimizer_iterate() to minimize an arbitary function supplied
     58by the user.  The GSL function requires the user-supplied function to be in
     59a different format than the psLib format.  The purpose of this procedure is
     60to serve as a GSL-format wrapper for the psLib user-supplied function which
     61is to be minimized.
     62    *params: The parameters of the function to be minimized.  These will be
     63 varied by GSL in order to minimize the function.
     64    *funcData: a psLib struct which contains the data point to be minimized,
     65 the function and derivative function pointers, an initial guess at
     66 the parameters, an option parameter mask, etc.
    6767 *****************************************************************************/
    68 double p_psMinFunc(const gsl_vector *v,
    69                    void *params)
     68double p_psMinFunc(const gsl_vector *params,
     69                   void *funcData)
    7070{
    7171    int i;    // Loop index variable.
    7272    int j;    // Loop index variable.
    7373    float tmpf;    // Temporary floating point variable.
    74     const psVector *restrict coord   = ((psModelData2 *) params)->coord;
    75     const psVector *restrict mask     = ((psModelData2 *) params)->paramMask;
    76     psVector *restrict initialGuess = ((psModelData2 *)params)->initialGuess;
     74    const psVector *restrict coord   = ((psMinimizeData *) funcData)->coord;
     75    const psVector *restrict mask     = ((psMinimizeData *) funcData)->paramMask;
     76    psVector *restrict initialGuess = ((psMinimizeData *)funcData)->initialGuess;
    7777    float (*evalModel)(const psVector *, const psVector *) =
    78         ((psModelData2 *) params)->evalModel;
     78        ((psMinimizeData *) funcData)->evalModel;
    7979    psVector *inputParameterList = NULL;
    8080
     81    // The GSL routines will call this function with the masked parameters
     82    // removed.  However, the user-supplied function (to be modified) does not
     83    // have those parameters removed.  Here will create a new parameter list
     84    // with the masked parameters added (we expand initialGuess).
    8185    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
    82 
    8386    if (mask != NULL) {
    8487        j = 0;
     
    8790                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
    8891            } else {
    89                 inputParameterList->data.F32[i] = gsl_vector_get(v, j++);
    90             }
    91         }
    92     } else {
    93         for (i=0;i<initialGuess->n;i++) {
    94             inputParameterList->data.F32[i] = gsl_vector_get(v, i);
    95         }
    96     }
    97     //printf("HMMM: (%.1f %.1f %.1f %.1f)\n",
    98     //       inputParameterList->data.F32[0],
    99     //       inputParameterList->data.F32[1],
    100     //       coord->data.F32[0],
    101     //       coord->data.F32[1]);
    102 
     92                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
     93            }
     94        }
     95    } else {
     96        for (i=0;i<initialGuess->n;i++) {
     97            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
     98        }
     99    }
     100
     101    // Call the user-supplied function.
    103102    tmpf = evalModel(inputParameterList, coord);
     103
     104    // Free allocated memory and return the value of the function.
    104105    psFree(inputParameterList);
    105     //printf("Called p_psMinFunc()\n");
    106106    return(tmpf);
    107107}
    108108
    109 void p_psMinFuncDeriv(const gsl_vector *v,
    110                       void *params,
     109/******************************************************************************
     110p_psMinFuncDeriv(*params, *funcData): We use the GSL-supplied function
     111gsl_multimin_fdfminimizer_iterate() to minimize an arbitary function supplied
     112by the user.  The GSL function requires the user-supplied function to be in
     113a different format than the psLib format.  The purpose of this procedure is
     114to serve as a GSL-format wrapper for the psLib user-supplied function which
     115is to be minimized.
     116    *params: The parameters of the function to be minimized.  These will be
     117 varied by GSL in order to minimize the function.
     118    *funcData: a psLib struct which contains the data point to be minimized,
     119 the function and derivative function pointers, an initial guess at
     120 the parameters, an option parameter mask, etc.
     121    *df: we calculate the derivative of the function w.r.t. to each parameter
     122 in "params" and return those derivatives in this psVector.
     123 *****************************************************************************/
     124void p_psMinFuncDeriv(const gsl_vector *params,
     125                      void *funcData,
    111126                      gsl_vector *df)
    112127{
     
    114129    int j;    // Loop index variable.
    115130    float tmpf;    // Temporary floating point variable.
    116     const psVector *restrict coord   = ((psModelData2 *) params)->coord;
    117     const psVector *restrict mask     = ((psModelData2 *) params)->paramMask;
    118     psVector *restrict initialGuess = ((psModelData2 *)params)->initialGuess;
     131    const psVector *restrict coord   = ((psMinimizeData *) funcData)->coord;
     132    const psVector *restrict mask     = ((psMinimizeData *) funcData)->paramMask;
     133    psVector *restrict initialGuess = ((psMinimizeData *)funcData)->initialGuess;
    119134    float (*d_evalModel)(const psVector *, const psVector *, int) =
    120         ((psModelData2 *) params)->d_evalModel;
     135        ((psMinimizeData *) funcData)->d_evalModel;
    121136    psVector *inputParameterList = NULL;
    122137
     138    // The GSL routines will call this function with the masked parameters
     139    // removed.  However, the user-supplied function (to be modified) does not
     140    // have those parameters removed.  Here will create a new parameter list
     141    // with the masked parameters added (we expand initialGuess).
    123142    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
    124 
    125143    if (mask != NULL) {
    126144        j = 0;
     
    129147                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
    130148            } else {
    131                 inputParameterList->data.F32[i] = gsl_vector_get(v, j++);
    132             }
    133         }
    134     } else {
    135         for (i=0;i<initialGuess->n;i++) {
    136             inputParameterList->data.F32[i] = gsl_vector_get(v, i);
    137         }
    138     }
    139 
     149                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
     150            }
     151        }
     152    } else {
     153        for (i=0;i<initialGuess->n;i++) {
     154            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
     155        }
     156    }
     157
     158    // Evaluate the derivative w.r.t. each parameter.
     159    // NOTE: we can probably remove the calls for masked parameters.
    140160    for (i=0;i<initialGuess->n;i++) {
    141161        tmpf = d_evalModel(inputParameterList, coord, i);
    142162        gsl_vector_set(df, i, tmpf);
    143163    }
     164
     165    // Free allocated memory.
    144166    psFree(inputParameterList);
    145167}
    146168
    147 /* Compute both f and df together. */
    148 void p_psMinFuncFuncDeriv(const gsl_vector *x,
    149                           void *params,
     169/******************************************************************************
     170    Compute both p_psMinFunc and p_psMinFuncDeriv together.
     171 *****************************************************************************/
     172void p_psMinFuncFuncDeriv(const gsl_vector *params,
     173                          void *funcData,
    150174                          double *f,
    151175                          gsl_vector *df)
    152176{
    153     *f = p_psMinFunc(x, params);
    154     p_psMinFuncDeriv(x, params, df);
     177    *f = p_psMinFunc(params, funcData);
     178    p_psMinFuncDeriv(params, funcData, df);
    155179}
    156180
     
    161185This routine must minimize an arbitrary function; it must determine the set
    162186of parameters of that function such that the
    163  
    164187 *****************************************************************************/
    165188psVector *
     
    175198    int iter = 0;
    176199    gsl_multimin_function_fdf f;
    177     double *xInit = NULL;
    178200    const gsl_multimin_fdfminimizer_type *T;
    179201    gsl_multimin_fdfminimizer *s;
    180     psModelData2 inputData;
     202    psMinimizeData inputData;
    181203    gsl_vector *x;
    182204
     
    188210    inputData.paramCount = 0;
    189211
    190     printf("psMinimize(): initialGuess->n is %d\n", initialGuess->n);
    191     printf("psMinimize(): coord->n is %d\n", coord->n);
    192     printf("psMinimize(): coord is (%.1f, %.1f)\n", coord->data.F32[0],
    193            coord->data.F32[1]);
    194 
     212    // If the user supplied a parameter mask, then count the number of
     213    // non-masked elements.  This will be used later in allocating a vector
     214    // for the parameters.
    195215    if (paramMask != NULL) {
    196216        for (i=0;i<paramMask->n;i++) {
     
    204224
    205225    // The initial guess at the parameters for the function are written into
    206     // the vector inputParameterList.  If the paramMask is not NULL, then those
    207     // parameters are masked out.
    208 
    209     xInit = (double *) psAlloc(inputData.paramCount * sizeof(double));
     226    // the vector inputParameterList.  If the paramMask is not NULL, then
     227    // masked parameters are masked out.
     228    x = gsl_vector_alloc(inputData.paramCount);
    210229    if (paramMask != NULL) {
    211230        j = 0;
    212231        for (i=0;i<initialGuess->n;i++) {
    213232            if (paramMask->data.U8[i] == 0) {
    214                 xInit[j++] = initialGuess->data.F32[i];
    215             }
    216         }
    217     } else {
    218         for (i=0;i<initialGuess->n;i++) {
    219             xInit[i] = initialGuess->data.F32[i];
     233                gsl_vector_set(x, j++, initialGuess->data.F32[i]);
     234            }
     235        }
     236    } else {
     237        for (i=0;i<initialGuess->n;i++) {
     238            gsl_vector_set(x, i, initialGuess->data.F32[i]);
    220239        }
    221240    }
     
    224243    f.fdf = &p_psMinFuncFuncDeriv;
    225244    f.n = inputData.paramCount;
    226     // GUS: is this correct?
    227     //f.params = xInit;
    228245    f.params = &inputData;
    229246
    230 
    231     printf("inputData.paramCount is %d\n", inputData.paramCount);
    232     x = gsl_vector_alloc(inputData.paramCount);
    233     for (i=0;i<inputData.paramCount;i++) {
    234         gsl_vector_set(x, i, xInit[i]);
    235     }
    236247    T = gsl_multimin_fdfminimizer_conjugate_fr;
    237248    s = gsl_multimin_fdfminimizer_alloc(T, inputData.paramCount);
    238 
    239249    gsl_multimin_fdfminimizer_set(s, &f, x, 0.01, 1e-4);
    240 
    241250    do {
    242251        iter++;
     
    251260            printf ("Minimum found at:\n");
    252261
    253     } while (status == GSL_CONTINUE && iter < 100);
     262    } while (status == GSL_CONTINUE && iter < MAX_MINIMIZE_ITERATIONS);
    254263
    255264    // In the above steps we had removed the masked elements from the
     
    270279        }
    271280    }
    272     psFree(xInit);
    273281    return(initialGuess);
    274282}
     
    278286
    279287
    280 // The first argument to evalModel() and
    281 // d_evalModel() specifies the data point.
    282 // It must have the same size as the second
    283 // dimension of *domain.
    284 // The second argument must have the same size
    285 // as *initialGuess and *paramMask.
     288// The first argument to evalModel() and d_evalModel() specifies the data
     289// point.  It must have the same size as the second dimension of *domain.
     290// The second argument must have the same size as *initialGuess and
     291// *paramMask.
    286292
    287293/******************************************************************************
    288  ******************************************************************************
    289 gsl_function_f(x, params, f): This function serves as a standardized wrapper
    290 for the user supplied function which is to be minimized.  The GSL
    291 minimization routines have no knowledge of the user-supplied function.  They
    292 only call this routine, which then calls the user-supplied function.  The
    293 arguments are:
    294  
     294p_psMinChi2Func(*x, *funcData, *outdata): We use the GSL-supplied function
     295gsl_multifit_fdfsolver_iterate() to determine the function parameters that
     296best fit the supllied set of data points.  That GSL function requires the
     297user-supplied function to be in a different format than the psLib format.
     298The purpose of this procedure is to serve as a GSL-format wrapper for the
     299psLib user-supplied function which is to be minimized.
    295300    x: These are the parameters which are to be varied by GSL in order to
    296301 minimized chi2 over the data set.
    297     params: this data structure contains the input values over which the
     302    funcData: this data structure contains the input values over which the
    298303 function will be evaluated, the expected value of the function at
    299304 those points, the amount of error tolerable at those points, a mask
     
    302307    outData: The function is evaluated at each point, then subtract the
    303308 expected value and divide by the error.
    304  ******************************************************************************
    305309 *****************************************************************************/
    306 int gsl_function_f(const gsl_vector *x,
    307                    void *params,
    308                    gsl_vector *outData)
     310int p_psMinChi2Func(const gsl_vector *params,
     311                    void *funcData,
     312                    gsl_vector *outData)
    309313{
    310314    int i;    // Loop index variable.
    311315    int j;    // Loop index variable.
    312316    float tmpf;    // Temporary floating point variable.
    313     const psImage *restrict  domain   = ((psModelData *)params)->domain;
    314     const psVector *restrict data     = ((psModelData *)params)->data;
    315     const psVector *restrict errors   = ((psModelData *) params)->errors;
    316     const psVector *restrict mask     = ((psModelData *) params)->paramMask;
    317     psVector *restrict initialGuess = ((psModelData *)params)->initialGuess;
    318     float (*evalModel)(const psVector *, const psVector *) = ((psModelData *) params)->evalModel;
     317    const psImage *restrict  domain   = ((psMinChi2Data *)funcData)->domain;
     318    const psVector *restrict data     = ((psMinChi2Data *)funcData)->data;
     319    const psVector *restrict errors   = ((psMinChi2Data *) funcData)->errors;
     320    const psVector *restrict mask     = ((psMinChi2Data *) funcData)->paramMask;
     321    psVector *restrict initialGuess = ((psMinChi2Data *)funcData)->initialGuess;
     322    float (*evalModel)(const psVector *, const psVector *) = ((psMinChi2Data *) funcData)->evalModel;
    319323    psVector *inputParameterList = NULL;
    320324    psVector *tmpVecPtr = NULL;
     
    326330    // have those parameters removed.  Here will create a new parameter list
    327331    // with the masked parameters added (we expand initialGuess).
     332
    328333    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
    329 
    330334    if (mask != NULL) {
    331335        j = 0;
     
    334338                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
    335339            } else {
    336                 inputParameterList->data.F32[i] = gsl_vector_get(x, j++);
    337             }
    338         }
    339     } else {
    340         for (i=0;i<initialGuess->n;i++) {
    341             inputParameterList->data.F32[i] = gsl_vector_get(x, i);
    342         }
    343     }
    344 
     340                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
     341            }
     342        }
     343    } else {
     344        for (i=0;i<initialGuess->n;i++) {
     345            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
     346        }
     347    }
     348
     349    // Evaluate the function at each data point.
    345350    for (i=0;i<domain->numRows;i++) {
    346351        for (j=0;j<domain->numCols;j++) {
     
    353358    }
    354359
     360    // Free allocated memory.
    355361    psFree(inputParameterList);
    356362    psFree(tmpVecPtr);
     363
    357364    return GSL_SUCCESS;
    358365}
    359366
    360 int gsl_function_df(const gsl_vector *x,
    361                     void *params,
    362                     gsl_matrix *J)
    363 {
    364     const psImage *restrict domain   = ((psModelData *)params)->domain;
    365     const psVector *restrict errors   = ((psModelData *) params)->errors;
    366     const psVector *restrict mask     = ((psModelData *) params)->paramMask;
    367     psVector *restrict initialGuess = ((psModelData *)params)->initialGuess;
     367int p_psMinChi2FuncDeriv(const gsl_vector *params,
     368                         void *funcData,
     369                         gsl_matrix *J)
     370{
     371    const psImage *restrict domain   = ((psMinChi2Data *)funcData)->domain;
     372    const psVector *restrict errors   = ((psMinChi2Data *) funcData)->errors;
     373    const psVector *restrict mask     = ((psMinChi2Data *) funcData)->paramMask;
     374    psVector *restrict initialGuess = ((psMinChi2Data *)funcData)->initialGuess;
    368375    psVector *inputParameterList = NULL;
    369376    psVector *tmpVecPtr = NULL;
    370     float (*d_evalModel)(const psVector *, const psVector *, int) = ((psModelData *) params)->d_evalModel;
     377    float (*d_evalModel)(const psVector *, const psVector *, int) = ((psMinChi2Data *) funcData)->d_evalModel;
    371378
    372379    size_t i;
     
    380387    // have those parameters removed.  Here will create a new parameter list
    381388    // with the masked parameters added (we expand initialGuess).
     389
    382390    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
    383 
    384391    if (mask != NULL) {
    385392        j = 0;
     
    388395                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
    389396            } else {
    390                 inputParameterList->data.F32[i] = gsl_vector_get(x, j++);
    391             }
    392         }
    393     } else {
    394         for (i=0;i<initialGuess->n;i++) {
    395             inputParameterList->data.F32[i] = gsl_vector_get(x, i);
    396         }
    397     }
    398 
     397                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
     398            }
     399        }
     400    } else {
     401        for (i=0;i<initialGuess->n;i++) {
     402            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
     403        }
     404    }
     405
     406    // Evaluate the derivtaive at each data point, and w.r.t. each parameter.
    399407    for (i=0;i<domain->numRows;i++) {
    400408        for (j=0;j<tmpVecPtr->n;j++) {
     
    413421}
    414422
    415 int gsl_my_function_fdf(const gsl_vector *x,
    416                         void *params,
    417                         gsl_vector *f,
    418                         gsl_matrix *J)
    419 {
    420     gsl_function_f(x, params, f);
    421     gsl_function_df(x, params, J);
     423
     424int p_psMinChi2FuncFuncDeriv(const gsl_vector *params,
     425                             void *funcData,
     426                             gsl_vector *f,
     427                             gsl_matrix *J)
     428{
     429    p_psMinChi2Func(params, funcData, f);
     430    p_psMinChi2FuncDeriv(params, funcData, J);
    422431
    423432    return GSL_SUCCESS;
     
    451460    // minimization.
    452461    gsl_multifit_fdfsolver *s; // GSL data structure.
    453     psModelData inputData;
     462    psMinChi2Data inputData;
    454463    float chiSqOld = 0.0;
    455464
     
    464473    inputData.d_evalModel = DevalModel;
    465474
     475    // If the user supplied a parameter mask, then count the number of
     476    // non-masked elements.  This will be used later in allocating a vector
     477    // for the parameters.
    466478    if (paramMask != NULL) {
    467479        for (i=0;i<paramMask->n;i++) {
     
    477489    // the vector inputParameterList.  If the paramMask is not NULL, then those
    478490    // parameters are masked out.
    479 
    480491    xInit = (double *) psAlloc(inputData.paramCount * sizeof(double));
    481492    if (paramMask != NULL) {
     
    504515    // and the data structures those functions use.
    505516
    506     f.f = &gsl_function_f;
    507     f.df = &gsl_function_df;
    508     f.fdf = &gsl_my_function_fdf;
     517    f.f = &p_psMinChi2Func;
     518    f.df = &p_psMinChi2FuncDeriv;
     519    f.fdf = &p_psMinChi2FuncFuncDeriv;
    509520    f.n = numData;
    510521    f.p = inputData.paramCount;
     
    542553        chiSqOld = *chiSq;
    543554
    544     } while (status == GSL_CONTINUE && iter < MAX_LMM_NUM_ITERATIONS);
     555    } while (status == GSL_CONTINUE && iter < MAX_LMM_ITERATIONS);
    545556
    546557
Note: See TracChangeset for help on using the changeset viewer.