IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Sep 13, 2005, 3:35:20 PM (21 years ago)
Author:
eugene
Message:

substantial work to match with psLib v.7

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psphot/src/psModulesUtils.c

    r4977 r5048  
    22
    33// extract config informatin from config data or from image header, if specified
     4// XXX EAM : this function should be replaced with Paul's image/header/metadata load scheme
    45psF32 pmConfigLookupF32 (bool *status, psMetadata *config, psMetadata *header, char *name) {
    56
     
    4849}
    4950
    50 // XXX EAM : these are my alternate implementations of psModule functions
    51 
    52 // this sets and clears bit 0x80
    53 bool pmSourceLocalSky_EAM (pmSource *source,
    54                            psStatsOptions statsOptions,
    55                            psF32 Radius)
    56 {
    57 
    58     psImage *image = source->pixels;
    59     psImage *mask  = source->mask;
    60     pmPeak *peak  = source->peak;
    61     psRegion srcRegion;
    62 
    63     // XXX EAM : psRegionXXX funcs need value not ptr
    64 
    65     srcRegion = psRegionForSquare (peak->x, peak->y, Radius);
    66     srcRegion = psRegionForImage (mask, &srcRegion);
    67 
    68     psImageMaskRegion (mask, &srcRegion, "OR", PSPHOT_MASK_MARKED);
    69     psStats *myStats = psStatsAlloc(statsOptions);
    70     myStats = psImageStats(myStats, image, mask, 0xff);
    71     psImageMaskRegion (mask, &srcRegion, "AND", ~PSPHOT_MASK_MARKED);
    72 
    73     psF64 tmpF64;
    74     p_psGetStatValue(myStats, &tmpF64);
    75     psFree (myStats);
    76 
    77     if (isnan(tmpF64)) return (false);
    78     source->moments = pmMomentsAlloc();
    79     source->moments->Sky = (psF32) tmpF64;
    80     return (true);
    81 }
    82 
    83 # define PM_SOURCE_FIT_MODEL_NUM_ITERATIONS 15
    84 # define PM_SOURCE_FIT_MODEL_TOLERANCE 0.1
    85 bool pmSourceFitModel_EAM (pmSource *source,
    86                              pmModel *model,
    87                              const bool PSF)
    88 {
    89     // PS_PTR_CHECK_NULL(source, false);
    90     // PS_PTR_CHECK_NULL(source->moments, false);
    91     // PS_PTR_CHECK_NULL(source->peak, false);
    92     // PS_PTR_CHECK_NULL(source->pixels, false);
    93     // PS_PTR_CHECK_NULL(source->mask, false);
    94     // PS_PTR_CHECK_NULL(source->noise, false);
    95     psBool fitStatus = true;
    96     psBool onPic     = true;
    97     psBool rc        = true;
    98     psF32  Ro, ymodel;
    99 
    100 
    101     // XXX EAM : is it necessary for the mask & noise to exist?  the
    102     //           tests below could be conditions (!NULL)
    103 
    104     pmModelFunc modelFunc = pmModelFunc_GetFunction (model->type);
    105     pmModelLimits modelLimits = pmModelLimits_GetFunction (model->type);
    106 
    107     psVector *params = model->params;
    108     psVector *dparams = model->dparams;
    109     psVector *paramMask = NULL;
    110 
    111     psVector *beta_lim = NULL;
    112     psVector *params_min = NULL;
    113     psVector *params_max = NULL;
    114 
    115     int nParams = PSF ? params->n - 4 : params->n;
    116     psF32 So = params->data.F32[0];
    117 
    118     // find the number of valid pixels
    119     // XXX EAM : this loop and the loop below could just be one pass
    120     //           using the psArrayAdd and psVectorExtend functions
    121     psS32 count = 0;
    122     for (psS32 i = 0; i < source->pixels->numRows; i++) {
    123         for (psS32 j = 0; j < source->pixels->numCols; j++) {
    124             if (source->mask->data.U8[i][j] == 0) {
    125                 count++;
    126             }
    127         }
    128     }
    129     if (count <  nParams + 1) {
    130       psTrace (".pmObjects.pmSourceFitModel", 4, "insufficient valid pixels\n");
    131       return(false);
    132     }
    133 
    134     // construct the coordinate and value entries
    135     psArray *x = psArrayAlloc(count);
    136     psVector *y = psVectorAlloc(count, PS_TYPE_F32);
    137     psVector *yErr = psVectorAlloc(count, PS_TYPE_F32);
    138     psS32 tmpCnt = 0;
    139     for (psS32 i = 0; i < source->pixels->numRows; i++) {
    140         for (psS32 j = 0; j < source->pixels->numCols; j++) {
    141             if (source->mask->data.U8[i][j] == 0) {
    142                 psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
    143                 // XXX: Convert i/j to image space:
    144                 // XXX EAM: coord order is (x,y) == (col,row)
    145                 coord->data.F32[0] = (psF32) (j + source->pixels->col0);
    146                 coord->data.F32[1] = (psF32) (i + source->pixels->row0);
    147                 x->data[tmpCnt] = (psPtr *) coord;
    148                 y->data.F32[tmpCnt] = source->pixels->data.F32[i][j];
    149 
    150                 ymodel = modelFunc (NULL, model->params, coord);
    151                
    152                 // this test enhances the noise based on deviation from the model flux
    153                 Ro = 1.0 + fabs (y->data.F32[tmpCnt] - ymodel) / sqrt(PS_SQR(ymodel - So) + PS_SQR(So));
    154                 yErr->data.F32[tmpCnt] = sqrt (source->noise->data.F32[i][j] * Ro);
    155                 // XXX EAM : note the wasted effort: we carry dY^2, take sqrt(), then
    156                 //           the minimization function calculates sq()
    157                 tmpCnt++;
    158             }
    159         }
    160     }
    161 
    162     psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS,
    163                             PM_SOURCE_FIT_MODEL_TOLERANCE);
    164 
    165     // PSF model only fits first 4 parameters, FLT model fits all
    166     if (PSF) {
    167       paramMask = psVectorAlloc (params->n, PS_TYPE_U8);
    168       for (int i = 0; i < 4; i++) {
    169         paramMask->data.U8[i] = 0;
    170       }
    171       for (int i = 4; i < paramMask->n; i++) {
    172         paramMask->data.U8[i] = 1;
    173       }
    174     } 
    175 
    176     psImage *covar = psImageAlloc (params->n, 3, PS_TYPE_F64);
    177     modelLimits (&beta_lim, &params_min, &params_max);
    178     for (int i = 0; i < params->n; i++) {
    179         covar->data.F64[0][i] = beta_lim->data.F32[i];
    180         covar->data.F64[1][i] = params_min->data.F32[i];
    181         covar->data.F64[2][i] = params_max->data.F32[i];
    182     }
    183 
    184     psTrace (".pmObjects.pmSourceFitModel", 5, "fitting function\n");
    185     fitStatus = psMinimizeLMChi2_EAM(myMin, covar, params, paramMask, x, y, yErr, modelFunc);
    186     for (int i = 0; i < dparams->n; i++) {
    187         if ((paramMask != NULL) && paramMask->data.U8[i]) continue;
    188         dparams->data.F32[i] = sqrt(covar->data.F64[i][i]);
    189     }
    190  
    191     // XXX EAM: we need to do something (give an error?) if rc is false
    192     // XXX EAM: psMinimizeLMChi2 does not check convergence
    193 
    194     // XXX models can go insane: reject these
    195     onPic &= (params->data.F32[2] >= source->pixels->col0);
    196     onPic &= (params->data.F32[2] <  source->pixels->col0 + source->pixels->numCols);
    197     onPic &= (params->data.F32[3] >= source->pixels->row0);
    198     onPic &= (params->data.F32[3] <  source->pixels->row0 + source->pixels->numRows);
    199 
    200     // XXX EAM: save the resulting chisq, nDOF, nIter
    201     model->chisq = myMin->value;
    202     model->nIter = myMin->iter;
    203     model->nDOF  = y->n - nParams;
    204 
    205     // XXX EAM get the Gauss-Newton distance for fixed model parameters
    206     if (paramMask != NULL) {
    207         psVector *delta = psVectorAlloc (params->n, PS_TYPE_F64);
    208         psMinimizeGaussNewtonDelta (delta, params, NULL, x, y, yErr, modelFunc);
    209         for (int i = 0; i < dparams->n; i++) {
    210             if (!paramMask->data.U8[i]) continue;
    211             dparams->data.F32[i] = delta->data.F64[i];
    212         }
    213     }
    214 
    215     psFree(paramMask);
    216     psFree(x);
    217     psFree(y);
    218     psFree(myMin);
    219 
    220     rc = (onPic && fitStatus);
    221     return(rc);
    222 }
    223 
    224 /******************************************************************************
    225 pmSourceMoments(source, radius): this function takes a subImage defined in the
    226 pmSource data structure, along with the peak location, and determines the
    227 various moments associated with that peak.
    228  
    229 Requires the following to have been created:
    230     pmSource
    231     pmSource->peak
    232     pmSource->pixels
    233  
    234 XXX: The peak calculations are done in image coords, not subImage coords.
    235  
    236 XXX: mask values?
    237 
    238 XXX EAM : this version clips input pixels on S/N
    239 *****************************************************************************/
    240 # define VALID_RADIUS(X,Y) (((R2) >= (PS_SQR(X) + PS_SQR(Y))) ? 1 : 0)
    241 
    242 bool pmSourceMoments_EAM(pmSource *source,
    243                          psF32 radius)
    244 {
    245     // PS_PTR_CHECK_NULL(source, NULL);
    246     // PS_PTR_CHECK_NULL(source->peak, NULL);
    247     // PS_PTR_CHECK_NULL(source->pixels, NULL);
    248     // PS_PTR_CHECK_NULL(source->noise, NULL);
    249     PS_FLOAT_COMPARE(0.0, radius, NULL);
    250 
    251     //
    252     // XXX: Verify the setting for sky if source->moments == NULL.
    253     //
    254     psF32 sky = 0.0;
    255     if (source->moments == NULL) {
    256         source->moments = pmMomentsAlloc();
    257     } else {
    258         sky = source->moments->Sky;
    259     }
    260 
    261     //
    262     // Sum = SUM (z - sky)
    263     // X1  = SUM (x - xc)*(z - sky)
    264     // X2  = SUM (x - xc)^2 * (z - sky)
    265     // XY  = SUM (x - xc)*(y - yc)*(z - sky)
    266     //
    267     psF32 peakPixel = -PS_MAX_F32;
    268     psS32 numPixels = 0;
    269     psF32 Sum = 0.0;
    270     psF32 X1 = 0.0;
    271     psF32 Y1 = 0.0;
    272     psF32 X2 = 0.0;
    273     psF32 Y2 = 0.0;
    274     psF32 XY = 0.0;
    275     psF32 x  = 0;
    276     psF32 y  = 0;
    277     psF32 R2 = PS_SQR(radius);
    278 
    279     psF32 xPeak = source->peak->x;
    280     psF32 yPeak = source->peak->y;
    281 
    282     // XXX why do I get different results for these two methods of finding Sx?
    283     // XXX Sx, Sy would be better measured if we clip pixels close to sky
    284     // XXX Sx, Sy can still be imaginary, so we probably need to keep Sx^2?
    285     // We loop through all pixels in this subimage (source->pixels), and for each
    286     // pixel that is not masked, AND within the radius of the peak pixel, we
    287     // proceed with the moments calculation.  need to do two loops for a
    288     // numerically stable result.  first loop: get the sums.
    289     // XXX EAM : mask == 0 is valid
    290 
    291     for (psS32 row = 0; row < source->pixels->numRows ; row++) {
    292         for (psS32 col = 0; col < source->pixels->numCols ; col++) {
    293             if ((source->mask != NULL) && (source->mask->data.U8[row][col])) continue;
    294 
    295             psF32 xDiff = col + source->pixels->col0 - xPeak;
    296             psF32 yDiff = row + source->pixels->row0 - yPeak;
    297 
    298             if (!VALID_RADIUS(xDiff, yDiff)) continue;
    299 
    300             psF32 pDiff = source->pixels->data.F32[row][col] - sky;
    301 
    302             // XXX EAM : check for valid S/N in pixel
    303             if (pDiff / sqrt(source->noise->data.F32[row][col]) < 1) continue;
    304            
    305             Sum += pDiff;
    306             X1  += xDiff * pDiff;
    307             Y1  += yDiff * pDiff;
    308             XY  += xDiff * yDiff * pDiff;
    309            
    310             X2  += PS_SQR(xDiff) * pDiff;
    311             Y2  += PS_SQR(yDiff) * pDiff;
    312            
    313             peakPixel = PS_MAX (source->pixels->data.F32[row][col], peakPixel);
    314             numPixels++;
    315         }
    316     }
    317     // XXX EAM - the limit is a bit arbitrary.  make it user defined?
    318     if ((numPixels < 3) || (Sum <= 0)) {
    319       psTrace (".psModules.pmSourceMoments", 5, "no valid pixels for source\n");
    320       return (false);
    321     }
    322 
    323     psTrace (".psModules.pmSourceMoments", 5,
    324              "sky: %f  Sum: %f  X1: %f  Y1: %f  X2: %f  Y2: %f  XY: %f  Npix: %d\n",
    325              sky, Sum, X1, Y1, X2, Y2, XY, numPixels);
    326 
    327     //
    328     // first moment X  = X1/Sum + xc
    329     // second moment X = sqrt (X2/Sum - (X1/Sum)^2)
    330     // Sxy             = XY / Sum
    331     //
    332     x = X1/Sum;
    333     y = Y1/Sum;
    334     if ((fabs(x) > radius) || (fabs(y) > radius)) {
    335       psTrace (".psModules.pmSourceMoments", 5,
    336                "large centroid swing; invalid peak %d, %d\n",
    337                source->peak->x, source->peak->y);
    338       return (false);
    339     }
    340 
    341     source->moments->x = x + xPeak;
    342     source->moments->y = y + yPeak;
    343 
    344     source->moments->Sxy = XY/Sum - x*y;
    345     source->moments->Sum = Sum;
    346     source->moments->Peak = peakPixel;
    347     source->moments->nPixels = numPixels;
    348 
    349     // XXX EAM : these values can be negative, so we need to limit the range
    350     source->moments->Sx = sqrt(PS_MAX(X2/Sum - PS_SQR(x), 0));
    351     source->moments->Sy = sqrt(PS_MAX(Y2/Sum - PS_SQR(y), 0));
    352 
    353     psTrace (".psModules.pmSourceMoments", 4,
    354              "sky: %f  Sum: %f  x: %f  y: %f  Sx: %f  Sy: %f  Sxy: %f\n",
    355              sky, Sum, source->moments->x, source->moments->y,
    356              source->moments->Sx, source->moments->Sy, source->moments->Sxy);
    357 
    358     return(true);
    359 }
    360 
    36151bool pmModelFitStatus (pmModel *model) {
    36252
Note: See TracChangeset for help on using the changeset viewer.