- Timestamp:
- Feb 17, 2006, 7:13:42 AM (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/rel10_ifa/psModules/src/imcombine/pmReadoutCombine.c
r6325 r6448 5 5 * @author GLG, MHPCC 6 6 * 7 * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $8 * @date $Date: 2006-02- 06 21:03:25$7 * @version $Revision: 1.5.4.1 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2006-02-17 17:13:41 $ 9 9 * 10 10 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 36 36 } 37 37 38 static void pmCombineParamsFree (pmCombineParams *params) 39 { 40 41 if (params == NULL) 42 return; 43 44 psFree (params->stats); 45 return; 46 } 47 48 pmCombineParams *pmCombineParamsAlloc (psStatsOptions statsOptions) 49 { 50 51 pmCombineParams *params = psAlloc (sizeof(pmCombineParams)); 52 psMemSetDeallocator(params, (psFreeFunc) pmCombineParamsFree); 53 54 params->stats = psStatsAlloc (statsOptions); 55 params->maskVal = 0; 56 params->fracHigh = 0.25; 57 params->fracHigh = 0.25; 58 params->nKeep = 3; 59 60 return (params); 61 } 62 38 63 /****************************************************************************** 39 64 XXX: Must add support for S16 and S32 types. F32 currently supported. 40 65 *****************************************************************************/ 41 66 psImage *pmReadoutCombine(psImage *output, 42 const psList *inputs, 43 psCombineParams *params, 67 const psArray *inputs, 44 68 const psVector *zero, 45 69 const psVector *scale, 70 pmCombineParams *params, 46 71 bool applyZeroScale, 47 72 psF32 gain, 48 73 psF32 readnoise) 74 { 75 PS_ASSERT_PTR_NON_NULL(inputs, NULL); 76 PS_ASSERT_PTR_NON_NULL(params, NULL); 77 PS_ASSERT_PTR_NON_NULL(params->stats, NULL); 78 if (zero != NULL) { 79 PS_ASSERT_VECTOR_TYPE(zero, PS_TYPE_F32, NULL); 80 // PS_ASSERT_VECTOR_TYPE_S16_S32_F32(zero, NULL); 81 } 82 if (scale != NULL) { 83 PS_ASSERT_VECTOR_TYPE(scale, PS_TYPE_F32, NULL); 84 // PS_ASSERT_VECTOR_TYPE_S16_S32_F32(scale, NULL); 85 } 86 if ((zero != NULL) && (scale != NULL)) { 87 PS_ASSERT_VECTOR_TYPE_EQUAL(zero, scale, NULL); 88 // PS_ASSERT_VECTOR_TYPE_S16_S32_F32(scale, NULL); 89 } 90 91 psStats *stats = params->stats; 92 psS32 maxInputCols = 0; 93 psS32 maxInputRows = 0; 94 psS32 minInputCols = PS_MAX_S32; 95 psS32 minInputRows = PS_MAX_S32; 96 pmReadout *tmpReadout = NULL; 97 psS32 tmpI; 98 psElemType outputType = PS_TYPE_F32; 99 100 if (DetermineNumBits(stats->options) != 1) { 101 psError(PS_ERR_UNKNOWN, true, 102 "Multiple statistical options have been requested. Returning NULL.\n"); 103 return(NULL); 104 } 105 106 // We step through each readout in the input image list. If any readout is 107 // NULL, empty, or has the wrong type, we generate an error and return 108 // NULL. We determine how big of an output image is needed to combine 109 // these input images. We do this by taking the 110 // max(readout->col0 + readout->numCols + image->col0 + image->numCols) 111 // max(readout->row0 + readout->numRows + image->row0 + image->numRows) 112 // 113 for (int i = 0; i < inputs->n; i++) { 114 tmpReadout = inputs->data[i]; 115 PS_ASSERT_READOUT_NON_NULL(tmpReadout, output); 116 PS_ASSERT_READOUT_NON_EMPTY(tmpReadout, output); 117 PS_ASSERT_READOUT_TYPE(tmpReadout, PS_TYPE_F32, output); 118 119 minInputRows = PS_MIN(minInputRows, (tmpReadout->row0 + tmpReadout->image->row0)); 120 tmpI = tmpReadout->row0 + 121 tmpReadout->image->row0 + 122 tmpReadout->image->numRows; 123 maxInputRows = PS_MAX(maxInputRows, tmpI); 124 125 minInputCols = PS_MIN(minInputCols, (tmpReadout->col0 + tmpReadout->image->col0)); 126 tmpI = tmpReadout->col0 + 127 tmpReadout->image->col0 + 128 tmpReadout->image->numCols; 129 maxInputCols = PS_MAX(maxInputCols, tmpI); 130 } 131 132 // We ensure that the zero vector is of the proper size. 133 if (zero != NULL) { 134 PS_ASSERT_VECTOR_TYPE(zero, PS_TYPE_F32, NULL); 135 if (zero->n < inputs->n) { 136 psError(PS_ERR_UNKNOWN, true, "zero vector has incorrect size (%d). Returning NULL.\n", zero->n); 137 return(NULL); 138 } else if (zero->n > inputs->n) { 139 // XXX EAM : abort on this condition? is probably an error 140 psLogMsg(__func__, PS_LOG_WARN, 141 "WARNING: the zero vector too many elements (%d)\n", zero->n); 142 } 143 } 144 145 // We ensure that the scale vector is of the proper size. 146 if (scale != NULL) { 147 PS_ASSERT_VECTOR_TYPE(scale, PS_TYPE_F32, NULL); 148 if (scale->n < inputs->n) { 149 psError(PS_ERR_UNKNOWN, true, "scale vector has incorrect size (%d). Returning NULL.\n", scale->n); 150 return(NULL); 151 } else if (scale->n > inputs->n) { 152 // XXX EAM : abort on this condition? is probably an error 153 psLogMsg(__func__, PS_LOG_WARN, 154 "WARNING: the scale vector has too many elements (%d)\n", scale->n); 155 } 156 } 157 158 // At this point, the following variables have been computed: 159 // maxInputRows: the largest input row value, in output image space. 160 // maxInputCols: the largest input column value, in output image space. 161 // minInputRows: the smallest input row value, in output image space. 162 // minInputCols: the smallest input column value, in output image space. 163 // 164 if (output == NULL) { 165 output = psImageAlloc(maxInputCols-minInputCols, maxInputRows-minInputRows, outputType); 166 *(psS32 *) &(output->col0) = minInputCols; 167 *(psS32 *) &(output->row0) = minInputRows; 168 } else { 169 170 // XXX EAM : recycle the existing output image? why would we care about the existing pixels? 171 PS_ASSERT_IMAGE_TYPE(output, PS_TYPE_F32, NULL); 172 if (((output->col0 + output->numCols) < maxInputCols) || 173 ((output->row0 + output->numRows) < maxInputRows)) { 174 psError(PS_ERR_UNKNOWN, true, 175 "Output image (%d, %d) is too small to hold combined images. Returning NULL.\n", 176 output->row0 + output->numRows, 177 output->col0 + output->numCols); 178 return(NULL); 179 } 180 181 // reset output origin using logic of above 182 *(psS32 *) &(output->col0) = minInputCols; 183 *(psS32 *) &(output->row0) = minInputRows; 184 } 185 186 psVector *tmpPixels = psVectorAlloc(inputs->n, PS_TYPE_F32); 187 psVector *tmpPixelsKeep = psVectorAlloc(inputs->n, PS_TYPE_F32); 188 psVector *outRowLower = psVectorAlloc(inputs->n, PS_TYPE_U32); 189 psVector *outRowUpper = psVectorAlloc(inputs->n, PS_TYPE_U32); 190 psVector *outColLower = psVectorAlloc(inputs->n, PS_TYPE_U32); 191 psVector *outColUpper = psVectorAlloc(inputs->n, PS_TYPE_U32); 192 193 // For each input readout, we store the min/max pixel indices for that readout, in detector coordinates, 194 // in the psVectors (outRowLower, outColLower, outRowUpper, outColUpper). 195 for (int i = 0; i < inputs->n; i++) { 196 tmpReadout = (pmReadout *) inputs->data[i]; 197 outRowLower->data.U32[i] = tmpReadout->row0 + tmpReadout->image->row0; 198 outColLower->data.U32[i] = tmpReadout->col0 + tmpReadout->image->col0; 199 outRowUpper->data.U32[i] = tmpReadout->row0 + 200 tmpReadout->image->row0 + 201 tmpReadout->image->numRows; 202 outColUpper->data.U32[i] = tmpReadout->col0 + 203 tmpReadout->image->col0 + 204 tmpReadout->image->numCols; 205 } 206 207 // We loop through each pixel in the output image. We loop through each 208 // input readout. We determine if that output pixel is contained in the 209 // image from that readout. If so, we save it in psVector tmpPixels. 210 // If not, we set a mask for that element in tmpPixels. Then, we mask off 211 // pixels not between fracLow and fracHigh. Then we call the vector 212 // stats routine on those pixels/mask. Then we set the output pixel value 213 // to the result of the stats call. 214 215 int nx, ny; 216 int nKeep, nMin; 217 float keepFrac = 1.0 - params->fracLow - params->fracHigh; 218 float value = 0; 219 psF32 *saveVector = tmpPixelsKeep->data.F32; 220 221 for (int j = output->row0; j < (output->row0 + output->numRows) ; j++) { 222 if (j % 10 == 0) 223 fprintf (stderr, "."); 224 for (int i = output->col0; i < (output->col0 + output->numCols) ; i++) { 225 int nPix = 0; 226 for (int r = 0; r < inputs->n; r++) { 227 tmpReadout = (pmReadout *) inputs->data[r]; 228 229 // psTrace (__func__, 6, "[%d][%d]: [%d][%d] to [%d][%d]\n", i, j, outColLower->data.U32[r], outRowLower->data.U32[r], outColUpper->data.U32[r], outRowUpper->data.U32[r]); 230 if (i < outColLower->data.U32[r]) 231 continue; 232 if (i >= outColUpper->data.U32[r]) 233 continue; 234 if (j < outRowLower->data.U32[r]) 235 continue; 236 if (j >= outRowUpper->data.U32[r]) 237 continue; 238 239 nx = i - (tmpReadout->col0 + tmpReadout->image->col0); 240 ny = j - (tmpReadout->row0 + tmpReadout->image->row0); 241 242 if (tmpReadout->mask != NULL) { 243 if (tmpReadout->mask->data.U8[ny][nx] && params->maskVal) 244 continue; 245 } 246 247 tmpPixels->data.F32[nPix] = tmpReadout->image->data.F32[ny][nx]; 248 // psTrace (__func__, 6, "readout[%d], image [%d][%d] is %f\n", r, i, j, tmpPixels->data.F32[nPix]); 249 nPix ++; 250 } 251 tmpPixels->n = nPix; 252 253 // are there enough valid pixels to apply fracLow,fracHigh? 254 nKeep = nPix * keepFrac; 255 if (nKeep >= params->nKeep) { 256 psVectorSort (tmpPixels, tmpPixels); 257 nMin = nPix * params->fracLow; 258 tmpPixelsKeep->data.F32 = &tmpPixels->data.F32[nMin]; 259 tmpPixelsKeep->n = nKeep; 260 } else { 261 tmpPixelsKeep->data.F32 = tmpPixels->data.F32; 262 tmpPixelsKeep->n = nPix; 263 } 264 265 // tmpPixelsKeep is already sorted. sample mean and median are very easy 266 if (stats->options & PS_STAT_SAMPLE_MEAN) { 267 value = 0; 268 for (int r = 0; r < tmpPixelsKeep->n; r++) { 269 value += tmpPixelsKeep->data.F32[r]; 270 } 271 if (tmpPixelsKeep->n == 0) { 272 value = 0; 273 } else { 274 value = value / tmpPixelsKeep->n; 275 } 276 } 277 if (stats->options & PS_STAT_SAMPLE_MEDIAN) { 278 int r = tmpPixelsKeep->n / 2; 279 if (tmpPixelsKeep->n == 0) { 280 value = 0; 281 goto got_value; 282 } 283 if (tmpPixelsKeep->n % 2 == 1) { 284 int r = 0.5*tmpPixelsKeep->n; 285 value = tmpPixelsKeep->data.F32[r]; 286 goto got_value; 287 } 288 if (tmpPixelsKeep->n % 2 == 0) { 289 value = 0.5*(tmpPixelsKeep->data.F32[r] + 290 tmpPixelsKeep->data.F32[r-1]); 291 goto got_value; 292 } 293 } 294 got_value: 295 output->data.F32[j-output->row0][i-output->col0] = value; 296 } 297 } 298 tmpPixelsKeep->data.F32 = saveVector; 299 300 psFree(tmpPixels); 301 psFree(tmpPixelsKeep); 302 psFree(outRowLower); 303 psFree(outRowUpper); 304 psFree(outColLower); 305 psFree(outColUpper); 306 307 return(output); 308 } 309 310 /****************************************************************************** 311 XXX: Must add support for S16 and S32 types. F32 currently supported. 312 *****************************************************************************/ 313 psImage *pmReadoutCombine_OLD(psImage *output, 314 const psList *inputs, 315 pmCombineParams *params, 316 const psVector *zero, 317 const psVector *scale, 318 bool applyZeroScale, 319 psF32 gain, 320 psF32 readnoise) 49 321 { 50 322 PS_ASSERT_PTR_NON_NULL(inputs, NULL); … … 410 682 psRegion minRegion; 411 683 psRegion maxRegion; 412 psStats *minStats = psStatsAlloc(PS_STAT_ FITTED_MEAN);413 psStats *maxStats = psStatsAlloc(PS_STAT_ FITTED_MEAN);684 psStats *minStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 685 psStats *maxStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 414 686 psStats *diffStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 415 687 psVector *diffs = psVectorAlloc(fringePoints->n, PS_TYPE_F32); … … 445 717 } 446 718 447 fp->midValue = 0.5 * (maxStats-> fittedMean + minStats->fittedMean);448 fp->delta = maxStats-> fittedMean - minStats->fittedMean;719 fp->midValue = 0.5 * (maxStats->robustMedian + minStats->robustMedian); 720 fp->delta = maxStats->robustMedian - minStats->robustMedian; 449 721 diffs->data.F32[i] = fp->delta; 450 722 } … … 455 727 psFree(diffs); 456 728 if (diffStats == NULL) { 457 psError(PS_ERR_UNKNOWN, true, "Could not determine fittedmedian of the differences.\n");729 psError(PS_ERR_UNKNOWN, true, "Could not determine robust median of the differences.\n"); 458 730 return(NULL); 459 731 } … … 461 733 } 462 734 463 464 465 /**466 *467 * The input array fluxLevels consists of Ni vectors, one per mosaic image.468 * Each vector consists of Nj elements, each a measurement of the input469 * flat-field image flux levels. All of these vectors must be constructed with470 * the same number of elements, or the function will return an error. If a chip471 * is missing from a particular image, that element should be set to NaN. The472 * vector chipGains supplies initial guesses for the chip gains. If the vector473 * contains the values 0.0 or NaN for any of the elements, the gain is set to the474 * mean of the valid values. If the vector length does not match the number of475 * chips, an warning is raised, all chip gain guesses will be set to 1.0, and the476 * vector length modified to match the number of chips defined by the supplied477 * fluxLevels. The sourceFlux input vector must be allocated (not NULL), but the478 * routine will set the vector length to the number of source images regardless479 * of the initial state of the vector. All vectors used by this function must be480 * of type PS_DATA_F64.481 *482 483 fluxLevels(i, j): for each flat field image i, this psArray contains a vector484 with an elemenmt for each chip j. So, fluxLevels(i, j) corresponds to the485 measured flux M_(i, j) for flat image i, chip j.486 487 chipGains[]: has j elements, one for each chip.488 489 490 They have the observed flux levels for each chip of each image. They want to491 solve for the actual flux levels and the gain of each chip.492 493 Okay, they want to solve for source fluxes and chip gains.494 495 *496 */497 bool pmFlatNormalization(498 psVector *sourceFlux,499 psVector *chipGains,500 psArray *fluxLevels)501 {502 PS_ASSERT_PTR_NON_NULL(fluxLevels, false);503 psS32 numImages = fluxLevels->n;504 psS32 numChips = ((psVector *) fluxLevels->data[0])->n;505 for (psS32 i = 0 ; i < numImages ; i++) {506 psVector *tmpVec = (psVector *) fluxLevels->data[i];507 PS_ASSERT_VECTOR_NON_NULL(tmpVec, false);508 PS_ASSERT_VECTOR_TYPE(tmpVec, PS_TYPE_F64, false);509 PS_ASSERT_VECTOR_SIZE(tmpVec, numChips, false);510 }511 512 //513 // Ensure that *localChipGains points to a vector of the same length as numImages.514 //515 PS_ASSERT_PTR_NON_NULL(chipGains, false);516 PS_ASSERT_VECTOR_TYPE(chipGains, PS_TYPE_F64, false);517 psVector *localChipGains = chipGains;518 if (numChips != chipGains->n) {519 psLogMsg(__func__, PS_LOG_WARN, "WARNING: the chipGains vector length does not match the number of chips.\n");520 localChipGains = psVectorAlloc(numChips, PS_TYPE_F64);521 psBool rc = psVectorInit(localChipGains, 1.0);522 if (rc == false) {523 printf("XXX: gen error\n");524 }525 }526 527 //528 // If the chipGains vector contains the values 0.0 or NaN for any of the elements,529 // the gain is set to the mean of the valid values.530 //531 psBool meanFlag = false;532 psVector *chipGainsMask = psVectorAlloc(chipGains->n, PS_TYPE_U8);533 for (psS32 i = 0 ; i < chipGains->n ; i++) {534 if ((fabs(chipGains->data.F64[i]) < FLT_EPSILON) ||535 (isnan(chipGains->data.F64[i]))) {536 chipGainsMask->data.U8[i] = 1;537 meanFlag = true;538 }539 }540 // Must calculate the mean.541 if (meanFlag == true) {542 psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);543 stats = psVectorStats(stats, chipGains, NULL, chipGainsMask, 1);544 if (stats == NULL) {545 printf("XXX: gen error\n");546 }547 psF64 mean;548 psBool rc = p_psGetStatValue(stats, &mean);549 if (rc == false) {550 printf("XXX: gen error\n");551 }552 // Set the gain to this mean for chips with a gain of 0.0 or NAN553 554 for (psS32 i = 0 ; i < chipGains->n ; i++) {555 if ((fabs(chipGains->data.F64[i]) < FLT_EPSILON) ||556 (isnan(chipGains->data.F64[i]))) {557 chipGains->data.F64[i] = mean;558 }559 }560 }561 562 //563 // Assert that sourceFlux is non-NULL, correct type, correct size.564 //565 PS_ASSERT_PTR_NON_NULL(sourceFlux, false);566 PS_ASSERT_VECTOR_TYPE(sourceFlux, PS_TYPE_F64, false);567 psVectorRealloc(sourceFlux, numImages);568 569 // psFree(psVector);570 if (numImages != chipGains->n) {571 psFree(localChipGains);572 }573 574 return(true);575 }
Note:
See TracChangeset
for help on using the changeset viewer.
