IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 37827


Ignore:
Timestamp:
Jan 12, 2015, 12:35:53 PM (12 years ago)
Author:
eugene
Message:

merge changes from trunk

Location:
branches/eam_branches/ipp-pv3-20140717-merge/psLib
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-pv3-20140717-merge/psLib/share/tai_utc.dat

    r34664 r37827  
    5151        2453736.5     33.0000000    41317.0     0.0000000
    5252        2454832.5     34.0000000    41317.0     0.0000000
    53         2456109.5     35.0000000    41317.0     0.0000000
     53        2456109.5     35.0000000    41317.0     0.0000000
     54        2457204.5     36.0000000    41317.0     0.0000000
  • branches/eam_branches/ipp-pv3-20140717-merge/psLib/share/tai_utc.raw

    r34664 r37827  
    3838 2009 JAN  1 =JD 2454832.5  TAI-UTC=  34.0       S + (MJD - 41317.) X 0.0      S
    3939 2012 JUL  1 =JD 2456109.5  TAI-UTC=  35.0       S + (MJD - 41317.) X 0.0      S
     40 2015 JUL  1 =JD 2457204.5  TAI-UTC=  36.0       S + (MJD - 41317.) X 0.0      S
  • branches/eam_branches/ipp-pv3-20140717-merge/psLib/src/imageops/psImageMapFit.c

    r34153 r37827  
    1818
    1919#include <stdio.h>
     20#include <stdlib.h>
    2021#include "psError.h"
    2122#include "psAbort.h"
     
    3536#include "psImageStructManip.h"
    3637#include "psImageMap.h"
     38#include "psSparse.h"
    3739// #include "psImagePixelInterpolate.h"
    3840// #include "psImageUnbin.h"
     
    118120    psImageInit (A, 0.0);
    119121    psVectorInit (B, 0.0);
    120 
     122   
    121123    // we are looping over the Nx,Ny image map elements;
    122124    // the matrix equation contains Nx*Ny rows and columns
     
    262264            int I = n + Nx * m;
    263265            B->data.F32[I] = fi_rx_ry + fi_rx_py + fi_px_ry + fi_px_py;
    264 
     266           
    265267            // insert these values into their corresponding locations in A, B
    266268            // float Sum = 0.0;
     
    273275                    int J = (n + jn) + Nx * (m + jm);
    274276                    A->data.F32[J][I] = sA[jn][jm];
     277                   
    275278                    // fprintf (stderr, "A %d %d (%d %d : %d %d): %f\n", I, J, n, m, n + jn, m + jm, sA[jn][jm]);
    276279                    // Sum += sA[jn][jm];
     
    282285    }
    283286    // fprintf (stderr, "Total: %f\n", Total);
     287
     288    double MaxPivot = 0.0;
     289    for (int i = 0; i < Nx*Ny; i++) {
     290      MaxPivot = PS_MAX(MaxPivot, fabs(A->data.F32[i][i]));
     291      // fprintf (stderr, "piv, max: %f : %f\n", A->data.F32[i][i], MaxPivot);
     292    }
    284293
    285294    // test for empty diagonal elements (unconstained cells), mark, and set pivots to 1.0
    286295    psVector *Empty = psVectorAlloc (Nx*Ny, PS_TYPE_S8);
    287296    psVectorInit (Empty, 0);
     297    double MinPivot = 0.025*MaxPivot;
    288298    for (int i = 0; i < Nx*Ny; i++) {
    289         if (A->data.F32[i][i] == 0.0) {
     299      if (fabs(A->data.F32[i][i]) < MinPivot) {
    290300            Empty->data.S8[i] = 1;
    291301            for (int j = 0; j < Nx*Ny; j++) {
     
    320330        return true;
    321331    }
    322 
     332   
    323333    // set bad values to NaN
    324334    for (int i = 0; i < Nx*Ny; i++) {
     
    341351    psFree (B);
    342352    psFree (Empty);
    343 
    344353    *pGoodFit = true;
    345354    return true;
     
    402411        psS32 Nkeep = 0;
    403412        if (!psImageMapFit(pGoodFit, map, mask, maskValue, x, y, f, df)) {
     413            psError(PS_ERR_UNKNOWN, false, "Could not fit image map.\n");
     414            psFree(resid);
     415            if (!inMask) psFree (mask);
     416            return false;
     417        }
     418        if (!*pGoodFit) {
     419            psWarning ("bad fit to image map, try something else");
     420            psFree(resid);
     421            if (!inMask) psFree (mask);
     422            return true;
     423        }
     424
     425        psVector *fit = psImageMapEvalVector(map, mask, maskValue, x, y);
     426        if (fit == NULL) {
     427            psError(PS_ERR_UNKNOWN, false, "Failure in psImageMapEvalVector().\n");
     428            psFree(resid);
     429            if (!inMask) psFree (mask);
     430            return false;
     431        }
     432        for (int i = 0 ; i < f->n ; i++) {
     433            resid->data.F32[i] = (f->data.F32[i] - fit->data.F32[i]);
     434        }
     435
     436        if (!psVectorStats(stats, resid, NULL, mask, maskValue)) {
     437            psError(PS_ERR_UNKNOWN, false, "Failure to compute statistics on the resid vector.\n");
     438            psFree(resid);
     439            psFree(fit);
     440            if (!inMask) psFree (mask);
     441            return false;
     442        }
     443
     444        double meanValue = psStatsGetValue (stats, meanOption);
     445        double stdevValue = psStatsGetValue (stats, stdevOption);
     446
     447        psTrace("psLib.imageops", 5, "Mean is %f\n", meanValue);
     448        psTrace("psLib.imageops", 5, "Stdev is %f\n", stdevValue);
     449        psF32 minClipValue = -minClipSigma*stdevValue;
     450        psF32 maxClipValue = +maxClipSigma*stdevValue;
     451
     452        // set mask if pts are not valid
     453        // we are masking out any point which is out of range
     454        // recovery is not allowed with this scheme
     455        for (psS32 i = 0; i < resid->n; i++) {
     456            // XXX this prevents recovery of previously masked values
     457            if (mask->data.PS_TYPE_VECTOR_MASK_DATA[i] & maskValue) {
     458                continue;
     459            }
     460
     461            if ((resid->data.F32[i] - meanValue > maxClipValue) || (resid->data.F32[i] - meanValue < minClipValue)) {
     462                psTrace("psLib.imageops", 6, "Masking element %d  : %f vs %f : resid is %f\n", i, f->data.F32[i], fit->data.F32[i], resid->data.F32[i]);
     463                mask->data.PS_TYPE_VECTOR_MASK_DATA[i] |= 0x01;
     464                continue;
     465            }
     466            Nkeep++;
     467        }
     468
     469        // We should probably exit this loop if no new elements were masked since the fit won't
     470        // change.
     471        psTrace("psLib.imageops", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
     472        stats->clippedNvalues = Nkeep;
     473        psFree(fit);
     474    }
     475
     476    // Free local temporary variables
     477    psFree(resid);
     478    if (!inMask) psFree (mask);
     479    *pGoodFit = true; // XXX probably don't need to set this (set by psImageMapFit)
     480    return true;
     481}
     482
     483// CZW: 2014-10-09
     484// Sparse versions of MapFit and MapFitClip that assume the matrices are not filled.
     485bool psImageMapFitSparse(bool *pGoodFit, psImageMap *map, const psVector *mask, psVectorMaskType maskValue,
     486                   const psVector *x, const psVector *y, const psVector *f, const psVector *df)
     487{
     488    // XXX Add Asserts
     489
     490    *pGoodFit = false;
     491
     492    // dimensions of the output map image
     493    int Nx = map->binning->nXruff;
     494    int Ny = map->binning->nYruff;
     495
     496   
     497    // no spatial information, just calculate mean & stdev
     498    if ((Nx == 1) && (Ny == 1)) {
     499        psStatsInit(map->stats);
     500
     501        // the user has supplied one of various stats option pairs,
     502        psStatsOptions mean = psStatsMeanOption(map->stats->options);
     503        psStatsOptions stdev = psStatsStdevOption(map->stats->options);
     504        if (!psStatsSingleOption(mean)) {
     505            psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
     506            return false;
     507        }
     508        if (!psStatsSingleOption(stdev)) {
     509            psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
     510            return false;
     511        }
     512
     513        // XXX does ROBUST_MEDIAN work with weight?
     514        if (!psVectorStats(map->stats, f, NULL, mask, maskValue)) {
     515            psError(PS_ERR_UNKNOWN, false, "failure to measure stats");
     516            return false;
     517        }
     518
     519        map->map->data.F32[0][0]   = psStatsGetValue(map->stats, mean);
     520        map->error->data.F32[0][0] = psStatsGetValue(map->stats, stdev);
     521        if (isfinite(map->map->data.F32[0][0]) && isfinite( map->error->data.F32[0][0])) {
     522            *pGoodFit = true;
     523        }
     524        return true;
     525    }
     526
     527    if (Nx == 1) {
     528        bool status;
     529        status = psImageMapFit1DinY (pGoodFit, map, mask, maskValue, x, y, f, df);
     530        return status;
     531    }
     532    if (Ny == 1) {
     533        bool status;
     534        status = psImageMapFit1DinX (pGoodFit, map, mask, maskValue, x, y, f, df);
     535        return status;
     536    }
     537
     538    // set up the redirection table so we can use sA[-1][-1], etc
     539    // XXX psKernel does this for you --- PAP.
     540    float SAm[3][3], *SAv[3], **sA;
     541
     542    for (int i = 0; i < 3; i++) {
     543        SAv[i] = SAm[i] + 1;
     544    }
     545    sA = SAv + 1;
     546
     547    // elements of the matrix equation Ax = B; we are solving for the vector x
     548    // psImage *A = psImageAlloc (Nx*Ny, Nx*Ny, PS_TYPE_F32);
     549    // psVector *B = psVectorAlloc (Nx*Ny, PS_TYPE_F32);
     550
     551    // psImageInit (A, 0.0);
     552    // psVectorInit (B, 0.0);
     553
     554    // CZW: call to psSparseAlloc
     555    // It should match old A, and each element of that should only touch four others.
     556    psSparse *Asparse = psSparseAlloc(Nx * Ny, 4 * Nx * Ny);
     557   
     558    // we are looping over the Nx,Ny image map elements;
     559    // the matrix equation contains Nx*Ny rows and columns
     560
     561    for (int n = 0; n < Nx; n++) {
     562        for (int m = 0; m < Ny; m++) {
     563            // define & init summing variables
     564            float rx_rx_ry_ry = 0;
     565            float rx_rx_dy_ry = 0;
     566            float dx_rx_ry_ry = 0;
     567            float dx_rx_dy_ry = 0;
     568            float fi_rx_ry    = 0;
     569            float rx_rx_py_py = 0;
     570            float rx_rx_qy_py = 0;
     571            float dx_rx_py_py = 0;
     572            float dx_rx_qy_py = 0;
     573            float fi_rx_py    = 0;
     574            float px_px_ry_ry = 0;
     575            float px_px_dy_ry = 0;
     576            float qx_px_ry_ry = 0;
     577            float qx_px_dy_ry = 0;
     578            float fi_px_ry    = 0;
     579            float px_px_py_py = 0;
     580            float px_px_qy_py = 0;
     581            float qx_px_py_py = 0;
     582            float qx_px_qy_py = 0;
     583            float fi_px_py    = 0;
     584
     585            // generate the sums for the fitting matrix element I,J
     586            // I = n + nX*m
     587            // J = (n + jn) + nX*(m + jm)
     588            for (int i = 0; i < x->n; i++) {
     589
     590                if (mask && (mask->data.PS_TYPE_VECTOR_MASK_DATA[i] & maskValue)) continue;
     591
     592                // base coordinate offset for this point (x,y) relative to this map element (n,m)
     593                float dx = psImageBinningGetRuffX (map->binning, x->data.F32[i]) - (n + 0.5);
     594                float dy = psImageBinningGetRuffY (map->binning, y->data.F32[i]) - (m + 0.5);
     595
     596                // edge cases to include:
     597                bool edgeX = false;
     598                edgeX |= ((n == 1) && (dx < -1.0));
     599                edgeX |= ((n == Nx - 2) && (dx > +1.0));
     600
     601                bool edgeY = false;
     602                edgeY |= ((m == 1) && (dy < -1.0));
     603                edgeY |= ((m == Ny - 2) && (dy > +1.0));
     604
     605                // skip points outside of 2x2 grid centered on n,m:
     606                if (!edgeX && (fabs(dx) > 1.0)) continue;
     607                if (!edgeY && (fabs(dy) > 1.0)) continue;
     608
     609                // related offset values
     610                float rx = 1.0 - dx;
     611                float ry = 1.0 - dy;
     612                float px = 1.0 + dx;
     613                float py = 1.0 + dy;
     614                float qx = -dx;
     615                float qy = -dy;
     616
     617                // data value & weight for this point
     618                float fi = f->data.F32[i];
     619                if (!isfinite(fi)) continue;
     620
     621                float wt = 1.0;
     622                if (df != NULL) {
     623                    if (df->data.F32[i] == 0.0) {
     624                        wt = 0.0;
     625                    } else {
     626                        if (!isfinite(df->data.F32[i])) continue;
     627                        wt = 1.0 / PS_SQR(df->data.F32[i]); // XXX test for dz == NULL or dz_i = 0
     628                    }
     629                }
     630
     631                // sum the appropriate elements for the different quadrants
     632
     633                int Qx = (dx >= 0) ? 1 : 0;
     634                if (n ==      0) Qx = 1;
     635                if (n == Nx - 1) Qx = 0;
     636
     637                int Qy = (dy >= 0) ? 1 : 0;
     638                if (m ==      0) Qy = 1;
     639                if (m == Ny - 1) Qy = 0;
     640
     641                assert (isfinite(fi));
     642                assert (isfinite(wt));
     643                assert (isfinite(rx));
     644                assert (isfinite(ry));
     645
     646                // points at offset 1,1
     647                if ((Qx == 1) && (Qy == 1)) {
     648                    rx_rx_ry_ry += rx*rx*ry*ry*wt;
     649                    rx_rx_dy_ry += rx*rx*dy*ry*wt;
     650                    dx_rx_ry_ry += dx*rx*ry*ry*wt;
     651                    dx_rx_dy_ry += dx*rx*dy*ry*wt;
     652                    fi_rx_ry    += fi*rx*ry*wt;
     653                }
     654                // points at offset 1,0
     655                if ((Qx == 1) && (Qy == 0)) {
     656                    rx_rx_py_py += rx*rx*py*py*wt;
     657                    rx_rx_qy_py += rx*rx*qy*py*wt;
     658                    dx_rx_py_py += dx*rx*py*py*wt;
     659                    dx_rx_qy_py += dx*rx*qy*py*wt;
     660                    fi_rx_py    += fi*rx*py*wt;
     661                }
     662                // points at offset 0,1
     663                if ((Qx == 0) && (Qy == 1)) {
     664                    px_px_ry_ry += px*px*ry*ry*wt;
     665                    px_px_dy_ry += px*px*dy*ry*wt;
     666                    qx_px_ry_ry += qx*px*ry*ry*wt;
     667                    qx_px_dy_ry += qx*px*dy*ry*wt;
     668                    fi_px_ry    += fi*px*ry*wt;
     669                }
     670                // points at offset 0,0
     671                if ((Qx == 0) && (Qy == 0)) {
     672                    px_px_py_py += px*px*py*py*wt;
     673                    px_px_qy_py += px*px*qy*py*wt;
     674                    qx_px_py_py += qx*px*py*py*wt;
     675                    qx_px_qy_py += qx*px*qy*py*wt;
     676                    fi_px_py    += fi*px*py*wt;
     677                }
     678            }
     679
     680            // the chi-square derivatives have elements of the form g(n+jn,m+jm)*A(jn,jm),
     681            // jn,jm = -1 to +1. Convert the sums above into the correct coefficients
     682            sA[-1][-1] = qx_px_qy_py;
     683            sA[-1][ 0] = qx_px_ry_ry + qx_px_py_py;
     684            sA[-1][+1] = qx_px_dy_ry;
     685            sA[ 0][-1] = rx_rx_qy_py + px_px_qy_py;
     686            sA[ 0][ 0] = rx_rx_ry_ry + px_px_ry_ry + rx_rx_py_py + px_px_py_py;
     687            sA[ 0][+1] = rx_rx_dy_ry + px_px_dy_ry;
     688            sA[+1][-1] = dx_rx_qy_py;
     689            sA[+1][ 0] = dx_rx_ry_ry + dx_rx_py_py;
     690            sA[+1][+1] = dx_rx_dy_ry;
     691
     692            // I[ 0][ 0] = index for this n,m element:
     693            int I = n + Nx * m;
     694            //            B->data.F32[I] = fi_rx_ry + fi_rx_py + fi_px_ry + fi_px_py;
     695            // CZW: call to psSparseVector Element
     696            if (fi_rx_ry + fi_rx_py + fi_px_ry + fi_px_py == 0.0) {
     697              psSparseVectorElement(Asparse, I, 1.0);
     698            }
     699            else {
     700              psSparseVectorElement(Asparse, I, fi_rx_ry + fi_rx_py + fi_px_ry + fi_px_py);
     701            }
     702           
     703            //      printf("ADDING: %d %g \n",I, fi_rx_ry + fi_rx_py + fi_px_ry + fi_px_py);
     704            // insert these values into their corresponding locations in A, B
     705            for (int jn = -1; jn <= +1; jn++) {
     706                if (n + jn <   0) continue;
     707                if (n + jn >= Nx) continue;
     708                for (int jm = -1; jm <= +1; jm++) {
     709                    if (m + jm <   0) continue;
     710                    if (m + jm >= Ny) continue;
     711                    int J = (n + jn) + Nx * (m + jm);
     712                    //              printf("A: %d %d %g\n",J,I,sA[jn][jm]);
     713                    // A->data.F32[J][I] = sA[jn][jm];
     714                    // CZW: call to psSparseMatrixElement
     715                    if (J < I) { continue; }
     716                    psSparseMatrixElement(Asparse,J,I,sA[jn][jm]); // Ensure J < I?
     717                   
     718                }
     719            }
     720        }
     721    }
     722
     723    // test for empty diagonal elements (unconstained cells), mark, and set pivots to 1.0
     724    // CZW: I'm not totally sure how to check these in the sparse context.
     725    // Iterate over all ii pairs, and manually check the structure?
     726#if (0)
     727    psVector *Empty = psVectorAlloc (Nx*Ny, PS_TYPE_S8);
     728    psVectorInit (Empty, 0);
     729    for (int i = 0; i < Nx*Ny; i++) {
     730        if (A->data.F32[i][i] == 0.0) {
     731            Empty->data.S8[i] = 1;
     732            for (int j = 0; j < Nx*Ny; j++) {
     733                A->data.F32[i][j] = 0.0;
     734                A->data.F32[j][i] = 0.0;
     735            }
     736            A->data.F32[i][i] = 1.0;
     737            B->data.F32[i] = 0.0;
     738        }
     739    }
     740#endif
     741
     742    // CZW: call to psSparseSolve
     743    psVector *solution = psVectorAlloc(Nx*Ny, PS_TYPE_F32);
     744    psSparseConstraint Constraint;
     745    Constraint.paramDelta = 1e-3;
     746    Constraint.paramMin   = -1e5;
     747    Constraint.paramMax   = 1e5;
     748    solution = psSparseSolve(solution, Constraint, Asparse, 1000);
     749    if (!solution) {
     750      psFree(solution);
     751      psFree(Asparse);
     752      return(false);
     753    }
     754
     755#if (0)
     756    // CZW: This is a continuation of the above information
     757    // set bad values to NaN
     758    for (int i = 0; i < Nx*Ny; i++) {
     759        if (Empty->data.S8[i]) {
     760            B->data.F32[i] = NAN;
     761            A->data.F32[i][i] = 0;
     762        }
     763    }
     764#endif
     765
     766    for (int n = 0; n < Nx; n++) {
     767        for (int m = 0; m < Ny; m++) {
     768            int I = n + Nx * m;
     769            map->map->data.F32[m][n] = solution->data.F32[I];
     770            map->error->data.F32[m][n] = NAN; // sqrt(A->data.F32[I][I]); // CZW: fix this to be a real error.
     771        }
     772    }
     773
     774    //    psFree (A);
     775    //    psFree (B);
     776    //    psFree (Empty);
     777    // CZW: free things
     778    psFree(solution);
     779    psFree(Asparse);
     780   
     781    *pGoodFit = true;
     782    return true;
     783}
     784
     785// measure residuals on each pass and clip outliers based on stats
     786bool psImageMapClipFitSparse(bool *pGoodFit, psImageMap *map, psStats *stats, psVector *inMask, psVectorMaskType maskValue,
     787                             const psVector *x, const psVector *y, const psVector *f, const psVector *df)
     788{
     789    // XXX add in full PS_ASSERTS
     790    psAssert(map, "impossible");
     791    psAssert(stats, "impossible");
     792    psAssert(x, "impossible");
     793    psAssert(y, "impossible");
     794    psAssert(f, "impossible");
     795
     796    *pGoodFit = false;
     797
     798    // the user supplies one of various stats option pairs,
     799    // determine the desired mean and stdev STATS options:
     800    psStatsOptions meanOption = psStatsMeanOption(stats->options);
     801    psStatsOptions stdevOption = psStatsStdevOption(stats->options);
     802    if (!psStatsSingleOption(meanOption)) {
     803        psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
     804        return false;
     805    }
     806    if (!psStatsSingleOption(stdevOption)) {
     807        psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
     808        return false;
     809    }
     810
     811    // clipping range defined by min and max and/or clipSigma
     812    psF32 minClipSigma;
     813    psF32 maxClipSigma;
     814    if (isfinite(stats->max)) {
     815        maxClipSigma = fabs(stats->max);
     816    } else {
     817        maxClipSigma = fabs(stats->clipSigma);
     818    }
     819    if (isfinite(stats->min)) {
     820        minClipSigma = fabs(stats->min);
     821    } else {
     822        minClipSigma = fabs(stats->clipSigma);
     823    }
     824
     825    psVector *mask = inMask;
     826    if (!inMask) {
     827        mask = psVectorAlloc (x->n, PS_TYPE_VECTOR_MASK);
     828        psVectorInit (mask, 0);
     829    }
     830
     831    // vector to store residuals
     832    psVector *resid = psVectorAlloc(f->n, PS_TYPE_F32);
     833
     834    psTrace("psLib.imageops", 4, "stats->clipIter is %d\n", stats->clipIter);
     835    psTrace("psLib.imageops", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma);
     836
     837    for (psS32 N = 0; N < stats->clipIter; N++) {
     838        psTrace("psLib.imageops", 6, "Loop iteration %d.  Calling psImageMapFit()\n", N);
     839        psS32 Nkeep = 0;
     840        if (!psImageMapFitSparse(pGoodFit, map, mask, maskValue, x, y, f, df)) {
    404841            psError(PS_ERR_UNKNOWN, false, "Could not fit image map.\n");
    405842            psFree(resid);
  • branches/eam_branches/ipp-pv3-20140717-merge/psLib/src/imageops/psImageMapFit.h

    r30044 r37827  
    2020// fit the image map to a set of points
    2121bool psImageMapClipFit(bool *pGoodFit,
     22                       psImageMap *map,
     23                       psStats *stats,
     24                       psVector *mask,  // WARNING: Mask is modified!
     25                       psVectorMaskType maskValue,
     26                       const psVector *x,
     27                       const psVector *y,
     28                       const psVector *f,
     29                       const psVector *df
     30    );
     31
     32
     33// fit the image map to a set of points, using sparse matrix tools
     34bool psImageMapFitSparse(bool *pGoodFit,
     35                   psImageMap *map,
     36                   const psVector *mask,
     37                   psVectorMaskType maskValue, //
     38                   const psVector *x,
     39                   const psVector *y,
     40                   const psVector *f,
     41                   const psVector *df
     42    );
     43
     44// fit the image map to a set of points using sparse matrix tools
     45bool psImageMapClipFitSparse(bool *pGoodFit,
    2246                       psImageMap *map,
    2347                       psStats *stats,
  • branches/eam_branches/ipp-pv3-20140717-merge/psLib/src/math/psEllipse.c

    r36375 r37827  
    134134    assert (isfinite(axes.major));
    135135    assert (isfinite(axes.minor));
     136
     137    return axes;
     138}
     139// ellipse derotation (sx, sy, sxy) -> (major, minor, theta)
     140psEllipseAxes psEllipseShapeToAxesWithErrors(psEllipseShape shape, psEllipseShape shapeErrors, double maxAR, psEllipseAxes *pShapeErrors)
     141{
     142    psEllipseAxes axes;
     143    psEllipseAxes errors;
     144
     145    double f1 = 1.0 / PS_SQR(shape.sy) + 1.0 / PS_SQR(shape.sx);
     146    double f2 = 1.0 / PS_SQR(shape.sy) - 1.0 / PS_SQR(shape.sx);
     147
     148    double f32 = PS_SQR(f2) + 4*PS_SQR(shape.sxy);
     149    double f3 = sqrt(f32);
     150
     151    double df1 = - 2.0 * shapeErrors.sy / (PS_SQR(shape.sy) * shape.sy)
     152                 - 2.0 * shapeErrors.sx / (PS_SQR(shape.sx) * shape.sx);
     153    double df2 = - 2.0 * shapeErrors.sy / (PS_SQR(shape.sy) * shape.sy)
     154                 + 2.0 * shapeErrors.sx / (PS_SQR(shape.sx) * shape.sx);
     155
     156    // df3 = 0.5 * df32 / sqrt(f32) = 0.5 * df32 / f3
     157    double df3 = 0.5 * (2.0*f2*df2 + 2 * 4 * shape.sxy * shapeErrors.sxy) / f3;
     158
     159    double f13 = f1 + f3;
     160    axes.minor = sqrt (2.0 / f13);
     161
     162    // dminor = -0.5 * sqrt (2) * df13 * f13**-3/2  = - 0.5 * df13 * minor / f13
     163    errors.minor = - 0.5 * (df1 + df3) * axes.minor / f13;
     164
     165    axes.theta = -0.5 * atan2 (+2.0*shape.sxy, f2);
     166
     167    // according to wikipedia the derivitive of atan2(y, x) is
     168    //
     169    //  dAtan2(y, x) = - y * dx / (x**2 + y**2)) + x * dy / (x**2 + y**2) (for x > 0 and y!=0)
     170    //  where
     171    //  y = 2 * sxy  dy = 2 * dsxy   x = f2 so dx = df2
     172
     173    // dtheta = -0.5 * dAtan2(y, x)
     174
     175    errors.theta = -0.5 * ( -2.0 * shape.sxy * df2  +  f2 * 2 *shapeErrors.sxy ) /
     176                            (PS_SQR(f2) + 4 * PS_SQR(shape.sxy)) ;
     177
     178    // long, thin objects are likely to have a poorly measured major axis
     179    // the angle and minor axis are likely to be ok.
     180    // restrict the axis ratio
     181    double rAR2 = (f1 - f3) / (f1 + f3);
     182    if (rAR2 < 1.0/PS_SQR(maxAR)) {
     183        axes.major = axes.minor * maxAR;
     184        errors.major = errors.minor * maxAR;
     185    } else {
     186        axes.major = sqrt (2.0 / (f1 - f3));
     187
     188        // dmajor = -0.5 * (df1 - df3) * sqrt(2) * (f1 - f3)**-3/2
     189        //        = -0.5 * (df2 - df3) * major / (f1 - f3)
     190        errors.major = -0.5 * axes.major * (df1 - df3) / (f1 - f3);
     191    }
     192
     193    assert (isfinite(axes.theta));
     194    assert (isfinite(axes.major));
     195    assert (isfinite(axes.minor));
     196
     197    *pShapeErrors = errors;
    136198
    137199    return axes;
  • branches/eam_branches/ipp-pv3-20140717-merge/psLib/src/math/psEllipse.h

    r36375 r37827  
    6565                                   );
    6666
     67/// Convert shape to axes representation and compute errors
     68psEllipseAxes psEllipseShapeToAxesWithErrors(psEllipseShape shape, ///< Shape of ellipse
     69                                   psEllipseShape errors, ///<errors on shape params
     70                                   double maxAR, ///< Maximum allowed axis ratio
     71                                   psEllipseAxes *pShapeErrors ///< propagated errors on axes
     72                                   );
     73
    6774/// Convert axes to polarization representation
    6875psEllipsePol psEllipseAxesToPol(psEllipseAxes axes ///< Axes of ellipse
  • branches/eam_branches/ipp-pv3-20140717-merge/psLib/src/math/psMinimizePolyFit.c

    r36296 r37827  
    700700
    701701    // Define values that may be used by PS_POLYNOMIAL_ORD form.
     702    // these scaling values put the dynamic range of the data into some vaguely sensible location
    702703    bool scale = false;
     704    bool median_zero = false;
    703705    double median = 0.0;
    704706    double sigma = 1.0;
    705     psVector *sorted = NULL;
    706     psVector *z64 = NULL;
    707    
     707
    708708    switch (poly->type) {
    709709    case PS_POLYNOMIAL_ORD:
    710710      if ((f64->n < 10000)&&(poly->nX > 1)) {
    711711        scale = true;
    712         sorted = psVectorSort(NULL,x64);
     712
     713        // generate a subset of the unmasked values:
     714        psVector *tmp = psVectorAllocEmpty (x64->n, PS_TYPE_F64);
     715        for (int itmp = 0; itmp < x64->n; itmp++) {
     716          if (mask && (mask->data.PS_TYPE_VECTOR_MASK_DATA[itmp] && maskValue)) continue;
     717          psVectorAppend (tmp, x64->data.F64[itmp]);
     718        }
     719        psVector *sorted = psVectorSort(NULL,tmp);
    713720        median = sorted->data.F64[sorted->n / 2];
    714721        // CZW: I'm not bothering to scale this because it doesn't really matter.
    715722        sigma  = (sorted->data.F64[3 * sorted->n / 4] - sorted->data.F64[sorted->n / 4]);
    716723        psFree(sorted);
     724        psFree(tmp);
    717725
    718726        if ((!isfinite(median))||
     
    721729          sigma = 1.0;
    722730        }
    723         if ((median == 0.0)&&(sigma == 1.0)) {
    724           scale = false;
     731        if (fabs(median) < 1e-10) {
     732          // CZW 2014-10-21: This median is small and close to zero.  This can cause issues with the
     733          // scaling,
     734          median_zero = true;
     735          if ((sigma == 1.0)||(fabs(sigma) <= 1e-10)) {
     736            // Don't bother scaling if sigma is unity (it's already scaled) or if the sigma calculation has gone wrong.
     737            scale = false;
     738          }
    725739        }
     740
    726741        // I can't see a way to not clobber x if it's already F64, so make a copy.x
    727         z64 = psVectorCopy(NULL,x64,PS_TYPE_F64);
     742        psVector *z64 = psVectorCopy(NULL,x64,PS_TYPE_F64);
    728743        psBinaryOp(z64,z64,"-",psScalarAlloc(median,PS_TYPE_F64));
    729744        psBinaryOp(z64,z64,"/",psScalarAlloc(sigma,PS_TYPE_F64));
     
    733748#endif
    734749
    735        
    736750        result = VectorFitPolynomial1DOrd(poly, mask, maskValue, f64, fErr64, z64);
    737751        psFree(z64); // Done with this.
     
    758772#endif
    759773        }
     774
    760775        for (psS32 i = 0; i <= poly->nX; i++) {
    761776          poly->coeff[i] = 0.0;
    762777          poly->coeffErr[i] = 0.0;
    763          
    764           for (psS32 j = 0; j <= poly->nX; j++) {
     778          if (median_zero) {  // If the median is zero, the obtained solution just needs to be scaled by the sigma values.
     779            poly->coeff[i]    = Zcoeff[i] * pow(1.0 / sigma,i);
     780            poly->coeffErr[i] = ZcoeffErr[i] * pow(1.0 / sigma,i);
     781          }
     782          else { // Otherwise, do the correct transformations by expanding the (x-m)/s terms.
     783            for (psS32 j = 0; j <= poly->nX; j++) {
    765784#if (CZW)
    766             printf("        %d %d %f %f %f %f => %f\n",
    767                    i,j,Zcoeff[j],
    768                    pow(1.0 / sigma,j) * pow(-1,j - i),
    769                    pow(median,j - i),
    770                    1.0 * psBinomialCoeff(j,i),
    771                    Zcoeff[j] * pow(1.0 / sigma,j) * pow(-1,j  -i) * pow(median,j - i) * 1.0 * psBinomialCoeff(j,i)
    772                    );
     785              printf("        %d %d %f %f %f %f => %f\n",
     786                     i,j,Zcoeff[j],
     787                     pow(1.0 / sigma,j) * pow(-1,j - i),
     788                     pow(median,j - i),
     789                     1.0 * psBinomialCoeff(j,i),
     790                     Zcoeff[j] * pow(1.0 / sigma,j) * pow(-1,j  -i) * pow(median,j - i) * 1.0 * psBinomialCoeff(j,i)
     791                     );
    773792#endif
    774             poly->coeff[i] += Zcoeff[j] * pow(1.0 / sigma,j) * pow(-1,j - i) * pow(median,j - i) * psBinomialCoeff(j,i);
    775             poly->coeffErr[i] += pow(ZcoeffErr[j] * pow(1.0 / sigma,j) * pow(-1,j - i) * pow(median,j - 1) * psBinomialCoeff(j,i),2);
     793              poly->coeff[i] += Zcoeff[j] * pow(1.0 / sigma,j) * pow(-1,j - i) * pow(median,j - i) * psBinomialCoeff(j,i);
     794              poly->coeffErr[i] += pow(ZcoeffErr[j] * pow(1.0 / sigma,j) * pow(-1,j - i) * pow(median,j - 1) * psBinomialCoeff(j,i),2);
     795            }
     796            poly->coeffErr[i] = sqrt(poly->coeffErr[i]);
    776797          }
    777           poly->coeffErr[i] = sqrt(poly->coeffErr[i]);
    778798#if (CZW)
    779799          printf("poly1d: unscaled parameters: %d %f %f\n",
     
    784804        psFree(ZcoeffErr);
    785805
    786       }
     806      } // End scaling block.
    787807       
    788808        break;
  • branches/eam_branches/ipp-pv3-20140717-merge/psLib/src/mathtypes/psImage.c

    r23443 r37827  
    9191    }
    9292
    93     long numBytes = numRows * numCols * elementSize;
     93    size_t numBytes = (size_t) numRows * (size_t) numCols * (size_t) elementSize;
    9494
    9595    psImage* image = (psImage* ) p_psAlloc(file, lineno, func, sizeof(psImage));
Note: See TracChangeset for help on using the changeset viewer.