Changeset 36375 for trunk/psphot/src/psphotSourceFits.c
- Timestamp:
- Dec 10, 2013, 2:55:11 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
-
. (modified) (1 prop)
-
psphot (modified) (1 prop)
-
psphot/src (modified) (2 props)
-
psphot/src/psphotSourceFits.c (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
trunk/psphot
- Property svn:mergeinfo changed
-
trunk/psphot/src
- Property svn:ignore
-
old new 24 24 psphotModelTest 25 25 psphotMinimal 26 psphotFullForce 27 psmakecff
-
- Property svn:mergeinfo changed
- Property svn:ignore
-
trunk/psphot/src/psphotSourceFits.c
r36107 r36375 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) { … … 579 582 maskVal |= markVal; 580 583 581 // allocate the model 584 // allocate the model (this can only fail on a config error) 582 585 pmModel *model = pmModelAlloc(modelType); 583 if (!model) { 584 return NULL; 585 } 586 587 float t1, t2, t4, t5; 588 t1 = t2 = t4 = t5 = 0.0; 586 psAssert (model, "invalid extended model name"); 587 588 float t1, t2, t3, t4, t5; 589 t1 = t2 = t3 = t4 = t5 = 0.0; 589 590 if (TIMING) { psTimerStart ("psphotFitPCM"); } 590 591 … … 619 620 if (!psphotSersicModelGuessPCM (pcm, source, maskVal, psfSize)) { 620 621 psFree (pcm); 621 model->flags |= PM_MODEL_S TATUS_BADARGS;622 model->flags |= PM_MODEL_SERSIC_PCM_FAIL_GUESS; 622 623 return model; 623 624 } … … 628 629 if (!psphotFitSersicShapeAndIndexGridAuto (pcm, readout, source, &options, maskVal, markVal, psfSize)) { 629 630 psFree (pcm); 630 model->flags |= PM_MODEL_S TATUS_BADARGS;631 model->flags |= PM_MODEL_SERSIC_PCM_FAIL_GRID; 631 632 psError(PS_ERR_UNKNOWN, true, "Failed to find a index & shape"); 632 633 psErrorClear (); // clear the polynomial error … … 637 638 if (!pmSourceModelGuessPCM (pcm, source, maskVal, markVal)) { 638 639 psFree (pcm); 639 model->flags |= PM_MODEL_ STATUS_BADARGS;640 model->flags |= PM_MODEL_PCM_FAIL_GUESS; 640 641 return model; 641 642 } 642 643 } 643 644 644 if (TIMING) { t 4= psTimerMark ("psphotFitPCM"); }645 if (TIMING) { t3 = psTimerMark ("psphotFitPCM"); } 645 646 646 647 // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5); … … 648 649 NfitIterPCM += pcm->modelConv->nIter; 649 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 // } 650 660 if (TIMING) { t5 = psTimerMark ("psphotFitPCM"); } 651 661 652 662 if (TIMING) { 653 663 int nPixBig = source->pixels->numCols * source->pixels->numRows; 654 fprintf (stderr, "psphotFitPCM : nIter: %2d, radius: %6.1f, npix: %5d of %5d, t1: %6.4f, t2: %6.4f, t 4: %6.4f, t5: %6.4f\n", model->nIter, model->fitRadius, model->nPix, nPixBig, t1, t2, t4, t5);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); 655 665 } 656 666 if (EXTRA_VERBOSE && !TIMING) { … … 778 788 } 779 789 780 // float indexGuessInv[] = {0.5, 0.33, 0.25, 0.167, 0.125, 0.083}; 781 float indexGuessInv[] = {0.5, 0.4, 0.3, 0.25, 0.20, 0.15, 0.125}; 782 # define N_INDEX_GUESS_INV 7 783 784 // float reffGuess[] = {3.0, 10.0, 20.0, 30.0, 40.0}; 785 float reffGuess[] = {0.5, 0.75, 1.0, 1.4, 2.0}; 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}; 786 800 # define N_REFF_GUESS 5 787 801 … … 791 805 792 806 // we get a reasonable guess from: 793 // * Reff = Kron R1 807 // * Reff = Kron R1 / Q(index) -- Q comes from Graham & Driver 794 808 // * Rmajor / Rminor & Theta from moments 795 809 // * Io from total Kron flux … … 813 827 psEllipseAxes momentAxes = psEllipseMomentsToAxes (moments, 20.0); 814 828 815 if (0) {816 psEllipseAxes guessAxes;817 guessAxes.major = source->moments->Mrf;818 guessAxes.minor = (momentAxes.minor / momentAxes.minor) * guessAxes.major;819 guessAxes.theta = momentAxes.theta;820 821 if (!isfinite(guessAxes.major)) return false;822 if (!isfinite(guessAxes.minor)) return false;823 if (!isfinite(guessAxes.theta)) return false;824 825 // convert the major,minor,theta to shape parameters for an Reff-like model826 pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);827 }828 829 829 // set the model position 830 830 if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) { … … 846 846 // loop over index guesses and find the best fit 847 847 for (int j = 0; j < N_REFF_GUESS; j++) { 848 849 psEllipseAxes guessAxes;850 guessAxes.major = reffGuess[j] * source->moments->Mrf;851 guessAxes.minor = guessAxes.major * (momentAxes.minor / momentAxes.major);852 guessAxes.theta = momentAxes.theta;853 854 if (!isfinite(guessAxes.major)) return false;855 if (!isfinite(guessAxes.minor)) return false;856 if (!isfinite(guessAxes.theta)) return false;857 858 // convert the major,minor,theta to shape parameters for an Reff-like model859 pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);860 861 848 for (int i = 0; i < N_INDEX_GUESS_INV; i++) { 862 849 PAR[PM_PAR_7] = indexGuessInv[i]; 863 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 864 863 // generated the modelFlux 865 pmPCMMakeModel (source, pcm->modelConv, maskVal, psfSize); 864 // XXX note that this does not add sky to model 865 pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize); 866 866 867 867 float YY = 0.0; … … 901 901 iMin = Io; 902 902 sMin = indexGuessInv[i]; 903 rMin = reffGuess[j] ;903 rMin = reffGuess[j] / indexGuessR1q[i]; 904 904 } 905 // fprintf (stderr, "%d | %f %f %f %f | %f %f %f %f", i, indexGuessInv[i], reffGuess[j], Io, Chisq, sMin, rMin, iMin, xMin); 906 // fprintf (stderr, "\n"); 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 } 907 909 } 908 910 } … … 1007 1009 psVector *Sidx = psVectorAllocEmpty (16, PS_TYPE_F32); 1008 1010 1009 PAR[PM_PAR_7] = indexGuessInv[nStart]; 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; 1010 1027 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1011 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]); … … 1013 1030 psVectorAppend (chi2, model->chisqNorm); 1014 1031 1015 PAR[PM_PAR_7] = (nStart < N_INDEX_GUESS_INV - 1) ? 0.5*(indexGuessInv[nStart + 1] + indexGuessInv[nStart]) : 0.1;1032 PAR[PM_PAR_7] = So; 1016 1033 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1017 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]); … … 1019 1036 psVectorAppend (chi2, model->chisqNorm); 1020 1037 1021 PAR[PM_PAR_7] = (nStart > 0) ? 0.5*(indexGuessInv[nStart - 1] + indexGuessInv[nStart]) : 0.55;1038 PAR[PM_PAR_7] = Sp; 1022 1039 pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize); 1023 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]); 1024 1041 psVectorAppend (Sidx, 100*PAR[PM_PAR_7]); 1025 1042 psVectorAppend (chi2, model->chisqNorm); 1026 1027 if (chi2->data.F32[1] < chi2->data.F32[2]) {1028 if (nStart == N_INDEX_GUESS_INV - 1) {1029 PAR[PM_PAR_7] = 0.11;1030 } else {1031 PAR[PM_PAR_7] = indexGuessInv[nStart + 1];1032 }1033 } else {1034 if (nStart == 0) {1035 PAR[PM_PAR_7] = 0.52;1036 } else {1037 PAR[PM_PAR_7] = indexGuessInv[nStart - 1];1038 }1039 }1040 1043 1041 1044 psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 2); … … 1051 1054 float Smin = -0.5 * poly->coeff[1] / poly->coeff[2] / 100.0; 1052 1055 1053 // constrain Smin to be in a valid range (1.0 - 0.1, corresponding to 0.5 (Gauss) to 5.0 (slightly peakier than Dev) 1054 Smin = PS_MAX(PS_MIN(Smin, 1.0), 0.1); 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); 1055 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 1056 1063 1057 1064 // return to the original fitting mode (fitOptions) … … 1246 1253 } 1247 1254 1248 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.
