Changeset 14652 for trunk/psModules/src/objects/pmSourceFitModel.c
- Timestamp:
- Aug 23, 2007, 2:11:02 PM (19 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/objects/pmSourceFitModel.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/objects/pmSourceFitModel.c
r13932 r14652 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1.2 4$ $Name: not supported by cvs2svn $9 * @date $Date: 2007-0 6-21 22:58:11$8 * @version $Revision: 1.25 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2007-08-24 00:11:02 $ 10 10 * 11 11 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 27 27 #include "pmGrowthCurve.h" 28 28 #include "pmResiduals.h" 29 #include "pmPSF.h" 29 30 #include "pmModel.h" 30 #include "pmPSF.h"31 31 #include "pmSource.h" 32 #include "pmModel Group.h"32 #include "pmModelClass.h" 33 33 #include "pmSourceFitModel.h" 34 34 … … 116 116 psVector *dparams = model->dparams; 117 117 118 pmModelFunc modelFunc = pmModelFunc_GetFunction (model->type);119 if (!modelFunc)120 psAbort("invalid model function");121 pmModelLimits checkLimits = pmModelLimits_GetFunction (model->type);122 if (!checkLimits)123 psAbort("invalid model limits function");124 125 118 // create the minimization constraints 126 119 psMinConstraint *constraint = psMinConstraintAlloc(); 127 120 constraint->paramMask = psVectorAlloc (params->n, PS_TYPE_U8); 128 constraint->checkLimits = checkLimits;121 constraint->checkLimits = model->modelLimits; 129 122 130 123 // set parameter mask based on fitting mode … … 156 149 // force the floating parameters to fall within the contraint ranges 157 150 for (int i = 0; i < params->n; i++) { 158 checkLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);159 checkLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);151 model->modelLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL); 152 model->modelLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL); 160 153 } 161 154 … … 174 167 psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32); 175 168 176 fitStatus = psMinimizeLMChi2(myMin, covar, params, constraint, x, y, yErr, model Func);169 fitStatus = psMinimizeLMChi2(myMin, covar, params, constraint, x, y, yErr, model->modelFunc); 177 170 for (int i = 0; i < dparams->n; i++) { 178 171 if (psTraceGetLevel("psModules.objects") >= 4) { … … 201 194 altmask->data.U8[i] = (constraint->paramMask->data.U8[i]) ? 0 : 1; 202 195 } 203 psMinimizeGaussNewtonDelta(delta, params, altmask, x, y, yErr, model Func);196 psMinimizeGaussNewtonDelta(delta, params, altmask, x, y, yErr, model->modelFunc); 204 197 for (int i = 0; i < dparams->n; i++) { 205 198 if (!constraint->paramMask->data.U8[i]) … … 237 230 } 238 231 239 /********************* Source Model Set Functions ***************************/240 241 // these static variables are used by one pass of pmSourceFitSet to store242 // data for a model set. If we are going to make psphot thread-safe, these243 // will have to go in a structure of their own or be allocated once per thread244 // sky, p1.1, p1.2, p1.3,... p1.n, p2.1, p2.2,245 // nPar = nSrc*(nOnePar - 1) + 1246 static pmModelFunc oneModelFunc;247 static pmModelLimits oneCheckLimits;248 static psVector *onePar;249 static psVector *oneDeriv;250 static int nOnePar;251 252 bool pmSourceFitSetInit (pmModelType type)253 {254 255 oneModelFunc = pmModelFunc_GetFunction (type);256 oneCheckLimits = pmModelLimits_GetFunction (type);257 nOnePar = pmModelParameterCount (type);258 259 onePar = psVectorAlloc (nOnePar, PS_DATA_F32);260 oneDeriv = psVectorAlloc (nOnePar, PS_DATA_F32);261 262 return true;263 }264 265 void pmSourceFitSetClear (void)266 {267 268 psFree (onePar);269 psFree (oneDeriv);270 return;271 }272 273 bool pmSourceFitSet_CheckLimits (psMinConstraintMode mode, int nParam, float *params, float *betas)274 {275 // convert the value of nParam into corresponding single model parameter entry276 // convert params into corresponding single model parameter pointer277 278 int nParamSingle = (nParam - 1) % (nOnePar - 1) + 1;279 float *paramSingle = params + nParam - nParamSingle;280 float *betaSingle = betas + nParam - nParamSingle;281 bool status = oneCheckLimits (mode, nParamSingle, paramSingle, betaSingle);282 return status;283 }284 285 psF32 pmSourceFitSet_Function(psVector *deriv,286 const psVector *params,287 const psVector *x)288 {289 290 psF32 value;291 psF32 model;292 293 psF32 *PAR = onePar->data.F32;294 psF32 *dPAR = oneDeriv->data.F32;295 296 psF32 *pars = params->data.F32;297 psF32 *dpars = (deriv == NULL) ? NULL : deriv->data.F32;298 299 int nSrc = (params->n - 1) / (nOnePar - 1);300 301 PAR[0] = model = pars[0];302 for (int i = 0; i < nSrc; i++) {303 int nOff = i*nOnePar - i;304 for (int n = 1; n < nOnePar; n++) {305 PAR[n] = pars[nOff + n];306 }307 if (deriv == NULL) {308 value = oneModelFunc (NULL, onePar, x);309 } else {310 value = oneModelFunc (oneDeriv, onePar, x);311 for (int n = 1; n < nOnePar; n++) {312 dpars[nOff + n] = dPAR[n];313 }314 }315 model += value;316 }317 if (deriv != NULL) {318 dpars[0] = dPAR[0]*2.0;319 }320 return (model);321 }322 323 /*324 i: 0 1 2325 n: 1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 4 5 6326 i*6 + n: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18327 */328 329 bool pmSourceFitSet (pmSource *source,330 psArray *modelSet,331 pmSourceFitMode mode,332 psMaskType maskVal)333 {334 psTrace("psModules.objects", 3, "---- %s begin ----\n", __func__);335 PS_ASSERT_PTR_NON_NULL(source, false);336 PS_ASSERT_PTR_NON_NULL(source->pixels, false);337 PS_ASSERT_PTR_NON_NULL(source->maskObj, false);338 PS_ASSERT_PTR_NON_NULL(source->weight, false);339 340 psBool fitStatus = true;341 psBool onPic = true;342 psBool rc = true;343 344 // maximum number of valid pixels345 psS32 nPix = source->pixels->numRows * source->pixels->numCols;346 347 // construct the coordinate and value entries348 psArray *x = psArrayAllocEmpty(nPix);349 psVector *y = psVectorAllocEmpty(nPix, PS_TYPE_F32);350 psVector *yErr = psVectorAllocEmpty(nPix, PS_TYPE_F32);351 352 // fill in the coordinate and value entries353 nPix = 0;354 for (psS32 i = 0; i < source->pixels->numRows; i++) {355 for (psS32 j = 0; j < source->pixels->numCols; j++) {356 // skip masked points357 if (source->maskObj->data.U8[i][j] & maskVal) {358 continue;359 }360 // skip zero-weight points361 if (source->weight->data.F32[i][j] == 0) {362 continue;363 }364 // skip nan values in image365 if (!isfinite(source->pixels->data.F32[i][j])) {366 continue;367 }368 369 psVector *coord = psVectorAlloc(2, PS_TYPE_F32);370 371 // Convert i/j to image space:372 coord->data.F32[0] = (psF32) (j + source->pixels->col0);373 coord->data.F32[1] = (psF32) (i + source->pixels->row0);374 x->data[nPix] = (psPtr *) coord;375 y->data.F32[nPix] = source->pixels->data.F32[i][j];376 377 // psMinimizeLMChi2 takes wt = 1/dY^2. suggestion from RHL is to use the local sky378 // as weight to avoid the bias from systematic errors here we would just use the379 // source sky variance380 if (PM_SOURCE_FIT_MODEL_PIX_WEIGHTS) {381 yErr->data.F32[nPix] = 1.0 / source->weight->data.F32[i][j];382 } else {383 yErr->data.F32[nPix] = 1.0 / PM_SOURCE_FIT_MODEL_WEIGHT;384 }385 nPix++;386 }387 }388 x->n = nPix;389 y->n = nPix;390 yErr->n = nPix;391 392 // base values on first model (all models must be identical)393 pmModel *model = modelSet->data[0];394 395 // determine number of model parameters396 int nSrc = modelSet->n;397 int nPar = model->params->n - 1; // number of object parameters (excluding sky)398 399 // define parameter vectors for source set400 psVector *params = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32);401 psVector *dparams = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_F32);402 403 // set the static variables404 pmSourceFitSetInit (model->type);405 406 // create the minimization constraints407 psMinConstraint *constraint = psMinConstraintAlloc();408 constraint->paramMask = psVectorAlloc (nSrc*nPar + 1, PS_TYPE_U8);409 constraint->checkLimits = pmSourceFitSet_CheckLimits;410 411 // set the parameter guesses for the multiple models412 // first the value for the single sky parameter413 params->data.F32[0] = model->params->data.F32[0];414 415 // next, the values for the source parameters416 for (int i = 0; i < nSrc; i++) {417 model = modelSet->data[i];418 for (int n = 1; n < nPar + 1; n++) {419 params->data.F32[i*nPar + n] = model->params->data.F32[n];420 }421 }422 423 if (psTraceGetLevel("psModules.objects") >= 5) {424 for (int i = 0; i < params->n; i++) {425 fprintf (stderr, "%d %f %d\n", i, params->data.F32[i], constraint->paramMask->data.U8[i]);426 }427 }428 429 // set the parameter masks based on the fitting mode430 int nParams = 0;431 switch (mode) {432 case PM_SOURCE_FIT_NORM:433 // NORM-only model fits only source normalization (Io)434 nParams = nSrc;435 psVectorInit (constraint->paramMask, 1);436 for (int i = 0; i < nSrc; i++) {437 constraint->paramMask->data.U8[1 + i*nPar] = 0;438 }439 break;440 case PM_SOURCE_FIT_PSF:441 // PSF model only fits x,y,Io442 nParams = 3*nSrc;443 psVectorInit (constraint->paramMask, 1);444 for (int i = 0; i < nSrc; i++) {445 constraint->paramMask->data.U8[1 + i*nPar] = 0;446 constraint->paramMask->data.U8[2 + i*nPar] = 0;447 constraint->paramMask->data.U8[3 + i*nPar] = 0;448 }449 break;450 case PM_SOURCE_FIT_EXT:451 // EXT model fits all params (except sky)452 nParams = nPar*nSrc;453 psVectorInit (constraint->paramMask, 0);454 constraint->paramMask->data.U8[0] = 1;455 break;456 default:457 psAbort("invalid fitting mode");458 }459 460 // force the floating parameters to fall within the contraint ranges461 for (int i = 0; i < params->n; i++) {462 pmSourceFitSet_CheckLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);463 pmSourceFitSet_CheckLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);464 }465 466 if (nPix < nParams + 1) {467 psTrace (__func__, 4, "insufficient valid pixels\n");468 psTrace("psModules.objects", 3, "---- %s() end : fail pixels ----\n", __func__);469 model->flags |= PM_MODEL_STATUS_BADARGS;470 psFree (x);471 psFree (y);472 psFree (yErr);473 psFree (params);474 psFree (dparams);475 psFree(constraint);476 pmSourceFitSetClear ();477 return(false);478 }479 480 psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE);481 482 psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);483 484 fitStatus = psMinimizeLMChi2(myMin, covar, params, constraint, x, y, yErr, pmSourceFitSet_Function);485 if (!fitStatus) {486 psTrace("psModules.objects", 4, "Failed to fit model (%d)\n", nSrc);487 }488 489 // parameter errors from the covariance matrix490 for (int i = 0; i < dparams->n; i++) {491 if ((constraint->paramMask != NULL) && constraint->paramMask->data.U8[i])492 continue;493 dparams->data.F32[i] = sqrt(covar->data.F32[i][i]);494 }495 496 // get the Gauss-Newton distance for fixed model parameters497 if (constraint->paramMask != NULL) {498 psVector *delta = psVectorAlloc (params->n, PS_TYPE_F32);499 psVector *altmask = psVectorAlloc (params->n, PS_TYPE_U8);500 altmask->data.U8[0] = 1;501 for (int i = 1; i < dparams->n; i++) {502 altmask->data.U8[i] = (constraint->paramMask->data.U8[i]) ? 0 : 1;503 }504 psMinimizeGaussNewtonDelta(delta, params, altmask, x, y, yErr, pmSourceFitSet_Function);505 for (int i = 0; i < dparams->n; i++) {506 if (!constraint->paramMask->data.U8[i])507 continue;508 // note that delta is the value *subtracted* from the parameter509 // to get the new guess. for dparams to represent the direction510 // of motion, we need to take -delta511 dparams->data.F32[i] = -delta->data.F32[i];512 }513 psFree (delta);514 psFree (altmask);515 }516 517 // assign back the parameters to the models518 for (int i = 0; i < nSrc; i++) {519 model = modelSet->data[i];520 model->params->data.F32[0] = params->data.F32[0];521 for (int n = 1; n < nPar + 1; n++) {522 if (psTraceGetLevel("psModules.objects") >= 4) {523 fprintf (stderr, "%f ", params->data.F32[i*nPar + n]);524 }525 model->params->data.F32[n] = params->data.F32[i*nPar + n];526 model->dparams->data.F32[n] = dparams->data.F32[i*nPar + n];527 }528 psTrace ("psModules.objects", 4, " src %d", i);529 530 // save the resulting chisq, nDOF, nIter531 // these are not unique for any one source532 model->chisq = myMin->value;533 model->nIter = myMin->iter;534 model->nDOF = y->n - nParams;535 536 // set the model success or failure status537 model->flags |= PM_MODEL_STATUS_FITTED;538 if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE;539 540 // models can go insane: reject these541 onPic &= (model->params->data.F32[PM_PAR_XPOS] >= source->pixels->col0);542 onPic &= (model->params->data.F32[PM_PAR_XPOS] < source->pixels->col0 + source->pixels->numCols);543 onPic &= (model->params->data.F32[PM_PAR_XPOS] >= source->pixels->row0);544 onPic &= (model->params->data.F32[PM_PAR_XPOS] < source->pixels->row0 + source->pixels->numRows);545 if (!onPic) model->flags |= PM_MODEL_STATUS_OFFIMAGE;546 }547 psTrace ("psModules.objects", 4, "niter: %d, chisq: %f", myMin->iter, myMin->value);548 549 source->mode |= PM_SOURCE_MODE_FITTED;550 551 psFree(x);552 psFree(y);553 psFree(yErr);554 psFree(myMin);555 psFree(covar);556 psFree(constraint);557 psFree(params);558 psFree(dparams);559 560 // free static memory used by pmSourceFitSet561 pmSourceFitSetClear ();562 563 rc = (onPic && fitStatus);564 psTrace (__func__, 5, "onPic: %d, fitStatus: %d, nIter: %d, chisq: %f, nDof: %d\n", onPic, fitStatus, model->nIter, model->chisq, model->nDOF);565 psTrace("psModules.objects", 5, "---- %s end (%d) ----\n", __func__, rc);566 return(rc);567 }568
Note:
See TracChangeset
for help on using the changeset viewer.
