IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 34368


Ignore:
Timestamp:
Aug 30, 2012, 6:10:52 AM (14 years ago)
Author:
eugene
Message:

some generalization of visualization code; add radial profile fits to deblend satstars (still testing)

Location:
branches/eam_branches/ipp-20120805/psphot/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20120805/psphot/src/psphot.h

    r34360 r34368  
    281281bool            psphotVisualShowSatStars (psMetadata *recipe, pmPSF *psf, psArray *sources);
    282282bool            psphotVisualShowPSFModel (pmReadout *readout, pmPSF *psf);
    283 bool            psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal);
     283bool            psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal, pmSourceMode showmode);
    284284bool            psphotVisualPlotRadialProfiles (psMetadata *recipe, psArray *sources, pmSourceMode showmode);
    285285bool            psphotVisualShowFlags (psArray *sources);
     
    295295bool            psphotVisualClose(void);
    296296
     297int             psphotKapaChannel (int channel);
     298void            plotline (int myKapa, Graphdata *graphdata, float x0, float y0, float x1, float y1);
     299
     300
    297301bool psphotPetrosian (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal);
    298302bool psphotPetrosianRadialBins (pmSource *source, float radiusMax, float skynoise);
  • branches/eam_branches/ipp-20120805/psphot/src/psphotDeblendSatstars.c

    r34360 r34368  
    11# include "psphotInternal.h"
     2
     3typedef struct {
     4    float min;
     5    float max;
     6    float lower20;
     7    float upper20;
     8    int Npts;
     9} QuickStats;
     10
     11bool psImageQuickStats (QuickStats *stats, psImage *image, psRegion region);
     12
     13bool  psphotTestRadialModel (pmSource *source, psVector **logRmodelOut, psVector **logFmodelOut, psVector *logFlux, psVector *logRad, float Rmax);
     14bool  psphotTestRadialModelSub (pmSource *source, psVector *logRmodel, psVector *logFmodel, float Xo, float Yo, float Rmax, psImageMaskType maskVal);
     15bool  psphotVisualRadialProfileSatstar (pmSource *source, psImageMaskType maskVal);
     16float InterpolateValues (float X0, float Y0, float X1, float Y1, float X);
     17bool  psphotVisualScaleImage (int kapaFD, psImage *inImage, psImage *inMask, const char *name, float factor, int channel);
    218
    319// for now, let's store the detections on the readout->analysis for each readout
     
    1733
    1834bool psphotDeblendSatstarsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int fileIndex) {
     35
     36    int N;
     37    pmSource *source;
     38    bool status;
     39
     40    psTimerStart ("psphot.deblend.sat");
     41
     42    // find the currently selected readout
     43    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, fileIndex); // 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->newSources;
     53    psAssert (sources, "missing sources?");
     54
     55    if (!sources->n) {
     56        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping satstar blend");
     57        return true;
     58    }
     59
     60    // select the appropriate recipe information
     61    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     62    psAssert (recipe, "missing recipe?");
     63
     64    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     65    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
     66    assert (maskVal);
     67
     68    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     69    psImageMaskType maskSat = psMetadataLookupImageMask(&status, recipe, "MASK.SAT"); // Mask value for bad pixels
     70    assert (maskSat);
     71
     72    float SATURATION = NAN;
     73    {
     74        // XXX do we need to set this differently from the value used to mark saturated pixels?
     75        pmCell *cell     = readout->parent;
     76
     77        // do not completely trust the values in the header...
     78        float CELL_SATURATION = psMetadataLookupF32 (&status, cell->concepts, "CELL.SATURATION");
     79        float MIN_SATURATION = psMetadataLookupF32 (&status, recipe, "DEBLEND_MIN_SATURATION");
     80        if (!status || !isfinite(MIN_SATURATION)) {
     81            MIN_SATURATION = 40000.0;
     82        }
     83        if (!isfinite(CELL_SATURATION)) {
     84            SATURATION = MIN_SATURATION;
     85        } else {
     86            SATURATION = PS_MAX(MIN_SATURATION, CELL_SATURATION);
     87        }
     88    }
     89
     90    // source analysis is done in peak order (brightest first)
     91    // we use an index for this so the spatial sorting is kept
     92    psVector *SN = psVectorAlloc (sources->n, PS_DATA_F32);
     93    for (int i = 0; i < SN->n; i++) {
     94        source = sources->data[i];
     95        SN->data.F32[i] = source->moments->SN;
     96    }
     97    psVector *index = psVectorSortIndex (NULL, SN);
     98    // this results in an index of increasing SN
     99
     100    // psphotVisualPlotRadialProfiles (recipe, sources, PM_SOURCE_MODE_SATSTAR);
     101
     102    int BIG_RADIUS = 250;
     103    int BIG_SIGMA = BIG_RADIUS / 4.0;
     104
     105    int display = psphotKapaChannel (1);
     106    psphotVisualScaleImage (display, (psImage *) source->pixels->parent, NULL, "image", 1.0, 0);
     107
     108    // examine sources in decreasing SN order
     109    for (int i = sources->n - 1; i >= 0; i--) {
     110        N = index->data.U32[i];
     111        source = sources->data[N];
     112
     113        bool isSat = source->mode & PM_SOURCE_MODE_SATSTAR;
     114
     115        // for fairly bright stars, check the pixels near the peak again
     116        if (source->moments->Peak > 0.5*SATURATION) {
     117            // pmSourceRoughClass does this analysis, but uses a small (5x5) window.
     118            // here we use a larger window since stacks can have some funny features
     119            psRegion inner;
     120            QuickStats stats;
     121            // grow out the search radius until we have lower20 < 0.1*SATURATION
     122            for (int radius = 2; radius < 30; radius ++) {
     123                inner = psRegionForSquare (source->peak->x, source->peak->y, radius);
     124                inner = psRegionForImage (source->maskView, inner);
     125                psImageQuickStats (&stats, readout->image, inner);
     126                if ((stats.Npts > 1) && (stats.lower20 < 0.1*SATURATION)) break;
     127            }
     128            int Nsatpix = psImageCountPixelMask (source->maskView, inner, maskSat);
     129            // fprintf (stderr, "test object: %d,%d : %d vs %d : %f - %f - %f - %f\n",
     130            // source->peak->x, source->peak->y, Nsatpix, stats.Npts,
     131            // stats.min, stats.lower20, stats.upper20, stats.max);
     132            if (Nsatpix > 1) isSat = true;
     133        }
     134        if (!isSat) continue;
     135
     136        // For saturated stars, choose a much larger box NOTE this is slightly sleazy, but
     137        // only slightly: pmSourceRedefinePixels uses the readout to pass the pointers to
     138        // the parent image data.  I guess the API could be simplified: we could recover
     139        // this from the source in the function
     140
     141        pmReadout tmpReadout;
     142        tmpReadout.image    = (psImage *)source->pixels->parent;
     143        tmpReadout.mask     = (psImage *)source->maskView->parent;
     144        tmpReadout.variance = (psImage *)source->variance->parent;
     145
     146        // re-allocate image, weight, mask arrays for each peak with box big enough to fit BIG_RADIUS
     147        pmSourceRedefinePixels (source, &tmpReadout, source->peak->x, source->peak->y, BIG_RADIUS + 2);
     148
     149        psTrace ("psphot", 4, "retrying moments for %d, %d\n", source->peak->x, source->peak->y);
     150        status = pmSourceMoments (source, BIG_RADIUS, BIG_SIGMA, 0.0, 5.0, maskVal);
     151        source->mode |= PM_SOURCE_MODE_BIG_RADIUS;
     152
     153        // XXX visualize, model, and subtract
     154        if (!psphotVisualRadialProfileSatstar (source, maskVal)) {
     155          break;
     156        }
     157
     158        // generate radial profile, store on the source structure
     159    }
     160    // show the image after object have been subtracted
     161    psphotVisualScaleImage (display, (psImage *) source->pixels->parent, NULL, "image", 1.0, 1);
     162
     163    psFree (SN);
     164    psFree (index);
     165
     166    psLogMsg ("psphot", PS_LOG_INFO, "deblend satstar: %f sec\n", psTimerMark ("psphot.deblend.sat"));
     167    return true;
     168}
     169
     170bool psphotDeblendSatstarsReadoutOld (pmConfig *config, const pmFPAview *view, const char *filerule, int fileIndex) {
    19171
    20172    int N;
     
    78230    psVector *index = psVectorSortIndex (NULL, SN);
    79231    // this results in an index of increasing SN
    80 
    81     psphotVisualPlotRadialProfiles (recipe, sources, PM_SOURCE_MODE_SATSTAR);
    82232
    83233    // examine sources in decreasing SN order
     
    222372}
    223373
    224 bool psphotDeblendSatstarsReadoutOld (pmConfig *config, const pmFPAview *view, const char *filerule, int fileIndex) {
    225 
    226     int N;
    227     pmSource *source;
    228     bool status;
    229 
    230     psTimerStart ("psphot.deblend.sat");
    231 
    232     int Nblend = 0;
    233     float SAT_MIN_RADIUS = 5.0;
    234 
    235     // find the currently selected readout
    236     pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, fileIndex); // File of interest
    237     psAssert (file, "missing file?");
    238 
    239     pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
    240     psAssert (readout, "missing readout?");
    241 
    242     pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
    243     psAssert (detections, "missing detections?");
    244 
    245     psArray *sources = detections->newSources;
    246     psAssert (sources, "missing sources?");
    247 
    248     if (!sources->n) {
    249         psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping satstar blend");
    250         return true;
    251     }
    252 
    253     // select the appropriate recipe information
    254     psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
    255     psAssert (recipe, "missing recipe?");
    256 
    257     pmCell *cell = readout->parent;
    258 
    259     float SATURATION = NAN;
    260 
    261     // do not completely trust the values in the header...
    262     float CELL_SATURATION = psMetadataLookupF32 (&status, cell->concepts, "CELL.SATURATION");
    263     float MIN_SATURATION = psMetadataLookupF32 (&status, recipe, "DEBLEND_MIN_SATURATION");
    264     if (!status || !isfinite(MIN_SATURATION)) {
    265         MIN_SATURATION = 40000.0;
    266     }
    267     if (!isfinite(CELL_SATURATION)) {
    268         SATURATION = MIN_SATURATION;
     374static bool skipDisplay = false;
     375bool psphotVisualRadialProfileSatstar (pmSource *source, psImageMaskType maskVal) {
     376
     377    int kapaImage = -1;
     378    int kapaGraph = -1;
     379    Graphdata graphdata;
     380
     381    if (!pmVisualTestLevel("psphot.satstar", 3)) {
     382        skipDisplay = true;
     383    }
     384
     385    float Rmax = 320.0;
     386
     387    bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     388    if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     389
     390    int nPts = source->pixels->numRows * source->pixels->numCols;
     391    psVector *rg = psVectorAllocEmpty (nPts, PS_TYPE_F32);
     392    psVector *Rg = psVectorAllocEmpty (nPts, PS_TYPE_F32);
     393    psVector *fg = psVectorAllocEmpty (nPts, PS_TYPE_F32);
     394    psVector *Fg = psVectorAllocEmpty (nPts, PS_TYPE_F32);
     395    psVector *rb = psVectorAllocEmpty (nPts, PS_TYPE_F32);
     396    psVector *Rb = psVectorAllocEmpty (nPts, PS_TYPE_F32);
     397    psVector *fb = psVectorAllocEmpty (nPts, PS_TYPE_F32);
     398
     399    int ng = 0;
     400    int nb = 0;
     401
     402    float Xo = NAN;
     403    float Yo = NAN;
     404
     405    if (source->modelPSF) {
     406        Xo = source->modelPSF->params->data.F32[PM_PAR_XPOS] - source->pixels->col0;
     407        Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS] - source->pixels->row0;
    269408    } else {
    270         SATURATION = PS_MAX(MIN_SATURATION, CELL_SATURATION);
    271     }
    272     float SAT_TEST_LEVEL = 0.5*SATURATION;
    273 
    274     // we need sources spatially-sorted to find overlaps
    275     sources = psArraySort (sources, pmSourceSortByY);
    276 
    277     // source analysis is done in peak order (brightest first)
    278     // we use an index for this so the spatial sorting is kept
    279     psVector *SN = psVectorAlloc (sources->n, PS_DATA_F32);
    280     for (int i = 0; i < SN->n; i++) {
    281         source = sources->data[i];
    282         SN->data.F32[i] = source->peak->rawFlux;
    283     }
    284     psVector *index = psVectorSortIndex (NULL, SN);
    285     // this results in an index of increasing SN
    286 
    287     // examine sources in decreasing SN order
    288     for (int i = sources->n - 1; i >= 0; i--) {
    289         N = index->data.U32[i];
    290         source = sources->data[N];
    291 
    292         // XXX filter? if (source->mode & PM_SOURCE_MODE_SATSTAR) continue;
    293         if (source->mode & PM_SOURCE_MODE_BLEND) continue;
    294         if (source->peak->rawFlux < SAT_TEST_LEVEL) continue;
    295 
    296         // save these for reference below
    297         int xPeak = source->peak->x;
    298         int yPeak = source->peak->y;
    299 
    300         // generate a basic contour (set of x,y coordinates at-or-below flux level)
    301         psArray *contour = pmSourceContour (source->pixels, xPeak, yPeak, SAT_TEST_LEVEL);
    302         if (contour == NULL) continue;
    303 
    304         // contour consists of a set of X,Y coords giving the boundary
    305         psVector *xVec = contour->data[0];
    306         psVector *yVec = contour->data[1];
    307         if (xVec->n < 5) {
    308             psFree(contour);
    309             continue;
    310         }
    311 
    312         // find the center of the contour (let's just use mid[x,y])
    313         int xMin = xVec->data.F32[0];
    314         int xMax = xVec->data.F32[0];
    315         int yMin = yVec->data.F32[0];
    316         int yMax = yVec->data.F32[0];
    317         for (int j = 0; j < xVec->n; j++) {
    318             xMin = PS_MIN (xMin, xVec->data.F32[j]);
    319             xMax = PS_MAX (xMax, xVec->data.F32[j]);
    320             yMin = PS_MIN (yMin, yVec->data.F32[j]);
    321             yMax = PS_MAX (yMax, yVec->data.F32[j]);
    322         }       
    323         int xCenter = 0.5*(xMin + xMax);
    324         int yCenter = 0.5*(yMin + yMax);
    325         psFree (contour);
    326 
    327         psAssert (xCenter >= source->pixels->col0, "invalid shift in object center");
    328         psAssert (xCenter <  source->pixels->col0 + source->pixels->numCols, "invalid shift in object center");
    329         psAssert (yCenter >= source->pixels->row0, "invalid shift in object center");
    330         psAssert (yCenter <  source->pixels->row0 + source->pixels->numRows, "invalid shift in object center");
    331 
    332         // reset the peak for this source to the value of the center pixel
    333         source->peak->x = xCenter;
    334         source->peak->y = yCenter;
    335         source->peak->xf = xCenter;
    336         source->peak->yf = yCenter;
     409        Xo = source->moments->Mx - source->pixels->col0;
     410        Yo = source->moments->My - source->pixels->row0;
     411    }
     412
     413    for (int iy = 0; iy < source->pixels->numRows; iy++) {
     414        for (int ix = 0; ix < source->pixels->numCols; ix++) {
     415            if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) {
     416                rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
     417                // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ;
     418                Rb->data.F32[nb] = log10(rb->data.F32[nb]);
     419                fb->data.F32[nb] = log10(source->pixels->data.F32[iy][ix]);
     420                nb++;
     421            } else {
     422                rg->data.F32[ng] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
     423                // rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ;
     424                Rg->data.F32[ng] = log10(rg->data.F32[ng]);
     425                Fg->data.F32[ng] = source->pixels->data.F32[iy][ix];
     426                fg->data.F32[ng] = log10(Fg->data.F32[ng]);
     427                ng++;
     428            }
     429        }
     430    }
     431    rg->n = ng;
     432    Rg->n = ng;
     433    fg->n = ng;
     434    Fg->n = ng;
     435    rb->n = nb;
     436    Rb->n = nb;
     437    fb->n = nb;
     438
     439    if (!skipDisplay) {
     440        kapaImage = psphotKapaChannel (1);
     441        if (kapaImage == -1) return false;
     442
     443        kapaGraph = psphotKapaChannel (2);
     444        if (kapaGraph == -1) return false;
     445
     446        KapaSection section;  // put the positive profile in one and the residuals in another?
     447
     448        // first section : mag vs CR nSigma
     449        section.dx = 1.0;
     450        section.dy = 0.5;
     451        section.x = 0.0;
     452        section.y = 0.0;
     453        section.bg = -1;
     454        section.name = NULL;
     455        psStringAppend (&section.name, "linlog");
     456        KapaSetSection (kapaGraph, &section);
     457        psFree (section.name);
     458
     459        // first section : mag vs CR nSigma
     460        section.dx = 1.0;
     461        section.dy = 0.5;
     462        section.x = 0.0;
     463        section.y = 0.5;
     464        section.bg = -1;
     465        section.name = NULL;
     466        psStringAppend (&section.name, "loglog");
     467        KapaSetSection (kapaGraph, &section);
     468        psFree (section.name);
     469
     470        KapaInitGraph (&graphdata);
     471
     472        // ** linlog **
     473        KapaSelectSection (kapaGraph, "linlog");
     474
     475        // examine sources to set data range
     476        graphdata.xmin =  -0.05;
     477        graphdata.xmax = Rmax + 0.05;
     478        graphdata.ymin = -0.05;
     479        graphdata.ymax = +8.05;
     480        KapaSetLimits (kapaGraph, &graphdata);
     481
     482        KapaSetFont (kapaGraph, "helvetica", 14);
     483        KapaBox (kapaGraph, &graphdata);
     484        KapaSendLabel (kapaGraph, "radius (pixels)", KAPA_LABEL_XM);
     485        KapaSendLabel (kapaGraph, "log flux (counts)", KAPA_LABEL_YM);
     486
     487        graphdata.color = KapaColorByName ("black");
     488        graphdata.ptype = 2;
     489        graphdata.size = 0.5;
     490        graphdata.style = 2;
     491        KapaPrepPlot (kapaGraph, ng, &graphdata);
     492        KapaPlotVector (kapaGraph, ng, rg->data.F32, "x");
     493        KapaPlotVector (kapaGraph, ng, fg->data.F32, "y");
     494
     495        graphdata.color = KapaColorByName ("red");
     496        graphdata.ptype = 0;
     497        graphdata.size = 0.3;
     498        graphdata.style = 2;
     499        KapaPrepPlot (kapaGraph, nb, &graphdata);
     500        KapaPlotVector (kapaGraph, nb, rb->data.F32, "x");
     501        KapaPlotVector (kapaGraph, nb, fb->data.F32, "y");
     502
     503        // ** loglog **
     504        KapaSelectSection (kapaGraph, "loglog");
     505
     506        // examine sources to set data range
     507        graphdata.xmin = -1.51;
     508        graphdata.xmax = log10(Rmax) + 0.02;
     509        graphdata.ymin = -5.05;
     510        graphdata.ymax = +8.05;
     511        graphdata.color = KapaColorByName ("black");
     512        KapaSetLimits (kapaGraph, &graphdata);
     513
     514        KapaSetFont (kapaGraph, "helvetica", 14);
     515        KapaBox (kapaGraph, &graphdata);
     516        KapaSendLabel (kapaGraph, "log radius (pixels)", KAPA_LABEL_XM);
     517        KapaSendLabel (kapaGraph, "log flux (counts)", KAPA_LABEL_YM);
     518
     519        graphdata.color = KapaColorByName ("black");
     520        graphdata.ptype = 2;
     521        graphdata.size = 0.5;
     522        graphdata.style = 2;
     523        KapaPrepPlot (kapaGraph, ng, &graphdata);
     524        KapaPlotVector (kapaGraph, ng, Rg->data.F32, "x");
     525        KapaPlotVector (kapaGraph, ng, fg->data.F32, "y");
     526
     527        graphdata.color = KapaColorByName ("red");
     528        graphdata.ptype = 0;
     529        graphdata.size = 0.3;
     530        graphdata.style = 2;
     531        KapaPrepPlot (kapaGraph, nb, &graphdata);
     532        KapaPlotVector (kapaGraph, nb, Rb->data.F32, "x");
     533        KapaPlotVector (kapaGraph, nb, fb->data.F32, "y");
     534    }
     535
     536    // measure the radial profile
     537    psVector *logFmodel = NULL;
     538    psVector *logRmodel = NULL;
     539    psphotTestRadialModel (source, &logRmodel, &logFmodel, Rg, Fg, Rmax);
     540   
     541    if (!skipDisplay) {
     542        graphdata.color = KapaColorByName ("red");
     543        graphdata.ptype = 2;
     544        graphdata.size = 1.0;
     545        graphdata.style = 2;
     546        KapaPrepPlot (kapaGraph, logRmodel->n, &graphdata);
     547        KapaPlotVector (kapaGraph, logRmodel->n, logRmodel->data.F32, "x");
     548        KapaPlotVector (kapaGraph, logRmodel->n, logFmodel->data.F32, "y");
     549    }
     550
     551    // subtract the model from the images
     552    psphotTestRadialModelSub (source, logRmodel, logFmodel, Xo, Yo, Rmax, maskVal);
     553
     554    psFree (logRmodel);
     555    psFree (logFmodel);
     556
     557    if (!skipDisplay && source->modelPSF) {
     558        // generate model profiles (major and minor axis):
     559        // create a model with theta = 0.0 so major and minor axes are equiv to x and y:
     560        psEllipseShape rawShape, rotShape;
     561
     562        rawShape.sx  = source->modelPSF->params->data.F32[PM_PAR_SXX] / M_SQRT2;
     563        rawShape.sy  = source->modelPSF->params->data.F32[PM_PAR_SYY] / M_SQRT2;
     564        rawShape.sxy = source->modelPSF->params->data.F32[PM_PAR_SXY];
     565
     566        psEllipseAxes axes = psEllipseShapeToAxes (rawShape, 20.0);
     567
     568        axes.theta = 0.0;
     569
     570        rotShape = psEllipseAxesToShape (axes);
     571
     572        psVector *params = psVectorAlloc(source->modelPSF->params->n, PS_TYPE_F32);
     573        for (int i = 0; i < source->modelPSF->params->n; i++) {
     574            params->data.F32[i] = source->modelPSF->params->data.F32[i];
     575        }
     576        params->data.F32[PM_PAR_SXX] = rotShape.sx * M_SQRT2;
     577        params->data.F32[PM_PAR_SYY] = rotShape.sy * M_SQRT2;
     578        params->data.F32[PM_PAR_SXY] = rotShape.sxy;
     579        params->data.F32[PM_PAR_XPOS] = 0.0;
     580        params->data.F32[PM_PAR_YPOS] = 0.0;
     581
     582        psVector *rmod = psVectorAlloc(Rmax*10, PS_TYPE_F32);
     583        psVector *fmaj = psVectorAlloc(Rmax*10, PS_TYPE_F32);
     584        psVector *fmin = psVectorAlloc(Rmax*10, PS_TYPE_F32);
     585
     586        psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
     587
     588        float r = 0.0;
     589        for (int i = 0; i < rmod->n; i++) {
     590            r = i*0.1;
     591            rmod->data.F32[i] = r;
     592
     593            coord->data.F32[1] = r;
     594            coord->data.F32[0] = 0.0;
     595            fmaj->data.F32[i] = log10(source->modelPSF->modelFunc (NULL, params, coord));
     596
     597            coord->data.F32[0] = r;
     598            coord->data.F32[1] = 0.0;
     599            fmin->data.F32[i] = log10(source->modelPSF->modelFunc (NULL, params, coord));
     600        }
     601        psFree (coord);
     602        psFree (params);
     603
     604        float FWHM_MAJOR = 2.0*source->modelPSF->modelRadius (source->modelPSF->params, 0.5*source->modelPSF->params->data.F32[PM_PAR_I0]);
     605        float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
     606        if (FWHM_MAJOR < FWHM_MINOR) PS_SWAP (FWHM_MAJOR, FWHM_MINOR);
     607
     608        psEllipseMoments emoments;
     609        emoments.x2 = source->moments->Mxx;
     610        emoments.xy = source->moments->Mxy;
     611        emoments.y2 = source->moments->Myy;
     612        axes = psEllipseMomentsToAxes (emoments, 20.0);
     613        float MOMENTS_MAJOR = 2.355*axes.major;
     614        float MOMENTS_MINOR = 2.355*axes.minor;
     615
     616        float logHM = log10(0.5*source->modelPSF->params->data.F32[PM_PAR_I0]);
     617
     618        // reset source Add/Sub state to recorded
     619        if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     620
     621        // ** linlog **
     622        KapaSelectSection (kapaGraph, "linlog");
     623        KapaGetGraphData (kapaGraph, &graphdata);
     624        graphdata.color = KapaColorByName ("blue");
     625        graphdata.ptype = 0;
     626        graphdata.size = 0.0;
     627        graphdata.style = 0;
     628        KapaPrepPlot   (kapaGraph, rmod->n, &graphdata);
     629        KapaPlotVector (kapaGraph, rmod->n, rmod->data.F32, "x");
     630        KapaPlotVector (kapaGraph, rmod->n, fmin->data.F32, "y");
     631        plotline (kapaGraph, &graphdata, graphdata.xmin, logHM, graphdata.xmax, logHM);
     632        plotline (kapaGraph, &graphdata, 0.5*FWHM_MINOR, graphdata.ymin, 0.5*FWHM_MINOR, graphdata.ymax);
     633        graphdata.ltype = 1;
     634        plotline (kapaGraph, &graphdata, 0.5*MOMENTS_MINOR, graphdata.ymin, 0.5*MOMENTS_MINOR, graphdata.ymax);
     635        graphdata.ltype = 0;
    337636       
    338         // temporary array for overlapping objects we find
    339         psArray *overlap = psArrayAllocEmpty (100);
    340 
    341         // search backwards for overlapping sources
    342         for (int j = N - 1; j >= 0; j--) {
    343             pmSource *testSource = sources->data[j];
    344             if (testSource->peak->x <  source->pixels->col0) continue;
    345             if (testSource->peak->x >= source->pixels->col0 + source->pixels->numCols) continue;
    346             if (testSource->peak->y <  source->pixels->row0) break;
    347             if (testSource->peak->y >= source->pixels->row0 + source->pixels->numRows) {
    348                 fprintf (stderr, "warning: invalid condition\n");
    349                 continue;
    350             }
    351             psArrayAdd (overlap, 100, testSource);
    352         }
    353 
    354         // search forwards for overlapping sources
    355         for (int j = N + 1; j < sources->n; j++) {
    356             pmSource *testSource = sources->data[j];
    357             if (testSource->peak->x <  source->pixels->col0) continue;
    358             if (testSource->peak->x >= source->pixels->col0 + source->pixels->numCols) continue;
    359             if (testSource->peak->y <  source->pixels->row0) {
    360                 fprintf (stderr, "warning: invalid condition\n");
    361                 continue;
    362             }
    363             if (testSource->peak->y >= source->pixels->row0 + source->pixels->numRows) break;
    364             psArrayAdd (overlap, 100, testSource);
    365         }
    366 
    367         if (overlap->n == 0) {
    368             psFree (overlap);
    369             continue;
    370         }
    371 
    372         // now find the contour which is at 0.5*SAT_TEST_LEVEL (xPeak, yPeak is valid high pixel)
    373         contour = pmSourceContour (source->pixels, xPeak, yPeak, 0.5*SAT_TEST_LEVEL);
    374         if (contour == NULL) {
    375             psFree (overlap);
    376             continue;
    377         }
     637        graphdata.color = KapaColorByName ("green");
     638        graphdata.ptype = 0;
     639        graphdata.size = 0.0;
     640        graphdata.style = 0;
     641        KapaPrepPlot   (kapaGraph, rmod->n, &graphdata);
     642        KapaPlotVector (kapaGraph, rmod->n, rmod->data.F32, "x");
     643        KapaPlotVector (kapaGraph, rmod->n, fmaj->data.F32, "y");
     644        plotline (kapaGraph, &graphdata, 0.5*FWHM_MAJOR, graphdata.ymin, 0.5*FWHM_MAJOR, graphdata.ymax);
     645        graphdata.ltype = 1;
     646        plotline (kapaGraph, &graphdata, 0.5*MOMENTS_MAJOR, graphdata.ymin, 0.5*MOMENTS_MAJOR, graphdata.ymax);
     647        graphdata.ltype = 0;
    378648       
    379         // any peaks within this contour should be dropped (mark as blend, drop after loop is done)
    380         // also drop any peaks which are too close to this peak
    381         psVector *xv = contour->data[0];
    382         psVector *yv = contour->data[1];
    383         for (int k = 0; k < overlap->n; k++) {
    384             pmSource *testSource = overlap->data[k];
    385             float radius = hypot((testSource->peak->x - xCenter), (testSource->peak->y - yCenter));
    386             if (radius < SAT_MIN_RADIUS) {
    387                 testSource->mode |= PM_SOURCE_MODE_BLEND;
    388                 Nblend ++;
    389                 continue;
    390             }
    391             for (int j = 0; j < xv->n; j+=2) {
    392                 if (fabs(yv->data.F32[j] - testSource->peak->y) > 0.5) continue;
    393                 if (xv->data.F32[j+0] > testSource->peak->x) break;
    394                 if (xv->data.F32[j+1] < testSource->peak->x) break;
    395                 testSource->mode |= PM_SOURCE_MODE_BLEND;
    396                 Nblend ++;
    397                 j = xv->n; // skip rest of contour
    398             }
    399         }
    400         psFree (overlap);
    401         psFree (contour);
    402     }
    403 
    404     // drop the sources marked as BLEND
    405     for (int i = 0; i < sources->n;) {
    406         pmSource *source = sources->data[i];
    407 
    408         if (!(source->mode & PM_SOURCE_MODE_BLEND)) {
    409             i++;
    410             continue;
    411         }
    412 
    413         // shuffle the remaining sources forward
    414         for (int j = i; j < sources->n - 1; j++) {
    415             sources->data[j] = sources->data[j+1];
    416         }
    417         psFree (source);
    418         sources->n --;
    419     }
    420 
    421     psFree (SN);
    422     psFree (index);
    423 
    424     psLogMsg ("psphot", PS_LOG_INFO, "found %d satstar blend peaks, leaving %ld sources: %f sec\n", Nblend, sources->n, psTimerMark ("psphot.deblend.sat"));
     649        for (int i = 0; i < rmod->n; i++) {
     650            rmod->data.F32[i] = log10(rmod->data.F32[i]);
     651        }
     652
     653        // ** loglog **
     654        KapaSelectSection (kapaGraph, "loglog");
     655        KapaGetGraphData (kapaGraph, &graphdata);
     656        graphdata.color = KapaColorByName ("blue");
     657        graphdata.ptype = 0;
     658        graphdata.size = 0.0;
     659        graphdata.style = 0;
     660        KapaPrepPlot   (kapaGraph, rmod->n, &graphdata);
     661        KapaPlotVector (kapaGraph, rmod->n, rmod->data.F32, "x");
     662        KapaPlotVector (kapaGraph, rmod->n, fmin->data.F32, "y");
     663
     664        graphdata.color = KapaColorByName ("green");
     665        graphdata.ptype = 0;
     666        graphdata.size = 0.0;
     667        graphdata.style = 0;
     668        KapaPrepPlot   (kapaGraph, rmod->n, &graphdata);
     669        KapaPlotVector (kapaGraph, rmod->n, rmod->data.F32, "x");
     670        KapaPlotVector (kapaGraph, rmod->n, fmaj->data.F32, "y");
     671
     672        psFree (rmod);
     673        psFree (fmin);
     674        psFree (fmaj);
     675    }
     676
     677    if (!skipDisplay) {
     678        KiiCenter (kapaImage, source->peak->xf, source->peak->yf, 1);
     679        psphotVisualScaleImage (kapaImage, (psImage *) source->pixels->parent, NULL, "image", 1.0, 1);
     680        KiiOverlay overlay;
     681        overlay.x = source->peak->xf;
     682        overlay.y = source->peak->yf;
     683        overlay.dx = 5;
     684        overlay.dy = 5;
     685        overlay.angle = 0.0;
     686        overlay.type = KiiOverlayTypeByName ("circle");
     687        KiiLoadOverlay (kapaImage, &overlay, 1, "red");
     688        overlay.x = source->moments->Mx;
     689        overlay.y = source->moments->My;
     690        overlay.dx = 8;
     691        overlay.dy = 8;
     692        overlay.angle = 0.0;
     693        overlay.type = KiiOverlayTypeByName ("circle");
     694        KiiLoadOverlay (kapaImage, &overlay, 1, "blue");
     695    }
     696
     697    psFree (rg);
     698    psFree (Rg);
     699    psFree (fg);
     700    psFree (Fg);
     701    psFree (rb);
     702    psFree (Rb);
     703    psFree (fb);
     704
     705    if (skipDisplay) return true;
     706
     707    // pause and wait for user input:
     708    // continue, save (provide name), ??
     709    char key[10];
     710    fprintf (stdout, "[q]uit satstar? [e]rase and continue? [o]verplot and continue? [s]kip rest of stars? : ");
     711    if (!fgets(key, 8, stdin)) {
     712      psWarning("Unable to read option");
     713    }
     714    if (key[0] == 'e') {
     715      KapaClearPlots (kapaGraph);
     716    }
     717    if (key[0] == 'q') {
     718        return false;
     719    }
     720    if (key[0] == 's') {
     721        skipDisplay = true;
     722    }
    425723    return true;
    426724}
     725
     726bool psphotTestRadialModel (pmSource *source, psVector **logRmodelOut, psVector **logFmodelOut, psVector *logRad, psVector *logFlux, float Rmax) {
     727
     728  // we have log(radius) & log(flux).  find the median flux in log radial bins
     729
     730  float logRmax = log10(Rmax);
     731  float logRdel = 0.1;
     732
     733  psVector *logRmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32);
     734  psVector *logFmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32);
     735
     736  pmSourceRadialProfileSortPair (logRad, logFlux);
     737
     738  psStats *fluxStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
     739  psVector *flux = psVectorAllocEmpty (100, PS_TYPE_F32);
     740
     741  int bin = 0;
     742  for (int i = 0; i < logRmodel->n; i++) {
     743   
     744    // bin (i) has log radius range (i*logRdel : (i+1)*logRdel)
     745    float lRmin = logRdel*(i + 0);
     746    float lRmax = logRdel*(i + 1);
     747
     748    // reset the flux vector
     749    flux->n = 0;
     750    psStatsInit (fluxStats);
     751
     752    while (logRad->data.F32[bin] < lRmax) {
     753      if (isfinite(logFlux->data.F32[bin])) {
     754          psVectorAppend (flux, logFlux->data.F32[bin]);
     755      }
     756      bin ++;
     757    }
     758   
     759    // we have the set of fluxes for this bin; find the median values
     760   
     761    float Rmin = pow(10.0, lRmin);
     762    float Rmax = pow(10.0, lRmax);
     763
     764    float Rmean = (2.0/3.0) * (pow(Rmax, 3.0) - pow(Rmin, 3.0)) / (PS_SQR(Rmax) - PS_SQR(Rmin));
     765    logRmodel->data.F32[i] = log10(Rmean);
     766
     767    float Area = M_PI * (PS_SQR(Rmax) - PS_SQR(Rmin));
     768    if (flux->n < 0.25*Area) {
     769      logFmodel->data.F32[i] = NAN;
     770      continue;
     771    }
     772   
     773    psVectorStats (fluxStats, flux, NULL, NULL, 0);
     774    if (fluxStats->robustMedian > 0.0) {
     775        logFmodel->data.F32[i] = log10(fluxStats->robustMedian);
     776    } else {
     777        logFmodel->data.F32[i] = -3.0;
     778    }
     779    // fprintf (stderr, "R: %f, F: %f +/- %f\n", Rmean, fluxStats->robustMedian, fluxStats->robustStdev);
     780  }
     781
     782  // now how do i use this to subtract a model??
     783  *logRmodelOut = logRmodel;
     784  *logFmodelOut = logFmodel;
     785 
     786  // need to free stuff
     787  psFree (fluxStats);
     788  psFree (flux);
     789
     790  return true;
     791}
     792
     793bool psphotTestRadialModelSub (pmSource *source, psVector *logRmodel, psVector *logFmodel, float Xo, float Yo, float Rmax, psImageMaskType maskVal) {
     794
     795    int alt;
     796  float logRdel = 0.1;
     797
     798  for (int iy = 0; iy < source->pixels->numRows; iy++) {
     799    for (int ix = 0; ix < source->pixels->numCols; ix++) {
     800      if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) continue;
     801
     802      float radius = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
     803      float logR = log10(radius);
     804
     805      int bin = (int)(logR / logRdel);
     806
     807      // we are going to interpolate if possible, or extrapolate if necessary
     808      if (bin >= logRmodel->n - 1) bin = logRmodel->n - 1;
     809      if (bin < 0) bin = 0;
     810     
     811      // interpolate to the current radial position
     812      // XXX BIG HACK : skip nan bins for now
     813
     814      float logF0 = logFmodel->data.F32[bin];
     815      float logR0 = logRmodel->data.F32[bin];
     816      if (!isfinite(logF0)) continue;
     817   
     818      // interpolate between closest two bins if possible, extrapolate on ends
     819      if (logR < logR0) {
     820          alt = (bin > 0) ? bin - 1 : bin + 1;
     821      } else {
     822          alt = (bin < logRmodel->n - 1) ? bin + 1 : bin - 1;
     823      }
     824
     825      float logF1 = logFmodel->data.F32[alt];
     826      float logR1 = logRmodel->data.F32[alt];
     827      if (!isfinite(logF1)) continue;
     828
     829      // XXX use linear flux, not logFlux
     830      float logF = InterpolateValues (logR0, logF0, logR1, logF1, logR);
     831      float flux = pow (10.0, logF);
     832
     833      // float flux = InterpolateValues (logR0, logF0, logR1, logF1, logR);
     834      source->pixels->data.F32[iy][ix] -= flux;
     835    }
     836  }
     837  return true;
     838}
     839
     840// only valid for F32
     841bool psImageQuickStats (QuickStats *stats, psImage *image, psRegion region) {
     842
     843    psAssert (image->type.type == PS_TYPE_F32, "unsupported image type");
     844
     845    int Npix = (region.y1 - region.y0) * (region.x1 - region.x0);
     846    psVector *tmp = psVectorAllocEmpty (Npix, PS_TYPE_F32);
     847
     848    int bin = 0;
     849    for (int iy = region.y0; iy < region.y1; iy++) {
     850        for (int ix = region.x0; ix < region.x1; ix++) {
     851            if (!isfinite(image->data.F32[iy][ix])) continue;
     852            tmp->data.F32[bin] = image->data.F32[iy][ix];
     853            bin ++;
     854        }
     855    }
     856    tmp->n = bin;
     857
     858    if (bin < 1) {
     859        stats->min     = NAN;
     860        stats->lower20 = NAN;
     861        stats->upper20 = NAN;
     862        stats->max     = NAN;
     863        stats->Npts    = 0;
     864        psFree (tmp);
     865        return true;
     866    }
     867
     868
     869    psVectorSortInPlace (tmp);
     870
     871    int N20  = 0.2*tmp->n;
     872    int N80  = 0.8*tmp->n;
     873    int Nmax = tmp->n - 1;
     874
     875    stats->min     = tmp->data.F32[0];
     876    stats->lower20 = tmp->data.F32[N20];
     877    stats->upper20 = tmp->data.F32[N80];
     878    stats->max     = tmp->data.F32[Nmax];
     879    stats->Npts    = bin;
     880    psFree (tmp);
     881
     882    return true;
     883}
  • branches/eam_branches/ipp-20120805/psphot/src/psphotReadout.c

    r34360 r34368  
    128128    }
    129129
    130     // find blended neighbors of very saturated stars (detections->newSources)
    131     if (!psphotDeblendSatstars (config, view, filerule)) {
    132         psError (PSPHOT_ERR_UNKNOWN, false, "failed on satstar deblend analysis");
    133         return psphotReadoutCleanup (config, view, filerule);
    134     }
    135 
    136130    // mark blended peaks PS_SOURCE_BLEND (detections->newSources)
    137131    // XXX I've deactivated this because it was preventing galaxies close to stars from being
     
    147141        psError (PSPHOT_ERR_UNKNOWN, false, "failed to determine rough classifications");
    148142        return psphotReadoutCleanup (config, view, filerule);
     143    }
     144
     145    // find blended neighbors of very saturated stars (detections->newSources)
     146    if (!psphotDeblendSatstars (config, view, filerule)) {
     147        psError (PSPHOT_ERR_UNKNOWN, false, "failed on satstar deblend analysis");
     148        return psphotReadoutCleanup (config, view, filerule);
    149149    }
    150150
  • branches/eam_branches/ipp-20120805/psphot/src/psphotVisual.c

    r34360 r34368  
    12731273}
    12741274
    1275 static void plotline (int myKapa, Graphdata *graphdata, float x0, float y0, float x1, float y1)
     1275void plotline (int myKapa, Graphdata *graphdata, float x0, float y0, float x1, float y1)
    12761276{
    12771277    float x[2], y[2];
     
    12851285}
    12861286
    1287 bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal) {
     1287bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal, pmSourceMode showmode) {
    12881288
    12891289    Graphdata graphdata;
     1290
     1291    float Rmax = (showmode & PM_SOURCE_MODE_SATSTAR) ? 100.0 : 30.0;
    12901292
    12911293    bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     
    13101312        Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS] - source->pixels->row0;
    13111313    } else {
    1312         Xo = source->moments->Mx;
    1313         Yo = source->moments->My;
     1314        Xo = source->moments->Mx - source->pixels->col0;
     1315        Yo = source->moments->My - source->pixels->row0;
    13141316    }
    13151317
    13161318    for (int iy = 0; iy < source->pixels->numRows; iy++) {
    13171319        for (int ix = 0; ix < source->pixels->numCols; ix++) {
    1318             if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
     1320            if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) {
    13191321                rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
    13201322                // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ;
     
    13391341    // examine sources to set data range
    13401342    graphdata.xmin =  -0.05;
    1341     graphdata.xmax = +30.05;
     1343    graphdata.xmax = Rmax + 0.05;
    13421344    graphdata.ymin = -0.05;
    13431345    graphdata.ymax = +8.05;
     
    13701372    // examine sources to set data range
    13711373    graphdata.xmin = -1.51;
    1372     graphdata.xmax = +1.51;
     1374    graphdata.xmax = log10(Rmax) + 0.02;
    13731375    graphdata.ymin = -0.05;
    13741376    graphdata.ymax = +8.05;
     
    14221424        params->data.F32[PM_PAR_YPOS] = 0.0;
    14231425
    1424         psVector *rmod = psVectorAlloc(300, PS_TYPE_F32);
    1425         psVector *fmaj = psVectorAlloc(300, PS_TYPE_F32);
    1426         psVector *fmin = psVectorAlloc(300, PS_TYPE_F32);
     1426        psVector *rmod = psVectorAlloc(Rmax*10, PS_TYPE_F32);
     1427        psVector *fmaj = psVectorAlloc(Rmax*10, PS_TYPE_F32);
     1428        psVector *fmin = psVectorAlloc(Rmax*10, PS_TYPE_F32);
    14271429
    14281430        psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
     
    15691571        if (!(source->mode & showmode)) continue;
    15701572
    1571         psphotVisualPlotRadialProfile (myKapa, source, maskVal);
     1573        psphotVisualPlotRadialProfile (myKapa, source, maskVal, showmode);
     1574
     1575        if (pmVisualTestLevel("psphot.image", 1)) {
     1576          int display = psphotKapaChannel (1);
     1577          KiiCenter (display, source->peak->xf, source->peak->yf, 1);
     1578          KiiOverlay overlay;
     1579          overlay.x = source->peak->xf;
     1580          overlay.y = source->peak->yf;
     1581          overlay.dx = 5;
     1582          overlay.dy = 5;
     1583          overlay.angle = 0.0;
     1584          overlay.type = KiiOverlayTypeByName ("circle");
     1585          KiiLoadOverlay (display, &overlay, 1, "red");
     1586          overlay.x = source->moments->Mx;
     1587          overlay.y = source->moments->My;
     1588          overlay.dx = 8;
     1589          overlay.dy = 8;
     1590          overlay.angle = 0.0;
     1591          overlay.type = KiiOverlayTypeByName ("circle");
     1592          KiiLoadOverlay (display, &overlay, 1, "blue");
     1593        }
    15721594
    15731595        // pause and wait for user input:
Note: See TracChangeset for help on using the changeset viewer.