IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 28435


Ignore:
Timestamp:
Jun 23, 2010, 2:03:31 PM (16 years ago)
Author:
eugene
Message:

add visual facility management a la psTrace

Location:
branches/eam_branches/ipp-20100621
Files:
2 added
9 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20100621/psModules/src/config/pmConfig.c

    r28287 r28435  
    3232
    3333#include "pmConfig.h"
     34#include "pmVisualUtils.h"
    3435
    3536#ifdef HAVE_NEBCLIENT
     
    638639        psArgumentVerbosity(argc, argv);
    639640        // XXX: substitute the string for the default log level for "2".
     641    }
     642
     643    // Set the visualization levels
     644    // argument format is: -visual (facil) (level)
     645    while ((argNum = psArgumentGet(*argc, argv, "-visual"))) {
     646        if ( (*argc < argNum + 3) ) {
     647            psError(PS_ERR_IO, true, "-visual switch specified without facility and level.");
     648            return NULL;
     649        }
     650        psArgumentRemove(argNum, argc, argv);
     651        pmVisualSetLevel(argv[argNum], atoi(argv[argNum+1]));
     652        psArgumentRemove(argNum, argc, argv);
     653        psArgumentRemove(argNum, argc, argv);
     654    }
     655    if ((argNum = psArgumentGet(*argc, argv, "-visual-all"))) {
     656        pmVisualSetLevel(".", 10);
     657    }
     658    if ((argNum = psArgumentGet(*argc, argv, "-visual-levels"))) {
     659        pmVisualPrintLevels(stdout);
    640660    }
    641661
  • branches/eam_branches/ipp-20100621/psModules/src/extras/Makefile.am

    r27750 r28435  
    99        pmKapaPlots.c \
    1010        pmVisual.c \
     11        pmVisualUtils.c \
    1112        ippStages.c
    1213
     
    1718        pmKapaPlots.h \
    1819        pmVisual.h \
     20        pmVisualUtils.h \
    1921        ippDiffMode.h \
    2022        ippStages.h
  • branches/eam_branches/ipp-20100621/psModules/src/objects/pmSourceVisual.c

    r26260 r28435  
    1313#include <kapa.h>
    1414#include "pmVisual.h"
     15#include "pmVisualUtils.h"
    1516
    1617// functions used to visualize the analysis as it goes
     
    3435    Graphdata graphdata;
    3536
    36     if (!pmVisualIsVisual()) return true;
     37    if (!pmVisualTestLevel("psphot.psf.metric", 2)) return true;
    3738
    3839    if (kapa1 == -1) {
     
    118119    Graphdata graphdata;
    119120
    120     if (!pmVisualIsVisual()) return true;
     121    if (!pmVisualTestLevel("psphot.psf.subpix", 3)) return true;
    121122
    122123    if (kapa1 == -1) {
     
    280281bool pmSourceVisualShowModelFits (pmPSF *psf, psArray *sources, psImageMaskType maskVal) {
    281282
    282     if (!pmVisualIsVisual()) return true;
     283    if (!pmVisualTestLevel("psphot.psf.fits", 2)) return true;
    283284
    284285    if (kapa2 == -1) {
     
    360361bool pmSourceVisualShowModelFit (pmSource *source) {
    361362
    362     if (!pmVisualIsVisual()) return true;
     363    if (!pmVisualTestLevel("psphot.psf.fitresid", 2)) return true;
     364
    363365    if (!source->pixels) return false;
    364366    if (!source->modelFlux) return false;
     
    404406    Graphdata graphdata;
    405407
    406     if (!pmVisualIsVisual() || !plotPSF) return true;
     408    if (!plotPSF) return true;
     409    if (!pmVisualTestLevel("psphot.psf.resid", 2)) return true;
    407410
    408411    if (kapa1 == -1) {
  • branches/eam_branches/ipp-20100621/psModules/src/psmodules.h

    r28043 r28435  
    1010#include <pmKapaPlots.h>
    1111#include <pmVisual.h>
     12#include <pmVisualUtils.h>
    1213#include <ippStages.h>
    1314#include <ippDiffMode.h>
  • branches/eam_branches/ipp-20100621/psphot/src/Makefile.am

    r28013 r28435  
    2020        -$(RM) psphotVersionDefinitions.h
    2121        $(SED) -e "s|@PSPHOT_VERSION@|\"$(PSPHOT_VERSION)\"|" -e "s|@PSPHOT_BRANCH@|\"$(PSPHOT_BRANCH)\"|" -e "s|@PSPHOT_SOURCE@|\"$(PSPHOT_SOURCE)\"|" psphotVersionDefinitions.h.in > psphotVersionDefinitions.h
    22 FORCE: ;
     22# FORCE: ;
    2323
    2424libpsphot_la_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
  • branches/eam_branches/ipp-20100621/psphot/src/psphotArguments.c

    r25985 r28435  
    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/eam_branches/ipp-20100621/psphot/src/psphotPetrosianVisual.c

    r27819 r28435  
    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/eam_branches/ipp-20100621/psphot/src/psphotSourceStats.c

    r28405 r28435  
    501501        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
    502502
    503         psphotVisualPlotMoments (recipe, analysis, sources);
     503        if (pmVisualTestLevel("psphot.moments.full", 2)) {
     504            psphotVisualPlotMoments (recipe, analysis, sources);
     505        }
    504506
    505507        Sout[i] = sqrt(0.5*(psfClump.X + psfClump.Y)) / sigma[i];
  • branches/eam_branches/ipp-20100621/psphot/src/psphotVisual.c

    r28128 r28435  
    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
     235// XXX : requires psphotVisualShowImage
    235236bool psphotVisualShowPeaks (pmDetections *detections) {
    236237
     
    238239    KiiOverlay *overlay;
    239240
    240     if (!DEBUG && !pmVisualIsVisual()) return true;
     241    if (!pmVisualTestLevel("psphot.objects.peaks", 1)) return true;
    241242
    242243    int kapa = psphotKapaChannel (1);
     
    252253    for (int i = 0; i < peaks->n; i++) {
    253254
    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 ++;
     255        pmPeak *peak = peaks->data[i];
     256        if (peak == NULL) continue;
     257
     258        overlay[Noverlay].type = KII_OVERLAY_BOX;
     259        overlay[Noverlay].x = peak->xf;
     260        overlay[Noverlay].y = peak->yf;
     261        overlay[Noverlay].dx = 2.0;
     262        overlay[Noverlay].dy = 2.0;
     263        overlay[Noverlay].angle = 0.0;
     264        overlay[Noverlay].text = NULL;
     265        Noverlay ++;
    265266    }
    266267
     
    272273}
    273274
     275// XXX : requires psphotVisualShowImage
    274276bool psphotVisualShowFootprints (pmDetections *detections) {
    275277
     
    277279    KiiOverlay *overlay;
    278280
    279     if (!DEBUG && !pmVisualIsVisual()) return true;
     281    if (!pmVisualTestLevel("psphot.objects.footprints", 3)) return true;
    280282
    281283    int kapa = psphotKapaChannel (1);
     
    292294    for (int i = 0; i < footprints->n; i++) {
    293295
    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);
     296        pmSpan *span = NULL;
     297
     298        pmFootprint *footprint = footprints->data[i];
     299        if (footprint == NULL) continue;
     300        if (footprint->spans == NULL) continue;
     301        if (footprint->spans->n < 1) continue;
     302
     303        // draw the top
     304        // XXX need to allow top (and bottom) to have more than one span
     305        span = footprint->spans->data[0];
     306        overlay[Noverlay].type = KII_OVERLAY_LINE;
     307        overlay[Noverlay].x = span->x0;
     308        overlay[Noverlay].y = span->y;
     309        overlay[Noverlay].dx = span->x1 - span->x0;
     310        overlay[Noverlay].dy = 0;
     311        overlay[Noverlay].angle = 0.0;
     312        overlay[Noverlay].text = NULL;
     313        Noverlay ++;
     314        CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     315
     316        int ys = span->y;
     317        int x0s = span->x0;
     318        int x1s = span->x1;
     319
     320        // draw the outer span edges
     321        for (int j = 1; j < footprint->spans->n; j++) {
     322            pmSpan *span1 = footprint->spans->data[j];
     323
     324            int ye = span1->y;
     325            int x0e = span1->x0;
     326            int x1e = span1->x1;
     327
     328            // we cannot have two discontinuous spans on the top or bottom, right? (no, probably not right)
     329            // find all of the spans in this row and generate x0e, x01:
     330            for (int k = j + 1; k < footprint->spans->n; k++) {
     331                pmSpan *span2 = footprint->spans->data[k];
     332                if (span2->y > span1->y) break;
     333                x0e = PS_MIN (x0e, span2->x0);
     334                x1e = PS_MAX (x1e, span2->x1);
     335                j++;
     336            }
     337
     338            overlay[Noverlay].type = KII_OVERLAY_LINE;
     339            overlay[Noverlay].x = x0s;
     340            overlay[Noverlay].y = ys;
     341            overlay[Noverlay].dx = x0e - x0s;
     342            overlay[Noverlay].dy = ye - ys;
     343            overlay[Noverlay].angle = 0.0;
     344            overlay[Noverlay].text = NULL;
     345            Noverlay ++;
     346            CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     347
     348            overlay[Noverlay].type = KII_OVERLAY_LINE;
     349            overlay[Noverlay].x = x1s;
     350            overlay[Noverlay].y = ys;
     351            overlay[Noverlay].dx = x1e - x1s;
     352            overlay[Noverlay].dy = ye - ys;
     353            overlay[Noverlay].angle = 0.0;
     354            overlay[Noverlay].text = NULL;
     355            Noverlay ++;
     356            CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     357
     358            ys = ye;
     359            x0s = x0e;
     360            x1s = x1e;
     361        }
     362
     363        // draw the bottom
     364        span = footprint->spans->data[footprint->spans->n - 1];
     365        overlay[Noverlay].type = KII_OVERLAY_LINE;
     366        overlay[Noverlay].x = span->x0;
     367        overlay[Noverlay].y = span->y;
     368        overlay[Noverlay].dx = span->x1 - span->x0;
     369        overlay[Noverlay].dy = 0;
     370        overlay[Noverlay].angle = 0.0;
     371        overlay[Noverlay].text = NULL;
     372        Noverlay ++;
     373        CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    372374    }
    373375
     
    379381}
    380382
     383// XXX : requires psphotVisualShowImage
    381384bool psphotVisualShowMoments (psArray *sources) {
    382385
     
    387390    psEllipseAxes axes;
    388391
    389     if (!DEBUG && !pmVisualIsVisual()) return true;
     392    if (!pmVisualTestLevel("psphot.objects.moments", 2)) return true;
    390393
    391394    int kapa = psphotKapaChannel (1);
     
    401404    for (int i = 0; i < sources->n; i++) {
    402405
    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 ++;
     406        pmSource *source = sources->data[i];
     407        if (source == NULL) continue;
     408
     409        pmMoments *moments = source->moments;
     410        if (moments == NULL) continue;
     411
     412        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     413        overlay[Noverlay].x = moments->Mx;
     414        overlay[Noverlay].y = moments->My;
     415
     416        emoments.x2 = moments->Mxx;
     417        emoments.xy = moments->Mxy;
     418        emoments.y2 = moments->Myy;
     419
     420        axes = psEllipseMomentsToAxes (emoments, 20.0);
     421
     422        overlay[Noverlay].dx = 2.0*axes.major;
     423        overlay[Noverlay].dy = 2.0*axes.minor;
     424
     425        overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
     426
     427        overlay[Noverlay].text = NULL;
     428        Noverlay ++;
    426429    }
    427430
     
    439442    KapaSection section;
    440443
    441     if (!DEBUG && !pmVisualIsVisual()) return true;
     444    if (!pmVisualTestLevel("psphot.moments", 1)) return true;
    442445
    443446    int myKapa = psphotKapaChannel (2);
     
    456459    float Ymin = 1000.0, Ymax = 0.0;
    457460    {
    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         }
     461        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     462        for (int n = 0; n < nRegions; n++) {
     463
     464            char regionName[64];
     465            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     466            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     467
     468            float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     469            float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     470            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     471            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     472
     473            float X0 = psfX - 4.0*psfdX;
     474            float X1 = psfX + 4.0*psfdX;
     475            float Y0 = psfY - 4.0*psfdY;
     476            float Y1 = psfY + 4.0*psfdY;
     477
     478            if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); }
     479            if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); }
     480            if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); }
     481            if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); }
     482        }
    480483    }
    481484    Xmin = PS_MAX(Xmin, -0.1);
     
    498501    int nF = 0;
    499502    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++;
     503        pmSource *source = sources->data[i];
     504        if (source->moments == NULL)
     505            continue;
     506
     507        xFaint->data.F32[nF] = source->moments->Mxx;
     508        yFaint->data.F32[nF] = source->moments->Myy;
     509        mFaint->data.F32[nF] = -2.5*log10(source->moments->Sum);
     510        nF++;
     511
     512        // XXX make this a user-defined cutoff
     513        if (source->moments->SN < SN_LIM)
     514            continue;
     515
     516        xBright->data.F32[nB] = source->moments->Mxx;
     517        yBright->data.F32[nB] = source->moments->Myy;
     518        mBright->data.F32[nB] = -2.5*log10(source->moments->Sum);
     519        nB++;
    517520    }
    518521    xFaint->n = nF;
     
    652655    // draw N circles to outline the clumps
    653656    {
    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);
     657        KapaSelectSection (myKapa, "MxxMyy");
     658
     659        // draw a circle centered on psfX,Y with size of the psf limit
     660        psVector *xLimit  = psVectorAlloc (120, PS_TYPE_F32);
     661        psVector *yLimit  = psVectorAlloc (120, PS_TYPE_F32);
     662
     663        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     664        float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
     665
     666        graphdata.color = KapaColorByName ("blue");
     667        graphdata.style = 0;
     668
     669        graphdata.xmin = Xmin;
     670        graphdata.ymin = Ymin;
     671        graphdata.xmax = Xmax;
     672        graphdata.ymax = Ymax;
     673        KapaSetLimits (myKapa, &graphdata);
     674
     675        for (int n = 0; n < nRegions; n++) {
     676
     677            char regionName[64];
     678            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     679            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     680
     681            float psfX  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     682            float psfY  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     683            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     684            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     685            float Rx = psfdX * PSF_CLUMP_NSIGMA;
     686            float Ry = psfdY * PSF_CLUMP_NSIGMA;
     687
     688            for (int i = 0; i < xLimit->n; i++) {
     689                xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX;
     690                yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY;
     691            }
     692            KapaPrepPlot (myKapa, xLimit->n, &graphdata);
     693            KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x");
     694            KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y");
     695        }
     696        psFree (xLimit);
     697        psFree (yLimit);
    695698    }
    696699
     
    721724    for (int i = 0; i < sources->n; i++) {
    722725
    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 ++;
     726        pmSource *source = sources->data[i];
     727        if (source == NULL) continue;
     728
     729        if (source->type != type) continue;
     730        if (mode && !(source->mode & mode)) continue;
     731
     732        pmMoments *moments = source->moments;
     733        if (moments == NULL) continue;
     734
     735        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     736        overlay[Noverlay].x = moments->Mx;
     737        overlay[Noverlay].y = moments->My;
     738
     739        emoments.x2 = moments->Mxx;
     740        emoments.y2 = moments->Myy;
     741        emoments.xy = moments->Mxy;
     742
     743        axes = psEllipseMomentsToAxes (emoments, 20.0);
     744
     745        overlay[Noverlay].dx = 2.0*axes.major;
     746        overlay[Noverlay].dy = 2.0*axes.minor;
     747        overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
     748        overlay[Noverlay].text = NULL;
     749        Noverlay ++;
    747750    }
    748751
     
    753756}
    754757
     758// XXX : requires psphotVisualShowImage
    755759bool psphotVisualShowRoughClass (psArray *sources) {
    756760
    757     if (!DEBUG && !pmVisualIsVisual()) return true;
     761    if (!pmVisualTestLevel("psphot.objects.size", 3)) return true;
    758762
    759763    int myKapa = psphotKapaChannel (1);
     
    776780bool psphotVisualShowPSFModel (pmReadout *readout, pmPSF *psf) {
    777781
    778     if (!DEBUG && !pmVisualIsVisual()) return true;
     782    if (!pmVisualTestLevel("psphot.psf.model", 1)) return true;
    779783
    780784    int myKapa = psphotKapaChannel (3);
     
    797801    // generate a fake model at each of the 3x3 image grid positions
    798802    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         }
     803        for (int y = -2; y <= +2; y ++) {
     804            // use the center of the center pixel of the image
     805            float xc = (int)((0.5 + 0.225*x)*readout->image->numCols) + readout->image->col0 + 0.5;
     806            float yc = (int)((0.5 + 0.225*y)*readout->image->numRows) + readout->image->row0 + 0.5;
     807
     808            // assign the x and y coords to the image center
     809            // create an object with center intensity of 1000
     810            modelRef->params->data.F32[PM_PAR_SKY] = 0;
     811            modelRef->params->data.F32[PM_PAR_I0] = 1000;
     812            modelRef->params->data.F32[PM_PAR_XPOS] = xc;
     813            modelRef->params->data.F32[PM_PAR_YPOS] = yc;
     814
     815            // create modelPSF from this model
     816            pmModel *model = pmModelFromPSF (modelRef, psf);
     817            if (!model) continue;
     818
     819            // place the reference object in the image center
     820            // no need to mask the source here
     821            // XXX should we measure this for the analytical model only or the full model?
     822            pmModelAddWithOffset (psfMosaic, NULL, model, PM_MODEL_OP_FULL | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
     823            pmModelAddWithOffset (funMosaic, NULL, model, PM_MODEL_OP_FUNC | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
     824            pmModelAddWithOffset (resMosaic, NULL, model, PM_MODEL_OP_RES0 | PM_MODEL_OP_RES1 | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
     825            psFree (model);
     826        }
    823827    }
    824828
     
    842846    bool status;
    843847
    844     if (!DEBUG && !pmVisualIsVisual()) return true;
     848    if (!pmVisualTestLevel("psphot.psf.stars", 2)) return true;
    845849
    846850    int myKapa = psphotKapaChannel (3);
     
    871875    for (int i = 0; i < sources->n; i++) {
    872876
    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         }
     877        pmSource *source = sources->data[i];
     878
     879        bool keep = false;
     880        keep |= (source->mode & PM_SOURCE_MODE_PSFSTAR);
     881        if (!keep) continue;
     882
     883        // how does this subimage get placed into the output image?
     884        // DX = source->pixels->numCols
     885        // DY = source->pixels->numRows
     886
     887        if (dX + DX > NX) {
     888            // too wide for the rest of this row
     889            if (dX == 0) {
     890                // alone on this row
     891                NY += DY;
     892                dX = 0;
     893                dY = 0;
     894            } else {
     895                // start the next row
     896                NY += dY;
     897                dX = DX;
     898                dY = DY;
     899            }
     900        } else {
     901            // extend this row
     902            dX += DX;
     903            dY = PS_MAX (dY, DY);
     904        }
    901905    }
    902906    NY += DY;
     
    918922    for (int i = 0; i < sources->n; i++) {
    919923
    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         }
     924        pmSource *source = sources->data[i];
     925
     926        bool keep = false;
     927        if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
     928            nPSF ++;
     929            keep = true;
     930        }
     931        if (!keep) continue;
     932
     933        if (Xo + DX > NX) {
     934            // too wide for the rest of this row
     935            if (Xo == 0) {
     936                // place source alone on this row
     937                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     938                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     939                psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
     940
     941                pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     942                psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
     943
     944                if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     945
     946                Yo += DY;
     947                Xo = 0;
     948                dY = 0;
     949            } else {
     950                // start the next row
     951                Yo += dY;
     952                Xo = 0;
     953
     954                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     955                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     956                psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
     957
     958                pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     959                psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
     960
     961                if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     962
     963                Xo = DX;
     964                dY = DY;
     965            }
     966        } else {
     967            // extend this row
     968            bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     969            if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     970            psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
     971
     972            pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     973            psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
     974            if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     975
     976            Xo += DX;
     977            dY = PS_MAX (dY, DY);
     978        }
    975979    }
    976980
     
    994998    bool status;
    995999
    996     if (!DEBUG && !pmVisualIsVisual()) return true;
     1000    if (!pmVisualTestLevel("psphot.psf.sat", 3)) return true;
    9971001
    9981002    int myKapa = psphotKapaChannel (3);
     
    10231027    for (int i = 0; i < sources->n; i++) {
    10241028
    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         }
     1029        pmSource *source = sources->data[i];
     1030
     1031        // only show "real" saturated stars (not defects)
     1032        if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;;
     1033        if (source->mode & PM_SOURCE_MODE_DEFECT) continue;;
     1034
     1035        // how does this subimage get placed into the output image?
     1036        // DX = source->pixels->numCols
     1037        // DY = source->pixels->numRows
     1038
     1039        if (dX + DX > NX) {
     1040            // too wide for the rest of this row
     1041            if (dX == 0) {
     1042                // alone on this row
     1043                NY += DY;
     1044                dX = 0;
     1045                dY = 0;
     1046            } else {
     1047                // start the next row
     1048                NY += dY;
     1049                dX = DX;
     1050                dY = DY;
     1051            }
     1052        } else {
     1053            // extend this row
     1054            dX += DX;
     1055            dY = PS_MAX (dY, DY);
     1056        }
    10531057    }
    10541058    NY += DY;
     
    10681072    for (int i = 0; i < sources->n; i++) {
    10691073
    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         }
     1074        pmSource *source = sources->data[i];
     1075
     1076        // only show "real" saturated stars (not defects)
     1077        if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;;
     1078        if (source->mode & PM_SOURCE_MODE_DEFECT) continue;;
     1079        nSAT ++;
     1080
     1081        if (Xo + DX > NX) {
     1082            // too wide for the rest of this row
     1083            if (Xo == 0) {
     1084                // place source alone on this row
     1085                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     1086                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     1087                psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
     1088                if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     1089
     1090                Yo += DY;
     1091                Xo = 0;
     1092                dY = 0;
     1093            } else {
     1094                // start the next row
     1095                Yo += dY;
     1096                Xo = 0;
     1097
     1098                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     1099                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     1100                psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
     1101                if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     1102
     1103                Xo = DX;
     1104                dY = DY;
     1105            }
     1106        } else {
     1107            // extend this row
     1108            bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     1109            if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     1110            psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
     1111            if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     1112
     1113            Xo += DX;
     1114            dY = PS_MAX (dY, DY);
     1115        }
    11121116    }
    11131117
     
    11511155    float Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS] - source->pixels->row0;
    11521156    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         }
     1157        for (int ix = 0; ix < source->pixels->numCols; ix++) {
     1158            if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
     1159                rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
     1160                // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ;
     1161                Rb->data.F32[nb] = log10(rb->data.F32[nb]);
     1162                fb->data.F32[nb] = log10(source->pixels->data.F32[iy][ix]);
     1163                nb++;
     1164            } else {
     1165                rg->data.F32[ng] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
     1166                // rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ;
     1167                Rg->data.F32[ng] = log10(rg->data.F32[ng]);
     1168                fg->data.F32[ng] = log10(source->pixels->data.F32[iy][ix]);
     1169                ng++;
     1170            }
     1171        }
    11681172    }
    11691173
     
    13581362    KapaSection section;  // put the positive profile in one and the residuals in another?
    13591363
    1360     if (!DEBUG && !pmVisualIsVisual()) return true;
     1364    if (!pmVisualTestLevel("psphot.profiles", 3)) return true;
    13611365
    13621366    int myKapa = psphotKapaChannel (2);
     
    13941398    for (int i = 0; i < sources->n; i++) {
    13951399
    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         }
     1400        pmSource *source = sources->data[i];
     1401        if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
     1402
     1403        psphotVisualPlotRadialProfile (myKapa, source, maskVal);
     1404
     1405        // pause and wait for user input:
     1406        // continue, save (provide name), ??
     1407        char key[10];
     1408        fprintf (stdout, "[e]rase and continue? [o]verplot and continue? [s]kip rest of stars? : ");
     1409        if (!fgets(key, 8, stdin)) {
     1410            psWarning("Unable to read option");
     1411        }
     1412        if (key[0] == 'e') {
     1413            KapaClearPlots (myKapa);
     1414        }
     1415        if (key[0] == 's') {
     1416            break;
     1417        }
    14141418    }
    14151419
     
    14291433    return true;
    14301434
    1431     if (!DEBUG && !pmVisualIsVisual()) return true;
     1435    if (!pmVisualTestLevel("psphot.objects.flags", 3)) return true;
    14321436
    14331437    int myKapa = psphotKapaChannel (1);
     
    14451449    for (int i = 0; i < sources->n; i++) {
    14461450
    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         }
     1451        float Xo, Yo, Rmaj, Rmin, cs, sn;
     1452
     1453        pmSource *source = sources->data[i];
     1454        if (source == NULL) continue;
     1455
     1456        pmMoments *moments = source->moments;
     1457        if (0) {
     1458            emoments.x2 = moments->Mxx;
     1459            emoments.y2 = moments->Myy;
     1460            emoments.xy = moments->Mxy;
     1461            Xo = moments->Mx;
     1462            Yo = moments->My;
     1463
     1464            axes = psEllipseMomentsToAxes (emoments, 20.0);
     1465            Rmaj = 2.0*axes.major;
     1466            Rmin = 2.0*axes.minor;
     1467            cs = cos(axes.theta);
     1468            sn = sin(axes.theta);
     1469        } else {
     1470            Rmaj = Rmin = 5.0;
     1471            cs = 1.0;
     1472            sn = 0.0;
     1473            Xo = source->peak->xf;
     1474            Yo = source->peak->yf;
     1475        }
     1476
     1477        unsigned short int flagMask = 0x01;
     1478        for (int j = 0; j < 8; j++) {
     1479            if (source->mode & flagMask) {
     1480                overlayE[NoverlayE].type = KII_OVERLAY_LINE;
     1481                overlayE[NoverlayE].x = Xo;
     1482                overlayE[NoverlayE].y = Yo;
     1483
     1484                float phi = j*M_PI/4.0;
     1485                overlayE[NoverlayE].dx = +Rmaj*cos(phi)*cs - Rmin*sin(phi)*sn;
     1486                overlayE[NoverlayE].dy = +Rmaj*cos(phi)*sn + Rmin*sin(phi)*cs;
     1487                overlayE[NoverlayE].angle = 0;
     1488                overlayE[NoverlayE].text = NULL;
     1489                NoverlayE ++;
     1490                CHECK_REALLOCATE (overlayE, KiiOverlay, NOVERLAYE, NoverlayE, 100);
     1491            }
     1492            flagMask <<= 1;
     1493
     1494            if (source->mode & flagMask) {
     1495                overlayO[NoverlayO].type = KII_OVERLAY_LINE;
     1496                overlayO[NoverlayO].x = Xo + 1;
     1497                overlayO[NoverlayO].y = Yo;
     1498
     1499                float phi = j*M_PI/4.0;
     1500                overlayO[NoverlayO].dx = +Rmaj*cos(phi)*cs - Rmin*sin(phi)*sn;
     1501                overlayO[NoverlayO].dy = +Rmaj*cos(phi)*sn + Rmin*sin(phi)*cs;
     1502                overlayO[NoverlayO].angle = 0;
     1503                overlayO[NoverlayO].text = NULL;
     1504                NoverlayO ++;
     1505                CHECK_REALLOCATE (overlayO, KiiOverlay, NOVERLAYO, NoverlayO, 100);
     1506            }
     1507            flagMask <<= 1;
     1508        }
    15051509    }
    15061510
     
    15311535    for (int i = 0; i < sources->n; i++) {
    15321536
    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 ++;
     1537        pmSource *source = sources->data[i];
     1538        if (source == NULL) continue;
     1539
     1540        if (mode) {
     1541            if (keep) {
     1542                if (!(source->mode & mode)) continue;
     1543            } else {
     1544                if (source->mode & mode) continue;
     1545            }
     1546        }
     1547
     1548        pmMoments *moments = source->moments;
     1549        if (moments == NULL) continue;
     1550
     1551        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     1552        overlay[Noverlay].x = moments->Mx;
     1553        overlay[Noverlay].y = moments->My;
     1554
     1555        emoments.x2 = moments->Mxx;
     1556        emoments.y2 = moments->Myy;
     1557        emoments.xy = moments->Mxy;
     1558
     1559        axes = psEllipseMomentsToAxes (emoments, 20.0);
     1560
     1561        overlay[Noverlay].dx = scale*2.0*axes.major;
     1562        overlay[Noverlay].dy = scale*2.0*axes.minor;
     1563        overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
     1564        overlay[Noverlay].text = NULL;
     1565        Noverlay ++;
    15621566    }
    15631567
     
    15701574bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources) {
    15711575
    1572     if (!DEBUG && !pmVisualIsVisual()) return true;
     1576    if (!pmVisualTestLevel("psphot.objects.size", 2)) return true;
    15731577
    15741578    int myKapa = psphotKapaChannel (1);
     
    15971601    KapaSection section;
    15981602
    1599     if (!DEBUG && !pmVisualIsVisual()) return true;
     1603    if (!pmVisualTestLevel("psphot.size", 2)) return true;
    16001604
    16011605    int myKapa = psphotKapaChannel (2);
     
    16121616    float Ymin = 1000.0, Ymax = 0.0;
    16131617    {
    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         }
     1618        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     1619        for (int n = 0; n < nRegions; n++) {
     1620
     1621            char regionName[64];
     1622            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     1623            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     1624
     1625            float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     1626            float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     1627            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     1628            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     1629
     1630            float X0 = psfX - 10.0*psfdX;
     1631            float X1 = psfX + 10.0*psfdX;
     1632            float Y0 = psfY - 10.0*psfdY;
     1633            float Y1 = psfY + 10.0*psfdY;
     1634
     1635            if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); }
     1636            if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); }
     1637            if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); }
     1638            if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); }
     1639        }
    16361640    }
    16371641    Xmin = PS_MAX(Xmin, -0.1);
     
    16771681    int nCR  = 0;
    16781682    for (int i = 0; i < sources->n; i++) {
    1679         pmSource *source = sources->data[i];
    1680         if (source->moments == NULL) continue;
     1683        pmSource *source = sources->data[i];
     1684        if (source->moments == NULL) continue;
    16811685
    16821686        // 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++;
     1687        if (!(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED)) continue;
     1688
     1689        if (source->mode & PM_SOURCE_MODE_CR_LIMIT) {
     1690            xCR->data.F32[nCR] = source->moments->Mxx;
     1691            yCR->data.F32[nCR] = source->moments->Myy;
     1692            mCR->data.F32[nCR] = -2.5*log10(source->moments->Sum);
     1693            sCR->data.F32[nCR] = source->extNsigma;
     1694            nCR++;
     1695        }
     1696        if (source->mode & PM_SOURCE_MODE_SATSTAR) {
     1697            xSAT->data.F32[nSAT] = source->moments->Mxx;
     1698            ySAT->data.F32[nSAT] = source->moments->Myy;
     1699            mSAT->data.F32[nSAT] = -2.5*log10(source->moments->Sum);
     1700            sSAT->data.F32[nSAT] = source->extNsigma;
     1701            nSAT++;
     1702        }
     1703        if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
     1704            xEXT->data.F32[nEXT] = source->moments->Mxx;
     1705            yEXT->data.F32[nEXT] = source->moments->Myy;
     1706            mEXT->data.F32[nEXT] = -2.5*log10(source->moments->Sum);
     1707            sEXT->data.F32[nEXT] = source->extNsigma;
     1708            nEXT++;
     1709            continue;
     1710        }
     1711        if (source->mode & PM_SOURCE_MODE_DEFECT) {
     1712            xDEF->data.F32[nDEF] = source->moments->Mxx;
     1713            yDEF->data.F32[nDEF] = source->moments->Myy;
     1714            mDEF->data.F32[nDEF] = -2.5*log10(source->moments->Sum);
     1715            sDEF->data.F32[nDEF] = source->extNsigma;
     1716            nDEF++;
     1717            continue;
     1718        }
     1719        if (source->errMag > 0.1) {
     1720            xLOW->data.F32[nLOW] = source->moments->Mxx;
     1721            yLOW->data.F32[nLOW] = source->moments->Myy;
     1722            mLOW->data.F32[nLOW] = -2.5*log10(source->moments->Sum);
     1723            sLOW->data.F32[nLOW] = source->extNsigma;
     1724            nLOW++;
     1725            continue;
     1726        }
     1727        xPSF->data.F32[nPSF] = source->moments->Mxx;
     1728        yPSF->data.F32[nPSF] = source->moments->Myy;
     1729        mPSF->data.F32[nPSF] = -2.5*log10(source->moments->Sum);
     1730        sPSF->data.F32[nPSF] = source->extNsigma;
     1731        nPSF++;
    17281732    }
    17291733
     
    20292033    // draw N circles to outline the clumps
    20302034    {
    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);
     2035        KapaSelectSection (myKapa, "MxxMyy");
     2036
     2037        // draw a circle centered on psfX,Y with size of the psf limit
     2038        psVector *xLimit  = psVectorAlloc (120, PS_TYPE_F32);
     2039        psVector *yLimit  = psVectorAlloc (120, PS_TYPE_F32);
     2040
     2041        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     2042        float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
     2043
     2044        graphdata.color = KapaColorByName ("blue");
     2045        graphdata.style = 0;
     2046
     2047        graphdata.xmin = Xmin;
     2048        graphdata.ymin = Ymin;
     2049        graphdata.xmax = Xmax;
     2050        graphdata.ymax = Ymax;
     2051        KapaSetLimits (myKapa, &graphdata);
     2052
     2053        for (int n = 0; n < nRegions; n++) {
     2054
     2055            char regionName[64];
     2056            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     2057            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     2058
     2059            float psfX  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     2060            float psfY  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     2061            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     2062            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     2063            float Rx = psfdX * PSF_CLUMP_NSIGMA;
     2064            float Ry = psfdY * PSF_CLUMP_NSIGMA;
     2065
     2066            for (int i = 0; i < xLimit->n; i++) {
     2067                xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX;
     2068                yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY;
     2069            }
     2070            KapaPrepPlot (myKapa, xLimit->n, &graphdata);
     2071            KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x");
     2072            KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y");
     2073        }
     2074        psFree (xLimit);
     2075        psFree (yLimit);
    20722076    }
    20732077
     
    21082112bool psphotVisualShowResidualImage (pmReadout *readout) {
    21092113
    2110     if (!DEBUG && !pmVisualIsVisual()) return true;
     2114    if (!pmVisualTestLevel("psphot.image.resid", 2)) return true;
    21112115
    21122116    int myKapa = psphotKapaChannel (1);
     
    21242128    float lineX[2], lineY[2];
    21252129
    2126     if (!DEBUG && !pmVisualIsVisual()) return true;
     2130    if (!pmVisualTestLevel("psphot.apresid", 1)) return true;
    21272131
    21282132    int myKapa = psphotKapaChannel (2);
     
    21442148    int n = 0;
    21452149    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++;
     2150        pmSource *source = sources->data[i];
     2151        if (!source) continue;
     2152        if (source->type != PM_SOURCE_TYPE_STAR) continue;
     2153        if (!isfinite (source->apMag)) continue;
     2154        if (!isfinite (source->psfMag)) continue;
     2155
     2156        x->data.F32[n] = source->psfMag;
     2157        y->data.F32[n] = source->apMag - source->psfMag;
     2158        dy->data.F32[n] = source->errMag;
     2159        graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
     2160        graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
     2161        graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
     2162        graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
     2163
     2164        n++;
    21612165    }
    21622166    x->n = y->n = dy->n = n;
     
    22422246    Graphdata graphdata;
    22432247
    2244     if (!DEBUG && !pmVisualIsVisual()) return true;
     2248    if (!pmVisualTestLevel("psphot.chisq", 1)) return true;
    22452249
    22462250    int myKapa = psphotKapaChannel (2);
     
    22632267    int n = 0;
    22642268    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++;
     2269        pmSource *source = sources->data[i];
     2270        if (!source) continue;
     2271        if (source->type != PM_SOURCE_TYPE_STAR) continue;
     2272        if (!source->moments) continue;
     2273        if (!isfinite(source->moments->Sum)) continue;
     2274        if (!source->modelPSF) continue;
     2275        if (!isfinite(source->modelPSF->chisq)) continue;
     2276
     2277        x->data.F32[n] = -2.5*log10(source->moments->Sum);
     2278        y->data.F32[n] = source->modelPSF->chisq / source->modelPSF->nDOF;
     2279        graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
     2280        graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
     2281        graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
     2282        graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
     2283
     2284        fprintf (f, "%d %d %f %f\n", i, n, x->data.F32[n], y->data.F32[n]);
     2285
     2286        n++;
    22832287    }
    22842288    x->n = y->n = n;
     
    23262330    KiiOverlay *overlay;
    23272331
    2328     if (!DEBUG && !pmVisualIsVisual()) return true;
     2332    if (!pmVisualTestLevel("psphot.objects.petro", 2)) return true;
    23292333
    23302334    int kapa = psphotKapaChannel (1);
     
    23362340
    23372341    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;
     2342        pmSource *source = sources->data[i];
     2343
     2344        if (!source) continue;
     2345        if (!source->extpars) continue;
     2346        if (!source->extpars->petProfile) continue;
     2347
     2348        float petrosianRadius = source->extpars->petrosianRadius;
    23452349        psEllipseAxes *axes = &source->extpars->axes;
    23462350
    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);
     2351        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     2352        overlay[Noverlay].x = source->peak->xf;
     2353        overlay[Noverlay].y = source->peak->yf;
     2354        overlay[Noverlay].dx = 1.0*petrosianRadius;
     2355        overlay[Noverlay].dy = 1.0*petrosianRadius*axes->minor/axes->major;
     2356        overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
     2357        overlay[Noverlay].text = NULL;
     2358        Noverlay ++;
     2359        CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     2360
     2361        // overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     2362        // overlay[Noverlay].x = source->peak->xf;
     2363        // overlay[Noverlay].y = source->peak->yf;
     2364        // overlay[Noverlay].dx = 2.0*petrosianRadius;
     2365        // overlay[Noverlay].dy = 2.0*petrosianRadius*axes->minor/axes->major;
     2366        // overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
     2367        // overlay[Noverlay].text = NULL;
     2368        // Noverlay ++;
     2369        // CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    23662370    }
    23672371
Note: See TracChangeset for help on using the changeset viewer.