IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 30624


Ignore:
Timestamp:
Feb 13, 2011, 12:33:05 PM (15 years ago)
Author:
eugene
Message:

adding some of the metadata needed by PSPS to output headers; skip models with few valid pixels (eg, only the edge is showing); only do the linear fit on pixels within the fit radius; modify psf-match auto-scaling process; enable multiple target psfs for matched-psf aperture photometry; speed up analysis of the radial apertures

Location:
trunk/psphot
Files:
42 edited
6 copied

Legend:

Unmodified
Added
Removed
  • trunk/psphot

  • trunk/psphot/doc/stack.txt

    r28013 r30624  
     1
     220101221
     3
     4  psphotStackReadout is now correctly subtracting the PSF models from
     5  the images as it measures the radial aperture fluxes.
     6
     7  Some issues:
     8
     9  * the source properties get buggered up by the radial aperture flux
     10    analysis (we need to re-determine the psf, re-create the source
     11    pixels, and re-fit the models (linearly) to subtract them
     12    correctly).
     13
     14  * the standard analysis sequence is not doing a second pass
     15
     16  * the choice of the best model is ambiguous
     17
     18  * the radial aperture (and source addition / subtraction) is only
     19    using the PSF model
     20
     21  * make sure psphotEfficiency actually subtracts the inserted fake
     22    sources
     23
     24  * XXX how does the PSF-convolved model work with changing psf models?
     25
     2620101207
     27
     28  header fields for PSPS:
     29
     30  * stack needs to count # of inputs
     31  * propagate the input header to the output image (DONE)
     32  * save PSF parameters in header
     33  * stack type is only known to the launcher
     34
     35  * what are we doing for the stack calibrations??
     36
     37skycellID    : code
     38surveyID     : code
     39filterID     : code
     40stackMetaID  : stack_id
     41photoCalID   : photcode -> number
     42magSat       : FSATUR       saturation magnitude level ** not correctly set
     43completMag   : FLIMIT       95% completion level in mag ** not correctly set
     44stackTypeID  : STK_TYPE     stack type identifier ** deep stack, nightly stack, best IQ stack?
     45refImageID   :              identifier of image used as reference for analysis
     46subtrImageID : N/A (stack)  identifier of image subtracted to generate difference image
     47analVer      :              analysis version index  ** index for tess_id + skycell_id + filter?
     48nP2Images    : NINPUTS      number of P2 images contributing to this cell ** missing from input stack
     49astroScat    :              astrometric scatter for chip ** measure scatter on stack creation?
     50photoScat    :              photometric scatter for chip ** internal scatter? 
     51nAstroRef    :              number of astrometric reference sources ** (connected to above)
     52nPhoRef      :              number of photometric reference sources ** same
     53psfFwhm      :              PSF full width at half maximum ** 0.5(FWHM_MAJ + FWHM_MIN)
     54psfmodelID   : * PSFMODEL   PSF model identifier ** save the PSF model name in the header
     55psfWidMajor  : * FWHM_MAJ     PSF parameters
     56psfWidMinor  : * FWHM_MIN     PSF parameters
     57psfTheta     : * ANGLE        PSF parameters
     58psfExtra1    : * PSF_EXT1   PSF parameters ** (at field center?)
     59psfExtra2    : * PSF_EXT2   PSF parameters ** (not set for all models)
     60photoZero    :              local derived photometric zero point
     61photoColor   :              local derived photometric color term
     62ctype1       : * CTYPE1             name of astrometric projection in RA ** propagate from input stacks
     63ctype2       : * CTYPE2             name of astrometric projection in DEC
     64crval1       : * CRVAL1             RA corresponding to reference pixel
     65crval2       : * CRVAL2             DEC corresponding to reference pixel
     66crpix1       : * CRPIX1             reference pixel value for RA
     67crpix2       : * CRPIX2             reference pixel value for DEC
     68cdelt1       : * CDELT1             scale factor for RA
     69cdelt2       : * CDELT2             scale factor for DEC
     70pc001001     : * PC001001           elements of rotation/Dcale matrix
     71pc001002     : * PC001002           elements of rotation/Dcale matrix
     72pc002001     : * PC002001           elements of rotation/Dcale matrix
     73pc002002     : * PC002002           elements of rotation/Dcale matrix
     74polyOrder    : * NPLYTERM           polynomial order of astrometry fit ** default to 1
     75pca1x3y0     : * PCA1X3Y0     polynomial coefficients for the astrometric fit
     76pca1x2y1     : * PCA1X2Y1     polynomial coefficients for the astrometric fit
     77pca1x1y2     : * PCA1X1Y2     polynomial coefficients for the astrometric fit
     78pca1x0y3     : * PCA1X0Y3     polynomial coefficients for the astrometric fit
     79pca1x2y0     : * PCA1X2Y0     polynomial coefficients for the astrometric fit
     80pca1x1y1     : * PCA1X1Y1     polynomial coefficients for the astrometric fit
     81pca1x0y2     : * PCA1X0Y2     polynomial coefficients for the astrometric fit
     82pca2x3y0     : * PCA2X3Y0     polynomial coefficients for the astrometric fit
     83pca2x2y1     : * PCA2X2Y1     polynomial coefficients for the astrometric fit
     84pca2x1y2     : * PCA2X1Y2     polynomial coefficients for the astrometric fit
     85pca2x0y3     : * PCA2X0Y3     polynomial coefficients for the astrometric fit
     86pca2x2y0     : * PCA2X2Y0     polynomial coefficients for the astrometric fit
     87pca2x1y1     : * PCA2X1Y1     polynomial coefficients for the astrometric fit
     88pca2x0y2     : * PCA2X0Y2     polynomial coefficients for the astrometric fit
     89calibModNum  :              calibration modification number
     90dataRelease  :              Data release
    191
    29220100506:
  • trunk/psphot/src/Makefile.am

    r29936 r30624  
    9898        psphotStackMatchPSFsUtils.c   \
    9999        psphotStackMatchPSFsPrepare.c \
     100        psphotStackMatchPSFsNext.c    \
    100101        psphotStackOptions.c          \
    101102        psphotStackObjects.c          \
  • trunk/psphot/src/psphot.h

    r29936 r30624  
    7575bool            psphotImageQualityReadout(pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
    7676
    77 bool            psphotChoosePSF (pmConfig *config, const pmFPAview *view, const char *filerule);
    78 bool            psphotChoosePSFReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     77bool            psphotChoosePSF (pmConfig *config, const pmFPAview *view, const char *filerule, bool newSources);
     78bool            psphotChoosePSFReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe, bool newSources);
    7979
    8080bool            psphotGuessModels (pmConfig *config, const pmFPAview *view, const char *filerule);
     
    260260bool            psphotVisualShowSourceSize (pmReadout *readout, psArray *sources);
    261261bool            psphotVisualPlotSourceSizeAlt (psMetadata *recipe, psMetadata *analysis, psArray *sources);
    262 bool            psphotVisualShowResidualImage (pmReadout *readout);
     262bool            psphotVisualShowResidualImage (pmReadout *readout, bool reshow);
     263bool            psphotVisualShowObjectRegions (pmReadout *readout, psMetadata *recipe, psArray *sources);
    263264bool            psphotVisualPlotApResid (psArray *sources, float mean, float error, bool useApMag);
    264265bool            psphotVisualPlotChisq (psArray *sources);
     
    312313
    313314int psphotFileruleCount(const pmConfig *config, const char *filerule);
     315bool psphotFileruleCountSet(const pmConfig *config, const char *filerule, int num);
    314316
    315317bool psphotAddKnownSources (pmConfig *config, const pmFPAview *view, const char *filerule, psArray *inSources);
     
    403405bool psphotStackMatchPSFsReadout (pmConfig *config, const pmFPAview *view, psphotStackOptions *options, int index);
    404406bool psphotStackMatchPSFsPrepare (pmConfig *config, const pmFPAview *view, psphotStackOptions *options, int index);
     407bool psphotStackMatchPSFsNext (bool *smoothAgain, pmConfig *config, const pmFPAview *view, const char *filerule, int lastSize);
     408bool psphotStackMatchPSFsNextReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe, psVector *fwhmValues, int lastSize);
    405409
    406410// psphotStackMatchPSFsUtils
     
    426430bool psphotRadialApertures (pmConfig *config, const pmFPAview *view, const char *filerule);
    427431bool psphotRadialAperturesReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
    428 bool psphotRadialApertureSource (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal, const psVector *radMax);
     432bool psphotRadialApertureSource (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal, const psVector *radMax, int entry);
    429433
    430434bool psphotExtendedSourceAnalysisByObject (pmConfig *config, psArray *objects, const pmFPAview *view, const char *filerule);
    431 bool psphotRadialAperturesByObject (pmConfig *config, psArray *objects, const pmFPAview *view, const char *filerule);
     435bool psphotRadialAperturesByObject (pmConfig *config, psArray *objects, const pmFPAview *view, const char *filerule, int nMatchedPSF);
    432436
    433437bool psphotStackObjectsUnifyPosition (psArray *objects);
     
    440444bool psphotCleanInputs (pmConfig *config, const pmFPAview *view, const char *filerule);
    441445
     446bool psphotResetModels (pmConfig *config, const pmFPAview *view, const char *filerule);
     447bool psphotResetModelsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     448
     449bool psphotRedefinePixels (pmConfig *config, const pmFPAview *view, const char *filerule);
     450bool psphotRedefinePixelsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     451
     452bool psphotSourceChildren (pmConfig *config, const pmFPAview *view, const char *ruleOut, const char *ruleSrc);
     453bool psphotSourceChildrenReadout (pmConfig *config, const pmFPAview *view, const char *ruleOut, const char *ruleSrc, int index);
     454psArray *psphotSourceChildrenByObject (pmConfig *config, const pmFPAview *view, const char *filerule, psArray *objectsSrc);
     455
    442456#endif
  • trunk/psphot/src/psphotApResid.c

    • Property svn:mergeinfo deleted
  • trunk/psphot/src/psphotBlendFit.c

    r29936 r30624  
    187187    psLogMsg ("psphot.psphotBlendFit", PS_LOG_INFO, "fit models: %f sec for %d objects (%d psf, %d ext, %d failed, %ld skipped)\n", psTimerMark ("psphot.fit.nonlinear"), Nfit, Npsf, Next, Nfail, sources->n - Nfit);
    188188
    189     psphotVisualShowResidualImage (readout);
     189    psphotVisualShowResidualImage (readout, false);
     190    psphotVisualShowObjectRegions (readout, recipe, sources);
    190191    psphotVisualShowFlags (sources);
    191192
  • trunk/psphot/src/psphotCheckStarDistribution.c

    r19909 r30624  
    3434        pmSource *source = stars->data[i];
    3535        if (source->peak == NULL) continue;
    36         if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
     36        if (!(source->tmpFlags & PM_SOURCE_TMPF_CANDIDATE_PSFSTAR)) continue;
    3737
    3838        int binX = psImageBinningGetRuffX (binning, source->peak->xf);
     
    8585        if (source->peak == NULL) continue;
    8686        if (source->moments == NULL) continue;
    87         if (source->mode & PM_SOURCE_MODE_PSFSTAR) continue;
     87        if (source->tmpFlags & PM_SOURCE_TMPF_CANDIDATE_PSFSTAR) continue;
    8888        if (source->mode & PM_SOURCE_MODE_SATSTAR) continue;
    8989        if (source->type != PM_SOURCE_TYPE_STAR) continue;
     
    9797        if (y > Ye) continue;
    9898
    99         source->mode |= PM_SOURCE_MODE_PSFSTAR;
     99        source->tmpFlags |= PM_SOURCE_TMPF_CANDIDATE_PSFSTAR;
    100100        psArrayAdd (stars, 200, source);
    101101
  • trunk/psphot/src/psphotChoosePSF.c

    r30041 r30624  
    22
    33// generate a PSF model for inputs without PSF models already loaded
    4 bool psphotChoosePSF (pmConfig *config, const pmFPAview *view, const char *filerule)
     4bool psphotChoosePSF (pmConfig *config, const pmFPAview *view, const char *filerule, bool newSources)
    55{
    66    bool status = true;
     
    1919    for (int i = 0; i < num; i++) {
    2020        if (i == chisqNum) continue; // skip chisq image
    21         if (!psphotChoosePSFReadout (config, view, filerule, i, recipe)) {
     21        if (!psphotChoosePSFReadout (config, view, filerule, i, recipe, newSources)) {
    2222            psError (PSPHOT_ERR_CONFIG, false, "failed to choose a psf model for %s entry %d", filerule, i);
    2323            return false;
     
    2828
    2929// try PSF models and select best option
    30 bool psphotChoosePSFReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe) {
     30bool psphotChoosePSFReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe, bool newSources) {
    3131
    3232    bool status;
     
    5050    psAssert (detections, "missing detections?");
    5151
    52     psArray *sources = detections->newSources;
     52    psArray *sources = newSources ? detections->newSources : detections->allSources;
    5353    psAssert (sources, "missing sources?");
    5454
     
    166166    for (int i = 0; i < sources->n; i++) {
    167167        pmSource *source = sources->data[i];
    168         if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
    169             // keep NSTARS PSF stars, unmark the rest
     168        if (source->tmpFlags & PM_SOURCE_TMPF_CANDIDATE_PSFSTAR) {
     169            // keep NSTARS PSF stars
    170170            if (stars->n < NSTARS) {
    171171                psArrayAdd (stars, 200, source);
    172             } else {
    173                 source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
    174172            }
    175173        }
     
    214212        psFree(options);
    215213
    216         // unset the PSFSTAR flags (none are used):
    217         for (int i = 0; i < sources->n; i++) {
    218             pmSource *source = sources->data[i];
    219             source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
    220         }
     214        // no sources are used as PSF stars
    221215
    222216        // XXX set sxx, etc from FWHM in recipe
     
    292286        psLogMsg ("psphot.pspsf", PS_LOG_INFO, "Using guess PSF model");
    293287
    294         // unset the PSFSTAR flags (none are used):
    295         for (int i = 0; i < sources->n; i++) {
    296             pmSource *source = sources->data[i];
    297             source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
    298         }
     288        // no sources are used as PSF stars
    299289
    300290        // XXX set sxx, etc from FWHM in recipe
     
    322312    pmPSFtry *try = models->data[bestN];
    323313
    324     // unset the PSFSTAR flag for stars not used for PSF model
    325     // XXX a more efficient way of achieving this would be to record a pair of arrays
    326     // of the source index and the source id for the psf stars.  but that would require we do
    327     // not re-sort the source list in the meanwhile
    328     int nDrop = 0;
     314    // set the PSFSTAR flag for stars used for the PSF model
     315    int nKeep = 0;
    329316    for (int i = 0; i < try->sources->n; i++) {
    330317        pmSource *source = try->sources->data[i];
    331         if (try->mask->data.PS_TYPE_VECTOR_MASK_DATA[i]) {
    332             // need to find this source in the original list (these are copies, not pointers)
    333             for (int j = 0; j < sources->n; j++) {
    334                 pmSource *realSource = sources->data[j];
    335                 if (realSource->id != source->id) continue;
    336                 realSource->mode &= ~PM_SOURCE_MODE_PSFSTAR;
    337                 source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
    338                 nDrop ++;
    339                 break;
    340             }
    341         }
    342     }
    343     // fprintf (stderr, "drop %d stars as PSF stars\n", nDrop);
    344 
    345     // XXX is this working?
    346     // int N1 = 0;
    347     // for (int i = 0; i < try->sources->n; i++) {
    348     //     pmSource *source = try->sources->data[i];
    349     //  fprintf (stderr, "%llx : %d\n", (long long int) source, (source->mode & PM_SOURCE_MODE_PSFSTAR));
    350     //  if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
    351     //      N1 ++;
    352     //     }
    353     // }
    354     // int N2 = 0;
    355     // for (int i = 0; i < sources->n; i++) {
    356     //     pmSource *source = sources->data[i];
    357     //  fprintf (stderr, "%llx : %d\n", (long long int) source, (source->mode & PM_SOURCE_MODE_PSFSTAR));
    358     //  if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
    359     //      N2 ++;
    360     //     }
    361     // }
    362     // fprintf (stderr, "N1: %d, N2: %d\n", N1, N2);
     318        if (try->mask->data.PS_TYPE_VECTOR_MASK_DATA[i]) continue;
     319        source->mode |= PM_SOURCE_MODE_PSFSTAR;
     320
     321        // this source was used: find the parent and set its PSFSTAR flag
     322        pmSource *realSource = source->parent;
     323        psAssert (realSource, "pmPSFtryAlloc should have set the parent pointers");
     324        realSource->mode |= PM_SOURCE_MODE_PSFSTAR;
     325        nKeep ++;
     326    }
     327    psLogMsg ("psphot.pspsf", PS_LOG_DETAIL, "used %d of %ld candidate PSF objects\n", nKeep, try->sources->n);
    363328
    364329    // build a PSF residual image
     330    // we need to use the 'try' set because they have the associated models defined
    365331    if (!psphotMakeResiduals (try->sources, recipe, try->psf, maskVal)) {
    366332        psError(PSPHOT_ERR_PSF, false, "Unable to construct residual table for PSF");
     
    386352    }
    387353
    388     // XXX test dump of psf star data and psf-subtracted image
     354    // test dump of psf star data and psf-subtracted image
    389355    if (psTraceGetLevel("psphot.psfstars") > 5) {
    390356        psphotDumpPSFStars (readout, try, options->fitRadius, maskVal, markVal);
     
    413379        return false;
    414380    }
    415     psFree (psf); // XXX double-check
    416 
    417     // move into psphotChoosePSF
     381    psFree (psf);
     382
    418383    psphotVisualShowPSFModel (readout, psf);
    419384
     
    436401    psVector *fwhmMajor = psVectorAllocEmpty (100, PS_DATA_F32);
    437402    psVector *fwhmMinor = psVectorAllocEmpty (100, PS_DATA_F32);
     403    psVector *psfExtra1 = psVectorAllocEmpty (100, PS_DATA_F32);
     404    psVector *psfExtra2 = psVectorAllocEmpty (100, PS_DATA_F32);
    438405
    439406    for (float ix = -0.4; ix <= +0.4; ix += 0.1) {
     
    459426            shape.sxy = modelPSF->params->data.F32[PM_PAR_SXY];
    460427            axes = psEllipseShapeToAxes (shape, 20.0);
    461             psFree (modelPSF);
    462428
    463429            float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
    464430            if (!isfinite(FWHM_MAJOR) || !isfinite(FWHM_MINOR)) {
    465431                fprintf (stderr, "!");
     432                psFree (modelPSF);
    466433                continue;
    467434            }
    468435            psVectorAppend (fwhmMajor, FWHM_MAJOR);
    469436            psVectorAppend (fwhmMinor, FWHM_MINOR);
     437
     438            if (modelPSF->params->n >= 7) {
     439              psVectorAppend (psfExtra1, modelPSF->params->data.F32[7]);
     440            }
     441            if (modelPSF->params->n >= 8) {
     442              psVectorAppend (psfExtra2, modelPSF->params->data.F32[8]);
     443            }
     444            psFree (modelPSF);
    470445        }
    471446    }
     
    474449    if (!psVectorStats (stats, fwhmMajor, NULL, NULL, 0)) {
    475450        psError(PS_ERR_UNKNOWN, false, "failure to measure stats for FWHM MAJOR");
    476         return false;
     451        goto escape;
    477452    }
    478453
     
    486461    if (!psVectorStats (stats, fwhmMinor, NULL, NULL, 0)) {
    487462        psError(PS_ERR_UNKNOWN, false, "failure to measure stats for FWHM MINOR");
    488         return false;
     463        goto escape;
    489464    }
    490465    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FWHM_MIN",   PS_META_REPLACE, "PSF FWHM Minor axis (mean)", stats->sampleMean);
     
    494469
    495470    float fwhmMin = stats->sampleMean;  // FWHM on minor axis
     471
    496472    if (readout->parent) {
     473
     474        // we now have 2 possible measurements of the seeing : the PSF model based version and
     475        // the Moments based value we need to define a definitive "CHIP.SEEING" value.  This
     476        // value is used by the PSF-matching programs (ppSub and ppStack).  The moments-based
     477        // value is probably more representative of the value needed by those tools (it is also
     478        // more stable?)
     479        bool status = false;
     480        float fwhmMajorMoments = psMetadataLookupF32(&status, readout->analysis, "IQ_FW1");
     481        float fwhmMinorMoments = psMetadataLookupF32(&status, readout->analysis, "IQ_FW1");
     482
    497483        pmChip *chip = readout->parent->parent; // Parent chip
    498484        psAssert(chip, "Cell should be attached to a chip.");
    499485        psMetadataItem *item = psMetadataLookup(chip->concepts, "CHIP.SEEING"); // Item with chip
    500         item->data.F32 = 0.5 * (fwhmMaj + fwhmMin);
     486        item->data.F32 = 0.5 * (fwhmMajorMoments + fwhmMinorMoments);
     487
     488        psLogMsg ("psphot", PS_LOG_DETAIL, "fwhm (psf): %f,%f (moments): %f,%f", fwhmMaj, fwhmMin, fwhmMajorMoments, fwhmMinorMoments);
     489    }
     490
     491    if (psfExtra1->n) {
     492      if (!psVectorStats (stats, psfExtra1, NULL, NULL, 0)) {
     493        psError(PS_ERR_UNKNOWN, false, "failure to measure stats for PSF EXTRA 1");
     494        goto escape;
     495      }
     496      psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "PSF_EXT1", PS_META_REPLACE, "PSF extra param 1", stats->sampleMean);
     497    }
     498
     499    if (psfExtra2->n) {
     500      if (!psVectorStats (stats, psfExtra2, NULL, NULL, 0)) {
     501        psError(PS_ERR_UNKNOWN, false, "failure to measure stats for PSF EXTRA 2");
     502        goto escape;
     503      }
     504      psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "PSF_EXT2", PS_META_REPLACE, "PSF extra param 2", stats->sampleMean);
    501505    }
    502506
    503507    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "ANGLE",    PS_META_REPLACE, "PSF angle",           axes.theta);
    504508    psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "NPSFSTAR", PS_META_REPLACE, "Number of stars used to make PSF", psf->nPSFstars);
    505     psMetadataAddBool(readout->analysis, PS_LIST_TAIL, "PSFMODEL", PS_META_REPLACE, "Valid PSF Model?", true);
     509
     510    char *psfModelName = pmModelClassGetName(psf->type);
     511    psMetadataAddStr(readout->analysis,  PS_LIST_TAIL, "PSFMODEL", PS_META_REPLACE, "PSF Model Name", psfModelName);
     512    psMetadataAddBool(readout->analysis, PS_LIST_TAIL, "PSF_OK",   PS_META_REPLACE, "Valid PSF Model?", true);
     513
     514    int nParams = pmModelClassParameterCount(psf->type);
     515    psMetadataAddS32(readout->analysis, PS_LIST_TAIL, "PSF_NPAR",   PS_META_REPLACE, "Number of PSF parameters", nParams);
    506516
    507517    psFree (fwhmMajor);
    508518    psFree (fwhmMinor);
     519    psFree (psfExtra1);
     520    psFree (psfExtra2);
    509521    psFree (stats);
    510522    return true;
     523
     524escape:
     525    psFree (fwhmMajor);
     526    psFree (fwhmMinor);
     527    psFree (psfExtra1);
     528    psFree (psfExtra2);
     529    psFree (stats);
     530    return false;
    511531}
    512532
     
    568588    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MN_LQ",   PS_META_REPLACE, "PSF FWHM Minor axis (lower quartile)", 0);
    569589    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MN_UQ",   PS_META_REPLACE, "PSF FWHM Minor axis (upper quartile)", 0);
    570     psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "ANGLE",    PS_META_REPLACE, "PSF angle",           FWHM_T);
    571     psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "NPSFSTAR", PS_META_REPLACE, "Number of stars used to make PSF", 0);
    572     psMetadataAddBool(readout->analysis, PS_LIST_TAIL, "PSFMODEL", PS_META_REPLACE, "Valid PSF Model?", false);
     590    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "ANGLE",      PS_META_REPLACE, "PSF angle",           FWHM_T);
     591    psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "NPSFSTAR",   PS_META_REPLACE, "Number of stars used to make PSF", 0);
     592    psMetadataAddStr(readout->analysis,  PS_LIST_TAIL, "PSFMODEL",   PS_META_REPLACE, "PSF Model Name", "NONE");
     593    psMetadataAddBool(readout->analysis, PS_LIST_TAIL, "PSF_OK",     PS_META_REPLACE, "Valid PSF Model?", false);
    573594
    574595    return true;
  • trunk/psphot/src/psphotExtendedSourceAnalysis.c

    r29936 r30624  
    173173    psLogMsg ("psphot", PS_LOG_INFO, "  %d kron\n", Nkron);
    174174
    175     psphotVisualShowResidualImage (readout);
     175    psphotVisualShowResidualImage (readout, false);
    176176
    177177    if (doPetrosian) {
  • trunk/psphot/src/psphotExtendedSourceAnalysisByObject.c

    r29936 r30624  
    5353        pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
    5454        psAssert (readout, "missing readout?");
     55
     56        psLogMsg("psphot", PS_LOG_INFO, "petrosians for image %d", i);
     57        psphotVisualShowImage(readout);
    5558
    5659        readouts->data[i] = psMemIncrRefCounter(readout);
  • trunk/psphot/src/psphotExtendedSourceFits.c

    r29936 r30624  
    1818    int num = psphotFileruleCount(config, filerule);
    1919
     20    // skip the chisq image (optionally?)
     21    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     22    if (!status) chisqNum = -1;
     23
    2024    // loop over the available readouts
    2125    for (int i = 0; i < num; i++) {
     26        if (i == chisqNum) continue; // skip chisq image
    2227        if (!psphotExtendedSourceFitsReadout (config, view, filerule, i, recipe)) {
    2328            psError (PSPHOT_ERR_CONFIG, false, "failed on to fit extended sources for %s entry %d", filerule, i);
     
    3742    int Nplain = 0;
    3843    int NplainPass = 0;
     44    int Nfaint = 0;
    3945
    4046    psTimerStart ("psphot.extended");
     
    4652    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
    4753    psAssert (readout, "missing readout?");
     54
     55    psLogMsg("psphot", PS_LOG_INFO, "extended source fits for image %d", index);
     56    psphotVisualShowImage(readout);
    4857
    4958    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     
    167176            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nplain
    168177            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for NplainPass
     178            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfain
    169179
    170180            if (false && !psThreadJobAddPending(job)) {
     
    189199                scalar = job->args->data[11];
    190200                NplainPass += scalar->data.S32;
     201                scalar = job->args->data[12];
     202                Nfaint += scalar->data.S32;
    191203                psFree(job);
    192204            }
     
    217229                scalar = job->args->data[11];
    218230                NplainPass += scalar->data.S32;
     231                scalar = job->args->data[12];
     232                Nfaint += scalar->data.S32;
    219233            }
    220234            psFree(job);
     
    227241    psLogMsg ("psphot", PS_LOG_INFO, "  %d convolved models (%d passed)\n", Nconvolve, NconvolvePass);
    228242    psLogMsg ("psphot", PS_LOG_INFO, "  %d plain models (%d passed)\n", Nplain, NplainPass);
     243    psLogMsg ("psphot", PS_LOG_INFO, "  %d too faint to fit\n", Nfaint);
    229244    return true;
    230245}
     
    238253    int NconvolvePass = 0;
    239254    int Nplain = 0;
     255    int Nfaint = 0;
    240256    int NplainPass = 0;
    241257    bool savePics = false;
     
    326342
    327343        // array to store the pointers to the model flux images while the models are being fitted
    328         psArray *modelFluxes = psArrayAllocEmpty (4);
     344        psArray *modelFluxes = psArrayAllocEmpty (models->list->n);
    329345
    330346        // allocate the array to store the model fits
    331347        if (source->modelFits == NULL) {
    332             source->modelFits = psArrayAllocEmpty (4);
     348            source->modelFits = psArrayAllocEmpty (models->list->n);
    333349        }
    334350
     
    350366          // limit selection to some SN limit
    351367          assert (source->peak); // how can a source not have a peak?
    352           if (source->peak->SN < SNlim) continue;
     368          if (source->peak->SN < SNlim) {
     369              Nfaint ++;
     370              continue;
     371          }
    353372
    354373          // check on the model type
     
    497516    scalar->data.S32 = NplainPass;
    498517
     518    scalar = job->args->data[12];
     519    scalar->data.S32 = Nfaint;
     520
    499521    return true;
    500522}
  • trunk/psphot/src/psphotFindDetections.c

    r29936 r30624  
    8686    psImage *significance = psphotSignificanceImage (readout, recipe, maskVal);
    8787
    88     // display the significance image
    89     psphotVisualShowSignificance (significance, -1.0, PS_SQR(3.0*NSIGMA_PEAK));
    90 
    9188    // display the log significance image
    9289    psphotVisualShowLogSignificance (significance, 0.0, 4.5);
     90
     91    // display the significance image
     92    psphotVisualShowSignificance (significance, 0.98*threshold, 1.02*threshold);
    9393
    9494    // detect the peaks in the significance image
     
    108108    }
    109109
     110    // XXX do a second (or third?) pass with rebinning (to detected more extended sources)
     111
    110112    psFree (significance);
    111113
  • trunk/psphot/src/psphotFindFootprints.c

    r27673 r30624  
    2121    psArray *footprints = pmFootprintsFind (significance, threshold, npixMin);
    2222
    23     pmFootprintsAssignPeaks(footprints, detections->peaks);
    24     // XXX handle the error conditions here
     23    if (pmFootprintsAssignPeaks(footprints, detections->peaks) != PS_ERR_NONE) {
     24        psAbort ("inconsistent peaks and footprints");
     25    }
    2526
    2627    // footprints now owns the peaks; after culling (below), we will rebuild the peaks array
  • trunk/psphot/src/psphotFitSourcesLinear.c

    r29936 r30624  
    4646            return false;
    4747        }
     48
     49        psphotVisualShowResidualImage (readout, (num > 0));
     50        psphotVisualShowPeaks (detections);
     51        psphotVisualShowObjectRegions (readout, recipe, sources);
    4852    }
    4953    return true;
     
    151155        if (x > AnalysisRegion.x1) continue;
    152156        if (y > AnalysisRegion.y1) continue;
     157
     158        // check the integral of the model : is it large enough?
     159        float modelSum = 0.0;
     160        for (int iy = 0; iy < source->modelFlux->numRows; iy++) {
     161            for (int ix = 0; ix < source->modelFlux->numCols; ix++) {
     162                modelSum += source->modelFlux->data.F32[iy][ix];
     163            }
     164        }
     165        if (modelSum < 0.5) continue; // skip sources with no model constraint (somewhat arbitrary limit)
     166        // if (modelSum < 0.01) continue; // skip sources with no model constraint (somewhat arbitrary limit)
     167        if (modelSum < 0.8) {
     168            fprintf (stderr, "low-sig model @ %f, %f (%f sum, %f peak)\n",
     169                     source->peak->xf, source->peak->yf, modelSum, source->peak->flux);
     170        }
     171
     172        pmModel *model = pmSourceGetModel (NULL, source);
     173
     174        psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
     175        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, model->fitRadius, "OR", markVal);
    153176
    154177        source->mode |= PM_SOURCE_MODE_LINEAR_FIT;
     
    270293        model->params->data.F32[PM_PAR_I0] = norm->data.F32[i];
    271294        model->dparams->data.F32[PM_PAR_I0] = errors->data.F32[i];
    272         // XXX is the value of 'errors' modified by the sky fit?
    273295
    274296        // subtract object
     
    297319    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "measure ensemble of PSFs: %f sec\n", psTimerMark ("psphot.linear"));
    298320
    299     psphotVisualShowResidualImage (readout);
    300321    psphotVisualPlotChisq (sources);
    301322    // psphotVisualShowFlags (sources);
  • trunk/psphot/src/psphotFitSourcesLinearStack.c

    r29548 r30624  
    176176
    177177    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "measure ensemble of PSFs: %f sec\n", psTimerMark ("psphot.linear"));
    178 
    179178    return true;
    180179}
  • trunk/psphot/src/psphotImageQuality.c

    r29936 r30624  
    7979        // select by PSFSTAR mode?
    8080        // ??
    81         if (source->type != PM_SOURCE_TYPE_STAR || !(source->mode & PM_SOURCE_MODE_PSFSTAR)) {
     81        if (source->type != PM_SOURCE_TYPE_STAR || !(source->tmpFlags & PM_SOURCE_TMPF_CANDIDATE_PSFSTAR)) {
    8282            psTrace("psphot", 10, "Ignoring source for image quality because not a good star");
    8383            continue;
     
    133133    if (num == 0) {
    134134        psLogMsg ("psphot", PS_LOG_INFO, "no valid sources for image quality, skipping");
     135        psFree(FWHM_MAJOR);
     136        psFree(FWHM_MINOR);
     137        psFree(M2);
     138        psFree(M2c);
     139        psFree(M2s);
     140        psFree(M3);
     141        psFree(M4);
     142
    135143        return true;
    136144    }
  • trunk/psphot/src/psphotMakeFluxScale.c

    • Property svn:mergeinfo deleted
  • trunk/psphot/src/psphotMakePSFReadout.c

    r29936 r30624  
    6060    // Use bright stellar objects to measure PSF. If we do not have enough stars to generate
    6161    // the PSF, build one from the SEEING guess and model class
    62     if (!psphotChoosePSF (config, view, filerule)) {
     62    if (!psphotChoosePSF (config, view, filerule, true)) {
    6363        psLogMsg ("psphot", 3, "failure to construct a psf model");
    6464        return psphotReadoutCleanup (config, view, filerule);
  • trunk/psphot/src/psphotMakeResiduals.c

    r27532 r30624  
    136136        psFree (interp);
    137137    }
     138    xSize = PS_MIN(xSize, 2*radiusMax+3);
     139    ySize = PS_MIN(ySize, 2*radiusMax+3);
     140
    138141    pmResiduals *resid = pmResidualsAlloc (xSize, ySize, xBin, yBin);
    139142    psImageInit (resid->mask, 0);
     
    316319    psFree (B);
    317320
    318     psLogMsg ("psphot.pspsf", PS_LOG_MINUTIA, "generate residuals for %ld objects: %f sec\n", input->n, psTimerMark ("psphot.residuals"));
     321    psLogMsg ("psphot.pspsf", PS_LOG_DETAIL, "generate residuals for %ld objects: %f sec\n", input->n, psTimerMark ("psphot.residuals"));
    319322
    320323    psFree (xC);
  • trunk/psphot/src/psphotMergeSources.c

    r29936 r30624  
    513513    }
    514514
    515     return true;
    516 }
    517 
     515    // loop over the sources, redefine their pixels to point at the new filerule image,
     516    // copy the source data, and add a reference back to the original source
     517   
     518
     519    return true;
     520}
     521
     522// create source children from ruleSrc for ruleOut
     523bool psphotSourceChildren (pmConfig *config, const pmFPAview *view, const char *ruleOut, const char *ruleSrc)
     524{
     525    bool status = true;
     526
     527    int num = psphotFileruleCount(config, ruleSrc);
     528
     529    // skip the chisq image because it is a duplicate of the detection version
     530    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     531    if (!status) chisqNum = -1;
     532
     533    // loop over the available readouts
     534    for (int i = 0; i < num; i++) {
     535        if (i == chisqNum) continue; // skip chisq image
     536        if (!psphotSourceChildrenReadout (config, view, ruleOut, ruleSrc, i)) {
     537            psError (PSPHOT_ERR_CONFIG, false, "failed to copy sources from %s to %s entry %d", ruleSrc, ruleOut, i);
     538            return false;
     539        }
     540    }
     541    return true;
     542}
     543
     544// create source children from ruleSrc for ruleOut for this entry.  XXX currently, this is only
     545// used by psphotStackReadout (sources go on allSources so that psphotChoosePSF can be called
     546// repeatedly)
     547bool psphotSourceChildrenReadout (pmConfig *config, const pmFPAview *view, const char *ruleOut, const char *ruleSrc, int index) {
     548
     549    bool status;
     550
     551    // find the currently selected readout
     552    pmFPAfile *fileSrc = pmFPAfileSelectSingle(config->files, ruleSrc, index); // File of interest
     553    psAssert (fileSrc, "missing file?");
     554
     555    pmReadout *readoutSrc = pmFPAviewThisReadout(view, fileSrc->fpa);
     556    psAssert (readoutSrc, "missing readout?");
     557
     558    pmDetections *detectionsSrc = psMetadataLookupPtr (&status, readoutSrc->analysis, "PSPHOT.DETECTIONS");
     559    psAssert (detectionsSrc, "missing detections?");
     560
     561    psArray *sourcesSrc = detectionsSrc->allSources;
     562    psAssert (sourcesSrc, "missing sources?");
     563
     564    // find the currently selected readout
     565    pmFPAfile *fileOut = pmFPAfileSelectSingle(config->files, ruleOut, index); // File of interest
     566    psAssert (fileOut, "missing file?");
     567
     568    pmReadout *readoutOut = pmFPAviewThisReadout(view, fileOut->fpa);
     569    psAssert (readoutOut, "missing readout?");
     570
     571    // generate a new detection structure for the output filerule
     572    pmDetections *detectionsOut = psMetadataLookupPtr (&status, readoutOut->analysis, "PSPHOT.DETECTIONS");
     573    if (!detectionsOut) {
     574        detectionsOut = pmDetectionsAlloc();
     575        detectionsOut->allSources = psArrayAllocEmpty (100);
     576        // save detections on the readout->analysis
     577        if (!psMetadataAddPtr (readoutOut->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot detections", detectionsOut)) {
     578            psError (PSPHOT_ERR_CONFIG, false, "problem saving detections on readout");
     579            return false;
     580        }
     581        psFree(detectionsOut); // a copy remains on the analysis metadata
     582    }
     583
     584    // loop over the sources, redefine their pixels to point at the new filerule image,
     585    // copy the source data, and add a reference back to the original source
     586   
     587    // copy the sources from sourceSrcs to the new detection structure
     588    for (int i = 0; i < sourcesSrc->n; i++) {
     589      pmSource *sourceSrc = sourcesSrc->data[i];
     590
     591      pmSource *sourceOut = pmSourceCopy(sourceSrc);
     592      sourceOut->parent = sourceSrc;
     593     
     594      // keep the original source flags
     595      sourceOut->type     = sourceSrc->type;
     596      sourceOut->mode     = sourceSrc->mode;
     597      sourceOut->mode2    = sourceSrc->mode2;
     598      sourceOut->tmpFlags = sourceSrc->tmpFlags;
     599
     600      // does this copy all model data? (NO)
     601      sourceOut->modelPSF = pmModelCopy(sourceSrc->modelPSF);
     602      sourceOut->modelEXT = pmModelCopy(sourceSrc->modelEXT);
     603
     604      if (sourceSrc->modelFits) {
     605          sourceOut->modelFits = psArrayAlloc(sourceSrc->modelFits->n);
     606          for (int j = 0; j < sourceSrc->modelFits->n; j++) {
     607              sourceOut->modelFits->data[j] = pmModelCopy(sourceSrc->modelFits->data[j]);
     608          }
     609      }
     610
     611      // drop the references to the original image pixels:
     612      pmSourceFreePixels (sourceOut);
     613
     614      // allocate image, weight, mask for the new image for each peak
     615      pmSourceRedefinePixels (sourceOut, readoutOut, sourceOut->peak->x, sourceOut->peak->y, sourceOut->modelPSF->fitRadius);
     616
     617      // child sources have not been subtracted in this image, but this flag may be raised if
     618      // they were subtracted in the parent's image
     619      sourceOut->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED;
     620
     621      psArrayAdd (detectionsOut->allSources, 100, sourceOut);
     622      psFree (sourceOut);
     623    }
     624    psLogMsg ("psphot", 3, "%ld known sources supplied", detectionsOut->allSources->n);
     625
     626
     627    return true;
     628}
     629
     630// create source children associated with 'filerule' from the objectsSrc.  XXX currently, this
     631// is only used by psphotStackReadout (sources go on allSources so that psphotChoosePSF can be
     632// called repeatedly)
     633psArray *psphotSourceChildrenByObject (pmConfig *config, const pmFPAview *view, const char *filerule, psArray *objectsSrc) {
     634
     635    bool status;
     636
     637    int nImages = psphotFileruleCount(config, filerule);
     638
     639    // generate look-up arrays for detections and readouts
     640    psArray *detArrays = psArrayAlloc(nImages);
     641    psArray *readouts = psArrayAlloc(nImages);
     642
     643    for (int i = 0; i < nImages; i++) {
     644
     645        // find the currently selected readout
     646        pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, i); // File of interest
     647        psAssert (file, "missing file?");
     648
     649        pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     650        psAssert (readout, "missing readout?");
     651
     652        pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     653        if (!detections) {
     654            detections = pmDetectionsAlloc();
     655            detections->allSources = psArrayAllocEmpty (100);
     656            detections->peaks = psArrayAllocEmpty (100);
     657            // save detections on the readout->analysis
     658            if (!psMetadataAddPtr (readout->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot detections", detections)) {
     659                psError (PSPHOT_ERR_CONFIG, false, "problem saving detections on readout");
     660                return NULL;
     661            }
     662            psFree(detections); // a copy remains on the analysis metadata
     663            psAssert (detections, "missing detections?");
     664        }
     665        detArrays->data[i] = psMemIncrRefCounter(detections);
     666        readouts->data[i] = psMemIncrRefCounter(readout);
     667    }
     668
     669    psArray *objectsOut = psArrayAlloc(objectsSrc->n);
     670
     671    // copy all sources for each object
     672    for (int k = 0; k < objectsSrc->n; k++) {
     673
     674        pmPhotObj *objectSrc = objectsSrc->data[k];
     675        if (!objectSrc) continue;
     676        if (!objectSrc->sources) continue;
     677
     678        pmPhotObj *objectOut = pmPhotObjAlloc();
     679        objectsOut->data[k] = objectOut;
     680
     681        objectOut->SN = objectSrc->SN;
     682        objectOut->x  = objectSrc->x;
     683        objectOut->y  = objectSrc->y;
     684       
     685        objectOut->sources = psArrayAlloc(objectSrc->sources->n);
     686
     687        // copy the sources from sourceSrcs to the new detection structure
     688        // loop over the sources, redefine their pixels to point at the new filerule image,
     689        // copy the source data, and add a reference back to the original source
     690        for (int i = 0; i < objectSrc->sources->n; i++) {
     691
     692            pmSource *sourceSrc = objectSrc->sources->data[i];
     693
     694            pmSource *sourceOut = pmSourceCopy(sourceSrc);
     695            objectOut->sources->data[i] = sourceOut;
     696
     697            sourceOut->parent = sourceSrc;
     698
     699            // keep the original source flags
     700            sourceOut->type     = sourceSrc->type;
     701            sourceOut->mode     = sourceSrc->mode;
     702            sourceOut->mode2    = sourceSrc->mode2;
     703            sourceOut->tmpFlags = sourceSrc->tmpFlags;
     704
     705            // does this copy all model data? (NO)
     706            sourceOut->modelPSF = pmModelCopy(sourceSrc->modelPSF);
     707            sourceOut->modelEXT = pmModelCopy(sourceSrc->modelEXT);
     708
     709            if (sourceSrc->modelFits) {
     710                sourceOut->modelFits = psArrayAlloc(sourceSrc->modelFits->n);
     711                for (int j = 0; j < sourceSrc->modelFits->n; j++) {
     712                    sourceOut->modelFits->data[j] = pmModelCopy(sourceSrc->modelFits->data[j]);
     713                }
     714            }
     715
     716            // drop the references to the original image pixels:
     717            pmSourceFreePixels (sourceOut);
     718
     719            // set the output readotu
     720            int index = sourceOut->imageID;
     721            if (index >= readouts->n) continue; // skip the sources generated by the chisq image
     722            pmReadout *readout = readouts->data[index];
     723
     724            // allocate image, weight, mask for the new image for each peak
     725            pmSourceRedefinePixels (sourceOut, readout, sourceOut->peak->x, sourceOut->peak->y, sourceOut->modelPSF->fitRadius);
     726
     727            // child sources have not been subtracted in this image, but this flag may be raised if
     728            // they were subtracted in the parent's image
     729            sourceOut->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED;
     730
     731            // set the output detections:
     732            pmDetections *detectionsOut = detArrays->data[index];
     733            psArrayAdd (detectionsOut->allSources, 100, sourceOut);
     734            psArrayAdd (detectionsOut->peaks, 100, sourceOut->peak);
     735        }
     736    }
     737
     738    for (int i = 0; i < nImages; i++) {
     739        pmDetections *detections = detArrays->data[i];
     740        psLogMsg ("psphot", 3, "%ld source children for image %d", detections->allSources->n, i);
     741    }
     742
     743    psFree (detArrays);
     744    psFree (readouts);
     745
     746    return objectsOut;
     747}
     748
  • trunk/psphot/src/psphotOutput.c

    r30560 r30624  
    1515    psFree (name);
    1616    return num;
     17}
     18
     19// convert filerule to filerule.NUM and look up in the config->arguments metadata
     20bool psphotFileruleCountSet(const pmConfig *config, const char *filerule, int num) {
     21
     22    psString name = NULL;
     23    psStringAppend(&name, "%s.NUM", filerule);
     24
     25    bool status = psMetadataAddS32(config->arguments, PS_LIST_TAIL, name, PS_META_REPLACE, "", num);
     26    psFree (name);
     27
     28    return status;
    1729}
    1830
     
    261273    psMetadataItemSupplement (&status, header, analysis, "ANGLE");
    262274
     275    psMetadataItemSupplement (&status, header, analysis, "PSFMODEL");
     276    psMetadataItemSupplement (&status, header, analysis, "PSF_OK");
     277
    263278    // Image Quality measurements
    264279    psMetadataItemSupplement (&status, header, analysis, "IQ_NSTAR");
  • trunk/psphot/src/psphotPetrosianAnalysis.c

    r25755 r30624  
    6464    }
    6565
    66     psphotVisualShowResidualImage (readout);
     66    psphotVisualShowResidualImage (readout, false);
    6767    return true;
    6868}
  • trunk/psphot/src/psphotPetrosianProfile.c

    r25755 r30624  
    6868    // XXX this will only work in the psphot context, not the psphotPetrosianStudy...
    6969    // XXX add the petrosian to the pmSource structure...
    70     // psphotVisualShowResidualImage (readout);
    7170    psphotVisualShowPetrosian (source, petrosian);
    7271
  • trunk/psphot/src/psphotRadialApertures.c

    r29936 r30624  
    102102        if (source->peak->x > AnalysisRegion.x1) continue;
    103103        if (source->peak->y > AnalysisRegion.y1) continue;
     104
     105        // allocate pmSourceExtendedParameters, if not already defined
     106        if (!source->radialAper) {
     107            source->radialAper = psArrayAlloc(1);
     108        }
    104109
    105110        // replace object in image
     
    116121        pmSourceRedefinePixels (source, readout, source->peak->xf, source->peak->yf, 1.5*radius);
    117122
    118         if (!psphotRadialApertureSource (source, recipe, skynoise, maskVal, radMax)) {
     123        if (!psphotRadialApertureSource (source, recipe, skynoise, maskVal, radMax, 0)) {
    119124            psTrace ("psphot", 5, "failed to extract radial profile for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    120125        } else {
     
    130135}
    131136
    132 bool psphotRadialApertureSource (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal, const psVector *radMax) {
    133 
    134     // allocate pmSourceExtendedParameters, if not already defined
    135     if (!source->radial) {
    136         source->radial = pmSourceRadialAperturesAlloc ();
     137bool psphotRadialApertureSource (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal, const psVector *aperRadii, int entry) {
     138
     139    // if we are a child source, save the results to the parent source radial aperture array
     140    psArray *radialAperSet = source->radialAper;
     141    if (source->parent) {
     142        radialAperSet = source->parent->radialAper;
     143    }
     144    psAssert(radialAperSet, "this should be defined before calling");
     145    psAssert(radialAperSet->data[entry] == NULL, "why is this already defined?");
     146
     147    pmSourceRadialApertures *radialAper = pmSourceRadialAperturesAlloc ();
     148    radialAperSet->data[entry] = radialAper;
     149
     150    // storage for the derived pixel values
     151    psVector *pixRadius2 = psVectorAllocEmpty(100, PS_TYPE_F32);
     152    psVector *pixFlux    = psVectorAllocEmpty(100, PS_TYPE_F32);
     153    psVector *pixVar     = psVectorAllocEmpty(100, PS_TYPE_F32);
     154
     155    // outer-most radius for initial truncation
     156    float Rmax  = aperRadii->data.F32[aperRadii->n - 1];
     157    float Rmax2 = PS_SQR(Rmax);
     158
     159    // store the R^2 values for the apertures
     160    psVector *aperRadii2 = psVectorAlloc(aperRadii->n, PS_TYPE_F32);
     161    for (int i = 0; i < aperRadii->n; i++) {
     162        aperRadii2->data.F32[i] = PS_SQR(aperRadii->data.F32[i]);
     163    }
     164
     165    // center of the apertures
     166    float xCM = source->moments->Mx - 0.5 - source->pixels->col0; // coord of peak in subimage
     167    float yCM = source->moments->My - 0.5 - source->pixels->row0; // coord of peak in subimage
     168
     169    // one pass through the pixels to select the valid pixels and calculate R^2
     170    for (int iy = 0; iy < source->pixels->numRows; iy++) {
     171
     172        float yDiff = iy - yCM;
     173        if (fabs(yDiff) > Rmax) continue;
     174
     175        float *vPix = source->pixels->data.F32[iy];
     176        float *vWgt = source->variance->data.F32[iy];
     177        psImageMaskType  *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy];
     178
     179        for (int ix = 0; ix < source->pixels->numCols; ix++, vPix++, vWgt++) {
     180
     181            if (vMsk) {
     182                if (*vMsk & maskVal) {
     183                    vMsk++;
     184                    continue;
     185                }
     186                vMsk++;
     187            }
     188            if (isnan(*vPix)) continue;
     189
     190            float xDiff = ix - xCM;
     191            if (fabs(xDiff) > Rmax) continue;
     192
     193            // radius is just a function of (xDiff, yDiff)
     194            float r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
     195            if (r2 > Rmax2) continue;
     196
     197            psVectorAppend(pixRadius2, r2);
     198            psVectorAppend(pixFlux, *vPix);
     199            psVectorAppend(pixVar, *vWgt);
     200        }
     201    }
     202
     203    psVector *flux    = psVectorAlloc(aperRadii->n, PS_TYPE_F32); // surface brightness of radial bin
     204    psVector *fluxErr = psVectorAlloc(aperRadii->n, PS_TYPE_F32); // surface brightness of radial bin
     205    psVector *fill    = psVectorAlloc(aperRadii->n, PS_TYPE_F32); // surface brightness of radial bin
     206
     207    psVectorInit (flux,    0.0);
     208    psVectorInit (fluxErr, 0.0);
     209    psVectorInit (fill,    0.0);
     210
     211    float *rPix2 = pixRadius2->data.F32;
     212    for (int i = 0; i < pixRadius2->n; i++, rPix2++) {
     213
     214        float *aRad2 = aperRadii2->data.F32;
     215        for (int j = 0; (*rPix2 < *aRad2) && (j < aperRadii2->n); j++, aRad2++) {
     216            flux->data.F32[j]    += pixFlux->data.F32[i];
     217            fluxErr->data.F32[j] += pixVar->data.F32[i];
     218            fill->data.F32[j]    += 1.0;
     219        }
     220    }
     221
     222    for (int i = 0; i < flux->n; i++) {
     223        // calculate the total flux for bin 'nOut'
     224        float Area = M_PI*aperRadii2->data.F32[i];
     225        fluxErr->data.F32[i] = sqrt(fluxErr->data.F32[i]);
     226        fill->data.F32[i] /= Area;
     227        psTrace ("psphot", 5, "radial bins: %3d  %5.1f : %8.1f +/- %7.2f : %4.2f %6.1f\n",
     228                 i, aperRadii->data.F32[i], flux->data.F32[i], fluxErr->data.F32[i], fill->data.F32[i], Area);
    137229    }
    138230   
    139     psVector *radius  = psVectorAllocEmpty(100, PS_TYPE_F32);
     231    radialAper->flux = flux;
     232    radialAper->fluxErr = fluxErr;
     233    radialAper->fill = fill;
     234
     235    psFree (aperRadii2);
     236    psFree (pixRadius2);
     237    psFree (pixFlux);
     238    psFree (pixVar);
     239
     240    return true;
     241}
     242
     243static int nCalls = 0;
     244static int nPass = 0;
     245static int nPix = 0;
     246
     247bool psphotRadialApertureSource_With_Sort (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal, const psVector *radMax, int entry) {
     248
     249    psAssert(source->radialAper->data[entry] == NULL, "why is this already defined?");
     250
     251    pmSourceRadialApertures *radialAper = pmSourceRadialAperturesAlloc ();
     252    source->radialAper->data[entry] = radialAper;
     253
     254    psVector *pixRadius  = psVectorAllocEmpty(100, PS_TYPE_F32);
    140255    psVector *pixFlux = psVectorAllocEmpty(100, PS_TYPE_F32);
    141256    psVector *pixVar  = psVectorAllocEmpty(100, PS_TYPE_F32);
     
    144259        for (int ix = 0; ix < source->pixels->numCols; ix++) {
    145260
    146             // 0.5 PIX: get radius as a function of pixel coord
     261            // 0.5 PIX: get pixRadius as a function of pixel coord
    147262            float x = ix + 0.5 - source->peak->xf + source->pixels->col0;
    148263            float y = iy + 0.5 - source->peak->yf + source->pixels->row0;
     
    150265            float r = hypot(x, y);
    151266
    152             psVectorAppend(radius, r);
     267            psVectorAppend(pixRadius, r);
    153268            psVectorAppend(pixFlux, source->pixels->data.F32[iy][ix]);
    154269            psVectorAppend(pixVar, source->variance->data.F32[iy][ix]);
    155         }
    156     }
    157     psphotRadialAperturesSortFlux(radius, pixFlux, pixVar);
     270            nPix ++;
     271            // if (nPix % 10000 == 0) {fprintf (stderr, "?");}
     272        }
     273    }
     274    psphotRadialAperturesSortFlux(pixRadius, pixFlux, pixVar);
    158275
    159276    psVector *flux    = psVectorAllocEmpty(radMax->n, PS_TYPE_F32); // surface brightness of radial bin
     
    174291
    175292    // XXX assume (or enforce) that the bins are contiguous and non-overlapping (Rmax[i] = Rmin[i+1])
    176     for (int i = 0; !done && (i < radius->n); i++) {
    177         if (radius->data.F32[i] > Rmax) {
     293    for (int i = 0; !done && (i < pixRadius->n); i++) {
     294        if (pixRadius->data.F32[i] > Rmax) {
    178295            // calculate the total flux for bin 'nOut'
    179296            float Area = M_PI*PS_SQR(Rmax);
     
    185302                     nOut, radMax->data.F32[nOut], flux->data.F32[nOut], fluxErr->data.F32[nOut], fill->data.F32[nOut], Area);
    186303
     304            nPass ++;
     305            // if (nPass % 1000 == 0) {fprintf (stderr, "!");}
     306
    187307            nOut ++;
    188308            if (nOut >= radMax->n) break;
     
    195315    flux->n = fluxErr->n = fill->n = nOut;
    196316   
    197     psFree(source->radial->flux);
    198     psFree(source->radial->fluxErr);
    199     psFree(source->radial->fill);
    200 
    201     source->radial->flux = flux;
    202     source->radial->fluxErr = fluxErr;
    203     source->radial->fill = fill;
    204 
    205     psFree (radius);
     317    radialAper->flux = flux;
     318    radialAper->fluxErr = fluxErr;
     319    radialAper->fill = fill;
     320
     321    psFree (pixRadius);
    206322    psFree (pixFlux);
    207323    psFree (pixVar);
    208324
     325    nCalls ++;
     326    // if (nCalls % 100 == 0) {fprintf (stderr, "*");}
    209327    return true;
    210328}
  • trunk/psphot/src/psphotRadialAperturesByObject.c

    r29936 r30624  
    33// aperture-like measurements for extended sources
    44// flux in simple, circular apertures
    5 bool psphotRadialAperturesByObject (pmConfig *config, psArray *objects, const pmFPAview *view, const char *filerule) {
     5
     6// **** it looks like this function will re-point the source pixels at the specified FILERULE
     7// **** I need to distinguish PSF-matched images from raw
     8// **** save (somewhere) the PSF-matched PSF values
     9
     10// this function measures the radial aperture fluxes for the set of readouts.  this function
     11// may be called multiple times (presumably with different matched PSF sizes).  we must have
     12// already added an entry to the readout->analysis identifying the FWHM of this version.
     13
     14bool psphotRadialAperturesByObject (pmConfig *config, psArray *objects, const pmFPAview *view, const char *filerule, int nMatchedPSF) {
    615
    716    bool status;
     
    2837    psAssert (radMax, "annular bins (RADIAL.ANNULAR.BINS.UPPER) are not defined in the recipe");
    2938    psAssert (radMax->n, "no valid annular bins (RADIAL.ANNULAR.BINS.UPPER) are define");
     39    float outerRadius = radMax->data.F32[radMax->n - 1];
    3040
    3141    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     
    3949    float SN_LIM = psMetadataLookupF32 (&status, recipe, "RADIAL_APERTURES_SN_LIM");
    4050
     51    // how many target PSFs do we want?
     52    int nPSFsizes = 0;
     53    {
     54        psMetadataLookupF32 (&status, recipe, "PSPHOT.STACK.TARGET.PSF.FWHM");
     55        if (status) {
     56            nPSFsizes = 1;
     57        } else {
     58            psVector *fwhmValues = psMetadataLookupVector(&status, recipe, "PSPHOT.STACK.TARGET.PSF.FWHM"); // Magnitude offsets
     59            psAssert (status, "missing psphot recipe value PSPHOT.STACK.TARGET.PSF.FWHM");
     60            nPSFsizes = fwhmValues->n;
     61        }
     62    }
     63   
    4164    // source analysis is done in S/N order (brightest first)
    4265    objects = psArraySort (objects, pmPhotObjSortBySN);
     
    5275        pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
    5376        psAssert (readout, "missing readout?");
     77
     78        psVector *fwhmValues = psMetadataLookupVector(&status, readout->analysis, "STACK.PSF.FWHM.VALUES");
     79        if (!fwhmValues) {
     80            psError (PSPHOT_ERR_CONFIG, true, "convolved or measured FWHM is not defined for this readout");
     81            return false;
     82        }
     83        if (fwhmValues->n != nMatchedPSF + 1) {
     84            psError (PSPHOT_ERR_CONFIG, true, "convolved or measured FWHM sequence is inconsistent this readout");
     85            return false;
     86        }
     87        psLogMsg ("psphot", PS_LOG_DETAIL, "PSF FWHM of %s : %f pixels\n", file->name, fwhmValues->data.F32[nMatchedPSF]);
    5488
    5589        readouts->data[i] = psMemIncrRefCounter(readout);
     
    77111            if (source->peak->SN < SN_LIM) continue;
    78112
     113            int index = source->imageID;
     114            if (index >= readouts->n) continue; // skip the sources generated by the chisq image
     115            pmReadout *readout = readouts->data[index];
     116
     117            // psLogMsg("psphot", PS_LOG_INFO, "radial apertures for %d", index);
     118            // psphotVisualShowImage(readout);
     119
     120            // allocate pmSourceExtendedParameters, if not already defined
     121            if (source->parent) {
     122                if (!source->parent->radialAper) {
     123                    source->parent->radialAper = psArrayAlloc(nPSFsizes);
     124                }
     125            } else {
     126                if (!source->radialAper) {
     127                    source->radialAper = psArrayAlloc(nPSFsizes);
     128                }
     129            }
     130
    79131            // replace object in image
    80132            if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) {
    81133                pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    82134            }
     135
     136            // we need to change the view for the radial aperture analysis, but we want to recover exactly
     137            // the original view; the following elements get destroyed by pmSourceRedefinePixels so save them:
     138            psImage *oldMaskObj   = psMemIncrRefCounter(source->maskObj);
     139            psImage *oldModelFlux = psMemIncrRefCounter(source->modelFlux);
     140            psImage *oldPSFimage  = psMemIncrRefCounter(source->psfImage);
     141            psRegion oldRegion    = source->region;
     142
    83143            Nradial ++;
    84144
    85             int index = source->imageID;
    86             pmReadout *readout = readouts->data[index];
     145            // psLogMsg("psphot", PS_LOG_INFO, "radial apertures for %d", index);
     146            // psphotVisualShowImage(readout);
    87147
    88148            // force source image to be a bit larger...
    89             float radius = source->peak->xf - source->pixels->col0;
    90             radius = PS_MAX (radius, source->peak->yf - source->pixels->row0);
    91             radius = PS_MAX (radius, source->pixels->numRows - source->peak->yf + source->pixels->row0);
    92             radius = PS_MAX (radius, source->pixels->numCols - source->peak->xf + source->pixels->col0);
    93             pmSourceRedefinePixels (source, readout, source->peak->xf, source->peak->yf, 1.5*radius);
     149            // float radius = source->peak->xf - source->pixels->col0;
     150            // radius = PS_MAX (radius, source->peak->yf - source->pixels->row0);
     151            // radius = PS_MAX (radius, source->pixels->numRows - source->peak->yf + source->pixels->row0);
     152            // radius = PS_MAX (radius, source->pixels->numCols - source->peak->xf + source->pixels->col0);
     153            pmSourceRedefinePixels (source, readout, source->peak->xf, source->peak->yf, outerRadius + 2);
    94154
    95             if (!psphotRadialApertureSource (source, recipe, skynoise, maskVal, radMax)) {
     155            if (!psphotRadialApertureSource (source, recipe, skynoise, maskVal, radMax, nMatchedPSF)) {
    96156                psTrace ("psphot", 5, "failed to extract radial profile for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    97157            } else {
     
    99159            }
    100160
     161            pmSourceRedefinePixelsByRegion (source, readout, oldRegion);
     162            psFree(source->maskObj);   source->maskObj   = oldMaskObj;
     163            psFree(source->modelFlux); source->modelFlux = oldModelFlux;
     164            psFree(source->psfImage);  source->psfImage  = oldPSFimage;
     165
    101166            // re-subtract the object, leave local sky
    102167            pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     168
     169            // psLogMsg("psphot", PS_LOG_INFO, "radial apertures for %d", index);
     170            // psphotVisualShowImage(readout);
    103171        }
    104172    }
  • trunk/psphot/src/psphotReadout.c

    r29936 r30624  
    112112    // use bright stellar objects to measure PSF if we were supplied a PSF for any input file,
    113113    // this step is skipped
    114     if (!psphotChoosePSF (config, view, filerule)) { // pass 1
     114    if (!psphotChoosePSF (config, view, filerule, true)) { // pass 1
    115115        psLogMsg ("psphot", 3, "failure to construct a psf model");
    116116        return psphotReadoutCleanup (config, view, filerule);
  • trunk/psphot/src/psphotReadoutFindPSF.c

    r29936 r30624  
    4949    }
    5050
    51     if (!psphotChoosePSF(config, view, filerule)) {
     51    if (!psphotChoosePSF(config, view, filerule, true)) {
    5252        psError(PSPHOT_ERR_PSF, false, "Failed to construct a psf model");
    5353        return psphotReadoutCleanup (config, view, filerule);
  • trunk/psphot/src/psphotReadoutKnownSources.c

    r29936 r30624  
    4343    }
    4444
    45     if (!psphotChoosePSF (config, view, filerule)) {
     45    if (!psphotChoosePSF (config, view, filerule, true)) {
    4646        psError(PSPHOT_ERR_PSF, false, "Failed to construct a psf model");
    4747        return psphotReadoutCleanup (config, view, filerule);
  • trunk/psphot/src/psphotReplaceUnfit.c

    r29936 r30624  
    7575      pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    7676    }
     77
     78    psphotVisualShowImage(readout);
    7779    psLogMsg ("psphot.replace", PS_LOG_INFO, "replaced models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.replace"));
    7880    return true;
     
    101103    return true;
    102104}
     105
     106// modify the sources to point at the corresponding pixels for the given filerule
     107bool psphotRedefinePixels (pmConfig *config, const pmFPAview *view, const char *filerule)
     108{
     109    bool status = true;
     110
     111    // select the appropriate recipe information
     112    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     113    psAssert (recipe, "missing recipe?");
     114
     115    int num = psphotFileruleCount(config, filerule);
     116
     117    // loop over the available readouts
     118    for (int i = 0; i < num; i++) {
     119        if (!psphotRedefinePixelsReadout (config, view, filerule, i, recipe)) {
     120            psError (PSPHOT_ERR_CONFIG, false, "failed to replace all sources for %s entry %d", filerule, i);
     121            return false;
     122        }
     123    }
     124    return true;
     125}
     126
     127bool psphotRedefinePixelsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe) {
     128
     129    bool status;
     130    pmSource *source;
     131
     132    psTimerStart ("psphot.replace");
     133
     134    // find the currently selected readout
     135    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, index); // File of interest
     136    psAssert (file, "missing file?");
     137
     138    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     139    psAssert (readout, "missing readout?");
     140
     141    // XXX the sources have already been copied (merge into here?)
     142    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     143    psAssert (detections, "missing detections?");
     144
     145    psArray *sources = detections->allSources;
     146    psAssert (sources, "missing sources?");
     147
     148    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     149    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
     150    psAssert (maskVal, "missing mask value?");
     151
     152    for (int i = 0; i < sources->n; i++) {
     153      source = sources->data[i];
     154
     155      // sources have not yet been subtracted in this image (but this flag may be raised)
     156      source->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED;
     157
     158      float Xo = source->modelPSF->params->data.F32[PM_PAR_XPOS];
     159      float Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS];
     160      float radius = source->modelPSF->fitRadius;
     161
     162      // force a redefine to this image
     163      pmSourceFreePixels(source);
     164      pmSourceRedefinePixels (source, readout, Xo, Yo, radius);
     165    }
     166    return true;
     167}
     168
     169// for now, let's store the detections on the readout->analysis for each readout
     170bool psphotResetModels (pmConfig *config, const pmFPAview *view, const char *filerule)
     171{
     172    bool status = true;
     173
     174    // select the appropriate recipe information
     175    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     176    psAssert (recipe, "missing recipe?");
     177
     178    int num = psphotFileruleCount(config, filerule);
     179
     180    // loop over the available readouts
     181    for (int i = 0; i < num; i++) {
     182        if (!psphotResetModelsReadout (config, view, filerule, i, recipe)) {
     183            psError (PSPHOT_ERR_CONFIG, false, "failed to replace all sources for %s entry %d", filerule, i);
     184            return false;
     185        }
     186    }
     187    return true;
     188}
     189
     190bool psphotResetModelsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe) {
     191
     192    bool status;
     193    pmSource *source;
     194
     195    psTimerStart ("psphot.replace");
     196
     197    // find the currently selected readout
     198    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, index); // File of interest
     199    psAssert (file, "missing file?");
     200
     201    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     202    psAssert (readout, "missing readout?");
     203
     204    // XXX the sources have already been copied (merge into here?)
     205    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     206    psAssert (detections, "missing detections?");
     207
     208    psArray *sources = detections->allSources;
     209    psAssert (sources, "missing sources?");
     210
     211    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     212    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
     213    psAssert (maskVal, "missing mask value?");
     214
     215    // what fraction of the PSF is used? (radius in pixels : 2 -> 5x5 box)
     216    int psfSize = psMetadataLookupS32 (&status, recipe, "PCM_BOX_SIZE");
     217    assert (status);
     218
     219    pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
     220    psAssert (psf, "missing psf?");
     221
     222    for (int i = 0; i < sources->n; i++) {
     223      source = sources->data[i];
     224
     225      // *** we need to cache the 'best' model, and we have 3 cases:
     226      // 1) model is the psf model --> generate from the new psf
     227      // 2) model is an unconvolved extended model --> just cache the copy (not perfect)
     228      // 3) model is a convolved extended model --> re-generate
     229
     230      // use the 'best' model to cache the model (PSF or EXT : EXT may point at one of modelFits
     231      bool isPSF = false;
     232      pmModel *model = pmSourceGetModel(&isPSF, source);
     233      float radius = model->fitRadius; // save for future use below
     234
     235      // regenerate the PSF if the model is a PSF, or if we need the PSF for a PCM
     236      if (isPSF || model->isPCM) {
     237          // the guess central intensity comes from the peak:
     238          float Io = source->peak->flux;
     239          float Xo = source->modelPSF->params->data.F32[PM_PAR_XPOS];
     240          float Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS];
     241
     242          // generate a model for this object with Io = 1.0
     243          pmModel *modelPSF = pmModelFromPSFforXY(psf, Xo, Yo, Io);
     244          if (modelPSF == NULL) {
     245              psWarning ("Failed to determine PSF model for source at (%f,%f), skipping", Xo, Yo);
     246              continue;
     247          }
     248
     249          // set the source PSF model
     250          psFree (source->modelPSF);
     251          source->modelPSF = modelPSF;
     252          source->modelPSF->fitRadius = radius;
     253      }
     254
     255      if (model->isPCM) {
     256          psAssert(false, "this section is not complete");
     257
     258          pmSourceCachePSF (source, maskVal);
     259
     260          psKernel *psfKernel = pmPCMkernelFromPSF(source, psfSize);
     261          if (!psfKernel) {
     262              psWarning ("no psf kernel");
     263          }
     264
     265          // generate an image of the right size
     266          psImage *rawModelFlux = psImageCopy (NULL, source->pixels, PS_TYPE_F32);
     267          psImageInit (rawModelFlux, 0.0);
     268         
     269          // insert the model image normalized to 1.0
     270          pmModelAdd (rawModelFlux, NULL, model, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM, maskVal);
     271
     272          psImageConvolveFFT (source->modelFlux, rawModelFlux, NULL, 0, psfKernel);
     273         
     274          psFree (psfKernel);
     275          psFree (rawModelFlux);
     276      }
     277
     278      pmSourceCacheModel (source, maskVal);  // ALLOC x14 (!)
     279    }
     280
     281    psLogMsg ("psphot.replace", PS_LOG_INFO, "subtracted models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.replace"));
     282    return true;
     283}
     284
  • trunk/psphot/src/psphotSetThreads.c

    r29004 r30624  
    3535    psFree(task);
    3636
    37     task = psThreadTaskAlloc("PSPHOT_EXTENDED_FIT", 12);
     37    task = psThreadTaskAlloc("PSPHOT_EXTENDED_FIT", 13);
    3838    task->function = &psphotExtendedSourceFits_Threaded;
    3939    psThreadTaskAdd(task);
  • trunk/psphot/src/psphotSourceFits.c

    r29548 r30624  
    365365
    366366    // copy most data from the primary source (modelEXT, blends stay NULL)
    367     pmSource *newSrc = pmSourceCopyData (source);
     367    pmSource *newSrc = pmSourceCopy (source);
    368368    newSrc->modelPSF = psMemIncrRefCounter (DBL->data[1]);
    369369
     
    385385            psLogMsg ("psphot", 1, "PAR %d : %f +/- %f\n", i, source->modelPSF->params->data.F32[i], source->modelPSF->dparams->data.F32[i]);
    386386        }
    387         psphotVisualShowResidualImage (readout);
     387        psphotVisualShowResidualImage (readout, false);
    388388    }
    389389# endif
  • trunk/psphot/src/psphotSourceMatch.c

    r29936 r30624  
    187187        pmPhotObj *obj = objects->data[i];
    188188
     189        // we will find the input source with the max number of spans and reproduce that footprint
     190        int nSpansMax = 0;
     191        int iSpansMax = -1;
     192
    189193        // mark the images for which sources have been found
    190194        psVectorInit (found, 0);
     
    196200            psAssert (index < found->n, "invalid index");
    197201
     202            if (src->peak && src->peak->footprint && src->peak->footprint->nspans > nSpansMax) {
     203                nSpansMax = src->peak->footprint->nspans;
     204                iSpansMax = j;
     205            }
     206
    198207            found->data.U8[index] = 1;
     208        }
     209
     210        // we make a copy of the largest footprint; this will be used for all new sources associated with this object
     211        pmFootprint *footprint = NULL;
     212        if (iSpansMax != -1) { // copy the footprint info
     213            pmSource *src = obj->sources->data[iSpansMax];
     214            psAssert(src->peak, "source does not exist?");
     215            psAssert(src->peak->footprint, "footprint does not exist");
     216            psAssert(src->peak->footprint->nspans == nSpansMax, "wrong footprint?");
     217           
     218            // we only care about the spans, do not worry about the image of this footprint
     219            footprint = pmFootprintCopyData(src->peak->footprint, NULL);
    199220        }
    200221
     
    219240            peak->dy = NAN;
    220241           
    221             // XXX assign to a footprint?
    222 
     242            // assign to a footprint on this readout->image
     243            peak->footprint = pmFootprintCopyData(footprint, readout->image);
     244
     245            // the peak does not claim ownership of the footprint (it does not free it). save a copy of this
     246            // footprint on detections->footprints so we can free it later
     247            psArrayAdd(detections->footprints, 100, peak->footprint);
     248            psFree (peak->footprint);
     249           
    223250            // create a new source
    224251            pmSource *source = pmSourceAlloc();
     
    227254
    228255            // add the peak
    229             source->peak = psMemIncrRefCounter(peak);
     256            source->peak = peak;
    230257
    231258            // allocate space for moments
     
    239266            psArrayAdd (detections->newSources, 100, source);
    240267            psFree (source);
    241             psFree (peak);
    242         }
     268        }
     269        psFree (footprint);
    243270    }
    244271
  • trunk/psphot/src/psphotSourceSize.c

    r29936 r30624  
    499499
    500500        // clear the mask bit and set the circular mask pixels
    501         psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
    502         psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", options->markVal);
    503 
     501        // psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
     502        // psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", options->markVal);
    504503        pmSourceMagnitudes (source, psf, photMode, maskVal, markVal);
    505504
    506505        // clear the mask bit
    507         psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
     506        // psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
    508507
    509508        // re-subtract the object, leave local sky
  • trunk/psphot/src/psphotStackArguments.c

    r28013 r30624  
    4141    if ((N = psArgumentGet (argc, argv, "-break"))) {
    4242        if (argc <= N+1) {
    43           psErrorStackPrint(stderr, "Expected to see 1 more argument; saw %d", argc - 1);
     43          psErrorStackPrint(stderr, "Expected to see an argument for -break");
    4444          exit(PS_EXIT_CONFIG_ERROR);
    4545        }
  • trunk/psphot/src/psphotStackChisqImage.c

    r29936 r30624  
    66
    77// XXX supply filename or keep PSPHOT.INPUT fixed?
    8 bool psphotStackChisqImage (pmConfig *config, const pmFPAview *view, const char *ruleDet, const char *ruleCnv)
     8bool psphotStackChisqImage (pmConfig *config, const pmFPAview *view, const char *ruleDet, const char *ruleSrc)
    99{
    1010    psTimerStart ("psphot.chisq.image");
     
    2727
    2828    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "PSPHOT.CHISQ.NUM", PS_META_REPLACE, "", num);
     29
     30    // we need to increment the counter for ruleDet and ruleSrc:
    2931    num++;
    30     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "PSPHOT.INPUT.NUM", PS_META_REPLACE, "", num);
    3132
    3233    // save the resulting image in the 'detection' set
     
    3536        return false;
    3637    }
     38    psphotFileruleCountSet(config, ruleDet, num);
    3739
    38     // save the resulting image in the 'convolved' set
    39     if (!psMetadataAddPtr(config->files, PS_LIST_TAIL, ruleCnv, PS_DATA_UNKNOWN | PS_META_DUPLICATE_OK, "", chisqFile)) {
    40         psError(PM_ERR_CONFIG, false, "could not add chisqFPA to config files");
    41         return false;
     40    // also save the resulting image in the 'source' set (analysis set)
     41    if (strcmp(ruleDet, ruleSrc)) {
     42        if (!psMetadataAddPtr(config->files, PS_LIST_TAIL, ruleSrc, PS_DATA_UNKNOWN | PS_META_DUPLICATE_OK, "", chisqFile)) {
     43            psError(PM_ERR_CONFIG, false, "could not add chisqFPA to config files");
     44            return false;
     45        }
     46        psphotFileruleCountSet(config, ruleSrc, num);
    4247    }
    4348
     
    119124    psAssert (status, "programming error: must define PSPHOT.CHISQ.NUM");
    120125
    121     int inputNum = psphotFileruleCount(config, "PSPHOT.INPUT");
     126    int inputNum = psphotFileruleCount(config, filerule);
    122127
    123128    pmFPAfileRemoveSingle (config->files, filerule, chisqNum);
    124129
    125130    inputNum --;
    126     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "PSPHOT.INPUT.NUM", PS_META_REPLACE, "", inputNum);
     131    psphotFileruleCountSet(config, filerule, inputNum);
    127132
    128133    return true;
  • trunk/psphot/src/psphotStackImageLoop.c

    r29936 r30624  
    101101*/
    102102
    103 # define UPDATE_HEADER 0
     103# define UPDATE_HEADER 1
    104104
    105105bool GetAstrometryFPA (pmConfig *config, pmFPAview *view) {
     
    174174        pmChip *outChip = pmFPAviewThisChip(view, output->fpa); ///< Chip in the output
    175175
    176 # if (UPDATE_HEADER)
    177176        pmHDU *outHDU = pmFPAviewThisHDU (view, output->fpa);
    178177        if (!outHDU) {
    179             pmFPAAddSourceFromView(output->fpa, "name", view, output->format);
     178            pmFPAAddSourceFromView(output->fpa, view, output->format);
    180179            outHDU = pmFPAviewThisHDU (view, output->fpa);
    181180            psAssert (outHDU, "failed to make HDU");
    182181        }
    183 # endif
     182        if (!outHDU->header) {
     183          outHDU->header = psMetadataAlloc();
     184        }
    184185
    185186        if (bilevelAstrometry) {
     
    188189                continue;
    189190            }
    190 # if (UPDATE_HEADER)
    191191            if (!pmAstromWriteBilevelChip(outHDU->header, outChip, WCS_NONLIN_TOL)) {
    192192                psWarning("Unable to generate WCS header.");
    193193                continue;
    194194            }
    195 # endif
    196195        } else {
    197196            // we use a default FPA pixel scale of 1.0
     
    200199                continue;
    201200            }
    202 # if (UPDATE_HEADER)
    203             if (UPDATE_HEADER && !pmAstromWriteWCS(outHDU->header, output->fpa, outChip, WCS_NONLIN_TOL)) {
     201            if (!pmAstromWriteWCS(outHDU->header, output->fpa, outChip, WCS_NONLIN_TOL)) {
    204202                psWarning("Unable to generate WCS header.");
    205203                continue;
    206204            }
    207 # endif
    208205        }
    209206    }
     
    225222        psAssert (output, "missing file?");
    226223
    227 # if (UPDATE_HEADER)
    228224        pmHDU *PHU = pmFPAviewThisPHU(view, output->fpa);
    229225        if (!PHU) {
    230             pmFPAAddSourceFromView(output->fpa, "name", view, output->format);
     226            pmFPAAddSourceFromView(output->fpa, view, output->format);
    231227            PHU = pmFPAviewThisPHU (view, output->fpa);
    232228            psAssert (PHU, "failed to make PHU");
    233229        }
     230        if (!PHU->header) {
     231          PHU->header = psMetadataAlloc();
     232        }
    234233
    235234        if (!pmAstromWriteBilevelMosaic(PHU->header, output->fpa, WCS_NONLIN_TOL)) {
    236235            psWarning("Unable to generate WCS header.");
    237236        }
    238 # endif
    239237    }
    240238
  • trunk/psphot/src/psphotStackMatchPSFs.c

    r29936 r30624  
    6565bool psphotStackMatchPSFsReadout (pmConfig *config, const pmFPAview *view, psphotStackOptions *options, int index) {
    6666
     67    psImageMaskType maskValue;
     68    psImageMaskType markValue;
     69
     70    // get the PSPHOT.MASK value from the config
     71    if (!pmConfigMaskSetBits (&maskValue, &markValue, config)) {
     72        psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
     73        return false;
     74    }
     75
    6776    pmFPAfile *fileSrc = psphotStackGetConvolveSource(config, options, index);
    6877    if (!fileSrc) {
     
    8493
    8594    // set NAN pixels to 'SAT'
    86     // XXX replace this is pmReadoutMaskInvalid?
    87     psImageMaskType maskVal = pmConfigMaskGet("SAT", config);
    88     if (!pmReadoutMaskNonfinite(readoutSrc, maskVal)) {
     95    psImageMaskType maskSat = pmConfigMaskGet("SAT", config);
     96    if (!pmReadoutMaskInvalid(readoutSrc, maskValue, maskSat)) {
    8997        psError(psErrorCodeLast(), false, "Unable to mask non-finite pixels in readout.");
    9098        return false;
     
    95103        matchKernel(config, readoutOut, readoutSrc, options, index);
    96104        saveMatchData(readoutOut, options, index);
    97         // renormKernel(readoutCnv, options, index);
    98     } else {
    99         // only match the flux (NO! not for multi-filter, at least!)
    100         // XXX do not generate readoutCnv in this case?
    101         // float norm = powf(10.0, -0.4 * options->norm->data.F32[index]); // Normalisation
    102         // psBinaryOp(readoutRaw->image, readoutRaw->image, "*", psScalarAlloc(norm, PS_TYPE_F32));
    103         // psBinaryOp(readoutRaw->variance, readoutRaw->variance, "*", psScalarAlloc(PS_SQR(norm), PS_TYPE_F32));
    104105    }
    105 
    106106    rescaleData(readoutOut, config, options, index);
    107107
    108     // dumpImage(readoutOut, readoutSrc, index, "convolved");
     108    // save the output fwhm values in the readout->analysis.  we may have / will have multiple output PSF sizes,
     109    // so we save this in a vector.  if the vector is not yet defined, create it
     110    bool mdok = false;
     111    psVector *fwhmValues = psMetadataLookupVector(&mdok, readoutOut->analysis, "STACK.PSF.FWHM.VALUES");
     112    if (!fwhmValues) {
     113        fwhmValues = psVectorAllocEmpty(10, PS_TYPE_F32);
     114        psMetadataAddVector(readoutOut->analysis, PS_LIST_TAIL, "STACK.PSF.FWHM.VALUES", PS_META_REPLACE, "PSF sizes", fwhmValues);
     115        psFree(fwhmValues); // drops the extra copy
     116    }
     117    psVectorAppend(fwhmValues, options->targetSeeing);
    109118
    110119    return true;
    111120}
    112 
    113 
    114 # if (0)
    115 // Read previously produced kernel
    116 if (psMetadataLookupBool(NULL, config->arguments, "PPSTACK.DEBUG.STACK")) {
    117     loadKernel(config, readoutCnv, options, index);
    118 } else {
    119     matchKernel(config, readoutCnv, readoutRaw, options, index);
    120 }
    121 # endif
  • trunk/psphot/src/psphotStackMatchPSFsUtils.c

    r29548 r30624  
    365365        pmSubtractionSetFWHMs(options->inputSeeing->data.F32[index], options->targetSeeing);
    366366
    367         if (scale && !pmSubtractionParamsScale(&size, &footprint, widthsCopy, scaleRef, scaleMin, scaleMax)) {
    368             psError(psErrorCodeLast(), false, "Unable to scale kernel parameters");
    369             goto escape;
    370         }
     367        pmSubtractionParamScaleOptions(scale, scaleRef, scaleMin, scaleMax);
     368
     369        // if (scale && !pmSubtractionParamsScale(&size, &footprint, widthsCopy, scaleRef, scaleMin, scaleMax)) {
     370        //     psError(psErrorCodeLast(), false, "Unable to scale kernel parameters");
     371        //     goto escape;
     372        // }
    371373
    372374        if (!pmSubtractionMatch(NULL, readoutOut, fake, readoutSrc, footprint, stride, regionSize, spacing, threshold, stampSources, stampsName, type, size, order, widthsCopy, orders, inner, ringsOrder, binning, penalty, optimum, optWidths, optOrder, optThresh, iter, rej, normFrac, sysError, skyErr, kernelError, covarFrac, maskVal, maskBad, maskPoor, poorFrac, badFrac, PM_SUBTRACTION_MODE_2)) {
     
    383385        goto escape;
    384386    }
     387
     388    // save the PSF on the new readout->analysis:
     389    // if (!psMetadataAddPtr (readoutOut->analysis, PS_LIST_TAIL, "PSPHOT.PSF", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot psf model", options->psf)) {
     390    //     psError (PSPHOT_ERR_UNKNOWN, false, "problem saving sources on readout");
     391    //     return false;
     392    // }
    385393
    386394    // dumpImage(readoutOut, readoutSrc, index, "conv");
  • trunk/psphot/src/psphotStackPSF.c

    r28013 r30624  
    1212    bool autoPSF = psMetadataLookupBool (&mdok, psphotRecipe, "PSPHOT.STACK.TARGET.PSF.AUTO");
    1313
     14    // Get the recipe values
     15    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "PPSTACK"); // ppStack recipe
     16    psAssert(recipe, "We've thrown an error on this before.");
     17       
     18    char *psfModel = psMetadataLookupStr(NULL, recipe, "PSF.MODEL"); // Model for PSF
     19
    1420    if (autoPSF) {
    15         // Get the recipe values
    16         psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "PPSTACK"); // ppStack recipe
    17         psAssert(recipe, "We've thrown an error on this before.");
    18 
    1921        int psfInstances = psMetadataLookupS32(NULL, recipe, "PSF.INSTANCES"); // Number of instances for PSF
    2022        float psfRadius = psMetadataLookupF32(NULL, recipe, "PSF.RADIUS"); // Radius for PSF
    21         const char *psfModel = psMetadataLookupStr(NULL, recipe, "PSF.MODEL"); // Model for PSF
    2223        int psfOrder = psMetadataLookupS32(NULL, recipe, "PSF.ORDER"); // Spatial order for PSF
    2324
     
    4950
    5051        float targetFWHM = psMetadataLookupF32 (&mdok, psphotRecipe, "PSPHOT.STACK.TARGET.PSF.FWHM");
    51         psAssert (isfinite(targetFWHM), "missing psphot recipe value PSPHOT.STACK.TARGET.PSF.FWHM");
     52        if (!mdok) {
     53            psVector *fwhmValues = psMetadataLookupVector(&mdok, psphotRecipe, "PSPHOT.STACK.TARGET.PSF.FWHM"); // Magnitude offsets
     54            psAssert (mdok, "missing psphot recipe value PSPHOT.STACK.TARGET.PSF.FWHM");
     55            targetFWHM = fwhmValues->data.F32[0];
     56        }
    5257
    5358        float Sxx = sqrt(2.0)*targetFWHM / 2.35;
    5459
    5560        // XXX probably should make the model type (and par 7) optional from recipe
    56         psf = pmPSFBuildSimple("PS_MODEL_PS1_V1", Sxx, Sxx, 0.0, 1.0);
     61        psf = pmPSFBuildSimple(psfModel, Sxx, Sxx, 0.0, 1.0);
    5762        if (!psf) {
    5863            psError(PSPHOT_ERR_PSF, false, "Unable to build dummy PSF.");
  • trunk/psphot/src/psphotStackParseCamera.c

    r29548 r30624  
    1515    }
    1616
     17    int nRaw = 0;
     18    int nCnv = 0;
    1719    int nInputs = inputs->list->n;
    1820    for (int i = 0; i < nInputs; i++) {
     
    5759                }
    5860            }
     61            nRaw ++;
    5962        }
    6063
     
    8891                }
    8992            }
     93            nCnv ++;
    9094        }
    9195
     
    9599        }
    96100
     101        // XXX what if they do not match in length
     102        if (nCnv && nRaw) {
     103            if (nCnv != nRaw) {
     104                psError (PSPHOT_ERR_CONFIG, true, "if both RAW and CNV images are supplied, the number must match");
     105                return false;
     106            }
     107        }
     108
    97109        psString sources = psMetadataLookupStr(&status, input, "SOURCES"); // Name of mask
    98         // pmFPAfile *srcInputFile = rawInputFile ? rawInputFile : cnvInputFile;
    99110        if (sources && strlen(sources) > 0) {
    100111            if (!defineFile(config, NULL, "PSPHOT.STACK.SOURCES", sources, PM_FPA_FILE_CMF)) {
     
    107118        // XXX output of these files should be optional
    108119        {
     120            // pmFPAfile *srcInputFile = rawInputFile ? rawInputFile : cnvInputFile;
    109121            pmFPAfile *outputImage = pmFPAfileDefineOutput(config, NULL, "PSPHOT.STACK.OUTPUT.IMAGE");
    110122            if (!outputImage) {
     
    150162    }
    151163    psMetadataRemoveKey(config->arguments, "FILENAMES");
     164    psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.STACK.INPUT.RAW.NUM", PS_META_REPLACE, "number of inputs", nRaw);
     165    psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.STACK.INPUT.CNV.NUM", PS_META_REPLACE, "number of inputs", nCnv);
     166    psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.STACK.OUTPUT.IMAGE.NUM", PS_META_REPLACE, "number of inputs", nInputs);
    152167    psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.INPUT.NUM", PS_META_REPLACE, "number of inputs", nInputs);
    153168
  • trunk/psphot/src/psphotStackReadout.c

    r29936 r30624  
    11# include "psphotInternal.h"
    22
     3// we have 3 possible real filesets:
    34# define STACK_RAW "PSPHOT.STACK.INPUT.RAW"
    4 # define STACK_OUT "PSPHOT.STACK.OUTPUT.IMAGE"
     5# define STACK_CNV "PSPHOT.STACK.INPUT.CNV"
     6# define STACK_OUT "PSPHOT.STACK.OUTPUT.IMAGE"  /* the psf-matched image */
     7
     8// we have 3 files on which we operate:
     9// DET (detection image)       : nominally RAW (optionally CNV?)
     10// SRC (source analysis image) : nominally CNV (optionally RAW)
     11// OUT (psf-matched images)    : always OUT
     12
     13bool psphotStackVisualFilerule(pmConfig *config, const pmFPAview *view, const char *filerule) {
     14
     15    bool status = false;
     16
     17    int num = psphotFileruleCount(config, filerule);
     18
     19    // select the appropriate recipe information
     20    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     21
     22    // loop over the available readouts
     23    for (int i = 0; i < num; i++) {
     24
     25        // find the currently selected readout
     26        pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, i); // File of interest
     27        psAssert (file, "missing file?");
     28
     29        pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     30        psAssert (readout, "missing readout?");
     31
     32        pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     33        psAssert (detections, "missing detections?");
     34
     35        psArray *sources = detections->allSources;
     36        psAssert (sources, "missing sources?");
     37
     38        psphotVisualShowResidualImage (readout, true);
     39        psphotVisualShowObjectRegions (readout, recipe, sources);
     40    }
     41    return true;
     42}
    543
    644bool psphotStackReadout (pmConfig *config, const pmFPAview *view) {
     
    2058    PS_ASSERT_PTR_NON_NULL (breakPt, false);
    2159
     60    // XXX or do I set OUT to be a pmFPAfile pointing at the input of interest?
     61    bool useRaw = psMetadataLookupBool (NULL, recipe, "PSPHOT.STACK.USE.RAW");
     62    char *STACK_SRC = useRaw ? STACK_RAW : STACK_CNV;
     63    char *STACK_DET = STACK_RAW; // XXX optionally allow this to be CNV?
     64
    2265    // we have 3 relevant files: RAW, CNV, OUT
    2366
    2467    // set the photcode for each image
    25     if (!psphotAddPhotcode (config, view, STACK_OUT)) {
     68    if (!psphotAddPhotcode (config, view, STACK_SRC)) {
    2669        psError (PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
    2770        return false;
     
    3073    // Generate the mask and weight images
    3174    // XXX this should be done before we perform the convolutions
    32     if (!psphotSetMaskAndVariance (config, view, STACK_RAW)) {
    33         return psphotReadoutCleanup (config, view, STACK_OUT);
     75    if (!psphotSetMaskAndVariance (config, view, STACK_DET)) {
     76        return psphotReadoutCleanup (config, view, STACK_SRC);
    3477    }
    3578    if (!strcasecmp (breakPt, "NOTHING")) {
    36         return psphotReadoutCleanup (config, view, STACK_OUT);
     79        return psphotReadoutCleanup (config, view, STACK_SRC);
    3780    }
    3881
     
    4083    // XXX I think this is not defined correctly for an array of images.
    4184    // XXX probably need to subtract the model (same model?) for both RAW and OUT
    42     if (!psphotModelBackground (config, view, STACK_RAW)) {
    43         return psphotReadoutCleanup (config, view, STACK_OUT);
    44     }
    45     if (!psphotSubtractBackground (config, view, STACK_RAW)) {
    46         return psphotReadoutCleanup (config, view, STACK_OUT);
     85    if (!psphotModelBackground (config, view, STACK_DET)) {
     86        return psphotReadoutCleanup (config, view, STACK_SRC);
     87    }
     88    if (!psphotSubtractBackground (config, view, STACK_DET)) {
     89        return psphotReadoutCleanup (config, view, STACK_SRC);
    4790    }
    4891    if (!strcasecmp (breakPt, "BACKMDL")) {
    49         return psphotReadoutCleanup (config, view, STACK_OUT);
    50     }
    51 
    52     // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are determined and saved on
    53     // readout->analysis XXX this function currently only works with a single PSPHOT.INPUT
    54     if (!psphotLoadPSF (config, view, STACK_RAW)) {
    55         psError (PSPHOT_ERR_UNKNOWN, false, "error loading psf model");
    56         return psphotReadoutCleanup (config, view, STACK_OUT);
    57     }
    58 
    59     if (!psphotStackChisqImage(config, view, STACK_RAW, STACK_OUT)) {
     92        return psphotReadoutCleanup (config, view, STACK_SRC);
     93    }
     94
     95    if (!psphotStackChisqImage(config, view, STACK_DET, STACK_SRC)) {
    6096        psError (PSPHOT_ERR_UNKNOWN, false, "failure to generate chisq image");
    61         return psphotReadoutCleanup (config, view, STACK_OUT);
     97        return psphotReadoutCleanup (config, view, STACK_SRC);
    6298    }
    6399    if (!strcasecmp (breakPt, "CHISQ")) {
    64         return psphotReadoutCleanup (config, view, STACK_OUT);
     100        return psphotReadoutCleanup (config, view, STACK_SRC);
    65101    }
    66102
    67103    // find the detections (by peak and/or footprint) in the image.
    68104    // This finds the detections on Chisq image as well as the individuals
    69     if (!psphotFindDetections (config, view, STACK_RAW, true)) { // pass 1
     105    if (!psphotFindDetections (config, view, STACK_DET, true)) { // pass 1
    70106        // this only happens if we had an error in psphotFindDetections
    71107        psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
    72         return psphotReadoutCleanup (config, view, STACK_OUT);
    73     }
    74 
    75     // copy the detections from RAW to OUT
    76     if (!psphotCopySources (config, view, STACK_OUT, STACK_RAW)) {
    77         psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
    78         return psphotReadoutCleanup (config, view, STACK_OUT);
     108        return psphotReadoutCleanup (config, view, STACK_SRC);
     109    }
     110
     111    // copy the detections from DET to SRC
     112    if (strcmp(STACK_SRC, STACK_DET)) {
     113        if (!psphotCopySources (config, view, STACK_SRC, STACK_DET)) {
     114            psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
     115            return psphotReadoutCleanup (config, view, STACK_SRC);
     116        }
    79117    }
    80118
    81119    // construct sources and measure basic stats (saved on detections->newSources)
    82     // only run this on detections from the input images, not chisq image
    83     if (!psphotSourceStats (config, view, STACK_OUT, true)) { // pass 1
     120    if (!psphotSourceStats (config, view, STACK_SRC, true)) { // pass 1
    84121        psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
    85         return psphotReadoutCleanup (config, view, STACK_OUT);
     122        return psphotReadoutCleanup (config, view, STACK_SRC);
     123    }
     124
     125    if (!strcasecmp (breakPt, "TEST1")) {
     126        return psphotReadoutCleanup (config, view, STACK_SRC);
    86127    }
    87128
    88129    // generate the objects (object unify the sources from the different images)
    89     psArray *objects = psphotMatchSources (config, view, STACK_OUT);
     130    // XXX this could just match the detections for the chisq image, and not bother measuring the
     131    // source stats in that case...
     132    psArray *objects = psphotMatchSources (config, view, STACK_SRC);
     133
     134    if (!strcasecmp (breakPt, "TEST2")) {
     135        psFree(objects);
     136        return psphotReadoutCleanup (config, view, STACK_SRC);
     137    }
    90138
    91139    // construct sources for the newly-generated sources (from other images)
    92     if (!psphotSourceStats (config, view, STACK_OUT, false)) { // pass 1
     140    if (!psphotSourceStats (config, view, STACK_SRC, false)) { // pass 1
     141        psFree(objects);
    93142        psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
    94         return psphotReadoutCleanup (config, view, STACK_OUT);
     143        return psphotReadoutCleanup (config, view, STACK_SRC);
    95144    }
    96145
     
    98147    // if (!psphotDeblendSatstars (config, view)) {
    99148    //     psError (PSPHOT_ERR_UNKNOWN, false, "failed on satstar deblend analysis");
    100     //     return psphotReadoutCleanup (config, view, STACK_OUT);
     149    //     return psphotReadoutCleanup (config, view, STACK_SRC);
    101150    // }
    102151
     
    104153    // if (!psphotBasicDeblend (config, view)) {
    105154    //     psError (PSPHOT_ERR_UNKNOWN, false, "failed on deblend analysis");
    106     //     return psphotReadoutCleanup (config, view, STACK_OUT);
     155    //     return psphotReadoutCleanup (config, view, STACK_SRC);
    107156    // }
    108157
    109158    // classify sources based on moments, brightness
    110159    // only run this on detections from the input images, not chisq image
    111     if (!psphotRoughClass (config, view, STACK_OUT)) {
     160    if (!psphotRoughClass (config, view, STACK_SRC)) {
     161        psFree(objects);
    112162        psError (PSPHOT_ERR_UNKNOWN, false, "failed to determine rough classifications");
    113         return psphotReadoutCleanup (config, view, STACK_OUT);
     163        return psphotReadoutCleanup (config, view, STACK_SRC);
    114164    }
    115165    // if we were not supplied a PSF model, determine the IQ stats here (detections->newSources)
    116166    // only run this on detections from the input images, not chisq image
    117     if (!psphotImageQuality (config, view, STACK_OUT)) { // pass 1
     167    if (!psphotImageQuality (config, view, STACK_SRC)) { // pass 1
     168        psFree(objects);
    118169        psError (PSPHOT_ERR_UNKNOWN, false, "failed to measure image quality");
    119         return psphotReadoutCleanup (config, view, STACK_OUT);
     170        return psphotReadoutCleanup (config, view, STACK_SRC);
    120171    }
    121172    if (!strcasecmp (breakPt, "MOMENTS")) {
    122         return psphotReadoutCleanup (config, view, STACK_OUT);
     173        psFree(objects);
     174        return psphotReadoutCleanup (config, view, STACK_SRC);
    123175    }
    124176
    125177    // use bright stellar objects to measure PSF if we were supplied a PSF for any input file,
    126178    // this step is skipped
    127     if (!psphotChoosePSF (config, view, STACK_OUT)) { // pass 1
     179    if (!psphotChoosePSF (config, view, STACK_SRC, true)) { // pass 1
     180        psFree(objects);
    128181        psLogMsg ("psphot", 3, "failure to construct a psf model");
    129         return psphotReadoutCleanup (config, view, STACK_OUT);
     182        return psphotReadoutCleanup (config, view, STACK_SRC);
    130183    }
    131184    if (!strcasecmp (breakPt, "PSFMODEL")) {
    132         return psphotReadoutCleanup (config, view, STACK_OUT);
     185        psFree(objects);
     186        return psphotReadoutCleanup (config, view, STACK_SRC);
    133187    }
    134188
    135189    // construct an initial model for each object, set the radius to fitRadius, set circular fit mask
    136     psphotGuessModels (config, view, STACK_OUT);
     190    psphotGuessModels (config, view, STACK_SRC);
    137191
    138192    // merge the newly selected sources into the existing list
    139193    // NOTE: merge OLD and NEW
    140     psphotMergeSources (config, view, STACK_OUT);
     194    psphotMergeSources (config, view, STACK_SRC);
    141195
    142196    // linear PSF fit to source peaks, subtract the models from the image (in PSF mask)
    143197    psphotFitSourcesLinearStack (config, objects, FALSE);
     198    psphotStackVisualFilerule(config, view, STACK_SRC);
    144199
    145200    // identify CRs and extended sources
    146     psphotSourceSize (config, view, STACK_OUT, TRUE);
     201    psphotSourceSize (config, view, STACK_SRC, TRUE);
     202
     203    // XXX do we want to do a preliminary (unconvolved) model fit here, and then
     204    // do a second detection pass? (like standard psphot)
    147205
    148206    // measure aperture photometry corrections
    149     if (!psphotApResid (config, view, STACK_OUT)) {
     207    if (!psphotApResid (config, view, STACK_SRC)) {
    150208        psFree (objects);
    151209        psLogMsg ("psphot", 3, "failed on psphotApResid");
    152         return psphotReadoutCleanup (config, view, STACK_OUT);
     210        return psphotReadoutCleanup (config, view, STACK_SRC);
    153211    }
    154212
    155213    psphotStackObjectsUnifyPosition (objects);
    156214
    157     // measure circular, radial apertures (objects sorted by S/N)
    158     psphotRadialAperturesByObject (config, objects, view, STACK_OUT);
    159 
    160215    // measure elliptical apertures, petrosians (objects sorted by S/N)
    161     psphotExtendedSourceAnalysisByObject (config, objects, view, STACK_OUT); // pass 1 (detections->allSources)
     216    psphotExtendedSourceAnalysisByObject (config, objects, view, STACK_SRC); // pass 1 (detections->allSources)
    162217
    163218    // measure non-linear extended source models (exponential, deVaucouleur, Sersic) (sources sorted by S/N)
    164     psphotExtendedSourceFits (config, view, STACK_OUT); // pass 1 (detections->allSources)
     219    psphotExtendedSourceFits (config, view, STACK_SRC); // pass 1 (detections->allSources)
    165220
    166221    // calculate source magnitudes
    167     psphotMagnitudes(config, view, STACK_OUT);
     222    psphotMagnitudes(config, view, STACK_SRC);
     223
     224    // create source children for the OUT filerule (for radial aperture photometry)
     225    psArray *objectsRadial = psphotSourceChildrenByObject (config, view, STACK_OUT, objects);
     226    if (!objectsRadial) {
     227        psFree(objects);
     228        psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
     229        return psphotReadoutCleanup (config, view, STACK_SRC);
     230    }
     231
     232    bool smoothAgain = true;
     233    for (int nMatchedPSF = 0; smoothAgain; nMatchedPSF++) {
     234
     235        // re-measure the PSF for the smoothed image (using entries in 'allSources')
     236        psphotChoosePSF (config, view, STACK_OUT, false);
     237
     238        // this is necessary to update the models based on the new PSF
     239        psphotResetModels (config, view, STACK_OUT);
     240
     241        // this is necessary to get the right normalization for the new models
     242        psphotFitSourcesLinear (config, view, STACK_OUT, false);
     243
     244        // measure circular, radial apertures (objects sorted by S/N)
     245        psphotRadialAperturesByObject (config, objectsRadial, view, STACK_OUT, nMatchedPSF);
     246
     247        // replace the flux in the image so it is returned to its original state
     248        psphotReplaceAllSources (config, view, STACK_OUT);
     249
     250        // smooth to the next FWHM, or set 'smoothAgain' to false if no more
     251        psphotStackMatchPSFsNext(&smoothAgain, config, view, STACK_OUT, nMatchedPSF);
     252    }
    168253
    169254    if (0 && !psphotEfficiency(config, view, STACK_OUT)) {
     
    176261
    177262    // replace background in residual image
    178     psphotSkyReplace (config, view, STACK_RAW);
     263    psphotSkyReplace (config, view, STACK_DET);
    179264
    180265    // drop the references to the image pixels held by each source
    181     psphotSourceFreePixels (config, view, STACK_OUT);
    182 
    183     // remove chisq image from config->file:PSPHOT.INPUT (why?)
    184     psphotStackRemoveChisqFromInputs(config, STACK_RAW);
     266    // psphotSourceFreePixels (config, view, STACK_OUT);
     267    psphotSourceFreePixels (config, view, STACK_SRC);
     268
     269    // remove chisq image from config->file:PSPHOT.INPUT
     270    psphotStackRemoveChisqFromInputs(config, STACK_DET);
     271    if (strcmp(STACK_SRC, STACK_DET)) {
     272        psphotStackRemoveChisqFromInputs(config, STACK_SRC);
     273    }
    185274
    186275    psFree (objects);
     276    psFree (objectsRadial);
    187277
    188278    // create the exported-metadata and free local data
    189     return psphotReadoutCleanup (config, view, STACK_OUT);
     279    return psphotReadoutCleanup (config, view, STACK_SRC);
    190280}
    191281
     282/* here is the process:
     283
     284 * we have three(*) images:
     285 * RAW : unconvolved image stack
     286 * CNV : input convolved image
     287
     288 * OUT : psf-matched output image (there may be more than one of
     289 * these.  we will generate the first matched image by selecting the
     290 * target PSF and doing a full psf-maching process (as used by ppStack
     291 * and ppSub).  But, additional target output files should use a
     292 * simple gaussian convolution kernel determind from therms of the
     293 * current and the target).
     294
     295 * the output should be / could be one of the matched images, but not
     296 * all.  should we ensure the first gets written out, and ot save the
     297 * others (or only optionally).
     298
     299 * by default, we probably only sve the cmf ffile outputs.
     300
     301 * load the RAW image (unconvolved stacks)
     302 * add photcode to the output headers / readout->analysis
     303 * generate mask and variance image (this is probably never needed in
     304   practice: we always load an input mask & var.
     305 * generate & subtract a model background for ?? (RAW? CNV? OUT? all?)
     306 * load a PSF (probably not yet working)
     307
     308 * generate the CHISQ image from the RAW input images (why save on OUT?)
     309
     310 * find detections on RAW
     311
     312 * copy detections to OUT
     313
     314 * generate source stats (moments) for OUT
     315
     316 * match sources across inputs (on OUT?)
     317
     318 * generate source stats for the new constructions
     319
     320 * rough class (star, galaxy, cosmic, etc)
     321
     322 * Image quality
     323
     324 * generate PSF
     325
     326 * guess models
     327
     328 * merge sources (new -> old)
     329
     330 * linear fit to the psf
     331
     332 * find ApResid
     333
     334 * assign common positions
     335
     336 * radial apertures (** this should be on the PSF-matched images
     337
     338 * extended analysis (elliptical profile & petrosian)
     339
     340 * extended fits (sersic, etc)
     341
     342 * psphot magnitudes
     343
     344
     345 ******
     346
     347 the above is all wrong:  first, we should be doing the full
     348 morphology analysis (ExtendedAnalysis & ExtendedFits) on the CNV or
     349 RAW image (as desired optionally), etc.
     350
     351 In the discussion below, 'BST' (best) means optionally RAW or CNV
     352
     353 * detection : RAW & CHISQ (of RAW)
     354 * moments : used by psf analysis & classification (BST)
     355 * rough class : uses moments, not pixels
     356 * image quality : uses moments as well
     357 * generate PSF : (BST)
     358 * guess models (BST)
     359 * linear fit (BST)
     360 * find ApResid (BST) -- uses sources not pixels
     361 * extended analysis (BST)
     362 * extended fits (BST)
     363 * detection efficiency (BST)
     364 
     365 * somehow need to copy the sources so they point at the pixels on the
     366 * OUT image
     367
     368 * foreach target PSF
     369   * radial aperture
     370   * convolve to next target PSF
     371
     372   * somehow need to organize the output file to have the values from
     373   * the different PSFs in separate tables (with header info to
     374   * specify the size of that PSF)
     375
     376   */
  • trunk/psphot/src/psphotVisual.c

    r29548 r30624  
    9393    strcpy (coords.ctype, "RA---TAN");
    9494
    95     psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    96     psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
    97     if (!psImageBackground(stats, NULL, inImage, NULL, 0, rng)) {
    98         fprintf (stderr, "failed to get background values\n");
    99         return false;
    100     }
    101 
    10295    image.Nx = inImage->numCols;
    10396    image.Ny = inImage->numRows;
     
    125118    free (image.data2d);
    126119
     120    return true;
     121}
     122
     123bool psphotVisualShowObjectRegions (pmReadout *readout, psMetadata *recipe, psArray *sources) {
     124
     125    KiiImage image;
     126    KapaImageData data;
     127    Coords coords;
     128
     129    bool status = false;
     130
     131    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     132    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
     133    assert (maskVal);
     134
     135    psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); // Mask value for bad pixels
     136    assert (maskVal);
     137
     138    maskVal |= markVal;
     139
     140    if (!pmVisualTestLevel("psphot.image.objects", 2)) return true;
     141
     142    int kapa = psphotKapaChannel (1);
     143    if (kapa == -1) return false;
     144
     145    strcpy (coords.ctype, "RA---TAN");
     146
     147    psImage *inImage = readout->image;
     148    psImage *inMask = readout->mask;
     149    image.Nx = inImage->numCols;
     150    image.Ny = inImage->numRows;
     151   
     152    psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
     153    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
     154    if (!psImageBackground(stats, NULL, inImage, inMask, 0xffff, rng)) {
     155        fprintf (stderr, "failed to get background values\n");
     156        return false;
     157    }
     158
     159    ALLOCATE (image.data2d, float *, image.Ny);
     160    for (int iy = 0; iy < image.Ny; iy++) {
     161        ALLOCATE (image.data2d[iy], float, image.Nx);
     162        for (int ix = 0; ix < image.Nx; ix++) {
     163            image.data2d[iy][ix] = 0;
     164        }
     165    }
     166
     167    // loop over sources and set unmasked pixels to 0
     168    for (int i = 0; i < sources->n; i++) {
     169
     170        pmSource *source = sources->data[i];
     171        if (source == NULL) continue;
     172
     173        psImage *mask = source->maskObj;
     174        if (mask == NULL) continue;
     175
     176        for (int iy = 0; iy < mask->numRows; iy++) {
     177            int jy = iy + mask->row0;
     178            if (jy < 0) continue;
     179            if (jy >= inImage->numRows) continue;
     180            for (int ix = 0; ix < mask->numCols; ix++) {
     181                int jx = ix + mask->col0;
     182                if (jx < 0) continue;
     183                if (jx >= inImage->numCols) continue;
     184
     185                if (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal) continue;
     186                image.data2d[jy][jx] = 1;
     187            }
     188        }
     189    }
     190
     191    for (int iy = 0; iy < image.Ny; iy++) {
     192        for (int ix = 0; ix < image.Nx; ix++) {
     193            image.data2d[iy][ix] = (image.data2d[iy][ix] == 0.0) ? NAN : inImage->data.F32[iy][ix];
     194        }
     195    }
     196
     197    strcpy (data.name, "maskObj");
     198    strcpy (data.file, "maskObj");
     199    // data.zero = 0.0;
     200    // data.range = 1.0;
     201    data.zero = stats->robustMedian - stats->robustStdev;
     202    data.range = 5*stats->robustStdev;
     203    data.logflux = 0;
     204
     205    KiiSetChannel (kapa, 2);
     206    KiiNewPicture2D (kapa, &image, &data, &coords);
     207
     208    for (int iy = 0; iy < image.Ny; iy++) {
     209        free (image.data2d[iy]);
     210    }
     211    free (image.data2d);
     212
    127213    psFree (stats);
    128214    psFree (rng);
    129 
     215   
     216    pmVisualAskUser(NULL);
    130217    return true;
    131218}
     
    24012488}
    24022489
    2403 bool psphotVisualShowResidualImage (pmReadout *readout) {
     2490// option to redo variance since in some cases we may have displayed a different image in the meanwhile
     2491bool psphotVisualShowResidualImage (pmReadout *readout, bool reshow) {
    24042492
    24052493    if (!pmVisualTestLevel("psphot.image.resid", 2)) return true;
     
    24082496    if (myKapa == -1) return false;
    24092497
    2410     psphotVisualScaleImage (myKapa, readout->image, readout->mask, "resid", 1);
     2498    if (reshow) {
     2499        psphotVisualShowMask (myKapa, readout->mask, "mask", 2);
     2500        psphotVisualScaleImage (myKapa, readout->variance, readout->mask, "variance", 1);
     2501    }
     2502    psphotVisualScaleImage (myKapa, readout->image, readout->mask, "resid", 0);
    24112503
    24122504    pmVisualAskUser(NULL);
Note: See TracChangeset for help on using the changeset viewer.