IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 13976


Ignore:
Timestamp:
Jun 25, 2007, 3:04:56 PM (19 years ago)
Author:
eugene
Message:

fleshed out psf-convolved model fitting function

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psphot/src/psphotModelWithPSF.c

    r13845 r13976  
    11# include "psphot.h"
     2
     3// XXX elevate the p_psMinLM_ functions to psMinLM_...
     4
     5
     6bool psphotModelWithPSF_LMM (
     7    psMinimization *min,
     8    psImage *covar,
     9    psVector *params,
     10    psMinConstraint *constraint,
     11    const pmSource *source,
     12    const psKernel *psf,
     13    psMinimizeLMChi2Func func)
     14{
     15    psTrace("psLib.math", 3, "---- begin ----\n");
     16    PS_ASSERT_PTR_NON_NULL(min, false);
     17    PS_ASSERT_VECTOR_NON_NULL(params, false);
     18    PS_ASSERT_VECTOR_NON_EMPTY(params, false);
     19    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false);
     20    psVector *paramMask = NULL;
     21    if (constraint != NULL) {
     22        paramMask = constraint->paramMask;
     23        if (paramMask != NULL) {
     24            PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_U8, false);
     25            PS_ASSERT_VECTORS_SIZE_EQUAL(params, paramMask, false);
     26        }
     27    }
     28    PS_ASSERT_PTR_NON_NULL(func, false);
     29    PS_ASSERT_PTR_NON_NULL(source, false);
     30
     31    psMinimizeLMLimitFunc checkLimits = NULL;
     32    if (constraint) {
     33        checkLimits = constraint->checkLimits;
     34    }
     35
     36    // this function has test values and current values for several things
     37    // the current value is in lower case
     38    // the test value is in upper case
     39
     40    // allocate internal arrays (current vs Guess)
     41    psImage *alpha   = psImageAlloc(params->n, params->n, PS_TYPE_F32);
     42    psImage *Alpha   = psImageAlloc(params->n, params->n, PS_TYPE_F32);
     43    psVector *beta   = psVectorAlloc(params->n, PS_TYPE_F32);
     44    psVector *Beta   = psVectorAlloc(params->n, PS_TYPE_F32);
     45    psVector *Params = psVectorAlloc(params->n, PS_TYPE_F32);
     46
     47    psF32 Chisq = 0.0;
     48    psF32 lambda = 0.001;
     49
     50    // calculate initial alpha and beta, set chisq (min->value)
     51    min->value = psphotModelWithPSF_SetABX(alpha, beta, params, paramMask, source, psf, func);
     52    if (isnan(min->value)) {
     53        min->iter = min->maxIter;
     54        return(false);
     55    }
     56    // dump some useful info if trace is defined
     57    if (psTraceGetLevel("psLib.math") >= 6) {
     58        p_psImagePrint(psTraceGetDestination(), alpha, "alpha guess (0)");
     59        p_psVectorPrint(psTraceGetDestination(), beta, "beta guess (0)");
     60    }
     61    if (psTraceGetLevel("psLib.math") >= 5) {
     62        p_psVectorPrint(psTraceGetDestination(), params, "params guess (0)");
     63    }
     64
     65    // iterate until the tolerance is reached, or give up
     66    while ((min->iter < min->maxIter) && ((min->lastDelta > min->tol) || !isfinite(min->lastDelta))) {
     67        psTrace("psLib.math", 5, "Iteration number %d.  (max iterations is %d).\n", min->iter, min->maxIter);
     68        psTrace("psLib.math", 5, "Last delta is %f.  Min->tol is %f.\n", min->lastDelta, min->tol);
     69
     70        // set a new guess for Alpha, Beta, Params
     71        if (!p_psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda)) {
     72            min->iter ++;
     73            lambda *= 10.0;
     74            continue;
     75        }
     76
     77        // measure linear model prediction
     78        psF32 dLinear = p_psMinLM_dLinear(Beta, beta, lambda);
     79
     80        // dump some useful info if trace is defined
     81        if (psTraceGetLevel("psLib.math") >= 6) {
     82            p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (1)");
     83            p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (1)");
     84        }
     85        if (psTraceGetLevel("psLib.math") >= 5) {
     86            p_psVectorPrint(psTraceGetDestination(), Params, "params guess (1)");
     87        }
     88
     89        // calculate Chisq for new guess, update Alpha & Beta
     90        Chisq = p_psMinLM_SetABX(Alpha, Beta, Params, paramMask, source, func);
     91        if (isnan(Chisq)) {
     92            min->iter ++;
     93            lambda *= 10.0;
     94            continue;
     95        }
     96
     97        // convergence criterion:
     98        // compare the delta (min->value - Chisq) with the
     99        // expected delta from the linear model (dLinear)
     100        // accept new guess if it is an improvement (rho > 0), or else increase lambda
     101        psF32 rho = (min->value - Chisq) / dLinear;
     102
     103        psTrace("psLib.math", 5, "last chisq: %f, new chisq %f, delta: %f, rho: %f\n", min->value,
     104                Chisq, min->lastDelta, rho);
     105
     106        // dump some useful info if trace is defined
     107        if (psTraceGetLevel("psLib.math") >= 6) {
     108            p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (2)");
     109            p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (2)");
     110        }
     111
     112        /* if (Chisq < min->value) {  */
     113        if (rho > 0.0) {
     114            min->lastDelta = (min->value - Chisq) / (dy->n - params->n);
     115            min->value = Chisq;
     116            alpha  = psImageCopy(alpha, Alpha, PS_TYPE_F32);
     117            beta   = psVectorCopy(beta, Beta, PS_TYPE_F32);
     118            params = psVectorCopy(params, Params, PS_TYPE_F32);
     119            lambda *= 0.1;
     120        } else {
     121            lambda *= 10.0;
     122        }
     123        min->iter++;
     124    }
     125    psTrace("psLib.math", 5, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter);
     126
     127    // construct & return the covariance matrix (if requested)
     128    if (covar != NULL) {
     129        if (!p_psMinLM_GuessABP(covar, Beta, Params, alpha, beta, params, paramMask, NULL, 0.0)) {
     130            psTrace ("psLib.math", 5, "failure to calculate covariance matrix\n");
     131        }
     132    }
     133
     134    // free the internal temporary data
     135    psFree(alpha);
     136    psFree(Alpha);
     137    psFree(beta);
     138    psFree(Beta);
     139    psFree(Params);
     140
     141    if (min->iter == min->maxIter) {
     142        psTrace("psLib.math", 3, "---- end (false) ----\n");
     143        return(false);
     144    }
     145
     146    psTrace("psLib.math", 3, "---- end (true) ----\n");
     147    return(true);
     148}
     149
     150psF32 psphotModelWithPSF_SetABX(
     151    psImage  *alpha,
     152    psVector *beta,
     153    const psVector *params,
     154    const psVector *paramMask,
     155    const pmSource *source,
     156    const psKernel *psf,
     157    psMinimizeLMChi2Func func)
     158{
     159    // XXX: Check vector sizes.
     160    PS_ASSERT_IMAGE_NON_NULL(alpha, NAN);
     161    PS_ASSERT_VECTOR_NON_NULL(beta, NAN);
     162    PS_ASSERT_VECTOR_NON_NULL(params, NAN);
     163
     164    PS_ASSERT_PTR_NON_NULL(source, NAN);
     165    PS_ASSERT_IMAGE_NON_NULL(source->pixels, NAN);
     166    PS_ASSERT_IMAGE_NON_NULL(source->weight, NAN);
     167    PS_ASSERT_IMAGE_NON_NULL(source->maskObj, NAN);
     168
     169    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false);
     170    if (paramMask) {
     171        PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_MASK, false);
     172    }
     173
     174    psF32 chisq;
     175    psF32 delta;
     176    psF32 weight;
     177    psF32 ymodel;
     178    psVector *deriv = psVectorAlloc(params->n, PS_TYPE_F32);
     179
     180    // generate the model and derivative images for this parameter set
     181    psImage *model = psImageAlloc (source->pixels->numCols, source->pixels->numRows, PS_TYPE_F32);
     182    psArray *dmodels = psArrayAlloc (params->n);
     183    for (psS32 n = 0; n < params->n; n++) {
     184      if ((paramMask != NULL) && (paramMask->data.U8[n])) { continue; }
     185      psImage *dmodel = psImageAlloc (source->pixels->numCols, source->pixels->numRows, PS_TYPE_F32);
     186      dmodels->data[n] = dmodel;
     187    }
     188
     189    // working vector to store local coordinate
     190    psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
     191
     192    // fill in the coordinate and value entries
     193    nPix = 0;
     194    for (psS32 i = 0; i < source->pixels->numRows; i++) {
     195        for (psS32 j = 0; j < source->pixels->numCols; j++) {
     196            // skip masked points
     197            // XXX probably should not skipped masked points:
     198            // XXX skip if convolution of unmasked pixels will not see this pixel
     199            if (source->maskObj->data.U8[i][j]) {
     200                continue;
     201            }
     202            // skip zero-weight points
     203            // XXX why is this not masked?
     204            if (source->weight->data.F32[i][j] == 0) {
     205                continue;
     206            }
     207            // skip nan value points
     208            // XXX why is this not masked?
     209            if (!isfinite(source->pixels->data.F32[i][j])) {
     210                continue;
     211            }
     212
     213            // Convert i/j to image space:
     214            coord->data.F32[0] = (psF32) (j + source->pixels->col0);
     215            coord->data.F32[1] = (psF32) (i + source->pixels->row0);
     216
     217            model->data.F32[i][j] = func (deriv, params, coord);
     218
     219            for (int n = 0; n < params->n; n++) {
     220              if ((paramMask != NULL) && (paramMask->data.U8[n])) { continue; }
     221              psImage *dmodel = dmodels->data[n];
     222              dmodel->data.F32[i][j] = deriv->data.F32[n];
     223            }
     224        }
     225    }
     226    psFree (coord);
     227
     228    // convolve model and dmodel arrays with PSF
     229    psImage *modelConv = psImageConvolveDirect (model, psf);
     230    psArray *dmodelsConv = psArrayAlloc (params->n);
     231    for (int n = 0; n < params->n; n++) {
     232      if ((paramMask != NULL) && (paramMask->data.U8[n])) { continue; }
     233      psImage *dmodel = dmodels->data[n];
     234      psImage *dmodelConv = psImageConvolveDirect (dmodel, psf);
     235      dmodelsConv->data[n] = dmodelConv;
     236    }
     237
     238    // zero alpha and beta for summing below
     239    psImageInit (alpha, 0.0);
     240    psVectorInit (beta, 0.0);
     241    chisq = 0.0;
     242
     243    for (psS32 i = 0; i < source->pixels->numRows; i++) {
     244        for (psS32 j = 0; j < source->pixels->numCols; j++) {
     245          // XXX are we doing the right thing with the mask?
     246            // skip masked points
     247            if (source->maskObj->data.U8[i][j]) {
     248                continue;
     249            }
     250            // skip zero-weight points
     251            if (source->weight->data.F32[i][j] == 0) {
     252                continue;
     253            }
     254            // skip nan value points
     255            if (!isfinite(source->pixels->data.F32[i][j])) {
     256                continue;
     257            }
     258
     259            ymodel  = modelConv->data.F32[i][j];
     260            yweight = 1.0 / source->weight->data.F32[i][j];
     261            delta = ymodel - source->pixels->data.F32[i][j];
     262
     263            chisq += PS_SQR(delta) * var;
     264
     265            if (isnan(delta))
     266              psAbort("nan in delta");
     267            if (isnan(chisq))
     268              psAbort("nan in chisq");
     269
     270            for (psS32 n1 = 0; n1 < params->n; n1++) {
     271              if ((paramMask != NULL) && (paramMask->data.U8[n1])) {
     272                continue;
     273              }
     274              psImage *dmodel = dmodelsConv->data[n1];
     275              weight = dmodel->data.F32[i][j] * yweight;
     276              for (psS32 n2 = 0; n2 <= n1; n2++) {
     277                if ((paramMask != NULL) && (paramMask->data.U8[n2])) {
     278                  continue;
     279                }
     280                dmodel = dmodelsConv->data[n2];
     281                alpha->data.F32[n1][n2] += weight * dmodel->data.F32[i][j];
     282              }
     283              beta->data.F32[jn] += weight * delta;
     284            }
     285        }
     286    }
     287
     288    // calculate lower-left half of alpha
     289    for (psS32 j = 1; j < params->n; j++) {
     290        for (psS32 k = 0; k < j; k++) {
     291            alpha->data.F32[k][j] = alpha->data.F32[j][k];
     292        }
     293    }
     294
     295    // fill in pivots if we apply a mask
     296    if (paramMask != NULL) {
     297        for (psS32 j = 0; j < params->n; j++) {
     298            if (paramMask->data.U8[j]) {
     299                alpha->data.F32[j][j] = 1;
     300                beta->data.F32[j] = 1;
     301            }
     302        }
     303    }
     304
     305    psFree (model);
     306    psFree (dmodels);
     307    psFree (modelConv);
     308    psFree (dmodelsConv);
     309    psFree(deriv);
     310
     311    return(chisq);
     312}
     313
     314
    2315
    3316/*
     
    7320 * basic LMM:
    8321 
    9  *
     322 - fill in the data (x, y)
     323 
     324 chisq = SetABX (alpha, beta, params, paramMask, x, y, dy, func)
     325 
     326 while () {
     327   GuessABP (Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda)
     328   dLinear = dLinear(Beta, beta, lambda);
     329   chisq = SetABX (alpha, beta, params, paramMask, x, y, dy, func)
     330   convergence tests...
     331 }
     332 
     333 
     334
     335 ** GuessABP:
     336
     337      f_c = sum_i (kern_i * func (x_i; p_o))
     338
     339df_c/dp_o = d/dp_o [sum_i (kern_i * func (x_i; p_o))]
     340
     341df_c/dp_o = sum_i (d/dp_o [kern_i * func (x_i; p_o)])
     342
     343df_c/dp_o = sum_i (kern_i * d/dp_o [func (x_i; p_o)])
     344
     345- generate image arrays for func, dfunc/dp_j (not masked)
     346- convolve each with psf
     347- measure delta = f_conv - data
     348- etc
     349*/
     350
     351
Note: See TracChangeset for help on using the changeset viewer.