- Timestamp:
- May 3, 2010, 8:45:22 AM (16 years ago)
- Location:
- branches/simmosaic_branches
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/simmosaic_branches
- Property svn:mergeinfo changed
-
branches/simmosaic_branches/psModules
-
Property svn:mergeinfo
set to (toggle deleted branches)
/trunk/psModules merged eligible /branches/eam_branches/stackphot.20100406/psModules 27623-27653 /branches/pap_delete/psModules 27530-27595
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
branches/simmosaic_branches/psModules/src/detrend/pmShutterCorrection.c
r25094 r27839 64 64 // the code (see pmShutterCorrectionDataAlloc). 65 65 66 //int corrRefCount = 1;67 //int corrFitCount = 1;68 //int corrGuessCount = 1;69 66 70 67 static void pmShutterCorrectionFree(pmShutterCorrection *pars) … … 91 88 pmShutterCorrection *pmShutterCorrectionGuess(const psVector *exptime, const psVector *counts) 92 89 { 93 //printf("pmShutterCorrectGuess count: %d\n", corrGuessCount++);94 90 // NOTE: vectors must be sorted on input. It is expensive to sort or check this here, but 95 91 // it is easy to arrange by sorting the images before generating these vectors. 96 92 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 exposures108 109 // use interpolation to guess shutter correction parameters given a set of exposures times and normalized110 // counts (divided by the reference counts for each image)111 112 pmShutterCorrection *corr = pmShutterCorrectionAlloc(); // Shutter correction, to be returned113 psPolynomial1D *line = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1); // Straight line, for extrapolation114 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 we117 // 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.0121 psVector *tmpX = psVectorAlloc(2, PS_TYPE_F32);122 psVector *tmpY = psVectorAlloc(2, PS_TYPE_F32);123 124 long index;125 126 // Iterate only127 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 only140 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.0148 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) / 2161 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 = dTo177 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 offref204 pmShutterCorrection *pmShutterCorrectionLinFit(const psVector *exptime, const psVector *counts,205 const psVector *cntError, const psVector *mask, float offref,206 int nIter, float rej)207 {208 93 PS_ASSERT_VECTOR_NON_NULL(exptime, NULL); 209 94 PS_ASSERT_VECTOR_NON_NULL(counts, NULL); … … 216 101 return NULL; 217 102 } 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 268 183 psFree(line); 184 psFree(tmpX); 185 psFree(tmpY); 269 186 270 187 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 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 { 295 202 PS_ASSERT_VECTOR_NON_NULL(exptime, NULL); 296 203 PS_ASSERT_VECTOR_NON_NULL(counts, NULL); … … 307 214 PS_ASSERT_VECTORS_SIZE_EQUAL(counts, cntError, NULL); 308 215 } 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 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 parameters 285 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 } 309 302 PS_ASSERT_PTR_NON_NULL(guess, NULL); 310 303 … … 351 344 psVector *resid = psVectorAlloc (exptime->n, PS_TYPE_F32); 352 345 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 356 346 float fitCounts = corr->scale * (exptime->data.F32[i] + corr->offset) / (exptime->data.F32[i] + corr->offref); 357 347 resid->data.F32[i] = counts->data.F32[i] - fitCounts; … … 373 363 if (rawStats->sampleStdev / resStats->sampleStdev < 1.5) corr->valid = false; 374 364 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);376 365 377 366 psFree (rawStats); … … 994 983 float pmShutterCorrectionReference(pmShutterCorrectionData *data) 995 984 { 996 //printf("pmShutterCorrectionReference: count %d\n", corrRefCount++);997 985 PS_ASSERT_PTR_NON_NULL(data, NAN); 998 986 PS_ASSERT_INT_POSITIVE(data->num, NAN); … … 1025 1013 pmShutterCorrection *guess = pmShutterCorrectionGuess(newtimes, newcounts); // Guess at correction 1026 1014 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);1028 1015 1029 1016 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 } 1038 1028 1039 1029 psFree(corr); … … 1146 1136 psImage *patternImage = pattern->image; // Illumination pattern 1147 1137 1148 int num = data->num; // N maxInputRowsmaxInputRowsumber of images1138 int num = data->num; // Number of images 1149 1139 psVector *counts = psVectorAlloc(num, PS_TYPE_F32); // Counts in each image 1150 1140 psVector *errors = psVectorAlloc(num, PS_TYPE_F32); // Counts in each image
Note:
See TracChangeset
for help on using the changeset viewer.
