IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 42510


Ignore:
Timestamp:
Aug 17, 2023, 3:24:45 PM (3 years ago)
Author:
eugene
Message:

convert 2D fitting to IRLS-based fitting; use sample median instead of robust median for initial pass

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20230313/psphot/src/psphotMakeResiduals.c

    r42507 r42510  
    9595    psVector *yC = psVectorAllocEmpty (100, PS_TYPE_F32);
    9696
    97 # define TESTRESID 1
     97# define TESTRESID 0
    9898# if (TESTRESID)
    9999    psArray *sourceRawCube = psArrayAllocEmpty (1);
     
    101101    psArray *sourceVarCube = psArrayAllocEmpty (1);
    102102    psArray *sourceMskCube = psArrayAllocEmpty (1);
     103
     104    psImage *refImage = NULL;
    103105# endif
    104106
     
    121123# if (TESTRESID)
    122124        psImage *tmpImage = psImageCopy(NULL, image, PS_TYPE_F32);
    123         psArrayAdd (sourceRawCube, 1, tmpImage);
    124         psFree (tmpImage);
     125        if (refImage == NULL) {
     126          refImage = tmpImage;
     127          psArrayAdd (sourceRawCube, 1, tmpImage);
     128        } else {
     129          if (tmpImage->numCols != refImage->numCols) {
     130            fprintf (stderr, "mismatched image sizes (%d : %f, %f)\n", i, model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
     131            continue;
     132          }
     133          if (tmpImage->numRows != refImage->numRows) {
     134            fprintf (stderr, "mismatched image sizes (%d : %f, %f)\n", i, model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
     135            continue;
     136          }
     137          psArrayAdd (sourceRawCube, 1, tmpImage);
     138          psFree (tmpImage);
     139        }
    125140# endif
    126141
     
    199214    psVector *fmasks  = psVectorAlloc (input->n, PS_TYPE_VECTOR_MASK);
    200215
    201     // statistic to use to determine baseline for clipping
    202     psStats *fluxClip     = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    203     psStats *fluxClipDef  = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    204216    // statistic to use to determine output flux
    205217    // XXX make API to convert statOption for MEAN/MEDIAN in to corresponding STDEV?
     
    207219    psStats *fluxStatsDef = psStatsAlloc (statOption | PS_STAT_SAMPLE_STDEV);
    208220
     221    // use this for the IRLS fitting below (defines niter)
     222    psStats *statsIRLS = psStatsAlloc(PS_STAT_CLIPPED_MEAN); statsIRLS->clipIter = 10; // max number of iterations
     223    psPolynomial2D *polyIRLS = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 1, 1);
     224
    209225    // Use psF64 to minimize overflow problems?
    210226    psImage *A = psImageAlloc(3, 3, PS_TYPE_F64); // Least-squares matrix
     
    217233
    218234            int nGoodPixel = 0;              // pixel is off the image
     235
     236            // skip pixels outside of the requested radius
     237            float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows));
     238            if (radius > radiusMax) {
     239              resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1;
     240              continue;
     241            }
    219242
    220243            // build the vector of data values for this output pixel
     
    268291
    269292            // measure the robust median to determine a baseline reference value
    270             *fluxClip = *fluxClipDef;
     293            psStats *fluxClip = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
    271294            if (!psVectorStats (fluxClip, fluxes, NULL, fmasks, fmaskVal)) {
    272295                psError(PSPHOT_ERR_CONFIG, false, "Error calculating residual stats");
     296                psFree (fluxClip);
    273297                return false;
    274298            }
    275             if (isnan(fluxClip->robustMedian)) {
     299            if (isnan(fluxClip->sampleMedian)) {
    276300                resid->Ro->data.F32[oy][ox] = 0.0;
    277301                resid->Rx->data.F32[oy][ox] = 0.0;
    278302                resid->Ry->data.F32[oy][ox] = 0.0;
    279303                resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = badMask;
     304                psFree (fluxClip);
    280305                continue;
    281306            }
    282307
    283             if (fabs(fluxClip->robustMedian) > 1.5) {
    284               fprintf (stderr, "warning: %d, %d : residual pixel has funny initial median value: %f\n", ox, oy, fluxClip->robustMedian);
     308            if (fabs(fluxClip->sampleMedian) > 1.5) {
     309              fprintf (stderr, "warning: %d, %d : residual pixel has funny initial median value: %f\n", ox, oy, fluxClip->sampleMedian);
    285310            }
    286311
     
    288313            int nKeep = 0;
    289314            for (int i = 0; i < fluxes->n; i++) {
    290                 float delta = fluxes->data.F32[i] - fluxClip->robustMedian;
     315                float delta = fluxes->data.F32[i] - fluxClip->sampleMedian;
    291316                float sigma = sqrt (dfluxes->data.F32[i]);
    292317                float swing = fabs(delta) / sigma;
     
    298323                if (!fmasks->data.PS_TYPE_VECTOR_MASK_DATA[i]) nKeep++;
    299324            }
     325            psFree (fluxClip);
    300326
    301327            if (nKeep < 5) {
     
    311337                }
    312338
    313                 // XXX this test should go at the top of the loop
    314                 float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows));
    315                 if (radius > radiusMax) {
    316                   resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1;
    317                   continue;
    318                 }
     339                resid->Rx->data.F32[oy][ox] = resid->Ry->data.F32[oy][ox] = 0.0;
    319340
    320341                resid->Ro->data.F32[oy][ox] = psStatsGetValue(fluxStats, statOption);
    321                 resid->Rx->data.F32[oy][ox] = resid->Ry->data.F32[oy][ox] = 0.0;
    322 
    323342                if (isnan(resid->Ro->data.F32[oy][ox])) {
    324343                    resid->Ro->data.F32[oy][ox] = 0.0;
    325                     resid->Rx->data.F32[oy][ox] = 0.0;
    326                     resid->Ry->data.F32[oy][ox] = 0.0;
    327344                    resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = badMask;
    328345                    continue;
     
    335352                assert (SPATIAL_ORDER == 1);
    336353
    337                 float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows));
    338                 if (radius > radiusMax) {
    339                   resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1;
    340                   continue;
    341                 }
    342 
    343                 psImageInit(A, 0.0);
    344                 psVectorInit(B, 0.0);
    345                 for (int i = 0; i < fluxes->n; i++) {
    346                     if (fmasks->data.PS_TYPE_VECTOR_MASK_DATA[i]) continue;
    347                     B->data.F64[0] += fluxes->data.F32[i]/dfluxes->data.F32[i];
    348                     B->data.F64[1] += fluxes->data.F32[i]*xC->data.F32[i]/dfluxes->data.F32[i];
    349                     B->data.F64[2] += fluxes->data.F32[i]*yC->data.F32[i]/dfluxes->data.F32[i];
    350 
    351                     A->data.F64[0][0] += 1.0/dfluxes->data.F32[i];
    352                     A->data.F64[1][0] += xC->data.F32[i]/dfluxes->data.F32[i];
    353                     A->data.F64[2][0] += yC->data.F32[i]/dfluxes->data.F32[i];
    354 
    355                     A->data.F64[1][1] += PS_SQR(xC->data.F32[i])/dfluxes->data.F32[i];
    356                     A->data.F64[2][2] += PS_SQR(yC->data.F32[i])/dfluxes->data.F32[i];
    357                     A->data.F64[1][2] += xC->data.F32[i]*yC->data.F32[i]/dfluxes->data.F32[i];
    358                 }
    359 
    360                 A->data.F64[0][1] = A->data.F64[1][0];
    361                 A->data.F64[0][2] = A->data.F64[2][0];
    362                 A->data.F64[2][1] = A->data.F64[1][2];
    363 
    364                 if (!psMatrixGJSolve(A, B)) {
    365                     resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1;
    366                     psWarning("Singular matrix solving for (y,x) = (%d,%d)'s residuals, masking", oy, ox);
    367                     continue;
    368                 }
    369 
    370                 resid->Ro->data.F32[oy][ox] = B->data.F64[0];
    371                 resid->Rx->data.F32[oy][ox] = B->data.F64[1];
    372                 resid->Ry->data.F32[oy][ox] = B->data.F64[2];
    373 
    374                 float dRo = sqrt(A->data.F32[0][0]);
    375 
    376                 if (fabs(B->data.F64[0]) > 1.5) {
    377                   fprintf (stderr, "warning: %d, %d : residual pixel has funny fit value: %f\n", ox, oy, B->data.F64[0]);
     354                // we have the following vectors to describe this pixel:
     355                // fluxes, dfluxes, fmasks, xC, yC
     356
     357                psVectorIRLSFitPolynomial2D (polyIRLS, statsIRLS, fmasks, fmaskVal, fluxes, dfluxes, xC, yC);
     358
     359                resid->Ro->data.F32[oy][ox] = polyIRLS->coeff[0][0];
     360                resid->Rx->data.F32[oy][ox] = polyIRLS->coeff[1][0];
     361                resid->Ry->data.F32[oy][ox] = polyIRLS->coeff[0][1];
     362
     363                // is the error well-defined?
     364                float dRo = polyIRLS->coeffErr[0][0];
     365
     366                if (fabs(resid->Ro->data.F32[oy][ox]) > 1.5) {
     367                  fprintf (stderr, "warning: %d, %d : residual pixel has funny fit value: %f\n", ox, oy, resid->Ro->data.F32[oy][ox]);
    378368                }
    379369
     
    442432    psFree (fluxStats);
    443433    psFree (fluxStatsDef);
    444     psFree (fluxClip);
    445     psFree (fluxClipDef);
    446434
    447435    if (resid != NULL && psTraceGetLevel("psphot") > 5) {
     
    453441    }
    454442
     443    psFree (statsIRLS);
     444    psFree (polyIRLS);
     445
    455446    psf->residuals = resid;
    456447    return (resid != NULL) ? true : false;
Note: See TracChangeset for help on using the changeset viewer.