IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Apr 12, 2006, 8:18:46 PM (20 years ago)
Author:
magnier
Message:

additions to objects for further flexibility with options

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/rel10_ifa/psModules/src/objects/pmSourceFitModel.c

    r6825 r6848  
    66 *  @author GLG, MHPCC
    77 *
    8  *  @version $Revision: 1.1.2.5 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2006-04-10 20:21:36 $
     8 *  @version $Revision: 1.1.2.6 $ $Name: not supported by cvs2svn $
     9 *  @date $Date: 2006-04-13 06:18:46 $
    1010 *
    1111 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2828#include "pmSourceFitModel.h"
    2929
    30 // save a static values so they may be set externally
     30// save as static values so they may be set externally
    3131static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15;
    3232static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1;
    33 
    34 bool pmSourceFitModelInit (float nIter, float tol)
     33static bool PM_PSF_POISSON_WEIGHTS = true;
     34
     35bool pmSourceFitModelInit (float nIter, float tol, bool poissonErrors)
    3536{
    3637
    3738    PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = nIter;
    3839    PM_SOURCE_FIT_MODEL_TOLERANCE = tol;
     40    PM_PSF_POISSON_WEIGHTS = poissonErrors;
     41
    3942    return true;
    4043}
     
    4245bool pmSourceFitModel (pmSource *source,
    4346                       pmModel *model,
    44                        const bool PSF)
     47                       pmSourceFitMode mode)
    4548{
    4649    psTrace(__func__, 3, "---- %s() begin ----\n", __func__);
     
    6568    pmModelFunc modelFunc = pmModelFunc_GetFunction (model->type);
    6669
    67     int nParams = PSF ? 4 : params->n;
    6870    psF32 dSky = source->moments->dSky;
    6971
     
    110112    y->n = nPix;
    111113    yErr->n = nPix;
     114
     115    // XXX EAM : the new minimization API supplies the constraints as a struct
     116    // XXX the chisq if a fcn of source flux. the minimization criterion should
     117    // probably  be scaled somehow by flux.  measure the trend?  it depends on
     118    // the about of systematic error in the models themselves...
     119    psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS,
     120                            PM_SOURCE_FIT_MODEL_TOLERANCE);
     121    psMinConstrain *constrain = psMinConstrainAlloc();
     122
     123    // set parameter mask based on fitting mode
     124    paramMask = psVectorAlloc (params->n, PS_TYPE_U8);
     125    psVectorInit (paramMask, 1);
     126
     127    int nParams = 0;
     128    switch (mode) {
     129    case PM_SOURCE_FIT_NORM:
     130        // NORM-only model fits only source normalization (Io)
     131        nParams = 1;
     132        paramMask->data.U8[1] = 0;
     133        break;
     134    case PM_SOURCE_FIT_PSF:
     135        // PSF model only fits x,y,Io
     136        nParams = 3;
     137        paramMask->data.U8[1] = 0;
     138        paramMask->data.U8[2] = 0;
     139        paramMask->data.U8[3] = 0;
     140        break;
     141    case PM_SOURCE_FIT_EXT:
     142        // EXT model fits all params (except sky)
     143        nParams = params->n - 1;
     144        psVectorInit (paramMask, 0);
     145        paramMask->data.U8[0] = 1;
     146        break;
     147    case PM_SOURCE_FIT_PSF_AND_SKY:
     148        nParams = 4;
     149        psAbort ("pmSourceFitModel", "PSF + SKY not currently available");
     150        break;
     151    case PM_SOURCE_FIT_EXT_AND_SKY:
     152        nParams = params->n;
     153        psAbort ("pmSourceFitModel", "EXT + SKY not currently available");
     154        break;
     155    default:
     156        psAbort ("pmSourceFitModel", "invalid fitting mode");
     157    }
     158    constrain->paramMask = paramMask;
     159
    112160    if (nPix <  nParams + 1) {
    113161        psTrace (".pmObjects.pmSourceFitModel", 4, "insufficient valid pixels\n");
     
    117165        psFree (y);
    118166        psFree (yErr);
     167        psFree (myMin);
     168        psFree (constrain);
     169        psFree (paramMask);
    119170        return(false);
    120171    }
    121 
    122     // XXX EAM : the new minimization API supplies the constraints as a struct
    123     // XXX the chisq if a fcn of source flux. the minimization criterion should
    124     // probably  be scaled somehow by flux.  measure the trend?  it depends on
    125     // the about of systematic error in the models themselves...
    126     psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS,
    127                             PM_SOURCE_FIT_MODEL_TOLERANCE);
    128     psMinConstrain *constrain = psMinConstrainAlloc();
    129 
    130     // PSF model only fits x,y,Io, EXT model fits all (both skip sky)
    131     paramMask = psVectorAlloc (params->n, PS_TYPE_U8);
    132     paramMask->data.U8[0] = 1;
    133     if (PSF) {
    134         for (int i = 1; i < 4; i++) {
    135             paramMask->data.U8[i] = 0;
    136         }
    137         for (int i = 4; i < paramMask->n; i++) {
    138             paramMask->data.U8[i] = 1;
    139         }
    140     } else {
    141         for (int i = 1; i < paramMask->n; i++) {
    142             paramMask->data.U8[i] = 0;
    143         }
    144     }
    145     constrain->paramMask = paramMask;
    146172
    147173    // Set the parameter range checks
     
    210236    return(rc);
    211237}
     238
     239/********************* Source Model Set Functions ***************************/
     240
     241// these static variables are used by one pass of pmSourceFitSet to store
     242// data for a model set.  If we are going to make psphot thread-safe, these
     243// will have to go in a structure of their own.
     244// sky, p1.1, p1.2, p1.3,... p1.n, p2.1, p2.2,
     245// nPar = nSrc*(nOnePar - 1) + 1
     246static pmModelFunc mFunc;
     247static int nPar;
     248static psVector *onePar;
     249static psVector *oneDeriv;
     250
     251bool pmModelFitSetInit (pmModelType type)
     252{
     253
     254    mFunc = pmModelFunc_GetFunction (type);
     255    nPar  = pmModelParameterCount (type);
     256
     257    onePar = psVectorAlloc (nPar, PS_DATA_F32);
     258    oneDeriv = psVectorAlloc (nPar, PS_DATA_F32);
     259
     260    return true;
     261}
     262
     263void pmModelFitSetClear (void)
     264{
     265
     266    psFree (onePar);
     267    psFree (oneDeriv);
     268    return;
     269}
     270
     271psF32 pmModelFitSet(psVector *deriv,
     272                    const psVector *params,
     273                    const psVector *x)
     274{
     275
     276    psF32 value;
     277    psF32 model;
     278
     279    psF32 *PAR = onePar->data.F32;
     280    psF32 *dPAR = oneDeriv->data.F32;
     281
     282    psF32 *pars = params->data.F32;
     283    psF32 *dpars = (deriv == NULL) ? NULL : deriv->data.F32;
     284
     285    int nSrc = (params->n - 1) / (nPar - 1);
     286
     287    PAR[0] = model = pars[0];
     288    for (int i = 0; i < nSrc; i++) {
     289        int nOff = i*nPar - i;
     290        for (int n = 1; n < nPar; n++) {
     291            PAR[n] = pars[nOff + n];
     292        }
     293        if (deriv == NULL) {
     294            value = mFunc (NULL, onePar, x);
     295        } else {
     296            value = mFunc (oneDeriv, onePar, x);
     297            for (int n = 1; n < nPar; n++) {
     298                dpars[nOff + n] = dPAR[n];
     299            }
     300        }
     301        model += value;
     302    }
     303    if (deriv != NULL) {
     304        dpars[0] = dPAR[0]*2.0;
     305    }
     306    return (model);
     307}
     308
     309/*
     310i:         0           1               2
     311n:         1  2  3  4  5  6  1  2  3  4  5  6  1  2  3  4  5  6
     312i*6 + n: 0 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
     313*/
     314
     315bool pmSourceFitSet (pmSource *source,
     316                     psArray *modelSet,
     317                     pmSourceFitMode mode)
     318{
     319    psTrace(__func__, 3, "---- %s() begin ----\n", __func__);
     320    PS_ASSERT_PTR_NON_NULL(source, false);
     321    PS_ASSERT_PTR_NON_NULL(source->moments, false);
     322    PS_ASSERT_PTR_NON_NULL(source->peak, false);
     323    PS_ASSERT_PTR_NON_NULL(source->pixels, false);
     324    PS_ASSERT_PTR_NON_NULL(source->mask, false);
     325    PS_ASSERT_PTR_NON_NULL(source->weight, false);
     326
     327    psBool fitStatus = true;
     328    psBool onPic     = true;
     329    psBool rc        = true;
     330
     331    // base values on first model
     332    pmModel *model = modelSet->data[0];
     333
     334    // set the static variables
     335    pmModelFitSetInit (model->type);
     336
     337    int nSrc = modelSet->n;
     338    int nPar = model->params->n - 1;  // number of object parameters (excluding sky)
     339
     340    // define parameter vectors for source set
     341    psVector *params = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32);
     342    psVector *dparams = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32);
     343
     344    pmModelLimits modelLimits = pmModelLimits_GetFunction (model->type);
     345
     346    // define limits for a single-source model
     347    psVector *oneDelta;
     348    psVector *oneParMin;
     349    psVector *oneParMax;
     350    modelLimits (&oneDelta, &oneParMin, &oneParMax);
     351
     352    psMinConstrain *constrain = psMinConstrainAlloc();
     353    constrain->paramMin = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32);
     354    constrain->paramMax = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32);
     355    constrain->paramMask = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_U8);
     356    constrain->paramDelta = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32);
     357
     358    // set the parameter guesses and constraints for the multiple models
     359    // first the values for the single sky parameter
     360    params->data.F32[0] = model->params->data.F32[0];
     361    constrain->paramMin->data.F32[0]   = oneParMin->data.F32[0];
     362    constrain->paramMax->data.F32[0]   = oneParMax->data.F32[0];
     363    constrain->paramDelta->data.F32[0] = oneDelta->data.F32[0];
     364
     365    // next, the values for the source parameters
     366    for (int i = 0; i < nSrc; i++) {
     367        model = modelSet->data[i];
     368        for (int n = 1; n < nPar + 1; n++) {
     369            params->data.F32[i*nPar + n] = model->params->data.F32[n];
     370            constrain->paramDelta->data.F32[i*nPar + n] = oneDelta->data.F32[n];
     371            constrain->paramMin->data.F32[i*nPar + n]   = oneParMin->data.F32[n];
     372            constrain->paramMax->data.F32[i*nPar + n]   = oneParMax->data.F32[n];
     373        }
     374    }
     375    psFree (oneDelta);
     376    psFree (oneParMin);
     377    psFree (oneParMax);
     378
     379    if (psTraceGetLevel(__func__) >= 5) {
     380        for (int i = 0; i < params->n; i++) {
     381            fprintf (stderr, "%d %f %d\n", i, params->data.F32[i], constrain->paramMask->data.U8[i]);
     382        }
     383    }
     384
     385    // set the parameter masks based on the fitting mode
     386    int nParams = 0;
     387    switch (mode) {
     388    case PM_SOURCE_FIT_NORM:
     389        // NORM-only model fits only source normalization (Io)
     390        nParams = nSrc;
     391        psVectorInit (constrain->paramMask, 1);
     392        for (int i = 0; i < nSrc; i++) {
     393            constrain->paramMask->data.U8[1 + i*nPar] = 0;
     394        }
     395        break;
     396    case PM_SOURCE_FIT_PSF:
     397        // PSF model only fits x,y,Io
     398        nParams = 3*nSrc;
     399        psVectorInit (constrain->paramMask, 1);
     400        for (int i = 0; i < nSrc; i++) {
     401            constrain->paramMask->data.U8[1 + i*nPar] = 0;
     402            constrain->paramMask->data.U8[2 + i*nPar] = 0;
     403            constrain->paramMask->data.U8[3 + i*nPar] = 0;
     404        }
     405        break;
     406    case PM_SOURCE_FIT_EXT:
     407        // EXT model fits all params (except sky)
     408        nParams = nPar*nSrc;
     409        psVectorInit (constrain->paramMask, 0);
     410        constrain->paramMask->data.U8[0] = 1;
     411        break;
     412    case PM_SOURCE_FIT_PSF_AND_SKY:
     413        nParams = 1 + 3*nSrc;
     414        psAbort ("pmSourceFitModel", "PSF + SKY not currently available");
     415        break;
     416    case PM_SOURCE_FIT_EXT_AND_SKY:
     417        nParams = 1 + nPar*nSrc;
     418        psAbort ("pmSourceFitModel", "EXT + SKY not currently available");
     419        break;
     420    default:
     421        psAbort ("pmSourceFitModel", "invalid fitting mode");
     422    }
     423
     424    // maximum number of valid pixels
     425    psS32 nPix = source->pixels->numRows * source->pixels->numCols;
     426
     427    // local sky variance
     428    psF32 dSky = source->moments->dSky;
     429
     430    // construct the coordinate and value entries
     431    psArray *x = psArrayAlloc(nPix);
     432    psVector *y = psVectorAlloc(nPix, PS_TYPE_F32);
     433    psVector *yErr = psVectorAlloc(nPix, PS_TYPE_F32);
     434
     435    nPix = 0;
     436    for (psS32 i = 0; i < source->pixels->numRows; i++) {
     437        for (psS32 j = 0; j < source->pixels->numCols; j++) {
     438            // skip masked points
     439            if (source->mask->data.U8[i][j]) {
     440                continue;
     441            }
     442            // skip zero-weight points
     443            if (source->weight->data.F32[i][j] == 0) {
     444                continue;
     445            }
     446            psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
     447
     448            // Convert i/j to image space:
     449            coord->data.F32[0] = (psF32) (j + source->pixels->col0);
     450            coord->data.F32[1] = (psF32) (i + source->pixels->row0);
     451            x->data[nPix] = (psPtr *) coord;
     452            y->data.F32[nPix] = source->pixels->data.F32[i][j];
     453            // psMinimizeLMChi2 takes wt = 1/dY^2
     454            if (PM_PSF_POISSON_WEIGHTS) {
     455                yErr->data.F32[nPix] = 1.0 / source->weight->data.F32[i][j];
     456            } else {
     457                yErr->data.F32[nPix] = 1.0 / dSky;
     458            }
     459            nPix++;
     460        }
     461    }
     462    if (nPix <  nParams + 1) {
     463        psTrace (__func__, 4, "insufficient valid pixels\n");
     464        psTrace(__func__, 3, "---- %s() end : fail pixels ----\n", __func__);
     465        model->status = PM_MODEL_BADARGS;
     466        psFree (x);
     467        psFree (y);
     468        psFree (yErr);
     469        psFree (params);
     470        psFree (dparams);
     471        psFree(constrain->paramMask);
     472        psFree(constrain->paramMin);
     473        psFree(constrain->paramMax);
     474        psFree(constrain->paramDelta);
     475        psFree(constrain);
     476        return(false);
     477    }
     478    x->n = nPix;
     479    y->n = nPix;
     480    yErr->n = nPix;
     481
     482    psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS,
     483                            PM_SOURCE_FIT_MODEL_TOLERANCE);
     484
     485    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F64);
     486
     487    psTrace (__func__, 5, "fitting function\n");
     488    fitStatus = psMinimizeLMChi2(myMin, covar, params, constrain, x, y, yErr, pmModelFitSet);
     489
     490    // parameter errors from the covariance matrix
     491    for (int i = 0; i < dparams->n; i++) {
     492        if ((constrain->paramMask != NULL) && constrain->paramMask->data.U8[i])
     493            continue;
     494        dparams->data.F32[i] = sqrt(covar->data.F64[i][i]);
     495    }
     496
     497    // get the Gauss-Newton distance for fixed model parameters
     498    if (constrain->paramMask != NULL) {
     499        psVector *delta = psVectorAlloc (params->n, PS_TYPE_F64);
     500        psMinimizeGaussNewtonDelta(delta, params, NULL, x, y, yErr, pmModelFitSet);
     501        for (int i = 0; i < dparams->n; i++) {
     502            if (!constrain->paramMask->data.U8[i])
     503                continue;
     504            dparams->data.F32[i] = delta->data.F64[i];
     505        }
     506        psFree (delta);
     507    }
     508
     509    // assign back the parameters to the models
     510    for (int i = 0; i < nSrc; i++) {
     511        model = modelSet->data[i];
     512        model->params->data.F32[0] = params->data.F32[0];
     513        for (int n = 1; n < nPar + 1; n++) {
     514            model->params->data.F32[n] = params->data.F32[i*nPar + n];
     515            model->dparams->data.F32[n] = dparams->data.F32[i*nPar + n];
     516        }
     517        // save the resulting chisq, nDOF, nIter
     518        // these are not unique for any one source
     519        model->chisq = myMin->value;
     520        model->nIter = myMin->iter;
     521        model->nDOF  = y->n - nParams;
     522
     523        // set the model success or failure status
     524        model->status = fitStatus ? PM_MODEL_SUCCESS : PM_MODEL_NONCONVERGE;
     525
     526        // models can go insane: reject these
     527        onPic &= (model->params->data.F32[2] >= source->pixels->col0);
     528        onPic &= (model->params->data.F32[2] <  source->pixels->col0 + source->pixels->numCols);
     529        onPic &= (model->params->data.F32[3] >= source->pixels->row0);
     530        onPic &= (model->params->data.F32[3] <  source->pixels->row0 + source->pixels->numRows);
     531        if (!onPic) {
     532            model->status = PM_MODEL_OFFIMAGE;
     533        }
     534    }
     535
     536    source->mode |= PM_SOURCE_MODE_FITTED;
     537
     538    psFree(x);
     539    psFree(y);
     540    psFree(yErr);
     541    psFree(myMin);
     542    psFree(covar);
     543    psFree(constrain->paramMask);
     544    psFree(constrain->paramMin);
     545    psFree(constrain->paramMax);
     546    psFree(constrain->paramDelta);
     547    psFree(constrain);
     548    psFree(params);
     549    psFree(dparams);
     550
     551    // free static memory used by pmModelFitSet
     552    pmModelFitSetClear ();
     553
     554    rc = (onPic && fitStatus);
     555    psTrace (__func__, 5, "onPic: %d, fitStatus: %d, nIter: %d, chisq: %f, nDof: %d\n", onPic, fitStatus, model->nIter, model->chisq, model->nDOF);
     556    psTrace(__func__, 3, "---- %s end : status %d ----\n", __func__, rc);
     557    return(rc);
     558}
     559
Note: See TracChangeset for help on using the changeset viewer.