IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 3, 2010, 8:45:22 AM (16 years ago)
Author:
eugene
Message:

updates from trunk

Location:
branches/simmosaic_branches
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/simmosaic_branches

  • branches/simmosaic_branches/psModules

  • branches/simmosaic_branches/psModules/src/detrend/pmShutterCorrection.c

    r25094 r27839  
    6464                                        // the code (see pmShutterCorrectionDataAlloc).
    6565
    66 //int corrRefCount = 1;
    67 //int corrFitCount = 1;
    68 //int corrGuessCount = 1;
    6966
    7067static void pmShutterCorrectionFree(pmShutterCorrection *pars)
     
    9188pmShutterCorrection *pmShutterCorrectionGuess(const psVector *exptime, const psVector *counts)
    9289{
    93 //printf("pmShutterCorrectGuess count: %d\n", corrGuessCount++);
    9490    // NOTE: vectors must be sorted on input.  It is expensive to sort or check this here, but
    9591    // it is easy to arrange by sorting the images before generating these vectors.
    9692
    97     PS_ASSERT_VECTOR_NON_NULL(exptime, NULL);
    98     PS_ASSERT_VECTOR_NON_NULL(counts, NULL);
    99     PS_ASSERT_VECTOR_TYPE(exptime, PS_TYPE_F32, NULL);
    100     PS_ASSERT_VECTOR_TYPE(counts, PS_TYPE_F32, NULL);
    101     PS_ASSERT_VECTORS_SIZE_EQUAL(exptime, counts, NULL);
    102     if (exptime->n <= 2) {
    103         printf("Require more than 2 exposures to guess shutter correction.\n");
    104         return NULL;
    105     }
    106 
    107     long N = exptime->n;                // Number of exposures
    108 
    109     // use interpolation to guess shutter correction parameters given a set of exposures times and normalized
    110     // counts (divided by the reference counts for each image)
    111 
    112     pmShutterCorrection *corr = pmShutterCorrectionAlloc(); // Shutter correction, to be returned
    113     psPolynomial1D *line = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1); // Straight line, for extrapolation
    114 
    115     // choose the highest exptime point as the guess for the scale:
    116     // XXX we could examine the top 2 or 3 values and decide if we
    117     // extended exptime enough or median clip.
    118     corr->scale = counts->data.F32[N-1];
    119 
    120     // fit a line to the lowest three points and extrapolate to 0.0
    121     psVector *tmpX = psVectorAlloc(2, PS_TYPE_F32);
    122     psVector *tmpY = psVectorAlloc(2, PS_TYPE_F32);
    123 
    124     long index;
    125 
    126     // Iterate only
    127     for (index = 0; !isfinite(exptime->data.F32[index]) && index < N - 1; index++);
    128 
    129     if (index == N - 1) {
    130         printf("Not enough good values to guess shutter correction.\n");
    131         goto GUESS_ERROR;
    132     }
    133     tmpX->data.F32[0] = exptime->data.F32[index];
    134     tmpY->data.F32[0] = counts->data.F32[index];
    135 
    136     for (index++;
    137             (!isfinite(exptime->data.F32[index]) || exptime->data.F32[index] == exptime->data.F32[0]) &&
    138             index < N; index++)
    139         ; // Iterate only
    140     if (index == N) {
    141         printf("Exposure times are all identical --- cannot guess shutter correction.\n");
    142         goto GUESS_ERROR;
    143     }
    144     tmpY->data.F32[1] = counts->data.F32[index];
    145     tmpX->data.F32[1] = exptime->data.F32[index];
    146 
    147     // fit a line and extrapolate the fit to 0.0
    148     if (!psVectorFitPolynomial1D(line, NULL, 0, tmpY, NULL, tmpX)) {
    149         printf("Unable to fit for the time offset.\n");
    150         goto GUESS_ERROR;
    151     }
    152     float ratio = psPolynomial1DEval(line, 0.0) / corr->scale;
    153 
    154     // XXX we need a sanity check:
    155     // if the mean value of the three points is higher than corr->scale,
    156     // then the slope should be negative.
    157     // if the mean value of the three points is lower than corr->scale,
    158     // then the slope should be positive.
    159 
    160     // find two points bracketing the value counts = A (1 + dTk/dTo) / 2 = corr->scale (1 + ratio) / 2
    161     float value = corr->scale * (1 + ratio) / 2.0;
    162 
    163     int Np;                             // Index of the value above (positive side)
    164     if (ratio < 1.0) {
    165         Np = psVectorBracket(counts, value, true);
    166     } else {
    167         Np = psVectorBracketDescend(counts, value, true);
    168     }
    169     int Nm = (Np == 0) ? 1 : Np - 1;    // Index of the value below (negative side)
    170 
    171     tmpX->data.F32[0] = counts->data.F32[Nm];
    172     tmpX->data.F32[1] = counts->data.F32[Np];
    173     tmpY->data.F32[0] = exptime->data.F32[Nm];
    174     tmpY->data.F32[1] = exptime->data.F32[Np];
    175 
    176     // fit a line and extrapolate the fit to counts = A (1 + dTk/dTo) : exptime = dTo
    177     if (!psVectorFitPolynomial1D (line, NULL, 0, tmpY, NULL, tmpX)) {
    178         printf("Unable to fit for the reference offset.\n");
    179         printf("tmpX0: %f, tmpX1: %f, tmpY0: %f, tmpY1: %f\n", tmpX->data.F32[0], tmpX->data.F32[1], tmpY->data.F32[0], tmpY->data.F32[1]);
    180         goto GUESS_ERROR;
    181     }
    182     corr->offref = psPolynomial1DEval(line, value);
    183     corr->offset = ratio * corr->offref;
    184 printf("guess scale, offset, offref: %f, %f, %f\n", corr->scale, corr->offset, corr->offref);
    185     psFree(line);
    186     psFree(tmpX);
    187     psFree(tmpY);
    188 
    189     return corr;
    190 
    191 GUESS_ERROR:
    192     psFree(tmpX);
    193     psFree(tmpY);
    194     psFree(line);
    195 //    psFree(corr);
    196 //    return NULL;
    197     corr->scale = 0.5;
    198     corr->offset = 0.5;
    199     corr->offref = 0.5;
    200     return corr;
    201 }
    202 
    203 // linear fit to the counts and exptime, given a value for offref
    204 pmShutterCorrection *pmShutterCorrectionLinFit(const psVector *exptime, const psVector *counts,
    205                                                const psVector *cntError, const psVector *mask, float offref,
    206                                                int nIter, float rej)
    207 {
    20893    PS_ASSERT_VECTOR_NON_NULL(exptime, NULL);
    20994    PS_ASSERT_VECTOR_NON_NULL(counts, NULL);
     
    216101        return NULL;
    217102    }
    218     if (cntError) {
    219         PS_ASSERT_VECTOR_TYPE(cntError, PS_TYPE_F32, NULL);
    220         PS_ASSERT_VECTORS_SIZE_EQUAL(counts, cntError, NULL);
    221     }
    222     PS_ASSERT_FLOAT_LARGER_THAN(offref, 0.0, NULL);
    223 
    224     // this step is identical for all pixels: do it once and save?
    225     psVector *x = psVectorAlloc(exptime->n, PS_TYPE_F32);
    226     psVector *y = psVectorAlloc(exptime->n, PS_TYPE_F32);
    227 
    228     for (long i = 0; i < exptime->n; i++) {
    229         // Should be safe (if expensive) to stick NaNs in --- the fitter deals with them
    230         float value = 1.0 / (exptime->data.F32[i] + offref);
    231         x->data.F32[i] = exptime->data.F32[i] * value;
    232         y->data.F32[i] = value;
    233     }
    234 
    235     psPolynomial2D *line = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, 1, 1);
    236 
    237     // mask out the terms we will not fit
    238     line->coeffMask[0][0] = PS_POLY_MASK_SET;
    239     line->coeffMask[1][1] = PS_POLY_MASK_SET;
    240     line->coeff[0][0] = 0;
    241     line->coeff[1][1] = 0;
    242 
    243     // the stats structure determines how the clipping statistic is measured
    244     // too few points to use the robust analysis method
    245     psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
    246     stats->clipSigma = rej;
    247     stats->clipIter = nIter;
    248 
    249     if (!psVectorClipFitPolynomial2D(line, stats, mask, 0xff, counts, cntError, x, y)) {
    250         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit shutter correction.\n");
    251         psFree(stats);
    252         psFree(x);
    253         psFree(y);
    254         psFree(line);
    255         return NULL;
    256     }
    257 
    258     pmShutterCorrection *corr = pmShutterCorrectionAlloc();
    259     corr->offref = offref;
    260     corr->scale  = line->coeff[1][0];
    261     corr->offset = line->coeff[0][1] / line->coeff[1][0];
    262     corr->num = stats->clippedNvalues;
    263     corr->stdev = stats->clippedStdev;
    264 
    265     psFree(stats);
    266     psFree(x);
    267     psFree(y);
     103
     104    long N = exptime->n;                // Number of exposures
     105
     106    // use interpolation to guess shutter correction parameters given a set of exposures times and normalized
     107    // counts (divided by the reference counts for each image)
     108
     109    pmShutterCorrection *corr = pmShutterCorrectionAlloc(); // Shutter correction, to be returned
     110    psPolynomial1D *line = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1); // Straight line, for extrapolation
     111
     112    // choose the highest exptime point as the guess for the scale:
     113    // XXX we could examine the top 2 or 3 values and decide if we
     114    // extended exptime enough or median clip.
     115    corr->scale = counts->data.F32[N-1];
     116
     117    // fit a line to the lowest three points and extrapolate to 0.0
     118    psVector *tmpX = psVectorAlloc(2, PS_TYPE_F32);
     119    psVector *tmpY = psVectorAlloc(2, PS_TYPE_F32);
     120
     121    long index;
     122
     123    // Iterate only
     124    for (index = 0; !isfinite(exptime->data.F32[index]) && index < N - 1; index++);
     125
     126    if (index == N - 1) {
     127        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     128                "Not enough good values to guess shutter correction.\n");
     129        goto GUESS_ERROR;
     130    }
     131    tmpX->data.F32[0] = exptime->data.F32[index];
     132    tmpY->data.F32[0] = counts->data.F32[index];
     133
     134    for (index++;
     135            (!isfinite(exptime->data.F32[index]) || exptime->data.F32[index] == exptime->data.F32[0]) &&
     136            index < N; index++)
     137        ; // Iterate only
     138    if (index == N) {
     139        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     140                "Exposure times are all identical --- cannot guess shutter correction.\n");
     141        goto GUESS_ERROR;
     142    }
     143    tmpY->data.F32[1] = counts->data.F32[index];
     144    tmpX->data.F32[1] = exptime->data.F32[index];
     145
     146    // fit a line and extrapolate the fit to 0.0
     147    if (!psVectorFitPolynomial1D(line, NULL, 0, tmpY, NULL, tmpX)) {
     148        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit for the time offset.\n");
     149        goto GUESS_ERROR;
     150    }
     151    float ratio = psPolynomial1DEval(line, 0.0) / corr->scale;
     152
     153    // XXX we need a sanity check:
     154    // if the mean value of the three points is higher than corr->scale,
     155    // then the slope should be negative.
     156    // if the mean value of the three points is lower than corr->scale,
     157    // then the slope should be positive.
     158
     159    // find two points bracketing the value counts = A (1 + dTk/dTo) / 2 = corr->scale (1 + ratio) / 2
     160    float value = corr->scale * (1 + ratio) / 2.0;
     161
     162    int Np;                             // Index of the value above (positive side)
     163    if (ratio < 1.0) {
     164        Np = psVectorBracket(counts, value, true);
     165    } else {
     166        Np = psVectorBracketDescend(counts, value, true);
     167    }
     168    int Nm = (Np == 0) ? 1 : Np - 1;    // Index of the value below (negative side)
     169
     170    tmpX->data.F32[0] = counts->data.F32[Nm];
     171    tmpX->data.F32[1] = counts->data.F32[Np];
     172    tmpY->data.F32[0] = exptime->data.F32[Nm];
     173    tmpY->data.F32[1] = exptime->data.F32[Np];
     174
     175    // fit a line and extrapolate the fit to counts = A (1 + dTk/dTo) : exptime = dTo
     176    if (!psVectorFitPolynomial1D (line, NULL, 0, tmpY, NULL, tmpX)) {
     177        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit for the reference offset.\n");
     178        goto GUESS_ERROR;
     179    }
     180    corr->offref = psPolynomial1DEval(line, value);
     181    corr->offset = ratio * corr->offref;
     182
    268183    psFree(line);
     184    psFree(tmpX);
     185    psFree(tmpY);
    269186
    270187    return corr;
    271 }
    272 
    273 static psF32 pmShutterCorrectionModel(psVector *deriv, const psVector *params, const psVector *x)
    274 {
    275     // This is in a tight loop, so we won't assert here.
    276 
    277     psF32 A = params->data.F32[0];
    278     psF32 p = x->data.F32[0] + params->data.F32[1];
    279     psF32 q = 1.0 / (x->data.F32[0] + params->data.F32[2]);
    280     psF32 f = A * p * q;
    281 
    282     if (deriv) {
    283         deriv->data.F32[0] = p * q;
    284         deriv->data.F32[1] = A * q;
    285         deriv->data.F32[2] = - f * q;
    286     }
    287     return f;
    288 }
    289 
    290 // non-linear fit to the counts and exptime, given a guess for the three parameters
    291 pmShutterCorrection *pmShutterCorrectionFullFit(const psVector *exptime, const psVector *counts,
    292                                                 const psVector *cntError, const pmShutterCorrection *guess)
    293 {
    294 //printf("pmShutterCorrectionFullFit count: %d\n", corrFitCount++);
     188
     189GUESS_ERROR:
     190    psFree(tmpX);
     191    psFree(tmpY);
     192    psFree(line);
     193    psFree(corr);
     194    return NULL;
     195}
     196
     197// linear fit to the counts and exptime, given a value for offref
     198pmShutterCorrection *pmShutterCorrectionLinFit(const psVector *exptime, const psVector *counts,
     199                                               const psVector *cntError, const psVector *mask, float offref,
     200                                               int nIter, float rej)
     201{
    295202    PS_ASSERT_VECTOR_NON_NULL(exptime, NULL);
    296203    PS_ASSERT_VECTOR_NON_NULL(counts, NULL);
     
    307214        PS_ASSERT_VECTORS_SIZE_EQUAL(counts, cntError, NULL);
    308215    }
     216    PS_ASSERT_FLOAT_LARGER_THAN(offref, 0.0, NULL);
     217
     218    // this step is identical for all pixels: do it once and save?
     219    psVector *x = psVectorAlloc(exptime->n, PS_TYPE_F32);
     220    psVector *y = psVectorAlloc(exptime->n, PS_TYPE_F32);
     221
     222    for (long i = 0; i < exptime->n; i++) {
     223        // Should be safe (if expensive) to stick NaNs in --- the fitter deals with them
     224        float value = 1.0 / (exptime->data.F32[i] + offref);
     225        x->data.F32[i] = exptime->data.F32[i] * value;
     226        y->data.F32[i] = value;
     227    }
     228
     229    psPolynomial2D *line = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, 1, 1);
     230
     231    // mask out the terms we will not fit
     232    line->coeffMask[0][0] = PS_POLY_MASK_SET;
     233    line->coeffMask[1][1] = PS_POLY_MASK_SET;
     234    line->coeff[0][0] = 0;
     235    line->coeff[1][1] = 0;
     236
     237    // the stats structure determines how the clipping statistic is measured
     238    // too few points to use the robust analysis method
     239    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
     240    stats->clipSigma = rej;
     241    stats->clipIter = nIter;
     242
     243    if (!psVectorClipFitPolynomial2D(line, stats, mask, 0xff, counts, cntError, x, y)) {
     244        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit shutter correction.\n");
     245        psFree(stats);
     246        psFree(x);
     247        psFree(y);
     248        psFree(line);
     249        return NULL;
     250    }
     251
     252    pmShutterCorrection *corr = pmShutterCorrectionAlloc();
     253    corr->offref = offref;
     254    corr->scale  = line->coeff[1][0];
     255    corr->offset = line->coeff[0][1] / line->coeff[1][0];
     256    corr->num = stats->clippedNvalues;
     257    corr->stdev = stats->clippedStdev;
     258
     259    psFree(stats);
     260    psFree(x);
     261    psFree(y);
     262    psFree(line);
     263
     264    return corr;
     265}
     266
     267static psF32 pmShutterCorrectionModel(psVector *deriv, const psVector *params, const psVector *x)
     268{
     269    // This is in a tight loop, so we won't assert here.
     270
     271    psF32 A = params->data.F32[0];
     272    psF32 p = x->data.F32[0] + params->data.F32[1];
     273    psF32 q = 1.0 / (x->data.F32[0] + params->data.F32[2]);
     274    psF32 f = A * p * q;
     275
     276    if (deriv) {
     277        deriv->data.F32[0] = p * q;
     278        deriv->data.F32[1] = A * q;
     279        deriv->data.F32[2] = - f * q;
     280    }
     281    return f;
     282}
     283
     284// non-linear fit to the counts and exptime, given a guess for the three parameters
     285pmShutterCorrection *pmShutterCorrectionFullFit(const psVector *exptime, const psVector *counts,
     286                                                const psVector *cntError, const pmShutterCorrection *guess)
     287{
     288    PS_ASSERT_VECTOR_NON_NULL(exptime, NULL);
     289    PS_ASSERT_VECTOR_NON_NULL(counts, NULL);
     290    PS_ASSERT_VECTOR_TYPE(exptime, PS_TYPE_F32, NULL);
     291    PS_ASSERT_VECTOR_TYPE(counts, PS_TYPE_F32, NULL);
     292    PS_ASSERT_VECTORS_SIZE_EQUAL(exptime, counts, NULL);
     293    if (exptime->n <= 2) {
     294        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
     295                "Require more than 2 exposures to guess shutter correction.\n");
     296        return NULL;
     297    }
     298    if (cntError) {
     299        PS_ASSERT_VECTOR_TYPE(cntError, PS_TYPE_F32, NULL);
     300        PS_ASSERT_VECTORS_SIZE_EQUAL(counts, cntError, NULL);
     301    }
    309302    PS_ASSERT_PTR_NON_NULL(guess, NULL);
    310303
     
    351344    psVector *resid = psVectorAlloc (exptime->n, PS_TYPE_F32);
    352345    for (int i = 0; i < exptime->n; i++) {
    353 float divTest = exptime->data.F32[i] + corr->offref;
    354 if(divTest == 0) {printf("division by 0\n");}
    355 
    356346        float fitCounts = corr->scale * (exptime->data.F32[i] + corr->offset) / (exptime->data.F32[i] + corr->offref);
    357347        resid->data.F32[i] = counts->data.F32[i] - fitCounts;
     
    373363    if (rawStats->sampleStdev / resStats->sampleStdev < 1.5) corr->valid = false;
    374364    if (isnan(rawStats->sampleStdev) || isnan(resStats->sampleStdev)) corr->valid = false;
    375 printf("corr scale, offset, offref: %f, %f, %f\n", corr->scale, corr->offset, corr->offref);
    376365
    377366    psFree (rawStats);
     
    994983float pmShutterCorrectionReference(pmShutterCorrectionData *data)
    995984{
    996 //printf("pmShutterCorrectionReference: count %d\n", corrRefCount++);
    997985    PS_ASSERT_PTR_NON_NULL(data, NAN);
    998986    PS_ASSERT_INT_POSITIVE(data->num, NAN);
     
    10251013        pmShutterCorrection *guess = pmShutterCorrectionGuess(newtimes, newcounts); // Guess at correction
    10261014        psTrace("psModules.detrend", 5, "Shutter correction guess: scale: %f, offset: %f, offref: %f\n", guess->scale, guess->offset, guess->offref);
    1027 //printf("Reference guess scale, offset, offref: %f, %f, %f\n", guess->scale, guess->offset, guess->offref);
    10281015
    10291016        pmShutterCorrection *corr = pmShutterCorrectionFullFit(newtimes, newcounts, newerrors, guess); // The actual correction
    1030         psTrace("psModules.detrend", 5, "Shutter correction fit: scale: %f, offset: %f, offref: %f\n", corr->scale, corr->offset, corr->offref);
    1031 
    1032 //printf("Reference corr scale, offset, offref: %f, %f, %f\n", corr->scale, corr->offset, corr->offref);
    1033         if (corr && isfinite(corr->offref) && corr->valid) {
    1034             psTrace("psModules.detrend", 5, "Sample reference value: %f\n", corr->offref);
    1035             meanRef += corr->offref;
    1036             numGood++;
    1037         }
     1017
     1018        if (corr) {
     1019            psTrace("psModules.detrend", 5, "Shutter correction fit: scale: %f, offset: %f, offref: %f\n", corr->scale, corr->offset, corr->offref);
     1020            if (isfinite(corr->offref) && corr->valid) {
     1021                psTrace("psModules.detrend", 5, "Sample reference value: %f\n", corr->offref);
     1022                meanRef += corr->offref;
     1023                numGood++;
     1024            }
     1025        } else {
     1026            psTrace("psModules.detrend", 5, "failed Shutter correction fit\n");
     1027        }
    10381028
    10391029        psFree(corr);
     
    11461136    psImage *patternImage = pattern->image; // Illumination pattern
    11471137
    1148     int num = data->num;                // NmaxInputRowsmaxInputRowsumber of images
     1138    int num = data->num;                // Number of images
    11491139    psVector *counts = psVectorAlloc(num, PS_TYPE_F32); // Counts in each image
    11501140    psVector *errors = psVectorAlloc(num, PS_TYPE_F32); // Counts in each image
Note: See TracChangeset for help on using the changeset viewer.