Changeset 10259 for trunk/psModules/src/objects/pmSourceFitModel.c
- Timestamp:
- Nov 28, 2006, 4:41:31 PM (19 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/objects/pmSourceFitModel.c (modified) (26 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/objects/pmSourceFitModel.c
r10199 r10259 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1.1 7$ $Name: not supported by cvs2svn $9 * @date $Date: 2006-11-2 6 22:26:51 $8 * @version $Revision: 1.18 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2006-11-29 02:41:31 $ 10 10 * 11 11 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 36 36 static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1; 37 37 static psF32 PM_SOURCE_FIT_MODEL_WEIGHT = 1.0; 38 static bool PM_PSF_POISSON_WEIGHTS = true;38 static bool PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = true; 39 39 40 40 bool pmSourceFitModelInit (float nIter, float tol, float weight, bool poissonErrors) … … 44 44 PM_SOURCE_FIT_MODEL_TOLERANCE = tol; 45 45 PM_SOURCE_FIT_MODEL_WEIGHT = weight; 46 PM_ PSF_POISSON_WEIGHTS = poissonErrors;46 PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = poissonErrors; 47 47 48 48 return true; … … 53 53 pmSourceFitMode mode) 54 54 { 55 psTrace("psModules.objects", 5, "---- %s ()begin ----\n", __func__);55 psTrace("psModules.objects", 5, "---- %s begin ----\n", __func__); 56 56 PS_ASSERT_PTR_NON_NULL(source, false); 57 PS_ASSERT_PTR_NON_NULL(source->moments, false);58 57 PS_ASSERT_PTR_NON_NULL(source->pixels, false); 59 58 PS_ASSERT_PTR_NON_NULL(source->mask, false); 60 59 PS_ASSERT_PTR_NON_NULL(source->weight, false); 61 60 62 // XXX EAM : is it necessary for the mask & weight to exist? the63 // tests below could be conditions (!NULL)64 65 61 psBool fitStatus = true; 66 62 psBool onPic = true; 67 63 psBool rc = true; 68 64 69 psVector *params = model->params;70 psVector *dparams = model->dparams;71 psVector *paramMask = NULL;72 73 pmModelFunc modelFunc = pmModelFunc_GetFunction (model->type);74 75 psF32 dSky = source->moments->dSky;76 77 65 // maximum number of valid pixels 78 66 psS32 nPix = source->pixels->numRows * source->pixels->numCols; 79 67 80 // construct the coordinate and value entries68 // arrays to hold the data to be fitted 81 69 psArray *x = psArrayAllocEmpty(nPix); 82 70 psVector *y = psVectorAllocEmpty(nPix, PS_TYPE_F32); 83 71 psVector *yErr = psVectorAllocEmpty(nPix, PS_TYPE_F32); 84 72 73 // fill in the coordinate and value entries 85 74 nPix = 0; 86 75 for (psS32 i = 0; i < source->pixels->numRows; i++) { … … 102 91 x->data[nPix] = (psPtr *) coord; 103 92 y->data.F32[nPix] = source->pixels->data.F32[i][j]; 104 // psMinimizeLMChi2 takes wt = 1/dY^2 105 if (PM_PSF_POISSON_WEIGHTS) { 93 94 // psMinimizeLMChi2 takes wt = 1/dY^2. suggestion from RHL is to use the local sky 95 // as weight to avoid the bias from systematic errors here we would just use the 96 // source sky variance 97 if (PM_SOURCE_FIT_MODEL_PIX_WEIGHTS) { 106 98 yErr->data.F32[nPix] = 1.0 / source->weight->data.F32[i][j]; 107 99 } else { 108 yErr->data.F32[nPix] = 1.0 / dSky; 109 } 110 // XXX EAM : suggestion from RHL is to use the local sky as weight 111 // to avoid the bias from systematic errors 112 // here we would just use the source sky variance 100 yErr->data.F32[nPix] = 1.0 / PM_SOURCE_FIT_MODEL_WEIGHT; 101 } 113 102 nPix++; 114 103 } … … 118 107 yErr->n = nPix; 119 108 120 // XXX EAM : the new minimization API supplies the constraints as a struct 121 // XXX the chisq if a fcn of source flux. the minimization criterion should 122 // probably be scaled somehow by flux. measure the trend? it depends on 123 // the about of systematic error in the models themselves... 124 psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, 125 PM_SOURCE_FIT_MODEL_TOLERANCE); 126 psMinConstrain *constrain = psMinConstrainAlloc(); 109 psVector *params = model->params; 110 psVector *dparams = model->dparams; 111 112 pmModelFunc modelFunc = pmModelFunc_GetFunction (model->type); 113 if (!modelFunc) 114 psAbort ("pmSourceFitModel", "invalid model function"); 115 pmModelLimits checkLimits = pmModelLimits_GetFunction (model->type); 116 if (!checkLimits) 117 psAbort ("pmSourceFitModel", "invalid model limits function"); 118 119 // create the minimization constraints 120 psMinConstraint *constraint = psMinConstraintAlloc(); 121 constraint->paramMask = psVectorAlloc (params->n, PS_TYPE_U8); 122 constraint->checkLimits = checkLimits; 127 123 128 124 // set parameter mask based on fitting mode 129 paramMask = psVectorAlloc (params->n, PS_TYPE_U8);130 psVectorInit (paramMask, 1);131 132 125 int nParams = 0; 133 126 switch (mode) { … … 135 128 // NORM-only model fits only source normalization (Io) 136 129 nParams = 1; 137 paramMask->data.U8[PM_PAR_I0] = 0; 130 psVectorInit (constraint->paramMask, 1); 131 constraint->paramMask->data.U8[PM_PAR_I0] = 0; 138 132 break; 139 133 case PM_SOURCE_FIT_PSF: 140 134 // PSF model only fits x,y,Io 141 135 nParams = 3; 142 paramMask->data.U8[PM_PAR_I0] = 0; 143 paramMask->data.U8[PM_PAR_XPOS] = 0; 144 paramMask->data.U8[PM_PAR_YPOS] = 0; 136 psVectorInit (constraint->paramMask, 1); 137 constraint->paramMask->data.U8[PM_PAR_I0] = 0; 138 constraint->paramMask->data.U8[PM_PAR_XPOS] = 0; 139 constraint->paramMask->data.U8[PM_PAR_YPOS] = 0; 145 140 break; 146 141 case PM_SOURCE_FIT_EXT: 147 142 // EXT model fits all params (except sky) 148 143 nParams = params->n - 1; 149 psVectorInit (paramMask, 0); 150 paramMask->data.U8[PM_PAR_SKY] = 1; 151 break; 152 case PM_SOURCE_FIT_PSF_AND_SKY: 153 nParams = 4; 154 psAbort ("pmSourceFitModel", "PSF + SKY not currently available"); 155 break; 156 case PM_SOURCE_FIT_EXT_AND_SKY: 157 nParams = params->n; 158 psAbort ("pmSourceFitModel", "EXT + SKY not currently available"); 144 psVectorInit (constraint->paramMask, 0); 145 constraint->paramMask->data.U8[PM_PAR_SKY] = 1; 159 146 break; 160 147 default: 161 148 psAbort ("pmSourceFitModel", "invalid fitting mode"); 162 149 } 163 constrain->paramMask = paramMask; 150 // force the floating parameters to fall within the contraint ranges 151 for (int i = 0; i < params->n; i++) { 152 checkLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL); 153 checkLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL); 154 } 164 155 165 156 if (nPix < nParams + 1) { 166 157 psTrace ("psModules.objects", 4, "insufficient valid pixels\n"); 167 psTrace ("psModules.objects", 5, "---- %s(false) end ----\n", __func__);168 158 model->status = PM_MODEL_BADARGS; 169 159 psFree (x); 170 160 psFree (y); 171 161 psFree (yErr); 172 psFree (myMin); 173 psFree (constrain); 174 psFree (paramMask); 162 psFree (constraint); 175 163 return(false); 176 164 } 177 165 178 // Set the parameter range checks 179 pmModelLimits modelLimits = pmModelLimits_GetFunction (model->type); 180 modelLimits (&constrain->paramDelta, &constrain->paramMin, &constrain->paramMax); 181 182 // force the floating parameters to fall within the contraint ranges 183 for (int i = 0; i < params->n; i++) { 184 if (constrain->paramMask->data.U8[i]) 166 psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE); 167 168 psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32); 169 170 fitStatus = psMinimizeLMChi2(myMin, covar, params, constraint, x, y, yErr, modelFunc); 171 for (int i = 0; i < dparams->n; i++) { 172 if (psTraceGetLevel("psModules.objects") >= 4) { 173 fprintf (stderr, "%f ", params->data.F32[i]); 174 } 175 if ((constraint->paramMask != NULL) && constraint->paramMask->data.U8[i]) 185 176 continue; 186 params->data.F32[i] = PS_MIN(constrain->paramMax->data.F32[i], params->data.F32[i]); 187 params->data.F32[i] = PS_MAX(constrain->paramMin->data.F32[i], params->data.F32[i]); 188 } 189 190 psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F64); 191 192 psTrace (__func__, 5, "fitting function\n"); 193 194 fitStatus = psMinimizeLMChi2(myMin, covar, params, constrain, x, y, yErr, modelFunc); 195 for (int i = 0; i < dparams->n; i++) { 196 psTrace ("psModules.objects", 4, "%f ", params->data.F32[i]); 197 if ((paramMask != NULL) && paramMask->data.U8[i]) 198 continue; 199 dparams->data.F32[i] = sqrt(covar->data.F64[i][i]); 177 dparams->data.F32[i] = sqrt(covar->data.F32[i][i]); 200 178 } 201 179 psTrace ("psModules.objects", 4, "niter: %d, chisq: %f", myMin->iter, myMin->value); … … 208 186 // get the Gauss-Newton distance for fixed model parameters 209 187 // hold the fitted parameters fixed; mask sky which is not fitted at all 210 if ( paramMask != NULL) {211 psVector *delta = psVectorAlloc (params->n, PS_TYPE_F 64);188 if (constraint->paramMask != NULL) { 189 psVector *delta = psVectorAlloc (params->n, PS_TYPE_F32); 212 190 psVector *altmask = psVectorAlloc (params->n, PS_TYPE_U8); 213 191 altmask->data.U8[0] = 1; 214 192 for (int i = 1; i < dparams->n; i++) { 215 altmask->data.U8[i] = ( paramMask->data.U8[i]) ? 0 : 1;193 altmask->data.U8[i] = (constraint->paramMask->data.U8[i]) ? 0 : 1; 216 194 } 217 195 psMinimizeGaussNewtonDelta(delta, params, altmask, x, y, yErr, modelFunc); 218 196 for (int i = 0; i < dparams->n; i++) { 219 if (! paramMask->data.U8[i])197 if (!constraint->paramMask->data.U8[i]) 220 198 continue; 221 199 // note that delta is the value *subtracted* from the parameter 222 200 // to get the new guess. for dparams to represent the direction 223 201 // of motion, we need to take -delta 224 dparams->data.F32[i] = -delta->data.F 64[i];202 dparams->data.F32[i] = -delta->data.F32[i]; 225 203 } 226 204 psFree (delta); … … 251 229 psFree(myMin); 252 230 psFree(covar); 253 psFree(constrain->paramMask); 254 psFree(constrain->paramMin); 255 psFree(constrain->paramMax); 256 psFree(constrain->paramDelta); 257 psFree(constrain); 231 psFree(constraint); 258 232 259 233 rc = (onPic && fitStatus); … … 266 240 // these static variables are used by one pass of pmSourceFitSet to store 267 241 // data for a model set. If we are going to make psphot thread-safe, these 268 // will have to go in a structure of their own .242 // will have to go in a structure of their own or be allocated once per thread 269 243 // sky, p1.1, p1.2, p1.3,... p1.n, p2.1, p2.2, 270 244 // nPar = nSrc*(nOnePar - 1) + 1 271 static pmModelFunc mFunc;272 static int nPar;245 static pmModelFunc oneModelFunc; 246 static pmModelLimits oneCheckLimits; 273 247 static psVector *onePar; 274 248 static psVector *oneDeriv; 275 276 bool pmModelFitSetInit (pmModelType type) 277 { 278 279 mFunc = pmModelFunc_GetFunction (type); 280 nPar = pmModelParameterCount (type); 281 282 onePar = psVectorAlloc (nPar, PS_DATA_F32); 283 oneDeriv = psVectorAlloc (nPar, PS_DATA_F32); 249 static int nOnePar; 250 251 bool pmSourceFitSetInit (pmModelType type) 252 { 253 254 oneModelFunc = pmModelFunc_GetFunction (type); 255 oneCheckLimits = pmModelLimits_GetFunction (type); 256 nOnePar = pmModelParameterCount (type); 257 258 onePar = psVectorAlloc (nOnePar, PS_DATA_F32); 259 oneDeriv = psVectorAlloc (nOnePar, PS_DATA_F32); 284 260 285 261 return true; 286 262 } 287 263 288 void pm ModelFitSetClear (void)264 void pmSourceFitSetClear (void) 289 265 { 290 266 … … 294 270 } 295 271 296 psF32 pmModelFitSet(psVector *deriv, 297 const psVector *params, 298 const psVector *x) 272 bool pmSourceFitSet_CheckLimits (psMinConstraintMode mode, int nParam, float *params, float *betas) 273 { 274 // convert the value of nParam into corresponding single model parameter entry 275 // convert params into corresponding single model parameter pointer 276 277 int nParamSingle = (nParam - 1) % (nOnePar - 1) + 1; 278 float *paramSingle = params + nParam - nParamSingle; 279 float *betaSingle = betas + nParam - nParamSingle; 280 bool status = oneCheckLimits (mode, nParamSingle, paramSingle, betaSingle); 281 return status; 282 } 283 284 psF32 pmSourceFitSet_Function(psVector *deriv, 285 const psVector *params, 286 const psVector *x) 299 287 { 300 288 … … 308 296 psF32 *dpars = (deriv == NULL) ? NULL : deriv->data.F32; 309 297 310 int nSrc = (params->n - 1) / (n Par - 1);298 int nSrc = (params->n - 1) / (nOnePar - 1); 311 299 312 300 PAR[0] = model = pars[0]; 313 301 for (int i = 0; i < nSrc; i++) { 314 int nOff = i*n Par - i;315 for (int n = 1; n < n Par; n++) {302 int nOff = i*nOnePar - i; 303 for (int n = 1; n < nOnePar; n++) { 316 304 PAR[n] = pars[nOff + n]; 317 305 } 318 306 if (deriv == NULL) { 319 value = mFunc (NULL, onePar, x);307 value = oneModelFunc (NULL, onePar, x); 320 308 } else { 321 value = mFunc (oneDeriv, onePar, x);322 for (int n = 1; n < n Par; n++) {309 value = oneModelFunc (oneDeriv, onePar, x); 310 for (int n = 1; n < nOnePar; n++) { 323 311 dpars[nOff + n] = dPAR[n]; 324 312 } … … 333 321 334 322 /* 335 i: 0 12323 i: 0 1 2 336 324 n: 1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 4 5 6 337 325 i*6 + n: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 … … 342 330 pmSourceFitMode mode) 343 331 { 344 psTrace("psModules.objects", 3, "---- %s ()begin ----\n", __func__);332 psTrace("psModules.objects", 3, "---- %s begin ----\n", __func__); 345 333 PS_ASSERT_PTR_NON_NULL(source, false); 346 PS_ASSERT_PTR_NON_NULL(source->moments, false);347 334 PS_ASSERT_PTR_NON_NULL(source->pixels, false); 348 335 PS_ASSERT_PTR_NON_NULL(source->mask, false); … … 353 340 psBool rc = true; 354 341 355 // base values on first model 342 // maximum number of valid pixels 343 psS32 nPix = source->pixels->numRows * source->pixels->numCols; 344 345 // construct the coordinate and value entries 346 psArray *x = psArrayAllocEmpty(nPix); 347 psVector *y = psVectorAllocEmpty(nPix, PS_TYPE_F32); 348 psVector *yErr = psVectorAllocEmpty(nPix, PS_TYPE_F32); 349 350 // fill in the coordinate and value entries 351 nPix = 0; 352 for (psS32 i = 0; i < source->pixels->numRows; i++) { 353 for (psS32 j = 0; j < source->pixels->numCols; j++) { 354 // skip masked points 355 if (source->mask->data.U8[i][j]) { 356 continue; 357 } 358 // skip zero-weight points 359 if (source->weight->data.F32[i][j] == 0) { 360 continue; 361 } 362 psVector *coord = psVectorAlloc(2, PS_TYPE_F32); 363 364 // Convert i/j to image space: 365 coord->data.F32[0] = (psF32) (j + source->pixels->col0); 366 coord->data.F32[1] = (psF32) (i + source->pixels->row0); 367 x->data[nPix] = (psPtr *) coord; 368 y->data.F32[nPix] = source->pixels->data.F32[i][j]; 369 370 // psMinimizeLMChi2 takes wt = 1/dY^2. suggestion from RHL is to use the local sky 371 // as weight to avoid the bias from systematic errors here we would just use the 372 // source sky variance 373 if (PM_SOURCE_FIT_MODEL_PIX_WEIGHTS) { 374 yErr->data.F32[nPix] = 1.0 / source->weight->data.F32[i][j]; 375 } else { 376 yErr->data.F32[nPix] = 1.0 / PM_SOURCE_FIT_MODEL_WEIGHT; 377 } 378 nPix++; 379 } 380 } 381 x->n = nPix; 382 y->n = nPix; 383 yErr->n = nPix; 384 385 // base values on first model (all models must be identical) 356 386 pmModel *model = modelSet->data[0]; 357 387 358 // set the static variables 359 pmModelFitSetInit (model->type); 360 388 // determine number of model parameters 361 389 int nSrc = modelSet->n; 362 390 int nPar = model->params->n - 1; // number of object parameters (excluding sky) … … 366 394 psVector *dparams = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32); 367 395 368 pmModelLimits modelLimits = pmModelLimits_GetFunction (model->type); 369 370 // define limits for a single-source model 371 psVector *oneDelta; 372 psVector *oneParMin; 373 psVector *oneParMax; 374 modelLimits (&oneDelta, &oneParMin, &oneParMax); 375 376 psMinConstrain *constrain = psMinConstrainAlloc(); 377 constrain->paramMin = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32); 378 constrain->paramMax = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32); 379 constrain->paramMask = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_U8); 380 constrain->paramDelta = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32); 381 382 // set the parameter guesses and constraints for the multiple models 383 // first the values for the single sky parameter 396 // set the static variables 397 pmSourceFitSetInit (model->type); 398 399 // create the minimization constraints 400 psMinConstraint *constraint = psMinConstraintAlloc(); 401 constraint->paramMask = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_U8); 402 constraint->checkLimits = pmSourceFitSet_CheckLimits; 403 404 // set the parameter guesses for the multiple models 405 // first the value for the single sky parameter 384 406 params->data.F32[0] = model->params->data.F32[0]; 385 constrain->paramMin->data.F32[0] = oneParMin->data.F32[0];386 constrain->paramMax->data.F32[0] = oneParMax->data.F32[0];387 constrain->paramDelta->data.F32[0] = oneDelta->data.F32[0];388 407 389 408 // next, the values for the source parameters … … 392 411 for (int n = 1; n < nPar + 1; n++) { 393 412 params->data.F32[i*nPar + n] = model->params->data.F32[n]; 394 constrain->paramDelta->data.F32[i*nPar + n] = oneDelta->data.F32[n]; 395 constrain->paramMin->data.F32[i*nPar + n] = oneParMin->data.F32[n]; 396 constrain->paramMax->data.F32[i*nPar + n] = oneParMax->data.F32[n]; 397 } 398 } 399 psFree (oneDelta); 400 psFree (oneParMin); 401 psFree (oneParMax); 413 } 414 } 402 415 403 416 if (psTraceGetLevel("psModules.objects") >= 5) { 404 417 for (int i = 0; i < params->n; i++) { 405 fprintf (stderr, "%d %f %d\n", i, params->data.F32[i], constrain ->paramMask->data.U8[i]);418 fprintf (stderr, "%d %f %d\n", i, params->data.F32[i], constraint->paramMask->data.U8[i]); 406 419 } 407 420 } … … 413 426 // NORM-only model fits only source normalization (Io) 414 427 nParams = nSrc; 415 psVectorInit (constrain ->paramMask, 1);428 psVectorInit (constraint->paramMask, 1); 416 429 for (int i = 0; i < nSrc; i++) { 417 constrain ->paramMask->data.U8[1 + i*nPar] = 0;430 constraint->paramMask->data.U8[1 + i*nPar] = 0; 418 431 } 419 432 break; … … 421 434 // PSF model only fits x,y,Io 422 435 nParams = 3*nSrc; 423 psVectorInit (constrain ->paramMask, 1);436 psVectorInit (constraint->paramMask, 1); 424 437 for (int i = 0; i < nSrc; i++) { 425 constrain ->paramMask->data.U8[1 + i*nPar] = 0;426 constrain ->paramMask->data.U8[2 + i*nPar] = 0;427 constrain ->paramMask->data.U8[3 + i*nPar] = 0;438 constraint->paramMask->data.U8[1 + i*nPar] = 0; 439 constraint->paramMask->data.U8[2 + i*nPar] = 0; 440 constraint->paramMask->data.U8[3 + i*nPar] = 0; 428 441 } 429 442 break; … … 431 444 // EXT model fits all params (except sky) 432 445 nParams = nPar*nSrc; 433 psVectorInit (constrain->paramMask, 0); 434 constrain->paramMask->data.U8[0] = 1; 435 break; 436 case PM_SOURCE_FIT_PSF_AND_SKY: 437 nParams = 1 + 3*nSrc; 438 psAbort ("pmSourceFitModel", "PSF + SKY not currently available"); 439 break; 440 case PM_SOURCE_FIT_EXT_AND_SKY: 441 nParams = 1 + nPar*nSrc; 442 psAbort ("pmSourceFitModel", "EXT + SKY not currently available"); 446 psVectorInit (constraint->paramMask, 0); 447 constraint->paramMask->data.U8[0] = 1; 443 448 break; 444 449 default: … … 448 453 // force the floating parameters to fall within the contraint ranges 449 454 for (int i = 0; i < params->n; i++) { 450 if (constrain->paramMask->data.U8[i]) 451 continue; 452 params->data.F32[i] = PS_MIN(constrain->paramMax->data.F32[i], params->data.F32[i]); 453 params->data.F32[i] = PS_MAX(constrain->paramMin->data.F32[i], params->data.F32[i]); 454 } 455 456 // maximum number of valid pixels 457 psS32 nPix = source->pixels->numRows * source->pixels->numCols; 458 459 // local sky variance 460 psF32 dSky = source->moments->dSky; 461 462 // construct the coordinate and value entries 463 psArray *x = psArrayAllocEmpty(nPix); 464 psVector *y = psVectorAllocEmpty(nPix, PS_TYPE_F32); 465 psVector *yErr = psVectorAllocEmpty(nPix, PS_TYPE_F32); 466 467 nPix = 0; 468 for (psS32 i = 0; i < source->pixels->numRows; i++) { 469 for (psS32 j = 0; j < source->pixels->numCols; j++) { 470 // skip masked points 471 if (source->mask->data.U8[i][j]) { 472 continue; 473 } 474 // skip zero-weight points 475 if (source->weight->data.F32[i][j] == 0) { 476 continue; 477 } 478 psVector *coord = psVectorAlloc(2, PS_TYPE_F32); 479 480 // Convert i/j to image space: 481 coord->data.F32[0] = (psF32) (j + source->pixels->col0); 482 coord->data.F32[1] = (psF32) (i + source->pixels->row0); 483 x->data[nPix] = (psPtr *) coord; 484 y->data.F32[nPix] = source->pixels->data.F32[i][j]; 485 // psMinimizeLMChi2 takes wt = 1/dY^2 486 if (PM_PSF_POISSON_WEIGHTS) { 487 yErr->data.F32[nPix] = 1.0 / source->weight->data.F32[i][j]; 488 } else { 489 yErr->data.F32[nPix] = 1.0 / dSky; 490 } 491 nPix++; 492 } 493 } 455 pmSourceFitSet_CheckLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL); 456 pmSourceFitSet_CheckLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL); 457 } 458 494 459 if (nPix < nParams + 1) { 495 460 psTrace (__func__, 4, "insufficient valid pixels\n"); … … 501 466 psFree (params); 502 467 psFree (dparams); 503 psFree(constrain->paramMask); 504 psFree(constrain->paramMin); 505 psFree(constrain->paramMax); 506 psFree(constrain->paramDelta); 507 psFree(constrain); 508 pmModelFitSetClear (); 468 psFree(constraint); 469 pmSourceFitSetClear (); 509 470 return(false); 510 471 } 511 x->n = nPix; 512 y->n = nPix; 513 yErr->n = nPix; 514 515 psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, 516 PM_SOURCE_FIT_MODEL_TOLERANCE); 517 518 psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F64); 519 520 psTrace (__func__, 5, "fitting function\n"); 521 fitStatus = psMinimizeLMChi2(myMin, covar, params, constrain, x, y, yErr, pmModelFitSet); 472 473 psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE); 474 475 psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32); 476 477 fitStatus = psMinimizeLMChi2(myMin, covar, params, constraint, x, y, yErr, pmSourceFitSet_Function); 522 478 if (!fitStatus) { 523 // psError(PS_ERR_UNKNOWN, false, "Failed to fit model (%d)\n", nSrc);524 479 psTrace("psModules.objects", 4, "Failed to fit model (%d)\n", nSrc); 525 480 } … … 527 482 // parameter errors from the covariance matrix 528 483 for (int i = 0; i < dparams->n; i++) { 529 if ((constrain ->paramMask != NULL) && constrain->paramMask->data.U8[i])484 if ((constraint->paramMask != NULL) && constraint->paramMask->data.U8[i]) 530 485 continue; 531 dparams->data.F32[i] = sqrt(covar->data.F 64[i][i]);486 dparams->data.F32[i] = sqrt(covar->data.F32[i][i]); 532 487 } 533 488 534 489 // get the Gauss-Newton distance for fixed model parameters 535 if (constrain ->paramMask != NULL) {536 psVector *delta = psVectorAlloc (params->n, PS_TYPE_F 64);490 if (constraint->paramMask != NULL) { 491 psVector *delta = psVectorAlloc (params->n, PS_TYPE_F32); 537 492 psVector *altmask = psVectorAlloc (params->n, PS_TYPE_U8); 538 493 altmask->data.U8[0] = 1; 539 494 for (int i = 1; i < dparams->n; i++) { 540 altmask->data.U8[i] = (constrain ->paramMask->data.U8[i]) ? 0 : 1;541 } 542 psMinimizeGaussNewtonDelta(delta, params, altmask, x, y, yErr, pm ModelFitSet);495 altmask->data.U8[i] = (constraint->paramMask->data.U8[i]) ? 0 : 1; 496 } 497 psMinimizeGaussNewtonDelta(delta, params, altmask, x, y, yErr, pmSourceFitSet_Function); 543 498 for (int i = 0; i < dparams->n; i++) { 544 if (!constrain ->paramMask->data.U8[i])499 if (!constraint->paramMask->data.U8[i]) 545 500 continue; 546 501 // note that delta is the value *subtracted* from the parameter 547 502 // to get the new guess. for dparams to represent the direction 548 503 // of motion, we need to take -delta 549 dparams->data.F32[i] = -delta->data.F 64[i];504 dparams->data.F32[i] = -delta->data.F32[i]; 550 505 } 551 506 psFree (delta); … … 558 513 model->params->data.F32[0] = params->data.F32[0]; 559 514 for (int n = 1; n < nPar + 1; n++) { 515 if (psTraceGetLevel("psModules.objects") >= 4) { 516 fprintf (stderr, "%f ", params->data.F32[i*nPar + n]); 517 } 560 518 model->params->data.F32[n] = params->data.F32[i*nPar + n]; 561 519 model->dparams->data.F32[n] = dparams->data.F32[i*nPar + n]; 562 520 } 521 psTrace ("psModules.objects", 4, " src %d", i); 522 563 523 // save the resulting chisq, nDOF, nIter 564 524 // these are not unique for any one source … … 571 531 572 532 // models can go insane: reject these 573 onPic &= (model->params->data.F32[ 2] >= source->pixels->col0);574 onPic &= (model->params->data.F32[ 2] < source->pixels->col0 + source->pixels->numCols);575 onPic &= (model->params->data.F32[ 3] >= source->pixels->row0);576 onPic &= (model->params->data.F32[ 3] < source->pixels->row0 + source->pixels->numRows);533 onPic &= (model->params->data.F32[PM_PAR_XPOS] >= source->pixels->col0); 534 onPic &= (model->params->data.F32[PM_PAR_XPOS] < source->pixels->col0 + source->pixels->numCols); 535 onPic &= (model->params->data.F32[PM_PAR_XPOS] >= source->pixels->row0); 536 onPic &= (model->params->data.F32[PM_PAR_XPOS] < source->pixels->row0 + source->pixels->numRows); 577 537 if (!onPic) { 578 538 model->status = PM_MODEL_OFFIMAGE; 579 539 } 580 540 } 541 psTrace ("psModules.objects", 4, "niter: %d, chisq: %f", myMin->iter, myMin->value); 581 542 582 543 source->mode |= PM_SOURCE_MODE_FITTED; … … 587 548 psFree(myMin); 588 549 psFree(covar); 589 psFree(constrain->paramMask); 590 psFree(constrain->paramMin); 591 psFree(constrain->paramMax); 592 psFree(constrain->paramDelta); 593 psFree(constrain); 550 psFree(constraint); 594 551 psFree(params); 595 552 psFree(dparams); 596 553 597 // free static memory used by pm ModelFitSet598 pm ModelFitSetClear ();554 // free static memory used by pmSourceFitSet 555 pmSourceFitSetClear (); 599 556 600 557 rc = (onPic && fitStatus); 601 558 psTrace (__func__, 5, "onPic: %d, fitStatus: %d, nIter: %d, chisq: %f, nDof: %d\n", onPic, fitStatus, model->nIter, model->chisq, model->nDOF); 602 psTrace("psModules.objects", 3, "---- %s end : status %d----\n", __func__, rc);559 psTrace("psModules.objects", 5, "---- %s end (%d) ----\n", __func__, rc); 603 560 return(rc); 604 561 }
Note:
See TracChangeset
for help on using the changeset viewer.
