- Timestamp:
- Jul 17, 2014, 12:30:45 PM (12 years ago)
- Location:
- branches/eam_branches/ipp-ops-20130712/psphot
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-ops-20130712/psphot
- Property svn:mergeinfo deleted
-
branches/eam_branches/ipp-ops-20130712/psphot/src
- Property svn:ignore
-
old new 24 24 psphotModelTest 25 25 psphotMinimal 26 psphotFullForce 27 psmakecff 28 psphotFullForceSummary
-
- Property svn:mergeinfo deleted
- Property svn:ignore
-
branches/eam_branches/ipp-ops-20130712/psphot/src/psphotSourceFits.c
r35769 r37066 19 19 static int NfitIterPCM = 0; 20 20 static int NfitPixPCM = 0; 21 22 bool psphotPCMfitCheckSize (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, float psfSize); 23 bool psphotPCMfitRetry (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, float psfSize); 21 24 22 25 bool psphotFitInit (int nThreads) { … … 559 562 560 563 # define TIMING 0 564 # define EXTRA_VERBOSE 0 565 566 bool psphotSersicModelGuessPCM (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, float psfSize); 567 bool psphotFitSersicShapeAndIndex (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize); 568 bool psphotFitSersicShapeAndIndexGrid (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize); 569 bool psphotFitSersicShapeAndIndexGridAuto (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize); 561 570 562 571 pmModel *psphotFitPCM (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) { … … 573 582 maskVal |= markVal; 574 583 575 // allocate the model 584 // allocate the model (this can only fail on a config error) 576 585 pmModel *model = pmModelAlloc(modelType); 577 if (!model) { 578 return NULL; 579 } 580 581 float t1, t2, t4, t5; 586 psAssert (model, "invalid extended model name"); 587 588 float t1, t2, t3, t4, t5; 589 t1 = t2 = t3 = t4 = t5 = 0.0; 582 590 if (TIMING) { psTimerStart ("psphotFitPCM"); } 591 592 // if we are ever (in a given psphot implementation) going to fit a parameter, we must set the options here to include 593 // that parameter (otherwise pmPCMupdate will fail to allocate the dmodelFlux image) 594 // thus, if the sersic analysis below uses an index fit, need to use this EXT_AND_SKY mode for init 595 596 options.mode = PM_SOURCE_FIT_EXT; 597 if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) { 598 options.mode = PM_SOURCE_FIT_EXT_AND_SKY; 599 } 600 if (modelType == pmModelClassGetType("PS_MODEL_DEV")) { 601 options.mode = PM_SOURCE_FIT_SHAPE; 602 options.mode = PM_SOURCE_FIT_EXT_AND_SKY; 603 } 604 if (modelType == pmModelClassGetType("PS_MODEL_EXP")) { 605 options.mode = PM_SOURCE_FIT_EXT_AND_SKY; 606 } 583 607 584 608 pmPCMdata *pcm = pmPCMinit (source, &options, model, maskVal, psfSize); … … 594 618 if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) { 595 619 // use the source moments, etc to guess basic model parameters 596 if (!psphotSersicModel ClassGuessPCM (pcm, source)) {620 if (!psphotSersicModelGuessPCM (pcm, source, maskVal, psfSize)) { 597 621 psFree (pcm); 598 model->flags |= PM_MODEL_STATUS_BADARGS; 622 model->flags |= PM_MODEL_SERSIC_PCM_FAIL_GUESS; 623 return model; 624 } 625 if (TIMING) { t2 = psTimerMark ("psphotFitPCM"); } 626 627 // psphotFitSersicShapeAndIndex (pcm, readout, source, fitOptions, maskVal, markVal, psfSize); 628 options.mode = PM_SOURCE_FIT_NO_INDEX; 629 if (!psphotFitSersicShapeAndIndexGridAuto (pcm, readout, source, &options, maskVal, markVal, psfSize)) { 630 psFree (pcm); 631 model->flags |= PM_MODEL_SERSIC_PCM_FAIL_GRID; 632 psError(PS_ERR_UNKNOWN, true, "Failed to find a index & shape"); 633 psErrorClear (); // clear the polynomial error 599 634 return model; 600 635 } … … 603 638 if (!pmSourceModelGuessPCM (pcm, source, maskVal, markVal)) { 604 639 psFree (pcm); 605 model->flags |= PM_MODEL_ STATUS_BADARGS;640 model->flags |= PM_MODEL_PCM_FAIL_GUESS; 606 641 return model; 607 642 } 608 643 } 609 644 610 if (TIMING) { t2 = psTimerMark ("psphotFitPCM"); } 611 612 if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) { 613 options.mode = PM_SOURCE_FIT_NO_INDEX; 614 } else { 615 options.mode = PM_SOURCE_FIT_EXT; 616 } 617 // update the pcm elements if we have changed the circumstance (options.mode or source->pixels) 618 pmPCMupdate(pcm, source, &options, model); 619 if (TIMING) { t4 = psTimerMark ("psphotFitPCM"); } 645 if (TIMING) { t3 = psTimerMark ("psphotFitPCM"); } 620 646 621 647 // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5); … … 623 649 NfitIterPCM += pcm->modelConv->nIter; 624 650 NfitPixPCM += pcm->modelConv->nDOF; 651 if (TIMING) { t4 = psTimerMark ("psphotFitPCM"); } 652 653 // XXX we might make this more efficient by setting NITER to be fairly small. if we hit the iteration 654 // limit, then we could do a small grid search on the size and try again from the best fit 655 656 if (options.isInteractive) psphotPCMfitCheckSize (pcm, source, maskVal, psfSize); 657 // if (pcm->modelConv->nIter == fitOptions->nIter) { 658 // psphotPCMfitRetry (pcm, source, &options, maskVal, markVal, psfSize); 659 // } 625 660 if (TIMING) { t5 = psTimerMark ("psphotFitPCM"); } 626 661 627 662 if (TIMING) { 628 663 int nPixBig = source->pixels->numCols * source->pixels->numRows; 629 fprintf (stderr, "psphotFitPCM : nIter: %2d, radius: %6.1f, npix: %5d of %5d, t1: %6.4f, t2: %6.4f, t4: %6.4f, t5: %6.4f\n", model->nIter, model->fitRadius, model->nPix, nPixBig, t1, t2, t4, t5); 630 } 631 632 // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0); 664 fprintf (stderr, "psphotFitPCM : nIter: %2d, radius: %6.1f, npix: %5d of %5d, t1: %6.4f, t2: %6.4f, t3: %6.4f, t4: %6.4f, t5: %6.4f\n", model->nIter, model->fitRadius, model->nPix, nPixBig, t1, t2, t3, t4, t5); 665 } 666 if (EXTRA_VERBOSE && !TIMING) { 667 int nPixBig = source->pixels->numCols * source->pixels->numRows; 668 float *PAR = model->params->data.F32; 669 fprintf (stderr, "source %d : %f - %f %f - %f %f %f - %f | nIter: %2d, radius: %6.1f, npix: %5d of %5d, chisq %f\n", source->id, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1], model->nIter, model->fitRadius, model->nPix, nPixBig, model->chisqNorm); 670 } 671 633 672 psFree (pcm); 634 673 … … 661 700 model->params->data.F32[PM_PAR_7] = 0.5/indexGuess[i]; 662 701 663 if (!model-> modelGuess(model, source, maskVal, markVal)) {702 if (!model->class->modelGuess(model, source, maskVal, markVal)) { 664 703 model->flags |= PM_MODEL_STATUS_BADARGS; 665 704 return false; … … 684 723 model->flags = PM_MODEL_STATUS_NONE; // do not attempt to handle failures here, let the next iteration deal with it 685 724 model->params->data.F32[PM_PAR_7] = 0.5/indexGuess[iMin]; 686 model-> modelGuess(model, source, maskVal, markVal);725 model->class->modelGuess(model, source, maskVal, markVal); 687 726 688 727 return true; … … 713 752 model->params->data.F32[PM_PAR_7] = indexGuess[i]; 714 753 715 if (!model-> modelGuess(model, source, maskVal, markVal)) {754 if (!model->class->modelGuess(model, source, maskVal, markVal)) { 716 755 model->flags |= PM_MODEL_STATUS_BADARGS; 717 756 return false; … … 748 787 return true; 749 788 } 789 790 // 0.5 / n for (1.0, 1.25, 1.66, 2.0, 3.33, 4.0) 791 // float indexGuessInv[] = {0.5, 0.4, 0.3, 0.25, 0.20, 0.15, 0.125}; 792 793 // 0.5 / n for (0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0) 794 float indexGuessInv[] = {1.00, 0.50, 0.333, 0.25, 0.166, 0.125, 0.10, 0.0833}; 795 float indexGuessR1q[] = {1.06, 1.19, 1.335, 1.48, 1.840, 2.290, 2.84, 3.5300}; 796 # define N_INDEX_GUESS_INV 8 797 798 // we are going to guess in fractions about the R1-based guess 799 float reffGuess[] = {0.8, 0.9, 1.0, 1.12, 1.25}; 800 # define N_REFF_GUESS 5 801 802 // A sersic model is very sensitive to the index. attempt to find the index first by grid search in just the index 803 // for a sersic model, attempt to fit just the index and normalization with a modest number of iterations 804 bool psphotSersicModelGuessPCM (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, float psfSize) { 805 806 // we get a reasonable guess from: 807 // * Reff = Kron R1 / Q(index) -- Q comes from Graham & Driver 808 // * Rmajor / Rminor & Theta from moments 809 // * Io from total Kron flux 810 811 // the guesses are used to fill in PAR: 812 psF32 *PAR = pcm->modelConv->params->data.F32; 813 814 // convert the moments to Major,Minor,Theta 815 psEllipseMoments moments; 816 817 if (!isfinite(source->moments->Mrf)) return false; 818 if (!isfinite(source->moments->Mxx)) return false; 819 if (!isfinite(source->moments->Mxy)) return false; 820 if (!isfinite(source->moments->Myy)) return false; 821 822 moments.x2 = source->moments->Mxx; 823 moments.y2 = source->moments->Myy; 824 moments.xy = source->moments->Mxy; 825 826 // limit axis ratio < 20.0 827 psEllipseAxes momentAxes = psEllipseMomentsToAxes (moments, 20.0); 828 829 // set the model position 830 if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) { 831 return false; 832 } 833 834 // sky is zero (no longer fitted, but not yet deprecated) 835 PAR[PM_PAR_SKY] = 0.0; 836 837 // for the index loop, use Io = 1.0, use fitted values to determine Io 838 PAR[PM_PAR_I0] = 1.0; 839 840 float xMin = NAN; 841 float iMin = NAN; 842 float sMin = NAN; 843 float rMin = NAN; 844 845 // loop over index and Reff, keeping the ARatio and Theta constant? 846 // loop over index guesses and find the best fit 847 for (int j = 0; j < N_REFF_GUESS; j++) { 848 for (int i = 0; i < N_INDEX_GUESS_INV; i++) { 849 PAR[PM_PAR_7] = indexGuessInv[i]; 850 851 psEllipseAxes guessAxes; 852 guessAxes.major = reffGuess[j] * source->moments->Mrf / indexGuessR1q[i]; 853 guessAxes.minor = guessAxes.major * (momentAxes.minor / momentAxes.major); 854 guessAxes.theta = momentAxes.theta; 855 856 if (!isfinite(guessAxes.major)) return false; 857 if (!isfinite(guessAxes.minor)) return false; 858 if (!isfinite(guessAxes.theta)) return false; 859 860 // convert the major,minor,theta to shape parameters for an Reff-like model 861 pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true); 862 863 // generated the modelFlux 864 // XXX note that this does not add sky to model 865 pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize); 866 867 float YY = 0.0; 868 float YM = 0.0; 869 float MM = 0.0; 870 bool usePoisson = false; 871 872 for (int iy = 0; iy < source->pixels->numRows; iy++) { 873 for (int ix = 0; ix < source->pixels->numCols; ix++) { 874 // skip masked points 875 if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) { 876 continue; 877 } 878 // skip zero-variance points 879 if (source->variance->data.F32[iy][ix] == 0) { 880 continue; 881 } 882 // skip nan value points 883 if (!isfinite(source->pixels->data.F32[iy][ix])) { 884 continue; 885 } 886 887 float fy = source->pixels->data.F32[iy][ix]; 888 float fm = source->modelFlux->data.F32[iy][ix]; 889 float wt = (usePoisson) ? 1.0 / source->variance->data.F32[iy][ix] : 1.0; 890 891 YY += PS_SQR(fy) * wt; 892 YM += fm * fy * wt; 893 MM += PS_SQR(fm) * wt; 894 } 895 } 896 897 float Io = YM / MM; 898 float Chisq = YY - 2 * Io * YM + Io * Io * MM; 899 if (isnan(xMin) || (Chisq < xMin)) { 900 xMin = Chisq; 901 iMin = Io; 902 sMin = indexGuessInv[i]; 903 rMin = reffGuess[j] / indexGuessR1q[i]; 904 } 905 if (EXTRA_VERBOSE) { 906 fprintf (stderr, "%d | %f %f %f %f | %f %f %f %f", i, indexGuessInv[i], reffGuess[j], Io, Chisq, sMin, rMin, iMin, xMin); 907 fprintf (stderr, "\n"); 908 } 909 } 910 } 911 912 { 913 psEllipseAxes guessAxes; 914 guessAxes.major = rMin * source->moments->Mrf; 915 guessAxes.minor = guessAxes.major * (momentAxes.minor / momentAxes.major); 916 guessAxes.theta = momentAxes.theta; 917 918 if (!isfinite(guessAxes.major)) return false; 919 if (!isfinite(guessAxes.minor)) return false; 920 if (!isfinite(guessAxes.theta)) return false; 921 922 // convert the major,minor,theta to shape parameters for an Reff-like model 923 pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true); 924 } 925 926 PAR[PM_PAR_I0] = iMin; 927 PAR[PM_PAR_7] = sMin; 928 929 return true; 930 } 931 932 // we have a set of guess parameters, do a small number of iterations fitting only SHAPE then only INDEX 933 bool psphotFitSersicShapeAndIndex (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) { 934 935 pmModel *model = pcm->modelConv; 936 937 assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC")); 938 939 pmSourceFitOptions options = *fitOptions; 940 941 for (int i = 0; i < 3; i++) { 942 // fit EXT (not PSF) model (set/unset the pixel mask) 943 options.mode = PM_SOURCE_FIT_SHAPE; 944 options.nIter = 2; 945 946 // update the pcm elements if we have changed the circumstance (here, options.mode) 947 pmPCMupdate(pcm, source, &options, model); 948 949 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 950 if (EXTRA_VERBOSE) { 951 float *PAR = model->params->data.F32; 952 fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 953 } 954 955 // fit EXT (not PSF) model (set/unset the pixel mask) 956 options.mode = PM_SOURCE_FIT_INDEX; 957 // options.mode = PM_SOURCE_FIT_EXT_AND_SKY; 958 options.nIter = 30; 959 960 // update the pcm elements if we have changed the circumstance (here, options.mode) 961 pmPCMupdate(pcm, source, &options, model); 962 963 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 964 if (EXTRA_VERBOSE) { 965 float *PAR = model->params->data.F32; 966 fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 967 } 968 } 969 970 // update the pcm elements if we have changed the circumstance (here, options.mode) 971 pmPCMupdate(pcm, source, fitOptions, model); 972 973 return true; 974 } 975 976 // we have a set of guess parameters, do a small number of iterations fitting only SHAPE then only INDEX 977 bool psphotFitSersicShapeAndIndexGridAuto (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) { 978 979 pmModel *model = pcm->modelConv; 980 981 assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC")); 982 983 pmSourceFitOptions options = *fitOptions; 984 985 psF32 *PAR = pcm->modelConv->params->data.F32; 986 987 options.mode = PM_SOURCE_FIT_SHAPE; 988 options.nIter = 7; 989 990 // update the pcm elements if we have changed the circumstance (here, options.mode) 991 pmPCMupdate(pcm, source, &options, model); 992 993 // we have been provided a guess at the index (P[7]) from the list of indexGuessInv 994 995 // find the matching indexGuessInv 996 int nStart = -1; 997 for (int i = 0; i < N_INDEX_GUESS_INV; i++) { 998 if (fabs(PAR[PM_PAR_7] - indexGuessInv[i]) < 0.01) { 999 nStart = i; 1000 break; 1001 } 1002 } 1003 if (nStart == -1) { 1004 fprintf (stderr, "WARNING: could not find start guess %f\n", PAR[PM_PAR_7]); 1005 return false; 1006 } 1007 1008 psVector *chi2 = psVectorAllocEmpty (16, PS_TYPE_F32); 1009 psVector *Sidx = psVectorAllocEmpty (16, PS_TYPE_F32); 1010 1011 float Sm = NAN, Sp = NAN, So = NAN; 1012 if (nStart == 0) { 1013 Sm = indexGuessInv[nStart]; 1014 So = 0.5*(indexGuessInv[nStart + 1] + indexGuessInv[nStart]); 1015 Sp = indexGuessInv[nStart + 1]; 1016 } else if (nStart == N_INDEX_GUESS_INV - 1) { 1017 Sp = indexGuessInv[nStart]; 1018 So = 0.5*(indexGuessInv[nStart - 1] + indexGuessInv[nStart]); 1019 Sm = indexGuessInv[nStart - 1]; 1020 } else { 1021 Sm = 0.5*(indexGuessInv[nStart - 1] + indexGuessInv[nStart]); 1022 So = indexGuessInv[nStart]; 1023 Sp = 0.5*(indexGuessInv[nStart + 1] + indexGuessInv[nStart]); 1024 } 1025 1026 PAR[PM_PAR_7] = Sm; 1027 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1028 if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 1029 psVectorAppend (Sidx, 100*PAR[PM_PAR_7]); 1030 psVectorAppend (chi2, model->chisqNorm); 1031 1032 PAR[PM_PAR_7] = So; 1033 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1034 if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 1035 psVectorAppend (Sidx, 100*PAR[PM_PAR_7]); 1036 psVectorAppend (chi2, model->chisqNorm); 1037 1038 PAR[PM_PAR_7] = Sp; 1039 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1040 if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 1041 psVectorAppend (Sidx, 100*PAR[PM_PAR_7]); 1042 psVectorAppend (chi2, model->chisqNorm); 1043 1044 psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 2); 1045 if (!psVectorFitPolynomial1D (poly, NULL, 0, chi2, NULL, Sidx)) { 1046 psError(PS_ERR_UNKNOWN, true, "Failed to find a good chisq parabola"); 1047 psFree (chi2); 1048 psFree (Sidx); 1049 psFree (poly); 1050 return false; 1051 } 1052 1053 // where is the minimum of this polynomial fit? 1054 float Smin = -0.5 * poly->coeff[1] / poly->coeff[2] / 100.0; 1055 1056 // constrain Smin to be in a valid range: allow the fitted range to go a bit beyond the 3 trial points, but no further 1057 float Smx = Sm - 0.25*(So - Sm); 1058 float Spx = Sp + 0.25*(Sp - So); 1059 Smin = PS_MAX(PS_MIN(Smin, Smx), Spx); 1060 PAR[PM_PAR_7] = Smin; 1061 1062 // XXX I could set the error on PAR_7 here if I knew how to roughly convert these chisq values to true chisq values 1063 1064 // return to the original fitting mode (fitOptions) 1065 pmPCMupdate(pcm, source, fitOptions, model); 1066 1067 psFree (chi2); 1068 psFree (Sidx); 1069 psFree (poly); 1070 1071 return true; 1072 } 1073 1074 1075 // we have a set of guess parameters, do a small number of iterations fitting only SHAPE then only INDEX 1076 bool psphotFitSersicShapeAndIndexGridAutoScaled (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) { 1077 1078 pmModel *model = pcm->modelConv; 1079 1080 assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC")); 1081 1082 pmSourceFitOptions options = *fitOptions; 1083 1084 psF32 *PAR = pcm->modelConv->params->data.F32; 1085 1086 options.mode = PM_SOURCE_FIT_SHAPE; 1087 options.nIter = 5; 1088 1089 // update the pcm elements if we have changed the circumstance (here, options.mode) 1090 pmPCMupdate(pcm, source, &options, model); 1091 1092 float parStart[8]; 1093 for (int i = 0; i < 8; i++) parStart[i] = PAR[i]; 1094 1095 // we start with a guess at the index (P[7]) 1096 1097 // get chisq for P[7], P[7]*1.1, P[7]*1.25 (or *0.75 depending on the result of 1.1) 1098 1099 psVector *chi2 = psVectorAllocEmpty (16, PS_TYPE_F32); 1100 psVector *Sidx = psVectorAllocEmpty (16, PS_TYPE_F32); 1101 1102 PAR[PM_PAR_7] = parStart[7]; 1103 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1104 if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 1105 psVectorAppend (Sidx, 100*PAR[PM_PAR_7]); 1106 psVectorAppend (chi2, model->chisqNorm); 1107 1108 float fI = 1.1; 1109 PAR[PM_PAR_7] = parStart[7]*fI; 1110 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1111 if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 1112 psVectorAppend (Sidx, 100*PAR[PM_PAR_7]); 1113 psVectorAppend (chi2, model->chisqNorm); 1114 1115 if (chi2->data.F32[1] < chi2->data.F32[0]) { 1116 fI = 1.3; 1117 } else { 1118 fI = 1.0 / 1.3; 1119 } 1120 1121 PAR[PM_PAR_7] = parStart[7]*fI; 1122 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1123 if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 1124 psVectorAppend (Sidx, 100*PAR[PM_PAR_7]); 1125 psVectorAppend (chi2, model->chisqNorm); 1126 1127 // can we fit the 3 pts with a parabola? 1128 int nTry = 0; 1129 psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 2); 1130 while (!psVectorFitPolynomial1D (poly, NULL, 0, chi2, NULL, Sidx)) { 1131 psErrorClear (); // clear the polynomial error 1132 if (nTry > 4) { 1133 psError(PS_ERR_UNKNOWN, true, "Failed to find a good chisq parabola"); 1134 psFree (chi2); 1135 psFree (Sidx); 1136 psFree (poly); 1137 return false; 1138 } 1139 fI = (fI < 1.0) ? fI / 1.3 : fI * 1.3; 1140 PAR[PM_PAR_7] = parStart[7]*fI; 1141 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1142 if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 1143 psVectorAppend (Sidx, 100*PAR[PM_PAR_7]); 1144 psVectorAppend (chi2, model->chisqNorm); 1145 nTry ++; 1146 } 1147 1148 // where is the minimum of this polynomial fit? 1149 float Smin = -0.5 * poly->coeff[1] / poly->coeff[2] / 100.0; 1150 1151 // constrain Smin to be in a valid range (1.0 - 0.1, corresponding to 0.5 (Gauss) to 5.0 (slightly peakier than Dev) 1152 Smin = PS_MAX(PS_MIN(Smin, 1.0), 0.1); 1153 PAR[PM_PAR_7] = Smin; 1154 1155 // pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1156 // if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 1157 1158 //// for (int i = 0; i < 8; i++) PAR[i] = parStart[i]; 1159 //// 1160 //// for (float fI = 0.0; fI < 0.15; fI += 0.01) { 1161 //// PAR[PM_PAR_7] = parStart[7] - fI; 1162 //// 1163 //// // fit EXT (not PSF) model (set/unset the pixel mask) 1164 //// 1165 //// pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1166 //// if (TIMING) { 1167 //// float *PAR = model->params->data.F32; 1168 //// fprintf (stderr, "%d %f : %f - %f %f %f - %f\n", model->nIter, model->chisqNorm, PAR[7], PAR[4], PAR[5], PAR[6], PAR[1]); 1169 //// } 1170 //// } 1171 1172 // return to the original fitting mode (fitOptions) 1173 pmPCMupdate(pcm, source, fitOptions, model); 1174 1175 psFree (chi2); 1176 psFree (Sidx); 1177 psFree (poly); 1178 1179 return true; 1180 } 1181 1182 1183 // we have a set of guess parameters, do a small number of iterations fitting only SHAPE then only INDEX 1184 bool psphotFitSersicShapeAndIndexGrid (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) { 1185 1186 pmModel *model = pcm->modelConv; 1187 1188 assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC")); 1189 1190 pmSourceFitOptions options = *fitOptions; 1191 1192 psF32 *PAR = pcm->modelConv->params->data.F32; 1193 1194 options.mode = PM_SOURCE_FIT_SHAPE; 1195 options.nIter = 10; 1196 1197 // update the pcm elements if we have changed the circumstance (here, options.mode) 1198 pmPCMupdate(pcm, source, &options, model); 1199 1200 psVector *chi2 = psVectorAllocEmpty (16, PS_TYPE_F32); 1201 psVector *Sidx = psVectorAllocEmpty (16, PS_TYPE_F32); 1202 1203 float par7[] = {0.100, 0.125, 0.150, 0.175, 0.200, 0.225, 0.250}; 1204 for (int i = 0; i < 7; i++) { 1205 PAR[PM_PAR_7] = par7[i]; 1206 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1207 if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 1208 psVectorAppend (Sidx, PAR[PM_PAR_7]); 1209 psVectorAppend (chi2, model->chisqNorm); 1210 } 1211 1212 psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 2); 1213 if (!psVectorFitPolynomial1D (poly, NULL, 0, chi2, NULL, Sidx)) { 1214 psError(PS_ERR_UNKNOWN, true, "Failed to find a good chisq parabola"); 1215 psFree (chi2); 1216 psFree (Sidx); 1217 psFree (poly); 1218 return false; 1219 } 1220 1221 // where is the minimum of this polynomial fit? 1222 fprintf (stderr, "fit1d: %f + %f x + %f x^2\n", poly->coeff[0], poly->coeff[1], poly->coeff[2]); 1223 float Smin = -0.5 * poly->coeff[1] / poly->coeff[2]; 1224 1225 // constrain Smin to be in a valid range (1.0 - 0.1, corresponding to 0.5 (Gauss) to 5.0 (slightly peakier than Dev) 1226 Smin = PS_MAX(PS_MIN(Smin, 1.0), 0.1); 1227 PAR[PM_PAR_7] = Smin; 1228 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1229 if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]); 1230 1231 //// for (int i = 0; i < 8; i++) PAR[i] = parStart[i]; 1232 //// 1233 //// for (float fI = 0.0; fI < 0.15; fI += 0.01) { 1234 //// PAR[PM_PAR_7] = parStart[7] - fI; 1235 //// 1236 //// // fit EXT (not PSF) model (set/unset the pixel mask) 1237 //// 1238 //// pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1239 //// if (TIMING) { 1240 //// float *PAR = model->params->data.F32; 1241 //// fprintf (stderr, "%d %f : %f - %f %f %f - %f\n", model->nIter, model->chisqNorm, PAR[7], PAR[4], PAR[5], PAR[6], PAR[1]); 1242 //// } 1243 //// } 1244 1245 // return to the original fitting mode (fitOptions) 1246 pmPCMupdate(pcm, source, fitOptions, model); 1247 1248 psFree (chi2); 1249 psFree (Sidx); 1250 psFree (poly); 1251 1252 return true; 1253 } 1254 1255 // # define N_REFF_CHECK 11 1256 // float drefCheck[] = {-0.02, -0.04, -0.06, 0.0, 0.85, 0.90, 0.95, 1.00, 1.05, 1.10, 1.15, 1.20, 1.25}; 1257 1258 // we have an initial fit, check to see if the current size is besst 1259 bool psphotPCMfitCheckSize (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, float psfSize) { 1260 1261 // PAR is already at my current best guess 1262 psF32 *PAR = pcm->modelConv->params->data.F32; 1263 1264 // store best guess as a shape 1265 psEllipseAxes centerAxes; 1266 pmModelParamsToAxes (¢erAxes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 1267 1268 float xMin = NAN; 1269 float iMin = NAN; 1270 float rMin = NAN; 1271 1272 // loop over Reff, keeping the ARatio and Theta constant 1273 for (int j = -4; j <= 4; j++) { 1274 1275 float dref = j * 0.01; 1276 1277 psEllipseAxes guessAxes; 1278 guessAxes.major = centerAxes.major + dref; 1279 guessAxes.minor = guessAxes.major * centerAxes.minor / centerAxes.major; 1280 guessAxes.theta = centerAxes.theta; 1281 1282 if (!isfinite(guessAxes.major)) return false; 1283 if (!isfinite(guessAxes.minor)) return false; 1284 if (!isfinite(guessAxes.theta)) return false; 1285 1286 // convert the major,minor,theta to shape parameters for an Reff-like model 1287 pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true); 1288 1289 // generated the modelFlux 1290 // XXX note that this does not add sky to model 1291 pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize); 1292 1293 float YY = 0.0; 1294 float YM = 0.0; 1295 float MM = 0.0; 1296 bool usePoisson = false; 1297 1298 for (int iy = 0; iy < source->pixels->numRows; iy++) { 1299 for (int ix = 0; ix < source->pixels->numCols; ix++) { 1300 // skip masked points 1301 if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) { 1302 continue; 1303 } 1304 // skip zero-variance points 1305 if (source->variance->data.F32[iy][ix] == 0) { 1306 continue; 1307 } 1308 // skip nan value points 1309 if (!isfinite(source->pixels->data.F32[iy][ix])) { 1310 continue; 1311 } 1312 1313 float fy = source->pixels->data.F32[iy][ix]; 1314 float fm = source->modelFlux->data.F32[iy][ix]; 1315 float wt = (usePoisson) ? 1.0 / source->variance->data.F32[iy][ix] : 1.0; 1316 1317 YY += PS_SQR(fy) * wt; 1318 YM += fm * fy * wt; 1319 MM += PS_SQR(fm) * wt; 1320 } 1321 } 1322 1323 float Io = YM / MM; 1324 float Chisq = YY - 2 * Io * YM + Io * Io * MM; 1325 if (isnan(xMin) || (Chisq < xMin)) { 1326 xMin = Chisq; 1327 iMin = Io; 1328 rMin = dref; 1329 } 1330 // fprintf (stderr, "%d | %f %f %f | %f %f %f\n", j, dref, Io, Chisq, rMin, iMin, xMin); 1331 } 1332 1333 psEllipseAxes guessAxes; 1334 guessAxes.major = centerAxes.major + rMin; 1335 guessAxes.minor = guessAxes.major * centerAxes.minor / centerAxes.major; 1336 guessAxes.theta = centerAxes.theta; 1337 1338 if (!isfinite(guessAxes.major)) return false; 1339 if (!isfinite(guessAxes.minor)) return false; 1340 if (!isfinite(guessAxes.theta)) return false; 1341 1342 // convert the major,minor,theta to shape parameters for an Reff-like model 1343 pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true); 1344 PAR[PM_PAR_I0] = iMin; 1345 1346 return true; 1347 } 1348 1349 // we have an initial fit, check to see if the current size is besst 1350 bool psphotPCMfitRetry (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, float psfSize) { 1351 1352 // PAR is already at my current best guess 1353 psF32 *PAR = pcm->modelConv->params->data.F32; 1354 1355 // store best guess as a shape 1356 psEllipseAxes centerAxes; 1357 pmModelParamsToAxes (¢erAxes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 1358 1359 // retry with axes smaller by 1 pixel 1360 psEllipseAxes guessAxes; 1361 guessAxes.major = centerAxes.major - 0.08; 1362 guessAxes.minor = guessAxes.major * centerAxes.minor / centerAxes.major; 1363 guessAxes.theta = centerAxes.theta; 1364 1365 if (!isfinite(guessAxes.major)) return false; 1366 if (!isfinite(guessAxes.minor)) return false; 1367 if (!isfinite(guessAxes.theta)) return false; 1368 1369 // convert the major,minor,theta to shape parameters for an Reff-like model 1370 pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true); 1371 1372 // generated the modelFlux 1373 // XXX note that this does not add sky to model 1374 pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize); 1375 1376 float YY = 0.0; 1377 float YM = 0.0; 1378 float MM = 0.0; 1379 bool usePoisson = false; 1380 1381 for (int iy = 0; iy < source->pixels->numRows; iy++) { 1382 for (int ix = 0; ix < source->pixels->numCols; ix++) { 1383 // skip masked points 1384 if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) { 1385 continue; 1386 } 1387 // skip zero-variance points 1388 if (source->variance->data.F32[iy][ix] == 0) { 1389 continue; 1390 } 1391 // skip nan value points 1392 if (!isfinite(source->pixels->data.F32[iy][ix])) { 1393 continue; 1394 } 1395 1396 float fy = source->pixels->data.F32[iy][ix]; 1397 float fm = source->modelFlux->data.F32[iy][ix]; 1398 float wt = (usePoisson) ? 1.0 / source->variance->data.F32[iy][ix] : 1.0; 1399 1400 YY += PS_SQR(fy) * wt; 1401 YM += fm * fy * wt; 1402 MM += PS_SQR(fm) * wt; 1403 } 1404 } 1405 1406 float Io = YM / MM; 1407 PAR[PM_PAR_I0] = Io; 1408 1409 pmSourceFitPCM (pcm, source, fitOptions, maskVal, markVal, psfSize); // NOTE : 1687 allocs in here 1410 1411 return true; 1412 } 1413 1414
Note:
See TracChangeset
for help on using the changeset viewer.
