Changeset 15002
- Timestamp:
- Sep 24, 2007, 6:17:29 PM (19 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/objects/pmPSFtry.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/objects/pmPSFtry.c
r15000 r15002 5 5 * @author EAM, IfA 6 6 * 7 * @version $Revision: 1.4 6$ $Name: not supported by cvs2svn $8 * @date $Date: 2007-09-2 4 21:27:58$7 * @version $Revision: 1.47 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2007-09-25 04:17:29 $ 9 9 * 10 10 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 35 35 #include "pmSourcePhotometry.h" 36 36 37 int testSaveImage (psMetadata *header, psImage *image, char *filename) { 38 39 psFits *fits = psFitsOpen (filename, "w"); 40 psFitsWriteImage (fits, NULL, image, 0, NULL); 41 psFitsClose (fits); 42 return (TRUE); 43 } 44 45 bool pmPSFParamTrend (pmPSF *psf, int scale, float *errorFloor, float *errorTotal, psVector *mask, psVector *x, psVector *y, psVector *e0, psVector *e1, psVector *e2, psVector *dz); 46 bool pmPSFErrorFloor (float *errorFloor, psVector *dMag, psVector *e0res, psVector *e1res, psVector *e2res, psVector *mask, int nGroup); 47 37 48 // ******** pmPSFtry functions ************************************************** 38 49 // * pmPSFtry holds a single pmPSF model test, with the input sources, the freely … … 172 183 if (!status) { 173 184 psfTry->mask->data.U8[i] = PSFTRY_MASK_PSF_FAIL; 174 psTrace ("psModules. pmPSFtry", 4, "dropping %d (%d,%d) : failed PSF fit\n", i, source->peak->x, source->peak->y);185 psTrace ("psModules.objects", 4, "dropping %d (%d,%d) : failed PSF fit\n", i, source->peak->x, source->peak->y); 175 186 continue; 176 187 } … … 179 190 if (!pmSourceMagnitudes (source, psfTry->psf, PM_SOURCE_PHOT_INTERP, maskVal, mark)) { 180 191 psfTry->mask->data.U8[i] = PSFTRY_MASK_BAD_PHOT; 181 psTrace ("psModules. pmPSFtry", 4, "dropping %d (%d,%d) : poor photometry\n", i, source->peak->x, source->peak->y);192 psTrace ("psModules.objects", 4, "dropping %d (%d,%d) : poor photometry\n", i, source->peak->x, source->peak->y); 182 193 continue; 183 194 } … … 352 363 psVector *y = psVectorAlloc (psfTry->sources->n, PS_TYPE_F32); 353 364 psVector *z = psVectorAlloc (psfTry->sources->n, PS_TYPE_F32); 365 psVector *flux = psVectorAlloc (psfTry->sources->n, PS_TYPE_F32); 354 366 355 367 psVector *dz = NULL; … … 366 378 x->data.F32[i] = source->modelEXT->params->data.F32[PM_PAR_XPOS]; 367 379 y->data.F32[i] = source->modelEXT->params->data.F32[PM_PAR_YPOS]; 380 flux->data.F32[i] = source->modelEXT->params->data.F32[PM_PAR_I0]; 368 381 369 382 // weight by the error on the source flux 370 383 if (dz) { 371 dz->data.F32[i] = source->modelEXT->dparams->data.F32[PM_PAR_I0]; 384 // dz->data.F32[i] = source->modelEXT->dparams->data.F32[PM_PAR_I0] / source->modelEXT->params->data.F32[PM_PAR_I0]; 385 dz->data.F32[i] = 1.0; 372 386 } 373 387 } … … 386 400 // threshold. 387 401 388 // XXX this function needs to check the fit residuals and modify Nx,Ny as needed389 390 402 // convert the measured source shape paramters to polarization terms 391 403 psVector *e0 = psVectorAlloc (psfTry->sources->n, PS_TYPE_F32); … … 403 415 } 404 416 405 // we run 'clipIter' cycles clipping in each of x and y, with only one iteration each. 406 // This way, the parameters masked by one of the fits will be applied to the others 407 for (int i = 0; i < psf->psfTrendStats->clipIter; i++) { 408 409 // XXX we are using the same stats structure on each pass: do we need to re-init it? 410 pmTrend2DFit (psf->params->data[PM_PAR_E0], psfTry->mask, 0xff, x, y, e0, dz); 411 psTrace ("psModules.pmPSFtry", 4, "clipped E0 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e0->n); 412 pmTrend2DFit (psf->params->data[PM_PAR_E1], psfTry->mask, 0xff, x, y, e1, dz); 413 psTrace ("psModules.pmPSFtry", 4, "clipped E1 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e1->n); 414 pmTrend2DFit (psf->params->data[PM_PAR_E2], psfTry->mask, 0xff, x, y, e2, dz); 415 psTrace ("psModules.pmPSFtry", 4, "clipped E2 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e2->n); 417 pmTrend2D *trend = psf->params->data[PM_PAR_E0]; 418 if (trend->mode == PM_TREND_MAP) { 419 float errorFloor = 0.0; 420 float errorTotal = 0.0; 421 float errorTotalMin = FLT_MAX; 422 int entryMin = -1; 423 424 // XXX do I need to store the initial value of psfTry->mask and reset? 425 426 // check the fit residuals and increase Nx,Ny until the error is minimized 427 for (int i = 1; i < 10; i++) { 428 429 if (!pmPSFParamTrend (psf, i, &errorFloor, &errorTotal, psfTry->mask, x, y, e0, e1, e2, dz)) { 430 break; 431 } 432 433 // we do not have a good model for the error distributions on e0, e1, e2. 434 // use the bright end scatter from the constant fit to set the scale for the 435 // versions with 2D variation 436 if (i == 1) { 437 for (int i = 0; i < psfTry->sources->n; i++) { 438 if (dz) { 439 dz->data.F32[i] = errorFloor; 440 } 441 } 442 } 443 444 // store the resulting errorTotal values and the scales, redo the best 445 if (errorTotal < errorTotalMin) { 446 errorTotalMin = errorTotal; 447 entryMin = i; 448 } 449 } 450 if (entryMin == -1) { 451 psAbort ("failed on ApResid Trend"); 452 } 453 454 // XXX catch error condition 455 pmPSFParamTrend (psf, entryMin, &errorFloor, &errorTotal, psfTry->mask, x, y, e0, e1, e2, dz); 456 } else { 457 // we run 'clipIter' cycles clipping in each of x and y, with only one iteration each. 458 // This way, the parameters masked by one of the fits will be applied to the others 459 for (int i = 0; i < psf->psfTrendStats->clipIter; i++) { 460 461 // XXX we are using the same stats structure on each pass: do we need to re-init it? 462 pmTrend2DFit (psf->params->data[PM_PAR_E0], psfTry->mask, 0xff, x, y, e0, dz); 463 psTrace ("psModules.pmPSFtry", 4, "clipped E0 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e0->n); 464 pmTrend2DFit (psf->params->data[PM_PAR_E1], psfTry->mask, 0xff, x, y, e1, dz); 465 psTrace ("psModules.pmPSFtry", 4, "clipped E1 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e1->n); 466 pmTrend2DFit (psf->params->data[PM_PAR_E2], psfTry->mask, 0xff, x, y, e2, dz); 467 psTrace ("psModules.pmPSFtry", 4, "clipped E2 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e2->n); 468 } 416 469 } 417 470 … … 421 474 fprintf (f, "# x y : e0obs e1obs e2obs : e0fit e1fit e2fit : mask\n"); 422 475 for (int i = 0; i < e0->n; i++) { 423 fprintf (f, "%f %f : %f %f %f : %f %f %f : %d\n",424 x->data.F32[i], y->data.F32[i], 476 fprintf (f, "%f %f %f : %f %f %f : %f %f %f : %d\n", 477 x->data.F32[i], y->data.F32[i], flux->data.F32[i], 425 478 e0->data.F32[i], e1->data.F32[i], e2->data.F32[i], 426 479 pmTrend2DEval (psf->params->data[PM_PAR_E0], x->data.F32[i], y->data.F32[i]), … … 437 490 438 491 // skip the unfitted parameters (X, Y, Io, Sky) and the shape parameters (SXX, SYY, SXY) 492 // XXX apply the values of Nx, Ny determined above for E0,E1,E2 to the remaining parameters 439 493 for (int i = 0; i < psf->params->n; i++) { 440 494 switch (i) { … … 459 513 } 460 514 515 pmTrend2D *trendE0 = psf->params->data[PM_PAR_E0]; 516 517 // re-create the pmTrend2D using the scales defined for E0 518 psImageBinning *binning = psImageBinningAlloc(); 519 if (trendE0->mode == PM_TREND_MAP) { 520 binning->nXruff = trend->map->map->numCols; 521 binning->nYruff = trend->map->map->numRows; 522 } else { 523 binning->nXruff = trend->poly->nX; 524 binning->nYruff = trend->poly->nY; 525 } 526 binning->nXfine = psf->fieldNx; 527 binning->nYfine = psf->fieldNy; 528 psImageBinningSetScale (binning, PS_IMAGE_BINNING_CENTER); 529 psImageBinningSetSkipByOffset (binning, psf->fieldXo, psf->fieldYo); 530 531 psFree (psf->params->data[i]); 532 psf->params->data[i] = pmTrend2DNoImageAlloc (trendE0->mode, binning, psf->psfTrendStats); 533 psFree (binning); 534 461 535 // fit the collection of measured parameters to the PSF 2D model 462 536 // the mask is carried from previous steps and updated with this operation 463 537 // the weight is either the flux error or NULL, depending on 'psf->poissonErrorParams' 464 if (!pmTrend2DFit (psf->params->data[i], psfTry->mask, 0xff, x, y, e0, NULL)) {538 if (!pmTrend2DFit (psf->params->data[i], psfTry->mask, 0xff, x, y, z, NULL)) { 465 539 psError(PS_ERR_UNKNOWN, false, "failed to build psf model for parameter %d", i); 466 540 psFree(x); … … 504 578 psFree (z); 505 579 psFree (dz); 580 psFree (flux); 506 581 return true; 507 582 } 508 583 584 // XXX this function only works for MAP type -- extend to poly... 585 bool pmPSFParamTrend (pmPSF *psf, int scale, float *errorFloor, float *errorTotal, psVector *mask, psVector *x, psVector *y, psVector *e0obs, psVector *e1obs, psVector *e2obs, psVector *dz) { 586 587 int Nx, Ny; 588 589 // set the map scale to match the aspect ratio 590 if (psf->fieldNx > psf->fieldNy) { 591 Nx = scale; 592 Ny = PS_MAX (1, Nx * (psf->fieldNy / psf->fieldNx)); 593 } else { 594 Ny = scale; 595 Nx = PS_MAX (1, Ny * (psf->fieldNx / psf->fieldNy)); 596 } 597 598 // do we have enough sources for this fine of a grid? 599 if (x->n < 3*Nx*Ny) { 600 return false; 601 } 602 603 // the mask marks the values not used to calculate the ApTrend 604 psVectorInit (mask, 0); 605 606 // XXX check this against the exising type 607 pmTrend2DMode psfTrendMode = PM_TREND_MAP; 608 609 psImageBinning *binning = psImageBinningAlloc(); 610 binning->nXruff = Nx; 611 binning->nYruff = Ny; 612 binning->nXfine = psf->fieldNx; 613 binning->nYfine = psf->fieldNy; 614 psImageBinningSetScale (binning, PS_IMAGE_BINNING_CENTER); 615 psImageBinningSetSkipByOffset (binning, psf->fieldXo, psf->fieldYo); 616 617 psFree (psf->params->data[PM_PAR_E0]); 618 psFree (psf->params->data[PM_PAR_E1]); 619 psFree (psf->params->data[PM_PAR_E2]); 620 621 int nIter = psf->psfTrendStats->clipIter; 622 psf->psfTrendStats->clipIter = 1; 623 psf->params->data[PM_PAR_E0] = pmTrend2DNoImageAlloc (psfTrendMode, binning, psf->psfTrendStats); 624 psf->params->data[PM_PAR_E1] = pmTrend2DNoImageAlloc (psfTrendMode, binning, psf->psfTrendStats); 625 psf->params->data[PM_PAR_E2] = pmTrend2DNoImageAlloc (psfTrendMode, binning, psf->psfTrendStats); 626 psFree (binning); 627 628 // we run 'clipIter' cycles clipping in each of x and y, with only one iteration each. 629 // This way, the parameters masked by one of the fits will be applied to the others 630 for (int i = 0; i < nIter; i++) { 631 // XXX we are using the same stats structure on each pass: do we need to re-init it? 632 pmTrend2DFit (psf->params->data[PM_PAR_E0], mask, 0xff, x, y, e0obs, dz); 633 psTrace ("psModules.objects", 5, "clipped E0 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e0obs->n); 634 pmTrend2DFit (psf->params->data[PM_PAR_E1], mask, 0xff, x, y, e1obs, dz); 635 psTrace ("psModules.objects", 5, "clipped E1 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e1obs->n); 636 pmTrend2DFit (psf->params->data[PM_PAR_E2], mask, 0xff, x, y, e2obs, dz); 637 psTrace ("psModules.objects", 5, "clipped E2 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e2obs->n); 638 } 639 psf->psfTrendStats->clipIter = nIter; // restore default setting 640 641 # if (0) 642 pmTrend2D *trend; 643 trend = psf->params->data[PM_PAR_E0]; 644 testSaveImage (NULL, trend->map->map, "e0.fits"); 645 testSaveImage (NULL, trend->map->error, "e0d.fits"); 646 trend = psf->params->data[PM_PAR_E1]; 647 testSaveImage (NULL, trend->map->map, "e1.fits"); 648 testSaveImage (NULL, trend->map->error, "e1d.fits"); 649 trend = psf->params->data[PM_PAR_E2]; 650 testSaveImage (NULL, trend->map->map, "e2.fits"); 651 testSaveImage (NULL, trend->map->error, "e2d.fits"); 652 # endif 653 654 // construct the fitted values and the residuals 655 psVector *e0fit = pmTrend2DEvalVector (psf->params->data[PM_PAR_E0], x, y); 656 psVector *e1fit = pmTrend2DEvalVector (psf->params->data[PM_PAR_E1], x, y); 657 psVector *e2fit = pmTrend2DEvalVector (psf->params->data[PM_PAR_E2], x, y); 658 659 psVector *e0res = (psVector *) psBinaryOp (NULL, (void *) e0obs, "-", (void *) e0fit); 660 psVector *e1res = (psVector *) psBinaryOp (NULL, (void *) e1obs, "-", (void *) e1fit); 661 psVector *e2res = (psVector *) psBinaryOp (NULL, (void *) e2obs, "-", (void *) e2fit); 662 663 // measure errors on the map pixels 664 pmTrend2D *trend; 665 666 trend = psf->params->data[PM_PAR_E0]; 667 float mapErrorSum = 0.0; 668 float mapError = 0.0; 669 for (int iy = 0; iy < trend->map->error->numRows; iy++) { 670 for (int ix = 0; ix < trend->map->error->numCols; ix++) { 671 mapError += PS_SQR (trend->map->error->data.F32[iy][ix]); 672 } 673 } 674 psTrace ("psModules.objects", 4, "E0 error: %f\n", sqrt(mapError)); 675 mapErrorSum += mapError; 676 677 trend = psf->params->data[PM_PAR_E1]; 678 mapError = 0.0; 679 for (int iy = 0; iy < trend->map->error->numRows; iy++) { 680 for (int ix = 0; ix < trend->map->error->numCols; ix++) { 681 mapError += PS_SQR (trend->map->error->data.F32[iy][ix]); 682 } 683 } 684 psTrace ("psModules.objects", 4, "E1 error: %f\n", sqrt(mapError)); 685 mapErrorSum += mapError; 686 687 trend = psf->params->data[PM_PAR_E2]; 688 mapError = 0.0; 689 for (int iy = 0; iy < trend->map->error->numRows; iy++) { 690 for (int ix = 0; ix < trend->map->error->numCols; ix++) { 691 mapError += PS_SQR (trend->map->error->data.F32[iy][ix]); 692 } 693 } 694 psTrace ("psModules.objects", 4, "E2 error: %f\n", sqrt(mapError)); 695 mapErrorSum += mapError; 696 697 psTrace ("psModules.objects", PS_LOG_INFO, "total map error: %f\n", sqrt(mapErrorSum)); 698 699 // measure systematic errorFloor & systematic / photon scale factor 700 // XXX this is a bit arbitrary, but it forces ~3 stars from the bright bin per spatial bin 701 int nGroup = PS_MAX (3*Nx*Ny, 10); 702 pmPSFErrorFloor (errorFloor, dz, e0res, e1res, e2res, mask, nGroup); 703 704 *errorTotal = sqrt(PS_SQR(*errorFloor) + mapErrorSum); 705 706 psLogMsg ("psphot.psftry", PS_LOG_INFO, "result of %d x %d grid (%d stars per bin)\n", Nx, Ny, nGroup); 707 psLogMsg ("psphot.psftry", PS_LOG_INFO, "systematic scatter floor: %f, error map total: %f\n", *errorFloor, *errorTotal); 708 709 psFree (e0fit); 710 psFree (e1fit); 711 psFree (e2fit); 712 713 psFree (e0res); 714 psFree (e1res); 715 psFree (e2res); 716 717 return true; 718 } 719 720 bool pmPSFErrorFloor (float *errorFloor, psVector *dMag, psVector *e0res, psVector *e1res, psVector *e2res, psVector *mask, int nGroup) { 721 722 psStats *statsS = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); 723 724 // measure the trend in bins with 10 values each; if < 10 total, use them all 725 int nBin = PS_MAX (dMag->n / nGroup, 1); 726 727 // output vectors for ApResid trend 728 psVector *dSo = psVectorAlloc (nBin, PS_TYPE_F32); 729 730 // use dMag to group the dMag and dap vectors 731 psVector *index = psVectorSortIndex (NULL, dMag); 732 733 // subset vectors for dMag and dap values within the given range 734 psVector *dE0subset = psVectorAllocEmpty (nGroup, PS_TYPE_F32); 735 psVector *dE1subset = psVectorAllocEmpty (nGroup, PS_TYPE_F32); 736 psVector *dE2subset = psVectorAllocEmpty (nGroup, PS_TYPE_F32); 737 psVector *mkSubset = psVectorAllocEmpty (nGroup, PS_TYPE_U8); 738 739 int n = 0; 740 for (int i = 0; i < dSo->n; i++) { 741 int j; 742 for (j = 0; (j < nGroup) && (n < dMag->n); j++, n++) { 743 int N = index->data.U32[n]; 744 dE0subset->data.F32[j] = e0res->data.F32[N]; 745 dE1subset->data.F32[j] = e1res->data.F32[N]; 746 dE2subset->data.F32[j] = e2res->data.F32[N]; 747 748 mkSubset->data.U8[j] = mask->data.U8[N]; 749 } 750 dE0subset->n = j; 751 dE1subset->n = j; 752 dE2subset->n = j; 753 mkSubset->n = j; 754 755 // calculate the root-mean-square of E0, E1, E2 756 float dEsquare = 0.0; 757 psStatsInit (statsS); 758 psVectorStats (statsS, dE0subset, NULL, mkSubset, 0xff); 759 dEsquare += PS_SQR(statsS->robustStdev); 760 761 psStatsInit (statsS); 762 psVectorStats (statsS, dE1subset, NULL, mkSubset, 0xff); 763 dEsquare += PS_SQR(statsS->robustStdev); 764 765 psStatsInit (statsS); 766 psVectorStats (statsS, dE2subset, NULL, mkSubset, 0xff); 767 dEsquare += PS_SQR(statsS->robustStdev); 768 769 dSo->data.F32[i] = sqrt(dEsquare); 770 } 771 psFree (dE0subset); 772 psFree (dE1subset); 773 psFree (dE2subset); 774 psFree (mkSubset); 775 776 psStats *stats = psStatsAlloc (PS_STAT_MIN); 777 psVectorStats (stats, dSo, NULL, NULL, 0); 778 779 *errorFloor = stats->min; 780 781 psFree (stats); 782 psFree (index); 783 784 psFree (dSo); 785 786 psFree (statsS); 787 788 return true; 789 }
Note:
See TracChangeset
for help on using the changeset viewer.
