IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Nov 4, 2021, 6:05:18 PM (5 years ago)
Author:
eugene
Message:

merge changes from eam_branches/ipp-dev-20210817 (pmPattern updates, new inverse transform extra orders api, forward transform uses ORD, pmSourceIO_CMF.c.in conversion to pmFitsTableNew)

Location:
trunk/psModules
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules

  • trunk/psModules/src/astrom/pmAstrometryObjects.c

    r41493 r41892  
    4040// XXX this is defined in pmPSFtry.h, which makes no sense
    4141float psVectorSystematicError (psVector *residuals, psVector *errors, float clipFraction);
     42float pmAstrom2DSystematics (psVector *xPos, psVector *yPos, psVector *value);
    4243
    4344#define PM_ASTROMETRYOBJECTS_DEBUG 1
     
    339340    psVector *yResGood = psVectorAllocEmpty (match->n, PS_TYPE_F32);
    340341
     342    // we measure the stdev of the median residual in NxN bins.
     343    // use only valid (not NAN) measurements
     344    psVector *xPosValid = psVectorAllocEmpty (match->n, PS_TYPE_F32);
     345    psVector *yPosValid = psVectorAllocEmpty (match->n, PS_TYPE_F32);
     346    psVector *xResValid = psVectorAllocEmpty (match->n, PS_TYPE_F32);
     347    psVector *yResValid = psVectorAllocEmpty (match->n, PS_TYPE_F32);
     348
    341349    for (int i = 0; i < match->n; i++) {
    342350        if (mask->data.PS_TYPE_VECTOR_MASK_DATA[i]) continue;
     
    344352        pmAstromObj *rawStar = raw->data[pair->raw];
    345353        if (!isfinite(rawStar->dMag)) continue;
     354
     355        bool isValid = true;
     356        isValid = isValid & isfinite (x->data.F32[i]);
     357        isValid = isValid & isfinite (y->data.F32[i]);
     358        isValid = isValid & isfinite (xRes->data.F32[i]);
     359        isValid = isValid & isfinite (yRes->data.F32[i]);
     360        if (isValid) {
     361          psVectorAppend (xPosValid, x->data.F32[i]);
     362          psVectorAppend (yPosValid, y->data.F32[i]);
     363          psVectorAppend (xResValid, xRes->data.F32[i]);
     364          psVectorAppend (yResValid, yRes->data.F32[i]);
     365        }
     366
     367        // for the systematic error, use only high S/N stars
    346368        if (rawStar->dMag > 0.02) continue;
    347369
     
    369391      results->dXsys   = results->dYsys   = NAN;
    370392      results->dXrange = results->dYrange = NAN;
     393      results->dXstdev = results->dYstdev = NAN;
    371394    } else {
    372395      results->dXsys = psVectorSystematicError (xResGood, xErr, 0.05);
     
    375398      results->dXrange = pmAstromVectorRange (xResGood, 0.1, 0.9, results->xStats->clippedStdev);
    376399      results->dYrange = pmAstromVectorRange (yResGood, 0.1, 0.9, results->yStats->clippedStdev);
    377     }
    378 
    379     psTrace ("psModules.astrom", 3, "dXsys: %f, dXrange: %f\n", results->dXsys, results->dXrange);
    380     psTrace ("psModules.astrom", 3, "dYsys: %f, dYrange: %f\n", results->dYsys, results->dYrange);
     400
     401      results->dXstdev = pmAstrom2DSystematics (xPosValid, yPosValid, xResValid);
     402      results->dYstdev = pmAstrom2DSystematics (xPosValid, yPosValid, yResValid);
     403    }
     404
     405    psTrace ("psModules.astrom", 3, "dXsys: %f, dXrange: %f, dXstdev: %f\n", results->dXsys, results->dXrange, results->dXstdev);
     406    psTrace ("psModules.astrom", 3, "dYsys: %f, dYrange: %f, dYstdev: %f\n", results->dYsys, results->dYrange, results->dYstdev);
    381407
    382408    psFree (xErr);
     
    386412    psFree (xResGood);
    387413    psFree (yResGood);
     414    psFree (xPosValid);
     415    psFree (yPosValid);
     416    psFree (xResValid);
     417    psFree (yResValid);
    388418
    389419    psFree (x);
     
    395425
    396426    return (results);
     427}
     428
     429# define VAL_COUNT 9.0
     430# define MIN_COUNT 5.0
     431
     432float pmAstrom2DSystematics (psVector *xPos, psVector *yPos, psVector *value) {
     433
     434    // pre-filter the values to ensure no NANs, other invalid
     435    if (xPos->n < VAL_COUNT*2*2) {
     436      return NAN;
     437    }
     438
     439    // generate a grid covering the full range of x,y and measure the median value in each
     440    // grid cell.  calculate the stdev of those median values.
     441
     442    // VAL_COUNT (9) is the (min) goal density, but a single cell may have only MIN_COUNT (7)
     443    // we have N points.  require a min of 9 pts per cell (configurable?).  grid is square.
     444    // Ncell*Ncell*9 = Npts, Ncell = MIN(sqrt(Npts/9), 5)
     445
     446    int Ncell = PS_MIN(sqrt((float)(xPos->n / VAL_COUNT)), 2);  // have to at least have a 2x2 grid
     447
     448    // find the range of x,y values
     449    float xMin = 1e9, xMax = -1e9, yMin = 1e9, yMax = 1e9;
     450    for (int i = 0; i < xPos->n; i++) {
     451        xMin = PS_MIN(xPos->data.F32[i],xMin);
     452        xMax = PS_MAX(xPos->data.F32[i],xMax);
     453        yMin = PS_MIN(yPos->data.F32[i],yMin);
     454        yMax = PS_MAX(yPos->data.F32[i],yMax);
     455    }
     456
     457    float xStep = Ncell / (xMax - xMin);
     458    float yStep = Ncell / (yMax - yMin);
     459 
     460    if (isnan(xStep)) {
     461      return NAN;
     462    }
     463    if (isnan(yStep)) {
     464      return NAN;
     465    }
     466
     467    psArray *xBin = psArrayAlloc (Ncell);
     468    for (int ix = 0; ix < Ncell; ix++) {
     469        psArray *yBin = psArrayAlloc (Ncell);
     470        xBin->data[ix] = yBin;
     471        for (int iy = 0; iy < Ncell; iy++) {
     472            yBin->data[iy] = psVectorAllocEmpty(128, PS_TYPE_F32);
     473        }
     474    }   
     475
     476    // xValue = ix/xStep + xMin -> ix = (xValue - xMin) * xStep;
     477
     478    for (int i = 0; i < xPos->n; i++) {
     479        int ix = PS_MIN(PS_MAX(0, (xPos->data.F32[i] - xMin) * xStep), Ncell - 1);
     480        int iy = PS_MIN(PS_MAX(0, (yPos->data.F32[i] - yMin) * yStep), Ncell - 1);
     481   
     482        psArray *yBin = xBin->data[ix];
     483        psVector *Bin = yBin->data[iy];
     484
     485        psVectorAppend(Bin, value->data.F32[i]);
     486    }
     487
     488    psVector *sample = psVectorAllocEmpty (Ncell*Ncell, PS_TYPE_F32);
     489    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
     490
     491    // calculate the median for each vector and save on a vector
     492    for (int ix = 0; ix < Ncell; ix++) {
     493        psArray *yBin = xBin->data[ix];
     494        for (int iy = 0; iy < Ncell; iy++) {
     495            psVector *Bin = yBin->data[iy];
     496            if (Bin->n < MIN_COUNT) { continue; }
     497
     498            // psVectorStats resets stats so we can call this repeatedly
     499            psVectorStats (stats, Bin, NULL, NULL, 0);
     500            if (isfinite(stats->sampleMedian)) {
     501                psVectorAppend (sample, stats->sampleMedian);
     502            }
     503        }
     504    }   
     505 
     506    stats->options = PS_STAT_SAMPLE_STDEV;
     507    psVectorStats (stats, sample, NULL, NULL, 0);
     508    float result = stats->sampleStdev;
     509
     510    if (!isfinite(stats->sampleStdev)) {
     511      fprintf (stderr, "*** bad solution ***\n");
     512    }
     513
     514    // NOTE: the elements of xBin are freed automatically, which extends down to the vectors
     515    psFree (xBin);
     516    psFree (stats);
     517    psFree (sample);
     518 
     519    return result;
    397520}
    398521
Note: See TracChangeset for help on using the changeset viewer.