Changeset 2755 for trunk/psModules/src/pmSubtractSky.c
- Timestamp:
- Dec 17, 2004, 4:27:42 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/pmSubtractSky.c (modified) (28 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/pmSubtractSky.c
r2720 r2755 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1. 7$ $Name: not supported by cvs2svn $9 * @date $Date: 2004-12-1 6 00:47:01$8 * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2004-12-18 02:27:42 $ 10 10 * 11 11 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 17 17 #include "pslib.h" 18 18 #include "psConstants.h" 19 20 // XXX: this is pmFit in pmSubtractBias.c, named psFit here. 21 typedef enum { 22 PM_FIT_NONE, ///< No fit 23 PM_FIT_POLYNOMIAL, ///< Fit polynomial 24 PM_FIT_SPLINE ///< Fit cubic splines 25 } psFit; 26 19 #include "pmSubtractSky.h" 20 21 /****************************************************************************** 22 *****************************************************************************/ 27 23 int p_psDetermineNumBits(unsigned int data) 28 24 { … … 40 36 } 41 37 38 /****************************************************************************** 39 *****************************************************************************/ 42 40 psU64 getHighestPriorityStatOption(psU64 statOptions) 43 41 { … … 60 58 } 61 59 62 63 60 /****************************************************************************** 64 61 psImage *binImage(origImage, binFactor, statOptions): This routine takes an … … 67 64 68 65 XXX: use static vectors for myStats, binVector and binMask. 66 XXX: I coded this before I was aware of a psLib reBin function. I don't 67 use this function in this module. I'm keeping it here in the event that 68 requirements change and we might need a custom reBin function. 69 69 *****************************************************************************/ 70 70 psImage *binImage(psImage *origImage, … … 72 72 psStatsOptions statOptions) 73 73 { 74 if (binFactor <= 0) { 75 psLogMsg(__func__, PS_LOG_WARN, 76 "WARNING: binImage(): binFactor is %d\n", binFactor); 77 return(origImage); 78 } 79 if (binFactor == 1) { 80 return(origImage); 81 } 82 74 83 psVector *binVector = psVectorAlloc(binFactor * binFactor, PS_TYPE_F32); 75 84 psVector *binMask = psVectorAlloc(binFactor * binFactor, PS_TYPE_U8); 76 85 psStats *myStats = psStatsAlloc(statOptions); 77 78 if (binFactor <= 0) {79 psLogMsg(__func__, PS_LOG_WARN,80 "WARNING: binImage(): binFactor is %d\n", binFactor);81 return(origImage);82 }83 if (binFactor == 1) {84 return(origImage);85 }86 86 87 87 for (int row = 0; row < origImage->numRows ; row+=binFactor) { … … 115 115 } 116 116 } 117 psFree(myStats);118 117 psFree(binVector); 119 118 psFree(binMask); 119 psFree(myStats); 120 120 121 121 return(origImage); … … 123 123 124 124 /****************************************************************************** 125 buildPolyTerms(): this routine computes a 2-D array polyTerms[] that holds 125 *****************************************************************************/ 126 psS32 CalculatePolyTerms(psS32 xOrder, psS32 yOrder) 127 { 128 psS32 maxOrder = PS_MAX(xOrder, yOrder); 129 psS32 localPolyTerms = 0; 130 psS32 order = 0; 131 psS32 num=0; 132 133 for (order=0;order<=maxOrder;order++) { 134 for (num=0;num<=order;num++) { 135 if (((order-num) <= xOrder) && (num <= yOrder)) { 136 localPolyTerms++; 137 } 138 } 139 } 140 return(localPolyTerms); 141 } 142 143 /****************************************************************************** 144 buildPolyTerms(): this routine computes a 2-D array polyTerms[][] that holds 126 145 terms for the polynomial that is used to model the sky background. We use 127 this array primarily for convenience in many computations involving that sky128 modelpolynomials. It is defined as:146 this array primarily for convenience in computations involving sky model 147 polynomials. It is defined as: 129 148 polyTerms[i][0] = the power to which X is raised in the i-th term of in an 130 149 poly-order sky background polynomial. … … 133 152 poly-order sky background polynomial. 134 153 *****************************************************************************/ 135 psS32 **buildPolyTerms(psS32 polyOrder)154 psS32 **buildPolyTerms(psS32 xOrder, psS32 yOrder) 136 155 { 137 156 psS32 i=0; 138 157 psS32 order = 0; 139 158 psS32 num=0; 140 psS32 localPolyTerms= (((polyOrder+1) * (polyOrder + 2)) / 2); 141 142 // We create the data structure which we hold the xy order of each coeff. 159 psS32 localPolyTerms = CalculatePolyTerms(xOrder, yOrder); 160 psS32 maxOrder = PS_MAX(xOrder, yOrder); 161 162 // Create the data structure which we hold the xy order of each coeff. 143 163 psS32 **polyTerms = (psS32 **) psAlloc(localPolyTerms * sizeof(psS32 *)); 144 164 for (i=0; i < localPolyTerms ; i++) { … … 150 170 // calculates the power to which x/y are raised in that i-th term. 151 171 // We first do the 0-order terms, then the 1-order terms, etc. 152 for (order=0;order<= polyOrder;order++) {172 for (order=0;order<=maxOrder;order++) { 153 173 for (num=0;num<=order;num++) { 154 polyTerms[i][0] = order-num; 155 polyTerms[i][1] = num; 156 i++; 157 } 174 if (((order-num) <= xOrder) && (num <= yOrder)) { 175 polyTerms[i][0] = order-num; 176 polyTerms[i][1] = num; 177 i++; 178 } 179 } 180 } 181 182 // XXX: Get rid of this. 183 for (i=0; i < localPolyTerms ; i++) { 184 psTrace(".psModule.pmSubtractSky.buildPolyTerms", 6, 185 "x^%d * y^%d\n", polyTerms[i][0], polyTerms[i][1]); 158 186 } 159 187 … … 161 189 } 162 190 163 #define PS_TWENTY 20 164 191 /****************************************************************************** 192 This procedure calculates various combinations of powers of x and y and stores 193 them in the data structure sums[][]. After it completes: 194 195 sums[i][j] == x^i * y^j 196 *****************************************************************************/ 165 197 // XXX: Use variable size arrays for polynomial sums. 166 /** @brief This procedure calculates various combinations of powers of x and y 167 * and stores them in the data structure sums[][]. After it completes: 168 * sums[i][j] == x^i * y^j 169 */ 198 #define PS_MAX_POLYNOMIAL_ORDER 20 170 199 void buildSums(psF64 x, 171 200 psF64 y, 172 psF64 sums[PS_TWENTY][PS_TWENTY], 173 psS32 polyOrder) 201 psF64 sums[PS_MAX_POLYNOMIAL_ORDER][PS_MAX_POLYNOMIAL_ORDER], 202 psS32 xOrder, 203 psS32 yOrder) 174 204 { 175 205 psS32 i = 0; … … 180 210 xSum = 1.0; 181 211 ySum = 1.0; 182 for(i=0;i<= polyOrder;i++) {212 for(i=0;i<=xOrder;i++) { 183 213 ySum = xSum; 184 for(j=0;j<= polyOrder;j++) {214 for(j=0;j<=yOrder;j++) { 185 215 sums[i][j] = ySum; 186 216 ySum*= y; … … 191 221 192 222 /****************************************************************************** 193 194 223 *****************************************************************************/ 195 224 psPolynomial2D *ImageFitPolynomial(psPolynomial2D *myPoly, … … 197 226 psImage *maskImage) 198 227 { 228 psTrace(".psModule.pmSubtractSky.ImageFitPolynomial", 4, 229 "---- ImageFitPolynomial() begin ----\n"); 199 230 PS_POLY_CHECK_NULL(myPoly, NULL); 200 231 PS_POLY_CHECK_TYPE(myPoly, PS_POLYNOMIAL_ORD, NULL); 201 PS_INT_CHECK_NON_EQUALS(myPoly->nX, myPoly->nY, NULL);202 232 PS_IMAGE_CHECK_NULL(binnedImage, NULL); 203 233 PS_IMAGE_CHECK_EMPTY(binnedImage, NULL); … … 207 237 PS_IMAGE_CHECK_TYPE(maskImage, PS_TYPE_U8, NULL); 208 238 PS_IMAGE_CHECK_SIZE_EQUAL(binnedImage, maskImage, NULL); 239 psS32 oldPolyX = -1; 240 psS32 oldPolyY = -1; 241 242 // The matrix equations become singular if there are more powers of X 243 // in myPoly then there are rows of the image. I think. Similarly for 244 // powers of Y and columns. So. Here we reduce the complexity of the 245 // polynomial if there are not enough rows/columns in the input image. 246 247 if (myPoly->nX > binnedImage->numRows) { 248 psLogMsg(__func__, PS_LOG_WARN, 249 "WARNING: ImageFitPolynomial(): Reducing polynomial complexity in x-dimension.\n"); 250 oldPolyX = myPoly->nX; 251 myPoly->nX = binnedImage->numRows; 252 } 253 if (myPoly->nY > binnedImage->numCols) { 254 psLogMsg(__func__, PS_LOG_WARN, 255 "WARNING: ImageFitPolynomial(): Reducing polynomial complexity in y-dimension.\n"); 256 oldPolyY = myPoly->nY; 257 myPoly->nY = binnedImage->numCols; 258 } 209 259 psS32 i; 210 260 psS32 j; … … 213 263 psS32 aRow; 214 264 psS32 aCol; 215 psS32 polyOrder = myPoly->nX; 216 psS32 localPolyTerms= (((polyOrder+1) * (polyOrder + 2)) / 2); 217 psS32 **polyTerms = buildPolyTerms(polyOrder); 218 psF64 sums[PS_TWENTY][PS_TWENTY]; 219 psImage *A = psImageAlloc(localPolyTerms+1, localPolyTerms+1, PS_TYPE_F64); 220 psVector *B = psVectorAlloc(localPolyTerms+1, PS_TYPE_F64); 221 psVector *outPerm = NULL; 265 // XXX: Document this. The myPoly->nX and ->nY terms are actual 1 larger 266 // than the order of the polynomial. 267 psS32 **polyTerms = buildPolyTerms(myPoly->nX-1, myPoly->nY-1); 268 psS32 localPolyTerms = CalculatePolyTerms(myPoly->nX-1, myPoly->nY-1); 269 psF64 sums[PS_MAX_POLYNOMIAL_ORDER][PS_MAX_POLYNOMIAL_ORDER]; 270 psImage *A = psImageAlloc(localPolyTerms, localPolyTerms, PS_TYPE_F64); 271 psImage *Aout = psImageAlloc(localPolyTerms, localPolyTerms, PS_TYPE_F64); 272 psVector *B = psVectorAlloc(localPolyTerms, PS_TYPE_F64); 273 psVector *outPerm = psVectorAlloc(localPolyTerms, PS_TYPE_F64); 222 274 223 275 for(i=0;i<A->numRows;i++) { … … 232 284 for (x=0;x<binnedImage->numRows;x++) { 233 285 for (y=0;y<binnedImage->numCols;y++) { 234 if (maskImage->data.U8[x][y] != 0) {235 buildSums((psF64) x, (psF64) y, sums, polyOrder);286 if (maskImage->data.U8[x][y] == 0) { 287 buildSums((psF64) x, (psF64) y, sums, myPoly->nX-1, myPoly->nY-1); 236 288 237 289 /************************************************************ 238 Equation (7) from the ADD describes 16 linear equations.290 Equation (7) from the pilot ADD describes 16 linear equations. 239 291 The i-th equation is simply the partial derivative of the 240 292 sky background polynomial (1) w.r.t. to the i-th term in … … 251 303 } 252 304 } 253 254 305 // Build the B[] vector, which is the right-hand side of (7). 255 for (i=0;i< =localPolyTerms;i++) {306 for (i=0;i<localPolyTerms;i++) { 256 307 B->data.F64[i]+= binnedImage->data.F32[x][y] * 257 308 sums[ polyTerms[i][0] ][ polyTerms[i][1] ]; … … 260 311 } 261 312 } 262 psImage *ALUD = psMatrixLUD(NULL, outPerm, A); 263 psVector *C = psMatrixLUSolve(C, ALUD, B, outPerm); 264 313 314 // XXX: Put this loop inside a psTrace conditional, somehow. 315 for (aRow=0;aRow<localPolyTerms;aRow++) { 316 for (aCol=0;aCol<localPolyTerms;aCol++) { 317 psTrace(".psModule.pmSubtractSky.ImageFitPolynomial", 6, 318 "A[%d][%d] is %f\n", aRow, aCol, A->data.F64[aRow][aCol]); 319 } 320 } 321 // XXX: Put this loop inside a psTrace conditional, somehow. 322 for (i=0;i<=localPolyTerms;i++) { 323 psTrace(".psModule.pmSubtractSky.ImageFitPolynomial", 6, 324 "B[%d] is %f\n", i, B->data.F64[i]); 325 } 326 327 328 // Solve the matrix equations for the polynomial coefficients C. 329 Aout = psMatrixLUD(Aout, outPerm, A); 330 psVector *C = psVectorAlloc(localPolyTerms, PS_TYPE_F64); 331 psMatrixLUSolve(C, Aout, B, outPerm); 332 333 // Set the appropriate coefficients in the myPoly structure. 265 334 for (i=0;i<localPolyTerms;i++) { 266 335 myPoly->coeff[ polyTerms[i][0] ][ polyTerms[i][1] ] = C->data.F64[i]; 267 } 268 336 psTrace(".psModule.pmSubtractSky.ImageFitPolynomial", 6, 337 "myPoly->coeff[%d][%d] is %f\n", polyTerms[i][0], polyTerms[i][1], myPoly->coeff[ polyTerms[i][0] ][ polyTerms[i][1] ]); 338 } 339 340 // Free data structures that were allocated in this module. 269 341 for (i=0;i<localPolyTerms;i++) { 270 342 psFree(polyTerms[i]); … … 272 344 psFree(polyTerms); 273 345 psFree(A); 274 psFree(A LUD);346 psFree(Aout); 275 347 psFree(B); 276 348 psFree(C); 277 349 psFree(outPerm); 278 350 351 // We restore the original size of the polynomial and set remaining 352 // coefficients to 0.0. 353 if (oldPolyX != -1) { 354 myPoly->nX = oldPolyX; 355 for (i=oldPolyX ; i < myPoly->nX ; i++) { 356 for (j=0;j<myPoly->nY ; j++) { 357 myPoly->coeff[i][j] = 0.0; 358 } 359 } 360 } 361 if (oldPolyY != -1) { 362 myPoly->nY = oldPolyY; 363 for (i=0 ; i < myPoly->nX ; i++) { 364 for (j=oldPolyY;j<myPoly->nY ; j++) { 365 myPoly->coeff[i][j] = 0.0; 366 } 367 } 368 } 369 370 psTrace(".psModule.pmSubtractSky.ImageFitPolynomial", 4, 371 "---- ImageFitPolynomial() end successfully ----\n"); 279 372 return(myPoly); 280 373 } … … 293 386 float clipSD) 294 387 { 388 psTrace(".psModule.pmSubtractSky", 4, 389 "---- pmSubtractSky() begin ----\n"); 390 295 391 // Return the original input readout if the fit specs are poorly defined. 296 392 if ((fitSpec == NULL) || … … 299 395 } 300 396 psImage *origImage = in->image; 301 psImage *maskImage = in->mask;302 397 psImage *binnedImage = NULL; 303 398 psPolynomial2D *myPoly; 399 psImage *binnedMaskImage = NULL; 304 400 305 401 psStatsOptions statOptions = stats->options; 306 if (1 <p_psDetermineNumBits(statOptions)) {402 if (1 > p_psDetermineNumBits(statOptions)) { 307 403 //XXX psWarning(PS_ERR_UNKNOWN,true, "Multiple statistical options have been requested.\n"); 308 404 statOptions = getHighestPriorityStatOption(statOptions); 405 // XXX: Don't modify input parameter. 406 stats->options = statOptions; 309 407 if (statOptions <= 0) { 310 408 psLogMsg(__func__, PS_LOG_WARN, … … 314 412 } 315 413 414 // 415 // Generate required warning messages. 416 // 417 if (0 == p_psDetermineNumBits(statOptions)) { 418 psLogMsg(__func__, PS_LOG_WARN, 419 "WARNING: pmSubtractSky(): no stats->options was requested\n"); 420 } 421 if (binFactor <= 0) { 422 psLogMsg(__func__, PS_LOG_WARN, 423 "WARNING: pmSubtractSky(): binFactor is %d\n", binFactor); 424 } 425 if (stats == NULL) { 426 psLogMsg(__func__, PS_LOG_WARN, 427 "WARNING: pmSubtractSky(): input parameter stats is NULL\n"); 428 } 429 430 // 316 431 // Bin the input image according to input parameters. 317 if ((binFactor <= 0) || (stats == NULL)) { 318 // Simply use the original image: no binning. 319 if (binFactor <= 0) { 320 psLogMsg(__func__, PS_LOG_WARN, 321 "WARNING: pmSubtractSky(): binFactor is %d\n", binFactor); 322 } 323 if (stats == NULL) { 324 psLogMsg(__func__, PS_LOG_WARN, 325 "WARNING: pmSubtractSky(): input parameter stats is NULL\n"); 326 } 327 binnedImage = origImage; 432 // 433 if ((binFactor <= 1) || 434 (stats == NULL) || 435 (0 == p_psDetermineNumBits(statOptions))) { 436 binnedImage = psImageCopy(binnedImage, origImage, PS_TYPE_F32); 328 437 } else { 329 // Call a private function to do the binning. 330 binnedImage = binImage(origImage, binFactor, statOptions); 331 } 332 438 // Add the original image mask in here. 439 binnedImage = psImageCopy(binnedImage, origImage, PS_TYPE_F32); 440 binnedImage = psImageRebin(NULL, binnedImage, NULL, 0, binFactor, stats); 441 } 442 psTrace(".psModule.pmSubtractSky", 4, 443 "binnedImage size is (%d, %d)\n", binnedImage->numRows, binnedImage->numCols); 444 445 // 333 446 // Clip pixels that are outside the acceptable range. 447 // 334 448 if (clipSD <= 0.0) { 335 449 psLogMsg(__func__, PS_LOG_WARN, … … 342 456 myStats = psImageStats(myStats, binnedImage, NULL, 0); 343 457 p_psGetStatValue(myStats, &binnedMean); 458 psTrace(".psModule.pmSubtractSky", 8, 459 "binned Mean is %f\n", binnedMean); 344 460 345 461 myStats->options = PS_STAT_SAMPLE_STDEV; … … 347 463 p_psGetStatValue(myStats, &binnedStdev); 348 464 psFree(myStats); 465 psTrace(".psModule.pmSubtractSky", 8, 466 "binned StDev is %f\n", binnedStdev); 349 467 350 468 // Clip all pixels which are more than clipSD sigmas from the mean. … … 352 470 // XXX: we must unset this later since we modify the image mask. 353 471 // XXX: Determine which pixels, mask or image, should be clipped. 472 473 binnedMaskImage = psImageAlloc(binnedImage->numCols, 474 binnedImage->numRows, 475 PS_TYPE_U8); 476 477 psTrace(".psModule.pmSubtractSky", 8, 478 "clipSD is %f\n", clipSD); 479 354 480 for (int row = 0; row < binnedImage->numRows ; row++) { 355 481 for (int col = 0; col < binnedImage->numCols ; col++) { 356 482 if (fabs(binnedImage->data.F32[row][col] - binnedMean) > 357 483 (clipSD * binnedStdev)) { 358 maskImage->data.U8[row][col] = 1;484 binnedMaskImage->data.U8[row][col] = 1; 359 485 } 360 486 } … … 362 488 } 363 489 364 // XXX: fit the polynomial to the binned image 490 // 491 // Fit the polynomial to the binned image 492 // 365 493 if (fit == PM_FIT_POLYNOMIAL) { 366 494 myPoly = (psPolynomial2D *) fitSpec; 367 368 // XXX Ensure that the polynomial is of type Chebyshev. 369 myPoly = ImageFitPolynomial(myPoly, binnedImage, maskImage); 370 371 // XXX Do we need to do something with ordinate scaling if Chebyshev? 372 binnedImage = psImageEvalPolynomial(binnedImage, myPoly); 373 } 374 495 PS_POLY_CHECK_NULL(myPoly, NULL); 496 PS_POLY_CHECK_TYPE(myPoly, PS_POLYNOMIAL_ORD, NULL); 497 498 myPoly = ImageFitPolynomial(myPoly, binnedImage, binnedMaskImage); 499 500 if (myPoly != NULL) { 501 // XXX:Add ordinary polynomials to psImageEvalPolynomial() 502 for (int row = 0; row < binnedImage->numRows ; row++) { 503 for (int col = 0; col < binnedImage->numCols ; col++) { 504 binnedImage->data.F32[row][col] = 505 psPolynomial2DEval(myPoly, (psF32) row, (psF32) col); 506 psTrace(".psModule.pmSubtractSky", 8, 507 "binned Image[%d][%d] is %f\n", 508 row, col, binnedImage->data.F32[row][col]); 509 } 510 } 511 } else { 512 psLogMsg(__func__, PS_LOG_WARN, 513 "WARNING: pmSubtractSky(): could not model sky with a polynomial.\n"); 514 psFree(binnedMaskImage); 515 if (!((binFactor <= 1) || (stats == NULL))) { 516 psFree(binnedImage); 517 } 518 return(in); 519 } 520 } else { 521 //XXX: error 522 } 523 524 // 375 525 //Subtract the polynomially fitted image from the original image 376 if (binFactor <= 0) { 526 // 527 if (binFactor <= 1) { 377 528 // The binned image is the same size as the original image. 378 529 for (int row = 0; row < origImage->numRows ; row++) { … … 384 535 for (int row = 0; row < origImage->numRows ; row++) { 385 536 for (int col = 0; col < origImage->numCols ; col++) { 386 int binRow = row / binFactor; 387 int binCol = col / binFactor; 388 origImage->data.F32[row][col]-= binnedImage->data.F32[binRow][binCol]; 389 } 390 } 391 392 } 393 394 if (!((binFactor <= 0) || (stats == NULL))) { 537 // We calculate the F32 value of the pixel coordinates in the 538 // binned image and then use a pixel interpolation routine to 539 // determine the value of the pixel at that location. 540 psF32 binRowF64 = ((psF32) row) / ((psF32) binFactor); 541 psF32 binColF64 = ((psF32) col) / ((psF32) binFactor); 542 543 // We add 0.5 to the pixel locations since the pixel 544 // interpolation routine defines the location of pixel 545 // (i, j) as (i+0.5, j+0.5). 546 binRowF64+= 0.5; 547 binColF64+= 0.5; 548 549 psF32 binPixel = (psF32) psImagePixelInterpolate( 550 binnedImage, binRowF64, binColF64, 551 NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR); 552 origImage->data.F32[row][col]-= binPixel; 553 554 psTrace(".psModule.pmSubtractSky", 8, 555 "image[%d][%d] <--> binnedImage[%.2f][%.2f]: %f (%f)\n", 556 row, col, binRowF64-0.5, binColF64-0.5, binPixel, 557 binnedImage->data.F32[(psS32)binRowF64][(psS32)binColF64]); 558 } 559 } 560 561 } 562 563 psFree(binnedMaskImage); 564 if (!((binFactor <= 1) || (stats == NULL))) { 395 565 psFree(binnedImage); 396 566 } 397 567 568 psTrace(".psModule.pmSubtractSky", 4, 569 "---- pmSubtractSky() exit successfully ----\n"); 398 570 return(in); 399 571 }
Note:
See TracChangeset
for help on using the changeset viewer.
