Changeset 5048 for trunk/psphot/src/psModulesUtils.c
- Timestamp:
- Sep 13, 2005, 3:35:20 PM (21 years ago)
- File:
-
- 1 edited
-
trunk/psphot/src/psModulesUtils.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src/psModulesUtils.c
r4977 r5048 2 2 3 3 // 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 4 5 psF32 pmConfigLookupF32 (bool *status, psMetadata *config, psMetadata *header, char *name) { 5 6 … … 48 49 } 49 50 50 // XXX EAM : these are my alternate implementations of psModule functions51 52 // this sets and clears bit 0x8053 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 ptr64 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 1584 # define PM_SOURCE_FIT_MODEL_TOLERANCE 0.185 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? the102 // 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 pixels119 // XXX EAM : this loop and the loop below could just be one pass120 // using the psArrayAdd and psVectorExtend functions121 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 entries135 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 flux153 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(), then156 // 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 all166 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, ¶ms_min, ¶ms_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 false192 // XXX EAM: psMinimizeLMChi2 does not check convergence193 194 // XXX models can go insane: reject these195 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, nIter201 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 parameters206 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 the226 pmSource data structure, along with the peak location, and determines the227 various moments associated with that peak.228 229 Requires the following to have been created:230 pmSource231 pmSource->peak232 pmSource->pixels233 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/N239 *****************************************************************************/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 sky284 // 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 each286 // pixel that is not masked, AND within the radius of the peak pixel, we287 // proceed with the moments calculation. need to do two loops for a288 // numerically stable result. first loop: get the sums.289 // XXX EAM : mask == 0 is valid290 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 pixel303 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 + xc329 // second moment X = sqrt (X2/Sum - (X1/Sum)^2)330 // Sxy = XY / Sum331 //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 range350 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 361 51 bool pmModelFitStatus (pmModel *model) { 362 52
Note:
See TracChangeset
for help on using the changeset viewer.
