Changeset 4630 for trunk/psphot/src/LocalSky.c
- Timestamp:
- Jul 27, 2005, 3:26:57 PM (21 years ago)
- File:
-
- 1 edited
-
trunk/psphot/src/LocalSky.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src/LocalSky.c
r4582 r4630 62 62 bool pmSourceFitModel_EAM(psSource *source, 63 63 psModel *model, 64 const bool PSF, 65 float SOFT) 64 const bool PSF) 66 65 { 67 66 PS_PTR_CHECK_NULL(source, false); … … 74 73 psBool onPic = true; 75 74 psBool rc = true; 76 psF32 Ro ;75 psF32 Ro, ymodel; 77 76 78 77 … … 81 80 82 81 psModelFunc modelFunc = psModelFunc_GetFunction (model->type); 82 psModelLimits modelLimits = psModelLimits_GetFunction (model->type); 83 83 84 84 psVector *params = model->params; … … 86 86 psVector *paramMask = NULL; 87 87 88 psVector *beta_lim = NULL; 89 psVector *params_min = NULL; 90 psVector *params_max = NULL; 91 88 92 int nParams = PSF ? params->n - 4 : params->n; 89 psF32 Xo = params->data.F32[2]; 90 psF32 Yo = params->data.F32[3]; 93 psF32 So = params->data.F32[0]; 91 94 92 95 // find the number of valid pixels … … 122 125 y->data.F32[tmpCnt] = source->pixels->data.F32[i][j]; 123 126 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))); 127 ymodel = modelFunc (NULL, model->params, coord); 128 129 // this test enhances the noise based on deviation from the model flux 130 Ro = 1.0 + fabs (y->data.F32[tmpCnt] - ymodel) / sqrt(PS_SQR(ymodel - So) + PS_SQR(So)); 131 yErr->data.F32[tmpCnt] = sqrt (source->noise->data.F32[i][j] * Ro); 130 132 // XXX EAM : note the wasted effort: we carry dY^2, take sqrt(), then 131 133 // the minimization function calculates sq() … … 147 149 paramMask->data.U8[i] = 1; 148 150 } 149 } 150 151 psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F64); 151 } 152 153 psImage *covar = psImageAlloc (params->n, 3, PS_TYPE_F64); 154 modelLimits (&beta_lim, ¶ms_min, ¶ms_max); 155 for (int i = 0; i < params->n; i++) { 156 covar->data.F64[0][i] = beta_lim->data.F32[i]; 157 covar->data.F64[1][i] = params_min->data.F32[i]; 158 covar->data.F64[2][i] = params_max->data.F32[i]; 159 } 152 160 153 161 psTrace (".pmObjects.pmSourceFitModel", 5, "fitting function\n"); 154 fitStatus = psMinimizeLMChi2 (myMin, covar, params, paramMask, x, y, yErr, modelFunc);162 fitStatus = psMinimizeLMChi2_EAM(myMin, covar, params, paramMask, x, y, yErr, modelFunc); 155 163 for (int i = 0; i < dparams->n; i++) { 156 164 if ((paramMask != NULL) && paramMask->data.U8[i]) continue; … … 326 334 } 327 335 336 bool pmModelFitStatus (psModel *model) { 337 338 bool status; 339 340 psModelFitStatusFunc statusFunc = psModelFitStatusFunc_GetFunction (model->type); 341 status = statusFunc (model); 342 343 return (status); 344 } 345 346 // XXX EAM this implementation of MinLM includes limits on params & dparams 347 psBool psMinimizeLMChi2_EAM(psMinimization *min, 348 psImage *covar, 349 psVector *params, 350 const psVector *paramMask, 351 const psArray *x, 352 const psVector *y, 353 const psVector *yErr, 354 psMinimizeLMChi2Func func) 355 { 356 PS_PTR_CHECK_NULL(min, NULL); 357 PS_VECTOR_CHECK_NULL(params, NULL); 358 PS_VECTOR_CHECK_EMPTY(params, NULL); 359 PS_PTR_CHECK_NULL(x, NULL); 360 PS_VECTOR_CHECK_NULL(y, NULL); 361 PS_VECTOR_CHECK_EMPTY(y, NULL); 362 PS_VECTOR_CHECK_SIZE_EQUAL(x, y, NULL); 363 PS_PTR_CHECK_NULL(func, NULL); 364 365 // this function has test and current values for several things 366 // the current best value is in lower case 367 // the next guess value is in upper case 368 369 // allocate internal arrays (current vs Guess) 370 psImage *alpha = psImageAlloc (params->n, params->n, PS_TYPE_F64); 371 psImage *Alpha = psImageAlloc (params->n, params->n, PS_TYPE_F64); 372 psVector *beta = psVectorAlloc (params->n, PS_TYPE_F64); 373 psVector *Beta = psVectorAlloc (params->n, PS_TYPE_F64); 374 psVector *Params = psVectorAlloc (params->n, PS_TYPE_F32); 375 psVector *dy = NULL; 376 psF64 Chisq = 0.0; 377 psF64 lambda = 0.001; 378 379 psVector *beta_lim = NULL; 380 psVector *param_min = NULL; 381 psVector *param_max = NULL; 382 383 // if we are provided a covar image, we expect to find these three vectors in first three rows 384 if (covar != NULL) { 385 beta_lim = psVectorAlloc (params->n, PS_TYPE_F32); 386 param_min = psVectorAlloc (params->n, PS_TYPE_F32); 387 param_max = psVectorAlloc (params->n, PS_TYPE_F32); 388 for (int i = 0; i < params->n; i++) { 389 beta_lim->data.F32[i] = covar->data.F64[0][i]; 390 param_min->data.F32[i] = covar->data.F64[1][i]; 391 param_max->data.F32[i] = covar->data.F64[2][i]; 392 } 393 psImageRecycle (covar, params->n, params->n, PS_TYPE_F64); 394 } 395 396 397 // why is this needed here??? the initial guess on params is provided by the user 398 Params = psVectorCopy (Params, params, PS_TYPE_F32); 399 400 // the user provides the error or NULL. we need to convert 401 // to appropriate weights 402 dy = psVectorAlloc (y->n, PS_TYPE_F32); 403 if (yErr != NULL) { 404 for (int i = 0; i < dy->n; i++) { 405 if (yErr->data.F32[i] == 0.0) { 406 dy->data.F32[i] = 1.0; 407 // mask this? bad pixel, obviously... 408 } else { 409 dy->data.F32[i] = 1.0 / PS_SQR (yErr->data.F32[i]); 410 } 411 } 412 } else { 413 for (int i = 0; i < dy->n; i++) { 414 dy->data.F32[i] = 1.0; 415 } 416 } 417 418 // calculate initial alpha and beta, set chisq (min->value) 419 min->value = p_psMinLM_SetABX (alpha, beta, params, paramMask, x, y, dy, func); 420 if (isnan(min->value)) { 421 min->iter = min->maxIter; 422 return (false); 423 } 424 # ifndef PS_NO_TRACE 425 // dump some useful info if trace is defined 426 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) { 427 p_psImagePrint (psTraceGetDestination(), alpha, "alpha guess"); 428 p_psVectorPrint (psTraceGetDestination(), beta, "beta guess"); 429 p_psVectorPrint (psTraceGetDestination(), params, "params guess"); 430 } 431 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") == 4) { 432 p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess"); 433 } 434 # endif /* PS_NO_TRACE */ 435 436 // iterate until the tolerance is reached, or give up 437 while ((min->lastDelta > min->tol) && (min->iter < min->maxIter)) { 438 439 // set a new guess for Alpha, Beta, Params 440 p_psMinLM_GuessABP_EAM (Alpha, Beta, Params, alpha, beta, params, paramMask, beta_lim, param_min, param_max, lambda); 441 442 // measure linear model prediction 443 psF64 dLinear = p_psMinLM_dLinear (Beta, beta, lambda); 444 445 # ifndef PS_NO_TRACE 446 // dump some useful info if trace is defined 447 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) { 448 p_psImagePrint (psTraceGetDestination(), Alpha, "alpha guess"); 449 p_psVectorPrint (psTraceGetDestination(), Beta, "beta guess"); 450 p_psVectorPrint (psTraceGetDestination(), Params, "params guess"); 451 } 452 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") == 4) { 453 p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess"); 454 } 455 # endif /* PS_NO_TRACE */ 456 457 // calculate Chisq for new guess, update Alpha & Beta 458 Chisq = p_psMinLM_SetABX (Alpha, Beta, Params, paramMask, x, y, dy, func); 459 460 // XXX EAM alternate convergence criterion: 461 // compare the delta (min->value - Chisq) with the 462 // expected delta from the linear model (dLinear) 463 // accept new guess (if improvement), or increase lambda 464 psF64 rho = (min->value - Chisq) / dLinear; 465 466 psTrace (".psLib.dataManip.psMinimizeLMChi2", 4, "last chisq: %f, new chisq %f, delta: %f, rho: %f\n", min->value, Chisq, min->lastDelta, rho); 467 # ifndef PS_NO_TRACE 468 // dump some useful info if trace is defined 469 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) { 470 p_psImagePrint (psTraceGetDestination(), Alpha, "alpha guess"); 471 p_psVectorPrint (psTraceGetDestination(), Beta, "beta guess"); 472 p_psVectorPrint (psTraceGetDestination(), Params, "params guess"); 473 } 474 # endif /* PS_NO_TRACE */ 475 476 /* if (Chisq < min->value) { */ 477 if (rho > 0.0) { 478 min->lastDelta = (min->value - Chisq) / (dy->n - params->n); 479 min->value = Chisq; 480 alpha = psImageCopy (alpha, Alpha, PS_TYPE_F64); 481 beta = psVectorCopy (beta, Beta, PS_TYPE_F64); 482 params = psVectorCopy (params, Params, PS_TYPE_F32); 483 lambda *= 0.1; 484 } else { 485 lambda *= 10.0; 486 } 487 min->iter ++; 488 } 489 psTrace (".psLib.dataManip.psMinimizeLMChi2", 3, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter); 490 491 // construct & return the covariance matrix (if requested) 492 if (covar != NULL) { 493 p_psMinLM_GuessABP_EAM (covar, Beta, Params, alpha, beta, params, paramMask, beta_lim, param_min, param_max, 0.0); 494 } 495 496 // free the internal temporary data 497 psFree (alpha); 498 psFree (Alpha); 499 psFree (beta); 500 psFree (Beta); 501 psFree (Params); 502 psFree (dy); 503 504 if (min->iter == min->maxIter) { 505 return (false); 506 } 507 return (true); 508 } 509 510 // XXX EAM : can we use static copies of LUv, LUm, A? 511 psBool p_psMinLM_GuessABP_EAM (psImage *Alpha, 512 psVector *Beta, 513 psVector *Params, 514 const psImage *alpha, 515 const psVector *beta, 516 const psVector *params, 517 const psVector *paramMask, 518 const psVector *beta_lim, 519 const psVector *params_min, 520 const psVector *params_max, 521 psF64 lambda) 522 { 523 524 # define USE_LU_DECOMP 1 525 # if (USE_LU_DECOMP) 526 psVector *LUv = NULL; 527 psImage *LUm = NULL; 528 psImage *A = NULL; 529 psF32 det; 530 531 // LU decomposition version 532 psTrace (".psLib.dataManip.psMinLM_GuessABP", 5, "using LUD version\n"); 533 534 // set new guess values (creates matrix A) 535 A = psImageCopy (NULL, alpha, PS_TYPE_F64); 536 for (int j = 0; j < params->n; j++) { 537 if ((paramMask != NULL) && (paramMask->data.U8[j])) continue; 538 A->data.F64[j][j] = alpha->data.F64[j][j] * (1.0 + lambda); 539 } 540 541 // solve A*beta = Beta (Alpha = 1/A) 542 // these operations do not modify the input values (creates LUm, LUv) 543 LUm = psMatrixLUD (NULL, &LUv, A); 544 Beta = psMatrixLUSolve (Beta, LUm, beta, LUv); 545 Alpha = psMatrixInvert (Alpha, A, &det); 546 547 # else 548 // gauss-jordan version 549 psTrace (".psLib.dataManip.psMinLM_GuessABP", 5, "using Gauss-J version"); 550 551 // set new guess values (creates matrix A) 552 Beta = psVectorCopy (Beta, beta, PS_TYPE_F64); 553 Alpha = psImageCopy (Alpha, alpha, PS_TYPE_F64); 554 for (int j = 0; j < params->n; j++) { 555 if ((paramMask != NULL) && (paramMask->data.U8[j])) continue; 556 Alpha->data.F64[j][j] = alpha->data.F64[j][j] * (1.0 + lambda); 557 } 558 559 psGaussJordan (Alpha, Beta); 560 # endif 561 562 // apply Beta to get new Params values 563 for (int j = 0; j < params->n; j++) { 564 if ((paramMask != NULL) && (paramMask->data.U8[j])) continue; 565 // Params->data.F32[j] = params->data.F32[j] - Beta->data.F64[j]; 566 // continue; 567 // compare Beta to beta limits 568 if (beta_lim != NULL) { 569 if (fabs(Beta->data.F64[j]) > fabs(beta_lim->data.F32[j])) { 570 Beta->data.F64[j] = (Beta->data.F64[j] > 0) ? fabs(beta_lim->data.F32[j]) : -fabs(beta_lim->data.F32[j]); 571 } 572 } 573 Params->data.F32[j] = params->data.F32[j] - Beta->data.F64[j]; 574 // compare new params to param limits 575 if (params_max != NULL) { 576 Params->data.F32[j] = PS_MIN (Params->data.F32[j], params_max->data.F32[j]); 577 } 578 if (params_min != NULL) { 579 Params->data.F32[j] = PS_MAX (Params->data.F32[j], params_min->data.F32[j]); 580 } 581 } 582 583 # if (USE_LU_DECOMP) 584 psFree (A); 585 psFree (LUm); 586 psFree (LUv); 587 # endif 588 589 return true; 590 } 591
Note:
See TracChangeset
for help on using the changeset viewer.
