IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 27, 2005, 3:26:57 PM (21 years ago)
Author:
eugene
Message:

various tests and changes

File:
1 edited

Legend:

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

    r4582 r4630  
    6262bool pmSourceFitModel_EAM(psSource *source,
    6363                          psModel *model,
    64                           const bool PSF,
    65                           float SOFT)
     64                          const bool PSF)
    6665{
    6766    PS_PTR_CHECK_NULL(source, false);
     
    7473    psBool onPic     = true;
    7574    psBool rc        = true;
    76     psF32  Ro;
     75    psF32  Ro, ymodel;
    7776
    7877
     
    8180
    8281    psModelFunc modelFunc = psModelFunc_GetFunction (model->type);
     82    psModelLimits modelLimits = psModelLimits_GetFunction (model->type);
    8383
    8484    psVector *params = model->params;
     
    8686    psVector *paramMask = NULL;
    8787
     88    psVector *beta_lim = NULL;
     89    psVector *params_min = NULL;
     90    psVector *params_max = NULL;
     91
    8892    int nParams = PSF ? params->n - 4 : params->n;
    89     psF32 Xo = params->data.F32[2];
    90     psF32 Yo = params->data.F32[3];
     93    psF32 So = params->data.F32[0];
    9194
    9295    // find the number of valid pixels
     
    122125                y->data.F32[tmpCnt] = source->pixels->data.F32[i][j];
    123126
    124                 // XXX just for test purposes, use the raw radius.  a better
    125                 // choice is to ask what is the value of z and scale by that
    126                 Ro = hypot ((Xo - coord->data.F32[0]), (Yo - coord->data.F32[1]));
    127 
    128                 // XXX enhance the noise (doubled if R = 10 pix, etc. note the square)
    129                 yErr->data.F32[tmpCnt] = sqrt (source->noise->data.F32[i][j] * (1 + PS_SQR(Ro/SOFT)));
     127                ymodel = modelFunc (NULL, model->params, coord);
     128               
     129                // this test enhances the noise based on deviation from the model flux
     130                Ro = 1.0 + fabs (y->data.F32[tmpCnt] - ymodel) / sqrt(PS_SQR(ymodel - So) + PS_SQR(So));
     131                yErr->data.F32[tmpCnt] = sqrt (source->noise->data.F32[i][j] * Ro);
    130132                // XXX EAM : note the wasted effort: we carry dY^2, take sqrt(), then
    131133                //           the minimization function calculates sq()
     
    147149        paramMask->data.U8[i] = 1;
    148150      }
    149     }       
    150 
    151     psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F64);
     151    } 
     152
     153    psImage *covar = psImageAlloc (params->n, 3, PS_TYPE_F64);
     154    modelLimits (&beta_lim, &params_min, &params_max);
     155    for (int i = 0; i < params->n; i++) {
     156        covar->data.F64[0][i] = beta_lim->data.F32[i];
     157        covar->data.F64[1][i] = params_min->data.F32[i];
     158        covar->data.F64[2][i] = params_max->data.F32[i];
     159    }
    152160
    153161    psTrace (".pmObjects.pmSourceFitModel", 5, "fitting function\n");
    154     fitStatus = psMinimizeLMChi2(myMin, covar, params, paramMask, x, y, yErr, modelFunc);
     162    fitStatus = psMinimizeLMChi2_EAM(myMin, covar, params, paramMask, x, y, yErr, modelFunc);
    155163    for (int i = 0; i < dparams->n; i++) {
    156164        if ((paramMask != NULL) && paramMask->data.U8[i]) continue;
     
    326334}
    327335
     336bool pmModelFitStatus (psModel *model) {
     337
     338    bool status;
     339
     340    psModelFitStatusFunc statusFunc = psModelFitStatusFunc_GetFunction (model->type);
     341    status = statusFunc (model);
     342
     343    return (status);
     344}
     345
     346// XXX EAM this implementation of MinLM includes limits on params & dparams
     347psBool psMinimizeLMChi2_EAM(psMinimization *min,
     348                            psImage *covar,
     349                            psVector *params,
     350                            const psVector *paramMask,
     351                            const psArray *x,
     352                            const psVector *y,
     353                            const psVector *yErr,
     354                            psMinimizeLMChi2Func func)
     355{
     356    PS_PTR_CHECK_NULL(min, NULL);
     357    PS_VECTOR_CHECK_NULL(params, NULL);
     358    PS_VECTOR_CHECK_EMPTY(params, NULL);
     359    PS_PTR_CHECK_NULL(x, NULL);
     360    PS_VECTOR_CHECK_NULL(y, NULL);
     361    PS_VECTOR_CHECK_EMPTY(y, NULL);
     362    PS_VECTOR_CHECK_SIZE_EQUAL(x, y, NULL);
     363    PS_PTR_CHECK_NULL(func, NULL);
     364
     365    // this function has test and current values for several things
     366    // the current best value is in lower case
     367    // the next guess value is in upper case
     368
     369    // allocate internal arrays (current vs Guess)
     370    psImage *alpha   = psImageAlloc (params->n, params->n, PS_TYPE_F64);
     371    psImage *Alpha   = psImageAlloc (params->n, params->n, PS_TYPE_F64);
     372    psVector *beta   = psVectorAlloc (params->n, PS_TYPE_F64);
     373    psVector *Beta   = psVectorAlloc (params->n, PS_TYPE_F64);
     374    psVector *Params = psVectorAlloc (params->n, PS_TYPE_F32);
     375    psVector *dy     = NULL;
     376    psF64 Chisq = 0.0;
     377    psF64 lambda = 0.001;
     378
     379    psVector *beta_lim = NULL;
     380    psVector *param_min = NULL;
     381    psVector *param_max = NULL;
     382
     383    // if we are provided a covar image, we expect to find these three vectors in first three rows
     384    if (covar != NULL) {
     385        beta_lim  = psVectorAlloc (params->n, PS_TYPE_F32);
     386        param_min = psVectorAlloc (params->n, PS_TYPE_F32);
     387        param_max = psVectorAlloc (params->n, PS_TYPE_F32);
     388        for (int i = 0; i < params->n; i++) {
     389            beta_lim->data.F32[i] = covar->data.F64[0][i];
     390            param_min->data.F32[i] = covar->data.F64[1][i];
     391            param_max->data.F32[i] = covar->data.F64[2][i];
     392        }
     393        psImageRecycle (covar, params->n, params->n, PS_TYPE_F64);
     394    }
     395       
     396
     397    // why is this needed here??? the initial guess on params is provided by the user
     398    Params = psVectorCopy (Params, params, PS_TYPE_F32);
     399
     400    // the user provides the error or NULL.  we need to convert
     401    // to appropriate weights
     402    dy = psVectorAlloc (y->n, PS_TYPE_F32);
     403    if (yErr != NULL) {
     404        for (int i = 0; i < dy->n; i++) {
     405            if (yErr->data.F32[i] == 0.0) {
     406                dy->data.F32[i] = 1.0;
     407                // mask this?  bad pixel, obviously...
     408            } else {
     409                dy->data.F32[i] = 1.0 / PS_SQR (yErr->data.F32[i]);
     410            }
     411        }
     412    } else {
     413        for (int i = 0; i < dy->n; i++) {
     414            dy->data.F32[i] = 1.0;
     415        }
     416    }
     417
     418    // calculate initial alpha and beta, set chisq (min->value)
     419    min->value = p_psMinLM_SetABX (alpha, beta, params, paramMask, x, y, dy, func);
     420    if (isnan(min->value)) {
     421        min->iter = min->maxIter;
     422        return (false);
     423    }
     424    # ifndef PS_NO_TRACE
     425    // dump some useful info if trace is defined
     426    if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) {
     427        p_psImagePrint  (psTraceGetDestination(), alpha, "alpha guess");
     428        p_psVectorPrint (psTraceGetDestination(), beta, "beta guess");
     429        p_psVectorPrint (psTraceGetDestination(), params, "params guess");
     430    }
     431    if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") == 4) {
     432        p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess");
     433    }
     434    # endif /* PS_NO_TRACE */
     435
     436    // iterate until the tolerance is reached, or give up
     437    while ((min->lastDelta > min->tol) && (min->iter < min->maxIter)) {
     438
     439        // set a new guess for Alpha, Beta, Params
     440        p_psMinLM_GuessABP_EAM (Alpha, Beta, Params, alpha, beta, params, paramMask, beta_lim, param_min, param_max, lambda);
     441
     442        // measure linear model prediction
     443        psF64 dLinear = p_psMinLM_dLinear (Beta, beta, lambda);
     444
     445        # ifndef PS_NO_TRACE
     446        // dump some useful info if trace is defined
     447        if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) {
     448            p_psImagePrint  (psTraceGetDestination(), Alpha, "alpha guess");
     449            p_psVectorPrint (psTraceGetDestination(), Beta, "beta guess");
     450            p_psVectorPrint (psTraceGetDestination(), Params, "params guess");
     451        }
     452        if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") == 4) {
     453            p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess");
     454        }
     455        # endif /* PS_NO_TRACE */
     456
     457        // calculate Chisq for new guess, update Alpha & Beta
     458        Chisq = p_psMinLM_SetABX (Alpha, Beta, Params, paramMask, x, y, dy, func);
     459
     460        // XXX EAM alternate convergence criterion:
     461        // compare the delta (min->value - Chisq) with the
     462        // expected delta from the linear model (dLinear)
     463        // accept new guess (if improvement), or increase lambda
     464        psF64 rho = (min->value - Chisq) / dLinear;
     465
     466        psTrace (".psLib.dataManip.psMinimizeLMChi2", 4, "last chisq: %f, new chisq %f, delta: %f, rho: %f\n", min->value, Chisq, min->lastDelta, rho);
     467        # ifndef PS_NO_TRACE
     468        // dump some useful info if trace is defined
     469        if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) {
     470            p_psImagePrint  (psTraceGetDestination(), Alpha, "alpha guess");
     471            p_psVectorPrint (psTraceGetDestination(), Beta, "beta guess");
     472            p_psVectorPrint (psTraceGetDestination(), Params, "params guess");
     473        }
     474        # endif /* PS_NO_TRACE */
     475
     476        /* if (Chisq < min->value) {  */
     477        if (rho > 0.0) { 
     478            min->lastDelta = (min->value - Chisq) / (dy->n - params->n);
     479            min->value = Chisq;
     480            alpha  = psImageCopy (alpha, Alpha, PS_TYPE_F64);
     481            beta   = psVectorCopy (beta, Beta, PS_TYPE_F64);
     482            params = psVectorCopy (params, Params, PS_TYPE_F32);
     483            lambda *= 0.1;
     484        } else {
     485            lambda *= 10.0;
     486        }
     487        min->iter ++;
     488    }
     489    psTrace (".psLib.dataManip.psMinimizeLMChi2", 3, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter);
     490
     491    // construct & return the covariance matrix (if requested)
     492    if (covar != NULL) {
     493      p_psMinLM_GuessABP_EAM (covar, Beta, Params, alpha, beta, params, paramMask, beta_lim, param_min, param_max, 0.0);
     494    }     
     495
     496    // free the internal temporary data
     497    psFree (alpha);
     498    psFree (Alpha);
     499    psFree (beta);
     500    psFree (Beta);
     501    psFree (Params);
     502    psFree (dy);
     503
     504    if (min->iter == min->maxIter) {
     505      return (false);
     506    }
     507    return (true);
     508}
     509
     510// XXX EAM : can we use static copies of LUv, LUm, A?
     511psBool p_psMinLM_GuessABP_EAM (psImage  *Alpha,
     512                               psVector *Beta,
     513                               psVector *Params,
     514                               const psImage  *alpha,
     515                               const psVector *beta,
     516                               const psVector *params,
     517                               const psVector *paramMask,
     518                               const psVector *beta_lim,
     519                               const psVector *params_min,
     520                               const psVector *params_max,
     521                               psF64 lambda)
     522{
     523
     524    # define USE_LU_DECOMP 1
     525    # if (USE_LU_DECOMP)
     526    psVector *LUv = NULL;
     527    psImage  *LUm = NULL;
     528    psImage  *A   = NULL;
     529    psF32    det;
     530
     531    // LU decomposition version
     532    psTrace (".psLib.dataManip.psMinLM_GuessABP", 5, "using LUD version\n");
     533
     534    // set new guess values (creates matrix A)
     535    A = psImageCopy (NULL, alpha, PS_TYPE_F64);
     536    for (int j = 0; j < params->n; j++) {
     537        if ((paramMask != NULL) && (paramMask->data.U8[j])) continue;
     538        A->data.F64[j][j] = alpha->data.F64[j][j] * (1.0 + lambda);
     539    }
     540
     541    // solve A*beta = Beta (Alpha = 1/A)
     542    // these operations do not modify the input values (creates LUm, LUv)
     543    LUm   = psMatrixLUD (NULL, &LUv, A);
     544    Beta  = psMatrixLUSolve (Beta, LUm, beta, LUv);
     545    Alpha = psMatrixInvert (Alpha, A, &det);
     546
     547    # else
     548    // gauss-jordan version
     549    psTrace (".psLib.dataManip.psMinLM_GuessABP", 5, "using Gauss-J version");
     550
     551    // set new guess values (creates matrix A)
     552    Beta = psVectorCopy (Beta, beta, PS_TYPE_F64);
     553    Alpha = psImageCopy (Alpha, alpha, PS_TYPE_F64);
     554    for (int j = 0; j < params->n; j++) {
     555        if ((paramMask != NULL) && (paramMask->data.U8[j])) continue;
     556        Alpha->data.F64[j][j] = alpha->data.F64[j][j] * (1.0 + lambda);
     557    }
     558
     559    psGaussJordan (Alpha, Beta);
     560    # endif
     561
     562    // apply Beta to get new Params values
     563    for (int j = 0; j < params->n; j++) {
     564        if ((paramMask != NULL) && (paramMask->data.U8[j])) continue;
     565        // Params->data.F32[j] = params->data.F32[j] - Beta->data.F64[j];
     566        // continue;
     567        // compare Beta to beta limits
     568        if (beta_lim != NULL) {
     569            if (fabs(Beta->data.F64[j]) > fabs(beta_lim->data.F32[j])) {
     570                Beta->data.F64[j] = (Beta->data.F64[j] > 0) ? fabs(beta_lim->data.F32[j]) : -fabs(beta_lim->data.F32[j]);
     571            }
     572        }
     573        Params->data.F32[j] = params->data.F32[j] - Beta->data.F64[j];
     574        // compare new params to param limits
     575        if (params_max != NULL) {
     576            Params->data.F32[j] = PS_MIN (Params->data.F32[j], params_max->data.F32[j]);
     577        }
     578        if (params_min != NULL) {
     579            Params->data.F32[j] = PS_MAX (Params->data.F32[j], params_min->data.F32[j]);
     580        }
     581    }
     582
     583    # if (USE_LU_DECOMP)
     584    psFree (A);
     585    psFree (LUm);
     586    psFree (LUv);
     587    # endif
     588
     589    return true;
     590}
     591
Note: See TracChangeset for help on using the changeset viewer.