IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 29, 2010, 2:36:33 PM (16 years ago)
Author:
eugene
Message:

attempting to get a better starting guess; attempting to downweight neighbor detections

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20100621/psphot/src/psphotSourceFits.c

    r28702 r28782  
    11# include "psphotInternal.h"
    2 bool psphotFitSersicIndex (pmSource *source, pmModel *model, pmSourceFitOptions *fitOptions, psImageMaskType maskVal);
    32
    43// given a source with an existing modelPSF, attempt a full PSF fit, subtract if successful
     
    1918
    2019    psLogMsg ("psphot.pspsf", PS_LOG_INFO, "fitted %5d psf, %5d blend, %5d ext, %5d dbl : %6.2f sec\n",
    21              NfitPSF, NfitBlend, NfitEXT, NfitDBL, psTimerMark ("psphot.fits"));
     20              NfitPSF, NfitBlend, NfitEXT, NfitDBL, psTimerMark ("psphot.fits"));
    2221    return true;
    2322}
     
    205204}
    206205
     206// save a local, static copy of the EXT model type so we don't have to lookup for each object
    207207static pmModelType modelTypeEXT;
    208208
    209 bool psphotInitLimitsEXT (psMetadata *recipe) {
     209bool psphotInitLimitsEXT (psMetadata *recipe, pmReadout *readout) {
    210210
    211211    bool status;
     
    214214    char *modelNameEXT = psMetadataLookupStr (&status, recipe, "EXT_MODEL");
    215215    modelTypeEXT = pmModelClassGetType (modelNameEXT);
    216     psphotInitRadiusEXT (recipe, modelTypeEXT);
     216
     217    psphotInitRadiusEXT (recipe, readout);
    217218
    218219    return true;
     
    221222bool psphotFitBlob (pmReadout *readout, pmSource *source, psArray *newSources, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
    222223
     224    float radius;
    223225    bool okEXT, okDBL;
    224226    float chiEXT, chiDBL;
     
    230232
    231233    // skip the source if we don't think it is extended
     234    // XXX are these robust, or do we have better info from the source-size analysis??
    232235    if (source->type == PM_SOURCE_TYPE_UNKNOWN) return false;
    233236    if (source->type == PM_SOURCE_TYPE_DEFECT) return false;
     
    235238
    236239    // set the radius based on the footprint (also sets the mask pixels)
    237     float radius = psphotSetRadiusEXT (readout, source, markVal);
     240    if (!psphotSetRadiusFootprint(&radius, readout, source, markVal, 1.0)) return false;
    238241
    239242    // XXX note that this changes the source moments that are published...
     243    // XXX all published moments should use the same measurement
    240244    // recalculate the source moments using the larger extended-source moments radius
    241245    // at this stage, skip Gaussian windowing, and do not clip pixels by S/N
    242246    // this uses the footprint to judge both radius and aperture?
     247    // XXX save the psf-based moments for output
    243248    if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) return false;
    244249
     
    250255    // this temporary source is used as a place-holder by the psphotEval functions below
    251256    tmpSrc = pmSourceAlloc ();
    252 
    253     // XXX need to handle failures better here
    254     EXT = psphotFitEXT (readout, source, fitOptions, modelTypeEXT, maskVal, markVal);
    255     if (!EXT) goto escape;
    256     if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) goto escape;
    257 
    258     okEXT = psphotEvalEXT (tmpSrc, EXT);
    259     chiEXT = EXT ? EXT->chisq / EXT->nDOF : NAN;
    260 
    261     // DBL will always be defined, but DBL->data[n] might not
    262     DBL = psphotFitDBL (readout, source, fitOptions, maskVal, markVal);
    263     if (!DBL) goto escape;
    264     if (!DBL->n) goto escape;
    265 
    266     okDBL  = psphotEvalDBL (tmpSrc, DBL->data[0]);
    267     okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]);
    268     // XXX should I keep / save the flags set in the eval functions?
     257    {
     258        // DBL will always be defined, but DBL->data[n] might not
     259        DBL = psphotFitDBL (readout, source, fitOptions, maskVal, markVal);
     260        if (!DBL) goto escape;
     261        if (!DBL->n) goto escape;
     262
     263        okDBL  = psphotEvalDBL (tmpSrc, DBL->data[0]);
     264        okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]);
     265        // XXX should I keep / save the flags set in the eval functions?
     266
     267        // correct first model chisqs for flux trend
     268        chiDBL = NAN;
     269        ONE = DBL->data[0];
     270        if (ONE) {
     271            if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
     272            chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
     273            ONE->chisqNorm = ONE->chisq / chiTrend;
     274            chiDBL = ONE->chisq / ONE->nDOF; // save chisq for double-star/galaxy comparison
     275            ONE->fitRadius = radius;
     276        }
     277
     278        // correct second model chisqs for flux trend
     279        ONE = DBL->data[1];
     280        if (ONE) {
     281            if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
     282            chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
     283            ONE->chisqNorm = ONE->chisq / chiTrend;
     284            ONE->fitRadius = radius;
     285        }
     286    }
     287
     288    {
     289        // XXX need to handle failures better here
     290        EXT = psphotFitEXT (readout, source, fitOptions, modelTypeEXT, maskVal, markVal);
     291        if (!EXT) goto escape;
     292        if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) goto escape;
     293
     294        okEXT = psphotEvalEXT (tmpSrc, EXT);
     295        chiEXT = EXT ? EXT->chisq / EXT->nDOF : NAN;
     296    }
    269297
    270298    // clear the circular mask
    271299    psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
    272 
    273     // correct first model chisqs for flux trend
    274     chiDBL = NAN;
    275     ONE = DBL->data[0];
    276     if (ONE) {
    277         if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
    278       chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
    279       ONE->chisqNorm = ONE->chisq / chiTrend;
    280       chiDBL = ONE->chisq / ONE->nDOF; // save chisq for double-star/galaxy comparison
    281     }
    282 
    283     // correct second model chisqs for flux trend
    284     ONE = DBL->data[1];
    285     if (ONE) {
    286         if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
    287       chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
    288       ONE->chisqNorm = ONE->chisq / chiTrend;
    289     }
    290300
    291301    psFree (tmpSrc);
     
    314324
    315325    // save new model
     326    // XXX save the correct radius...
    316327    source->modelEXT = EXT;
    317     source->modelEXT->fitRadius = radius;
    318328    source->type = PM_SOURCE_TYPE_EXTENDED;
    319329    source->mode |= PM_SOURCE_MODE_EXTMODEL;
     
    343353    source->modelPSF = psMemIncrRefCounter (DBL->data[0]);
    344354    source->mode     |= PM_SOURCE_MODE_PAIR;
    345     source->modelPSF->fitRadius = radius;
    346355
    347356    // copy most data from the primary source (modelEXT, blends stay NULL)
    348357    pmSource *newSrc = pmSourceCopyData (source);
    349358    newSrc->modelPSF = psMemIncrRefCounter (DBL->data[1]);
    350     newSrc->modelPSF->fitRadius = radius;
    351359
    352360    // build cached models and subtract
     
    452460    maskVal |= markVal;
    453461
    454     // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
    455 
    456462    // use the source moments, etc to guess basic model parameters
    457     pmModel *EXT = pmSourceModelGuess (source, modelType);
    458     if (!EXT) {
     463    pmModel *model = pmSourceModelGuess (source, modelType);
     464    if (!model) {
    459465        psTrace ("psphot", 5, "failed to generate a model for source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
    460466        return NULL;
     
    463469    // for sersic models, use a grid search to choose an index, then float the params there
    464470    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
    465         psphotFitSersicIndex (source, EXT, fitOptions, maskVal);
     471        // for the test fits, use a somewhat smaller radius
     472        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     473        psphotFitSersicIndex (model, readout, source, fitOptions, maskVal, markVal);
     474    }
     475
     476    if (!psphotSetRadiusModel (model, readout, source, markVal, true)) {
     477        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 1.0);
    466478    }
    467479
     
    471483        options.mode = PM_SOURCE_FIT_EXT;
    472484    }
    473     pmSourceFitModel (source, EXT, &options, maskVal);
     485
     486    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
     487    pmSourceFitModel (source, model, &options, maskVal);
     488    fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
    474489
    475490    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0);
    476     return (EXT);
     491    return (model);
    477492}
    478493
    479494pmModel *psphotFitPCM (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     495
     496    if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) {
     497        psTrace ("psphot", 5, "problem source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
     498    }
     499
     500    pmSourceFitOptions options = *fitOptions;
     501
     502    NfitPCM ++;
     503
     504    // maskVal is used to test for rejected pixels, and must include markVal
     505    maskVal |= markVal;
    480506
    481507    // allocate the model
     
    484510        return NULL;
    485511    }
    486 
    487     pmSourceFitOptions options = *fitOptions;
    488 
    489     if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) {
    490         psTrace ("psphot", 5, "problem source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
    491     }
    492 
    493     float radius = psphotSetRadiusEXT (readout, source, markVal);
    494 
    495     // XXX note that this changes the source moments that are published...
    496     // recalculate the source moments using the larger extended-source moments radius
    497     // at this stage, skip Gaussian windowing, and do not clip pixels by S/N
    498     // this uses the footprint to judge both radius and aperture?
    499     if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) {
    500         // XXX set some mask bit/
    501         model->flags |= PM_MODEL_STATUS_BADARGS;
    502         return model;
    503     }
    504 
    505     NfitPCM ++;
    506 
    507     // maskVal is used to test for rejected pixels, and must include markVal
    508     maskVal |= markVal;
    509 
    510     // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
    511512
    512513    pmPCMdata *pcm = pmPCMinit (source, &options, model, maskVal, psfSize);
     
    518519
    519520    // use the source moments, etc to guess basic model parameters
    520     pmSourceModelGuessPCM (pcm, source, maskVal, markVal);
     521    if (!pmSourceModelGuessPCM (pcm, source, maskVal, markVal)) {
     522        psFree (pcm);
     523        model->flags |= PM_MODEL_STATUS_BADARGS;
     524        return model;
     525    }
    521526
    522527    // for sersic models, use a grid search to choose an index, then float the params there
    523528    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
    524         psphotFitSersicIndexPCM (pcm, source, fitOptions, maskVal, markVal, psfSize);
     529        // for the test fits, use a somewhat smaller radius
     530        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     531        if (!psphotFitSersicIndexPCM (pcm, readout, source, fitOptions, maskVal, markVal, psfSize)) {
     532            model->flags |= PM_MODEL_STATUS_BADARGS;
     533            return model;
     534        }
     535    }
     536
     537    if (!psphotSetRadiusModel (model, readout, source, markVal, true)) {
     538        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 1.0);
    525539    }
    526540
     
    530544        options.mode = PM_SOURCE_FIT_EXT;
    531545    }
     546
     547    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
    532548    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     549    fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
    533550
    534551    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0);
     
    544561// A sersic model is very sensitive to the index.  attempt to find the index first by grid search in just the index
    545562// for a sersic model, attempt to fit just the index and normalization with a modest number of iterations
    546 bool psphotFitSersicIndex (pmSource *source, pmModel *model, pmSourceFitOptions *fitOptions, psImageMaskType maskVal) {
     563bool psphotFitSersicIndex (pmModel *model, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
    547564
    548565    assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     
    552569    // fit EXT (not PSF) model (set/unset the pixel mask)
    553570    options.mode = PM_SOURCE_FIT_NO_INDEX;
    554     options.nIter = 3;
     571    options.nIter = 4;
    555572
    556573    int iMin = -1;
     
    561578        model->params->data.F32[PM_PAR_7] = indexGuess[i];
    562579
    563         model->modelGuess(model, source);
     580        if (!model->modelGuess(model, source)) {
     581            model->flags |= PM_MODEL_STATUS_BADARGS;
     582            return false;
     583        }
     584
     585        // each time we change the model guess, we need to adjust the radius
     586        // XXX this did not work : we do not need such a large radius -- just uses moments-based radius
     587        if (false && !psphotSetRadiusModel (model, readout, source, markVal, false)) {
     588            psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     589        }
     590       
    564591        pmSourceFitModel (source, model, &options, maskVal);
     592        fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
     593
     594        chiSquare[i] = model->chisqNorm;
     595        if (i == 0) {
     596            xMin = chiSquare[i];
     597            iMin = i;
     598        } else {
     599            if (chiSquare[i] < xMin) {
     600                xMin = chiSquare[i];
     601                iMin = i;
     602            }
     603        }
     604    }
     605    assert (iMin >= 0);
     606
     607    model->flags = PM_MODEL_STATUS_NONE; // do not attempt to handle failures here, let the next iteration deal with it
     608    model->params->data.F32[PM_PAR_7] = indexGuess[iMin];
     609    model->modelGuess(model, source);
     610
     611    // each time we change the model guess, we need to adjust the radius
     612    // if (!psphotSetRadiusModel (model, readout, source, markVal, true)) {
     613    //  psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal);
     614    // }
     615
     616    return true;
     617}
     618
     619// A sersic model is very sensitive to the index.  attempt to find the index first by grid search in just the index
     620// for a sersic model, attempt to fit just the index and normalization with a modest number of iterations
     621bool psphotFitSersicIndexPCM (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     622
     623    pmModel *model = pcm->modelConv;
     624
     625    assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     626
     627    pmSourceFitOptions options = *fitOptions;
     628   
     629    // fit EXT (not PSF) model (set/unset the pixel mask)
     630    options.mode = PM_SOURCE_FIT_NO_INDEX;
     631    options.nIter = 4;
     632
     633    int iMin = -1;
     634    float xMin = NAN;
     635    float chiSquare[N_INDEX_GUESS];
     636
     637    for (int i = 0; i < N_INDEX_GUESS; i++) {
     638        model->params->data.F32[PM_PAR_7] = indexGuess[i];
     639       
     640        if (!model->modelGuess(model, source)) {
     641            model->flags |= PM_MODEL_STATUS_BADARGS;
     642            return false;
     643        }
     644
     645        // each time we change the model guess, we need to adjust the radius
     646        // XXX this did not work : we do not need such a large radius -- just uses moments-based radius
     647        if (false && !psphotSetRadiusModel (model, readout, source, markVal, false)) {
     648            psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     649        }
     650       
     651        pmSourceFitModel (source, model, &options, maskVal);
     652        fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
     653
     654        // pmSourceModelGuessPCM(pcm, source, maskVal, markVal);
     655        // pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
    565656
    566657        chiSquare[i] = model->chisq;
     
    575666        }
    576667    }
    577 
    578     model->flags = PM_MODEL_STATUS_NONE; // do not attempt to handle failures here, let the next iteration deal with it
    579     model->params->data.F32[PM_PAR_7] = indexGuess[iMin];
    580     model->modelGuess(model, source);
    581 
    582     return true;
    583 }
    584 
    585 // A sersic model is very sensitive to the index.  attempt to find the index first by grid search in just the index
    586 // for a sersic model, attempt to fit just the index and normalization with a modest number of iterations
    587 bool psphotFitSersicIndexPCM (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
    588 
    589     pmModel *model = pcm->modelConv;
    590 
    591     assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
    592 
    593     pmSourceFitOptions options = *fitOptions;
    594    
    595     // fit EXT (not PSF) model (set/unset the pixel mask)
    596     options.mode = PM_SOURCE_FIT_NO_INDEX;
    597     options.nIter = 3;
    598 
    599     int iMin = -1;
    600     float xMin = NAN;
    601     float chiSquare[N_INDEX_GUESS];
    602 
    603     for (int i = 0; i < N_INDEX_GUESS; i++) {
    604         model->params->data.F32[PM_PAR_7] = indexGuess[i];
    605        
    606         model->modelGuess(model, source);
    607         pmSourceFitModel (source, model, &options, maskVal);
    608 
    609         // pmSourceModelGuessPCM(pcm, source, maskVal, markVal);
    610         // pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
    611 
    612         chiSquare[i] = model->chisq;
    613         if (i == 0) {
    614             xMin = chiSquare[i];
    615             iMin = i;
    616         } else {
    617             if (chiSquare[i] < xMin) {
    618                 xMin = chiSquare[i];
    619                 iMin = i;
    620             }
    621         }
    622     }
    623 
    624668    assert (iMin >= 0);
    625669   
Note: See TracChangeset for help on using the changeset viewer.