IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 4582


Ignore:
Timestamp:
Jul 20, 2005, 4:19:11 AM (21 years ago)
Author:
eugene
Message:

working on the stability of the galaxy models

Location:
trunk/psphot/src
Files:
6 edited

Legend:

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

    r4375 r4582  
    5858}
    5959
     60# define PM_SOURCE_FIT_MODEL_NUM_ITERATIONS 15
     61# define PM_SOURCE_FIT_MODEL_TOLERANCE 0.1
     62bool pmSourceFitModel_EAM(psSource *source,
     63                          psModel *model,
     64                          const bool PSF,
     65                          float SOFT)
     66{
     67    PS_PTR_CHECK_NULL(source, false);
     68    PS_PTR_CHECK_NULL(source->moments, false);
     69    PS_PTR_CHECK_NULL(source->peak, false);
     70    PS_PTR_CHECK_NULL(source->pixels, false);
     71    PS_PTR_CHECK_NULL(source->mask, false);
     72    PS_PTR_CHECK_NULL(source->noise, false);
     73    psBool fitStatus = true;
     74    psBool onPic     = true;
     75    psBool rc        = true;
     76    psF32  Ro;
     77
     78
     79    // XXX EAM : is it necessary for the mask & noise to exist?  the
     80    //           tests below could be conditions (!NULL)
     81
     82    psModelFunc modelFunc = psModelFunc_GetFunction (model->type);
     83
     84    psVector *params = model->params;
     85    psVector *dparams = model->dparams;
     86    psVector *paramMask = NULL;
     87
     88    int nParams = PSF ? params->n - 4 : params->n;
     89    psF32 Xo = params->data.F32[2];
     90    psF32 Yo = params->data.F32[3];
     91
     92    // find the number of valid pixels
     93    // XXX EAM : this loop and the loop below could just be one pass
     94    //           using the psArrayAdd and psVectorExtend functions
     95    psS32 count = 0;
     96    for (psS32 i = 0; i < source->pixels->numRows; i++) {
     97        for (psS32 j = 0; j < source->pixels->numCols; j++) {
     98            if (source->mask->data.U8[i][j] == 0) {
     99                count++;
     100            }
     101        }
     102    }
     103    if (count <  nParams + 1) {
     104      psTrace (".pmObjects.pmSourceFitModel", 4, "insufficient valid pixels\n");
     105      return(false);
     106    }
     107
     108    // construct the coordinate and value entries
     109    psArray *x = psArrayAlloc(count);
     110    psVector *y = psVectorAlloc(count, PS_TYPE_F32);
     111    psVector *yErr = psVectorAlloc(count, PS_TYPE_F32);
     112    psS32 tmpCnt = 0;
     113    for (psS32 i = 0; i < source->pixels->numRows; i++) {
     114        for (psS32 j = 0; j < source->pixels->numCols; j++) {
     115            if (source->mask->data.U8[i][j] == 0) {
     116                psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
     117                // XXX: Convert i/j to image space:
     118                // XXX EAM: coord order is (x,y) == (col,row)
     119                coord->data.F32[0] = (psF32) (j + source->pixels->col0);
     120                coord->data.F32[1] = (psF32) (i + source->pixels->row0);
     121                x->data[tmpCnt] = (psPtr *) coord;
     122                y->data.F32[tmpCnt] = source->pixels->data.F32[i][j];
     123
     124                // XXX just for test purposes, use the raw radius.  a better
     125                // choice is to ask what is the value of z and scale by that
     126                Ro = hypot ((Xo - coord->data.F32[0]), (Yo - coord->data.F32[1]));
     127
     128                // XXX enhance the noise (doubled if R = 10 pix, etc. note the square)
     129                yErr->data.F32[tmpCnt] = sqrt (source->noise->data.F32[i][j] * (1 + PS_SQR(Ro/SOFT)));
     130                // XXX EAM : note the wasted effort: we carry dY^2, take sqrt(), then
     131                //           the minimization function calculates sq()
     132                tmpCnt++;
     133            }
     134        }
     135    }
     136
     137    psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS,
     138                            PM_SOURCE_FIT_MODEL_TOLERANCE);
     139
     140    // PSF model only fits first 4 parameters, FLT model fits all
     141    if (PSF) {
     142      paramMask = psVectorAlloc (params->n, PS_TYPE_U8);
     143      for (int i = 0; i < 4; i++) {
     144        paramMask->data.U8[i] = 0;
     145      }
     146      for (int i = 4; i < paramMask->n; i++) {
     147        paramMask->data.U8[i] = 1;
     148      }
     149    }       
     150
     151    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F64);
     152
     153    psTrace (".pmObjects.pmSourceFitModel", 5, "fitting function\n");
     154    fitStatus = psMinimizeLMChi2(myMin, covar, params, paramMask, x, y, yErr, modelFunc);
     155    for (int i = 0; i < dparams->n; i++) {
     156        if ((paramMask != NULL) && paramMask->data.U8[i]) continue;
     157        dparams->data.F32[i] = sqrt(covar->data.F64[i][i]);
     158    }
     159 
     160    // XXX EAM: we need to do something (give an error?) if rc is false
     161    // XXX EAM: psMinimizeLMChi2 does not check convergence
     162
     163    // XXX models can go insane: reject these
     164    onPic &= (params->data.F32[2] >= source->pixels->col0);
     165    onPic &= (params->data.F32[2] <  source->pixels->col0 + source->pixels->numCols);
     166    onPic &= (params->data.F32[3] >= source->pixels->row0);
     167    onPic &= (params->data.F32[3] <  source->pixels->row0 + source->pixels->numRows);
     168
     169    // XXX EAM: save the resulting chisq, nDOF, nIter
     170    model->chisq = myMin->value;
     171    model->nIter = myMin->iter;
     172    model->nDOF  = y->n - nParams;
     173
     174    // XXX EAM get the Gauss-Newton distance for fixed model parameters
     175    if (paramMask != NULL) {
     176        psVector *delta = psVectorAlloc (params->n, PS_TYPE_F64);
     177        psMinimizeGaussNewtonDelta (delta, params, NULL, x, y, yErr, modelFunc);
     178        for (int i = 0; i < dparams->n; i++) {
     179            if (!paramMask->data.U8[i]) continue;
     180            dparams->data.F32[i] = delta->data.F64[i];
     181        }
     182    }
     183
     184    psFree(paramMask);
     185    psFree(x);
     186    psFree(y);
     187    psFree(myMin);
     188
     189    rc = (onPic && fitStatus);
     190    return(rc);
     191}
     192
     193/******************************************************************************
     194pmSourceMoments(source, radius): this function takes a subImage defined in the
     195psSource data structure, along with the peak location, and determines the
     196various moments associated with that peak.
     197 
     198Requires the following to have been created:
     199    psSource
     200    psSource->peak
     201    psSource->pixels
     202 
     203XXX: The peak calculations are done in image coords, not subImage coords.
     204 
     205XXX: mask values?
     206*****************************************************************************/
     207# define VALID_RADIUS(X,Y) (((R2) >= (PS_SQR(X) + PS_SQR(Y))) ? 1 : 0)
     208
     209bool pmSourceMoments_EAM(psSource *source,
     210                         psF32 radius)
     211{
     212    PS_PTR_CHECK_NULL(source, NULL);
     213    PS_PTR_CHECK_NULL(source->peak, NULL);
     214    PS_PTR_CHECK_NULL(source->pixels, NULL);
     215    PS_PTR_CHECK_NULL(source->noise, NULL);
     216    PS_FLOAT_COMPARE(0.0, radius, NULL);
     217
     218    //
     219    // XXX: Verify the setting for sky if source->moments == NULL.
     220    //
     221    psF32 sky = 0.0;
     222    if (source->moments == NULL) {
     223        source->moments = pmMomentsAlloc();
     224    } else {
     225        sky = source->moments->Sky;
     226    }
     227
     228    //
     229    // Sum = SUM (z - sky)
     230    // X1  = SUM (x - xc)*(z - sky)
     231    // X2  = SUM (x - xc)^2 * (z - sky)
     232    // XY  = SUM (x - xc)*(y - yc)*(z - sky)
     233    //
     234    psF32 peakPixel = -PS_MAX_F32;
     235    psS32 numPixels = 0;
     236    psF32 Sum = 0.0;
     237    psF32 X1 = 0.0;
     238    psF32 Y1 = 0.0;
     239    psF32 X2 = 0.0;
     240    psF32 Y2 = 0.0;
     241    psF32 XY = 0.0;
     242    psF32 x  = 0;
     243    psF32 y  = 0;
     244    psF32 R2 = PS_SQR(radius);
     245
     246    psF32 xPeak = source->peak->x;
     247    psF32 yPeak = source->peak->y;
     248
     249    // XXX why do I get different results for these two methods of finding Sx?
     250    // XXX Sx, Sy would be better measured if we clip pixels close to sky
     251    // XXX Sx, Sy can still be imaginary, so we probably need to keep Sx^2?
     252    // We loop through all pixels in this subimage (source->pixels), and for each
     253    // pixel that is not masked, AND within the radius of the peak pixel, we
     254    // proceed with the moments calculation.  need to do two loops for a
     255    // numerically stable result.  first loop: get the sums.
     256    // XXX EAM : mask == 0 is valid
     257
     258    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
     259        for (psS32 col = 0; col < source->pixels->numCols ; col++) {
     260            if ((source->mask != NULL) && (source->mask->data.U8[row][col])) continue;
     261
     262            psF32 xDiff = col + source->pixels->col0 - xPeak;
     263            psF32 yDiff = row + source->pixels->row0 - yPeak;
     264
     265            if (!VALID_RADIUS(xDiff, yDiff)) continue;
     266
     267            psF32 pDiff = source->pixels->data.F32[row][col] - sky;
     268
     269            // XXX EAM : check for valid S/N in pixel
     270            if (pDiff / sqrt(source->noise->data.F32[row][col]) < 1) continue;
     271           
     272            Sum += pDiff;
     273            X1  += xDiff * pDiff;
     274            Y1  += yDiff * pDiff;
     275            XY  += xDiff * yDiff * pDiff;
     276           
     277            X2  += PS_SQR(xDiff) * pDiff;
     278            Y2  += PS_SQR(yDiff) * pDiff;
     279           
     280            peakPixel = PS_MAX (source->pixels->data.F32[row][col], peakPixel);
     281            numPixels++;
     282        }
     283    }
     284    // XXX EAM - the limit is a bit arbitrary.  make it user defined?
     285    if ((numPixels < 3) || (Sum <= 0)) {
     286      psTrace (".psModules.pmSourceMoments", 5, "no valid pixels for source\n");
     287      return (false);
     288    }
     289
     290    psTrace (".psModules.pmSourceMoments", 5,
     291             "sky: %f  Sum: %f  X1: %f  Y1: %f  X2: %f  Y2: %f  XY: %f  Npix: %d\n",
     292             sky, Sum, X1, Y1, X2, Y2, XY, numPixels);
     293
     294    //
     295    // first moment X  = X1/Sum + xc
     296    // second moment X = sqrt (X2/Sum - (X1/Sum)^2)
     297    // Sxy             = XY / Sum
     298    //
     299    x = X1/Sum;
     300    y = Y1/Sum;
     301    if ((fabs(x) > radius) || (fabs(y) > radius)) {
     302      psTrace (".psModules.pmSourceMoments", 5,
     303               "large centroid swing; invalid peak %d, %d\n",
     304               source->peak->x, source->peak->y);
     305      return (false);
     306    }
     307
     308    source->moments->x = x + xPeak;
     309    source->moments->y = y + yPeak;
     310
     311    source->moments->Sxy = XY/Sum - x*y;
     312    source->moments->Sum = Sum;
     313    source->moments->Peak = peakPixel;
     314    source->moments->nPixels = numPixels;
     315
     316    // XXX EAM : these values can be negative, so we need to limit the range
     317    source->moments->Sx = sqrt(PS_MAX(X2/Sum - PS_SQR(x), 0));
     318    source->moments->Sy = sqrt(PS_MAX(Y2/Sum - PS_SQR(y), 0));
     319
     320    psTrace (".psModules.pmSourceMoments", 4,
     321             "sky: %f  Sum: %f  x: %f  y: %f  Sx: %f  Sy: %f  Sxy: %f\n",
     322             sky, Sum, source->moments->x, source->moments->y,
     323             source->moments->Sx, source->moments->Sy, source->moments->Sxy);
     324
     325    return(true);
     326}
     327
  • trunk/psphot/src/apply_psf_model.c

    r4574 r4582  
    2121    float FIT_PADDING = psMetadataLookupF32 (&status, config, "FIT_PADDING");
    2222    float shapeNsigma = psMetadataLookupF32 (&status, config, "PSF_SHAPE_NSIGMA");
    23     float snFaint     = psMetadataLookupF32 (&status, config, "FAINT_SN_LIM");
    2423    float OUTER       = psMetadataLookupF32 (&status, config, "OUTER_RADIUS");
    2524
  • trunk/psphot/src/basic_classes.c

    r4574 r4582  
    1111    // make this optional
    1212    // DumpMoments (sources, "moments.dat");
     13    return (true);
    1314}
  • trunk/psphot/src/fit_galaxies.c

    r4574 r4582  
    1414
    1515    float MOMENT_R = psMetadataLookupF32 (&status, config, "GAL_MOMENTS_RADIUS");
    16     float RADIUS   = psMetadataLookupF32 (&status, config, "FIT_RADIUS");
     16    // float RADIUS   = psMetadataLookupF32 (&status, config, "FIT_RADIUS");
    1717    float snFaint  = psMetadataLookupF32 (&status, config, "FAINT_SN_LIM");
    1818    float OUTER    = psMetadataLookupF32 (&status, config, "OUTER_RADIUS");
     
    2222    float FLUX_LIMIT  = FIT_NSIGMA * skyStats->sampleStdev;
    2323
    24     psModelType   modelType   = psModelSetType ("PS_MODEL_RGAUSS");
     24    psModelType   modelType   = psModelSetType ("PS_MODEL_SGAUSS");
    2525    psModelRadius modelRadius = psModelRadius_GetFunction (modelType);
    2626
     
    3434
    3535        // recalculate the source moments using the galaxy radius (larger)
    36         status = pmSourceMoments (source, MOMENT_R);
     36        status = pmSourceMoments_EAM (source, MOMENT_R);
     37        if (!status) {
     38          fprintf (stderr, "invalid moments, skipping\n");
     39          continue;
     40        }
    3741
    3842        // use the source moments, etc to guess basic model parameters
  • trunk/psphot/src/onesource.c

    r4421 r4582  
    1414    float MRAD   = psMetadataLookupF32 (&status, config, "PSF_MOMENTS_RADIUS");
    1515    float RADIUS = psMetadataLookupF32 (&status, config, "FIT_RADIUS");
     16    float SOFT   = psMetadataLookupF32 (&status, config, "SOFT_RADIUS");
    1617
    1718    psSource *source = pmSourceAlloc();
     
    2627
    2728    psImageKeepCircle (source->mask, x, y, RADIUS, OR, 0x80);
    28     status = pmSourceFitModel (source, model, false);
     29    status = pmSourceFitModel_EAM (source, model, false, SOFT);
    2930
    3031    pmSourcePhotometry (&fitMag, &obsMag, model, source->pixels, source->mask);
  • trunk/psphot/src/psphot.h

    r4574 r4582  
    6767bool DumpModelFits (psArray *models, char *filename);
    6868bool DumpModelPSF (psArray *sources, char *filename);
     69bool DumpModelFLT (psArray *sources, char *filename);
     70bool DumpModelNULL (psArray *sources, char *filename);
    6971bool DumpImage (psImage *image, char *filename);
     72bool DumpPSFTestData (pmPSF_Test *test, char *filename);
    7073
    7174// psphot utilities
     
    7780bool pmSourceDefinePixels(psSource *mySource, const psImageData *imdata, psF32 x, psF32 y, psF32 Radius);
    7881bool pmSourceLocalSky_EAM (psSource *source, psStatsOptions statsOptions, psF32 Radius);
     82bool pmSourceFitModel_EAM(psSource *source, psModel *model, const bool PSF, float SOFT);
     83bool pmSourceMoments_EAM(psSource *source, psF32 radius);
    7984
    8085// fitsource utilities
Note: See TracChangeset for help on using the changeset viewer.