IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Aug 26, 2010, 9:18:39 AM (16 years ago)
Author:
Serge CHASTEL
Message:

Merging trunk in branch

Location:
branches/sc_branches/trunkTest
Files:
32 edited
3 copied

Legend:

Unmodified
Added
Removed
  • branches/sc_branches/trunkTest

  • branches/sc_branches/trunkTest/psphot

    • Property svn:mergeinfo deleted
  • branches/sc_branches/trunkTest/psphot/src/Makefile.am

    r28013 r29060  
    163163        psphotOutput.c                 \
    164164        psphotFakeSources.c            \
    165         psphotModelWithPSF.c           \
    166165        psphotExtendedSourceAnalysis.c \
    167166        psphotExtendedSourceAnalysisByObject.c \
    168167        psphotExtendedSourceFits.c     \
    169168        psphotKernelFromPSF.c          \
    170         psphotPSFConvModel.c           \
    171169        psphotFitSet.c                 \
    172170        psphotSourceFreePixels.c       \
  • branches/sc_branches/trunkTest/psphot/src/psphot.h

    r28013 r29060  
    1212
    1313#define PSPHOT_RECIPE_PSF_FAKE_ALLOW "PSF.FAKE.ALLOW" // Name for recipe component permitting fake PSFs
    14 
    15 // pmPCMData : PSF Convolved Model data storage structure
    16 typedef struct {
    17     psImage *model;
    18     psArray *dmodels;
    19     psImage *modelConv;
    20     psArray *dmodelsConv;
    21 } pmPCMData;
    2214
    2315// top-level psphot functions
     
    114106bool            psphotExtendedSourceFits (pmConfig *config, const pmFPAview *view, const char *filerule);
    115107bool            psphotExtendedSourceFitsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     108bool            psphotExtendedSourceFits_Threaded (psThreadJob *job);
    116109
    117110bool            psphotApResid (pmConfig *config, const pmFPAview *view, const char *filerule);
     
    188181
    189182// functions to set the correct source pixels
    190 bool            psphotInitRadiusPSF(const psMetadata *recipe, const psMetadata *analysis, const pmModelType type);
     183bool            psphotInitRadiusPSF (psMetadata *recipe, pmReadout *readout);
     184bool            psphotInitRadiusEXT (psMetadata *recipe, pmReadout *readout);
    191185
    192186bool            psphotCheckRadiusPSF (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal);
    193187bool            psphotCheckRadiusPSFBlend (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal, float dR);
    194 bool            psphotInitRadiusEXT (psMetadata *recipe, pmModelType type);
    195 bool            psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal);
    196 float           psphotSetRadiusEXT (pmReadout *readout, pmSource *source, psImageMaskType markVal);
     188bool            psphotSetRadiusFootprint (float *radius, pmReadout *readout, pmSource *source, psImageMaskType markVal, float factor);
     189bool            psphotSetRadiusModel (pmModel *model, pmReadout *readout, pmSource *source, psImageMaskType markVal, bool deep);
    197190
    198191bool            psphotDumpMoments (psMetadata *recipe, psArray *sources);
     
    210203//  functions to support the source fitting process
    211204bool            psphotInitLimitsPSF (psMetadata *recipe, pmReadout *readout);
    212 bool            psphotInitLimitsEXT (psMetadata *recipe);
    213 bool            psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal);
    214 bool            psphotFitBlob (pmReadout *readout, pmSource *source, psArray *sources, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal);
    215 bool            psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal);
    216 pmModel        *psphotFitEXT (pmReadout *readout, pmSource *source, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal);
    217 psArray        *psphotFitDBL (pmReadout *readout, pmSource *source, psImageMaskType maskVal, psImageMaskType markVal);
     205bool            psphotInitLimitsEXT (psMetadata *recipe, pmReadout *readout);
     206bool            psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal);
     207bool            psphotFitBlob (pmReadout *readout, pmSource *source, psArray *sources, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal);
     208bool            psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal);
     209pmModel        *psphotFitEXT (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal);
     210psArray        *psphotFitDBL (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal);
    218211
    219212// functions to support simultaneous multi-source fitting
     
    252245bool            psphotVisualShowBackground (pmConfig *config, const pmFPAview *view, pmReadout *readout);
    253246bool            psphotVisualShowSignificance (psImage *image, float min, float max);
     247bool            psphotVisualShowLogSignificance (psImage *image, float min, float max);
    254248bool            psphotVisualShowPeaks (pmDetections *detections);
    255249bool            psphotVisualShowFootprints (pmDetections *detections);
     
    292286bool psphotRadialBins (psMetadata *recipe, pmSource *source, float radiusMax, float skynoise);
    293287
    294 // structures & functions to support psf-convolved model fitting
    295 
    296 // psf-convolved model fitting
    297 bool psphotModelWithPSF_LMM (
    298     psMinimization *min,
    299     psImage *covar,
    300     psVector *params,
    301     psMinConstraint *constraint,
    302     pmSource *source,
    303     const psKernel *psf,
    304     psMinimizeLMChi2Func func);
    305 
    306 psF32 psphotModelWithPSF_SetABX(
    307     psImage  *alpha,
    308     psVector *beta,
    309     const psVector *params,
    310     const psVector *paramMask,
    311     pmPCMData *pcm,
    312     const pmSource *source,
    313     const psKernel *psf,
    314     psMinimizeLMChi2Func func);
    315 
    316 pmPCMData *pmPCMDataAlloc (
    317     const psVector *params,
    318     const psVector *paramMask,
    319     pmSource *source);
    320 
    321 psImage *pmPCMDataSaveImage (pmPCMData *pcm);
    322 
    323288int psphotKapaOpen (void);
    324289bool psphotKapaClose (void);
     
    364329
    365330bool psphotFitSourcesLinearStack (pmConfig *config, psArray *objects, bool final);
    366 int pmPhotObjSortBySN (const void **a, const void **b);
    367 int pmPhotObjSortByX (const void **a, const void **b);
    368331
    369332typedef enum {
     
    462425bool psphotStackObjectsUnifyPosition (psArray *objects);
    463426
     427bool psphotFitSersicIndex (pmModel *model, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal);
     428
     429bool psphotFitSersicIndexPCM (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);
     430pmModel *psphotFitPCM (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);
     431
    464432#endif
  • branches/sc_branches/trunkTest/psphot/src/psphotAddNoise.c

    r28013 r29060  
    3434
    3535    bool status = false;
    36     psEllipseShape oldshape;
    37     psEllipseShape newshape;
    38     psEllipseAxes axes;
    3936
    4037    // find the currently selected readout
     
    8683        if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) continue;
    8784
    88         // select appropriate model
    89         pmModel *model = pmSourceGetModel (NULL, source);
    90         if (model == NULL) continue;  // model must be defined
    91 
    92         if (add) {
    93             psTrace ("psphot", 4, "adding noise for object at %f,%f\n", model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
    94         } else {
    95             psTrace ("psphot", 4, "remove noise for object at %f,%f\n", model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
    96         }
    97 
    98         psF32 *PAR = model->params->data.F32;
    99 
    100         // save original values
    101         float oldI0  = PAR[PM_PAR_I0];
    102         oldshape.sx  = PAR[PM_PAR_SXX];
    103         oldshape.sy  = PAR[PM_PAR_SYY];
    104         oldshape.sxy = PAR[PM_PAR_SXY];
    105 
    106         // XXX can this be done more intelligently?
    107         if (oldI0 == 0.0) continue;
    108         if (!isfinite(oldI0)) continue;
    109 
    110         // increase size and height of source
    111         axes = psEllipseShapeToAxes (oldshape, 20.0);
    112         axes.major *= SIZE;
    113         axes.minor *= SIZE;
    114         newshape = psEllipseAxesToShape (axes);
    115         PAR[PM_PAR_I0]  = FACTOR*oldI0;
    116         PAR[PM_PAR_SXX] = newshape.sx;
    117         PAR[PM_PAR_SYY] = newshape.sy;
    118         PAR[PM_PAR_SXY] = newshape.sxy;
    119 
    120         // XXX if we use pmSourceOp, the size (and possibly Io) will not be respected
    121         pmSourceOp (source, PM_MODEL_OP_FULL | PM_MODEL_OP_NOISE, add, maskVal, 0, 0);
    122 
    123         // restore original values
    124         PAR[PM_PAR_I0]  = oldI0;
    125         PAR[PM_PAR_SXX] = oldshape.sx;
    126         PAR[PM_PAR_SYY] = oldshape.sy;
    127         PAR[PM_PAR_SXY] = oldshape.sxy;
     85        pmSourceNoiseOp (source, PM_MODEL_OP_FULL | PM_MODEL_OP_NOISE, FACTOR, SIZE, add, maskVal, 0, 0);
    12886    }
    12987    if (add) {
     
    13290        psLogMsg ("psphot.noise", PS_LOG_INFO, "sub noise for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.noise"));
    13391    }
     92
    13493    return true;
    13594}
  • branches/sc_branches/trunkTest/psphot/src/psphotApResid.c

    r28524 r29060  
    459459        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal);
    460460
    461         bool status = pmSourceMagnitudes (source, psf, photMode, maskVal);
     461        bool status = pmSourceMagnitudes (source, psf, photMode, maskVal, markVal);
    462462
    463463        // clear the mask bit
  • branches/sc_branches/trunkTest/psphot/src/psphotArguments.c

    r25985 r29060  
    176176    }
    177177
    178     // visual : interactive display mode
    179     if ((N = psArgumentGet (argc, argv, "-visual"))) {
    180         psArgumentRemove (N, &argc, argv);
    181         pmVisualSetVisual(true);
    182     }
    183 
    184178    // break : used from recipe throughout psphotReadout
    185179    if ((N = psArgumentGet (argc, argv, "-break"))) {
  • branches/sc_branches/trunkTest/psphot/src/psphotBlendFit.c

    r28405 r29060  
    6565    assert (status && fitIter > 0);
    6666
    67     float fitTol = psMetadataLookupF32 (&status, recipe, "EXT_FIT_TOL"); // Fit tolerance
    68     assert (status && isfinite(fitTol) && fitTol > 0);
     67    float fitMinTol = psMetadataLookupF32 (&status, recipe, "EXT_FIT_MIN_TOL"); // Fit tolerance
     68    if (!status || !isfinite(fitMinTol) || fitMinTol <= 0) {
     69        fitMinTol = psMetadataLookupF32 (&status, recipe, "PSF_FIT_TOL"); // Fit tolerance
     70        if (!status || !isfinite(fitMinTol) || fitMinTol <= 0) {
     71            psAbort("PSF_FIT_MIN_TOL (and PSF_FIT_TOL) not defined or positive");
     72        }
     73    }
     74
     75    float fitMaxTol = psMetadataLookupF32 (&status, recipe, "EXT_FIT_MAX_TOL"); // Fit tolerance
     76    if (!status || !isfinite(fitMaxTol) || fitMaxTol <= 0) {
     77        fitMaxTol = 1.0;
     78    }
    6979
    7080    bool poisson = psMetadataLookupBool(&status, recipe, "POISSON.ERRORS.PHOT.LMM"); // Poisson errors?
    7181    assert (status);
    7282
     83    float maxChisqDOF = psMetadataLookupF32 (&status, recipe, "EXT_FIT_MAX_CHISQ"); // Fit tolerance
     84
    7385    float skySig = psMetadataLookupF32(&status, recipe, "SKY_SIG");
    7486    assert (status && isfinite(skySig) && skySig > 0);
    7587
    7688    // Define source fitting parameters for extended source fits
    77     pmSourceFitModelInit(fitIter, fitTol, PS_SQR(skySig), poisson);
     89    pmSourceFitOptions *fitOptions = pmSourceFitOptionsAlloc();
     90    fitOptions->nIter         = fitIter;
     91    fitOptions->minTol        = fitMinTol;
     92    fitOptions->maxTol        = fitMaxTol;
     93    fitOptions->maxChisqDOF   = maxChisqDOF;
     94    fitOptions->poissonErrors = poisson;
     95    fitOptions->weight        = PS_SQR(skySig);
     96    fitOptions->mode          = PM_SOURCE_FIT_PSF;
    7897
    7998    psphotInitLimitsPSF (recipe, readout);
    80     psphotInitLimitsEXT (recipe);
    81     psphotInitRadiusPSF (recipe, readout->analysis, psf->type);
     99    psphotInitLimitsEXT (recipe, readout);
     100    psphotInitRadiusPSF (recipe, readout);
    82101
    83102    // starts the timer, sets up the array of fitSets
     
    88107    if (!sources->n) {
    89108        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping blend");
     109        psFree (fitOptions);
    90110        return true;
    91111    }
     
    112132            psArrayAdd(job->args, 1, psf);
    113133            psArrayAdd(job->args, 1, newSources); // return for new sources
     134            psArrayAdd(job->args, 1, fitOptions); // default fit options
    114135            psFree (newSources);
    115136
     
    121142            if (!psThreadJobAddPending(job)) {
    122143                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     144                psFree (fitOptions);
    123145                return NULL;
    124146            }
    125 
    126 # if (0)
    127             {
    128                 int nfit = 0;
    129                 int npsf = 0;
    130                 int next = 0;
    131                 int nfail = 0;
    132                 psArray *newSources = psArrayAllocEmpty(16);
    133 
    134                 if (!psphotBlendFit_Unthreaded (&nfit, &npsf, &next, &nfail, readout, recipe, cells->data[j], psf, newSources)) {
    135                     psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    136                     return NULL;
    137                 }
    138                 Nfit += nfit;
    139                 Npsf += npsf;
    140                 Next += next;
    141                 Nfail += nfail;
    142 
    143                 // add these back onto sources
    144                 for (int k = 0; k < newSources->n; k++) {
    145                     psArrayAdd (sources, 16, newSources->data[k]);
    146                 }
    147                 psFree (newSources);
    148             }
    149 # endif
    150147        }
    151148
     
    153150        if (!psThreadPoolWait (false)) {
    154151            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     152            psFree (fitOptions);
    155153            return NULL;
    156154        }
     
    163161            } else {
    164162                psScalar *scalar = NULL;
    165                 scalar = job->args->data[5];
     163                scalar = job->args->data[6];
    166164                Nfit += scalar->data.S32;
    167                 scalar = job->args->data[6];
     165                scalar = job->args->data[7];
    168166                Npsf += scalar->data.S32;
    169                 scalar = job->args->data[7];
     167                scalar = job->args->data[8];
    170168                Next += scalar->data.S32;
    171                 scalar = job->args->data[8];
     169                scalar = job->args->data[9];
    172170                Nfail += scalar->data.S32;
    173171
     
    186184      psphotSaveImage (NULL, readout->image,  "image.v2.fits");
    187185    }
     186    psFree (fitOptions);
    188187
    189188    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);
     
    204203    psScalar *scalar = NULL;
    205204
    206     pmReadout *readout  = job->args->data[0];
    207     psMetadata *recipe  = job->args->data[1];
    208     psArray *sources    = job->args->data[2];
    209     pmPSF *psf          = job->args->data[3];
    210     psArray *newSources = job->args->data[4];
     205    pmReadout *readout             = job->args->data[0];
     206    psMetadata *recipe             = job->args->data[1];
     207    psArray *sources               = job->args->data[2];
     208    pmPSF *psf                     = job->args->data[3];
     209    psArray *newSources            = job->args->data[4];
     210    pmSourceFitOptions *fitOptions = job->args->data[5];
    211211
    212212    // bit-masks to test for good/bad pixels
     
    269269        Nfit ++;
    270270
     271        if (0) {
     272            psF32 Mxx = source->moments->Mxx;
     273            psF32 Myy = source->moments->Myy;
     274            fprintf (stderr, "1: Mxx: %f, Myy: %f\n", Mxx, Myy);
     275        }
     276
    271277        // try fitting PSFs or extended sources depending on source->mode
    272278        // these functions subtract the resulting fitted source
    273279        if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    274             if (psphotFitBlob (readout, source, newSources, psf, maskVal, markVal)) {
     280            if (psphotFitBlob (readout, source, newSources, psf, fitOptions, maskVal, markVal)) {
    275281                source->type = PM_SOURCE_TYPE_EXTENDED;
    276282                psTrace ("psphot", 5, "source at %7.1f, %7.1f is ext", source->peak->xf, source->peak->yf);
     
    280286            }
    281287        } else {
    282             if (psphotFitBlend (readout, source, psf, maskVal, markVal)) {
     288            if (psphotFitBlend (readout, source, psf, fitOptions, maskVal, markVal)) {
    283289                source->type = PM_SOURCE_TYPE_STAR;
    284290                psTrace ("psphot", 5, "source at %7.1f, %7.1f is psf", source->peak->xf, source->peak->yf);
     
    289295        }
    290296
     297        if (0) {
     298            psF32 Mxx = source->moments->Mxx;
     299            psF32 Myy = source->moments->Myy;
     300            fprintf (stderr, "2: Mxx: %f, Myy: %f\n", Mxx, Myy);
     301        }
     302
    291303        psTrace ("psphot", 5, "source at %7.1f, %7.1f failed", source->peak->xf, source->peak->yf);
    292304        Nfail ++;
     
    298310
    299311    // change the value of a scalar on the array (wrap this and put it in psArray.h)
    300     scalar = job->args->data[5];
     312    scalar = job->args->data[6];
    301313    scalar->data.S32 = Nfit;
    302314
    303     scalar = job->args->data[6];
     315    scalar = job->args->data[7];
    304316    scalar->data.S32 = Npsf;
    305317
    306     scalar = job->args->data[7];
     318    scalar = job->args->data[8];
    307319    scalar->data.S32 = Next;
    308320
    309     scalar = job->args->data[8];
     321    scalar = job->args->data[9];
    310322    scalar->data.S32 = Nfail;
    311323
  • branches/sc_branches/trunkTest/psphot/src/psphotChoosePSF.c

    r28013 r29060  
    7474
    7575    // structure to store user options defining the psf
    76     pmPSFOptions *options = pmPSFOptionsAlloc ();
     76    pmPSFOptions *options = pmPSFOptionsAlloc();
    7777
    7878    // load user options from the recipe. no need to check existence -- they are
     
    138138        return false;
    139139    }
    140     float fitTol = psMetadataLookupF32 (&status, recipe, "PSF_FIT_TOL"); // Fit tolerance
    141     if (!status || !isfinite(fitTol) || fitTol <= 0) {
    142         psError(PS_ERR_BAD_PARAMETER_VALUE, true, "PSF_FIT_TOL is not positive");
    143         return false;
    144     }
    145     pmSourceFitModelInit(fitIter, fitTol, PS_SQR(SKY_SIG), options->poissonErrorsPhotLMM);
    146 
     140    float fitMinTol = psMetadataLookupF32 (&status, recipe, "PSF_FIT_MIN_TOL"); // Fit tolerance
     141    if (!status || !isfinite(fitMinTol) || fitMinTol <= 0) {
     142        fitMinTol = psMetadataLookupF32 (&status, recipe, "PSF_FIT_TOL"); // Fit tolerance
     143        if (!status || !isfinite(fitMinTol) || fitMinTol <= 0) {
     144            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "PSF_FIT_MIN_TOL (and PSF_FIT_TOL) not defined or positive");
     145            return false;
     146        }
     147    }
     148    float fitMaxTol = psMetadataLookupF32 (&status, recipe, "PSF_FIT_MAX_TOL"); // Fit tolerance
     149    if (!status || !isfinite(fitMaxTol) || fitMaxTol <= 0) {
     150        fitMaxTol = 1.0;
     151    }
     152    float maxChisqDOF = psMetadataLookupF32 (&status, recipe, "PSF_FIT_MAX_CHISQ"); // Fit tolerance
     153
     154    // options which modify the behavior of the model fitting
     155    options->fitOptions                = pmSourceFitOptionsAlloc();
     156    options->fitOptions->nIter         = fitIter;
     157    options->fitOptions->minTol        = fitMinTol;
     158    options->fitOptions->maxTol        = fitMaxTol;
     159    options->fitOptions->maxChisqDOF   = maxChisqDOF;
     160    options->fitOptions->poissonErrors = options->poissonErrorsPhotLMM;
     161    options->fitOptions->weight        = PS_SQR(SKY_SIG);
     162    options->fitOptions->mode          = PM_SOURCE_FIT_PSF;
     163   
    147164    psArray *stars = psArrayAllocEmpty (sources->n);
    148165
     
    227244
    228245    // try each model option listed in config
     246    // pmPSFtryModel makes a local copy of the sources -- those points are not the same as those for 'sources'
    229247    for (int i = 0; i < modelNames->n; i++) {
    230248        char *modelName = modelNames->data[i];
     
    304322
    305323    // unset the PSFSTAR flag for stars not used for PSF model
     324    // XXX a more efficient way of achieving this would be to record a pair of arrays
     325    // of the source index and the source id for the psf stars.  but that would require we do
     326    // not re-sort the source list in the meanwhile
     327    int nDrop = 0;
    306328    for (int i = 0; i < try->sources->n; i++) {
    307329        pmSource *source = try->sources->data[i];
    308330        if (try->mask->data.PS_TYPE_VECTOR_MASK_DATA[i]) {
    309             source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
    310         }
    311     }
     331            // need to find this source in the original list (these are copies, not pointers)
     332            for (int j = 0; j < sources->n; j++) {
     333                pmSource *realSource = sources->data[j];
     334                if (realSource->id != source->id) continue;
     335                realSource->mode &= ~PM_SOURCE_MODE_PSFSTAR;
     336                source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
     337                nDrop ++;
     338                break;
     339            }
     340        }
     341    }
     342    // fprintf (stderr, "drop %d stars as PSF stars\n", nDrop);
     343
     344    // XXX is this working?
     345    // int N1 = 0;
     346    // for (int i = 0; i < try->sources->n; i++) {
     347    //     pmSource *source = try->sources->data[i];
     348    //  fprintf (stderr, "%llx : %d\n", (long long int) source, (source->mode & PM_SOURCE_MODE_PSFSTAR));
     349    //  if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
     350    //      N1 ++;
     351    //     }
     352    // }
     353    // int N2 = 0;
     354    // for (int i = 0; i < sources->n; i++) {
     355    //     pmSource *source = sources->data[i];
     356    //  fprintf (stderr, "%llx : %d\n", (long long int) source, (source->mode & PM_SOURCE_MODE_PSFSTAR));
     357    //  if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
     358    //      N2 ++;
     359    //     }
     360    // }
     361    // fprintf (stderr, "N1: %d, N2: %d\n", N1, N2);
    312362
    313363    // build a PSF residual image
  • branches/sc_branches/trunkTest/psphot/src/psphotEllipticalContour.c

    r27819 r29060  
    8282    params->data.F32[PAR_RMIN]    = Rmin;
    8383
    84     psMinimization *myMin = psMinimizationAlloc (25, 0.001);
     84    psMinimization *myMin = psMinimizationAlloc (25, 0.01, 1.00);
    8585    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
    8686   
  • branches/sc_branches/trunkTest/psphot/src/psphotExtendedSourceAnalysis.c

    r28013 r29060  
    121121        if (source->peak->y > AnalysisRegion.y1) continue;
    122122
     123        // fprintf (stderr, "xsrc: %f, %f : %f\n", source->peak->xf, source->peak->yf, source->peak->SN);
     124
    123125        // replace object in image
    124126        if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) {
     
    157159        }
    158160
    159 # if (0)
    160         // Isophotal Mags
    161         if (doIsophotal) {
    162             if (!psphotIsophotal (source, recipe, maskVal)) {
    163                 psTrace ("psphot", 5, "failed to measure isophotal mags for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    164             } else {
    165                 psTrace ("psphot", 5, "measured isophotal mags for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    166                 Nisophot ++;
    167                 source->mode |= PM_SOURCE_MODE_EXTENDED_STATS;
    168             }
    169         }
    170         // Kron Mags
    171         if (doKron) {
    172             if (!psphotKron (source, recipe, maskVal)) {
    173                 psTrace ("psphot", 5, "failed to measure kron mags for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    174             } else {
    175                 psTrace ("psphot", 5, "measure kron mags for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    176                 Nkron ++;
    177                 source->mode |= PM_SOURCE_MODE_EXTENDED_STATS;
    178             }
    179         }
    180 # endif
    181 
    182161        // re-subtract the object, leave local sky
    183162        pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     
    201180    }
    202181
     182    // fprintf (stderr, "xsrc : tried %ld objects\n", sources->n);
     183
    203184    return true;
    204185}
  • branches/sc_branches/trunkTest/psphot/src/psphotExtendedSourceFits.c

    r28013 r29060  
    3131// non-linear model fitting for extended sources
    3232bool psphotExtendedSourceFitsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe) {
     33
     34    bool status;
     35    int Next = 0;
     36    int Nconvolve = 0;
     37    int NconvolvePass = 0;
     38    int Nplain = 0;
     39    int NplainPass = 0;
     40
     41    psTimerStart ("psphot.extended");
     42
     43    // find the currently selected readout
     44    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, index); // File of interest
     45    psAssert (file, "missing file?");
     46
     47    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     48    psAssert (readout, "missing readout?");
     49
     50    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     51    psAssert (detections, "missing detections?");
     52
     53    psArray *sources = detections->allSources;
     54    psAssert (sources, "missing sources?");
     55
     56    if (!sources->n) {
     57        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source size");
     58        return true;
     59    }
     60
     61    // determine the number of allowed threads
     62    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
     63    if (!status) {
     64        nThreads = 0;
     65    }
     66
     67    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     68    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
     69    assert (maskVal);
     70
     71    psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); // Mask value for bad pixels
     72    assert (markVal);
     73
     74    // maskVal is used to test for rejected pixels, and must include markVal
     75    maskVal |= markVal;
     76
     77    // select the collection of desired models
     78    psMetadata *models = psMetadataLookupMetadata (&status, recipe, "EXTENDED_SOURCE_MODELS");
     79    if (!status) {
     80        psWarning ("extended source model fits requested but model model is missing (EXTENDED_SOURCE_MODELS)\n");
     81        return true;
     82    }
     83    if (models->list->n == 0) {
     84        psWarning ("extended source model fits requested but no models are specified\n");
     85        return true;
     86    }
     87
     88    // validate the model entries
     89    psMetadataIterator *iter = psMetadataIteratorAlloc (models, PS_LIST_HEAD, NULL);
     90    psMetadataItem *item = NULL;
     91    while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
     92
     93      if (item->type != PS_DATA_METADATA) {
     94        psAbort ("Invalid type for EXTENDED_SOURCE_MODEL entry %s, not a metadata folder", item->name);
     95        // XXX we could cull the bad entries or build a validated model folder
     96      }
     97
     98      psMetadata *model = (psMetadata *) item->data.md;
     99
     100      // check on the model type
     101      char *modelName = psMetadataLookupStr (&status, model, "MODEL");
     102      int modelType = pmModelClassGetType (modelName);
     103      if (modelType < 0) {
     104        psAbort ("Unknown model class for EXTENDED_SOURCE_MODEL entry %s: %s", item->name, modelName);
     105      }
     106      psMetadataAddS32 (model, PS_LIST_TAIL, "MODEL_TYPE", PS_META_REPLACE, "", modelType);
     107
     108      // check on the SNLIM, set a float value
     109      char *SNword = psMetadataLookupStr (&status, model, "SNLIM");
     110      if (!status) {
     111        psAbort("SNLIM not defined for extended source model %s\n", item->name);
     112      }
     113      float SNlim = atof (SNword);
     114      psMetadataAddF32 (model, PS_LIST_TAIL, "SNLIM_VALUE", PS_META_REPLACE, "", SNlim);
     115
     116      // check on the PSF-Convolution status
     117      char *convolvedWord = psMetadataLookupStr (&status, model, "PSF_CONVOLVED");
     118      if (!status || (strcasecmp (convolvedWord, "true") && strcasecmp (convolvedWord, "false"))) {
     119        psAbort ("PSF_CONVOLVED entry invalid or missing for EXTENDED_SOURCE_MODEL entry %s", item->name);
     120      }
     121      bool convolved = !strcasecmp (convolvedWord, "true");
     122      psMetadataAddBool (model, PS_LIST_TAIL, "PSF_CONVOLVED_VALUE", PS_META_REPLACE, "", convolved);
     123    }
     124    psFree (iter);
     125
     126    // option to limit analysis to a specific region
     127    char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
     128    psRegion *AnalysisRegion = psRegionAlloc(0,0,0,0);
     129    *AnalysisRegion = psRegionForImage(readout->image, psRegionFromString (region));
     130    if (psRegionIsNaN (*AnalysisRegion)) psAbort("analysis region mis-defined");
     131
     132    // what fraction of the PSF is used? (radius in pixels : 2 -> 5x5 box)
     133    int psfSize = psMetadataLookupS32 (&status, recipe, "PCM_BOX_SIZE");
     134    assert (status);
     135
     136    // source analysis is done in S/N order (brightest first)
     137    sources = psArraySort (sources, pmSourceSortBySN);
     138
     139    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     140    int Cx = 1, Cy = 1;
     141    psphotChooseCellSizes (&Cx, &Cy, readout, nThreads);
     142
     143    psArray *cellGroups = psphotAssignSources (Cx, Cy, sources);
     144
     145    for (int i = 0; i < cellGroups->n; i++) {
     146
     147        psArray *cells = cellGroups->data[i];
     148
     149        for (int j = 0; j < cells->n; j++) {
     150
     151            // allocate a job -- if threads are not defined, this just runs the job
     152            psThreadJob *job = psThreadJobAlloc ("PSPHOT_EXTENDED_FIT");
     153
     154            psArrayAdd(job->args, 1, readout);
     155            psArrayAdd(job->args, 1, cells->data[j]); // sources
     156            psArrayAdd(job->args, 1, models);
     157            psArrayAdd(job->args, 1, AnalysisRegion); // XXX make a pointer
     158
     159            PS_ARRAY_ADD_SCALAR(job->args, psfSize, PS_TYPE_S32);
     160            PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK);
     161            PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK);
     162
     163            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Next
     164            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nconvolve
     165            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for NconvolvePass
     166            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nplain
     167            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for NplainPass
     168
     169            if (!psThreadJobAddPending(job)) {
     170                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     171                psFree(AnalysisRegion);
     172                return false;
     173            }
     174        }
     175
     176        // wait for the threads to finish and manage results
     177        if (!psThreadPoolWait (false)) {
     178            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     179            psFree(AnalysisRegion);
     180            return false;
     181        }
     182
     183        // we have only supplied one type of job, so we can assume the types here
     184        psThreadJob *job = NULL;
     185        while ((job = psThreadJobGetDone()) != NULL) {
     186            if (job->args->n < 1) {
     187                fprintf (stderr, "error with job\n");
     188            } else {
     189                psScalar *scalar = NULL;
     190                scalar = job->args->data[7];
     191                Next += scalar->data.S32;
     192                scalar = job->args->data[8];
     193                Nconvolve += scalar->data.S32;
     194                scalar = job->args->data[9];
     195                NconvolvePass += scalar->data.S32;
     196                scalar = job->args->data[10];
     197                Nplain += scalar->data.S32;
     198                scalar = job->args->data[11];
     199                NplainPass += scalar->data.S32;
     200            }
     201            psFree(job);
     202        }
     203    }
     204    psFree (cellGroups);
     205    psFree(AnalysisRegion);
     206
     207    psLogMsg ("psphot", PS_LOG_INFO, "extended source analysis: %f sec for %d objects\n", psTimerMark ("psphot.extended"), Next);
     208    psLogMsg ("psphot", PS_LOG_INFO, "  %d convolved models (%d passed)\n", Nconvolve, NconvolvePass);
     209    psLogMsg ("psphot", PS_LOG_INFO, "  %d plain models (%d passed)\n", Nplain, NplainPass);
     210    return true;
     211}
     212
     213// non-linear model fitting for extended sources
     214bool psphotExtendedSourceFits_Threaded (psThreadJob *job) {
    33215
    34216    bool status;
     
    39221    int NplainPass = 0;
    40222    bool savePics = false;
    41 
    42     // find the currently selected readout
    43     pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, index); // File of interest
    44     psAssert (file, "missing file?");
    45 
    46     pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
    47     psAssert (readout, "missing readout?");
    48 
    49     pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
    50     psAssert (detections, "missing detections?");
    51 
    52     psArray *sources = detections->allSources;
    53     psAssert (sources, "missing sources?");
    54 
    55     if (!sources->n) {
    56         psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source size");
    57         return true;
    58     }
    59 
    60     // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    61     psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
    62     assert (maskVal);
    63 
    64     psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); // Mask value for bad pixels
    65     assert (markVal);
    66 
    67     // maskVal is used to test for rejected pixels, and must include markVal
    68     maskVal |= markVal;
    69 
    70     // select the collection of desired models
    71     psMetadata *models = psMetadataLookupMetadata (&status, recipe, "EXTENDED_SOURCE_MODELS");
    72     if (!status) {
    73         psWarning ("extended source model fits requested but model model is missing (EXTENDED_SOURCE_MODELS)\n");
    74         return true;
    75     }
    76     if (models->list->n == 0) {
    77         psWarning ("extended source model fits requested but no models are specified\n");
    78         return true;
    79     }
    80 
    81     // validate the model entries
    82     psMetadataIterator *iter = psMetadataIteratorAlloc (models, PS_LIST_HEAD, NULL);
    83     psMetadataItem *item = NULL;
    84     while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
    85 
    86       if (item->type != PS_DATA_METADATA) {
    87         psAbort ("Invalid type for EXTENDED_SOURCE_MODEL entry %s, not a metadata folder", item->name);
    88         // XXX we could cull the bad entries or build a validated model folder
    89       }
    90 
    91       psMetadata *model = (psMetadata *) item->data.md;
    92 
    93       // check on the model type
    94       char *modelName = psMetadataLookupStr (&status, model, "MODEL");
    95       int modelType = pmModelClassGetType (modelName);
    96       if (modelType < 0) {
    97         psAbort ("Unknown model class for EXTENDED_SOURCE_MODEL entry %s: %s", item->name, modelName);
    98       }
    99       psMetadataAddS32 (model, PS_LIST_TAIL, "MODEL_TYPE", PS_META_REPLACE, "", modelType);
    100 
    101       // check on the SNLIM, set a float value
    102       char *SNword = psMetadataLookupStr (&status, model, "SNLIM");
    103       if (!status) {
    104         psAbort("SNLIM not defined for extended source model %s\n", item->name);
    105       }
    106       float SNlim = atof (SNword);
    107       psMetadataAddF32 (model, PS_LIST_TAIL, "SNLIM_VALUE", PS_META_REPLACE, "", SNlim);
    108 
    109       // check on the PSF-Convolution status
    110       char *convolvedWord = psMetadataLookupStr (&status, model, "PSF_CONVOLVED");
    111       if (!status || (strcasecmp (convolvedWord, "true") && strcasecmp (convolvedWord, "false"))) {
    112         psAbort ("PSF_CONVOLVED entry invalid or missing for EXTENDED_SOURCE_MODEL entry %s", item->name);
    113       }
    114       bool convolved = !strcasecmp (convolvedWord, "true");
    115       psMetadataAddBool (model, PS_LIST_TAIL, "PSF_CONVOLVED_VALUE", PS_META_REPLACE, "", convolved);
    116     }
    117     psFree (iter);
    118 
    119     // option to limit analysis to a specific region
    120     char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
    121     psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region));
    122     if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined");
    123 
    124     // what fraction of the PSF is used? (radius in pixels : 2 -> 5x5 box)
    125     int psfSize = psMetadataLookupS32 (&status, recipe, "PCM_BOX_SIZE");
    126     assert (status);
    127 
    128     // source analysis is done in S/N order (brightest first)
    129     sources = psArraySort (sources, pmSourceSortBySN);
     223    float radius;
     224    psScalar *scalar = NULL;
     225
     226    // arguments: readout, sources, models, region, psfSize, maskVal, markVal
     227    pmReadout *readout      = job->args->data[0];
     228    psArray *sources        = job->args->data[1];
     229    psMetadata *models      = job->args->data[2];
     230    psRegion *region        = job->args->data[3];
     231    int psfSize             = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA);
     232    psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[5],PS_TYPE_IMAGE_MASK_DATA);
     233    psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[6],PS_TYPE_IMAGE_MASK_DATA);
     234
     235    // Define source fitting parameters for extended source fits
     236    pmSourceFitOptions *fitOptions = pmSourceFitOptionsAlloc();
     237    fitOptions->mode          = PM_SOURCE_FIT_EXT;
     238    // XXX for now, use the defaults for the rest:
     239    // fitOptions->nIter         = fitIter;
     240    // fitOptions->tol           = fitTol;
     241    // fitOptions->poissonErrors = poisson;
     242    // fitOptions->weight        = PS_SQR(skySig);
    130243
    131244    // choose the sources of interest
     
    140253
    141254        // XXX this should use peak?
    142         if (source->peak->x < AnalysisRegion.x0) continue;
    143         if (source->peak->y < AnalysisRegion.y0) continue;
    144         if (source->peak->x > AnalysisRegion.x1) continue;
    145         if (source->peak->y > AnalysisRegion.y1) continue;
     255        if (source->peak->x < region->x0) continue;
     256        if (source->peak->y < region->y0) continue;
     257        if (source->peak->x > region->x1) continue;
     258        if (source->peak->y > region->y1) continue;
    146259
    147260        // if model is NULL, we don't have a starting guess
     
    155268        Next ++;
    156269
     270        // set the radius based on the footprint (also sets the mask pixels)
     271        if (!psphotSetRadiusFootprint(&radius, readout, source, markVal, 1.0)) {
     272            fprintf (stderr, "skipping (1) %f, %f\n", source->peak->xf, source->peak->yf);
     273            psFree (fitOptions)
     274            return false;
     275        }
     276
     277        // XXX note that this changes the source moments that are published...
     278        // recalculate the source moments using the larger extended-source moments radius
     279        // at this stage, skip Gaussian windowing, and do not clip pixels by S/N
     280        // this uses the footprint to judge both radius and aperture?
     281        // XXX save the psf-based moments for output
     282        if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) {
     283            fprintf (stderr, "skipping (2) %f, %f\n", source->peak->xf, source->peak->yf);
     284            // subtract the best fit from the object, leave local sky
     285            pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     286            // XXX raise an error of some kind
     287            continue;
     288        }
     289
    157290        // save the modelFlux here in case we need to subtract it (for failure)
    158291        psImage *modelFluxStart = psMemIncrRefCounter (source->modelFlux);
    159 
     292        if (!modelFluxStart) {
     293            pmSourceCacheModel (source, maskVal);
     294            modelFluxStart = psMemIncrRefCounter (source->modelFlux);
     295            if (!modelFluxStart) {
     296                fprintf (stderr, "skipping (3) %f, %f\n", source->peak->xf, source->peak->yf);
     297                // XXX raise an error of some kind?
     298                continue;
     299            }
     300        }
     301       
    160302        if (savePics) {
    161303          psphotSaveImage (NULL, readout->image, "image.xp.fits");
     
    183325          assert (status);
    184326
     327          // fprintf (stderr, "xfit: %f, %f : %f\n", source->peak->xf, source->peak->yf, source->peak->SN);
     328
    185329          // limit selection to some SN limit
    186330          assert (source->peak); // how can a source not have a peak?
     
    201345          pmModel *modelFit = NULL;
    202346          if (convolved) {
    203               modelFit = psphotPSFConvModel (readout, source, modelType, maskVal, markVal, psfSize);
     347              modelFit = psphotFitPCM (readout, source, fitOptions, modelType, maskVal, markVal, psfSize);
    204348              if (!modelFit) {
    205349                  psTrace ("psphot", 5, "failed to fit psf-conv model for object at %f, %f", source->moments->Mx, source->moments->My);
     
    215359              psFree (source->modelFlux);
    216360              source->modelFlux = NULL;
    217               modelFit = psphotFitEXT (readout, source, modelType, maskVal, markVal);
     361              modelFit = psphotFitEXT (readout, source, fitOptions, modelType, maskVal, markVal);
    218362              if (!modelFit) {
    219363                  psTrace ("psphot", 5, "failed to fit plain model for object at %f, %f", source->moments->Mx, source->moments->My);
     
    233377
    234378          // test for fit quality / result
     379          modelFit->fitRadius = radius;
    235380          psArrayAdd (source->modelFits, 4, modelFit);
    236381
     
    311456        }
    312457    }
    313 
    314     psLogMsg ("psphot", PS_LOG_INFO, "extended source analysis: %f sec for %d objects\n", psTimerMark ("psphot"), Next);
    315     psLogMsg ("psphot", PS_LOG_INFO, "  %d convolved models (%d passed)\n", Nconvolve, NconvolvePass);
    316     psLogMsg ("psphot", PS_LOG_INFO, "  %d plain models (%d passed)\n", Nplain, NplainPass);
     458    psFree (fitOptions);
     459
     460    // fprintf (stderr, "xfit : tried %ld objects\n", sources->n);
     461
     462    // change the value of a scalar on the array (wrap this and put it in psArray.h)
     463    scalar = job->args->data[7];
     464    scalar->data.S32 = Next;
     465
     466    scalar = job->args->data[8];
     467    scalar->data.S32 = Nconvolve;
     468
     469    scalar = job->args->data[9];
     470    scalar->data.S32 = NconvolvePass;
     471
     472    scalar = job->args->data[10];
     473    scalar->data.S32 = Nplain;
     474
     475    scalar = job->args->data[11];
     476    scalar->data.S32 = NplainPass;
     477
    317478    return true;
    318479}
  • branches/sc_branches/trunkTest/psphot/src/psphotFindDetections.c

    r28013 r29060  
    9090    psphotVisualShowSignificance (significance, -1.0, PS_SQR(3.0*NSIGMA_PEAK));
    9191
    92     // XXX getting some strange results from significance image
    93     if (0) {
    94         psImage *lsig = (psImage *) psUnaryOp (NULL, significance, "log");
    95         psphotVisualShowSignificance (lsig, 0.0, 4.0);
    96         psFree (lsig);
    97     }   
     92    // display the log significance image
     93    psphotVisualShowLogSignificance (significance, 0.0, 4.5);
    9894
    9995    // detect the peaks in the significance image
  • branches/sc_branches/trunkTest/psphot/src/psphotFitSet.c

    r21183 r29060  
    2424    }
    2525
     26    // Define source fitting parameters for extended source fits
     27    pmSourceFitOptions *fitOptions = pmSourceFitOptionsAlloc();
     28    fitOptions->mode          = PM_SOURCE_FIT_EXT;
     29    // XXX for now, use the defaults for the rest:
     30    // fitOptions->nIter         = fitIter;
     31    // fitOptions->tol           = fitTol;
     32    // fitOptions->poissonErrors = poisson;
     33    // fitOptions->weight        = PS_SQR(skySig);
     34
    2635    // XXX pmSourceFitSet must cache the modelFlux?
    27     pmSourceFitSet (source, modelSet, mode, maskVal);
     36    pmSourceFitSet (source, modelSet, fitOptions, maskVal);
    2837
    2938    // write out positive object
  • branches/sc_branches/trunkTest/psphot/src/psphotFitSourcesLinear.c

    r28426 r29060  
    100100    if (!status) {
    101101        SKY_FIT_LINEAR = false;
     102    }
     103   
     104    float MIN_VALID_FLUX = psMetadataLookupF32(&status, recipe, "PSF_FIT_MIN_VALID_FLUX");
     105    if (!status) {
     106        MIN_VALID_FLUX = 1e-8;
     107    }
     108    float MAX_VALID_FLUX = psMetadataLookupF32(&status, recipe, "PSF_FIT_MAX_VALID_FLUX");
     109    if (!status) {
     110        MAX_VALID_FLUX = 1e+8;
    102111    }
    103112
     
    228237
    229238    psSparseConstraint constraint;
    230     constraint.paramMin   = 0.0;
    231     constraint.paramMax   = 1e8;
    232     constraint.paramDelta = 1e8;
     239    constraint.paramMin   = MIN_VALID_FLUX;
     240    constraint.paramMax   = MAX_VALID_FLUX;
     241    constraint.paramDelta = 1e7;
    233242
    234243    // solve for normalization terms (need include local sky?)
  • branches/sc_branches/trunkTest/psphot/src/psphotFitSourcesLinearStack.c

    r28426 r29060  
    170170    return true;
    171171}
    172 
    173 // sort by X (ascending)
    174 int pmPhotObjSortByX (const void **a, const void **b)
    175 {
    176     pmPhotObj *objA = *(pmPhotObj **)a;
    177     pmPhotObj *objB = *(pmPhotObj **)b;
    178 
    179     psF32 fA = objA->x;
    180     psF32 fB = objB->x;
    181 
    182     psF32 diff = fA - fB;
    183     if (diff > FLT_EPSILON) return (+1);
    184     if (diff < FLT_EPSILON) return (-1);
    185     return (0);
    186 }
  • branches/sc_branches/trunkTest/psphot/src/psphotGuessModels.c

    r28405 r29060  
    8080
    8181    // setup the PSF fit radius details
    82     psphotInitRadiusPSF (recipe, readout->analysis, psf->type);
     82    psphotInitRadiusPSF (recipe, readout);
    8383
    8484    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
  • branches/sc_branches/trunkTest/psphot/src/psphotLoadSRCTEXT.c

    r25983 r29060  
    8484            source->peak->yf   = PAR[PM_PAR_YPOS]; // but we know the pixel coordinate
    8585
    86             source->pixWeight = 1.0;
     86            source->pixWeightNotBad = 1.0;
     87            source->pixWeightNotPoor = 1.0;
    8788            source->crNsigma  = 0.0;
    8889            source->extNsigma = 0.0;
  • branches/sc_branches/trunkTest/psphot/src/psphotMagnitudes.c

    r28405 r29060  
    124124                return false;
    125125            }
    126 
    127 # if (0)
    128                 int nap = 0;
    129                 if (!psphotMagnitudes_Unthreaded (&nap, cells->data[j], psf, binning, backModel, backStdev, photMode, maskVal)) {
    130                     psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    131                     return false;
    132                 }
    133                 Nap += nap;
    134 # endif
    135126        }
    136127
     
    186177        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal);
    187178
    188         status = pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal
     179        status = pmSourceMagnitudes (source, psf, photMode, maskVal, markVal);
    189180        if (status && isfinite(source->apMag)) Nap ++;
    190181
     
    268259            psArrayAdd(job->args, 1, cells->data[j]); // sources
    269260            PS_ARRAY_ADD_SCALAR(job->args, maskVal,  PS_TYPE_IMAGE_MASK);
     261            PS_ARRAY_ADD_SCALAR(job->args, markVal,  PS_TYPE_IMAGE_MASK);
    270262
    271263            if (!psThreadJobAddPending(job)) {
     
    304296    psArray *sources                = job->args->data[0];
    305297    psImageMaskType maskVal         = PS_SCALAR_VALUE(job->args->data[1],PS_TYPE_IMAGE_MASK_DATA);
     298    psImageMaskType markVal         = PS_SCALAR_VALUE(job->args->data[2],PS_TYPE_IMAGE_MASK_DATA);
    306299
    307300    for (int i = 0; i < sources->n; i++) {
     
    312305        if (model == NULL) {
    313306          psTrace ("psphot", 3, "fail mag : no valid model");
    314           source->pixWeight = NAN;
     307          source->pixWeightNotBad = NAN;
     308          source->pixWeightNotPoor = NAN;
    315309          continue;
    316310        }
    317311
    318         status = pmSourcePixelWeight (&source->pixWeight, model, source->maskObj, maskVal);
     312        status = pmSourcePixelWeight (&source->pixWeightNotBad, &source->pixWeightNotPoor, model, source->maskObj, maskVal, markVal);
    319313        if (!status) {
    320314          psTrace ("psphot", 3, "fail to measure pixel weight");
    321           source->pixWeight = NAN;
     315          source->pixWeightNotBad = NAN;
     316          source->pixWeightNotPoor = NAN;
    322317          continue;
    323318        }
  • branches/sc_branches/trunkTest/psphot/src/psphotModelWithPSF.c

    r21366 r29060  
    7373
    7474    // iterate until the tolerance is reached, or give up
    75     while ((min->iter < min->maxIter) && ((min->lastDelta > min->tol) || !isfinite(min->lastDelta))) {
     75    while ((min->iter < min->maxIter) && ((min->lastDelta > min->minTol) || !isfinite(min->lastDelta))) {
    7676        psTrace("psphot", 5, "Iteration number %d.  (max iterations is %d).\n", min->iter, min->maxIter);
    77         psTrace("psphot", 5, "Last delta is %f.  Min->tol is %f.\n", min->lastDelta, min->tol);
     77        psTrace("psphot", 5, "Last delta is %f.  Min->minTol is %f.\n", min->lastDelta, min->minTol);
    7878
    7979
     
    166166    psFree(pcm);
    167167
    168     if (min->iter == min->maxIter) {
    169         psTrace("psphot", 3, "---- end (false) ----\n");
    170         return(false);
    171     }
    172 
    173     psTrace("psphot", 3, "---- end (true) ----\n");
    174     return(true);
     168    // if the last improvement was at least as good as maxTol, accept the fit:
     169    if (min->lastDelta <= min->maxTol) {
     170        psTrace("psphot", 6, "---- end (true) ----\n");
     171        return(true);
     172    }
     173    psTrace("psphot", 6, "---- end (false) ----\n");
     174    return(false);
    175175}
    176176
  • branches/sc_branches/trunkTest/psphot/src/psphotPSFConvModel.c

    r26894 r29060  
    44// save as static values so they may be set externally
    55static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15;
    6 static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1;
     6static psF32 PM_SOURCE_FIT_MODEL_MIN_TOL = 0.1;
     7static psF32 PM_SOURCE_FIT_MODEL_MAX_TOL = 2.0;
    78
    89// input source has both modelPSF and modelEXT.  on successful exit, we set the
    910// modelConv to contain the fitted parameters, and the modelFlux to contain the
    1011// convolved model image.
    11 pmModel *psphotPSFConvModel (pmReadout *readout, pmSource *source, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     12
     13// XXX need to generalize this -- number of fitted parameters must be flexible based on the fitOptions
     14
     15pmModel *psphotPSFConvModel (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
    1216   
    1317    // maskVal is used to test for rejected pixels, and must include markVal
     
    9094
    9195    // set up the minimization process
    92     psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE);
     96    psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_MIN_TOL, PM_SOURCE_FIT_MODEL_MAX_TOL);
    9397
    9498    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
  • branches/sc_branches/trunkTest/psphot/src/psphotPetrosianVisual.c

    r27819 r29060  
    11# include "psphotInternal.h"
    2 # define FORCE_VISUAL 0
    32
    43// this function displays representative images as the psphot analysis progresses:
     
    5453    Graphdata graphdata;
    5554
    56     // return true;
    57     if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
     55    if (!pmVisualTestLevel("psphot.petro.byangle", 2)) return true;
    5856
    5957    if (kapa2 == -1) {
     
    10199    Graphdata graphdata;
    102100
    103     // return true;
    104     if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
     101    if (!pmVisualTestLevel("psphot.petro.radii", 2)) return true;
    105102
    106103    if (kapa == -1) {
     
    173170    KapaSection section;
    174171
    175     if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
     172    if (!pmVisualTestLevel("psphot.petro.stats", 2)) return true;
    176173
    177174    if (kapa2 == -1) {
     
    311308    Graphdata graphdata;
    312309
    313     if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
     310    if (!pmVisualTestLevel("psphot.petro.ellipse", 2)) return true;
    314311
    315312    if (kapa == -1) {
  • branches/sc_branches/trunkTest/psphot/src/psphotRadiusChecks.c

    r28418 r29060  
    88                                        // and a per-object radius is calculated)
    99
    10 bool psphotInitRadiusPSF(const psMetadata *recipe, const psMetadata *analysis, const pmModelType type) {
     10bool psphotInitRadiusPSF(psMetadata *recipe, pmReadout *readout) {
    1111
    1212    bool status = true;
     
    1515    PSF_FIT_PADDING = psMetadataLookupF32(&status, recipe, "PSF_FIT_PADDING");
    1616
    17     PSF_FIT_RADIUS =  psMetadataLookupF32(&status, analysis, "PSF_FIT_RADIUS");
     17    PSF_FIT_RADIUS =  psMetadataLookupF32(&status, readout->analysis, "PSF_FIT_RADIUS");
    1818    if (!status) {
    1919        PSF_FIT_RADIUS = psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS");
    2020    }
    2121
    22     PSF_APERTURE =  psMetadataLookupF32(&status, analysis, "PSF_APERTURE");
     22    PSF_APERTURE =  psMetadataLookupF32(&status, readout->analysis, "PSF_APERTURE");
    2323    if (!status) {
    2424        PSF_APERTURE =  psMetadataLookupF32(&status, recipe, "PSF_APERTURE");
     
    2828
    2929    if (PSF_FIT_RADIUS == 0.0) {
    30         float gaussSigma = psMetadataLookupF32(&status, analysis, "MOMENTS_GAUSS_SIGMA");
     30        float gaussSigma = psMetadataLookupF32(&status, readout->analysis, "MOMENTS_GAUSS_SIGMA");
    3131        if (!status) {
    3232            gaussSigma = psMetadataLookupF32(&status, recipe, "MOMENTS_GAUSS_SIGMA");
     
    3737
    3838    if (PSF_APERTURE == 0.0) {
    39         float gaussSigma = psMetadataLookupF32(&status, analysis, "MOMENTS_GAUSS_SIGMA");
     39        float gaussSigma = psMetadataLookupF32(&status, readout->analysis, "MOMENTS_GAUSS_SIGMA");
    4040        if (!status) {
    4141            gaussSigma = psMetadataLookupF32(&status, recipe, "MOMENTS_GAUSS_SIGMA");
     
    122122}
    123123
     124static float EXT_FIT_SKY_SIG;
    124125static float EXT_FIT_NSIGMA;
    125126static float EXT_FIT_PADDING;
    126127static float EXT_FIT_MAX_RADIUS;
    127128
    128 bool psphotInitRadiusEXT (psMetadata *recipe, pmModelType type) {
     129bool psphotInitRadiusEXT (psMetadata *recipe, pmReadout *readout) {
    129130
    130131    bool status;
     
    134135    EXT_FIT_MAX_RADIUS = psMetadataLookupF32 (&status, recipe, "EXT_FIT_MAX_RADIUS");
    135136
     137    float skyMean  = psMetadataLookupF32 (&status, readout->analysis, "SKY_MEAN");
     138    float skyStdev = psMetadataLookupF32 (&status, readout->analysis, "SKY_STDEV");
     139
     140    fprintf (stderr, "sky: %f +/- %f\n", skyMean, skyStdev);
     141
     142    EXT_FIT_SKY_SIG = skyStdev;
     143
    136144    return true;
    137145}
    138146
    139147// call this function whenever you (re)-define the EXT model
    140 float psphotSetRadiusEXT (pmReadout *readout, pmSource *source, psImageMaskType markVal) {
     148bool psphotSetRadiusFootprint (float *radius, pmReadout *readout, pmSource *source, psImageMaskType markVal, float factor) {
    141149
    142150    psAssert (source, "source not defined??");
     
    146154
    147155    // set the radius based on the footprint:
    148     if (!peak->footprint) goto escape;
     156    if (!peak->footprint) return false;
    149157    pmFootprint *footprint = peak->footprint;
    150     if (!footprint->spans) goto escape;
    151     if (footprint->spans->n < 1) goto escape;
     158    if (!footprint->spans) return false;
     159    if (footprint->spans->n < 1) return false;
    152160
    153161    // find the max radius
    154     float radius = 0.0;
     162    float rawRadius = 0.0;
    155163    for (int j = 0; j < footprint->spans->n; j++) {
    156164        pmSpan *span = footprint->spans->data[j];
     
    160168        float dX1 = span->x1 - peak->xf;
    161169
    162         radius = PS_MAX (radius, hypot(dY, dX0));
    163         radius = PS_MAX (radius, hypot(dY, dX1));
    164     }
    165 
    166     radius += EXT_FIT_PADDING;
    167     if (isnan(radius)) psAbort("error in radius");
    168 
    169     radius = PS_MIN (radius, EXT_FIT_MAX_RADIUS);
     170        rawRadius = PS_MAX (rawRadius, hypot(dY, dX0));
     171        rawRadius = PS_MAX (rawRadius, hypot(dY, dX1));
     172    }
     173    if (isnan(rawRadius)) return false;
     174    rawRadius = PS_MIN (factor*rawRadius + EXT_FIT_PADDING, EXT_FIT_MAX_RADIUS);
    170175
    171176    // redefine the pixels if needed
    172     pmSourceRedefinePixels (source, readout, peak->xf, peak->yf, radius);
    173 
    174     // set the mask to flag the excluded pixels
    175     psImageKeepCircle (source->maskObj, peak->xf, peak->yf, radius, "OR", markVal);
    176     return radius;
    177 
    178 escape:
    179     return NAN;
    180     // bool result = psphotCheckRadiusEXT (readout, source, model, markVal);
    181     // return result;
     177    pmSourceRedefinePixels (source, readout, peak->xf, peak->yf, rawRadius);
     178
     179    // set the mask to flag the excluded pixels
     180    psImageKeepCircle (source->maskObj, peak->xf, peak->yf, rawRadius, "OR", markVal);
     181
     182    *radius = rawRadius;
     183    return true;
    182184}
    183185
    184186// alternative EXT radius based on model guess (for use without footprints)
    185 bool psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal) {
    186 
    187     psAbort ("do not use this function");
     187bool psphotSetRadiusModel (pmModel *model, pmReadout *readout, pmSource *source, psImageMaskType markVal, bool deep) {
    188188
    189189    psF32 *PAR = model->params->data.F32;
     
    193193
    194194    // set the fit radius based on the object flux limit and the model
    195     float rawRadius = model->modelRadius (model->params, EXT_FIT_NSIGMA*moments->dSky);
    196 
    197     model->fitRadius = rawRadius + EXT_FIT_PADDING;
    198     if (isnan(model->fitRadius)) psAbort("error in radius");
     195    float flux = deep ? EXT_FIT_NSIGMA*EXT_FIT_SKY_SIG : 0.1 * model->params->data.F32[PM_PAR_I0];
     196
     197    float rawRadius = model->modelRadius (model->params, flux);
     198    if (isnan(rawRadius)) return false;
     199
     200    rawRadius = PS_MIN (rawRadius + EXT_FIT_PADDING, EXT_FIT_MAX_RADIUS);
     201    model->fitRadius = rawRadius;
    199202
    200203    // redefine the pixels if needed
    201     bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius);
     204    pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius);
    202205
    203206    // set the mask to flag the excluded pixels
    204207    psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius, "OR", markVal);
    205     return status;
    206 }
     208    return true;
     209}
  • branches/sc_branches/trunkTest/psphot/src/psphotReadout.c

    r28398 r29060  
    5353    }
    5454
    55     // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are determined and saved on
    56     // readout->analysis XXX this function currently only works with a single PSPHOT.INPUT
     55    // load the psf model, if suppled.  FWHM_MAJ,FWHM_MIN,etc are determined and saved on
     56    // readout->analysis. XXX Note: this function currently only works with a single
     57    // PSPHOT.INPUT
    5758    if (!psphotLoadPSF (config, view)) { // ??? need to supply 2 ?
    5859        psError (PSPHOT_ERR_UNKNOWN, false, "error loading psf model");
  • branches/sc_branches/trunkTest/psphot/src/psphotSetThreads.c

    r26894 r29060  
    1515    psFree(task);
    1616
    17     task = psThreadTaskAlloc("PSPHOT_PSF_WEIGHTS", 2);
     17    task = psThreadTaskAlloc("PSPHOT_PSF_WEIGHTS", 3);
    1818    task->function = &psphotPSFWeights_Threaded;
    1919    psThreadTaskAdd(task);
     
    3030    psFree(task);
    3131
    32     task = psThreadTaskAlloc("PSPHOT_BLEND_FIT", 9);
     32    task = psThreadTaskAlloc("PSPHOT_BLEND_FIT", 10);
    3333    task->function = &psphotBlendFit_Threaded;
     34    psThreadTaskAdd(task);
     35    psFree(task);
     36
     37    task = psThreadTaskAlloc("PSPHOT_EXTENDED_FIT", 12);
     38    task->function = &psphotExtendedSourceFits_Threaded;
    3439    psThreadTaskAdd(task);
    3540    psFree(task);
  • branches/sc_branches/trunkTest/psphot/src/psphotSignificanceImage.c

    r28667 r29060  
    9797                smooth_im->data.F32[j][i] = 0.0;
    9898            } else {
    99                 smooth_im->data.F32[j][i] = factor * PS_SQR(value) / smooth_wt->data.F32[j][i];
     99                float v2 = value + PS_SQR(value/1000.0);
     100                smooth_im->data.F32[j][i] = factor * PS_SQR(v2) / smooth_wt->data.F32[j][i];
    100101            }
    101102        }
  • branches/sc_branches/trunkTest/psphot/src/psphotSourceFits.c

    r26894 r29060  
    22
    33// given a source with an existing modelPSF, attempt a full PSF fit, subtract if successful
    4 // XXX this function does not call pmSourceFitModelInit : fix this?
    54
    65static int NfitPSF = 0;
     
    87static int NfitDBL = 0;
    98static int NfitEXT = 0;
     9static int NfitPCM = 0;
    1010
    1111bool psphotFitInit (int nThreads) {
     
    1818
    1919    psLogMsg ("psphot.pspsf", PS_LOG_INFO, "fitted %5d psf, %5d blend, %5d ext, %5d dbl : %6.2f sec\n",
    20              NfitPSF, NfitBlend, NfitEXT, NfitDBL, psTimerMark ("psphot.fits"));
    21     return true;
    22 }
    23 
    24 bool psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal) {
     20              NfitPSF, NfitBlend, NfitEXT, NfitDBL, psTimerMark ("psphot.fits"));
     21    return true;
     22}
     23
     24bool psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
    2525
    2626    float x, y, dR;
     27
     28    pmSourceFitOptions options = *fitOptions;
    2729
    2830    // maskVal is used to test for rejected pixels, and must include markVal
     
    3133    // if this source is not a possible blend, just fit as PSF
    3234    if ((source->blends == NULL) || (source->mode & PM_SOURCE_MODE_SATSTAR)) {
    33         bool status = psphotFitPSF (readout, source, psf, maskVal, markVal);
     35        bool status = psphotFitPSF (readout, source, psf, fitOptions, maskVal, markVal);
    3436        return status;
    3537    }
     
    9193
    9294    // fit PSF model
    93     pmSourceFitSet (source, modelSet, PM_SOURCE_FIT_PSF, maskVal);
     95    options.mode = PM_SOURCE_FIT_PSF;
     96    pmSourceFitSet (source, modelSet, &options, maskVal);
    9497
    9598    // clear the circular mask
     
    154157}
    155158
    156 bool psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal) {
     159bool psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
    157160
    158161    double chiTrend;
     162    pmSourceFitOptions options = *fitOptions;
    159163
    160164    // maskVal is used to test for rejected pixels, and must include markVal
     
    171175
    172176    // fit PSF model (set/unset the pixel mask)
    173     pmSourceFitModel (source, PSF, PM_SOURCE_FIT_PSF, maskVal);
     177    options.mode = PM_SOURCE_FIT_PSF;
     178    pmSourceFitModel (source, PSF, &options, maskVal);
    174179
    175180    if (!isfinite(PSF->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
     
    199204}
    200205
     206// save a local, static copy of the EXT model type so we don't have to lookup for each object
    201207static pmModelType modelTypeEXT;
    202208
    203 bool psphotInitLimitsEXT (psMetadata *recipe) {
     209bool psphotInitLimitsEXT (psMetadata *recipe, pmReadout *readout) {
    204210
    205211    bool status;
     
    208214    char *modelNameEXT = psMetadataLookupStr (&status, recipe, "EXT_MODEL");
    209215    modelTypeEXT = pmModelClassGetType (modelNameEXT);
    210     psphotInitRadiusEXT (recipe, modelTypeEXT);
    211 
    212     return true;
    213 }
    214 
    215 bool psphotFitBlob (pmReadout *readout, pmSource *source, psArray *newSources, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal) {
    216 
     216
     217    psphotInitRadiusEXT (recipe, readout);
     218
     219    return true;
     220}
     221
     222bool psphotFitBlob (pmReadout *readout, pmSource *source, psArray *newSources, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
     223
     224    float radius;
    217225    bool okEXT, okDBL;
    218226    float chiEXT, chiDBL;
     
    222230    pmModel *EXT = NULL;
    223231    psArray *DBL = NULL;
     232    pmMoments psfMoments;
    224233
    225234    // skip the source if we don't think it is extended
     235    // XXX are these robust, or do we have better info from the source-size analysis??
    226236    if (source->type == PM_SOURCE_TYPE_UNKNOWN) return false;
    227237    if (source->type == PM_SOURCE_TYPE_DEFECT) return false;
     
    229239
    230240    // set the radius based on the footprint (also sets the mask pixels)
    231     float radius = psphotSetRadiusEXT (readout, source, markVal);
     241    if (!psphotSetRadiusFootprint(&radius, readout, source, markVal, 1.0)) return false;
    232242
    233243    // XXX note that this changes the source moments that are published...
     244    // XXX all published moments should use the same measurement
    234245    // recalculate the source moments using the larger extended-source moments radius
    235246    // at this stage, skip Gaussian windowing, and do not clip pixels by S/N
    236247    // this uses the footprint to judge both radius and aperture?
    237     if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) return false;
     248    // XXX save the psf-based moments for output
     249    psfMoments = *source->moments;
     250    if (!pmSourceMoments (source, radius, 0.0, 0.5, maskVal)) {
     251      *source->moments = psfMoments;
     252      return false;
     253    }
    238254
    239255    psTrace ("psphot", 5, "trying blob...\n");
     
    244260    // this temporary source is used as a place-holder by the psphotEval functions below
    245261    tmpSrc = pmSourceAlloc ();
    246 
    247     // XXX need to handle failures better here
    248     EXT = psphotFitEXT (readout, source, modelTypeEXT, maskVal, markVal);
    249     if (!EXT) goto escape;
    250     if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) goto escape;
    251 
    252     okEXT = psphotEvalEXT (tmpSrc, EXT);
    253     chiEXT = EXT ? EXT->chisq / EXT->nDOF : NAN;
    254 
    255     // DBL will always be defined, but DBL->data[n] might not
    256     DBL = psphotFitDBL (readout, source, maskVal, markVal);
    257     if (!DBL) goto escape;
    258     if (!DBL->n) goto escape;
    259 
    260     okDBL  = psphotEvalDBL (tmpSrc, DBL->data[0]);
    261     okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]);
    262     // XXX should I keep / save the flags set in the eval functions?
     262    {
     263        // DBL will always be defined, but DBL->data[n] might not
     264        DBL = psphotFitDBL (readout, source, fitOptions, maskVal, markVal);
     265        if (!DBL) goto escape;
     266        if (!DBL->n) goto escape;
     267
     268        okDBL  = psphotEvalDBL (tmpSrc, DBL->data[0]);
     269        okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]);
     270        // XXX should I keep / save the flags set in the eval functions?
     271
     272        // correct first model chisqs for flux trend
     273        chiDBL = NAN;
     274        ONE = DBL->data[0];
     275        if (ONE) {
     276            if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
     277            chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
     278            ONE->chisqNorm = ONE->chisq / chiTrend;
     279            chiDBL = ONE->chisq / ONE->nDOF; // save chisq for double-star/galaxy comparison
     280            ONE->fitRadius = radius;
     281        }
     282
     283        // correct second model chisqs for flux trend
     284        ONE = DBL->data[1];
     285        if (ONE) {
     286            if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
     287            chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
     288            ONE->chisqNorm = ONE->chisq / chiTrend;
     289            ONE->fitRadius = radius;
     290        }
     291    }
     292
     293    {
     294        // XXX need to handle failures better here
     295        EXT = psphotFitEXT (readout, source, fitOptions, modelTypeEXT, maskVal, markVal);
     296        if (!EXT) goto escape;
     297        if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) goto escape;
     298
     299        okEXT = psphotEvalEXT (tmpSrc, EXT);
     300        chiEXT = EXT ? EXT->chisq / EXT->nDOF : NAN;
     301    }
    263302
    264303    // clear the circular mask
    265304    psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
    266 
    267     // correct first model chisqs for flux trend
    268     chiDBL = NAN;
    269     ONE = DBL->data[0];
    270     if (ONE) {
    271         if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
    272       chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
    273       ONE->chisqNorm = ONE->chisq / chiTrend;
    274       chiDBL = ONE->chisq / ONE->nDOF; // save chisq for double-star/galaxy comparison
    275     }
    276 
    277     // correct second model chisqs for flux trend
    278     ONE = DBL->data[1];
    279     if (ONE) {
    280         if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
    281       chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
    282       ONE->chisqNorm = ONE->chisq / chiTrend;
    283     }
    284305
    285306    psFree (tmpSrc);
     
    298319
    299320    // both models failed; reject them both
    300     // XXX -- change type flags to psf in this case and keep original moments?
     321    // XXX -- change type flags to psf in this case, and make sure we subtract it?
     322    // reset the psf moments
     323    *source->moments = psfMoments;
     324
    301325    psFree (EXT);
    302326    psFree (DBL);
     
    308332
    309333    // save new model
     334    // XXX save the correct radius...
    310335    source->modelEXT = EXT;
    311     source->modelEXT->fitRadius = radius;
    312336    source->type = PM_SOURCE_TYPE_EXTENDED;
    313337    source->mode |= PM_SOURCE_MODE_EXTMODEL;
     
    327351# endif
    328352
     353    // reset the psf moments
     354    *source->moments = psfMoments;
    329355    return true;
    330356
     
    337363    source->modelPSF = psMemIncrRefCounter (DBL->data[0]);
    338364    source->mode     |= PM_SOURCE_MODE_PAIR;
    339     source->modelPSF->fitRadius = radius;
    340365
    341366    // copy most data from the primary source (modelEXT, blends stay NULL)
    342     pmSource *newSrc = pmSourceCopy (source);
     367    pmSource *newSrc = pmSourceCopyData (source);
    343368    newSrc->modelPSF = psMemIncrRefCounter (DBL->data[1]);
    344     newSrc->modelPSF->fitRadius = radius;
    345369
    346370    // build cached models and subtract
     
    365389# endif
    366390
     391    // reset the (original) psf moments
     392    *source->moments = psfMoments;
     393    *newSrc->moments = psfMoments;
     394
    367395    psArrayAdd (newSources, 100, newSrc);
    368396    psFree (newSrc);
     
    371399
    372400escape:
     401    // reset the psf moments
     402    *source->moments = psfMoments;
    373403    psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
    374404    psFree (tmpSrc);
     
    379409
    380410// fit a double PSF source to an extended blob
    381 psArray *psphotFitDBL (pmReadout *readout, pmSource *source, psImageMaskType maskVal, psImageMaskType markVal) {
     411psArray *psphotFitDBL (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
    382412
    383413    float dx, dy;
     
    387417    psEllipseMoments moments;
    388418    psArray *modelSet;
     419
     420    pmSourceFitOptions options = *fitOptions;
    389421
    390422    NfitDBL ++;
     
    403435    axes = psEllipseMomentsToAxes (moments, 20.0);
    404436
     437    if (isnan(axes.major)) return NULL;
     438    if (isnan(axes.minor)) return NULL;
     439    if (isnan(axes.theta)) return NULL;
     440
    405441    // XXX this is really arbitrary: 4 pixel separation?
    406442    dx = 2 * cos (axes.theta);
     
    426462
    427463    // fit PSF model (set/unset the pixel mask)
    428     pmSourceFitSet (source, modelSet, PM_SOURCE_FIT_PSF, maskVal);
     464    options.mode = PM_SOURCE_FIT_PSF;
     465    pmSourceFitSet (source, modelSet, &options, maskVal);
    429466    return (modelSet);
    430467}
    431468
    432 pmModel *psphotFitEXT (pmReadout *readout, pmSource *source, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal) {
     469pmModel *psphotFitEXT (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal) {
     470
     471    if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) {
     472        psTrace ("psphot", 5, "problem source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
     473    }
     474
     475    pmSourceFitOptions options = *fitOptions;
    433476
    434477    NfitEXT ++;
     
    438481
    439482    // use the source moments, etc to guess basic model parameters
    440     pmModel *EXT = pmSourceModelGuess (source, modelType);
    441     if (!EXT) {
     483    pmModel *model = pmSourceModelGuess (source, modelType);
     484    if (!model) {
    442485        psTrace ("psphot", 5, "failed to generate a model for source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
    443486        return NULL;
    444487    }
    445488
     489    // for sersic models, use a grid search to choose an index, then float the params there
     490    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
     491        // for the test fits, use a somewhat smaller radius
     492        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     493        psphotFitSersicIndex (model, readout, source, fitOptions, maskVal, markVal);
     494    }
     495
     496    if (!psphotSetRadiusModel (model, readout, source, markVal, true)) {
     497        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 1.0);
     498    }
     499
     500    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
     501        options.mode = PM_SOURCE_FIT_NO_INDEX;
     502    } else {
     503        options.mode = PM_SOURCE_FIT_EXT;
     504    }
     505
     506    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
     507    pmSourceFitModel (source, model, &options, maskVal);
     508    // fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
     509
     510    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0);
     511    return (model);
     512}
     513
     514pmModel *psphotFitPCM (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     515
    446516    if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) {
    447517        psTrace ("psphot", 5, "problem source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
    448518    }
    449519
     520    pmSourceFitOptions options = *fitOptions;
     521
     522    NfitPCM ++;
     523
     524    // maskVal is used to test for rejected pixels, and must include markVal
     525    maskVal |= markVal;
     526
     527    // allocate the model
     528    pmModel *model = pmModelAlloc(modelType);
     529    if (!model) {
     530        return NULL;
     531    }
     532
     533    pmPCMdata *pcm = pmPCMinit (source, &options, model, maskVal, psfSize);
     534    if (!pcm) {
     535        psTrace ("psphot", 5, "failed to generate a model for source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
     536        model->flags |= PM_MODEL_STATUS_BADARGS; // XXX this is probably already set in pmPCMinit
     537        return model;
     538    }
     539
     540    // use the source moments, etc to guess basic model parameters
     541    if (!pmSourceModelGuessPCM (pcm, source, maskVal, markVal)) {
     542        psFree (pcm);
     543        model->flags |= PM_MODEL_STATUS_BADARGS;
     544        return model;
     545    }
     546
     547    // for sersic models, use a grid search to choose an index, then float the params there
     548    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
     549        // for the test fits, use a somewhat smaller radius
     550        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     551
     552        if (!psphotFitSersicIndexPCM (pcm, readout, source, fitOptions, maskVal, markVal, psfSize)) {
     553            model->flags |= PM_MODEL_STATUS_BADARGS;
     554            return model;
     555        }
     556    }
     557
     558    if (!psphotSetRadiusModel (model, readout, source, markVal, true)) {
     559        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 1.0);
     560    }
     561
     562    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
     563        options.mode = PM_SOURCE_FIT_NO_INDEX;
     564    } else {
     565        options.mode = PM_SOURCE_FIT_EXT;
     566    }
     567    // update the pcm elements if we have changed the circumstance (options.mode or source->pixels)
     568    pmPCMupdate(pcm, source, &options, model);
     569
     570    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
     571    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     572    // fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
     573
     574    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0);
     575    psFree (pcm);
     576
     577    return model;
     578}
     579
     580// note that these should be 1/2n of the standard sersic index
     581float indexGuess[] = {0.5, 0.33, 0.25, 0.167, 0.125, 0.083};
     582# define N_INDEX_GUESS 6
     583
     584// A sersic model is very sensitive to the index.  attempt to find the index first by grid search in just the index
     585// for a sersic model, attempt to fit just the index and normalization with a modest number of iterations
     586bool psphotFitSersicIndex (pmModel *model, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
     587
     588    assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     589
     590    pmSourceFitOptions options = *fitOptions;
     591   
    450592    // fit EXT (not PSF) model (set/unset the pixel mask)
    451     pmSourceFitModel (source, EXT, PM_SOURCE_FIT_EXT, maskVal);
    452     return (EXT);
    453 }
     593    options.mode = PM_SOURCE_FIT_NO_INDEX;
     594    options.nIter = 4;
     595
     596    int iMin = -1;
     597    float xMin = NAN;
     598    float chiSquare[N_INDEX_GUESS];
     599
     600    for (int i = 0; i < N_INDEX_GUESS; i++) {
     601        model->params->data.F32[PM_PAR_7] = indexGuess[i];
     602
     603        if (!model->modelGuess(model, source)) {
     604            model->flags |= PM_MODEL_STATUS_BADARGS;
     605            return false;
     606        }
     607
     608        // each time we change the model guess, we need to adjust the radius
     609        // XXX this did not work : we do not need such a large radius -- just uses moments-based radius
     610        if (false && !psphotSetRadiusModel (model, readout, source, markVal, false)) {
     611            psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     612        }
     613       
     614        pmSourceFitModel (source, model, &options, maskVal);
     615        // fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
     616
     617        chiSquare[i] = model->chisqNorm;
     618        if (i == 0) {
     619            xMin = chiSquare[i];
     620            iMin = i;
     621        } else {
     622            if (chiSquare[i] < xMin) {
     623                xMin = chiSquare[i];
     624                iMin = i;
     625            }
     626        }
     627    }
     628    assert (iMin >= 0);
     629
     630    model->flags = PM_MODEL_STATUS_NONE; // do not attempt to handle failures here, let the next iteration deal with it
     631    model->params->data.F32[PM_PAR_7] = indexGuess[iMin];
     632    model->modelGuess(model, source);
     633
     634    // each time we change the model guess, we need to adjust the radius
     635    // if (!psphotSetRadiusModel (model, readout, source, markVal, true)) {
     636    //  psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal);
     637    // }
     638
     639    return true;
     640}
     641
     642// A sersic model is very sensitive to the index.  attempt to find the index first by grid search in just the index
     643// for a sersic model, attempt to fit just the index and normalization with a modest number of iterations
     644bool psphotFitSersicIndexPCM (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     645
     646    pmModel *model = pcm->modelConv;
     647
     648    assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     649
     650    pmSourceFitOptions options = *fitOptions;
     651   
     652    // fit EXT (not PSF) model (set/unset the pixel mask)
     653    options.mode = PM_SOURCE_FIT_NO_INDEX;
     654    options.nIter = 4;
     655
     656    // update the pcm elements if we have changed the circumstance (here, options.mode)
     657    pmPCMupdate(pcm, source, &options, model);
     658
     659    int iMin = -1;
     660    float xMin = NAN;
     661    float chiSquare[N_INDEX_GUESS];
     662
     663    for (int i = 0; i < N_INDEX_GUESS; i++) {
     664        model->params->data.F32[PM_PAR_7] = indexGuess[i];
     665       
     666        if (!model->modelGuess(model, source)) {
     667            model->flags |= PM_MODEL_STATUS_BADARGS;
     668            return false;
     669        }
     670
     671        // each time we change the model guess, we need to adjust the radius
     672        // XXX this did not work : we do not need such a large radius -- just uses moments-based radius
     673        if (false && !psphotSetRadiusModel (model, readout, source, markVal, false)) {
     674            psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     675        }
     676       
     677# if (0)
     678        pmSourceFitModel (source, model, &options, maskVal);
     679# else
     680        pmSourceModelGuessPCM(pcm, source, maskVal, markVal);
     681        pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     682# endif
     683        // fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
     684
     685        chiSquare[i] = model->chisq;
     686        if (i == 0) {
     687            xMin = chiSquare[i];
     688            iMin = i;
     689        } else {
     690            if (chiSquare[i] < xMin) {
     691                xMin = chiSquare[i];
     692                iMin = i;
     693            }
     694        }
     695    }
     696    assert (iMin >= 0);
     697   
     698    model->flags = PM_MODEL_STATUS_NONE; // do not attempt to handle failures here, let the next iteration deal with it
     699    model->params->data.F32[PM_PAR_7] = indexGuess[iMin];
     700
     701    pmSourceModelGuessPCM(pcm, source, maskVal, markVal);
     702
     703    return true;
     704}
  • branches/sc_branches/trunkTest/psphot/src/psphotSourceSize.c

    r28013 r29060  
    11# include "psphotInternal.h"
    22# include <gsl/gsl_sf_gamma.h>
     3
     4# define KRON 1
    35
    46typedef struct {
     
    168170    psVector *ApErr = psVectorAllocEmpty (100, PS_TYPE_F32);
    169171
     172    psImageMaskType markVal = options->markVal;
    170173    psImageMaskType maskVal = options->maskVal | options->markVal;
    171174
     
    189192
    190193        // XXX can we test if psfMag is set and calculate only if needed?
    191         pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal
     194        pmSourceMagnitudes (source, psf, photMode, maskVal, markVal);
    192195
    193196        // clear the mask bit
     
    197200        pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal);
    198201
     202        // XXX test: switch to kron flux
     203# if (KRON)
     204        float apMag = -2.5*log10(source->moments->KronFlux);
     205# else
    199206        float apMag = -2.5*log10(source->moments->Sum);
     207# endif
    200208        float dMag = source->psfMag - apMag;
    201209
     
    288296    pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_WEIGHT;
    289297
     298    psImageMaskType markVal = options->markVal;
    290299    psImageMaskType maskVal = options->maskVal | options->markVal;
    291300
     
    335344
    336345        // XXX can we test if psfMag is set and calculate only if needed?
    337         pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal
     346        pmSourceMagnitudes (source, psf, photMode, maskVal, markVal);
    338347
    339348        // clear the mask bit
     
    343352        pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal);
    344353
     354# if (KRON)
     355        float apMag = -2.5*log10(source->moments->KronFlux);
     356# else
    345357        float apMag = -2.5*log10(source->moments->Sum);
     358# endif
    346359        float dMag = source->psfMag - apMag;
    347360
    348361        // set nSigma to include both systematic and poisson error terms
    349362        // XXX the 'poisson error' contribution for size is probably wrong...
    350         float nSigmaMAG = (dMag - options->ApResid) / hypot(source->errMag, options->ApSysErr);
     363        // XXX add in a hard floor on the Ap Sys Err (to be a bit generous)
     364        float nSigmaMAG = (dMag - options->ApResid) / hypot(source->errMag, hypot(options->ApSysErr, 0.025));
    351365        float nSigmaMXX = (Mxx - psfClump->X) / hypot(psfClump->dX, psfClump->X*psfClump->X*source->errMag);
    352366        float nSigmaMYY = (Myy - psfClump->Y) / hypot(psfClump->dY, psfClump->Y*psfClump->Y*source->errMag);
    353367
    354         // partially-masked sources are more likely to be mis-measured PSFs
     368        // fprintf (stderr, "%f %f : Mxx: %f, Myy: %f, dx: %f, dy: %f, psfMag: %f, apMag: %f, dMag: %f, errMag: %f, nSigmaMag: %f, nSigmaMxx: %f, nSigmaMyy: %f\n",
     369        // source->peak->xf, source->peak->yf, Mxx, Myy, source->peak->xf - source->moments->Mx, source->peak->yf - source->moments->My,
     370        // source->psfMag, apMag, dMag, source->errMag, nSigmaMAG, nSigmaMXX, nSigmaMYY);
     371
     372        // XXX double check on ths stuff!! partially-masked sources are more likely to be mis-measured PSFs
    355373        float sizeBias = 1.0;
    356         if (source->pixWeight < 0.9) {
     374        if (source->pixWeightNotBad < 0.9) {
     375            sizeBias = 3.0;
     376        }
     377        if (source->pixWeightNotPoor < 0.9) {
    357378            sizeBias = 3.0;
    358379        }
     
    389410        if (isCR) {
    390411            psTrace("psphotSourceClassRegion.CR",4,"CLASS: %g %g %f\t%g %g  %g %g  %g %g\t%g %g\t%g CR\t%g %g\n",
    391                     source->peak->xf,source->peak->yf,source->pixWeight,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG,
     412                    source->peak->xf,source->peak->yf,source->pixWeightNotBad,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG,
    392413                    options->nSigmaApResid,sizeBias*options->nSigmaMoments);
    393414            source->mode |= PM_SOURCE_MODE_DEFECT;
  • branches/sc_branches/trunkTest/psphot/src/psphotSourceStats.c

    r28419 r29060  
    11# include "psphotInternal.h"
     2void pmSourceMomentsSetVerbose(bool state);
    23
    34// convert detections to sources and measure their basic properties (moments, local sky, sky
     
    369370    maskVal |= markVal;
    370371
     372    // XXX test : pmSourceMomentsSetVerbose(true);
     373
    371374    // threaded measurement of the sources moments
    372375    int Nfail = 0;
     
    408411        // measure basic source moments (no S/N clipping on input pixels)
    409412        status = pmSourceMoments (source, RADIUS, SIGMA, 0.0, maskVal);
     413        // XXX moments / aperture test:
     414        if (0) {
     415            // clear the mask bit and set the circular mask pixels
     416            psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
     417            psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, 4.0*source->moments->Mrf, "OR", markVal);
     418           
     419            float apMag = NAN;
     420            pmSourcePhotometryAper (&apMag, NULL, source->pixels, source->maskObj, maskVal);
     421            fprintf (stderr, "apMag: %f, kronMag: %f\n", apMag, -2.5*log10(source->moments->KronFlux));
     422
     423            // clear the mask bit
     424            psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
     425        }           
    410426        if (status) {
    411427            Nmoments ++;
     
    502518        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
    503519        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
    504         psphotVisualPlotMoments (recipe, analysis, sources);
     520        if (pmVisualTestLevel("psphot.moments.full", 2)) {
     521            psphotVisualPlotMoments (recipe, analysis, sources);
     522        }
    505523#endif
    506524
  • branches/sc_branches/trunkTest/psphot/src/psphotStack.c

    r27547 r29060  
    2424        exit (psphotGetExitStatus());
    2525    }
     26    // Dump configuration
     27    bool mdok;
     28    psString dump = psMetadataLookupStr(&mdok, config->arguments, "DUMP_CONFIG"); // File for config
     29    if (dump && !pmConfigDump(config, dump)) {
     30        psError(psErrorCodeLast(), false, "Unable to dump configuration.");
     31        exit (psphotGetExitStatus());
     32    }
     33
     34
    2635
    2736    psLogMsg ("psphot", 3, "complete psphot run: %f sec\n", psTimerMark ("complete"));
  • branches/sc_branches/trunkTest/psphot/src/psphotStackMatchPSFsUtils.c

    r28013 r29060  
    346346    if (!fake) goto escape;
    347347
    348     dumpImage(fake, readoutSrc, index, "fake");
    349     dumpImage(readoutSrc,  readoutSrc, index, "real");
     348    // dumpImage(fake, readoutSrc, index, "fake");
     349    // dumpImage(readoutSrc,  readoutSrc, index, "real");
    350350
    351351    if (threads) pmSubtractionThreadsInit();
     
    380380    }
    381381
    382     dumpImage(readoutOut, readoutSrc, index, "conv");
    383     dumpImageDiff(readoutOut, fake, readoutSrc, index, "diff");
     382    // dumpImage(readoutOut, readoutSrc, index, "conv");
     383    // dumpImageDiff(readoutOut, fake, readoutSrc, index, "diff");
    384384
    385385    psFree(fake);
  • branches/sc_branches/trunkTest/psphot/src/psphotVisual.c

    r28128 r29060  
    6666    int myKapa = psphotKapaChannel (channel);
    6767    if (!(strcasecmp (overlay, "all"))) {
    68       KiiEraseOverlay (myKapa, "red");
    69       KiiEraseOverlay (myKapa, "green");
    70       KiiEraseOverlay (myKapa, "blue");
    71       KiiEraseOverlay (myKapa, "yellow");
    72       return true;
     68        KiiEraseOverlay (myKapa, "red");
     69        KiiEraseOverlay (myKapa, "green");
     70        KiiEraseOverlay (myKapa, "blue");
     71        KiiEraseOverlay (myKapa, "yellow");
     72        return true;
    7373    }
    7474    KiiEraseOverlay (myKapa, overlay);
     
    182182bool psphotVisualShowImage (pmReadout *readout) {
    183183
    184     if (!pmVisualIsVisual()) return true;
     184    if (!pmVisualTestLevel("psphot.image", 1)) return true;
    185185
    186186    int kapa = psphotKapaChannel (1);
     
    199199    pmReadout *backgnd;
    200200
    201     if (!DEBUG && !pmVisualIsVisual()) return true;
     201    if (!pmVisualTestLevel("psphot.image.backgnd", 2)) return true;
    202202
    203203    int kapa = psphotKapaChannel (1);
     
    208208
    209209    if (file->mode == PM_FPA_MODE_INTERNAL) {
    210         backgnd = file->readout;
     210        backgnd = file->readout;
    211211    } else {
    212         backgnd = pmFPAviewThisReadout (view, file->fpa);
     212        backgnd = pmFPAviewThisReadout (view, file->fpa);
    213213    }
    214214
     
    222222bool psphotVisualShowSignificance (psImage *image, float min, float max) {
    223223
    224     if (!DEBUG && !pmVisualIsVisual()) return true;
     224    if (!pmVisualTestLevel("psphot.image.signif", 2)) return true;
    225225
    226226    int kapa = psphotKapaChannel (1);
     
    233233}
    234234
     235bool psphotVisualShowLogSignificance (psImage *image, float min, float max) {
     236
     237    if (!pmVisualTestLevel("psphot.image.logsignif", 3)) return true;
     238
     239    int kapa = psphotKapaChannel (1);
     240    if (kapa == -1) return false;
     241
     242    psImage *lsig = (psImage *) psUnaryOp (NULL, image, "log");
     243    psphotVisualRangeImage (kapa, lsig, "log-signif", 2, min, max);
     244    psFree (lsig);
     245
     246    pmVisualAskUser(NULL);
     247    return true;
     248}
     249
     250// XXX : requires psphotVisualShowImage
    235251bool psphotVisualShowPeaks (pmDetections *detections) {
    236252
     
    238254    KiiOverlay *overlay;
    239255
    240     if (!DEBUG && !pmVisualIsVisual()) return true;
     256    if (!pmVisualTestLevel("psphot.objects.peaks", 1)) return true;
    241257
    242258    int kapa = psphotKapaChannel (1);
     
    252268    for (int i = 0; i < peaks->n; i++) {
    253269
    254         pmPeak *peak = peaks->data[i];
    255         if (peak == NULL) continue;
    256 
    257         overlay[Noverlay].type = KII_OVERLAY_BOX;
    258         overlay[Noverlay].x = peak->xf;
    259         overlay[Noverlay].y = peak->yf;
    260         overlay[Noverlay].dx = 2.0;
    261         overlay[Noverlay].dy = 2.0;
    262         overlay[Noverlay].angle = 0.0;
    263         overlay[Noverlay].text = NULL;
    264         Noverlay ++;
     270        pmPeak *peak = peaks->data[i];
     271        if (peak == NULL) continue;
     272
     273        overlay[Noverlay].type = KII_OVERLAY_BOX;
     274        overlay[Noverlay].x = peak->xf;
     275        overlay[Noverlay].y = peak->yf;
     276        overlay[Noverlay].dx = 2.0;
     277        overlay[Noverlay].dy = 2.0;
     278        overlay[Noverlay].angle = 0.0;
     279        overlay[Noverlay].text = NULL;
     280        Noverlay ++;
    265281    }
    266282
     
    272288}
    273289
     290// XXX : requires psphotVisualShowImage
    274291bool psphotVisualShowFootprints (pmDetections *detections) {
    275292
     
    277294    KiiOverlay *overlay;
    278295
    279     if (!DEBUG && !pmVisualIsVisual()) return true;
     296    if (!pmVisualTestLevel("psphot.objects.footprints", 3)) return true;
    280297
    281298    int kapa = psphotKapaChannel (1);
     
    292309    for (int i = 0; i < footprints->n; i++) {
    293310
    294         pmSpan *span = NULL;
    295 
    296         pmFootprint *footprint = footprints->data[i];
    297         if (footprint == NULL) continue;
    298         if (footprint->spans == NULL) continue;
    299         if (footprint->spans->n < 1) continue;
    300 
    301         // draw the top
    302         // XXX need to allow top (and bottom) to have more than one span
    303         span = footprint->spans->data[0];
    304         overlay[Noverlay].type = KII_OVERLAY_LINE;
    305         overlay[Noverlay].x = span->x0;
    306         overlay[Noverlay].y = span->y;
    307         overlay[Noverlay].dx = span->x1 - span->x0;
    308         overlay[Noverlay].dy = 0;
    309         overlay[Noverlay].angle = 0.0;
    310         overlay[Noverlay].text = NULL;
    311         Noverlay ++;
    312         CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    313 
    314         int ys = span->y;
    315         int x0s = span->x0;
    316         int x1s = span->x1;
    317 
    318         // draw the outer span edges
    319         for (int j = 1; j < footprint->spans->n; j++) {
    320             pmSpan *span1 = footprint->spans->data[j];
    321 
    322             int ye = span1->y;
    323             int x0e = span1->x0;
    324             int x1e = span1->x1;
    325 
    326             // we cannot have two discontinuous spans on the top or bottom, right? (no, probably not right)
    327             // find all of the spans in this row and generate x0e, x01:
    328             for (int k = j + 1; k < footprint->spans->n; k++) {
    329                 pmSpan *span2 = footprint->spans->data[k];
    330                 if (span2->y > span1->y) break;
    331                 x0e = PS_MIN (x0e, span2->x0);
    332                 x1e = PS_MAX (x1e, span2->x1);
    333                 j++;
    334             }
    335 
    336             overlay[Noverlay].type = KII_OVERLAY_LINE;
    337             overlay[Noverlay].x = x0s;
    338             overlay[Noverlay].y = ys;
    339             overlay[Noverlay].dx = x0e - x0s;
    340             overlay[Noverlay].dy = ye - ys;
    341             overlay[Noverlay].angle = 0.0;
    342             overlay[Noverlay].text = NULL;
    343             Noverlay ++;
    344             CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    345 
    346             overlay[Noverlay].type = KII_OVERLAY_LINE;
    347             overlay[Noverlay].x = x1s;
    348             overlay[Noverlay].y = ys;
    349             overlay[Noverlay].dx = x1e - x1s;
    350             overlay[Noverlay].dy = ye - ys;
    351             overlay[Noverlay].angle = 0.0;
    352             overlay[Noverlay].text = NULL;
    353             Noverlay ++;
    354             CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    355 
    356             ys = ye;
    357             x0s = x0e;
    358             x1s = x1e;
    359         }
    360 
    361         // draw the bottom
    362         span = footprint->spans->data[footprint->spans->n - 1];
    363         overlay[Noverlay].type = KII_OVERLAY_LINE;
    364         overlay[Noverlay].x = span->x0;
    365         overlay[Noverlay].y = span->y;
    366         overlay[Noverlay].dx = span->x1 - span->x0;
    367         overlay[Noverlay].dy = 0;
    368         overlay[Noverlay].angle = 0.0;
    369         overlay[Noverlay].text = NULL;
    370         Noverlay ++;
    371         CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     311        pmSpan *span = NULL;
     312
     313        pmFootprint *footprint = footprints->data[i];
     314        if (footprint == NULL) continue;
     315        if (footprint->spans == NULL) continue;
     316        if (footprint->spans->n < 1) continue;
     317
     318        // draw the top
     319        // XXX need to allow top (and bottom) to have more than one span
     320        span = footprint->spans->data[0];
     321        overlay[Noverlay].type = KII_OVERLAY_LINE;
     322        overlay[Noverlay].x = span->x0;
     323        overlay[Noverlay].y = span->y;
     324        overlay[Noverlay].dx = span->x1 - span->x0;
     325        overlay[Noverlay].dy = 0;
     326        overlay[Noverlay].angle = 0.0;
     327        overlay[Noverlay].text = NULL;
     328        Noverlay ++;
     329        CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     330
     331        int ys = span->y;
     332        int x0s = span->x0;
     333        int x1s = span->x1;
     334
     335        // draw the outer span edges
     336        for (int j = 1; j < footprint->spans->n; j++) {
     337            pmSpan *span1 = footprint->spans->data[j];
     338
     339            int ye = span1->y;
     340            int x0e = span1->x0;
     341            int x1e = span1->x1;
     342
     343            // we cannot have two discontinuous spans on the top or bottom, right? (no, probably not right)
     344            // find all of the spans in this row and generate x0e, x01:
     345            for (int k = j + 1; k < footprint->spans->n; k++) {
     346                pmSpan *span2 = footprint->spans->data[k];
     347                if (span2->y > span1->y) break;
     348                x0e = PS_MIN (x0e, span2->x0);
     349                x1e = PS_MAX (x1e, span2->x1);
     350                j++;
     351            }
     352
     353            overlay[Noverlay].type = KII_OVERLAY_LINE;
     354            overlay[Noverlay].x = x0s;
     355            overlay[Noverlay].y = ys;
     356            overlay[Noverlay].dx = x0e - x0s;
     357            overlay[Noverlay].dy = ye - ys;
     358            overlay[Noverlay].angle = 0.0;
     359            overlay[Noverlay].text = NULL;
     360            Noverlay ++;
     361            CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     362
     363            overlay[Noverlay].type = KII_OVERLAY_LINE;
     364            overlay[Noverlay].x = x1s;
     365            overlay[Noverlay].y = ys;
     366            overlay[Noverlay].dx = x1e - x1s;
     367            overlay[Noverlay].dy = ye - ys;
     368            overlay[Noverlay].angle = 0.0;
     369            overlay[Noverlay].text = NULL;
     370            Noverlay ++;
     371            CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     372
     373            ys = ye;
     374            x0s = x0e;
     375            x1s = x1e;
     376        }
     377
     378        // draw the bottom
     379        span = footprint->spans->data[footprint->spans->n - 1];
     380        overlay[Noverlay].type = KII_OVERLAY_LINE;
     381        overlay[Noverlay].x = span->x0;
     382        overlay[Noverlay].y = span->y;
     383        overlay[Noverlay].dx = span->x1 - span->x0;
     384        overlay[Noverlay].dy = 0;
     385        overlay[Noverlay].angle = 0.0;
     386        overlay[Noverlay].text = NULL;
     387        Noverlay ++;
     388        CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    372389    }
    373390
     
    379396}
    380397
     398// XXX : requires psphotVisualShowImage
    381399bool psphotVisualShowMoments (psArray *sources) {
    382400
     
    387405    psEllipseAxes axes;
    388406
    389     if (!DEBUG && !pmVisualIsVisual()) return true;
     407    if (!pmVisualTestLevel("psphot.objects.moments", 2)) return true;
    390408
    391409    int kapa = psphotKapaChannel (1);
     
    401419    for (int i = 0; i < sources->n; i++) {
    402420
    403         pmSource *source = sources->data[i];
    404         if (source == NULL) continue;
    405 
    406         pmMoments *moments = source->moments;
    407         if (moments == NULL) continue;
    408 
    409         overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    410         overlay[Noverlay].x = moments->Mx;
    411         overlay[Noverlay].y = moments->My;
    412 
    413         emoments.x2 = moments->Mxx;
    414         emoments.xy = moments->Mxy;
    415         emoments.y2 = moments->Myy;
    416 
    417         axes = psEllipseMomentsToAxes (emoments, 20.0);
    418 
    419         overlay[Noverlay].dx = 2.0*axes.major;
    420         overlay[Noverlay].dy = 2.0*axes.minor;
    421 
    422         overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
    423 
    424         overlay[Noverlay].text = NULL;
    425         Noverlay ++;
     421        pmSource *source = sources->data[i];
     422        if (source == NULL) continue;
     423
     424        pmMoments *moments = source->moments;
     425        if (moments == NULL) continue;
     426
     427        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     428        overlay[Noverlay].x = moments->Mx;
     429        overlay[Noverlay].y = moments->My;
     430
     431        emoments.x2 = moments->Mxx;
     432        emoments.xy = moments->Mxy;
     433        emoments.y2 = moments->Myy;
     434
     435        axes = psEllipseMomentsToAxes (emoments, 20.0);
     436
     437        overlay[Noverlay].dx = 2.0*axes.major;
     438        overlay[Noverlay].dy = 2.0*axes.minor;
     439
     440        overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
     441
     442        overlay[Noverlay].text = NULL;
     443        Noverlay ++;
    426444    }
    427445
     
    439457    KapaSection section;
    440458
    441     if (!DEBUG && !pmVisualIsVisual()) return true;
     459    if (!pmVisualTestLevel("psphot.moments", 1)) return true;
    442460
    443461    int myKapa = psphotKapaChannel (2);
     
    456474    float Ymin = 1000.0, Ymax = 0.0;
    457475    {
    458         int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
    459         for (int n = 0; n < nRegions; n++) {
    460 
    461             char regionName[64];
    462             snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
    463             psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
    464 
    465             float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
    466             float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
    467             float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
    468             float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
    469 
    470             float X0 = psfX - 4.0*psfdX;
    471             float X1 = psfX + 4.0*psfdX;
    472             float Y0 = psfY - 4.0*psfdY;
    473             float Y1 = psfY + 4.0*psfdY;
    474 
    475             if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); }
    476             if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); }
    477             if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); }
    478             if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); }
    479         }
     476        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     477        for (int n = 0; n < nRegions; n++) {
     478
     479            char regionName[64];
     480            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     481            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     482
     483            float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     484            float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     485            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     486            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     487
     488            float X0 = psfX - 4.0*psfdX;
     489            float X1 = psfX + 4.0*psfdX;
     490            float Y0 = psfY - 4.0*psfdY;
     491            float Y1 = psfY + 4.0*psfdY;
     492
     493            if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); }
     494            if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); }
     495            if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); }
     496            if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); }
     497        }
    480498    }
    481499    Xmin = PS_MAX(Xmin, -0.1);
     
    498516    int nF = 0;
    499517    for (int i = 0; i < sources->n; i++) {
    500         pmSource *source = sources->data[i];
    501         if (source->moments == NULL)
    502             continue;
    503 
    504         xFaint->data.F32[nF] = source->moments->Mxx;
    505         yFaint->data.F32[nF] = source->moments->Myy;
    506         mFaint->data.F32[nF] = -2.5*log10(source->moments->Sum);
    507         nF++;
    508 
    509         // XXX make this a user-defined cutoff
    510         if (source->moments->SN < SN_LIM)
    511             continue;
    512 
    513         xBright->data.F32[nB] = source->moments->Mxx;
    514         yBright->data.F32[nB] = source->moments->Myy;
    515         mBright->data.F32[nB] = -2.5*log10(source->moments->Sum);
    516         nB++;
     518        pmSource *source = sources->data[i];
     519        if (source->moments == NULL)
     520            continue;
     521
     522        xFaint->data.F32[nF] = source->moments->Mxx;
     523        yFaint->data.F32[nF] = source->moments->Myy;
     524        mFaint->data.F32[nF] = -2.5*log10(source->moments->Sum);
     525        nF++;
     526
     527        // XXX make this a user-defined cutoff
     528        if (source->moments->SN < SN_LIM)
     529            continue;
     530
     531        xBright->data.F32[nB] = source->moments->Mxx;
     532        yBright->data.F32[nB] = source->moments->Myy;
     533        mBright->data.F32[nB] = -2.5*log10(source->moments->Sum);
     534        nB++;
    517535    }
    518536    xFaint->n = nF;
     
    652670    // draw N circles to outline the clumps
    653671    {
    654         KapaSelectSection (myKapa, "MxxMyy");
    655 
    656         // draw a circle centered on psfX,Y with size of the psf limit
    657         psVector *xLimit  = psVectorAlloc (120, PS_TYPE_F32);
    658         psVector *yLimit  = psVectorAlloc (120, PS_TYPE_F32);
    659 
    660         int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
    661         float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
    662 
    663         graphdata.color = KapaColorByName ("blue");
    664         graphdata.style = 0;
    665 
    666         graphdata.xmin = Xmin;
    667         graphdata.ymin = Ymin;
    668         graphdata.xmax = Xmax;
    669         graphdata.ymax = Ymax;
    670         KapaSetLimits (myKapa, &graphdata);
    671 
    672         for (int n = 0; n < nRegions; n++) {
    673 
    674             char regionName[64];
    675             snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
    676             psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
    677 
    678             float psfX  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
    679             float psfY  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
    680             float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
    681             float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
    682             float Rx = psfdX * PSF_CLUMP_NSIGMA;
    683             float Ry = psfdY * PSF_CLUMP_NSIGMA;
    684 
    685             for (int i = 0; i < xLimit->n; i++) {
    686                 xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX;
    687                 yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY;
    688             }
    689             KapaPrepPlot (myKapa, xLimit->n, &graphdata);
    690             KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x");
    691             KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y");
    692         }
    693         psFree (xLimit);
    694         psFree (yLimit);
     672        KapaSelectSection (myKapa, "MxxMyy");
     673
     674        // draw a circle centered on psfX,Y with size of the psf limit
     675        psVector *xLimit  = psVectorAlloc (120, PS_TYPE_F32);
     676        psVector *yLimit  = psVectorAlloc (120, PS_TYPE_F32);
     677
     678        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     679        float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
     680
     681        graphdata.color = KapaColorByName ("blue");
     682        graphdata.style = 0;
     683
     684        graphdata.xmin = Xmin;
     685        graphdata.ymin = Ymin;
     686        graphdata.xmax = Xmax;
     687        graphdata.ymax = Ymax;
     688        KapaSetLimits (myKapa, &graphdata);
     689
     690        for (int n = 0; n < nRegions; n++) {
     691
     692            char regionName[64];
     693            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     694            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     695
     696            float psfX  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     697            float psfY  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     698            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     699            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     700            float Rx = psfdX * PSF_CLUMP_NSIGMA;
     701            float Ry = psfdY * PSF_CLUMP_NSIGMA;
     702
     703            for (int i = 0; i < xLimit->n; i++) {
     704                xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX;
     705                yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY;
     706            }
     707            KapaPrepPlot (myKapa, xLimit->n, &graphdata);
     708            KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x");
     709            KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y");
     710        }
     711        psFree (xLimit);
     712        psFree (yLimit);
    695713    }
    696714
     
    721739    for (int i = 0; i < sources->n; i++) {
    722740
    723         pmSource *source = sources->data[i];
    724         if (source == NULL) continue;
    725 
    726         if (source->type != type) continue;
    727         if (mode && !(source->mode & mode)) continue;
    728 
    729         pmMoments *moments = source->moments;
    730         if (moments == NULL) continue;
    731 
    732         overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    733         overlay[Noverlay].x = moments->Mx;
    734         overlay[Noverlay].y = moments->My;
    735 
    736         emoments.x2 = moments->Mxx;
    737         emoments.y2 = moments->Myy;
    738         emoments.xy = moments->Mxy;
    739 
    740         axes = psEllipseMomentsToAxes (emoments, 20.0);
    741 
    742         overlay[Noverlay].dx = 2.0*axes.major;
    743         overlay[Noverlay].dy = 2.0*axes.minor;
    744         overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
    745         overlay[Noverlay].text = NULL;
    746         Noverlay ++;
     741        pmSource *source = sources->data[i];
     742        if (source == NULL) continue;
     743
     744        if (source->type != type) continue;
     745        if (mode && !(source->mode & mode)) continue;
     746
     747        pmMoments *moments = source->moments;
     748        if (moments == NULL) continue;
     749
     750        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     751        overlay[Noverlay].x = moments->Mx;
     752        overlay[Noverlay].y = moments->My;
     753
     754        emoments.x2 = moments->Mxx;
     755        emoments.y2 = moments->Myy;
     756        emoments.xy = moments->Mxy;
     757
     758        axes = psEllipseMomentsToAxes (emoments, 20.0);
     759
     760        overlay[Noverlay].dx = 2.0*axes.major;
     761        overlay[Noverlay].dy = 2.0*axes.minor;
     762        overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
     763        overlay[Noverlay].text = NULL;
     764        Noverlay ++;
    747765    }
    748766
     
    753771}
    754772
     773// XXX : requires psphotVisualShowImage
    755774bool psphotVisualShowRoughClass (psArray *sources) {
    756775
    757     if (!DEBUG && !pmVisualIsVisual()) return true;
     776    if (!pmVisualTestLevel("psphot.objects.size", 3)) return true;
    758777
    759778    int myKapa = psphotKapaChannel (1);
     
    776795bool psphotVisualShowPSFModel (pmReadout *readout, pmPSF *psf) {
    777796
    778     if (!DEBUG && !pmVisualIsVisual()) return true;
     797    if (!pmVisualTestLevel("psphot.psf.model", 1)) return true;
    779798
    780799    int myKapa = psphotKapaChannel (3);
     
    797816    // generate a fake model at each of the 3x3 image grid positions
    798817    for (int x = -2; x <= +2; x ++) {
    799         for (int y = -2; y <= +2; y ++) {
    800             // use the center of the center pixel of the image
    801             float xc = (int)((0.5 + 0.225*x)*readout->image->numCols) + readout->image->col0 + 0.5;
    802             float yc = (int)((0.5 + 0.225*y)*readout->image->numRows) + readout->image->row0 + 0.5;
    803 
    804             // assign the x and y coords to the image center
    805             // create an object with center intensity of 1000
    806             modelRef->params->data.F32[PM_PAR_SKY] = 0;
    807             modelRef->params->data.F32[PM_PAR_I0] = 1000;
    808             modelRef->params->data.F32[PM_PAR_XPOS] = xc;
    809             modelRef->params->data.F32[PM_PAR_YPOS] = yc;
    810 
    811             // create modelPSF from this model
    812             pmModel *model = pmModelFromPSF (modelRef, psf);
    813             if (!model) continue;
    814 
    815             // place the reference object in the image center
    816             // no need to mask the source here
    817             // XXX should we measure this for the analytical model only or the full model?
    818             pmModelAddWithOffset (psfMosaic, NULL, model, PM_MODEL_OP_FULL | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
    819             pmModelAddWithOffset (funMosaic, NULL, model, PM_MODEL_OP_FUNC | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
    820             pmModelAddWithOffset (resMosaic, NULL, model, PM_MODEL_OP_RES0 | PM_MODEL_OP_RES1 | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
    821             psFree (model);
    822         }
     818        for (int y = -2; y <= +2; y ++) {
     819            // use the center of the center pixel of the image
     820            float xc = (int)((0.5 + 0.225*x)*readout->image->numCols) + readout->image->col0 + 0.5;
     821            float yc = (int)((0.5 + 0.225*y)*readout->image->numRows) + readout->image->row0 + 0.5;
     822
     823            // assign the x and y coords to the image center
     824            // create an object with center intensity of 1000
     825            modelRef->params->data.F32[PM_PAR_SKY] = 0;
     826            modelRef->params->data.F32[PM_PAR_I0] = 1000;
     827            modelRef->params->data.F32[PM_PAR_XPOS] = xc;
     828            modelRef->params->data.F32[PM_PAR_YPOS] = yc;
     829
     830            // create modelPSF from this model
     831            pmModel *model = pmModelFromPSF (modelRef, psf);
     832            if (!model) continue;
     833
     834            // place the reference object in the image center
     835            // no need to mask the source here
     836            // XXX should we measure this for the analytical model only or the full model?
     837            pmModelAddWithOffset (psfMosaic, NULL, model, PM_MODEL_OP_FULL | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
     838            pmModelAddWithOffset (funMosaic, NULL, model, PM_MODEL_OP_FUNC | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
     839            pmModelAddWithOffset (resMosaic, NULL, model, PM_MODEL_OP_RES0 | PM_MODEL_OP_RES1 | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
     840            psFree (model);
     841        }
    823842    }
    824843
     
    842861    bool status;
    843862
    844     if (!DEBUG && !pmVisualIsVisual()) return true;
     863    if (!pmVisualTestLevel("psphot.psf.stars", 2)) return true;
    845864
    846865    int myKapa = psphotKapaChannel (3);
     
    871890    for (int i = 0; i < sources->n; i++) {
    872891
    873         pmSource *source = sources->data[i];
    874 
    875         bool keep = false;
    876         keep |= (source->mode & PM_SOURCE_MODE_PSFSTAR);
    877         if (!keep) continue;
    878 
    879         // how does this subimage get placed into the output image?
    880         // DX = source->pixels->numCols
    881         // DY = source->pixels->numRows
    882 
    883         if (dX + DX > NX) {
    884             // too wide for the rest of this row
    885             if (dX == 0) {
    886                 // alone on this row
    887                 NY += DY;
    888                 dX = 0;
    889                 dY = 0;
    890             } else {
    891                 // start the next row
    892                 NY += dY;
    893                 dX = DX;
    894                 dY = DY;
    895             }
    896         } else {
    897             // extend this row
    898             dX += DX;
    899             dY = PS_MAX (dY, DY);
    900         }
     892        pmSource *source = sources->data[i];
     893
     894        bool keep = false;
     895        keep |= (source->mode & PM_SOURCE_MODE_PSFSTAR);
     896        if (!keep) continue;
     897
     898        // how does this subimage get placed into the output image?
     899        // DX = source->pixels->numCols
     900        // DY = source->pixels->numRows
     901
     902        if (dX + DX > NX) {
     903            // too wide for the rest of this row
     904            if (dX == 0) {
     905                // alone on this row
     906                NY += DY;
     907                dX = 0;
     908                dY = 0;
     909            } else {
     910                // start the next row
     911                NY += dY;
     912                dX = DX;
     913                dY = DY;
     914            }
     915        } else {
     916            // extend this row
     917            dX += DX;
     918            dY = PS_MAX (dY, DY);
     919        }
    901920    }
    902921    NY += DY;
     
    918937    for (int i = 0; i < sources->n; i++) {
    919938
    920         pmSource *source = sources->data[i];
    921 
    922         bool keep = false;
    923         if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
    924             nPSF ++;
    925             keep = true;
    926         }
    927         if (!keep) continue;
    928 
    929         if (Xo + DX > NX) {
    930             // too wide for the rest of this row
    931             if (Xo == 0) {
    932                 // place source alone on this row
    933                 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    934                 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    935                 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
    936 
    937                 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    938                 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
    939 
    940                 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    941 
    942                 Yo += DY;
    943                 Xo = 0;
    944                 dY = 0;
    945             } else {
    946                 // start the next row
    947                 Yo += dY;
    948                 Xo = 0;
    949 
    950                 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    951                 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    952                 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
    953 
    954                 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    955                 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
    956 
    957                 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    958 
    959                 Xo = DX;
    960                 dY = DY;
    961             }
    962         } else {
    963             // extend this row
    964             bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    965             if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    966             psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
    967 
    968             pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    969             psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
    970             if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    971 
    972             Xo += DX;
    973             dY = PS_MAX (dY, DY);
    974         }
     939        pmSource *source = sources->data[i];
     940
     941        bool keep = false;
     942        if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
     943            nPSF ++;
     944            keep = true;
     945        }
     946        if (!keep) continue;
     947
     948        if (Xo + DX > NX) {
     949            // too wide for the rest of this row
     950            if (Xo == 0) {
     951                // place source alone on this row
     952                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     953                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     954                psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
     955
     956                pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     957                psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
     958
     959                if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     960
     961                Yo += DY;
     962                Xo = 0;
     963                dY = 0;
     964            } else {
     965                // start the next row
     966                Yo += dY;
     967                Xo = 0;
     968
     969                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     970                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     971                psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
     972
     973                pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     974                psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
     975
     976                if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     977
     978                Xo = DX;
     979                dY = DY;
     980            }
     981        } else {
     982            // extend this row
     983            bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     984            if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     985            psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
     986
     987            pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     988            psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
     989            if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     990
     991            Xo += DX;
     992            dY = PS_MAX (dY, DY);
     993        }
    975994    }
    976995
     
    9941013    bool status;
    9951014
    996     if (!DEBUG && !pmVisualIsVisual()) return true;
     1015    if (!pmVisualTestLevel("psphot.psf.sat", 3)) return true;
    9971016
    9981017    int myKapa = psphotKapaChannel (3);
     
    10231042    for (int i = 0; i < sources->n; i++) {
    10241043
    1025         pmSource *source = sources->data[i];
    1026 
    1027         // only show "real" saturated stars (not defects)
    1028         if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;;
    1029         if (source->mode & PM_SOURCE_MODE_DEFECT) continue;;
    1030 
    1031         // how does this subimage get placed into the output image?
    1032         // DX = source->pixels->numCols
    1033         // DY = source->pixels->numRows
    1034 
    1035         if (dX + DX > NX) {
    1036             // too wide for the rest of this row
    1037             if (dX == 0) {
    1038                 // alone on this row
    1039                 NY += DY;
    1040                 dX = 0;
    1041                 dY = 0;
    1042             } else {
    1043                 // start the next row
    1044                 NY += dY;
    1045                 dX = DX;
    1046                 dY = DY;
    1047             }
    1048         } else {
    1049             // extend this row
    1050             dX += DX;
    1051             dY = PS_MAX (dY, DY);
    1052         }
     1044        pmSource *source = sources->data[i];
     1045
     1046        // only show "real" saturated stars (not defects)
     1047        if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;;
     1048        if (source->mode & PM_SOURCE_MODE_DEFECT) continue;;
     1049
     1050        // how does this subimage get placed into the output image?
     1051        // DX = source->pixels->numCols
     1052        // DY = source->pixels->numRows
     1053
     1054        if (dX + DX > NX) {
     1055            // too wide for the rest of this row
     1056            if (dX == 0) {
     1057                // alone on this row
     1058                NY += DY;
     1059                dX = 0;
     1060                dY = 0;
     1061            } else {
     1062                // start the next row
     1063                NY += dY;
     1064                dX = DX;
     1065                dY = DY;
     1066            }
     1067        } else {
     1068            // extend this row
     1069            dX += DX;
     1070            dY = PS_MAX (dY, DY);
     1071        }
    10531072    }
    10541073    NY += DY;
     
    10681087    for (int i = 0; i < sources->n; i++) {
    10691088
    1070         pmSource *source = sources->data[i];
    1071 
    1072         // only show "real" saturated stars (not defects)
    1073         if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;;
    1074         if (source->mode & PM_SOURCE_MODE_DEFECT) continue;;
    1075         nSAT ++;
    1076 
    1077         if (Xo + DX > NX) {
    1078             // too wide for the rest of this row
    1079             if (Xo == 0) {
    1080                 // place source alone on this row
    1081                 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    1082                 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    1083                 psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
    1084                 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    1085 
    1086                 Yo += DY;
    1087                 Xo = 0;
    1088                 dY = 0;
    1089             } else {
    1090                 // start the next row
    1091                 Yo += dY;
    1092                 Xo = 0;
    1093 
    1094                 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    1095                 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    1096                 psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
    1097                 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    1098 
    1099                 Xo = DX;
    1100                 dY = DY;
    1101             }
    1102         } else {
    1103             // extend this row
    1104             bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    1105             if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    1106             psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
    1107             if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    1108 
    1109             Xo += DX;
    1110             dY = PS_MAX (dY, DY);
    1111         }
     1089        pmSource *source = sources->data[i];
     1090
     1091        // only show "real" saturated stars (not defects)
     1092        if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;;
     1093        if (source->mode & PM_SOURCE_MODE_DEFECT) continue;;
     1094        nSAT ++;
     1095
     1096        if (Xo + DX > NX) {
     1097            // too wide for the rest of this row
     1098            if (Xo == 0) {
     1099                // place source alone on this row
     1100                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     1101                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     1102                psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
     1103                if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     1104
     1105                Yo += DY;
     1106                Xo = 0;
     1107                dY = 0;
     1108            } else {
     1109                // start the next row
     1110                Yo += dY;
     1111                Xo = 0;
     1112
     1113                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     1114                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     1115                psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
     1116                if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     1117
     1118                Xo = DX;
     1119                dY = DY;
     1120            }
     1121        } else {
     1122            // extend this row
     1123            bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     1124            if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     1125            psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
     1126            if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     1127
     1128            Xo += DX;
     1129            dY = PS_MAX (dY, DY);
     1130        }
    11121131    }
    11131132
     
    11511170    float Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS] - source->pixels->row0;
    11521171    for (int iy = 0; iy < source->pixels->numRows; iy++) {
    1153         for (int ix = 0; ix < source->pixels->numCols; ix++) {
    1154             if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
    1155                 rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
    1156                 // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ;
    1157                 Rb->data.F32[nb] = log10(rb->data.F32[nb]);
    1158                 fb->data.F32[nb] = log10(source->pixels->data.F32[iy][ix]);
    1159                 nb++;
    1160             } else {
    1161                 rg->data.F32[ng] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
    1162                 // rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ;
    1163                 Rg->data.F32[ng] = log10(rg->data.F32[ng]);
    1164                 fg->data.F32[ng] = log10(source->pixels->data.F32[iy][ix]);
    1165                 ng++;
    1166             }
    1167         }
     1172        for (int ix = 0; ix < source->pixels->numCols; ix++) {
     1173            if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
     1174                rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
     1175                // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ;
     1176                Rb->data.F32[nb] = log10(rb->data.F32[nb]);
     1177                fb->data.F32[nb] = log10(source->pixels->data.F32[iy][ix]);
     1178                nb++;
     1179            } else {
     1180                rg->data.F32[ng] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
     1181                // rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ;
     1182                Rg->data.F32[ng] = log10(rg->data.F32[ng]);
     1183                fg->data.F32[ng] = log10(source->pixels->data.F32[iy][ix]);
     1184                ng++;
     1185            }
     1186        }
    11681187    }
    11691188
     
    13581377    KapaSection section;  // put the positive profile in one and the residuals in another?
    13591378
    1360     if (!DEBUG && !pmVisualIsVisual()) return true;
     1379    if (!pmVisualTestLevel("psphot.profiles", 3)) return true;
    13611380
    13621381    int myKapa = psphotKapaChannel (2);
     
    13941413    for (int i = 0; i < sources->n; i++) {
    13951414
    1396         pmSource *source = sources->data[i];
    1397         if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
    1398 
    1399         psphotVisualPlotRadialProfile (myKapa, source, maskVal);
    1400 
    1401         // pause and wait for user input:
    1402         // continue, save (provide name), ??
    1403         char key[10];
    1404         fprintf (stdout, "[e]rase and continue? [o]verplot and continue? [s]kip rest of stars? : ");
    1405         if (!fgets(key, 8, stdin)) {
    1406             psWarning("Unable to read option");
    1407         }
    1408         if (key[0] == 'e') {
    1409             KapaClearPlots (myKapa);
    1410         }
    1411         if (key[0] == 's') {
    1412             break;
    1413         }
     1415        pmSource *source = sources->data[i];
     1416        if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
     1417
     1418        psphotVisualPlotRadialProfile (myKapa, source, maskVal);
     1419
     1420        // pause and wait for user input:
     1421        // continue, save (provide name), ??
     1422        char key[10];
     1423        fprintf (stdout, "[e]rase and continue? [o]verplot and continue? [s]kip rest of stars? : ");
     1424        if (!fgets(key, 8, stdin)) {
     1425            psWarning("Unable to read option");
     1426        }
     1427        if (key[0] == 'e') {
     1428            KapaClearPlots (myKapa);
     1429        }
     1430        if (key[0] == 's') {
     1431            break;
     1432        }
    14141433    }
    14151434
     
    14291448    return true;
    14301449
    1431     if (!DEBUG && !pmVisualIsVisual()) return true;
     1450    if (!pmVisualTestLevel("psphot.objects.flags", 3)) return true;
    14321451
    14331452    int myKapa = psphotKapaChannel (1);
     
    14451464    for (int i = 0; i < sources->n; i++) {
    14461465
    1447         float Xo, Yo, Rmaj, Rmin, cs, sn;
    1448 
    1449         pmSource *source = sources->data[i];
    1450         if (source == NULL) continue;
    1451 
    1452         pmMoments *moments = source->moments;
    1453         if (0) {
    1454             emoments.x2 = moments->Mxx;
    1455             emoments.y2 = moments->Myy;
    1456             emoments.xy = moments->Mxy;
    1457             Xo = moments->Mx;
    1458             Yo = moments->My;
    1459 
    1460             axes = psEllipseMomentsToAxes (emoments, 20.0);
    1461             Rmaj = 2.0*axes.major;
    1462             Rmin = 2.0*axes.minor;
    1463             cs = cos(axes.theta);
    1464             sn = sin(axes.theta);
    1465         } else {
    1466             Rmaj = Rmin = 5.0;
    1467             cs = 1.0;
    1468             sn = 0.0;
    1469             Xo = source->peak->xf;
    1470             Yo = source->peak->yf;
    1471         }
    1472 
    1473         unsigned short int flagMask = 0x01;
    1474         for (int j = 0; j < 8; j++) {
    1475             if (source->mode & flagMask) {
    1476                 overlayE[NoverlayE].type = KII_OVERLAY_LINE;
    1477                 overlayE[NoverlayE].x = Xo;
    1478                 overlayE[NoverlayE].y = Yo;
    1479 
    1480                 float phi = j*M_PI/4.0;
    1481                 overlayE[NoverlayE].dx = +Rmaj*cos(phi)*cs - Rmin*sin(phi)*sn;
    1482                 overlayE[NoverlayE].dy = +Rmaj*cos(phi)*sn + Rmin*sin(phi)*cs;
    1483                 overlayE[NoverlayE].angle = 0;
    1484                 overlayE[NoverlayE].text = NULL;
    1485                 NoverlayE ++;
    1486                 CHECK_REALLOCATE (overlayE, KiiOverlay, NOVERLAYE, NoverlayE, 100);
    1487             }
    1488             flagMask <<= 1;
    1489 
    1490             if (source->mode & flagMask) {
    1491                 overlayO[NoverlayO].type = KII_OVERLAY_LINE;
    1492                 overlayO[NoverlayO].x = Xo + 1;
    1493                 overlayO[NoverlayO].y = Yo;
    1494 
    1495                 float phi = j*M_PI/4.0;
    1496                 overlayO[NoverlayO].dx = +Rmaj*cos(phi)*cs - Rmin*sin(phi)*sn;
    1497                 overlayO[NoverlayO].dy = +Rmaj*cos(phi)*sn + Rmin*sin(phi)*cs;
    1498                 overlayO[NoverlayO].angle = 0;
    1499                 overlayO[NoverlayO].text = NULL;
    1500                 NoverlayO ++;
    1501                 CHECK_REALLOCATE (overlayO, KiiOverlay, NOVERLAYO, NoverlayO, 100);
    1502             }
    1503             flagMask <<= 1;
    1504         }
     1466        float Xo, Yo, Rmaj, Rmin, cs, sn;
     1467
     1468        pmSource *source = sources->data[i];
     1469        if (source == NULL) continue;
     1470
     1471        pmMoments *moments = source->moments;
     1472        if (0) {
     1473            emoments.x2 = moments->Mxx;
     1474            emoments.y2 = moments->Myy;
     1475            emoments.xy = moments->Mxy;
     1476            Xo = moments->Mx;
     1477            Yo = moments->My;
     1478
     1479            axes = psEllipseMomentsToAxes (emoments, 20.0);
     1480            Rmaj = 2.0*axes.major;
     1481            Rmin = 2.0*axes.minor;
     1482            cs = cos(axes.theta);
     1483            sn = sin(axes.theta);
     1484        } else {
     1485            Rmaj = Rmin = 5.0;
     1486            cs = 1.0;
     1487            sn = 0.0;
     1488            Xo = source->peak->xf;
     1489            Yo = source->peak->yf;
     1490        }
     1491
     1492        unsigned short int flagMask = 0x01;
     1493        for (int j = 0; j < 8; j++) {
     1494            if (source->mode & flagMask) {
     1495                overlayE[NoverlayE].type = KII_OVERLAY_LINE;
     1496                overlayE[NoverlayE].x = Xo;
     1497                overlayE[NoverlayE].y = Yo;
     1498
     1499                float phi = j*M_PI/4.0;
     1500                overlayE[NoverlayE].dx = +Rmaj*cos(phi)*cs - Rmin*sin(phi)*sn;
     1501                overlayE[NoverlayE].dy = +Rmaj*cos(phi)*sn + Rmin*sin(phi)*cs;
     1502                overlayE[NoverlayE].angle = 0;
     1503                overlayE[NoverlayE].text = NULL;
     1504                NoverlayE ++;
     1505                CHECK_REALLOCATE (overlayE, KiiOverlay, NOVERLAYE, NoverlayE, 100);
     1506            }
     1507            flagMask <<= 1;
     1508
     1509            if (source->mode & flagMask) {
     1510                overlayO[NoverlayO].type = KII_OVERLAY_LINE;
     1511                overlayO[NoverlayO].x = Xo + 1;
     1512                overlayO[NoverlayO].y = Yo;
     1513
     1514                float phi = j*M_PI/4.0;
     1515                overlayO[NoverlayO].dx = +Rmaj*cos(phi)*cs - Rmin*sin(phi)*sn;
     1516                overlayO[NoverlayO].dy = +Rmaj*cos(phi)*sn + Rmin*sin(phi)*cs;
     1517                overlayO[NoverlayO].angle = 0;
     1518                overlayO[NoverlayO].text = NULL;
     1519                NoverlayO ++;
     1520                CHECK_REALLOCATE (overlayO, KiiOverlay, NOVERLAYO, NoverlayO, 100);
     1521            }
     1522            flagMask <<= 1;
     1523        }
    15051524    }
    15061525
     
    15311550    for (int i = 0; i < sources->n; i++) {
    15321551
    1533         pmSource *source = sources->data[i];
    1534         if (source == NULL) continue;
    1535 
    1536         if (mode) {
    1537             if (keep) {
    1538                 if (!(source->mode & mode)) continue;
    1539             } else {
    1540                 if (source->mode & mode) continue;
    1541             }
    1542         }
    1543 
    1544         pmMoments *moments = source->moments;
    1545         if (moments == NULL) continue;
    1546 
    1547         overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    1548         overlay[Noverlay].x = moments->Mx;
    1549         overlay[Noverlay].y = moments->My;
    1550 
    1551         emoments.x2 = moments->Mxx;
    1552         emoments.y2 = moments->Myy;
    1553         emoments.xy = moments->Mxy;
    1554 
    1555         axes = psEllipseMomentsToAxes (emoments, 20.0);
    1556 
    1557         overlay[Noverlay].dx = scale*2.0*axes.major;
    1558         overlay[Noverlay].dy = scale*2.0*axes.minor;
    1559         overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
    1560         overlay[Noverlay].text = NULL;
    1561         Noverlay ++;
     1552        pmSource *source = sources->data[i];
     1553        if (source == NULL) continue;
     1554
     1555        if (mode) {
     1556            if (keep) {
     1557                if (!(source->mode & mode)) continue;
     1558            } else {
     1559                if (source->mode & mode) continue;
     1560            }
     1561        }
     1562
     1563        pmMoments *moments = source->moments;
     1564        if (moments == NULL) continue;
     1565
     1566        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     1567        overlay[Noverlay].x = moments->Mx;
     1568        overlay[Noverlay].y = moments->My;
     1569
     1570        emoments.x2 = moments->Mxx;
     1571        emoments.y2 = moments->Myy;
     1572        emoments.xy = moments->Mxy;
     1573
     1574        axes = psEllipseMomentsToAxes (emoments, 20.0);
     1575
     1576        overlay[Noverlay].dx = scale*2.0*axes.major;
     1577        overlay[Noverlay].dy = scale*2.0*axes.minor;
     1578        overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
     1579        overlay[Noverlay].text = NULL;
     1580        Noverlay ++;
    15621581    }
    15631582
     
    15701589bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources) {
    15711590
    1572     if (!DEBUG && !pmVisualIsVisual()) return true;
     1591    if (!pmVisualTestLevel("psphot.objects.size", 2)) return true;
    15731592
    15741593    int myKapa = psphotKapaChannel (1);
     
    15971616    KapaSection section;
    15981617
    1599     if (!DEBUG && !pmVisualIsVisual()) return true;
     1618    if (!pmVisualTestLevel("psphot.size", 2)) return true;
    16001619
    16011620    int myKapa = psphotKapaChannel (2);
     
    16121631    float Ymin = 1000.0, Ymax = 0.0;
    16131632    {
    1614         int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
    1615         for (int n = 0; n < nRegions; n++) {
    1616 
    1617             char regionName[64];
    1618             snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
    1619             psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
    1620 
    1621             float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
    1622             float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
    1623             float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
    1624             float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
    1625 
    1626             float X0 = psfX - 10.0*psfdX;
    1627             float X1 = psfX + 10.0*psfdX;
    1628             float Y0 = psfY - 10.0*psfdY;
    1629             float Y1 = psfY + 10.0*psfdY;
    1630 
    1631             if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); }
    1632             if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); }
    1633             if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); }
    1634             if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); }
    1635         }
     1633        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     1634        for (int n = 0; n < nRegions; n++) {
     1635
     1636            char regionName[64];
     1637            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     1638            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     1639
     1640            float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     1641            float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     1642            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     1643            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     1644
     1645            float X0 = psfX - 10.0*psfdX;
     1646            float X1 = psfX + 10.0*psfdX;
     1647            float Y0 = psfY - 10.0*psfdY;
     1648            float Y1 = psfY + 10.0*psfdY;
     1649
     1650            if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); }
     1651            if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); }
     1652            if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); }
     1653            if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); }
     1654        }
    16361655    }
    16371656    Xmin = PS_MAX(Xmin, -0.1);
     
    16771696    int nCR  = 0;
    16781697    for (int i = 0; i < sources->n; i++) {
    1679         pmSource *source = sources->data[i];
    1680         if (source->moments == NULL) continue;
     1698        pmSource *source = sources->data[i];
     1699        if (source->moments == NULL) continue;
    16811700
    16821701        // only plot the measured sources...
    1683         if (!(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED)) continue;
    1684 
    1685         if (source->mode & PM_SOURCE_MODE_CR_LIMIT) {
    1686             xCR->data.F32[nCR] = source->moments->Mxx;
    1687             yCR->data.F32[nCR] = source->moments->Myy;
    1688             mCR->data.F32[nCR] = -2.5*log10(source->moments->Sum);
    1689             sCR->data.F32[nCR] = source->extNsigma;
    1690             nCR++;
    1691         }
    1692         if (source->mode & PM_SOURCE_MODE_SATSTAR) {
    1693             xSAT->data.F32[nSAT] = source->moments->Mxx;
    1694             ySAT->data.F32[nSAT] = source->moments->Myy;
    1695             mSAT->data.F32[nSAT] = -2.5*log10(source->moments->Sum);
    1696             sSAT->data.F32[nSAT] = source->extNsigma;
    1697             nSAT++;
    1698         }
    1699         if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    1700             xEXT->data.F32[nEXT] = source->moments->Mxx;
    1701             yEXT->data.F32[nEXT] = source->moments->Myy;
    1702             mEXT->data.F32[nEXT] = -2.5*log10(source->moments->Sum);
    1703             sEXT->data.F32[nEXT] = source->extNsigma;
    1704             nEXT++;
    1705             continue;
    1706         }
    1707         if (source->mode & PM_SOURCE_MODE_DEFECT) {
    1708             xDEF->data.F32[nDEF] = source->moments->Mxx;
    1709             yDEF->data.F32[nDEF] = source->moments->Myy;
    1710             mDEF->data.F32[nDEF] = -2.5*log10(source->moments->Sum);
    1711             sDEF->data.F32[nDEF] = source->extNsigma;
    1712             nDEF++;
    1713             continue;
    1714         }
    1715         if (source->errMag > 0.1) {
    1716             xLOW->data.F32[nLOW] = source->moments->Mxx;
    1717             yLOW->data.F32[nLOW] = source->moments->Myy;
    1718             mLOW->data.F32[nLOW] = -2.5*log10(source->moments->Sum);
    1719             sLOW->data.F32[nLOW] = source->extNsigma;
    1720             nLOW++;
    1721             continue;
    1722         }
    1723         xPSF->data.F32[nPSF] = source->moments->Mxx;
    1724         yPSF->data.F32[nPSF] = source->moments->Myy;
    1725         mPSF->data.F32[nPSF] = -2.5*log10(source->moments->Sum);
    1726         sPSF->data.F32[nPSF] = source->extNsigma;
    1727         nPSF++;
     1702        if (!(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED)) continue;
     1703
     1704        if (source->mode & PM_SOURCE_MODE_CR_LIMIT) {
     1705            xCR->data.F32[nCR] = source->moments->Mxx;
     1706            yCR->data.F32[nCR] = source->moments->Myy;
     1707            mCR->data.F32[nCR] = -2.5*log10(source->moments->Sum);
     1708            sCR->data.F32[nCR] = source->extNsigma;
     1709            nCR++;
     1710        }
     1711        if (source->mode & PM_SOURCE_MODE_SATSTAR) {
     1712            xSAT->data.F32[nSAT] = source->moments->Mxx;
     1713            ySAT->data.F32[nSAT] = source->moments->Myy;
     1714            mSAT->data.F32[nSAT] = -2.5*log10(source->moments->Sum);
     1715            sSAT->data.F32[nSAT] = source->extNsigma;
     1716            nSAT++;
     1717        }
     1718        if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
     1719            xEXT->data.F32[nEXT] = source->moments->Mxx;
     1720            yEXT->data.F32[nEXT] = source->moments->Myy;
     1721            mEXT->data.F32[nEXT] = -2.5*log10(source->moments->Sum);
     1722            sEXT->data.F32[nEXT] = source->extNsigma;
     1723            nEXT++;
     1724            continue;
     1725        }
     1726        if (source->mode & PM_SOURCE_MODE_DEFECT) {
     1727            xDEF->data.F32[nDEF] = source->moments->Mxx;
     1728            yDEF->data.F32[nDEF] = source->moments->Myy;
     1729            mDEF->data.F32[nDEF] = -2.5*log10(source->moments->Sum);
     1730            sDEF->data.F32[nDEF] = source->extNsigma;
     1731            nDEF++;
     1732            continue;
     1733        }
     1734        if (source->errMag > 0.1) {
     1735            xLOW->data.F32[nLOW] = source->moments->Mxx;
     1736            yLOW->data.F32[nLOW] = source->moments->Myy;
     1737            mLOW->data.F32[nLOW] = -2.5*log10(source->moments->Sum);
     1738            sLOW->data.F32[nLOW] = source->extNsigma;
     1739            nLOW++;
     1740            continue;
     1741        }
     1742        xPSF->data.F32[nPSF] = source->moments->Mxx;
     1743        yPSF->data.F32[nPSF] = source->moments->Myy;
     1744        mPSF->data.F32[nPSF] = -2.5*log10(source->moments->Sum);
     1745        sPSF->data.F32[nPSF] = source->extNsigma;
     1746        nPSF++;
    17281747    }
    17291748
     
    20292048    // draw N circles to outline the clumps
    20302049    {
    2031         KapaSelectSection (myKapa, "MxxMyy");
    2032 
    2033         // draw a circle centered on psfX,Y with size of the psf limit
    2034         psVector *xLimit  = psVectorAlloc (120, PS_TYPE_F32);
    2035         psVector *yLimit  = psVectorAlloc (120, PS_TYPE_F32);
    2036 
    2037         int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
    2038         float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
    2039 
    2040         graphdata.color = KapaColorByName ("blue");
    2041         graphdata.style = 0;
    2042 
    2043         graphdata.xmin = Xmin;
    2044         graphdata.ymin = Ymin;
    2045         graphdata.xmax = Xmax;
    2046         graphdata.ymax = Ymax;
    2047         KapaSetLimits (myKapa, &graphdata);
    2048 
    2049         for (int n = 0; n < nRegions; n++) {
    2050 
    2051             char regionName[64];
    2052             snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
    2053             psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
    2054 
    2055             float psfX  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
    2056             float psfY  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
    2057             float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
    2058             float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
    2059             float Rx = psfdX * PSF_CLUMP_NSIGMA;
    2060             float Ry = psfdY * PSF_CLUMP_NSIGMA;
    2061 
    2062             for (int i = 0; i < xLimit->n; i++) {
    2063                 xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX;
    2064                 yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY;
    2065             }
    2066             KapaPrepPlot (myKapa, xLimit->n, &graphdata);
    2067             KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x");
    2068             KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y");
    2069         }
    2070         psFree (xLimit);
    2071         psFree (yLimit);
     2050        KapaSelectSection (myKapa, "MxxMyy");
     2051
     2052        // draw a circle centered on psfX,Y with size of the psf limit
     2053        psVector *xLimit  = psVectorAlloc (120, PS_TYPE_F32);
     2054        psVector *yLimit  = psVectorAlloc (120, PS_TYPE_F32);
     2055
     2056        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     2057        float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
     2058
     2059        graphdata.color = KapaColorByName ("blue");
     2060        graphdata.style = 0;
     2061
     2062        graphdata.xmin = Xmin;
     2063        graphdata.ymin = Ymin;
     2064        graphdata.xmax = Xmax;
     2065        graphdata.ymax = Ymax;
     2066        KapaSetLimits (myKapa, &graphdata);
     2067
     2068        for (int n = 0; n < nRegions; n++) {
     2069
     2070            char regionName[64];
     2071            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     2072            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     2073
     2074            float psfX  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     2075            float psfY  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     2076            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     2077            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     2078            float Rx = psfdX * PSF_CLUMP_NSIGMA;
     2079            float Ry = psfdY * PSF_CLUMP_NSIGMA;
     2080
     2081            for (int i = 0; i < xLimit->n; i++) {
     2082                xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX;
     2083                yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY;
     2084            }
     2085            KapaPrepPlot (myKapa, xLimit->n, &graphdata);
     2086            KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x");
     2087            KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y");
     2088        }
     2089        psFree (xLimit);
     2090        psFree (yLimit);
    20722091    }
    20732092
     
    21082127bool psphotVisualShowResidualImage (pmReadout *readout) {
    21092128
    2110     if (!DEBUG && !pmVisualIsVisual()) return true;
     2129    if (!pmVisualTestLevel("psphot.image.resid", 2)) return true;
    21112130
    21122131    int myKapa = psphotKapaChannel (1);
     
    21242143    float lineX[2], lineY[2];
    21252144
    2126     if (!DEBUG && !pmVisualIsVisual()) return true;
     2145    if (!pmVisualTestLevel("psphot.apresid", 1)) return true;
    21272146
    21282147    int myKapa = psphotKapaChannel (2);
     
    21442163    int n = 0;
    21452164    for (int i = 0; i < sources->n; i++) {
    2146         pmSource *source = sources->data[i];
    2147         if (!source) continue;
    2148         if (source->type != PM_SOURCE_TYPE_STAR) continue;
    2149         if (!isfinite (source->apMag)) continue;
    2150         if (!isfinite (source->psfMag)) continue;
    2151 
    2152         x->data.F32[n] = source->psfMag;
    2153         y->data.F32[n] = source->apMag - source->psfMag;
    2154         dy->data.F32[n] = source->errMag;
    2155         graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
    2156         graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
    2157         graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
    2158         graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
    2159 
    2160         n++;
     2165        pmSource *source = sources->data[i];
     2166        if (!source) continue;
     2167        if (source->type != PM_SOURCE_TYPE_STAR) continue;
     2168        if (!isfinite (source->apMag)) continue;
     2169        if (!isfinite (source->psfMag)) continue;
     2170
     2171        x->data.F32[n] = source->psfMag;
     2172        y->data.F32[n] = source->apMag - source->psfMag;
     2173        dy->data.F32[n] = source->errMag;
     2174        graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
     2175        graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
     2176        graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
     2177        graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
     2178
     2179        n++;
    21612180    }
    21622181    x->n = y->n = dy->n = n;
     
    22422261    Graphdata graphdata;
    22432262
    2244     if (!DEBUG && !pmVisualIsVisual()) return true;
     2263    if (!pmVisualTestLevel("psphot.chisq", 1)) return true;
    22452264
    22462265    int myKapa = psphotKapaChannel (2);
     
    22632282    int n = 0;
    22642283    for (int i = 0; i < sources->n; i++) {
    2265         pmSource *source = sources->data[i];
    2266         if (!source) continue;
    2267         if (source->type != PM_SOURCE_TYPE_STAR) continue;
    2268         if (!source->moments) continue;
    2269         if (!isfinite(source->moments->Sum)) continue;
    2270         if (!source->modelPSF) continue;
    2271         if (!isfinite(source->modelPSF->chisq)) continue;
    2272 
    2273         x->data.F32[n] = -2.5*log10(source->moments->Sum);
    2274         y->data.F32[n] = source->modelPSF->chisq / source->modelPSF->nDOF;
    2275         graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
    2276         graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
    2277         graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
    2278         graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
    2279 
    2280         fprintf (f, "%d %d %f %f\n", i, n, x->data.F32[n], y->data.F32[n]);
    2281 
    2282         n++;
     2284        pmSource *source = sources->data[i];
     2285        if (!source) continue;
     2286        if (source->type != PM_SOURCE_TYPE_STAR) continue;
     2287        if (!source->moments) continue;
     2288        if (!isfinite(source->moments->Sum)) continue;
     2289        if (!source->modelPSF) continue;
     2290        if (!isfinite(source->modelPSF->chisq)) continue;
     2291
     2292        x->data.F32[n] = -2.5*log10(source->moments->Sum);
     2293        y->data.F32[n] = source->modelPSF->chisq / source->modelPSF->nDOF;
     2294        graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
     2295        graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
     2296        graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
     2297        graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
     2298
     2299        fprintf (f, "%d %d %f %f\n", i, n, x->data.F32[n], y->data.F32[n]);
     2300
     2301        n++;
    22832302    }
    22842303    x->n = y->n = n;
     
    23262345    KiiOverlay *overlay;
    23272346
    2328     if (!DEBUG && !pmVisualIsVisual()) return true;
     2347    if (!pmVisualTestLevel("psphot.objects.petro", 2)) return true;
    23292348
    23302349    int kapa = psphotKapaChannel (1);
     
    23362355
    23372356    for (int i = 0; i < sources->n; i++) {
    2338         pmSource *source = sources->data[i];
    2339 
    2340         if (!source) continue;
    2341         if (!source->extpars) continue;
    2342         if (!source->extpars->petProfile) continue;
    2343 
    2344         float petrosianRadius = source->extpars->petrosianRadius;
     2357        pmSource *source = sources->data[i];
     2358
     2359        if (!source) continue;
     2360        if (!source->extpars) continue;
     2361        if (!source->extpars->petProfile) continue;
     2362
     2363        float petrosianRadius = source->extpars->petrosianRadius;
    23452364        psEllipseAxes *axes = &source->extpars->axes;
    23462365
    2347         overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    2348         overlay[Noverlay].x = source->peak->xf;
    2349         overlay[Noverlay].y = source->peak->yf;
    2350         overlay[Noverlay].dx = 1.0*petrosianRadius;
    2351         overlay[Noverlay].dy = 1.0*petrosianRadius*axes->minor/axes->major;
    2352         overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
    2353         overlay[Noverlay].text = NULL;
    2354         Noverlay ++;
    2355         CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    2356 
    2357         // overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    2358         // overlay[Noverlay].x = source->peak->xf;
    2359         // overlay[Noverlay].y = source->peak->yf;
    2360         // overlay[Noverlay].dx = 2.0*petrosianRadius;
    2361         // overlay[Noverlay].dy = 2.0*petrosianRadius*axes->minor/axes->major;
    2362         // overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
    2363         // overlay[Noverlay].text = NULL;
    2364         // Noverlay ++;
    2365         // CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     2366        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     2367        overlay[Noverlay].x = source->peak->xf;
     2368        overlay[Noverlay].y = source->peak->yf;
     2369        overlay[Noverlay].dx = 1.0*petrosianRadius;
     2370        overlay[Noverlay].dy = 1.0*petrosianRadius*axes->minor/axes->major;
     2371        overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
     2372        overlay[Noverlay].text = NULL;
     2373        Noverlay ++;
     2374        CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     2375
     2376        // overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     2377        // overlay[Noverlay].x = source->peak->xf;
     2378        // overlay[Noverlay].y = source->peak->yf;
     2379        // overlay[Noverlay].dx = 2.0*petrosianRadius;
     2380        // overlay[Noverlay].dy = 2.0*petrosianRadius*axes->minor/axes->major;
     2381        // overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
     2382        // overlay[Noverlay].text = NULL;
     2383        // Noverlay ++;
     2384        // CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    23662385    }
    23672386
Note: See TracChangeset for help on using the changeset viewer.