IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 8, 2006, 5:14:23 PM (20 years ago)
Author:
magnier
Message:

major rework of objects code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/rel10_ifa/psModules/src/objects/pmSource.c

    r6537 r6556  
    1 /** @file  pmObjects.c
     1/** @file  pmSource.c
    22 *
    3  *  This file will ...
     3 *  Functions to define and manipulate sources on images
    44 *
    55 *  @author GLG, MHPCC
    66 *  @author EAM, IfA: significant modifications.
    77 *
    8  *  @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2006-03-07 06:33:35 $
     8 *  @version $Revision: 1.1.2.2 $ $Name: not supported by cvs2svn $
     9 *  @date $Date: 2006-03-09 03:14:23 $
    1010 *
    1111 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1717#include <string.h>
    1818#include "pslib.h"
    19 #include "pmObjects.h"
    20 #include "pmModelGroup.h"
     19#include "pmHDU.h"
     20#include "pmFPA.h"
     21#include "pmPeaks.h"
     22#include "pmMoments.h"
     23#include "pmModel.h"
     24#include "pmSource.h"
    2125
    2226static void sourceFree(pmSource *tmp)
     
    5054    tmp->modelPSF = NULL;
    5155    tmp->modelEXT = NULL;
    52     tmp->type = PM_SOURCE_UNKNOWN;
    53     tmp->mode = PM_SOURCE_DEFAULT;
     56    tmp->type = PM_SOURCE_TYPE_UNKNOWN;
     57    tmp->mode = PM_SOURCE_MODE_DEFAULT;
    5458    psMemSetDeallocator(tmp, (psFreeFunc) sourceFree);
    5559
     
    219223
    220224        // XXX EAM : this lets us takes the single highest peak
    221         psArraySort (peaks, pmComparePeakDescend);
     225        psArraySort (peaks, pmPeaksCompareDescend);
    222226        clump = peaks->data[0];
    223227        psTrace (".pmObjects.pmSourceRoughClass", 2, "clump is at %d, %d (%f)\n", clump->x, clump->y, clump->counts);
     
    331335        // inner = psRegionForSquare (tmpSrc->peak->x - tmpSrc->mask->col0, tmpSrc->peak->y - tmpSrc->mask->row0, 2);
    332336        inner = psRegionForSquare (tmpSrc->peak->x, tmpSrc->peak->y, 2);
    333         int Nsatpix = psImageCountPixelMask (tmpSrc->mask, inner, PSPHOT_MASK_SATURATED);
     337        int Nsatpix = psImageCountPixelMask (tmpSrc->mask, inner, PM_SOURCE_MASK_SATURATED);
    334338
    335339        // saturated star (size consistent with PSF or larger)
     
    338342        big = true;
    339343        if ((Nsatpix > 1) && big) {
    340             tmpSrc->type = PM_SOURCE_STAR;
    341             tmpSrc->mode = PM_SOURCE_SATSTAR;
     344            tmpSrc->type = PM_SOURCE_TYPE_STAR;
     345            tmpSrc->mode = PM_SOURCE_MODE_SATSTAR;
    342346            Nsatstar ++;
    343347            continue;
     
    346350        // saturated object (not a star, eg bleed trails, hot pixels)
    347351        if (Nsatpix > 1) {
    348             tmpSrc->type = PM_SOURCE_SATURATED;
    349             tmpSrc->mode = PM_SOURCE_DEFAULT;
     352            tmpSrc->type = PM_SOURCE_TYPE_SATURATED;
     353            tmpSrc->mode = PM_SOURCE_MODE_DEFAULT;
    350354            Nsat ++;
    351355            continue;
     
    356360        // only set candidate defects if
    357361        if ((sigX < 0.05) || (sigY < 0.05)) {
    358             tmpSrc->type = PM_SOURCE_DEFECT;
    359             tmpSrc->mode = PM_SOURCE_DEFAULT;
     362            tmpSrc->type = PM_SOURCE_TYPE_DEFECT;
     363            tmpSrc->mode = PM_SOURCE_MODE_DEFAULT;
    360364            Ncr ++;
    361365            continue;
     
    364368        // likely unsaturated extended source (too large to be stellar)
    365369        if ((sigX > (clump.X + 3*clump.dX)) || (sigY > (clump.Y + 3*clump.dY))) {
    366             tmpSrc->type = PM_SOURCE_EXTENDED;
    367             tmpSrc->mode = PM_SOURCE_DEFAULT;
     370            tmpSrc->type = PM_SOURCE_TYPE_EXTENDED;
     371            tmpSrc->mode = PM_SOURCE_MODE_DEFAULT;
    368372            Next ++;
    369373            continue;
     
    378382        psF32 radius = hypot ((sigX-clump.X)/clump.dX, (sigY-clump.Y)/clump.dY);
    379383        if ((tmpSrc->moments->SN > PSF_SN_LIM) && (radius < 1.5)) {
    380             tmpSrc->type = PM_SOURCE_STAR;
    381             tmpSrc->mode = PM_SOURCE_PSFSTAR;
     384            tmpSrc->type = PM_SOURCE_TYPE_STAR;
     385            tmpSrc->mode = PM_SOURCE_MODE_PSFSTAR;
    382386            Npsf ++;
    383387            continue;
     
    385389
    386390        // random type of star
    387         tmpSrc->type = PM_SOURCE_STAR;
    388         tmpSrc->mode = PM_SOURCE_DEFAULT;
     391        tmpSrc->type = PM_SOURCE_TYPE_STAR;
     392        tmpSrc->mode = PM_SOURCE_MODE_DEFAULT;
    389393    }
    390394
     
    409413}
    410414
     415/******************************************************************************
     416pmSourceMoments(source, radius): this function takes a subImage defined in the
     417pmSource data structure, along with the peak location, and determines the
     418various moments associated with that peak.
     419 
     420Requires the following to have been created:
     421    pmSource
     422    pmSource->peak
     423    pmSource->pixels
     424    pmSource->weight
     425    pmSource->mask
     426 
     427XXX: The peak calculations are done in image coords, not subImage coords.
     428 
     429XXX EAM : this version clips input pixels on S/N
     430XXX EAM : this version returns false for several reasons
     431*****************************************************************************/
     432# define VALID_RADIUS(X,Y,RAD2) (((RAD2) >= (PS_SQR(X) + PS_SQR(Y))) ? 1 : 0)
     433
     434bool pmSourceMoments(pmSource *source,
     435                     psF32 radius)
     436{
     437    psTrace(__func__, 3, "---- %s() begin ----\n", __func__);
     438    PS_ASSERT_PTR_NON_NULL(source, false);
     439    PS_ASSERT_PTR_NON_NULL(source->peak, false);
     440    PS_ASSERT_PTR_NON_NULL(source->pixels, false);
     441    PS_ASSERT_PTR_NON_NULL(source->mask, false);
     442    PS_ASSERT_FLOAT_LARGER_THAN(radius, 0.0, false);
     443
     444    //
     445    // XXX: Verify the setting for sky if source->moments == NULL.
     446    //
     447    psF32 sky = 0.0;
     448    if (source->moments == NULL) {
     449        source->moments = pmMomentsAlloc();
     450    } else {
     451        sky = source->moments->Sky;
     452    }
     453
     454    //
     455    // Sum = SUM (z - sky)
     456    // X1  = SUM (x - xc)*(z - sky)
     457    // X2  = SUM (x - xc)^2 * (z - sky)
     458    // XY  = SUM (x - xc)*(y - yc)*(z - sky)
     459    //
     460    psF32 peakPixel = -PS_MAX_F32;
     461    psS32 numPixels = 0;
     462    psF32 Sum = 0.0;
     463    psF32 Var = 0.0;
     464    psF32 X1 = 0.0;
     465    psF32 Y1 = 0.0;
     466    psF32 X2 = 0.0;
     467    psF32 Y2 = 0.0;
     468    psF32 XY = 0.0;
     469    psF32 x  = 0;
     470    psF32 y  = 0;
     471    psF32 R2 = PS_SQR(radius);
     472
     473    psF32 xPeak = source->peak->x;
     474    psF32 yPeak = source->peak->y;
     475    psF32 xOff = source->pixels->col0 - source->peak->x;
     476    psF32 yOff = source->pixels->row0 - source->peak->y;
     477
     478    // XXX why do I get different results for these two methods of finding Sx?
     479    // XXX Sx, Sy would be better measured if we clip pixels close to sky
     480    // XXX Sx, Sy can still be imaginary, so we probably need to keep Sx^2?
     481    // We loop through all pixels in this subimage (source->pixels), and for each
     482    // pixel that is not masked, AND within the radius of the peak pixel, we
     483    // proceed with the moments calculation.  need to do two loops for a
     484    // numerically stable result.  first loop: get the sums.
     485    // XXX EAM : mask == 0 is valid
     486
     487    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
     488
     489        psF32 *vPix = source->pixels->data.F32[row];
     490        psF32 *vWgt = source->weight->data.F32[row];
     491        psU8  *vMsk = (source->mask == NULL) ? NULL : source->mask->data.U8[row];
     492
     493        for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
     494            if ((vMsk != NULL) && *vMsk) {
     495                vMsk++;
     496                continue;
     497            }
     498
     499            psF32 xDiff = col + xOff;
     500            psF32 yDiff = row + yOff;
     501
     502            // radius is just a function of (xDiff, yDiff)
     503            if (!VALID_RADIUS(xDiff, yDiff, R2)) {
     504                if (vMsk != NULL)
     505                    vMsk++;
     506                continue;
     507            }
     508
     509            psF32 pDiff = *vPix - sky;
     510            psF32 wDiff = *vWgt;
     511
     512            // XXX EAM : check for valid S/N in pixel
     513            // XXX EAM : should this limit be user-defined?
     514            if (PS_SQR(pDiff) < wDiff) {
     515                if (vMsk != NULL)
     516                    vMsk++;
     517                continue;
     518            }
     519
     520            Var += wDiff;
     521            Sum += pDiff;
     522
     523            psF32 xWght = xDiff * pDiff;
     524            psF32 yWght = yDiff * pDiff;
     525
     526            X1  += xWght;
     527            Y1  += yWght;
     528
     529            XY  += xDiff * yWght;
     530            X2  += xDiff * xWght;
     531            Y2  += yDiff * yWght;
     532
     533            peakPixel = PS_MAX (*vPix, peakPixel);
     534            numPixels++;
     535            if (vMsk != NULL)
     536                vMsk++;
     537        }
     538    }
     539
     540    // if we have less than (1/4) of the possible pixels, force a retry
     541    // XXX EAM - the limit is a bit arbitrary.  make it user defined?
     542    if ((numPixels < 0.75*R2) || (Sum <= 0)) {
     543        psTrace (".psModules.pmSourceMoments", 3, "no valid pixels for source\n");
     544        psTrace(__func__, 3, "---- %s(false) end ----\n", __func__);
     545        return (false);
     546    }
     547
     548    psTrace (".psModules.pmSourceMoments", 5,
     549             "sky: %f  Sum: %f  X1: %f  Y1: %f  X2: %f  Y2: %f  XY: %f  Npix: %d\n",
     550             sky, Sum, X1, Y1, X2, Y2, XY, numPixels);
     551
     552    //
     553    // first moment X  = X1/Sum + xc
     554    // second moment X = sqrt (X2/Sum - (X1/Sum)^2)
     555    // Sxy             = XY / Sum
     556    //
     557    x = X1/Sum;
     558    y = Y1/Sum;
     559    if ((fabs(x) > radius) || (fabs(y) > radius)) {
     560        psTrace (".psModules.pmSourceMoments", 3,
     561                 "large centroid swing; invalid peak %d, %d\n",
     562                 source->peak->x, source->peak->y);
     563        psTrace(__func__, 3, "---- %s(false) end ----\n", __func__);
     564        return (false);
     565    }
     566
     567    source->moments->x = x + xPeak;
     568    source->moments->y = y + yPeak;
     569
     570    // XXX EAM : Sxy needs to have x*y subtracted
     571    source->moments->Sxy = XY/Sum - x*y;
     572    source->moments->Sum = Sum;
     573    source->moments->SN  = Sum / sqrt(Var);
     574    source->moments->Peak = peakPixel;
     575    source->moments->nPixels = numPixels;
     576
     577    // XXX EAM : these values can be negative, so we need to limit the range
     578    source->moments->Sx = sqrt(PS_MAX(X2/Sum - PS_SQR(x), 0));
     579    source->moments->Sy = sqrt(PS_MAX(Y2/Sum - PS_SQR(y), 0));
     580
     581    psTrace (".psModules.pmSourceMoments", 4,
     582             "sky: %f  Sum: %f  x: %f  y: %f  Sx: %f  Sy: %f  Sxy: %f\n",
     583             sky, Sum, source->moments->x, source->moments->y,
     584             source->moments->Sx, source->moments->Sy, source->moments->Sxy);
     585
     586    psTrace(__func__, 3, "---- %s(true) end ----\n", __func__);
     587    return(true);
     588}
     589
     590pmModel *pmSourceSelectModel (pmSource *source)
     591{
     592    switch (source->type) {
     593    case PM_SOURCE_TYPE_STAR:
     594        return source->modelPSF;
     595
     596    case PM_SOURCE_TYPE_EXTENDED:
     597        return source->modelEXT;
     598
     599    default:
     600        return NULL;
     601    }
     602    return NULL;
     603}
Note: See TracChangeset for help on using the changeset viewer.