Changeset 6873 for trunk/psModules/src/imcombine/pmReadoutCombine.c
- Timestamp:
- Apr 17, 2006, 8:10:08 AM (20 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/imcombine/pmReadoutCombine.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/imcombine/pmReadoutCombine.c
r6511 r6873 5 5 * @author GLG, MHPCC 6 6 * 7 * @version $Revision: 1. 6$ $Name: not supported by cvs2svn $8 * @date $Date: 2006-0 3-04 01:01:33$7 * @version $Revision: 1.7 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2006-04-17 18:10:08 $ 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); … … 418 690 psRegion minRegion; 419 691 psRegion maxRegion; 420 psStats *minStats = psStatsAlloc(PS_STAT_ FITTED_MEAN);421 psStats *maxStats = psStatsAlloc(PS_STAT_ FITTED_MEAN);692 psStats *minStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 693 psStats *maxStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 422 694 psStats *diffStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 423 695 psVector *diffs = psVectorAlloc(fringePoints->n, PS_TYPE_F32); … … 454 726 } 455 727 456 fp->midValue = 0.5 * (maxStats-> fittedMean + minStats->fittedMean);457 fp->delta = maxStats-> fittedMean - minStats->fittedMean;728 fp->midValue = 0.5 * (maxStats->robustMedian + minStats->robustMedian); 729 fp->delta = maxStats->robustMedian - minStats->robustMedian; 458 730 diffs->data.F32[i] = fp->delta; 459 731 } … … 464 736 psFree(diffs); 465 737 if (diffStats == NULL) { 466 psError(PS_ERR_UNKNOWN, true, "Could not determine fittedmedian of the differences.\n");738 psError(PS_ERR_UNKNOWN, true, "Could not determine robust median of the differences.\n"); 467 739 return(NULL); 468 740 } 469 741 return(diffStats); 470 742 } 471 472 473 743 474 744 /**
Note:
See TracChangeset
for help on using the changeset viewer.
