- Timestamp:
- Apr 12, 2006, 8:18:46 PM (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/rel10_ifa/psModules/src/objects/pmSourceFitModel.c
r6825 r6848 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1.1.2. 5$ $Name: not supported by cvs2svn $9 * @date $Date: 2006-04-1 0 20:21:36 $8 * @version $Revision: 1.1.2.6 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2006-04-13 06:18:46 $ 10 10 * 11 11 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 28 28 #include "pmSourceFitModel.h" 29 29 30 // save a static values so they may be set externally30 // save as static values so they may be set externally 31 31 static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15; 32 32 static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1; 33 34 bool pmSourceFitModelInit (float nIter, float tol) 33 static bool PM_PSF_POISSON_WEIGHTS = true; 34 35 bool pmSourceFitModelInit (float nIter, float tol, bool poissonErrors) 35 36 { 36 37 37 38 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = nIter; 38 39 PM_SOURCE_FIT_MODEL_TOLERANCE = tol; 40 PM_PSF_POISSON_WEIGHTS = poissonErrors; 41 39 42 return true; 40 43 } … … 42 45 bool pmSourceFitModel (pmSource *source, 43 46 pmModel *model, 44 const bool PSF)47 pmSourceFitMode mode) 45 48 { 46 49 psTrace(__func__, 3, "---- %s() begin ----\n", __func__); … … 65 68 pmModelFunc modelFunc = pmModelFunc_GetFunction (model->type); 66 69 67 int nParams = PSF ? 4 : params->n;68 70 psF32 dSky = source->moments->dSky; 69 71 … … 110 112 y->n = nPix; 111 113 yErr->n = nPix; 114 115 // XXX EAM : the new minimization API supplies the constraints as a struct 116 // XXX the chisq if a fcn of source flux. the minimization criterion should 117 // probably be scaled somehow by flux. measure the trend? it depends on 118 // the about of systematic error in the models themselves... 119 psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, 120 PM_SOURCE_FIT_MODEL_TOLERANCE); 121 psMinConstrain *constrain = psMinConstrainAlloc(); 122 123 // set parameter mask based on fitting mode 124 paramMask = psVectorAlloc (params->n, PS_TYPE_U8); 125 psVectorInit (paramMask, 1); 126 127 int nParams = 0; 128 switch (mode) { 129 case PM_SOURCE_FIT_NORM: 130 // NORM-only model fits only source normalization (Io) 131 nParams = 1; 132 paramMask->data.U8[1] = 0; 133 break; 134 case PM_SOURCE_FIT_PSF: 135 // PSF model only fits x,y,Io 136 nParams = 3; 137 paramMask->data.U8[1] = 0; 138 paramMask->data.U8[2] = 0; 139 paramMask->data.U8[3] = 0; 140 break; 141 case PM_SOURCE_FIT_EXT: 142 // EXT model fits all params (except sky) 143 nParams = params->n - 1; 144 psVectorInit (paramMask, 0); 145 paramMask->data.U8[0] = 1; 146 break; 147 case PM_SOURCE_FIT_PSF_AND_SKY: 148 nParams = 4; 149 psAbort ("pmSourceFitModel", "PSF + SKY not currently available"); 150 break; 151 case PM_SOURCE_FIT_EXT_AND_SKY: 152 nParams = params->n; 153 psAbort ("pmSourceFitModel", "EXT + SKY not currently available"); 154 break; 155 default: 156 psAbort ("pmSourceFitModel", "invalid fitting mode"); 157 } 158 constrain->paramMask = paramMask; 159 112 160 if (nPix < nParams + 1) { 113 161 psTrace (".pmObjects.pmSourceFitModel", 4, "insufficient valid pixels\n"); … … 117 165 psFree (y); 118 166 psFree (yErr); 167 psFree (myMin); 168 psFree (constrain); 169 psFree (paramMask); 119 170 return(false); 120 171 } 121 122 // XXX EAM : the new minimization API supplies the constraints as a struct123 // XXX the chisq if a fcn of source flux. the minimization criterion should124 // probably be scaled somehow by flux. measure the trend? it depends on125 // the about of systematic error in the models themselves...126 psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS,127 PM_SOURCE_FIT_MODEL_TOLERANCE);128 psMinConstrain *constrain = psMinConstrainAlloc();129 130 // PSF model only fits x,y,Io, EXT model fits all (both skip sky)131 paramMask = psVectorAlloc (params->n, PS_TYPE_U8);132 paramMask->data.U8[0] = 1;133 if (PSF) {134 for (int i = 1; i < 4; i++) {135 paramMask->data.U8[i] = 0;136 }137 for (int i = 4; i < paramMask->n; i++) {138 paramMask->data.U8[i] = 1;139 }140 } else {141 for (int i = 1; i < paramMask->n; i++) {142 paramMask->data.U8[i] = 0;143 }144 }145 constrain->paramMask = paramMask;146 172 147 173 // Set the parameter range checks … … 210 236 return(rc); 211 237 } 238 239 /********************* Source Model Set Functions ***************************/ 240 241 // these static variables are used by one pass of pmSourceFitSet to store 242 // data for a model set. If we are going to make psphot thread-safe, these 243 // will have to go in a structure of their own. 244 // sky, p1.1, p1.2, p1.3,... p1.n, p2.1, p2.2, 245 // nPar = nSrc*(nOnePar - 1) + 1 246 static pmModelFunc mFunc; 247 static int nPar; 248 static psVector *onePar; 249 static psVector *oneDeriv; 250 251 bool pmModelFitSetInit (pmModelType type) 252 { 253 254 mFunc = pmModelFunc_GetFunction (type); 255 nPar = pmModelParameterCount (type); 256 257 onePar = psVectorAlloc (nPar, PS_DATA_F32); 258 oneDeriv = psVectorAlloc (nPar, PS_DATA_F32); 259 260 return true; 261 } 262 263 void pmModelFitSetClear (void) 264 { 265 266 psFree (onePar); 267 psFree (oneDeriv); 268 return; 269 } 270 271 psF32 pmModelFitSet(psVector *deriv, 272 const psVector *params, 273 const psVector *x) 274 { 275 276 psF32 value; 277 psF32 model; 278 279 psF32 *PAR = onePar->data.F32; 280 psF32 *dPAR = oneDeriv->data.F32; 281 282 psF32 *pars = params->data.F32; 283 psF32 *dpars = (deriv == NULL) ? NULL : deriv->data.F32; 284 285 int nSrc = (params->n - 1) / (nPar - 1); 286 287 PAR[0] = model = pars[0]; 288 for (int i = 0; i < nSrc; i++) { 289 int nOff = i*nPar - i; 290 for (int n = 1; n < nPar; n++) { 291 PAR[n] = pars[nOff + n]; 292 } 293 if (deriv == NULL) { 294 value = mFunc (NULL, onePar, x); 295 } else { 296 value = mFunc (oneDeriv, onePar, x); 297 for (int n = 1; n < nPar; n++) { 298 dpars[nOff + n] = dPAR[n]; 299 } 300 } 301 model += value; 302 } 303 if (deriv != NULL) { 304 dpars[0] = dPAR[0]*2.0; 305 } 306 return (model); 307 } 308 309 /* 310 i: 0 1 2 311 n: 1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 4 5 6 312 i*6 + n: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 313 */ 314 315 bool pmSourceFitSet (pmSource *source, 316 psArray *modelSet, 317 pmSourceFitMode mode) 318 { 319 psTrace(__func__, 3, "---- %s() begin ----\n", __func__); 320 PS_ASSERT_PTR_NON_NULL(source, false); 321 PS_ASSERT_PTR_NON_NULL(source->moments, false); 322 PS_ASSERT_PTR_NON_NULL(source->peak, false); 323 PS_ASSERT_PTR_NON_NULL(source->pixels, false); 324 PS_ASSERT_PTR_NON_NULL(source->mask, false); 325 PS_ASSERT_PTR_NON_NULL(source->weight, false); 326 327 psBool fitStatus = true; 328 psBool onPic = true; 329 psBool rc = true; 330 331 // base values on first model 332 pmModel *model = modelSet->data[0]; 333 334 // set the static variables 335 pmModelFitSetInit (model->type); 336 337 int nSrc = modelSet->n; 338 int nPar = model->params->n - 1; // number of object parameters (excluding sky) 339 340 // define parameter vectors for source set 341 psVector *params = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32); 342 psVector *dparams = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32); 343 344 pmModelLimits modelLimits = pmModelLimits_GetFunction (model->type); 345 346 // define limits for a single-source model 347 psVector *oneDelta; 348 psVector *oneParMin; 349 psVector *oneParMax; 350 modelLimits (&oneDelta, &oneParMin, &oneParMax); 351 352 psMinConstrain *constrain = psMinConstrainAlloc(); 353 constrain->paramMin = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32); 354 constrain->paramMax = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32); 355 constrain->paramMask = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_U8); 356 constrain->paramDelta = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32); 357 358 // set the parameter guesses and constraints for the multiple models 359 // first the values for the single sky parameter 360 params->data.F32[0] = model->params->data.F32[0]; 361 constrain->paramMin->data.F32[0] = oneParMin->data.F32[0]; 362 constrain->paramMax->data.F32[0] = oneParMax->data.F32[0]; 363 constrain->paramDelta->data.F32[0] = oneDelta->data.F32[0]; 364 365 // next, the values for the source parameters 366 for (int i = 0; i < nSrc; i++) { 367 model = modelSet->data[i]; 368 for (int n = 1; n < nPar + 1; n++) { 369 params->data.F32[i*nPar + n] = model->params->data.F32[n]; 370 constrain->paramDelta->data.F32[i*nPar + n] = oneDelta->data.F32[n]; 371 constrain->paramMin->data.F32[i*nPar + n] = oneParMin->data.F32[n]; 372 constrain->paramMax->data.F32[i*nPar + n] = oneParMax->data.F32[n]; 373 } 374 } 375 psFree (oneDelta); 376 psFree (oneParMin); 377 psFree (oneParMax); 378 379 if (psTraceGetLevel(__func__) >= 5) { 380 for (int i = 0; i < params->n; i++) { 381 fprintf (stderr, "%d %f %d\n", i, params->data.F32[i], constrain->paramMask->data.U8[i]); 382 } 383 } 384 385 // set the parameter masks based on the fitting mode 386 int nParams = 0; 387 switch (mode) { 388 case PM_SOURCE_FIT_NORM: 389 // NORM-only model fits only source normalization (Io) 390 nParams = nSrc; 391 psVectorInit (constrain->paramMask, 1); 392 for (int i = 0; i < nSrc; i++) { 393 constrain->paramMask->data.U8[1 + i*nPar] = 0; 394 } 395 break; 396 case PM_SOURCE_FIT_PSF: 397 // PSF model only fits x,y,Io 398 nParams = 3*nSrc; 399 psVectorInit (constrain->paramMask, 1); 400 for (int i = 0; i < nSrc; i++) { 401 constrain->paramMask->data.U8[1 + i*nPar] = 0; 402 constrain->paramMask->data.U8[2 + i*nPar] = 0; 403 constrain->paramMask->data.U8[3 + i*nPar] = 0; 404 } 405 break; 406 case PM_SOURCE_FIT_EXT: 407 // EXT model fits all params (except sky) 408 nParams = nPar*nSrc; 409 psVectorInit (constrain->paramMask, 0); 410 constrain->paramMask->data.U8[0] = 1; 411 break; 412 case PM_SOURCE_FIT_PSF_AND_SKY: 413 nParams = 1 + 3*nSrc; 414 psAbort ("pmSourceFitModel", "PSF + SKY not currently available"); 415 break; 416 case PM_SOURCE_FIT_EXT_AND_SKY: 417 nParams = 1 + nPar*nSrc; 418 psAbort ("pmSourceFitModel", "EXT + SKY not currently available"); 419 break; 420 default: 421 psAbort ("pmSourceFitModel", "invalid fitting mode"); 422 } 423 424 // maximum number of valid pixels 425 psS32 nPix = source->pixels->numRows * source->pixels->numCols; 426 427 // local sky variance 428 psF32 dSky = source->moments->dSky; 429 430 // construct the coordinate and value entries 431 psArray *x = psArrayAlloc(nPix); 432 psVector *y = psVectorAlloc(nPix, PS_TYPE_F32); 433 psVector *yErr = psVectorAlloc(nPix, PS_TYPE_F32); 434 435 nPix = 0; 436 for (psS32 i = 0; i < source->pixels->numRows; i++) { 437 for (psS32 j = 0; j < source->pixels->numCols; j++) { 438 // skip masked points 439 if (source->mask->data.U8[i][j]) { 440 continue; 441 } 442 // skip zero-weight points 443 if (source->weight->data.F32[i][j] == 0) { 444 continue; 445 } 446 psVector *coord = psVectorAlloc(2, PS_TYPE_F32); 447 448 // Convert i/j to image space: 449 coord->data.F32[0] = (psF32) (j + source->pixels->col0); 450 coord->data.F32[1] = (psF32) (i + source->pixels->row0); 451 x->data[nPix] = (psPtr *) coord; 452 y->data.F32[nPix] = source->pixels->data.F32[i][j]; 453 // psMinimizeLMChi2 takes wt = 1/dY^2 454 if (PM_PSF_POISSON_WEIGHTS) { 455 yErr->data.F32[nPix] = 1.0 / source->weight->data.F32[i][j]; 456 } else { 457 yErr->data.F32[nPix] = 1.0 / dSky; 458 } 459 nPix++; 460 } 461 } 462 if (nPix < nParams + 1) { 463 psTrace (__func__, 4, "insufficient valid pixels\n"); 464 psTrace(__func__, 3, "---- %s() end : fail pixels ----\n", __func__); 465 model->status = PM_MODEL_BADARGS; 466 psFree (x); 467 psFree (y); 468 psFree (yErr); 469 psFree (params); 470 psFree (dparams); 471 psFree(constrain->paramMask); 472 psFree(constrain->paramMin); 473 psFree(constrain->paramMax); 474 psFree(constrain->paramDelta); 475 psFree(constrain); 476 return(false); 477 } 478 x->n = nPix; 479 y->n = nPix; 480 yErr->n = nPix; 481 482 psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, 483 PM_SOURCE_FIT_MODEL_TOLERANCE); 484 485 psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F64); 486 487 psTrace (__func__, 5, "fitting function\n"); 488 fitStatus = psMinimizeLMChi2(myMin, covar, params, constrain, x, y, yErr, pmModelFitSet); 489 490 // parameter errors from the covariance matrix 491 for (int i = 0; i < dparams->n; i++) { 492 if ((constrain->paramMask != NULL) && constrain->paramMask->data.U8[i]) 493 continue; 494 dparams->data.F32[i] = sqrt(covar->data.F64[i][i]); 495 } 496 497 // get the Gauss-Newton distance for fixed model parameters 498 if (constrain->paramMask != NULL) { 499 psVector *delta = psVectorAlloc (params->n, PS_TYPE_F64); 500 psMinimizeGaussNewtonDelta(delta, params, NULL, x, y, yErr, pmModelFitSet); 501 for (int i = 0; i < dparams->n; i++) { 502 if (!constrain->paramMask->data.U8[i]) 503 continue; 504 dparams->data.F32[i] = delta->data.F64[i]; 505 } 506 psFree (delta); 507 } 508 509 // assign back the parameters to the models 510 for (int i = 0; i < nSrc; i++) { 511 model = modelSet->data[i]; 512 model->params->data.F32[0] = params->data.F32[0]; 513 for (int n = 1; n < nPar + 1; n++) { 514 model->params->data.F32[n] = params->data.F32[i*nPar + n]; 515 model->dparams->data.F32[n] = dparams->data.F32[i*nPar + n]; 516 } 517 // save the resulting chisq, nDOF, nIter 518 // these are not unique for any one source 519 model->chisq = myMin->value; 520 model->nIter = myMin->iter; 521 model->nDOF = y->n - nParams; 522 523 // set the model success or failure status 524 model->status = fitStatus ? PM_MODEL_SUCCESS : PM_MODEL_NONCONVERGE; 525 526 // models can go insane: reject these 527 onPic &= (model->params->data.F32[2] >= source->pixels->col0); 528 onPic &= (model->params->data.F32[2] < source->pixels->col0 + source->pixels->numCols); 529 onPic &= (model->params->data.F32[3] >= source->pixels->row0); 530 onPic &= (model->params->data.F32[3] < source->pixels->row0 + source->pixels->numRows); 531 if (!onPic) { 532 model->status = PM_MODEL_OFFIMAGE; 533 } 534 } 535 536 source->mode |= PM_SOURCE_MODE_FITTED; 537 538 psFree(x); 539 psFree(y); 540 psFree(yErr); 541 psFree(myMin); 542 psFree(covar); 543 psFree(constrain->paramMask); 544 psFree(constrain->paramMin); 545 psFree(constrain->paramMax); 546 psFree(constrain->paramDelta); 547 psFree(constrain); 548 psFree(params); 549 psFree(dparams); 550 551 // free static memory used by pmModelFitSet 552 pmModelFitSetClear (); 553 554 rc = (onPic && fitStatus); 555 psTrace (__func__, 5, "onPic: %d, fitStatus: %d, nIter: %d, chisq: %f, nDof: %d\n", onPic, fitStatus, model->nIter, model->chisq, model->nDOF); 556 psTrace(__func__, 3, "---- %s end : status %d ----\n", __func__, rc); 557 return(rc); 558 } 559
Note:
See TracChangeset
for help on using the changeset viewer.
