- Timestamp:
- Aug 26, 2010, 9:18:39 AM (16 years ago)
- Location:
- branches/sc_branches/trunkTest
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/sc_branches/trunkTest
- Property svn:mergeinfo changed
-
branches/sc_branches/trunkTest/psphot
- Property svn:mergeinfo deleted
-
branches/sc_branches/trunkTest/psphot/src/psphotSourceFits.c
r26894 r29060 2 2 3 3 // given a source with an existing modelPSF, attempt a full PSF fit, subtract if successful 4 // XXX this function does not call pmSourceFitModelInit : fix this?5 4 6 5 static int NfitPSF = 0; … … 8 7 static int NfitDBL = 0; 9 8 static int NfitEXT = 0; 9 static int NfitPCM = 0; 10 10 11 11 bool psphotFitInit (int nThreads) { … … 18 18 19 19 psLogMsg ("psphot.pspsf", PS_LOG_INFO, "fitted %5d psf, %5d blend, %5d ext, %5d dbl : %6.2f sec\n", 20 NfitPSF, NfitBlend, NfitEXT, NfitDBL, psTimerMark ("psphot.fits"));21 return true; 22 } 23 24 bool psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, p sImageMaskType maskVal, psImageMaskType markVal) {20 NfitPSF, NfitBlend, NfitEXT, NfitDBL, psTimerMark ("psphot.fits")); 21 return true; 22 } 23 24 bool psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) { 25 25 26 26 float x, y, dR; 27 28 pmSourceFitOptions options = *fitOptions; 27 29 28 30 // maskVal is used to test for rejected pixels, and must include markVal … … 31 33 // if this source is not a possible blend, just fit as PSF 32 34 if ((source->blends == NULL) || (source->mode & PM_SOURCE_MODE_SATSTAR)) { 33 bool status = psphotFitPSF (readout, source, psf, maskVal, markVal);35 bool status = psphotFitPSF (readout, source, psf, fitOptions, maskVal, markVal); 34 36 return status; 35 37 } … … 91 93 92 94 // fit PSF model 93 pmSourceFitSet (source, modelSet, PM_SOURCE_FIT_PSF, maskVal); 95 options.mode = PM_SOURCE_FIT_PSF; 96 pmSourceFitSet (source, modelSet, &options, maskVal); 94 97 95 98 // clear the circular mask … … 154 157 } 155 158 156 bool psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, p sImageMaskType maskVal, psImageMaskType markVal) {159 bool psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) { 157 160 158 161 double chiTrend; 162 pmSourceFitOptions options = *fitOptions; 159 163 160 164 // maskVal is used to test for rejected pixels, and must include markVal … … 171 175 172 176 // fit PSF model (set/unset the pixel mask) 173 pmSourceFitModel (source, PSF, PM_SOURCE_FIT_PSF, maskVal); 177 options.mode = PM_SOURCE_FIT_PSF; 178 pmSourceFitModel (source, PSF, &options, maskVal); 174 179 175 180 if (!isfinite(PSF->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); … … 199 204 } 200 205 206 // save a local, static copy of the EXT model type so we don't have to lookup for each object 201 207 static pmModelType modelTypeEXT; 202 208 203 bool psphotInitLimitsEXT (psMetadata *recipe ) {209 bool psphotInitLimitsEXT (psMetadata *recipe, pmReadout *readout) { 204 210 205 211 bool status; … … 208 214 char *modelNameEXT = psMetadataLookupStr (&status, recipe, "EXT_MODEL"); 209 215 modelTypeEXT = pmModelClassGetType (modelNameEXT); 210 psphotInitRadiusEXT (recipe, modelTypeEXT); 211 212 return true; 213 } 214 215 bool psphotFitBlob (pmReadout *readout, pmSource *source, psArray *newSources, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal) { 216 216 217 psphotInitRadiusEXT (recipe, readout); 218 219 return true; 220 } 221 222 bool psphotFitBlob (pmReadout *readout, pmSource *source, psArray *newSources, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) { 223 224 float radius; 217 225 bool okEXT, okDBL; 218 226 float chiEXT, chiDBL; … … 222 230 pmModel *EXT = NULL; 223 231 psArray *DBL = NULL; 232 pmMoments psfMoments; 224 233 225 234 // skip the source if we don't think it is extended 235 // XXX are these robust, or do we have better info from the source-size analysis?? 226 236 if (source->type == PM_SOURCE_TYPE_UNKNOWN) return false; 227 237 if (source->type == PM_SOURCE_TYPE_DEFECT) return false; … … 229 239 230 240 // set the radius based on the footprint (also sets the mask pixels) 231 float radius = psphotSetRadiusEXT (readout, source, markVal);241 if (!psphotSetRadiusFootprint(&radius, readout, source, markVal, 1.0)) return false; 232 242 233 243 // XXX note that this changes the source moments that are published... 244 // XXX all published moments should use the same measurement 234 245 // recalculate the source moments using the larger extended-source moments radius 235 246 // at this stage, skip Gaussian windowing, and do not clip pixels by S/N 236 247 // this uses the footprint to judge both radius and aperture? 237 if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) return false; 248 // XXX save the psf-based moments for output 249 psfMoments = *source->moments; 250 if (!pmSourceMoments (source, radius, 0.0, 0.5, maskVal)) { 251 *source->moments = psfMoments; 252 return false; 253 } 238 254 239 255 psTrace ("psphot", 5, "trying blob...\n"); … … 244 260 // this temporary source is used as a place-holder by the psphotEval functions below 245 261 tmpSrc = pmSourceAlloc (); 246 247 // XXX need to handle failures better here 248 EXT = psphotFitEXT (readout, source, modelTypeEXT, maskVal, markVal); 249 if (!EXT) goto escape; 250 if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) goto escape; 251 252 okEXT = psphotEvalEXT (tmpSrc, EXT); 253 chiEXT = EXT ? EXT->chisq / EXT->nDOF : NAN; 254 255 // DBL will always be defined, but DBL->data[n] might not 256 DBL = psphotFitDBL (readout, source, maskVal, markVal); 257 if (!DBL) goto escape; 258 if (!DBL->n) goto escape; 259 260 okDBL = psphotEvalDBL (tmpSrc, DBL->data[0]); 261 okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]); 262 // XXX should I keep / save the flags set in the eval functions? 262 { 263 // DBL will always be defined, but DBL->data[n] might not 264 DBL = psphotFitDBL (readout, source, fitOptions, maskVal, markVal); 265 if (!DBL) goto escape; 266 if (!DBL->n) goto escape; 267 268 okDBL = psphotEvalDBL (tmpSrc, DBL->data[0]); 269 okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]); 270 // XXX should I keep / save the flags set in the eval functions? 271 272 // correct first model chisqs for flux trend 273 chiDBL = NAN; 274 ONE = DBL->data[0]; 275 if (ONE) { 276 if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); 277 chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]); 278 ONE->chisqNorm = ONE->chisq / chiTrend; 279 chiDBL = ONE->chisq / ONE->nDOF; // save chisq for double-star/galaxy comparison 280 ONE->fitRadius = radius; 281 } 282 283 // correct second model chisqs for flux trend 284 ONE = DBL->data[1]; 285 if (ONE) { 286 if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); 287 chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]); 288 ONE->chisqNorm = ONE->chisq / chiTrend; 289 ONE->fitRadius = radius; 290 } 291 } 292 293 { 294 // XXX need to handle failures better here 295 EXT = psphotFitEXT (readout, source, fitOptions, modelTypeEXT, maskVal, markVal); 296 if (!EXT) goto escape; 297 if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) goto escape; 298 299 okEXT = psphotEvalEXT (tmpSrc, EXT); 300 chiEXT = EXT ? EXT->chisq / EXT->nDOF : NAN; 301 } 263 302 264 303 // clear the circular mask 265 304 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 266 267 // correct first model chisqs for flux trend268 chiDBL = NAN;269 ONE = DBL->data[0];270 if (ONE) {271 if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");272 chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);273 ONE->chisqNorm = ONE->chisq / chiTrend;274 chiDBL = ONE->chisq / ONE->nDOF; // save chisq for double-star/galaxy comparison275 }276 277 // correct second model chisqs for flux trend278 ONE = DBL->data[1];279 if (ONE) {280 if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");281 chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);282 ONE->chisqNorm = ONE->chisq / chiTrend;283 }284 305 285 306 psFree (tmpSrc); … … 298 319 299 320 // both models failed; reject them both 300 // XXX -- change type flags to psf in this case and keep original moments? 321 // XXX -- change type flags to psf in this case, and make sure we subtract it? 322 // reset the psf moments 323 *source->moments = psfMoments; 324 301 325 psFree (EXT); 302 326 psFree (DBL); … … 308 332 309 333 // save new model 334 // XXX save the correct radius... 310 335 source->modelEXT = EXT; 311 source->modelEXT->fitRadius = radius;312 336 source->type = PM_SOURCE_TYPE_EXTENDED; 313 337 source->mode |= PM_SOURCE_MODE_EXTMODEL; … … 327 351 # endif 328 352 353 // reset the psf moments 354 *source->moments = psfMoments; 329 355 return true; 330 356 … … 337 363 source->modelPSF = psMemIncrRefCounter (DBL->data[0]); 338 364 source->mode |= PM_SOURCE_MODE_PAIR; 339 source->modelPSF->fitRadius = radius;340 365 341 366 // copy most data from the primary source (modelEXT, blends stay NULL) 342 pmSource *newSrc = pmSourceCopy (source);367 pmSource *newSrc = pmSourceCopyData (source); 343 368 newSrc->modelPSF = psMemIncrRefCounter (DBL->data[1]); 344 newSrc->modelPSF->fitRadius = radius;345 369 346 370 // build cached models and subtract … … 365 389 # endif 366 390 391 // reset the (original) psf moments 392 *source->moments = psfMoments; 393 *newSrc->moments = psfMoments; 394 367 395 psArrayAdd (newSources, 100, newSrc); 368 396 psFree (newSrc); … … 371 399 372 400 escape: 401 // reset the psf moments 402 *source->moments = psfMoments; 373 403 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 374 404 psFree (tmpSrc); … … 379 409 380 410 // fit a double PSF source to an extended blob 381 psArray *psphotFitDBL (pmReadout *readout, pmSource *source, p sImageMaskType maskVal, psImageMaskType markVal) {411 psArray *psphotFitDBL (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) { 382 412 383 413 float dx, dy; … … 387 417 psEllipseMoments moments; 388 418 psArray *modelSet; 419 420 pmSourceFitOptions options = *fitOptions; 389 421 390 422 NfitDBL ++; … … 403 435 axes = psEllipseMomentsToAxes (moments, 20.0); 404 436 437 if (isnan(axes.major)) return NULL; 438 if (isnan(axes.minor)) return NULL; 439 if (isnan(axes.theta)) return NULL; 440 405 441 // XXX this is really arbitrary: 4 pixel separation? 406 442 dx = 2 * cos (axes.theta); … … 426 462 427 463 // fit PSF model (set/unset the pixel mask) 428 pmSourceFitSet (source, modelSet, PM_SOURCE_FIT_PSF, maskVal); 464 options.mode = PM_SOURCE_FIT_PSF; 465 pmSourceFitSet (source, modelSet, &options, maskVal); 429 466 return (modelSet); 430 467 } 431 468 432 pmModel *psphotFitEXT (pmReadout *readout, pmSource *source, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal) { 469 pmModel *psphotFitEXT (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal) { 470 471 if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) { 472 psTrace ("psphot", 5, "problem source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy); 473 } 474 475 pmSourceFitOptions options = *fitOptions; 433 476 434 477 NfitEXT ++; … … 438 481 439 482 // use the source moments, etc to guess basic model parameters 440 pmModel * EXT= pmSourceModelGuess (source, modelType);441 if (! EXT) {483 pmModel *model = pmSourceModelGuess (source, modelType); 484 if (!model) { 442 485 psTrace ("psphot", 5, "failed to generate a model for source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy); 443 486 return NULL; 444 487 } 445 488 489 // for sersic models, use a grid search to choose an index, then float the params there 490 if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) { 491 // for the test fits, use a somewhat smaller radius 492 psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5); 493 psphotFitSersicIndex (model, readout, source, fitOptions, maskVal, markVal); 494 } 495 496 if (!psphotSetRadiusModel (model, readout, source, markVal, true)) { 497 psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 1.0); 498 } 499 500 if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) { 501 options.mode = PM_SOURCE_FIT_NO_INDEX; 502 } else { 503 options.mode = PM_SOURCE_FIT_EXT; 504 } 505 506 // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5); 507 pmSourceFitModel (source, model, &options, maskVal); 508 // fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix); 509 510 // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0); 511 return (model); 512 } 513 514 pmModel *psphotFitPCM (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) { 515 446 516 if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) { 447 517 psTrace ("psphot", 5, "problem source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy); 448 518 } 449 519 520 pmSourceFitOptions options = *fitOptions; 521 522 NfitPCM ++; 523 524 // maskVal is used to test for rejected pixels, and must include markVal 525 maskVal |= markVal; 526 527 // allocate the model 528 pmModel *model = pmModelAlloc(modelType); 529 if (!model) { 530 return NULL; 531 } 532 533 pmPCMdata *pcm = pmPCMinit (source, &options, model, maskVal, psfSize); 534 if (!pcm) { 535 psTrace ("psphot", 5, "failed to generate a model for source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy); 536 model->flags |= PM_MODEL_STATUS_BADARGS; // XXX this is probably already set in pmPCMinit 537 return model; 538 } 539 540 // use the source moments, etc to guess basic model parameters 541 if (!pmSourceModelGuessPCM (pcm, source, maskVal, markVal)) { 542 psFree (pcm); 543 model->flags |= PM_MODEL_STATUS_BADARGS; 544 return model; 545 } 546 547 // for sersic models, use a grid search to choose an index, then float the params there 548 if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) { 549 // for the test fits, use a somewhat smaller radius 550 psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5); 551 552 if (!psphotFitSersicIndexPCM (pcm, readout, source, fitOptions, maskVal, markVal, psfSize)) { 553 model->flags |= PM_MODEL_STATUS_BADARGS; 554 return model; 555 } 556 } 557 558 if (!psphotSetRadiusModel (model, readout, source, markVal, true)) { 559 psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 1.0); 560 } 561 562 if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) { 563 options.mode = PM_SOURCE_FIT_NO_INDEX; 564 } else { 565 options.mode = PM_SOURCE_FIT_EXT; 566 } 567 // update the pcm elements if we have changed the circumstance (options.mode or source->pixels) 568 pmPCMupdate(pcm, source, &options, model); 569 570 // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5); 571 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 572 // fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix); 573 574 // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0); 575 psFree (pcm); 576 577 return model; 578 } 579 580 // note that these should be 1/2n of the standard sersic index 581 float indexGuess[] = {0.5, 0.33, 0.25, 0.167, 0.125, 0.083}; 582 # define N_INDEX_GUESS 6 583 584 // A sersic model is very sensitive to the index. attempt to find the index first by grid search in just the index 585 // for a sersic model, attempt to fit just the index and normalization with a modest number of iterations 586 bool psphotFitSersicIndex (pmModel *model, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) { 587 588 assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC")); 589 590 pmSourceFitOptions options = *fitOptions; 591 450 592 // fit EXT (not PSF) model (set/unset the pixel mask) 451 pmSourceFitModel (source, EXT, PM_SOURCE_FIT_EXT, maskVal); 452 return (EXT); 453 } 593 options.mode = PM_SOURCE_FIT_NO_INDEX; 594 options.nIter = 4; 595 596 int iMin = -1; 597 float xMin = NAN; 598 float chiSquare[N_INDEX_GUESS]; 599 600 for (int i = 0; i < N_INDEX_GUESS; i++) { 601 model->params->data.F32[PM_PAR_7] = indexGuess[i]; 602 603 if (!model->modelGuess(model, source)) { 604 model->flags |= PM_MODEL_STATUS_BADARGS; 605 return false; 606 } 607 608 // each time we change the model guess, we need to adjust the radius 609 // XXX this did not work : we do not need such a large radius -- just uses moments-based radius 610 if (false && !psphotSetRadiusModel (model, readout, source, markVal, false)) { 611 psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5); 612 } 613 614 pmSourceFitModel (source, model, &options, maskVal); 615 // fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix); 616 617 chiSquare[i] = model->chisqNorm; 618 if (i == 0) { 619 xMin = chiSquare[i]; 620 iMin = i; 621 } else { 622 if (chiSquare[i] < xMin) { 623 xMin = chiSquare[i]; 624 iMin = i; 625 } 626 } 627 } 628 assert (iMin >= 0); 629 630 model->flags = PM_MODEL_STATUS_NONE; // do not attempt to handle failures here, let the next iteration deal with it 631 model->params->data.F32[PM_PAR_7] = indexGuess[iMin]; 632 model->modelGuess(model, source); 633 634 // each time we change the model guess, we need to adjust the radius 635 // if (!psphotSetRadiusModel (model, readout, source, markVal, true)) { 636 // psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal); 637 // } 638 639 return true; 640 } 641 642 // A sersic model is very sensitive to the index. attempt to find the index first by grid search in just the index 643 // for a sersic model, attempt to fit just the index and normalization with a modest number of iterations 644 bool psphotFitSersicIndexPCM (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) { 645 646 pmModel *model = pcm->modelConv; 647 648 assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC")); 649 650 pmSourceFitOptions options = *fitOptions; 651 652 // fit EXT (not PSF) model (set/unset the pixel mask) 653 options.mode = PM_SOURCE_FIT_NO_INDEX; 654 options.nIter = 4; 655 656 // update the pcm elements if we have changed the circumstance (here, options.mode) 657 pmPCMupdate(pcm, source, &options, model); 658 659 int iMin = -1; 660 float xMin = NAN; 661 float chiSquare[N_INDEX_GUESS]; 662 663 for (int i = 0; i < N_INDEX_GUESS; i++) { 664 model->params->data.F32[PM_PAR_7] = indexGuess[i]; 665 666 if (!model->modelGuess(model, source)) { 667 model->flags |= PM_MODEL_STATUS_BADARGS; 668 return false; 669 } 670 671 // each time we change the model guess, we need to adjust the radius 672 // XXX this did not work : we do not need such a large radius -- just uses moments-based radius 673 if (false && !psphotSetRadiusModel (model, readout, source, markVal, false)) { 674 psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5); 675 } 676 677 # if (0) 678 pmSourceFitModel (source, model, &options, maskVal); 679 # else 680 pmSourceModelGuessPCM(pcm, source, maskVal, markVal); 681 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 682 # endif 683 // fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix); 684 685 chiSquare[i] = model->chisq; 686 if (i == 0) { 687 xMin = chiSquare[i]; 688 iMin = i; 689 } else { 690 if (chiSquare[i] < xMin) { 691 xMin = chiSquare[i]; 692 iMin = i; 693 } 694 } 695 } 696 assert (iMin >= 0); 697 698 model->flags = PM_MODEL_STATUS_NONE; // do not attempt to handle failures here, let the next iteration deal with it 699 model->params->data.F32[PM_PAR_7] = indexGuess[iMin]; 700 701 pmSourceModelGuessPCM(pcm, source, maskVal, markVal); 702 703 return true; 704 }
Note:
See TracChangeset
for help on using the changeset viewer.
