IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 9298


Ignore:
Timestamp:
Oct 5, 2006, 10:48:56 AM (20 years ago)
Author:
Paul Price
Message:

Cleaning up code, adding error checks, adding const where appropriate.

Location:
trunk/psModules/src/detrend
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/detrend/pmShutterCorrection.c

    r8926 r9298  
    6363#include "psVectorBracket.h"
    6464
    65 static void pmShutterCorrParsFree (pmShutterCorrPars *pars)
    66 {
    67     if (pars == NULL)
    68         return;
     65static void pmShutterCorrectionFree(pmShutterCorrection *pars)
     66{
     67    // Nothing to free
    6968    return;
    7069}
    7170
    72 pmShutterCorrPars *pmShutterCorrParsAlloc ()
    73 {
    74 
    75     pmShutterCorrPars *pars = (pmShutterCorrPars *) psAlloc(sizeof(pmShutterCorrPars));
    76     psMemSetDeallocator(pars, (psFreeFunc) pmShutterCorrParsFree);
    77     pars->scale  = 0.0;
    78     pars->offset = 0.0;
    79     pars->offref = 0.0;
    80     return (pars);
    81 }
    82 
    83 // use interpolation to guess shutter correction parameters given a set of exposures times and normalized
    84 // counts (divided by the reference counts for each image)
    85 pmShutterCorrPars *pmShutterCorrectionGuess (psVector *exptime, psVector *counts)
    86 {
    87 
    88     psVector *tmpX = NULL;
    89     psVector *tmpY = NULL;
    90 
    91     pmShutterCorrPars *pars = pmShutterCorrParsAlloc ();
    92     psPolynomial1D *line = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 1);
    93 
    94     int N = exptime->n;
    95     // ASSERT (N >> 5)
    96 
     71pmShutterCorrection *pmShutterCorrectionAlloc()
     72{
     73    pmShutterCorrection *corr = (pmShutterCorrection*)psAlloc(sizeof(pmShutterCorrection));
     74    psMemSetDeallocator(corr, (psFreeFunc)pmShutterCorrectionFree);
     75
     76    corr->scale  = 0.0;
     77    corr->offset = 0.0;
     78    corr->offref = 0.0;
     79
     80    return corr;
     81}
     82
     83pmShutterCorrection *pmShutterCorrectionGuess(const psVector *exptime, const psVector *counts)
     84{
    9785    // NOTE: vectors must be sorted on input.  It is expensive to sort or check this here, but
    9886    // it is easy to arrange by sorting the images before generating these vectors.
     87
     88    PS_ASSERT_VECTOR_NON_NULL(exptime, NULL);
     89    PS_ASSERT_VECTOR_NON_NULL(counts, NULL);
     90    PS_ASSERT_VECTOR_TYPE(exptime, PS_TYPE_F32, NULL);
     91    PS_ASSERT_VECTOR_TYPE(counts, PS_TYPE_F32, NULL);
     92    PS_ASSERT_VECTORS_SIZE_EQUAL(exptime, counts, NULL);
     93    if (exptime->n <= 2) {
     94        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
     95                "Require more than 2 exposures to guess shutter correction.\n");
     96        return NULL;
     97    }
     98
     99    long N = exptime->n;                // Number of exposures
     100
     101    // use interpolation to guess shutter correction parameters given a set of exposures times and normalized
     102    // counts (divided by the reference counts for each image)
     103
     104    pmShutterCorrection *corr = pmShutterCorrectionAlloc(); // Shutter correction, to be returned
     105    psPolynomial1D *line = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1); // Straight line, for extrapolation
    99106
    100107    // choose the highest exptime point as the guess for the scale:
    101108    // XXX we could examine the top 2 or 3 values and decide if we
    102109    // extended exptime enough or median clip.
    103     pars->scale = counts->data.F32[N-1];
     110    corr->scale = counts->data.F32[N-1];
    104111
    105112    // fit a line to the lowest three points and extrapolate to 0.0
    106     tmpX = psVectorAlloc (2, PS_TYPE_F32);
    107     tmpY = psVectorAlloc (2, PS_TYPE_F32);
     113    psVector *tmpX = psVectorAlloc(2, PS_TYPE_F32);
     114    psVector *tmpY = psVectorAlloc(2, PS_TYPE_F32);
    108115    tmpX->n = tmpY->n = 2;
    109116
    110     tmpX->data.F32[0] = exptime->data.F32[0];
    111     tmpX->data.F32[1] = exptime->data.F32[1];
    112     tmpY->data.F32[0] = counts->data.F32[0];
    113     tmpY->data.F32[1] = counts->data.F32[1];
     117    long index;
     118    for (index = 0; !isfinite(exptime->data.F32[index]) && index < N - 1; index++)
     119        ; // Iterate only
     120    if (index == N - 1) {
     121        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     122                "Not enough good values to guess shutter correction.\n");
     123        goto ERROR;
     124    }
     125    tmpX->data.F32[0] = exptime->data.F32[index];
     126    tmpY->data.F32[0] = counts->data.F32[index];
     127
     128    for (index++;
     129            (!isfinite(exptime->data.F32[index]) || exptime->data.F32[index] == exptime->data.F32[0]) &&
     130            index < N; index++)
     131        ; // Iterate only
     132    if (index == N) {
     133        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     134                "Exposure times are all identical --- cannot guess shutter correction.\n");
     135        goto ERROR;
     136    }
     137    tmpY->data.F32[1] = counts->data.F32[index];
     138    tmpX->data.F32[1] = exptime->data.F32[index];
    114139
    115140    // fit a line and extrapolate the fit to 0.0
    116     psVectorFitPolynomial1D (line, NULL, 0, tmpY, NULL, tmpX);
    117     float ratio = psPolynomial1DEval (line, 0.0) / pars->scale;
     141    if (!psVectorFitPolynomial1D(line, NULL, 0, tmpY, NULL, tmpX)) {
     142        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit for the time offset.\n");
     143        goto ERROR;
     144    }
     145    float ratio = psPolynomial1DEval(line, 0.0) / corr->scale;
    118146
    119147    // XXX we need a sanity check:
    120     // if the mean value of the three points is higher than pars->scale,
     148    // if the mean value of the three points is higher than corr->scale,
    121149    // then the slope should be negative.
    122     // if the mean value of the three points is lower than pars->scale,
     150    // if the mean value of the three points is lower than corr->scale,
    123151    // then the slope should be positive.
    124152
    125     // find two points bracketing the value counts = A (1 + dTk/dTo) / 2 = pars->scale (1 + ratio) / 2
    126     float value = pars->scale * (1 + ratio) / 2.0;
    127 
    128     int Np;
     153    // find two points bracketing the value counts = A (1 + dTk/dTo) / 2 = corr->scale (1 + ratio) / 2
     154    float value = corr->scale * (1 + ratio) / 2.0;
     155
     156    int Np;                             // Index of the value above (positive side)
    129157    if (ratio < 1.0) {
    130         Np = psVectorBracket (counts, value, true);
     158        Np = psVectorBracket(counts, value, true);
    131159    } else {
    132         Np = psVectorBracketDescend (counts, value, true);
    133     }
    134     int Nm = (Np == 0) ? 1 : Np - 1;
     160        Np = psVectorBracketDescend(counts, value, true);
     161    }
     162    int Nm = (Np == 0) ? 1 : Np - 1;    // Index of the value below (negative side)
    135163
    136164    tmpX->data.F32[0] = counts->data.F32[Nm];
     
    140168
    141169    // fit a line and extrapolate the fit to counts = A (1 + dTk/dTo) : exptime = dTo
    142     line = psVectorFitPolynomial1D (line, NULL, 0, tmpY, NULL, tmpX);
    143     pars->offref = psPolynomial1DEval (line, value);
    144     pars->offset = ratio * pars->offref;
    145 
    146     psFree (line);
    147     psFree (tmpX);
    148     psFree (tmpY);
    149 
    150     return (pars);
     170    if (!psVectorFitPolynomial1D (line, NULL, 0, tmpY, NULL, tmpX)) {
     171        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit for the reference offset.\n");
     172        goto ERROR;
     173    }
     174    corr->offref = psPolynomial1DEval(line, value);
     175    corr->offset = ratio * corr->offref;
     176
     177    psFree(line);
     178    psFree(tmpX);
     179    psFree(tmpY);
     180
     181    return corr;
     182
     183ERROR:
     184    psFree(tmpX);
     185    psFree(tmpY);
     186    psFree(line);
     187    psFree(corr);
     188    return NULL;
    151189}
    152190
    153191// linear fit to the counts and exptime, given a value for offref
    154 pmShutterCorrPars *pmShutterCorrectionLinFit (psVector *exptime, psVector *counts, psVector *cntError, float offref)
    155 {
     192pmShutterCorrection *pmShutterCorrectionLinFit(const psVector *exptime,
     193        const psVector *counts,
     194        const psVector *cntError,
     195        float offref
     196                                              )
     197{
     198    PS_ASSERT_VECTOR_NON_NULL(exptime, NULL);
     199    PS_ASSERT_VECTOR_NON_NULL(counts, NULL);
     200    PS_ASSERT_VECTOR_TYPE(exptime, PS_TYPE_F32, NULL);
     201    PS_ASSERT_VECTOR_TYPE(counts, PS_TYPE_F32, NULL);
     202    PS_ASSERT_VECTORS_SIZE_EQUAL(exptime, counts, NULL);
     203    if (exptime->n <= 2) {
     204        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
     205                "Require more than 2 exposures to guess shutter correction.\n");
     206        return NULL;
     207    }
     208    if (cntError) {
     209        PS_ASSERT_VECTOR_TYPE(cntError, PS_TYPE_F32, NULL);
     210        PS_ASSERT_VECTORS_SIZE_EQUAL(counts, cntError, NULL);
     211    }
     212    PS_ASSERT_FLOAT_LARGER_THAN(offref, 0.0, NULL);
    156213
    157214    // this step is identical for all pixels: do it once and save?
    158     psVector *x = psVectorAlloc (exptime->n, PS_TYPE_F32);
    159     psVector *y = psVectorAlloc (exptime->n, PS_TYPE_F32);
     215    psVector *x = psVectorAlloc(exptime->n, PS_TYPE_F32);
     216    psVector *y = psVectorAlloc(exptime->n, PS_TYPE_F32);
    160217    x->n = y->n = exptime->n;
    161218
    162     for (int i = 0; i < exptime->n; i++) {
     219    for (long i = 0; i < exptime->n; i++) {
     220        // Should be safe (if expensive) to stick NaNs in --- the fitter deals with them
    163221        float value = 1.0 / (exptime->data.F32[i] + offref);
    164222        x->data.F32[i] = exptime->data.F32[i] * value;
     
    174232    line->coeff[1][1] = 0;
    175233
    176     psVectorFitPolynomial2D (line, NULL, 0, counts, cntError, x, y);
    177 
    178     pmShutterCorrPars *pars = pmShutterCorrParsAlloc ();
    179 
    180     pars->offref = offref;
    181     pars->scale  = line->coeff[1][0];
    182     pars->offset = line->coeff[0][1] / line->coeff[1][0];
    183 
    184     psFree (x);
    185     psFree (y);
    186     psFree (line);
    187 
    188     return (pars);
     234    if (!psVectorFitPolynomial2D(line, NULL, 0, counts, cntError, x, y)) {
     235        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit shutter correction.\n");
     236        psFree(x);
     237        psFree(y);
     238        psFree(line);
     239        return NULL;
     240    }
     241
     242    pmShutterCorrection *corr = pmShutterCorrectionAlloc();
     243    corr->offref = offref;
     244    corr->scale  = line->coeff[1][0];
     245    corr->offset = line->coeff[0][1] / line->coeff[1][0];
     246
     247    psFree(x);
     248    psFree(y);
     249    psFree(line);
     250
     251    return corr;
    189252}
    190253
     
    193256                                      const psVector *x)
    194257{
    195     psF32 A  = params->data.F32[0];
    196     psF32 p  = x->data.F32[0] + params->data.F32[1];
    197     psF32 q  = 1.0 / (x->data.F32[0] + params->data.F32[2]);
    198     psF32 f  = A*p*q;
    199 
    200     if (deriv != NULL) {
    201         deriv->data.F32[0] = p*q;
    202         deriv->data.F32[1] = A*q;
    203         deriv->data.F32[2] = -A*p*q*q;
    204     }
    205     return(f);
     258    // This is in a tight loop, so we won't assert here.
     259
     260    psF32 A = params->data.F32[0];
     261    psF32 p = x->data.F32[0] + params->data.F32[1];
     262    psF32 q = 1.0 / (x->data.F32[0] + params->data.F32[2]);
     263    psF32 f = A * p * q;
     264
     265    if (deriv) {
     266        deriv->data.F32[0] = p * q;
     267        deriv->data.F32[1] = A * q;
     268        deriv->data.F32[2] = - f * q;
     269    }
     270    return f;
    206271}
    207272
    208273// non-linear fit to the counts and exptime, given a guess for the three parameters
    209 pmShutterCorrPars *pmShutterCorrectionFullFit (psVector *exptime, psVector *counts, psVector *cntError, pmShutterCorrPars *guess)
    210 {
    211 
    212     psMinimization *myMin = psMinimizationAlloc(15, 0.1);
    213 
    214     psVector *params = psVectorAlloc (3, PS_TYPE_F32);
     274pmShutterCorrection *pmShutterCorrectionFullFit(const psVector *exptime,
     275        const psVector *counts,
     276        const psVector *cntError,
     277        const pmShutterCorrection *guess
     278                                               )
     279{
     280    PS_ASSERT_VECTOR_NON_NULL(exptime, NULL);
     281    PS_ASSERT_VECTOR_NON_NULL(counts, NULL);
     282    PS_ASSERT_VECTOR_TYPE(exptime, PS_TYPE_F32, NULL);
     283    PS_ASSERT_VECTOR_TYPE(counts, PS_TYPE_F32, NULL);
     284    PS_ASSERT_VECTORS_SIZE_EQUAL(exptime, counts, NULL);
     285    if (exptime->n <= 2) {
     286        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
     287                "Require more than 2 exposures to guess shutter correction.\n");
     288        return NULL;
     289    }
     290    if (cntError) {
     291        PS_ASSERT_VECTOR_TYPE(cntError, PS_TYPE_F32, NULL);
     292        PS_ASSERT_VECTORS_SIZE_EQUAL(counts, cntError, NULL);
     293    }
     294    PS_ASSERT_PTR_NON_NULL(guess, NULL);
     295
     296    psMinimization *minInfo = psMinimizationAlloc(15, 0.1); // Minimization information
     297
     298    psVector *params = psVectorAlloc (3, PS_TYPE_F32); // Fitting parameters
    215299    params->data.F32[0] = guess->scale;
    216300    params->data.F32[1] = guess->offset;
     
    224308    // constrain->paramMax   = psVectorAlloc (3, PS_TYPE_F32);
    225309    // constrain->paramMask  = NULL;
    226     psMinConstrain *constrain = NULL;
     310    psMinConstrain *constrain = NULL;   // Constraints on the minimization
    227311
    228312    // XXX ignore covariance matrix for the moment
    229313    // psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F64);
    230     psImage *covar = NULL;
     314    psImage *covar = NULL;              // Covariance matrix
    231315
    232316    // construct the coordinate and value entries (y is counts)
    233     psArray *x = psArrayAlloc(exptime->n);
     317    psArray *x = psArrayAlloc(exptime->n); // Coordinates
    234318    x->n = exptime->n;
    235319
    236     for (int i = 0; i < exptime->n; i++) {
     320    for (long i = 0; i < exptime->n; i++) {
    237321        psVector *coord = psVectorAlloc(1, PS_TYPE_F32);
    238322        coord->n = 1;
     
    241325    }
    242326
    243     psMinimizeLMChi2(myMin, covar, params, constrain, x, counts, cntError, pmShutterCorrectionModel);
    244 
    245     pmShutterCorrPars *pars = pmShutterCorrParsAlloc ();
    246 
    247     pars->scale  = params->data.F32[0];
    248     pars->offset = params->data.F32[1];
    249     pars->offref = params->data.F32[2];
    250 
    251     psFree (myMin);
    252     psFree (params);
    253     psFree (x);
    254 
    255     return (pars);
    256 }
     327    if (!psMinimizeLMChi2(minInfo, covar, params, constrain, x, counts, cntError, pmShutterCorrectionModel)) {
     328        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit for shutter correction.\n");
     329        psFree(x);
     330        psFree(minInfo);
     331        psFree(params);
     332        return NULL;
     333    }
     334
     335    pmShutterCorrection *corr = pmShutterCorrectionAlloc(); // Shutter correction
     336    corr->scale  = params->data.F32[0];
     337    corr->offset = params->data.F32[1];
     338    corr->offref = params->data.F32[2];
     339
     340    psFree(minInfo);
     341    psFree(params);
     342    psFree(x);
     343
     344    return corr;
     345}
  • trunk/psModules/src/detrend/pmShutterCorrection.h

    r8926 r9298  
    3131 * First, as T_o goes to a large value, s() approaches the value of f'(x,y).
    3232 * Next, as T_o goes to a very small value, s() approaches the value of
    33  * f'(x,y)*dT(x,y)/dT(0,0).  Finally, when s() has the value of 
     33 * f'(x,y)*dT(x,y)/dT(0,0).  Finally, when s() has the value of
    3434 * f'(x,y)*(1 + dT(x,y)/dT(0,0))/2, T_o has the value of dT(0,0).  with data
    3535 * points covering a reasonable dynamic range, we can solve for these three
    36  * values by interpolation and/or extrapolation. 
     36 * values by interpolation and/or extrapolation.
    3737 
    3838 * To take the strategy one step further, we could use the above recipe to
     
    4848 *  @author Eugene Magnier, IfA
    4949 *
    50  *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
    51  *  @date $Date: 2006-09-25 01:06:28 $
     50 *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
     51 *  @date $Date: 2006-10-05 20:48:56 $
    5252 *
    5353 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    5656#include "pslib.h"
    5757
     58// Shutter correction parameters, applicable for a single pixel
    5859typedef struct
    5960{
    60     double scale;     // A(k)
    61     double offset;   // dTk
    62     double offref;   // dTo
     61    double scale;                       // The normalisation for an exposure, A(k)
     62    double offset;                      // The time offset, dTk
     63    double offref;                      // The reference time offset, dTo
    6364}
    64 pmShutterCorrPars;
     65pmShutterCorrection;
    6566
    66 pmShutterCorrPars *pmShutterCorrParsAlloc ();
    67 pmShutterCorrPars *pmShutterCorrectionGuess (psVector *exptime, psVector *counts);
    68 pmShutterCorrPars *pmShutterCorrectionLinFit (psVector *exptime, psVector *counts, psVector *cntError, float offref);
    69 pmShutterCorrPars *pmShutterCorrectionFullFit (psVector *exptime, psVector *counts, psVector *cntError, pmShutterCorrPars *guess);
     67// Allocator
     68pmShutterCorrection *pmShutterCorrectionAlloc();
     69
     70// Guess a shutter correction, based on plot of counts vs exposure time.
     71// Used before doing the full non-linear fit, to get parameters close to the true.
     72// Assumes exptime vector is sorted (ascending order; longest is last) prior to input.
     73pmShutterCorrection *pmShutterCorrectionGuess(const psVector *exptime, // Exposure times for each exposure
     74        const psVector *counts // Counts for each exposure
     75                                             );
     76
     77// Generate shutter correction based on a linear fit
     78pmShutterCorrection *pmShutterCorrectionLinFit(const psVector *exptime, // Exposure times for each exposure
     79        const psVector *counts, // Counts for each exposure
     80        const psVector *cntError, // Error in the counts, for each exp.
     81        float offref // Reference time offset
     82                                              );
     83
     84// Generate shutter correction based on a full non-linear fit
     85pmShutterCorrection *pmShutterCorrectionFullFit(const psVector *exptime, // Exposure times for each exposure
     86        const psVector *counts, // Counts for each exposure
     87        const psVector *cntError, // Error in the counts, for each exp
     88        const pmShutterCorrection *guess // Initial guess
     89                                               );
Note: See TracChangeset for help on using the changeset viewer.