Changeset 25094
- Timestamp:
- Aug 17, 2009, 1:23:08 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/simmosaic_branches/psModules/src/detrend/pmShutterCorrection.c
r23989 r25094 64 64 // the code (see pmShutterCorrectionDataAlloc). 65 65 66 //int corrRefCount = 1; 67 //int corrFitCount = 1; 68 //int corrGuessCount = 1; 66 69 67 70 static void pmShutterCorrectionFree(pmShutterCorrection *pars) … … 88 91 pmShutterCorrection *pmShutterCorrectionGuess(const psVector *exptime, const psVector *counts) 89 92 { 93 //printf("pmShutterCorrectGuess count: %d\n", corrGuessCount++); 90 94 // NOTE: vectors must be sorted on input. It is expensive to sort or check this here, but 91 95 // it is easy to arrange by sorting the images before generating these vectors. 92 96 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 { 93 208 PS_ASSERT_VECTOR_NON_NULL(exptime, NULL); 94 209 PS_ASSERT_VECTOR_NON_NULL(counts, NULL); … … 101 216 return NULL; 102 217 } 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 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); 183 268 psFree(line); 184 psFree(tmpX);185 psFree(tmpY);186 269 187 270 return corr; 188 189 GUESS_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 198 pmShutterCorrection *pmShutterCorrectionLinFit(const psVector *exptime, const psVector *counts, 199 const psVector *cntError, const psVector *mask, float offref, 200 int nIter, float rej) 201 { 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++); 202 295 PS_ASSERT_VECTOR_NON_NULL(exptime, NULL); 203 296 PS_ASSERT_VECTOR_NON_NULL(counts, NULL); … … 214 307 PS_ASSERT_VECTORS_SIZE_EQUAL(counts, cntError, NULL); 215 308 } 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 them224 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 fit232 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 measured238 // too few points to use the robust analysis method239 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 267 static 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 parameters285 pmShutterCorrection *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 }302 309 PS_ASSERT_PTR_NON_NULL(guess, NULL); 303 310 … … 344 351 psVector *resid = psVectorAlloc (exptime->n, PS_TYPE_F32); 345 352 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 346 356 float fitCounts = corr->scale * (exptime->data.F32[i] + corr->offset) / (exptime->data.F32[i] + corr->offref); 347 357 resid->data.F32[i] = counts->data.F32[i] - fitCounts; … … 363 373 if (rawStats->sampleStdev / resStats->sampleStdev < 1.5) corr->valid = false; 364 374 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); 365 376 366 377 psFree (rawStats); … … 983 994 float pmShutterCorrectionReference(pmShutterCorrectionData *data) 984 995 { 996 //printf("pmShutterCorrectionReference: count %d\n", corrRefCount++); 985 997 PS_ASSERT_PTR_NON_NULL(data, NAN); 986 998 PS_ASSERT_INT_POSITIVE(data->num, NAN); … … 1013 1025 pmShutterCorrection *guess = pmShutterCorrectionGuess(newtimes, newcounts); // Guess at correction 1014 1026 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); 1015 1028 1016 1029 pmShutterCorrection *corr = pmShutterCorrectionFullFit(newtimes, newcounts, newerrors, guess); // The actual correction 1017 1030 psTrace("psModules.detrend", 5, "Shutter correction fit: scale: %f, offset: %f, offref: %f\n", corr->scale, corr->offset, corr->offref); 1018 1031 1032 //printf("Reference corr scale, offset, offref: %f, %f, %f\n", corr->scale, corr->offset, corr->offref); 1019 1033 if (corr && isfinite(corr->offref) && corr->valid) { 1020 1034 psTrace("psModules.detrend", 5, "Sample reference value: %f\n", corr->offref); … … 1132 1146 psImage *patternImage = pattern->image; // Illumination pattern 1133 1147 1134 int num = data->num; // N umber of images1148 int num = data->num; // NmaxInputRowsmaxInputRowsumber of images 1135 1149 psVector *counts = psVectorAlloc(num, PS_TYPE_F32); // Counts in each image 1136 1150 psVector *errors = psVectorAlloc(num, PS_TYPE_F32); // Counts in each image
Note:
See TracChangeset
for help on using the changeset viewer.
