Changeset 29543
- Timestamp:
- Oct 25, 2010, 2:45:41 PM (16 years ago)
- Location:
- trunk/psModules/src/imcombine
- Files:
-
- 14 edited
- 2 copied
-
README (copied) (copied from branches/eam_branches/ipp-20100823/psModules/src/imcombine/README )
-
pmPSFEnvelope.c (modified) (1 diff)
-
pmStack.c (modified) (30 diffs)
-
pmSubtraction.c (modified) (1 diff)
-
pmSubtractionAnalysis.c (modified) (1 diff)
-
pmSubtractionAnalysis.h (modified) (1 diff)
-
pmSubtractionEquation.c (modified) (47 diffs)
-
pmSubtractionEquation.h (modified) (1 diff)
-
pmSubtractionEquation.v0.c (copied) (copied from branches/eam_branches/ipp-20100823/psModules/src/imcombine/pmSubtractionEquation.v0.c )
-
pmSubtractionKernels.c (modified) (6 diffs)
-
pmSubtractionKernels.h (modified) (1 diff)
-
pmSubtractionMatch.c (modified) (19 diffs)
-
pmSubtractionMatch.h (modified) (1 diff)
-
pmSubtractionStamps.c (modified) (23 diffs)
-
pmSubtractionStamps.h (modified) (2 diffs)
-
pmSubtractionVisual.c (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/imcombine/pmPSFEnvelope.c
r29004 r29543 380 380 381 381 // measure the source moments: tophat windowing, no pixel S/N cutoff 382 // XXX probably should be passing the maskVal to this function so we can pass it along here... 383 if (!pmSourceMoments(source, maxRadius, 0.0, 1.0, maskVal)) { 382 if (!pmSourceMoments(source, maxRadius, 0.0, 0.0, maskVal)) { 384 383 // Can't do anything about it; limp along as best we can 385 384 psErrorClear(); -
trunk/psModules/src/imcombine/pmStack.c
r27427 r29543 19 19 20 20 #include <stdio.h> 21 #include <string.h> // for memset 21 22 #include <pslib.h> 22 23 … … 34 35 35 36 36 //#define TESTING // Enable test output 37 //#define TEST_X 843-1 // x coordinate to examine 38 //#define TEST_Y 813-1 // y coordinate to examine 39 //#define TEST_RADIUS 0 // Radius to examine 40 37 # if (0) 38 #define TESTING // Enable test output 39 #define TEST_X 4963 // x coordinate to examine 40 #define TEST_Y 5353 // y coordinate to examine 41 #define TEST_X 40 // x coordinate to examine 42 #define TEST_Y 40 // y coordinate to examine 43 #define TEST_RADIUS 0.5 // Radius to examine 44 # endif 45 46 # ifdef TESTING 47 # define CHECKPIX(XPIX,YPIX,MSG,...) { if (PS_SQR(XPIX - TEST_X) + PS_SQR(YPIX - TEST_Y) <= PS_SQR(TEST_RADIUS)) { fprintf(stderr,MSG,__VA_ARGS__); } } 48 # else 49 # define CHECKPIX(XPIX,YPIX,MSG,...) { } 50 # endif 41 51 42 52 // Data structure for use as a buffer when combining pixels … … 250 260 ) 251 261 { 252 #ifdef TESTING 253 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 254 fprintf(stderr, "Marking image %d, pixel %d,%d for inspection\n", source, x, y); 255 } 256 #endif 262 CHECKPIX(x, y, "Marking image %d, pixel %d,%d for inspection\n", source, x, y); 257 263 pmStackData *data = inputs->data[source]; // Stack data of interest 258 264 if (!data) { … … 272 278 ) 273 279 { 274 #ifdef TESTING 275 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 276 fprintf(stderr, "Marking pixel image %d, pixel %d,%d for rejection\n", source, x, y); 277 } 278 #endif 280 CHECKPIX(x, y, "Marking pixel image %d, pixel %d,%d for rejection\n", source, x, y); 279 281 pmStackData *data = inputs->data[source]; // Stack data of interest 280 282 if (!data) { … … 290 292 static void combineExtract(int *num, // Number of good pixels 291 293 bool *suspect, // Any suspect pixels? 294 psImageMaskType *badMask, // OR of all bad (masked) pixels 295 psImageMaskType *goodMask, // OR of all good (unmasked) pixels 292 296 combineBuffer *buffer, // Buffer with vectors 293 297 psImage *image, // Combined image, for output … … 300 304 const psVector *reject, // Indices of pixels to reject, or NULL 301 305 int x, int y, // Coordinates of interest; frame of output image 302 psImageMaskType maskVal, // Value to mask303 psImageMaskType maskSuspect // Value to suspect306 psImageMaskType badMaskBits, // Value to mask as 'bad' 307 psImageMaskType suspectMaskBits // Value to mask as 'suspect' 304 308 ) 305 309 { … … 322 326 } 323 327 328 // mask values to store possible mask combinations 329 *badMask = 0; 330 *goodMask = 0xffff; 331 332 int nGoodBits[16]; // accumulate the good pixel bits here for fuzzy logic 333 psAssert (sizeof(psImageMaskType) == 2, "psImageMaskType is not the expected size"); 334 memset (nGoodBits, 0, 16*sizeof(int)); 335 324 336 // Extract the pixel and mask data 325 337 int numGood = 0; // Number of good pixels … … 328 340 // should be because of how pixelMapGenerate works 329 341 if (reject && reject->data.U16[j] == i) { 342 // pixels can be rejected because: 343 // 1) only 1 input pixel (and 'safe' is true) 344 // 2) only 2 input pixels were available and they were mutually inconsistent (or variance info was missing) 345 // 3) NOTE : ifdef'ed out code for 3 inputs case 346 // 4) outlier from sample of N pixels 347 // 5) some of these may have been suspect. 348 // XXX raise a specific mask bit for these (currently results in BLANK) 330 349 j++; 350 351 pmStackData *data = inputs->data[i]; // Stack data of interest 352 if (data) { 353 int xIn = x - data->readout->col0, yIn = y - data->readout->row0; // Coordinates on input readout 354 psImage *mask = data->readout->mask; // Mask of interest 355 *badMask |= mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn]; // save the bad bits used 356 CHECKPIX(x, y, "reject: adding bit to mask: %d : %x (badMask = %x)\n", i, mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn], *badMask); 357 } else { 358 CHECKPIX(x, y, "reject: no item in data (badMask = %x)\n", *badMask); 359 } 331 360 continue; 332 361 } … … 334 363 pmStackData *data = inputs->data[i]; // Stack data of interest 335 364 if (!data) { 365 CHECKPIX(x, y, "skip: no item in data (badMask = %x)\n", *badMask); 336 366 continue; 337 367 } … … 339 369 int xIn = x - data->readout->col0, yIn = y - data->readout->row0; // Coordinates on input readout 340 370 psImage *mask = data->readout->mask; // Mask of interest 341 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & maskVal) { 371 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & badMaskBits) { 372 *badMask |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & badMaskBits); // save the bad bits used 373 CHECKPIX(x, y, "skip: adding bit to mask: %d : %x (badMask = %x)\n", i, mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn], *badMask); 342 374 continue; 343 375 } 344 376 345 pixelSuspects->data.U8[numGood] = mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & maskSuspect ? 346 true : false; 377 pixelSuspects->data.U8[numGood] = mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & suspectMaskBits ? true : false; 378 379 // *goodMask &= mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn]; // save the mask bits still used 380 // check for set bits and increment counter as appropriate 381 { 382 psImageMaskType value = 0x0001; 383 for (int nbit = 0; nbit < 16; nbit ++) { 384 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & value) { 385 nGoodBits[nbit] ++; 386 } 387 value <<= 1; 388 } 389 } 347 390 348 391 psImage *image = data->readout->image; // Image of interest … … 356 399 pixelSources->data.U16[numGood] = i; 357 400 numGood++; 401 402 CHECKPIX(x, y, "keep: %d : %x (badMask = %x)\n", i, mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn], *badMask); 358 403 } 359 404 pixelData->n = numGood; … … 367 412 *num = numGood; 368 413 414 // set the mask bits if nGoodBits[i] > f*numGood 415 { 416 # define SUSPECT_FRACTION 0.65 417 *goodMask = 0x0000; 418 psImageMaskType value = 0x0001; 419 for (int nbit = 0; nbit < 16; nbit ++) { 420 if (nGoodBits[nbit] > SUSPECT_FRACTION*numGood) { 421 *goodMask |= value; 422 } 423 value <<= 1; 424 } 425 } 426 369 427 #ifdef TESTING 370 428 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 371 429 for (int i = 0; i < numGood; i++) { 372 fprintf(stderr, "Input %d, pixel %d,%d (%" PRIu16 "): %f %f (%f) %f %f %d \n",430 fprintf(stderr, "Input %d, pixel %d,%d (%" PRIu16 "): %f %f (%f) %f %f %d %x %x -> %x %x\n", 373 431 i, x, y, pixelSources->data.U16[i], pixelData->data.F32[i], pixelVariances->data.F32[i], 374 432 addVariance->data.F32[i], pixelWeights->data.F32[i], pixelExps->data.F32[i], 375 pixelSuspects->data.U8[i] );433 pixelSuspects->data.U8[i], badMaskBits, suspectMaskBits, *badMask, *goodMask); 376 434 } 377 435 } … … 380 438 return; 381 439 } 382 383 440 384 441 // Combine pixels … … 392 449 combineBuffer *buffer, // Buffer with vectors 393 450 int x, int y, // Coordinates of interest; frame of output image 394 psImageMaskType bad, // Value for bad pixels 451 psImageMaskType blankMask, // Value for empty pixels 452 psImageMaskType badMask, // Value for bad pixels 453 psImageMaskType goodMask, // Value for good pixels 395 454 bool safe, // Safe combination? 396 455 float invTotalWeight // Inverse of total weight for all inputs … … 404 463 // Default option is that the pixel is bad 405 464 float imageValue = NAN, varianceValue = NAN; // Value for combined image and variance map 406 psImageMaskType maskValue = bad; // Value for combined mask407 465 float expValue = 0.0, expWeightValue = NAN; // Exposure value (straight, and weighted) 466 467 // default output mask value. badMask is the OR of all unused input pixels. 468 // if there are no input pixels, this value will be 0, in which case we want to set the output pixel to BLANK. 469 // if there are only good input pixels, and they do not result in a valid pixel, we still want to set this to BLANK. 470 psImageMaskType maskValue = badMask ? badMask : blankMask; // Value for combined mask 471 472 CHECKPIX(x, y, "bad vs good : %x %x %x\n", maskValue, badMask, blankMask); 408 473 409 474 switch (num) { 410 475 case 0: { 411 476 // Nothing to combine: it's bad 412 #ifdef TESTING 413 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 414 fprintf(stderr, "No inputs to combine, pixel %d,%d is bad.\n", x, y); 415 } 416 #endif 477 CHECKPIX(x, y, "No inputs to combine, pixel %d,%d is bad.\n", x, y); 417 478 break; 418 479 } … … 428 489 expWeightValue = pixelExps->data.F32[0]; 429 490 } 430 maskValue = 0; 431 #ifdef TESTING 432 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 433 fprintf(stderr, "Single input to combine, safety off, pixel %d,%d --> %f\n", 434 x, y, imageValue); 435 } 436 #endif 437 } 438 #ifdef TESTING 439 else if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 440 fprintf(stderr, "Single input to combine, safety on, pixel %d,%d is bad.\n", x, y); 441 } 442 #endif 491 maskValue = goodMask; 492 CHECKPIX(x, y, "Single input to combine, safety off, pixel %d,%d --> %f\n", x, y, imageValue); 493 } else { 494 CHECKPIX(x, y, "Single input to combine, safety on, pixel %d,%d is bad.\n", x, y); 495 } 443 496 break; 444 497 } … … 446 499 // Automatically accept the mean of the pixels only if we're not playing safe 447 500 if (!safe) { 448 if (combinationMeanVariance(&imageValue, &varianceValue, &expValue, &expWeightValue, 449 pixelData, pixelVariances, pixelExps, pixelWeights)) { 450 maskValue = 0; 451 #ifdef TESTING 452 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 453 fprintf(stderr, "Two inputs to combine using unsafe, pixel %d,%d --> %f %f\n", 454 x, y, imageValue, varianceValue); 455 } 456 #endif 501 if (combinationMeanVariance(&imageValue, &varianceValue, &expValue, &expWeightValue, pixelData, pixelVariances, pixelExps, pixelWeights)) { 502 maskValue = goodMask; 503 CHECKPIX(x, y, "Two inputs to combine using unsafe, pixel %d,%d --> %f %f\n", x, y, imageValue, varianceValue); 457 504 } 505 } else { 506 CHECKPIX(x, y, "Two inputs to combine, safety on, pixel %d,%d is bad\n", x, y); 458 507 } 459 #ifdef TESTING460 else {461 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) {462 fprintf(stderr, "Two inputs to combine, safety on, pixel %d,%d is bad\n", x, y);463 }464 }465 #endif466 508 break; 467 509 } … … 472 514 break; 473 515 } 474 maskValue = 0; 475 #ifdef TESTING 476 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 477 fprintf(stderr, "Combined inputs, pixel %d,%d --> %f %f\n", x, y, imageValue, varianceValue); 478 } 479 #endif 516 maskValue = goodMask; 517 CHECKPIX(x, y, "Combined inputs, pixel %d,%d --> %f %f\n", x, y, imageValue, varianceValue); 480 518 break; 481 519 } … … 522 560 int numIter = PS_MAX(iter * num, 1); // Number of iterations 523 561 524 #ifdef TESTING 525 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 526 fprintf(stderr, "Testing pixel %d,%d: %d %f %f %f %d %d\n", 527 x, y, numIter, rej, sys, olympic, useVariance, safe); 528 } 529 #endif 562 CHECKPIX(x, y, "Testing pixel %d,%d: %d %f %f %f %d %d\n", x, y, numIter, rej, sys, olympic, useVariance, safe); 530 563 531 564 psVector *pixelData = buffer->pixels; // Values for the pixel of interest … … 548 581 // Systematic error contributes to the rejection level 549 582 float sysVar = PS_SQR(sys * pixelData->data.F32[i]); 550 #ifdef TESTING 551 // Correct variance for comparison against weighted mean including itself 552 float compare = 1.0 - pixelWeights->data.F32[i] / sumWeights; 553 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 554 fprintf(stderr, "Variance %d (%d), pixel %d,%d: %f %f %f\n", i, pixelSources->data.U16[i], 555 x, y, pixelVariances->data.F32[i], sysVar, compare); 556 } 557 #endif 583 CHECKPIX(x, y, "Variance %d (%d), pixel %d,%d: %f %f %f\n", 584 i, pixelSources->data.U16[i], x, y, 585 pixelVariances->data.F32[i], sysVar, 1.0 - pixelWeights->data.F32[i] / sumWeights); 558 586 pixelLimits->data.F32[i] = rej2 * (pixelVariances->data.F32[i] + sysVar); 559 587 } … … 593 621 combineMarkInspect(inputs, x, y, pixelSources->data.U16[1]); 594 622 } 595 #ifdef TESTING 596 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 597 fprintf(stderr, "Flagged both inputs for pixel %d,%d (%f > %f x %f\n)", 598 x, y, diff, rej, sqrtf(sigma2)); 599 } 600 #endif 623 CHECKPIX(x, y, "Flagged both inputs for pixel %d,%d (%f > %f x %f\n)", x, y, diff, rej, sqrtf(sigma2)); 601 624 } 602 625 } else if (i == 0 && safe) { … … 708 731 float median = combinationWeightedOlympic(pixelData, pixelWeights, 709 732 olympic, buffer->sort); // Median for stack 710 #ifdef TESTING 711 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 712 fprintf(stderr, "Flag with variance pixel %d,%d: median = %f\n", x, y, median); 713 } 714 #endif 733 CHECKPIX(x, y, "Flag with variance pixel %d,%d: median = %f\n", x, y, median); 715 734 float worst = -INFINITY; // Largest deviation 716 735 for (int j = 0; j < num; j++) { 717 736 float diff = pixelData->data.F32[j] - median; // Difference from expected 718 #ifdef TESTING 719 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 720 fprintf(stderr, "Testing input %d for pixel %d,%d: %f\n", j, x, y, diff); 721 } 722 #endif 737 CHECKPIX(x, y, "Testing input %d for pixel %d,%d: %f\n", j, x, y, diff); 723 738 724 739 // Comparing squares --- cheaper than lots of sqrts … … 737 752 combinationMedianStdev(&median, &stdev, pixelData, buffer->sort); 738 753 float limit = rej * stdev; // Rejection limit 739 #ifdef TESTING 740 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 741 fprintf(stderr, 742 "Flag without variance pixel %d,%d; median = %f, stdev = %f, limit = %f\n", 743 x, y, median, stdev, limit); 744 } 745 #endif 754 CHECKPIX(x, y, "Flag without variance pixel %d,%d; median = %f, stdev = %f, limit = %f\n", x, y, median, stdev, limit); 746 755 float worst = -INFINITY; // Largest deviation 747 756 for (int j = 0; j < num; j++) { … … 763 772 if (maskIndex >= 0) { 764 773 if (suspect) { 765 #ifdef TESTING 766 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 767 fprintf(stderr, "Throwing out all suspect pixels for %d,%d\n", x, y); 768 } 769 #endif 774 CHECKPIX(x, y, "Throwing out all suspect pixels for %d,%d\n", x, y); 770 775 // Throw out all suspect pixels 771 776 int numGood = 0; // Number of good pixels … … 796 801 } else { 797 802 // Throw out masked pixel 798 #ifdef TESTING 799 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 800 fprintf(stderr, "Throwing out input %d for pixel %d,%d\n", maskIndex, x, y); 801 } 802 #endif 803 CHECKPIX(x, y, "Throwing out input %d for pixel %d,%d\n", maskIndex, x, y); 803 804 combineMarkInspect(inputs, x, y, pixelSources->data.U16[maskIndex]); 804 805 int numGood = 0; // Number of good pixels … … 999 1000 1000 1001 /// Stack input images 1001 bool pmStackCombine(pmReadout *combined, pmReadout *expmaps, psArray *input, 1002 psImageMaskType maskVal, psImageMaskType maskSuspect, 1003 psImageMaskType bad, int kernelSize, 1004 float iter, float rej, float sys, float olympic, 1005 bool useVariance, bool safe, bool rejection) 1002 bool pmStackCombine( 1003 pmReadout *combined, // output stacked readout 1004 pmReadout *expmaps, // output exposure map information 1005 psArray *input, // input exposures 1006 psImageMaskType badMaskBits, // treat these bits as 'bad' 1007 psImageMaskType suspectMaskBits, // treat these bits as 'suspect' 1008 psImageMaskType blankMaskBits, // use this mask value for pixels missing input data (distinguish between Ninput = 0 and Ngood = 0?) 1009 int kernelSize, 1010 float iter, 1011 float rej, 1012 float sys, 1013 float olympic, 1014 bool useVariance, 1015 bool safe, 1016 bool rejection) 1006 1017 { 1007 1018 bool haveVariances; // Do we have the variance maps? … … 1012 1023 } 1013 1024 PS_ASSERT_INT_NONNEGATIVE(kernelSize, false); 1014 PS_ASSERT_INT_POSITIVE(b ad, false);1025 PS_ASSERT_INT_POSITIVE(blankMaskBits, false); 1015 1026 if (isnan(rej)) { 1016 1027 PS_ASSERT_FLOAT_EQUAL(iter, 0, false); … … 1070 1081 } 1071 1082 psFree(stack); 1072 pmReadoutUpdateSize(combined, minInputCols, minInputRows, xSize, ySize, true, true, b ad);1083 pmReadoutUpdateSize(combined, minInputCols, minInputRows, xSize, ySize, true, true, blankMaskBits); 1073 1084 psTrace("psModules.imcombine", 1, "Have for combination [%d:%d,%d:%d] (%dx%d)\n", 1074 1085 minInputCols, maxInputCols, minInputRows, maxInputRows, xSize, ySize); … … 1131 1142 for (int y = minInputRows; y < maxInputRows; y++) { 1132 1143 for (int x = minInputCols; x < maxInputCols; x++) { 1144 CHECKPIX(x, y, "Combining pixel %d,%d: %x %x %f %f %f %f %d %d %d\n", x, y, badMaskBits, blankMaskBits, iter, rej, sys, olympic, useVariance, safe, rejection); 1145 1133 1146 #ifdef TESTING 1134 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) {1135 fprintf(stderr, "Combining pixel %d,%d: %x %x %f %f %f %f %d %d %d\n", 1136 x, y, maskVal, bad, iter, rej, sys, olympic, useVariance, safe, rejection); 1137 } 1138 #endif 1147 if (PS_SQR(x - TEST_X) + PS_SQR(y - TEST_Y) <= PS_SQR(TEST_RADIUS)) { 1148 fprintf (stderr, "combine\n"); 1149 } 1150 # endif 1151 1139 1152 psVector *reject = NULL; // Images to reject for this pixel 1140 1153 if (rejection) { … … 1154 1167 #endif 1155 1168 } 1156 1157 int num; // Number of good pixels1158 bool suspect; // Suspect pixels in stack?1159 combineExtract(&num, &suspect, buffer, combinedImage, combinedMask, combinedVariance, 1160 input, weights, exps, addVariance, reject, x, y, maskVal, maskSuspect); 1161 combine Pixels(combinedImage, combinedMask, combinedVariance, exp, expnum, expweight,1162 num, buffer, x, y, bad, safe, totalExpWeight);1169 1170 int num; // Number of good pixels 1171 bool suspect; // Suspect pixels in stack? 1172 psImageMaskType badMask = 0; // OR of mask bits in all bad input pixels 1173 psImageMaskType goodMask = 0; // OR of mask bits in all good input pixels 1174 combineExtract(&num, &suspect, &badMask, &goodMask, buffer, combinedImage, combinedMask, combinedVariance, input, weights, exps, addVariance, reject, x, y, badMaskBits, suspectMaskBits); 1175 combinePixels(combinedImage, combinedMask, combinedVariance, exp, expnum, expweight, num, buffer, x, y, blankMaskBits, badMask, goodMask, safe, totalExpWeight); 1163 1176 1164 1177 if (iter > 0) { -
trunk/psModules/src/imcombine/pmSubtraction.c
r29004 r29543 540 540 541 541 psImage *conv = psImageConvolveFFT(NULL, image->image, NULL, 0, kernel); // Convolved image 542 543 // note: do not attempt to renormalize kernels here: cannot have different stars with 544 // different kernel ratios 545 542 546 int x0 = - image->xMin, y0 = - image->yMin; // Position of centre of convolved image 543 547 psKernel *convolved = psKernelAllocFromImage(conv, x0, y0); // Kernel version -
trunk/psModules/src/imcombine/pmSubtractionAnalysis.c
r27086 r29543 299 299 kernels->rms); 300 300 301 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_F SIGMA_RES_MEAN, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResMean);302 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_F SIGMA_RES_STDEV, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResStdev);303 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_F MIN_RES_MEAN, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResMean);304 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_F MIN_RES_STDEV, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResStdev);305 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_F MAX_RES_MEAN, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResMean);306 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_F MAX_RES_STDEV, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResStdev);307 308 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FSIGMA_RES_MEAN, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResMean);309 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FSIGMA_RES_STDEV, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResStdev);310 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FMIN_RES_MEAN, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResMean);311 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FMIN_RES_STDEV, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResStdev);312 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FMAX_RES_MEAN, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResMean);313 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FMAX_RES_STDEV, 0, "Mean Fractional Sigma of Residuals", kernels->fSigResStdev);301 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_SIGMA_MEAN, 0, "Fractional Sigma of Residuals (Mean)", kernels->fResSigmaMean); 302 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_SIGMA_STDEV, 0, "Fractional Sigma of Residuals (Stdev)", kernels->fResSigmaStdev); 303 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_OUTER_MEAN, 0, "Fractional Residual Flux (Mean, R > 2 pix)", kernels->fResOuterMean); 304 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_OUTER_STDEV, 0, "Fractional Residual Flux (Stdev, R > 2 pix)", kernels->fResOuterStdev); 305 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_TOTAL_MEAN, 0, "Fractional Residual Flux (Mean, R > 0 pix)", kernels->fResTotalMean); 306 psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_TOTAL_STDEV, 0, "Fractional Residual Flux (Stdev, R > 0 pix)", kernels->fResTotalStdev); 307 308 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_SIGMA_MEAN, 0, "Fractional Sigma of Residuals (Mean)", kernels->fResSigmaMean); 309 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_SIGMA_STDEV, 0, "Fractional Sigma of Residuals (Stdev)", kernels->fResSigmaStdev); 310 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_OUTER_MEAN, 0, "Fractional Residual Flux (Mean, R > 2 pix)", kernels->fResOuterMean); 311 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_OUTER_STDEV, 0, "Fractional Residual Flux (Stdev, R > 2 pix)", kernels->fResOuterStdev); 312 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_TOTAL_MEAN, 0, "Fractional Residual Flux (Mean, R > 0 pix)", kernels->fResTotalMean); 313 psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_FRES_TOTAL_STDEV, 0, "Fractional Residual Flux (Stdev, R > 0 pix)", kernels->fResTotalStdev); 314 314 } 315 315 -
trunk/psModules/src/imcombine/pmSubtractionAnalysis.h
r26893 r29543 24 24 #define PM_SUBTRACTION_ANALYSIS_DECONV_MAX "SUBTRACTION.DECONV.MAX" // Maximum deconvolution fraction 25 25 26 #define PM_SUBTRACTION_ANALYSIS_F SIGMA_RES_MEAN "SUBTRACTION.RES.FSIGMA.MEAN"// RMS stamp deviation27 #define PM_SUBTRACTION_ANALYSIS_F SIGMA_RES_STDEV "SUBTRACTION.RES.FSIGMA.STDEV"// RMS stamp deviation28 #define PM_SUBTRACTION_ANALYSIS_F MIN_RES_MEAN "SUBTRACTION.RES.FMIN.MEAN"// RMS stamp deviation29 #define PM_SUBTRACTION_ANALYSIS_F MIN_RES_STDEV "SUBTRACTION.RES.FMIN.STDEV"// RMS stamp deviation30 #define PM_SUBTRACTION_ANALYSIS_F MAX_RES_MEAN "SUBTRACTION.RES.FMAX.MEAN"// RMS stamp deviation31 #define PM_SUBTRACTION_ANALYSIS_F MAX_RES_STDEV "SUBTRACTION.RES.FMAX.STDEV"// RMS stamp deviation26 #define PM_SUBTRACTION_ANALYSIS_FRES_SIGMA_MEAN "SUBTRACTION.FRES.MEAN" // RMS stamp deviation 27 #define PM_SUBTRACTION_ANALYSIS_FRES_SIGMA_STDEV "SUBTRACTION.FRES.STDEV" // RMS stamp deviation 28 #define PM_SUBTRACTION_ANALYSIS_FRES_OUTER_MEAN "SUBTRACTION.FRES.OUTER.MEAN" // RMS stamp deviation 29 #define PM_SUBTRACTION_ANALYSIS_FRES_OUTER_STDEV "SUBTRACTION.FRES.OUTER.STDEV" // RMS stamp deviation 30 #define PM_SUBTRACTION_ANALYSIS_FRES_TOTAL_MEAN "SUBTRACTION.FRES.TOTAL.MEAN" // RMS stamp deviation 31 #define PM_SUBTRACTION_ANALYSIS_FRES_TOTAL_STDEV "SUBTRACTION.FRES.TOTAL.STDEV" // RMS stamp deviation 32 32 33 33 // Derive QA information about the subtraction -
trunk/psModules/src/imcombine/pmSubtractionEquation.c
r29004 r29543 19 19 20 20 //#define USE_WEIGHT // Include weight (1/variance) in equation? 21 //#define USE_WINDOW // Include weight (1/variance) in equation? 22 21 22 // XXX TEST: 23 //# define USE_WINDOW // window to avoid neighbor contamination 24 25 # define PENALTY false 26 # define MOMENTS (!PENALTY) 23 27 24 28 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 27 31 28 32 // Calculate the least-squares matrix and vector 29 static bool calculateMatrixVector(psImage *matrix, // Least-squares matrix, updated30 psVector *vector, // Least-squares vector, updated31 double *norm, // Normalisation, updated33 static bool calculateMatrixVector(psImage *matrix, // Least-squares matrix, updated 34 psVector *vector, // Least-squares vector, updated 35 double normValue, // Normalisation, supplied 32 36 const psKernel *input, // Input image (target) 33 37 const psKernel *reference, // Reference image (convolution source) … … 37 41 const pmSubtractionKernels *kernels, // Kernels 38 42 const psImage *polyValues, // Spatial polynomial values 39 int footprint, // (Half-)Size of stamp 40 int normWindow1, // Window (half-)size for normalisation measurement 41 int normWindow2, // Window (half-)size for normalisation measurement 42 const pmSubtractionEquationCalculationMode mode 43 int footprint // (Half-)Size of stamp 43 44 ) 44 45 { … … 50 51 51 52 int numKernels = kernels->num; // Number of kernels 52 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation53 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background54 53 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 55 54 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 56 55 double poly[numPoly]; // Polynomial terms 57 56 double poly2[numPoly][numPoly]; // Polynomial-polynomial values 57 int numParams = numKernels * numPoly; 58 59 psAssert(matrix && 60 matrix->type.type == PS_TYPE_F64 && 61 matrix->numCols == numParams && 62 matrix->numRows == numParams, 63 "Least-squares matrix is bad."); 64 psAssert(vector && 65 vector->type.type == PS_TYPE_F64 && 66 vector->n == numParams, 67 "Least-squares vector is bad."); 58 68 59 69 // Evaluate polynomial-polynomial terms 60 // XXX we can skip this if we are not calculating kernel coeffs61 70 for (int iyOrder = 0, iIndex = 0; iyOrder <= spatialOrder; iyOrder++) { 62 71 for (int ixOrder = 0; ixOrder <= spatialOrder - iyOrder; ixOrder++, iIndex++) { … … 84 93 // [kernel 0, x^1 y^0][kernel 1 x^1 y^0]...[kernel N, x^1 y^0] 85 94 // [kernel 0, x^n y^m][kernel 1 x^n y^m]...[kernel N, x^n y^m] 86 // normalization87 // bg 0, bg 1, bg 2 (only 0 is currently used?)88 95 89 96 for (int i = 0; i < numKernels; i++) { … … 107 114 108 115 // Spatial variation of kernel coeffs 109 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 110 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 111 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 112 double value = sumCC * poly2[iTerm][jTerm]; 113 matrix->data.F64[iIndex][jIndex] = value; 114 matrix->data.F64[jIndex][iIndex] = value; 115 } 116 } 117 } 116 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 117 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 118 double value = sumCC * poly2[iTerm][jTerm]; 119 matrix->data.F64[iIndex][jIndex] = value; 120 matrix->data.F64[jIndex][iIndex] = value; 121 } 122 } 118 123 } 119 124 120 125 double sumRC = 0.0; // Sum of the reference-convolution products 121 126 double sumIC = 0.0; // Sum of the input-convolution products 122 double sumC = 0.0; // Sum of the convolution123 127 for (int y = - footprint; y <= footprint; y++) { 124 128 for (int x = - footprint; x <= footprint; x++) { … … 128 132 double ic = in * conv; 129 133 double rc = ref * conv; 130 double c = conv;131 134 if (weight) { 132 135 float wtVal = weight->kernel[y][x]; 133 136 ic *= wtVal; 134 137 rc *= wtVal; 135 c *= wtVal;136 138 } 137 139 if (window) { … … 139 141 ic *= winVal; 140 142 rc *= winVal; 141 c *= winVal;142 143 } 143 144 sumIC += ic; 144 145 sumRC += rc; 145 sumC += c;146 }147 } 146 } 147 } 148 148 149 // Spatial variation 149 150 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 150 double normTerm = sumRC * poly[iTerm]; 151 double bgTerm = sumC * poly[iTerm]; 152 if ((mode & PM_SUBTRACTION_EQUATION_NORM) && (mode & PM_SUBTRACTION_EQUATION_KERNELS)) { 153 matrix->data.F64[iIndex][normIndex] = normTerm; 154 matrix->data.F64[normIndex][iIndex] = normTerm; 155 } 156 if ((mode & PM_SUBTRACTION_EQUATION_BG) && (mode & PM_SUBTRACTION_EQUATION_KERNELS)) { 157 matrix->data.F64[iIndex][bgIndex] = bgTerm; 158 matrix->data.F64[bgIndex][iIndex] = bgTerm; 159 } 160 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 161 vector->data.F64[iIndex] = sumIC * poly[iTerm]; 162 if (!(mode & PM_SUBTRACTION_EQUATION_NORM)) { 163 // subtract norm * sumRC * poly[iTerm] 164 psAssert (kernels->solution1, "programming error: define solution first!"); 165 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 166 double norm = fabs(kernels->solution1->data.F64[normIndex]); // Normalisation 167 vector->data.F64[iIndex] -= norm * normTerm; 168 } 169 } 170 } 171 } 172 173 double sumRR = 0.0; // Sum of the reference product 174 double sumIR = 0.0; // Sum of the input-reference product 175 double sum1 = 0.0; // Sum of the background 176 double sumR = 0.0; // Sum of the reference 177 double sumI = 0.0; // Sum of the input 178 double normI1 = 0.0, normI2 = 0.0; // Sum of I_1 and I_2 within the normalisation window 179 for (int y = - footprint; y <= footprint; y++) { 180 for (int x = - footprint; x <= footprint; x++) { 181 double in = input->kernel[y][x]; 182 double ref = reference->kernel[y][x]; 183 double ir = in * ref; 184 double rr = PS_SQR(ref); 185 double one = 1.0; 186 187 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow1)) { 188 normI1 += ref; 189 } 190 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow2)) { 191 normI2 += in; 192 } 193 194 if (weight) { 195 float wtVal = weight->kernel[y][x]; 196 rr *= wtVal; 197 ir *= wtVal; 198 in *= wtVal; 199 ref *= wtVal; 200 one *= wtVal; 201 } 202 if (window) { 203 float winVal = window->kernel[y][x]; 204 rr *= winVal; 205 ir *= winVal; 206 in *= winVal; 207 ref *= winVal; 208 one *= winVal; 209 } 210 sumRR += rr; 211 sumIR += ir; 212 sumR += ref; 213 sumI += in; 214 sum1 += one; 215 } 216 } 217 218 *norm = normI2 / normI1; 219 220 fprintf (stderr, "normValue: %f %f %f\n", normI1, normI2, *norm); 221 222 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 223 matrix->data.F64[normIndex][normIndex] = sumRR; 224 vector->data.F64[normIndex] = sumIR; 225 // subtract sum over kernels * kernel solution 226 } 227 if (mode & PM_SUBTRACTION_EQUATION_BG) { 228 matrix->data.F64[bgIndex][bgIndex] = sum1; 229 vector->data.F64[bgIndex] = sumI; 230 } 231 if ((mode & PM_SUBTRACTION_EQUATION_NORM) && (mode & PM_SUBTRACTION_EQUATION_BG)) { 232 matrix->data.F64[normIndex][bgIndex] = sumR; 233 matrix->data.F64[bgIndex][normIndex] = sumR; 151 vector->data.F64[iIndex] = (sumIC - normValue*sumRC) * poly[iTerm]; 152 } 234 153 } 235 154 … … 255 174 256 175 // Calculate the least-squares matrix and vector for dual convolution 257 static bool calculateDualMatrixVector(psImage *matrix, // Least-squares matrix, updated 258 psVector *vector, // Least-squares vector, updated 259 double *norm, // Normalisation, updated 260 const psKernel *image1, // Image 1 261 const psKernel *image2, // Image 2 176 // XXX we could avoid calculating these values on successive passes *if* the stamp has not changed. 177 static bool calculateDualMatrixVector(pmSubtractionStamp *stamp, // stamp of interest 178 double normValue, // Normalisation, updated 179 double normValue2, // Normalisation, updated 262 180 const psKernel *weight, // Weight image 263 181 const psKernel *window, // Window image 264 const psArray *convolutions1, // Convolutions of image 1 for each kernel265 const psArray *convolutions2, // Convolutions of image 2 for each kernel266 182 const pmSubtractionKernels *kernels, // Kernels 267 183 const psImage *polyValues, // Spatial polynomial values 268 int footprint, // (Half-)Size of stamp 269 int normWindow1, // Window (half-)size for normalisation measurement 270 int normWindow2, // Window (half-)size for normalisation measurement 271 const pmSubtractionEquationCalculationMode mode 184 int footprint // (Half-)Size of stamp 272 185 ) 273 186 { 274 int numKernels = kernels->num; // Number of kernels 275 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 276 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 277 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 187 int numKernels = kernels->num; // Number of kernels 188 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 278 189 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 279 190 double poly[numPoly]; // Polynomial terms 280 191 double poly2[numPoly][numPoly]; // Polynomial-polynomial values 281 192 282 int numBackground = PM_SUBTRACTION_POLYTERMS(kernels->bgOrder); // Number of background terms 283 int numParams = numKernels * numPoly + 1 + numBackground; // Number of regular parameters 284 int numParams2 = numKernels * numPoly; // Number of additional parameters for dual 285 int numDual = numParams + numParams2; // Total number of parameters for dual 193 int numParams = numKernels * numPoly; // Number of regular parameters 194 int numParams2 = numKernels * numPoly; // Number of additional parameters for dual 195 int numDual = numParams + numParams2; // Total number of parameters for dual 196 197 psImage *matrix = stamp->matrix; // Least-squares matrix, updated 198 psVector *vector = stamp->vector; // Least-squares vector, updated 199 psKernel *image1 = stamp->image1; // Image 1 200 psKernel *image2 = stamp->image2; // Image 2 201 psArray *convolutions1 = stamp->convolutions1; // Convolutions of image 1 for each kernel 202 psArray *convolutions2 = stamp->convolutions2; // Convolutions of image 2 for each kernel 286 203 287 204 psAssert(matrix && … … 290 207 matrix->numRows == numDual, 291 208 "Least-squares matrix is bad."); 209 292 210 psAssert(vector && 293 211 vector->type.type == PS_TYPE_F64 && … … 318 236 } 319 237 238 // the order of the elements in the matrix and vector is: 239 // [kernel 0, x^0 y^0][kernel 1 x^0 y^0]...[kernel N, x^0 y^0] 240 // [kernel 0, x^1 y^0][kernel 1 x^1 y^0]...[kernel N, x^1 y^0] 241 // [kernel 0, x^n y^m][kernel 1 x^n y^m]...[kernel N, x^n y^m] 242 243 // for DUAL convolution analysis, we apply the normalization to I1 as follows: 244 // norm = I2 / I1 245 // 246 // I1c = norm I1 + \Sum_i a_i norm I1 \cross k_i 247 // I2c = I2 + \Sum_i b_i I2 \cross k_i 248 249 // we cannot absorb the normalization into a_i until the analysis is complete, or the 250 // second moment terms are incorrectly calculated. 251 320 252 for (int i = 0; i < numKernels; i++) { 321 253 psKernel *iConv1 = convolutions1->data[i]; // Convolution 1 for index i … … 328 260 double sumBB = 0.0; // Sum of convolution products between image 2 329 261 double sumAB = 0.0; // Sum of convolution products across images 1 and 2 262 263 double MxxAA = 0.0; 264 double MyyAA = 0.0; 265 double MxxBB = 0.0; 266 double MyyBB = 0.0; 330 267 for (int y = - footprint; y <= footprint; y++) { 331 268 for (int x = - footprint; x <= footprint; x++) { 332 double aa = iConv1->kernel[y][x] * jConv1->kernel[y][x] ;269 double aa = iConv1->kernel[y][x] * jConv1->kernel[y][x] * PS_SQR(normValue); 333 270 double bb = iConv2->kernel[y][x] * jConv2->kernel[y][x]; 334 double ab = iConv1->kernel[y][x] * jConv2->kernel[y][x] ;271 double ab = iConv1->kernel[y][x] * jConv2->kernel[y][x] * normValue; 335 272 if (weight) { 336 273 float wtVal = weight->kernel[y][x]; … … 348 285 sumBB += bb; 349 286 sumAB += ab; 350 } 351 } 287 288 if (MOMENTS) { 289 MxxAA += x*x*aa; 290 MyyAA += y*y*aa; 291 MxxBB += x*x*bb; 292 MyyBB += y*y*bb; 293 } 294 } 295 } 296 297 if (MOMENTS) { 298 MxxAA /= stamp->normSquare1 * PS_SQR(normValue); 299 MyyAA /= stamp->normSquare1 * PS_SQR(normValue); 300 MxxBB /= stamp->normSquare2; 301 MyyBB /= stamp->normSquare2; 302 } 303 304 // XXX this makes the Chisq portion independent of the normalization and star flux 305 // but may be mis-scaling between stars of different fluxes 306 sumAA /= PS_SQR(stamp->normI2); 307 sumAB /= PS_SQR(stamp->normI2); 308 sumBB /= PS_SQR(stamp->normI2); 309 310 // fprintf (stderr, "i,j : %d %d : M(xx,yy)(AA,BB) : %f %f %f %f\n", i, j, MxxAA, MyyAA, MxxBB, MyyBB); 352 311 353 312 // Spatial variation of kernel coeffs 354 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 355 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 356 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 357 double aa = sumAA * poly2[iTerm][jTerm]; 358 double bb = sumBB * poly2[iTerm][jTerm]; 359 double ab = sumAB * poly2[iTerm][jTerm]; 360 361 matrix->data.F64[iIndex][jIndex] = aa; 362 matrix->data.F64[jIndex][iIndex] = aa; 363 364 matrix->data.F64[iIndex + numParams][jIndex + numParams] = bb; 365 matrix->data.F64[jIndex + numParams][iIndex + numParams] = bb; 366 367 matrix->data.F64[iIndex][jIndex + numParams] = ab; 368 matrix->data.F64[jIndex + numParams][iIndex] = ab; 369 } 370 } 371 } 372 } 313 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 314 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 315 double aa = sumAA * poly2[iTerm][jTerm]; 316 double bb = sumBB * poly2[iTerm][jTerm]; 317 double ab = sumAB * poly2[iTerm][jTerm]; 318 319 matrix->data.F64[iIndex][jIndex] = aa; 320 matrix->data.F64[jIndex][iIndex] = aa; 321 322 matrix->data.F64[iIndex + numParams][jIndex + numParams] = bb; 323 matrix->data.F64[jIndex + numParams][iIndex + numParams] = bb; 324 325 // add in second moments 326 if (MOMENTS) { 327 matrix->data.F64[iIndex][jIndex] += kernels->penalty * MxxAA; 328 matrix->data.F64[iIndex][jIndex] += kernels->penalty * MyyAA; 329 330 matrix->data.F64[jIndex][iIndex] += kernels->penalty * MxxAA; 331 matrix->data.F64[jIndex][iIndex] += kernels->penalty * MyyAA; 332 333 matrix->data.F64[iIndex + numParams][jIndex + numParams] += kernels->penalty * MxxBB; 334 matrix->data.F64[iIndex + numParams][jIndex + numParams] += kernels->penalty * MyyBB; 335 336 matrix->data.F64[jIndex + numParams][iIndex + numParams] += kernels->penalty * MxxBB; 337 matrix->data.F64[jIndex + numParams][iIndex + numParams] += kernels->penalty * MyyBB; 338 339 // XXX this uses the single moments, first try 340 // matrix->data.F64[iIndex][jIndex] += kernels->penalty * stamp->MxxI1->data.F32[i]*stamp->MxxI1->data.F32[j]; 341 // matrix->data.F64[iIndex][jIndex] += kernels->penalty * stamp->MyyI1->data.F32[i]*stamp->MyyI1->data.F32[j]; 342 // 343 // matrix->data.F64[jIndex][iIndex] += kernels->penalty * stamp->MxxI1->data.F32[i]*stamp->MxxI1->data.F32[j]; 344 // matrix->data.F64[jIndex][iIndex] += kernels->penalty * stamp->MyyI1->data.F32[i]*stamp->MyyI1->data.F32[j]; 345 // 346 // matrix->data.F64[iIndex + numParams][jIndex + numParams] += kernels->penalty * stamp->MxxI2->data.F32[i]*stamp->MxxI2->data.F32[j]; 347 // matrix->data.F64[iIndex + numParams][jIndex + numParams] += kernels->penalty * stamp->MyyI2->data.F32[i]*stamp->MyyI2->data.F32[j]; 348 // 349 // matrix->data.F64[jIndex + numParams][iIndex + numParams] += kernels->penalty * stamp->MxxI2->data.F32[i]*stamp->MxxI2->data.F32[j]; 350 // matrix->data.F64[jIndex + numParams][iIndex + numParams] += kernels->penalty * stamp->MyyI2->data.F32[i]*stamp->MyyI2->data.F32[j]; 351 } 352 matrix->data.F64[iIndex][jIndex + numParams] = ab; 353 matrix->data.F64[jIndex + numParams][iIndex] = ab; 354 } 355 } 356 } 357 358 // we need to calculate the lower-diagonal AB elements since they are not symmetric for A <-> B 373 359 for (int j = 0; j < i; j++) { 374 360 psKernel *jConv2 = convolutions2->data[j]; // Convolution 2 for index j … … 376 362 for (int y = - footprint; y <= footprint; y++) { 377 363 for (int x = - footprint; x <= footprint; x++) { 378 double ab = iConv1->kernel[y][x] * jConv2->kernel[y][x] ;364 double ab = iConv1->kernel[y][x] * jConv2->kernel[y][x] * normValue; 379 365 if (weight) { 380 366 ab *= weight->kernel[y][x]; … … 387 373 } 388 374 375 // XXX this makes the Chisq portion independent of the normalization and star flux 376 // but may be mis-scaling between stars of different fluxes 377 sumAB /= PS_SQR(stamp->normI2); 378 389 379 // Spatial variation of kernel coeffs 390 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 391 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 392 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 393 double ab = sumAB * poly2[iTerm][jTerm]; 394 matrix->data.F64[iIndex][jIndex + numParams] = ab; 395 matrix->data.F64[jIndex + numParams][iIndex] = ab; 396 } 397 } 380 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 381 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 382 double ab = sumAB * poly2[iTerm][jTerm]; 383 matrix->data.F64[iIndex][jIndex + numParams] = ab; 384 matrix->data.F64[jIndex + numParams][iIndex] = ab; 385 } 398 386 } 399 387 } … … 402 390 double sumBI2 = 0.0; // Sum of B.I_2 products (for vector) 403 391 double sumAI1 = 0.0; // Sum of A.I_1 products (for matrix, normalisation) 404 double sumA = 0.0; // Sum of A (for matrix, background)405 392 double sumBI1 = 0.0; // Sum of B.I_1 products (for matrix, normalisation) 406 double sumB = 0.0; // Sum of B products (for matrix, background) 407 double sumI2 = 0.0; // Sum of I_2 (for vector, background) 393 394 double MxxAI1 = 0.0; 395 double MyyAI1 = 0.0; 396 double MxxBI2 = 0.0; 397 double MyyBI2 = 0.0; 408 398 for (int y = - footprint; y <= footprint; y++) { 409 399 for (int x = - footprint; x <= footprint; x++) { … … 413 403 float i2 = image2->kernel[y][x]; 414 404 415 double ai2 = a * i2 ;405 double ai2 = a * i2 * normValue; 416 406 double bi2 = b * i2; 417 double ai1 = a * i1 ;418 double bi1 = b * i1 ;407 double ai1 = a * i1 * PS_SQR(normValue); 408 double bi1 = b * i1 * normValue; 419 409 420 410 if (weight) { … … 424 414 ai1 *= wtVal; 425 415 bi1 *= wtVal; 426 a *= wtVal;427 b *= wtVal;428 i2 *= wtVal;429 416 } 430 417 if (window) { … … 434 421 ai1 *= wtVal; 435 422 bi1 *= wtVal; 436 a *= wtVal;437 b *= wtVal;438 i2 *= wtVal;439 423 } 440 424 sumAI2 += ai2; 441 425 sumBI2 += bi2; 442 426 sumAI1 += ai1; 443 sumA += a;444 427 sumBI1 += bi1; 445 sumB += b; 446 sumI2 += i2; 447 } 448 } 428 429 if (MOMENTS) { 430 MxxAI1 += x*x*ai1; 431 MyyAI1 += y*y*ai1; 432 MxxBI2 += x*x*bi2; 433 MyyBI2 += y*y*bi2; 434 } 435 } 436 } 437 438 if (MOMENTS) { 439 MxxAI1 /= stamp->normSquare1 * PS_SQR(normValue); 440 MyyAI1 /= stamp->normSquare1 * PS_SQR(normValue); 441 MxxBI2 /= stamp->normSquare2; 442 MyyBI2 /= stamp->normSquare2; 443 } 444 445 // fprintf (stderr, "i : %d : M(xx,yy)(AI1,BI2) : %f %f %f %f\n", i, MxxAI1, MyyAI1, MxxBI2, MyyBI2); 446 447 // XXX this makes the Chisq portion independent of the normalization and star flux 448 // but may be mis-scaling between stars of different fluxes 449 sumAI1 /= PS_SQR(stamp->normI2); 450 sumBI1 /= PS_SQR(stamp->normI2); 451 sumAI2 /= PS_SQR(stamp->normI2); 452 sumBI2 /= PS_SQR(stamp->normI2); 453 449 454 // Spatial variation 450 455 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { … … 452 457 double bi2 = sumBI2 * poly[iTerm]; 453 458 double ai1 = sumAI1 * poly[iTerm]; 454 double a = sumA * poly[iTerm];455 459 double bi1 = sumBI1 * poly[iTerm]; 456 double b = sumB * poly[iTerm]; 457 458 if ((mode & PM_SUBTRACTION_EQUATION_NORM) && (mode & PM_SUBTRACTION_EQUATION_KERNELS)) { 459 matrix->data.F64[iIndex][normIndex] = ai1; 460 matrix->data.F64[normIndex][iIndex] = ai1; 461 matrix->data.F64[iIndex + numParams][normIndex] = bi1; 462 matrix->data.F64[normIndex][iIndex + numParams] = bi1; 463 } 464 if ((mode & PM_SUBTRACTION_EQUATION_BG) && (mode & PM_SUBTRACTION_EQUATION_KERNELS)) { 465 matrix->data.F64[iIndex][bgIndex] = a; 466 matrix->data.F64[bgIndex][iIndex] = a; 467 matrix->data.F64[iIndex + numParams][bgIndex] = b; 468 matrix->data.F64[bgIndex][iIndex + numParams] = b; 469 } 470 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 471 vector->data.F64[iIndex] = ai2; 472 vector->data.F64[iIndex + numParams] = bi2; 473 if (!(mode & PM_SUBTRACTION_EQUATION_NORM)) { 474 // subtract norm * sumRC * poly[iTerm] 475 psAssert (kernels->solution1, "programming error: define solution first!"); 476 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 477 double norm = fabs(kernels->solution1->data.F64[normIndex]); // Normalisation 478 vector->data.F64[iIndex] -= norm * ai1; 479 vector->data.F64[iIndex + numParams] -= norm * bi1; 480 } 481 } 482 } 483 } 484 485 double sumI1 = 0.0; // Sum of I_1 (for matrix, background-normalisation) 486 double sumI1I1 = 0.0; // Sum of I_1^2 (for matrix, normalisation-normalisation) 487 double sum1 = 0.0; // Sum of 1 (for matrix, background-background) 488 double sumI2 = 0.0; // Sum of I_2 (for vector, background) 489 double sumI1I2 = 0.0; // Sum of I_1.I_2 (for vector, normalisation) 490 double normI1 = 0.0, normI2 = 0.0; // Sum of I_1 and I_2 within the normalisation window 491 for (int y = - footprint; y <= footprint; y++) { 492 for (int x = - footprint; x <= footprint; x++) { 493 double i1 = image1->kernel[y][x]; 494 double i2 = image2->kernel[y][x]; 495 496 double i1i1 = i1 * i1; 497 double one = 1.0; 498 double i1i2 = i1 * i2; 499 500 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow1)) { 501 normI1 += i1; 502 } 503 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow2)) { 504 normI2 += i2; 505 } 506 507 if (weight) { 508 float wtVal = weight->kernel[y][x]; 509 i1 *= wtVal; 510 i1i1 *= wtVal; 511 one *= wtVal; 512 i2 *= wtVal; 513 i1i2 *= wtVal; 514 } 515 if (window) { 516 float wtVal = window->kernel[y][x]; 517 i1 *= wtVal; 518 i1i1 *= wtVal; 519 one *= wtVal; 520 i2 *= wtVal; 521 i1i2 *= wtVal; 522 } 523 sumI1 += i1; 524 sumI1I1 += i1i1; 525 sum1 += one; 526 sumI2 += i2; 527 sumI1I2 += i1i2; 528 } 529 } 530 531 *norm = normI2 / normI1; 532 fprintf (stderr, "normValue: %f %f %f\n", normI1, normI2, *norm); 533 534 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 535 matrix->data.F64[normIndex][normIndex] = sumI1I1; 536 vector->data.F64[normIndex] = sumI1I2; 537 } 538 if (mode & PM_SUBTRACTION_EQUATION_BG) { 539 matrix->data.F64[bgIndex][bgIndex] = sum1; 540 vector->data.F64[bgIndex] = sumI2; 541 } 542 if ((mode & PM_SUBTRACTION_EQUATION_NORM) && (mode & PM_SUBTRACTION_EQUATION_BG)) { 543 matrix->data.F64[bgIndex][normIndex] = sumI1; 544 matrix->data.F64[normIndex][bgIndex] = sumI1; 460 vector->data.F64[iIndex] = ai2 - ai1; 461 vector->data.F64[iIndex + numParams] = bi2 - bi1; 462 463 // fprintf (stderr, "i : %d : V(I1,I2) : %f %f\n", i, vector->data.F64[iIndex], vector->data.F64[iIndex + numParams]); 464 465 // add in second moments 466 if (MOMENTS) { 467 vector->data.F64[iIndex] -= kernels->penalty * MxxAI1; 468 vector->data.F64[iIndex] -= kernels->penalty * MyyAI1; 469 470 vector->data.F64[iIndex + numParams] -= kernels->penalty * MxxBI2; 471 vector->data.F64[iIndex + numParams] -= kernels->penalty * MyyBI2; 472 } 473 } 545 474 } 546 475 … … 565 494 } 566 495 567 #if 1568 496 // Add in penalty term to least-squares vector 569 497 bool calculatePenalty(psImage *matrix, // Matrix to which to add in penalty term 570 498 psVector *vector, // Vector to which to add in penalty term 571 499 const pmSubtractionKernels *kernels, // Kernel parameters 572 float norm // Normalisation 500 float normSquare1, // Normalisation for image 1 501 float normSquare2 // Normalisation for image 2 573 502 ) 574 503 { 504 psAssert (kernels->mode == PM_SUBTRACTION_MODE_DUAL, "only use penalties for dual convolution"); 505 575 506 if (kernels->penalty == 0.0) { 576 507 return true; … … 589 520 // [p_0,x_1,y_0 p_1,x_1,y_0, p_2,x_1,y_0] 590 521 // [p_0,x_0,y_1 p_1,x_0,y_1, p_2,x_0,y_1] 591 // [norm] 592 // [bg] 522 593 523 // [q_0,x_0,y_0 q_1,x_0,y_0, q_2,x_0,y_0] 594 524 // [q_0,x_1,y_0 q_1,x_1,y_0, q_2,x_1,y_0] … … 600 530 // Contribution to chi^2: a_i^2 P_i 601 531 psAssert(isfinite(penalties1->data.F32[i]), "Invalid penalty"); 602 fprintf (stderr, "penalty: %f + %f (%f * %f)\n", matrix->data.F64[index][index], norm * penalties1->data.F32[i], norm, penalties1->data.F32[i]); 603 matrix->data.F64[index][index] += norm * penalties1->data.F32[i]; 604 if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 605 fprintf (stderr, "penalty: (x^%d y^%d fwhm %f) : %f + %f (%f * %f)\n", kernels->u->data.S32[index], kernels->v->data.S32[index], kernels->widths->data.F32[index], 606 matrix->data.F64[index + numParams + 2][index + numParams + 2], norm * penalties2->data.F32[i], norm, penalties2->data.F32[i]); 607 matrix->data.F64[index + numParams + 2][index + numParams + 2] += norm * penalties2->data.F32[i]; 608 // matrix[i][i] is ~ (k_i * I_1)(k_i * I_1) 609 // penalties scale with second moments 610 // 611 } 612 } 613 } 614 } 615 616 return true; 617 } 618 # endif 532 // fprintf (stderr, "penalty: %f + %f (%f * %f)\n", matrix->data.F64[index][index], normSquare1 * penalties1->data.F32[i], normSquare1, penalties1->data.F32[i]); 533 matrix->data.F64[index][index] += normSquare1 * penalties1->data.F32[i]; 534 535 // fprintf (stderr, "penalty: (x^%d y^%d fwhm %f) : %f + %f (%f * %f)\n", kernels->u->data.S32[index], kernels->v->data.S32[index], kernels->widths->data.F32[index], 536 // matrix->data.F64[index + numParams][index + numParams], normSquare2 * penalties2->data.F32[i], normSquare2, penalties2->data.F32[i]); 537 matrix->data.F64[index + numParams][index + numParams] += normSquare2 * penalties2->data.F32[i]; 538 // matrix[i][i] is ~ (k_i * I_1)(k_i * I_1) 539 // penalties scale with second moments 540 // 541 } 542 } 543 } 544 545 return true; 546 } 619 547 620 548 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 647 575 int index, bool wantDual) 648 576 { 649 #if 0650 577 // This is probably in a tight loop, so don't check inputs 651 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NAN);652 PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NAN);653 PS_ASSERT_IMAGE_NON_NULL(polyValues, NAN);654 PS_ASSERT_INT_POSITIVE(index, NAN);655 #endif656 657 578 psVector *solution = wantDual ? kernels->solution2 : kernels->solution1; // Solution vector 658 579 return p_pmSubtractionCalculatePolynomial(solution, polyValues, kernels->spatialOrder, index, … … 662 583 double p_pmSubtractionSolutionNorm(const pmSubtractionKernels *kernels) 663 584 { 664 #if 0665 585 // This is probably in a tight loop, so don't check inputs 666 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NAN);667 PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NAN);668 PS_ASSERT_IMAGE_NON_NULL(polyValues, NAN);669 #endif670 671 586 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 672 587 return kernels->solution1->data.F64[normIndex]; … … 676 591 const psImage *polyValues) 677 592 { 678 #if 0679 593 // This is probably in a tight loop, so don't check inputs 680 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NAN);681 PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NAN);682 PS_ASSERT_IMAGE_NON_NULL(polyValues, NAN);683 #endif684 685 594 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 686 595 return p_pmSubtractionCalculatePolynomial(kernels->solution1, polyValues, kernels->bgOrder, bgIndex, 1); … … 690 599 // Public functions 691 600 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 601 602 bool pmSubtractionCalculateMoments( 603 pmSubtractionKernels *kernels, // Kernels 604 pmSubtractionStampList *stamps) 605 { 606 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); 607 608 // XXX skip this, right? 609 return true; 610 611 // these are only used by DUAL mode 612 if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) return true; 613 614 psTimerStart("pmSubtractionCalculateMoments"); 615 616 int footprint = stamps->footprint; // Half-size of stamps 617 618 // Loop over each stamp and calculate its normalization factor 619 for (int i = 0; i < stamps->num; i++) { 620 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 621 if (stamp->status == PM_SUBTRACTION_STAMP_REJECTED) continue; 622 if (stamp->status == PM_SUBTRACTION_STAMP_NONE) continue; 623 624 pmSubtractionCalculateMomentsStamp(kernels, stamp, footprint, stamps->normWindow2, stamps->normWindow1); 625 } 626 627 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Calculate moments: %f sec", psTimerClear("pmSubtractionCalculateMoments")); 628 629 return true; 630 } 631 632 bool pmSubtractionCalculateMomentsStamp( 633 pmSubtractionKernels *kernels, // Kernels 634 pmSubtractionStamp *stamp, // stamp on which to save normalization) 635 int footprint, // (Half-)Size of stamp 636 int normWindow1, // Window (half-)size for normalisation measurement 637 int normWindow2 // Window (half-)size for normalisation measurement 638 ) 639 { 640 double Mxx, Myy; 641 642 int numKernels = kernels->num; 643 644 // Generate convolutions: these are generated once and saved 645 if (!pmSubtractionConvolveStamp(stamp, kernels, footprint)) { 646 psError(psErrorCodeLast(), false, "Unable to convolve stamp"); 647 return false; 648 } 649 650 if (!stamp->MxxI1) { 651 stamp->MxxI1 = psVectorAlloc (numKernels, PS_TYPE_F32); 652 } 653 if (!stamp->MyyI1) { 654 stamp->MyyI1 = psVectorAlloc (numKernels, PS_TYPE_F32); 655 } 656 if (!stamp->MxxI2) { 657 stamp->MxxI2 = psVectorAlloc (numKernels, PS_TYPE_F32); 658 } 659 if (!stamp->MyyI2) { 660 stamp->MyyI2 = psVectorAlloc (numKernels, PS_TYPE_F32); 661 } 662 663 for (int i = 0; i < numKernels; i++) { 664 pmSubtractionCalculateMomentsKernel(&Mxx, &Myy, stamp->convolutions1->data[i], footprint, normWindow1); 665 stamp->MxxI1->data.F32[i] = Mxx / stamp->normI1; 666 stamp->MyyI1->data.F32[i] = Myy / stamp->normI1; 667 pmSubtractionCalculateMomentsKernel(&Mxx, &Myy, stamp->convolutions2->data[i], footprint, normWindow2); 668 stamp->MxxI2->data.F32[i] = Mxx / stamp->normI2; 669 stamp->MyyI2->data.F32[i] = Myy / stamp->normI2; 670 } 671 672 pmSubtractionCalculateMomentsKernel(&Mxx, &Myy, stamp->image1, footprint, normWindow1); 673 stamp->MxxI1raw = Mxx / stamp->normI1; 674 stamp->MyyI1raw = Myy / stamp->normI1; 675 676 pmSubtractionCalculateMomentsKernel(&Mxx, &Myy, stamp->image2, footprint, normWindow2); 677 stamp->MxxI2raw = Mxx / stamp->normI2; 678 stamp->MyyI2raw = Myy / stamp->normI2; 679 680 // fprintf (stderr, "Mxx I1: %f, Myy I1: %f, Mxx I2: %f, Myy I2: %f\n", stamp->MxxI1raw, stamp->MyyI1raw, stamp->MxxI2raw, stamp->MyyI2raw); 681 682 return true; 683 } 684 685 bool pmSubtractionCalculateMomentsKernel(double *Mxx, double *Myy, psKernel *image, int footprint, int window) { 686 687 double Sxx = 0.0; 688 double Syy = 0.0; 689 for (int y = - footprint; y <= footprint; y++) { 690 for (int x = - footprint; x <= footprint; x++) { 691 if (PS_SQR(x) + PS_SQR(y) > PS_SQR(window)) continue; 692 693 double flux = image->kernel[y][x]; 694 695 Sxx += PS_SQR(x) * flux; 696 Syy += PS_SQR(y) * flux; 697 } 698 } 699 *Mxx = Sxx; 700 *Myy = Syy; 701 return true; 702 } 703 704 ///--------- 705 706 bool pmSubtractionCalculateNormalization( 707 pmSubtractionStampList *stamps, 708 const pmSubtractionMode mode) 709 { 710 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); 711 712 psTimerStart("pmSubtractionCalculateNormalization"); 713 714 psVector *norms = psVectorAllocEmpty(stamps->num, PS_TYPE_F64); // Normalisations 715 psVector *norm2 = psVectorAllocEmpty(stamps->num, PS_TYPE_F64); // Normalisations 716 717 int footprint = stamps->footprint; // Half-size of stamps 718 719 // Loop over each stamp and calculate its normalization factor 720 for (int i = 0; i < stamps->num; i++) { 721 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 722 if (stamp->status == PM_SUBTRACTION_STAMP_REJECTED) continue; 723 if (stamp->status == PM_SUBTRACTION_STAMP_NONE) continue; 724 725 // XXX skip this if we have already calculated it? (stamp->norm does not change, just the median statistic) 726 // XXX maybe not: the star may have changed for a given stamp -- only if norm is reset to NAN can we do this 727 if (mode == PM_SUBTRACTION_MODE_2) { 728 pmSubtractionCalculateNormalizationStamp(stamp, stamp->image2, stamp->image1, footprint, stamps->normWindow2, stamps->normWindow1); 729 } else { 730 pmSubtractionCalculateNormalizationStamp(stamp, stamp->image1, stamp->image2, footprint, stamps->normWindow1, stamps->normWindow2); 731 } 732 psVectorAppend(norms, stamp->norm); 733 psVectorAppend(norm2, stamp->normSquare2 / stamp->normSquare1); 734 } 735 736 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics for norm 737 if (!psVectorStats(stats, norms, NULL, NULL, 0)) { 738 psError(PM_ERR_DATA, false, "Unable to determine median normalisation"); 739 psFree(stats); 740 psFree(norms); 741 psFree(norm2); 742 return false; 743 } 744 stamps->normValue = stats->robustMedian; 745 746 psStatsInit(stats); 747 if (!psVectorStats(stats, norm2, NULL, NULL, 0)) { 748 psError(PM_ERR_DATA, false, "Unable to determine median normalisation"); 749 psFree(stats); 750 psFree(norms); 751 psFree(norm2); 752 return false; 753 } 754 stamps->normValue2 = stats->robustMedian; 755 756 psLogMsg ("psModules.imcombine", PS_LOG_INFO, "norm (1): %f (%f)\n", stamps->normValue, stamps->normValue2); 757 758 psFree(stats); 759 psFree(norms); 760 psFree(norm2); 761 762 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Calculate normalization: %f sec", psTimerClear("pmSubtractionCalculateNormalization")); 763 764 return true; 765 } 766 767 bool pmSubtractionCalculateNormalizationStamp( 768 pmSubtractionStamp *stamp, // stamp on which to save normalization) 769 const psKernel *image1, // Input image (target) 770 const psKernel *image2, // Reference image (convolution source) 771 int footprint, // (Half-)Size of stamp 772 int normWindow1, // Window (half-)size for normalisation measurement 773 int normWindow2 // Window (half-)size for normalisation measurement 774 ) 775 { 776 double normI1 = 0.0; // Sum of I_1 within the normalisation window (aperture) 777 double normI2 = 0.0; // Sum of I_2 within the normalisation window (aperture) 778 double normSquare1 = 0.0; // Sum of (I_1)^2 within the normalisation window (aperture) 779 double normSquare2 = 0.0; // Sum of (I_2)^2 within the normalisation window (aperture) 780 for (int y = - footprint; y <= footprint; y++) { 781 for (int x = - footprint; x <= footprint; x++) { 782 double im1 = image1->kernel[y][x]; 783 double im2 = image2->kernel[y][x]; 784 785 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow1)) { 786 normI1 += im1; 787 normSquare1 += PS_SQR(im1); 788 } 789 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow2)) { 790 normI2 += im2; 791 normSquare2 += PS_SQR(im2); 792 } 793 } 794 } 795 stamp->norm = normI2 / normI1; 796 stamp->normI1 = normI1; 797 stamp->normI2 = normI2; 798 stamp->normSquare1 = normSquare1; 799 stamp->normSquare2 = normSquare2; 800 801 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "normValue: %f %f %f (%f %f)\n", normI1, normI2, stamp->norm, normSquare1, normSquare2); 802 803 return true; 804 } 692 805 693 806 bool pmSubtractionCalculateEquationThread(psThreadJob *job) … … 715 828 int numKernels = kernels->num; // Number of kernel basis functions 716 829 int numSpatial = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of spatial variations 717 int numBackground = PM_SUBTRACTION_POLYTERMS(kernels->bgOrder); // Number of background terms718 830 719 831 // numKernels is the number of unique kernel images (one for each Gaussian modified by a specific polynomial). … … 722 834 // Total number of parameters to solve for: coefficient of each kernel basis function, multipled by the 723 835 // number of coefficients for the spatial polynomial, normalisation and a constant background offset. 724 int numParams = numKernels * numSpatial + 1 + numBackground; 836 // XXX we no longer solve for the normalization and background in the matrix inversion 837 int numParams = numKernels * numSpatial; 725 838 if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 726 839 // An additional image is convolved … … 790 903 switch (kernels->mode) { 791 904 case PM_SUBTRACTION_MODE_1: 792 status = calculateMatrixVector(stamp->matrix, stamp->vector, &stamp->norm, stamp->image2, stamp->image1, 793 weight, window, stamp->convolutions1, kernels, 794 polyValues, footprint, stamps->normWindow1, stamps->normWindow2, mode); 905 status = calculateMatrixVector(stamp->matrix, stamp->vector, stamps->normValue, stamp->image2, stamp->image1, 906 weight, window, stamp->convolutions1, kernels, polyValues, footprint); 795 907 break; 796 908 case PM_SUBTRACTION_MODE_2: 797 status = calculateMatrixVector(stamp->matrix, stamp->vector, &stamp->norm, stamp->image1, stamp->image2, 798 weight, window, stamp->convolutions2, kernels, 799 polyValues, footprint, stamps->normWindow2, stamps->normWindow1, mode); 909 status = calculateMatrixVector(stamp->matrix, stamp->vector, stamps->normValue, stamp->image1, stamp->image2, 910 weight, window, stamp->convolutions2, kernels, polyValues, footprint); 800 911 break; 801 912 case PM_SUBTRACTION_MODE_DUAL: 802 status = calculateDualMatrixVector(stamp->matrix, stamp->vector, &stamp->norm, 803 stamp->image1, stamp->image2, 804 weight, window, stamp->convolutions1, stamp->convolutions2, 805 kernels, polyValues, footprint, stamps->normWindow1, stamps->normWindow2, mode); 913 status = calculateDualMatrixVector(stamp, stamps->normValue, stamps->normValue2, weight, window, kernels, polyValues, footprint); 806 914 break; 807 915 default: … … 928 1036 int numKernels = kernels->num; // Number of kernel basis functions 929 1037 int numSpatial = PM_SUBTRACTION_POLYTERMS(kernels->spatialOrder); // Number of spatial variations 930 int numBackground = PM_SUBTRACTION_POLYTERMS(kernels->bgOrder); // Number of background terms 931 int numParams = numKernels * numSpatial + 1 + numBackground; // Number of parameters being solved for 932 int numSolution1 = numParams, numSolution2 = 0; // Number of parameters for each solution 1038 // XXX int numBackground = PM_SUBTRACTION_POLYTERMS(kernels->bgOrder); // Number of background terms 1039 // XXX int numParams = numKernels * numSpatial + 1 + numBackground; // Number of parameters being solved for 1040 int numParams = numKernels * numSpatial; // Number of parameters being solved for 1041 int numSolution1 = numParams, numSolution2 = 0; // Number of parameters for each solution 933 1042 if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 934 1043 // An additional image is convolved … … 960 1069 961 1070 if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) { 962 // Accumulate the least-squares matricies and vectors 1071 // Accumulate the least-squares matrices and vectors. These are generated for the 1072 // kernel elements, excluding the background and normalization. 963 1073 psImage *sumMatrix = psImageAlloc(numParams, numParams, PS_TYPE_F64); // Combined matrix 964 1074 psVector *sumVector = psVectorAlloc(numParams, PS_TYPE_F64); // Combined vector … … 966 1076 psImageInit(sumMatrix, 0.0); 967 1077 968 psVector *norms = psVectorAllocEmpty(stamps->num, PS_TYPE_F64); // Normalisations969 970 1078 int numStamps = 0; // Number of good stamps 1079 for (int i = 0; i < stamps->num; i++) { 1080 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 1081 if (stamp->status == PM_SUBTRACTION_STAMP_USED) { 1082 1083 (void)psBinaryOp(sumMatrix, sumMatrix, "+", stamp->matrix); 1084 (void)psBinaryOp(sumVector, sumVector, "+", stamp->vector); 1085 1086 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green"); 1087 numStamps++; 1088 } else if (stamp->status == PM_SUBTRACTION_STAMP_REJECTED) { 1089 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red"); 1090 } 1091 } 1092 1093 #if 0 1094 psImage *save = psImageCopy(NULL, sumMatrix, PS_TYPE_F32); 1095 psFitsWriteImageSimple ("sumMatrix.fits", save, NULL); 1096 psVectorWriteFile("sumVector.dat", sumVector); 1097 psFree (save); 1098 #endif 1099 1100 psVector *solution = NULL; // Solution to equation! 1101 solution = psVectorAlloc(numParams, PS_TYPE_F64); 1102 psVectorInit(solution, 0); 1103 1104 // XXX TEST: try some constraint on the svd solution 1105 // solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1106 // SINGLE solution 1107 if (1) { 1108 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1109 } else { 1110 psVector *PERM = NULL; 1111 psImage *LU = psMatrixLUDecomposition(NULL, &PERM, sumMatrix); 1112 solution = psMatrixLUSolution(solution, LU, sumVector, PERM); 1113 psFree (LU); 1114 psFree (PERM); 1115 } 1116 1117 # if (0) 1118 for (int i = 0; i < solution->n; i++) { 1119 psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "Single solution %d: %lf\n", i, solution->data.F64[i]); 1120 } 1121 # endif 1122 1123 if (!kernels->solution1) { 1124 kernels->solution1 = psVectorAlloc(sumVector->n + 2, PS_TYPE_F64); // 1 for norm, 1 for bg 1125 psVectorInit(kernels->solution1, 0.0); 1126 } 1127 1128 int numKernels = kernels->num; 1129 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 1130 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 1131 for (int i = 0; i < numKernels * numPoly; i++) { 1132 kernels->solution1->data.F64[i] = solution->data.F64[i]; 1133 } 1134 1135 // Apply the normalisation and background separately 1136 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1137 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 1138 kernels->solution1->data.F64[normIndex] = stamps->normValue; 1139 kernels->solution1->data.F64[bgIndex] = 0.0; 1140 1141 psFree(solution); 1142 psFree(sumVector); 1143 psFree(sumMatrix); 1144 1145 } else { 1146 // Dual convolution solution 1147 // Accumulate the least-squares matrices and vectors. These are generated for the 1148 // kernel elements, excluding the background and normalization. 1149 psImage *sumMatrix = psImageAlloc(numParams, numParams, PS_TYPE_F64); 1150 psVector *sumVector = psVectorAlloc(numParams, PS_TYPE_F64); 1151 psImageInit(sumMatrix, 0.0); 1152 psVectorInit(sumVector, 0.0); 1153 1154 int numStamps = 0; // Number of good stamps 1155 double normSquare1 = 0.0; // Sum of (I_1)^2 over stamps 1156 double normSquare2 = 0.0; // Sum of (I_2)^2 over stamps 971 1157 for (int i = 0; i < stamps->num; i++) { 972 1158 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest … … 974 1160 (void)psBinaryOp(sumMatrix, sumMatrix, "+", stamp->matrix); 975 1161 (void)psBinaryOp(sumVector, sumVector, "+", stamp->vector); 976 psVectorAppend(norms, stamp->norm); 1162 1163 normSquare1 += stamp->normSquare1; 1164 normSquare2 += stamp->normSquare2; 1165 977 1166 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green"); 978 1167 numStamps++; … … 983 1172 984 1173 #if 0 985 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 986 calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[bgIndex][bgIndex]); 1174 psImage *save = psImageCopy(NULL, sumMatrix, PS_TYPE_F32); 1175 psFitsWriteImageSimple ("sumMatrix.fits", save, NULL); 1176 psVectorWriteFile("sumVector.dat", sumVector); 1177 psFree (save); 987 1178 #endif 1179 1180 if (PENALTY) { 1181 calculatePenalty(sumMatrix, sumVector, kernels, normSquare1, normSquare2); 1182 } 988 1183 989 1184 psVector *solution = NULL; // Solution to equation! … … 991 1186 psVectorInit(solution, 0); 992 1187 993 #if 0 994 // Regular, straight-forward solution 995 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 996 #else 997 { 998 // Solve normalisation and background separately 999 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1000 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 1001 1002 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics for norm 1003 if (!psVectorStats(stats, norms, NULL, NULL, 0)) { 1004 psError(PM_ERR_DATA, false, "Unable to determine median normalisation"); 1005 psFree(stats); 1006 psFree(sumMatrix); 1007 psFree(sumVector); 1008 psFree(norms); 1009 return false; 1010 } 1011 1012 // double normValue = 1.0; 1013 double normValue = stats->robustMedian; 1014 // double bgValue = 0.0; 1015 1016 psFree(stats); 1017 1018 #ifdef TESTING 1019 fprintf(stderr, "Norm: %lf\n", normValue); 1020 #endif 1021 // Solve kernel components 1022 for (int i = 0; i < numSolution1; i++) { 1023 sumVector->data.F64[i] -= normValue * sumMatrix->data.F64[normIndex][i]; 1024 1025 sumMatrix->data.F64[i][normIndex] = 0.0; 1026 sumMatrix->data.F64[normIndex][i] = 0.0; 1027 } 1028 sumVector->data.F64[bgIndex] -= normValue * sumMatrix->data.F64[normIndex][bgIndex]; 1029 sumMatrix->data.F64[bgIndex][normIndex] = 0.0; 1030 sumMatrix->data.F64[normIndex][bgIndex] = 0.0; 1031 1032 sumMatrix->data.F64[normIndex][normIndex] = 1.0; 1033 sumVector->data.F64[normIndex] = 0.0; 1034 1035 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1036 1037 solution->data.F64[normIndex] = normValue; 1038 } 1039 # endif 1040 1041 #if (1) 1042 for (int i = 0; i < solution->n; i++) { 1043 fprintf(stderr, "Single solution %d: %lf\n", i, solution->data.F64[i]); 1044 } 1045 #endif 1046 1047 if (!kernels->solution1) { 1048 kernels->solution1 = psVectorAlloc(sumVector->n, PS_TYPE_F64); 1049 psVectorInit(kernels->solution1, 0.0); 1050 } 1051 1052 // only update the solutions that we chose to calculate: 1053 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 1054 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1055 kernels->solution1->data.F64[normIndex] = solution->data.F64[normIndex]; 1056 } 1057 if (mode & PM_SUBTRACTION_EQUATION_BG) { 1058 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 1059 kernels->solution1->data.F64[bgIndex] = solution->data.F64[bgIndex]; 1060 } 1061 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 1062 int numKernels = kernels->num; 1063 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 1064 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 1065 for (int i = 0; i < numKernels * numPoly; i++) { 1066 kernels->solution1->data.F64[i] = solution->data.F64[i]; 1067 } 1068 } 1069 1070 psFree(norms); 1071 psFree(solution); 1072 psFree(sumVector); 1073 psFree(sumMatrix); 1074 1075 #ifdef TESTING 1076 // XXX double-check for NAN in data: 1077 for (int ix = 0; ix < kernels->solution1->n; ix++) { 1078 if (!isfinite(kernels->solution1->data.F64[ix])) { 1079 fprintf (stderr, "WARNING: NAN in vector\n"); 1080 } 1081 } 1082 #endif 1083 1084 } else { 1085 // Dual convolution solution 1086 1087 // Accumulation of stamp matrices/vectors 1088 psImage *sumMatrix = psImageAlloc(numParams, numParams, PS_TYPE_F64); 1089 psVector *sumVector = psVectorAlloc(numParams, PS_TYPE_F64); 1090 psImageInit(sumMatrix, 0.0); 1091 psVectorInit(sumVector, 0.0); 1092 1093 psVector *norms = psVectorAllocEmpty(stamps->num, PS_TYPE_F64); // Normalisations 1094 1095 int numStamps = 0; // Number of good stamps 1096 for (int i = 0; i < stamps->num; i++) { 1097 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 1098 if (stamp->status == PM_SUBTRACTION_STAMP_USED) { 1099 (void)psBinaryOp(sumMatrix, sumMatrix, "+", stamp->matrix); 1100 (void)psBinaryOp(sumVector, sumVector, "+", stamp->vector); 1101 1102 psVectorAppend(norms, stamp->norm); 1103 1104 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green"); 1105 numStamps++; 1106 } 1107 } 1108 1109 #ifdef TESTING 1110 psFitsWriteImageSimple ("sumMatrix.fits", sumMatrix, NULL); 1111 psVectorWriteFile("sumVector.dat", sumVector); 1112 #endif 1113 1114 #if 1 1115 // int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 1116 // calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[bgIndex][bgIndex]); 1117 1118 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1119 calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[normIndex][normIndex] / 100.0); 1120 #endif 1121 1122 psVector *solution = NULL; // Solution to equation! 1123 solution = psVectorAlloc(numParams, PS_TYPE_F64); 1124 psVectorInit(solution, 0); 1125 1126 #if 0 1127 // Regular, straight-forward solution 1128 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1129 #else 1130 { 1131 // Solve normalisation and background separately 1132 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1133 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 1134 1135 #if 0 1136 psImage *normMatrix = psImageAlloc(2, 2, PS_TYPE_F64); 1137 psVector *normVector = psVectorAlloc(2, PS_TYPE_F64); 1138 1139 normMatrix->data.F64[0][0] = sumMatrix->data.F64[normIndex][normIndex]; 1140 normMatrix->data.F64[1][1] = sumMatrix->data.F64[bgIndex][bgIndex]; 1141 normMatrix->data.F64[0][1] = normMatrix->data.F64[1][0] = sumMatrix->data.F64[normIndex][bgIndex]; 1142 1143 normVector->data.F64[0] = sumVector->data.F64[normIndex]; 1144 normVector->data.F64[1] = sumVector->data.F64[bgIndex]; 1145 1146 psVector *normSolution = psMatrixSolveSVD(NULL, normMatrix, normVector, NAN); 1147 1148 double normValue = normSolution->data.F64[0]; 1149 double bgValue = normSolution->data.F64[1]; 1150 1151 psFree(normMatrix); 1152 psFree(normVector); 1153 psFree(normSolution); 1154 #endif 1155 1156 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics for norm 1157 if (!psVectorStats(stats, norms, NULL, NULL, 0)) { 1158 psError(PM_ERR_DATA, false, "Unable to determine median normalisation"); 1159 psFree(stats); 1160 psFree(sumMatrix); 1161 psFree(sumVector); 1162 psFree(norms); 1163 return false; 1164 } 1165 1166 double normValue = stats->robustMedian; 1167 1168 psFree(stats); 1169 1170 #ifdef TESTING 1171 fprintf(stderr, "Norm: %lf\n", normValue); 1172 #endif 1173 1174 // Solve kernel components 1175 for (int i = 0; i < numSolution2; i++) { 1176 sumVector->data.F64[i] -= normValue * sumMatrix->data.F64[normIndex][i]; 1177 sumVector->data.F64[i + numSolution1] -= normValue * sumMatrix->data.F64[normIndex][i + numSolution1]; 1178 1179 sumMatrix->data.F64[i][normIndex] = 0.0; 1180 sumMatrix->data.F64[normIndex][i] = 0.0; 1181 1182 sumMatrix->data.F64[i + numSolution1][normIndex] = 0.0; 1183 sumMatrix->data.F64[normIndex][i + numSolution1] = 0.0; 1184 } 1185 sumVector->data.F64[bgIndex] -= normValue * sumMatrix->data.F64[normIndex][bgIndex]; 1186 sumMatrix->data.F64[bgIndex][normIndex] = 0.0; 1187 sumMatrix->data.F64[normIndex][bgIndex] = 0.0; 1188 1189 sumMatrix->data.F64[normIndex][normIndex] = 1.0; 1190 1191 sumVector->data.F64[normIndex] = 0.0; 1192 1193 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1194 1195 solution->data.F64[normIndex] = normValue; 1196 } 1197 #endif 1198 1199 1200 #if (1) 1188 // DUAL solution 1189 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1190 1191 #if (0) 1201 1192 for (int i = 0; i < solution->n; i++) { 1202 1193 fprintf(stderr, "Dual solution %d: %lf\n", i, solution->data.F64[i]); … … 1204 1195 #endif 1205 1196 1206 psFree(sumMatrix);1207 psFree(sumVector);1208 1209 psFree(norms);1210 1211 1197 if (!kernels->solution1) { 1212 kernels->solution1 = psVectorAlloc(numSolution1 , PS_TYPE_F64);1198 kernels->solution1 = psVectorAlloc(numSolution1 + 2, PS_TYPE_F64); 1213 1199 psVectorInit (kernels->solution1, 0.0); 1214 1200 } … … 1218 1204 } 1219 1205 1220 // only update the solutions that we chose to calculate: 1221 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 1222 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1223 kernels->solution1->data.F64[normIndex] = solution->data.F64[normIndex]; 1224 } 1225 if (mode & PM_SUBTRACTION_EQUATION_BG) { 1226 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 1227 kernels->solution1->data.F64[bgIndex] = solution->data.F64[bgIndex]; 1228 } 1229 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 1230 int numKernels = kernels->num; 1231 for (int i = 0; i < numKernels * numSpatial; i++) { 1232 // XXX fprintf (stderr, "keep\n"); 1233 kernels->solution1->data.F64[i] = solution->data.F64[i]; 1234 kernels->solution2->data.F64[i] = solution->data.F64[i + numSolution1]; 1235 } 1236 } 1237 1238 1239 memcpy(kernels->solution1->data.F64, solution->data.F64, 1240 numSolution1 * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 1241 memcpy(kernels->solution2->data.F64, &solution->data.F64[numSolution1], 1242 numSolution2 * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 1243 1206 // for DUAL convolution analysis, we apply the normalization to I1 as follows: 1207 // I1c = norm I1 + \Sum_i a_i norm I1 \cross k_i 1208 // I2c = I2 + \Sum_i b_i I2 \cross k_i 1209 1210 // We absorb the normalization into a_i after the analysis is complete to be consistent 1211 // with the SINGLE definitions of the convolutions 1212 1213 int numKernels = kernels->num; 1214 for (int i = 0; i < numKernels * numSpatial; i++) { 1215 // we solve for coefficients 1216 kernels->solution1->data.F64[i] = solution->data.F64[i] * stamps->normValue; 1217 kernels->solution2->data.F64[i] = solution->data.F64[i + numSolution1]; 1218 } 1219 1220 // Apply the normalisation and background separately 1221 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1222 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 1223 kernels->solution1->data.F64[normIndex] = stamps->normValue; 1224 kernels->solution1->data.F64[bgIndex] = 0.0; 1225 1226 psFree(sumMatrix); 1227 psFree(sumVector); 1244 1228 psFree(solution); 1245 1246 1229 } 1247 1230 … … 1265 1248 } 1266 1249 1267 bool pmSubtractionResidualStats(psVector *fSigRes, psVector *fMaxRes, psVector *fMinRes, psKernel *target, psKernel *source, psKernel *residual, double norm, int footprint) { 1268 1269 // XXX measure some useful stats on the residuals 1250 // measure some useful stats on the stamp residuals: 1251 // fResSigma : the residual stdev / total flux 1252 // fResOuter : the residual fabs / total flux for R > 2 pix 1253 // fResTotal : the residual fabs / total flux for R > 0 pix 1254 bool pmSubtractionResidualStats(psVector *fResSigma, psVector *fResOuter, psVector *fResTotal, psKernel *target, psKernel *source, psKernel *residual, double norm, int footprint) { 1255 1270 1256 float sum = 0.0; 1271 1257 float peak = 0.0; … … 1277 1263 } 1278 1264 1279 // only count pixels with more than X% of the source flux1280 // calculate stdev(dflux)1265 // init counters 1266 int npix = 0; 1281 1267 float dflux1 = 0.0; 1282 1268 float dflux2 = 0.0; 1283 int npix = 0; 1284 1285 float dmax = 0.0; 1286 float dmin = 0.0; 1269 float dOuter = 0.0; 1270 float dTotal = 0.0; 1287 1271 1288 1272 for (int y = - footprint; y <= footprint; y++) { 1289 1273 for (int x = - footprint; x <= footprint; x++) { 1290 float dflux = 0.5*(target->kernel[y][x] + source->kernel[y][x] * norm);1291 if (dflux < 0.02*sum) continue;1292 1274 dflux1 += residual->kernel[y][x]; 1293 1275 dflux2 += PS_SQR(residual->kernel[y][x]); 1294 dmax = PS_MAX(residual->kernel[y][x], dmax); 1295 dmin = PS_MIN(residual->kernel[y][x], dmin); 1276 dTotal += fabs(residual->kernel[y][x]); 1277 if (hypot(x,y) > 2.0) { 1278 dOuter += fabs(residual->kernel[y][x]); 1279 } 1296 1280 npix ++; 1297 1281 } … … 1299 1283 float sigma = sqrt(dflux2 / npix - PS_SQR(dflux1/npix)); 1300 1284 if (!isfinite(sum)) return false; 1301 if (!isfinite(dmax)) return false;1302 if (!isfinite(dmin)) return false;1303 1285 if (!isfinite(peak)) return false; 1304 1305 // fprintf (stderr, "sum: %f, peak: %f, sigma: %f, fsigma: %f, fmax: %f, fmin: %f\n", sum, peak, sigma, sigma/sum, dmax/peak, dmin/peak); 1306 psVectorAppend(fSigRes, sigma/sum); 1307 psVectorAppend(fMaxRes, dmax/peak); 1308 psVectorAppend(fMinRes, dmin/peak); 1286 if (!isfinite(dOuter)) return false; 1287 if (!isfinite(dTotal)) return false; 1288 1289 // fprintf (stderr, "sum: %f, peak: %f, sigma: %f, fsigma: %f, fmax: %f, fmin: %f\n", sum, peak, sigma, sigma/sum, dOuter/sum, dTotal/sum); 1290 psVectorAppend(fResSigma, sigma/sum); 1291 psVectorAppend(fResOuter, dOuter/sum); 1292 psVectorAppend(fResTotal, dTotal/sum); 1309 1293 return true; 1310 1294 } … … 1329 1313 pmSubtractionVisualShowFitInit (stamps); 1330 1314 1331 psVector *f SigRes= psVectorAllocEmpty(stamps->num, PS_TYPE_F32);1332 psVector *f MinRes= psVectorAllocEmpty(stamps->num, PS_TYPE_F32);1333 psVector *f MaxRes= psVectorAllocEmpty(stamps->num, PS_TYPE_F32);1315 psVector *fResSigma = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1316 psVector *fResOuter = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1317 psVector *fResTotal = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1334 1318 1335 1319 // we want to save the residual images for the 9 brightest stamps. … … 1443 1427 } 1444 1428 1445 pmSubtractionResidualStats(f SigRes, fMaxRes, fMinRes, target, source, residual, norm, footprint);1429 pmSubtractionResidualStats(fResSigma, fResOuter, fResTotal, target, source, residual, norm, footprint); 1446 1430 1447 1431 } else { … … 1479 1463 } 1480 1464 1481 pmSubtractionResidualStats(f SigRes, fMaxRes, fMinRes, image1, image2, residual, norm, footprint);1465 pmSubtractionResidualStats(fResSigma, fResOuter, fResTotal, image1, image2, residual, norm, footprint); 1482 1466 } 1483 1467 … … 1558 1542 1559 1543 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); 1560 psVectorStats (stats, f SigRes, NULL, NULL, 0);1561 kernels->f SigResMean= stats->robustMedian;1562 kernels->f SigResStdev = stats->robustStdev;1544 psVectorStats (stats, fResSigma, NULL, NULL, 0); 1545 kernels->fResSigmaMean = stats->robustMedian; 1546 kernels->fResSigmaStdev = stats->robustStdev; 1563 1547 1564 1548 psStatsInit (stats); 1565 psVectorStats (stats, f MaxRes, NULL, NULL, 0);1566 kernels->f MaxResMean= stats->robustMedian;1567 kernels->f MaxResStdev = stats->robustStdev;1549 psVectorStats (stats, fResOuter, NULL, NULL, 0); 1550 kernels->fResOuterMean = stats->robustMedian; 1551 kernels->fResOuterStdev = stats->robustStdev; 1568 1552 1569 1553 psStatsInit (stats); 1570 psVectorStats (stats, f MinRes, NULL, NULL, 0);1571 kernels->f MinResMean= stats->robustMedian;1572 kernels->f MinResStdev = stats->robustStdev;1554 psVectorStats (stats, fResTotal, NULL, NULL, 0); 1555 kernels->fResTotalMean = stats->robustMedian; 1556 kernels->fResTotalStdev = stats->robustStdev; 1573 1557 1574 1558 // XXX save these values somewhere 1575 psLogMsg("psModules.imcombine", PS_LOG_INFO, "f Sigma: %f +/- %f, fMaxRes: %f +/- %f, fMinRes: %f +/- %f",1576 kernels->f SigResMean, kernels->fSigResStdev,1577 kernels->f MaxResMean, kernels->fMaxResStdev,1578 kernels->f MinResMean, kernels->fMinResStdev);1579 1580 psFree (f SigRes);1581 psFree (f MaxRes);1582 psFree (f MinRes);1559 psLogMsg("psModules.imcombine", PS_LOG_INFO, "fResSigma: %f +/- %f, fResOuter: %f +/- %f, fResTotal: %f +/- %f", 1560 kernels->fResSigmaMean, kernels->fResSigmaStdev, 1561 kernels->fResOuterMean, kernels->fResOuterStdev, 1562 kernels->fResTotalMean, kernels->fResTotalStdev); 1563 1564 psFree (fResSigma); 1565 psFree (fResOuter); 1566 psFree (fResTotal); 1583 1567 psFree (stats); 1584 1568 } … … 1586 1570 psFree(residual); 1587 1571 psFree(polyValues); 1588 1589 1572 1590 1573 return deviations; … … 1912 1895 return true; 1913 1896 } 1914 1915 1916 # if 01917 1918 #ifdef TESTING1919 psFitsWriteImageSimple("A.fits", sumMatrix, NULL);1920 psVectorWriteFile ("B.dat", sumVector);1921 #endif1922 1923 # define SVD_ANALYSIS 01924 # define COEFF_SIG 0.01925 # define SVD_TOL 0.01926 1927 // Use SVD to determine the kernel coeffs (and validate)1928 if (SVD_ANALYSIS) {1929 1930 // We have sumVector and sumMatrix. we are trying to solve the following equation:1931 // sumMatrix * x = sumVector.1932 1933 // we can use any standard matrix inversion to solve this. However, the basis1934 // functions in general have substantial correlation, so that the solution may be1935 // somewhat poorly determined or unstable. If not numerically ill-conditioned, the1936 // system of equations may be statistically ill-conditioned. Noise in the image1937 // will drive insignificant, but correlated, terms in the solution. To avoid these1938 // problems, we can use SVD to identify numerically unconstrained values and to1939 // avoid statistically badly determined value.1940 1941 // A = sumMatrix, B = sumVector1942 // SVD: A = U w V^T -> A^{-1} = V (1/w) U^T1943 // x = V (1/w) (U^T B)1944 // \sigma_x = sqrt(diag(A^{-1}))1945 // solve for x and A^{-1} to get x & dx1946 // identify the elements of (1/w) that are nan (1/0.0) -> set to 0.01947 // identify the elements of x that are insignificant (x / dx < 1.0? < 0.5?) -> set to 0.01948 1949 // If I use the SVD trick to re-condition the matrix, I need to break out the1950 // kernel and normalization terms from the background term.1951 // XXX is this true? or was this due to an error in the analysis?1952 1953 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background1954 1955 // now pull out the kernel elements into their own square matrix1956 psImage *kernelMatrix = psImageAlloc (sumMatrix->numCols - 1, sumMatrix->numRows - 1, PS_TYPE_F64);1957 psVector *kernelVector = psVectorAlloc (sumMatrix->numCols - 1, PS_TYPE_F64);1958 1959 for (int ix = 0, kx = 0; ix < sumMatrix->numCols; ix++) {1960 if (ix == bgIndex) continue;1961 for (int iy = 0, ky = 0; iy < sumMatrix->numRows; iy++) {1962 if (iy == bgIndex) continue;1963 kernelMatrix->data.F64[ky][kx] = sumMatrix->data.F64[iy][ix];1964 ky++;1965 }1966 kernelVector->data.F64[kx] = sumVector->data.F64[ix];1967 kx++;1968 }1969 1970 psImage *U = NULL;1971 psImage *V = NULL;1972 psVector *w = NULL;1973 if (!psMatrixSVD (&U, &w, &V, kernelMatrix)) {1974 psError(psErrorCodeLast(), false, "failed to perform SVD on sumMatrix\n");1975 return NULL;1976 }1977 1978 // calculate A_inverse:1979 // Ainv = V * w * U^T1980 psImage *wUt = p_pmSubSolve_wUt (w, U);1981 psImage *Ainv = p_pmSubSolve_VwUt (V, wUt);1982 psImage *Xvar = NULL;1983 psFree (wUt);1984 1985 # ifdef TESTING1986 // kernel terms:1987 for (int i = 0; i < w->n; i++) {1988 fprintf (stderr, "w: %f\n", w->data.F64[i]);1989 }1990 # endif1991 // loop over w adding in more and more of the values until chisquare is no longer1992 // dropping significantly.1993 // XXX this does not seem to work very well: we seem to need all terms even for1994 // simple cases...1995 1996 psVector *Xsvd = NULL;1997 {1998 psVector *Ax = NULL;1999 psVector *UtB = NULL;2000 psVector *wUtB = NULL;2001 2002 psVector *wApply = psVectorAlloc(w->n, PS_TYPE_F64);2003 psVector *wMask = psVectorAlloc(w->n, PS_TYPE_U8);2004 psVectorInit (wMask, 1); // start by masking everything2005 2006 double chiSquareLast = NAN;2007 int maxWeight = 0;2008 2009 double Axx, Bx, y2;2010 2011 // XXX this is an attempt to exclude insignificant modes.2012 // it was not successful with the ISIS kernel set: removing even2013 // the least significant mode leaves additional ringing / noise2014 // because the terms are so coupled.2015 for (int k = 0; false && (k < w->n); k++) {2016 2017 // unmask the k-th weight2018 wMask->data.U8[k] = 0;2019 p_pmSubSolve_SetWeights(wApply, w, wMask);2020 2021 // solve for x:2022 // x = V * w * (U^T * B)2023 p_pmSubSolve_UtB (&UtB, U, kernelVector);2024 p_pmSubSolve_wUtB (&wUtB, wApply, UtB);2025 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB);2026 2027 // chi-square for this system of equations:2028 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^22029 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^22030 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd);2031 p_pmSubSolve_VdV (&Axx, Ax, Xsvd);2032 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd);2033 p_pmSubSolve_y2 (&y2, kernels, stamps);2034 2035 // apparently, this works (compare with the brute force value below2036 double chiSquare = Axx - 2.0*Bx + y2;2037 double deltaChi = (k == 0) ? chiSquare : chiSquareLast - chiSquare;2038 chiSquareLast = chiSquare;2039 2040 // fprintf (stderr, "chi square = %f, delta: %f\n", chiSquare, deltaChi);2041 if (k && !maxWeight && (deltaChi < 1.0)) {2042 maxWeight = k;2043 }2044 }2045 2046 // keep all terms or we get extra ringing2047 maxWeight = w->n;2048 psVectorInit (wMask, 1);2049 for (int k = 0; k < maxWeight; k++) {2050 wMask->data.U8[k] = 0;2051 }2052 p_pmSubSolve_SetWeights(wApply, w, wMask);2053 2054 // solve for x:2055 // x = V * w * (U^T * B)2056 p_pmSubSolve_UtB (&UtB, U, kernelVector);2057 p_pmSubSolve_wUtB (&wUtB, wApply, UtB);2058 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB);2059 2060 // chi-square for this system of equations:2061 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^22062 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^22063 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd);2064 p_pmSubSolve_VdV (&Axx, Ax, Xsvd);2065 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd);2066 p_pmSubSolve_y2 (&y2, kernels, stamps);2067 2068 // apparently, this works (compare with the brute force value below2069 double chiSquare = Axx - 2.0*Bx + y2;2070 psLogMsg ("psModules.imcombine", PS_LOG_INFO, "model kernel with %d terms; chi square = %f\n", maxWeight, chiSquare);2071 2072 // re-calculate A^{-1} to get new variances:2073 // Ainv = V * w * U^T2074 // XXX since we keep all terms, this is identical to Ainv2075 psImage *wUt = p_pmSubSolve_wUt (wApply, U);2076 Xvar = p_pmSubSolve_VwUt (V, wUt);2077 psFree (wUt);2078 2079 psFree (Ax);2080 psFree (UtB);2081 psFree (wUtB);2082 psFree (wApply);2083 psFree (wMask);2084 }2085 2086 // copy the kernel solutions to the full solution vector:2087 solution = psVectorAlloc(sumVector->n, PS_TYPE_F64);2088 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64);2089 2090 for (int ix = 0, kx = 0; ix < sumVector->n; ix++) {2091 if (ix == bgIndex) {2092 solution->data.F64[ix] = 0;2093 solutionErr->data.F64[ix] = 0.001;2094 continue;2095 }2096 solutionErr->data.F64[ix] = sqrt(Ainv->data.F64[kx][kx]);2097 solution->data.F64[ix] = Xsvd->data.F64[kx];2098 kx++;2099 }2100 2101 psFree (kernelMatrix);2102 psFree (kernelVector);2103 2104 psFree (U);2105 psFree (V);2106 psFree (w);2107 2108 psFree (Ainv);2109 psFree (Xsvd);2110 } else {2111 psVector *permutation = NULL; // Permutation vector, required for LU decomposition2112 psImage *luMatrix = psMatrixLUDecomposition(NULL, &permutation, sumMatrix);2113 if (!luMatrix) {2114 psError(PM_ERR_DATA, true, "LU Decomposition of least-squares matrix failed.\n");2115 psFree(solution);2116 psFree(sumVector);2117 psFree(sumMatrix);2118 psFree(luMatrix);2119 psFree(permutation);2120 return NULL;2121 }2122 2123 solution = psMatrixLUSolution(NULL, luMatrix, sumVector, permutation);2124 psFree(luMatrix);2125 psFree(permutation);2126 if (!solution) {2127 psError(PM_ERR_DATA, true, "Failed to solve the least-squares system.\n");2128 psFree(solution);2129 psFree(sumVector);2130 psFree(sumMatrix);2131 return NULL;2132 }2133 2134 // XXX LUD does not provide A^{-1}? fake the error for now2135 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64);2136 for (int ix = 0; ix < sumVector->n; ix++) {2137 solutionErr->data.F64[ix] = 0.1*solution->data.F64[ix];2138 }2139 }2140 2141 if (!kernels->solution1) {2142 kernels->solution1 = psVectorAlloc (sumVector->n, PS_TYPE_F64);2143 psVectorInit (kernels->solution1, 0.0);2144 }2145 2146 // only update the solutions that we chose to calculate:2147 if (mode & PM_SUBTRACTION_EQUATION_NORM) {2148 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation2149 kernels->solution1->data.F64[normIndex] = solution->data.F64[normIndex];2150 }2151 if (mode & PM_SUBTRACTION_EQUATION_BG) {2152 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background2153 kernels->solution1->data.F64[bgIndex] = solution->data.F64[bgIndex];2154 }2155 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) {2156 int numKernels = kernels->num;2157 int spatialOrder = kernels->spatialOrder; // Order of spatial variation2158 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms2159 for (int i = 0; i < numKernels * numPoly; i++) {2160 // XXX fprintf (stderr, "%f +/- %f (%f) -> ", solution->data.F64[i], solutionErr->data.F64[i], fabs(solution->data.F64[i]/solutionErr->data.F64[i]));2161 if (fabs(solution->data.F64[i] / solutionErr->data.F64[i]) < COEFF_SIG) {2162 // XXX fprintf (stderr, "drop\n");2163 kernels->solution1->data.F64[i] = 0.0;2164 } else {2165 // XXX fprintf (stderr, "keep\n");2166 kernels->solution1->data.F64[i] = solution->data.F64[i];2167 }2168 }2169 }2170 // double chiSquare = p_pmSubSolve_ChiSquare (kernels, stamps);2171 // fprintf (stderr, "chi square Brute = %f\n", chiSquare);2172 2173 psFree(solution);2174 psFree(sumVector);2175 psFree(sumMatrix);2176 # endif2177 2178 #ifdef TESTING2179 // XXX double-check for NAN in data:2180 for (int iy = 0; iy < stamp->matrix->numRows; iy++) {2181 for (int ix = 0; ix < stamp->matrix->numCols; ix++) {2182 if (!isfinite(stamp->matrix->data.F64[iy][ix])) {2183 fprintf (stderr, "WARNING: NAN in matrix\n");2184 }2185 }2186 }2187 for (int ix = 0; ix < stamp->vector->n; ix++) {2188 if (!isfinite(stamp->vector->data.F64[ix])) {2189 fprintf (stderr, "WARNING: NAN in vector\n");2190 }2191 }2192 #endif2193 2194 #ifdef TESTING2195 for (int ix = 0; ix < sumVector->n; ix++) {2196 if (!isfinite(sumVector->data.F64[ix])) {2197 fprintf (stderr, "WARNING: NAN in vector\n");2198 }2199 }2200 #endif2201 2202 #ifdef TESTING2203 for (int ix = 0; ix < sumVector->n; ix++) {2204 if (!isfinite(sumVector->data.F64[ix])) {2205 fprintf (stderr, "WARNING: NAN in vector\n");2206 }2207 }2208 {2209 psImage *inverse = psMatrixInvert(NULL, sumMatrix, NULL);2210 psFitsWriteImageSimple("matrixInv.fits", inverse, NULL);2211 psFree(inverse);2212 }2213 {2214 psImage *X = psMatrixInvert(NULL, sumMatrix, NULL);2215 psImage *Xt = psMatrixTranspose(NULL, X);2216 psImage *XtX = psMatrixMultiply(NULL, Xt, X);2217 psFitsWriteImageSimple("matrixErr.fits", XtX, NULL);2218 psFree(X);2219 psFree(Xt);2220 psFree(XtX);2221 }2222 #endif2223 -
trunk/psModules/src/imcombine/pmSubtractionEquation.h
r29004 r29543 65 65 ); 66 66 67 bool pmSubtractionCalculateNormalization( 68 pmSubtractionStampList *stamps, 69 const pmSubtractionMode mode); 70 71 bool pmSubtractionCalculateNormalizationStamp( 72 pmSubtractionStamp *stamp, // stamp on which to save normalization) 73 const psKernel *input, // Input image (target) 74 const psKernel *reference, // Reference image (convolution source) 75 int footprint, // (Half-)Size of stamp 76 int normWindow1, // Window (half-)size for normalisation measurement 77 int normWindow2 // Window (half-)size for normalisation measurement 78 ); 79 80 bool pmSubtractionCalculateMoments( 81 pmSubtractionKernels *kernels, // Kernels 82 pmSubtractionStampList *stamps); 83 84 bool pmSubtractionCalculateMomentsStamp( 85 pmSubtractionKernels *kernels, // Kernels 86 pmSubtractionStamp *stamp, // stamp on which to save normalization) 87 int footprint, // (Half-)Size of stamp 88 int normWindow1, // Window (half-)size for normalisation measurement 89 int normWindow2 // Window (half-)size for normalisation measurement 90 ); 91 92 bool pmSubtractionCalculateMomentsKernel(double *Mxx, double *Myy, psKernel *image, int footprint, int window); 93 67 94 #endif -
trunk/psModules/src/imcombine/pmSubtractionKernels.c
r29004 r29543 183 183 } 184 184 185 # define CENTRAL_DELTA 0 186 187 # if (CENTRAL_DELTA) 188 189 // XXX *** this code used the central pixel to force zero net flux, 190 // Alard actually uses kernel(0) for this purpose (for even order, kernel[i] = kernel'[i] - kernel[0]) 185 191 static bool pmSubtractionKernelPreCalcNormalize(pmSubtractionKernels *kernels, pmSubtractionKernelPreCalc *preCalc, 186 192 int index, int uOrder, int vOrder, float fwhm, … … 220 226 // Re-normalize 221 227 // scale2D = 1.0 / fabs(sum); 222 scale2D = 1.0 / sqrt(sum2) ;228 scale2D = 1.0 / sqrt(sum2) / PS_SQR(fwhm); 223 229 zeroNull = true; 224 230 } else { 225 231 // Odd functions: choose normalisation so that parameters have about the same strength as for even 226 232 // functions, no subtraction of null pixel because the sum is already (near) zero 227 scale2D = 1.0 / sqrt(sum2) ;233 scale2D = 1.0 / sqrt(sum2) / PS_SQR(fwhm); 228 234 zeroNull = false; 229 235 } … … 235 241 if (forceZeroNull) { 236 242 // Force rescaling and subtraction of null pixel even though the order doesn't indicate it's even 237 scale2D = 1.0 / fabs(sum) ;243 scale2D = 1.0 / fabs(sum) / PS_SQR(fwhm); 238 244 zeroNull = true; 239 245 } 240 246 if (!forceZeroNull && ((uOrder % 2) || (vOrder % 2))) { 241 247 // Odd function 242 scale2D = 1.0 / sqrt(sum2) ;248 scale2D = 1.0 / sqrt(sum2) / PS_SQR(fwhm); 243 249 } 244 250 … … 255 261 if (zeroNull) { 256 262 // preCalc->kernel->kernel[0][0] -= 1.0; 257 preCalc->kernel->kernel[0][0] -= sum / sqrt (sum2);258 } 259 260 #if 1263 preCalc->kernel->kernel[0][0] -= sum * scale2D; 264 } 265 266 #if 0 261 267 { 262 268 double Sum = 0.0; // Sum of kernel component … … 287 293 return true; 288 294 } 295 296 # else /* CENTRAL_DELTA */ 297 298 static bool zeroIsNormal = false; 299 300 // this code uses kernel(0) to force zero flux, and is invalid for other kinds of normalizations 301 static bool pmSubtractionKernelPreCalcNormalize(pmSubtractionKernels *kernels, pmSubtractionKernelPreCalc *preCalc, 302 int index, int uOrder, int vOrder, float fwhm, 303 bool AlardLuptonStyle, bool forceZeroNull) 304 { 305 // 1) for odd functions: no renormalization 306 // 2) for even functions, normalize the kernel to unity 307 // 3) for even functions & index > 0, subtract kernel(0) 308 309 // Calculate moments 310 double sum = 0.0, sum2 = 0.0; // Sum of kernel component 311 float min = INFINITY, max = -INFINITY; // Minimum and maximum kernel value 312 313 for (int v = preCalc->kernel->yMin; v <= preCalc->kernel->yMax; v++) { 314 for (int u = preCalc->kernel->xMin; u <= preCalc->kernel->xMax; u++) { 315 double value = preCalc->kernel->kernel[v][u]; 316 double value2 = PS_SQR(value); 317 sum += value; 318 sum2 += value2; 319 min = PS_MIN(value, min); 320 max = PS_MAX(value, max); 321 } 322 } 323 324 #if 0 325 fprintf(stderr, "%d raw: %lf, null: %f, min: %lf, max: %lf\n", index, sum, preCalc->kernel->kernel[0][0], min, max); 326 #endif 327 328 float scale2D = 1.0; // Scaling for 2-D kernels 329 float scale1D = 1.0; // Scaling for 1-D kernels 330 331 if (uOrder % 2 == 0 && vOrder % 2 == 0) { 332 333 scale2D = 1.0 / sum; // Scaling for 2-D kernels 334 scale1D = sqrtf(scale2D); // Scaling for 1-D kernels 335 336 for (int v = preCalc->kernel->yMin; v <= preCalc->kernel->yMax; v++) { 337 for (int u = preCalc->kernel->xMin; u <= preCalc->kernel->xMax; u++) { 338 preCalc->kernel->kernel[v][u] *= scale2D; 339 } 340 } 341 if (index == 0) { 342 zeroIsNormal = true; 343 } else { 344 psAssert(zeroIsNormal, "failed to normalize zero kernel first"); 345 pmSubtractionKernelPreCalc *zeroKernel = kernels->preCalc->data[0]; 346 psAssert(zeroKernel, "failed to supply zero kernel"); 347 for (int v = preCalc->kernel->yMin; v <= preCalc->kernel->yMax; v++) { 348 for (int u = preCalc->kernel->xMin; u <= preCalc->kernel->xMax; u++) { 349 preCalc->kernel->kernel[v][u] -= zeroKernel->kernel->kernel[v][u]; 350 } 351 } 352 } 353 354 // XXX why do we bother renormlizing the 1D kernels? I don't think we use them again... 355 if (preCalc->xKernel) { 356 psBinaryOp(preCalc->xKernel, preCalc->xKernel, "*", psScalarAlloc(scale1D, PS_TYPE_F32)); 357 } 358 if (preCalc->yKernel) { 359 psBinaryOp(preCalc->yKernel, preCalc->yKernel, "*", psScalarAlloc(scale1D, PS_TYPE_F32)); 360 } 361 } 362 363 #if 0 364 { 365 double Sum = 0.0; // Sum of kernel component 366 double Sum2 = 0.0; // Sum of kernel component 367 float min = INFINITY, max = -INFINITY; // Minimum and maximum kernel value 368 for (int v = preCalc->kernel->yMin; v <= preCalc->kernel->yMax; v++) { 369 for (int u = preCalc->kernel->xMin; u <= preCalc->kernel->xMax; u++) { 370 double value = preCalc->kernel->kernel[v][u]; 371 Sum += value; 372 Sum2 += PS_SQR(value); 373 min = PS_MIN(preCalc->kernel->kernel[v][u], min); 374 max = PS_MAX(preCalc->kernel->kernel[v][u], max); 375 } 376 } 377 fprintf(stderr, "%d sum: %lf, sum2: %lf, null: %f, min: %lf, max: %lf, scale: %f\n", index, Sum, Sum2, preCalc->kernel->kernel[0][0], min, max, scale2D); 378 } 379 #endif 380 381 kernels->widths->data.F32[index] = fwhm; 382 kernels->u->data.S32[index] = uOrder; 383 kernels->v->data.S32[index] = vOrder; 384 if (kernels->preCalc->data[index]) { 385 psFree(kernels->preCalc->data[index]); 386 } 387 kernels->preCalc->data[index] = preCalc; 388 psTrace("psModules.imcombine", 7, "Kernel %d: %f %d %d\n", index, fwhm, uOrder, vOrder); 389 390 return true; 391 } 392 # endif /* Central Delta */ 289 393 290 394 pmSubtractionKernels *p_pmSubtractionKernelsRawISIS(int size, int spatialOrder, … … 603 707 kernels->sampleStamps = NULL; 604 708 605 kernels->f SigResMean = NAN;606 kernels->f SigResStdev = NAN;607 kernels->f MaxResMean = NAN;608 kernels->f MaxResStdev = NAN;609 kernels->f MinResMean = NAN;610 kernels->f MinResStdev = NAN;709 kernels->fResSigmaMean = NAN; 710 kernels->fResSigmaStdev = NAN; 711 kernels->fResOuterMean = NAN; 712 kernels->fResOuterStdev = NAN; 713 kernels->fResTotalMean = NAN; 714 kernels->fResTotalStdev = NAN; 611 715 612 716 return kernels; -
trunk/psModules/src/imcombine/pmSubtractionKernels.h
r29004 r29543 51 51 float mean, rms; ///< Mean and RMS of chi^2 from stamps 52 52 int numStamps; ///< Number of good stamps 53 float f SigResMean;///< mean fractional stdev of residuals54 float f SigResStdev;///< stdev of fractional stdev of residuals55 float f MaxResMean;///< mean fractional positive swing in residuals56 float f MaxResStdev;///< stdev of fractional positive swing in residuals57 float f MinResMean;///< mean fractional negative swing in residuals58 float f MinResStdev;///< stdev of fractional negative swing in residuals53 float fResSigmaMean; ///< mean fractional stdev of residuals 54 float fResSigmaStdev; ///< stdev of fractional stdev of residuals 55 float fResOuterMean; ///< mean fractional positive swing in residuals 56 float fResOuterStdev; ///< stdev of fractional positive swing in residuals 57 float fResTotalMean; ///< mean fractional negative swing in residuals 58 float fResTotalStdev; ///< stdev of fractional negative swing in residuals 59 59 psArray *sampleStamps; ///< array of brightest set of stamps for output visualizations 60 60 } pmSubtractionKernels; -
trunk/psModules/src/imcombine/pmSubtractionMatch.c
r29004 r29543 28 28 static bool useFFT = true; // Do convolutions using FFT 29 29 30 # define SEPARATE 031 # if (SEPARATE)32 # define SUBMODE PM_SUBTRACTION_EQUATION_NORM33 # else34 30 # define SUBMODE PM_SUBTRACTION_EQUATION_ALL 35 # endif36 31 37 32 //#define TESTING … … 280 275 } 281 276 282 bool pmSubtractionMaskInvalid (const pmReadout *readout, psImageMaskType maskVal) {283 284 if (!readout) return true;285 286 psImage *image = readout->image;287 psImage *mask = readout->mask;288 psImage *variance = readout->variance;289 for (int y = 0; y < image->numRows; y++) {290 for (int x = 0; x < image->numCols; x++) {291 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) continue;292 bool valid = false;293 valid = isfinite(image->data.F32[y][x]);294 if (variance) {295 valid &= isfinite(variance->data.F32[y][x]);296 }297 if (valid) continue;298 mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = maskVal;299 }300 }301 302 return true;303 }277 // bool pmSubtractionMaskInvalid (const pmReadout *readout, psImageMaskType maskVal) { 278 // 279 // if (!readout) return true; 280 // 281 // psImage *image = readout->image; 282 // psImage *mask = readout->mask; 283 // psImage *variance = readout->variance; 284 // for (int y = 0; y < image->numRows; y++) { 285 // for (int x = 0; x < image->numCols; x++) { 286 // if (mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) continue; 287 // bool valid = false; 288 // valid = isfinite(image->data.F32[y][x]); 289 // if (variance) { 290 // valid &= isfinite(variance->data.F32[y][x]); 291 // } 292 // if (valid) continue; 293 // mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = maskVal; 294 // } 295 // } 296 // 297 // return true; 298 // } 304 299 305 300 bool pmSubtractionMatchPrecalc(pmReadout *conv1, pmReadout *conv2, const pmReadout *ro1, const pmReadout *ro2, … … 392 387 } 393 388 394 pmSubtractionMaskInvalid(ro1, maskVal); 395 pmSubtractionMaskInvalid(ro2, maskVal); 389 // XXX this is done before calling this function 390 // pmSubtractionMaskInvalid(ro1, maskVal); 391 // pmSubtractionMaskInvalid(ro2, maskVal); 396 392 397 393 // General background subtraction, since this is done in pmSubtractionMatch … … 565 561 memCheck("start"); 566 562 567 pmSubtractionMaskInvalid(ro1, maskVal);568 pmSubtractionMaskInvalid(ro2, maskVal);563 // pmSubtractionMaskInvalid(ro1, maskVal); 564 // pmSubtractionMaskInvalid(ro2, maskVal); 569 565 570 566 psRegion bounds = psRegionSet(NAN, NAN, NAN, NAN); // Bounds of valid pixels … … 672 668 kernels = pmSubtractionKernelsGenerate(type, size, spatialOrder, isisWidths, isisOrders, 673 669 inner, binning, ringsOrder, penalty, bounds, subMode); 674 // pmSubtractionVisualShowKernels(kernels);675 670 } 676 671 … … 678 673 679 674 if (subMode == PM_SUBTRACTION_MODE_UNSURE) { 680 #if 0681 // Get backgrounds682 psStats *bgStats = psStatsAlloc(BG_STAT); // Statistics for background683 psVector *buffer = NULL;// Buffer for stats684 if (!psImageBackground(bgStats, &buffer, ro1->image, ro1->mask, maskVal, rng)) {685 psError(PM_ERR_DATA, false, "Unable to measure background of image 1.");686 psFree(bgStats);687 psFree(buffer);688 goto MATCH_ERROR;689 }690 float bg1 = psStatsGetValue(bgStats, BG_STAT); // Background for image 1691 if (!psImageBackground(bgStats, &buffer, ro2->image, ro2->mask, maskVal, rng)) {692 psError(PM_ERR_DATA, false, "Unable to measure background of image 2.");693 psFree(bgStats);694 psFree(buffer);695 goto MATCH_ERROR;696 }697 float bg2 = psStatsGetValue(bgStats, BG_STAT); // Background for image 2698 psFree(bgStats);699 psFree(buffer);700 701 pmSubtractionMode newMode = pmSubtractionOrder(stamps, bg1, bg2); // Subtraction mode to use702 #endif703 675 pmSubtractionMode newMode = pmSubtractionBestMode(&stamps, &kernels, subMask, rej); 704 676 switch (newMode) { … … 732 704 } 733 705 734 // XXX step 1: calculate normalization 735 psTrace("psModules.imcombine", 3, "Calculating equation for normalization...\n"); 706 // step 0 : calculate the normalizations, pass along to the next steps via stamps->normValue 707 psTrace("psModules.imcombine", 3, "Calculating normalization...\n"); 708 if (!pmSubtractionCalculateNormalization(stamps, kernels->mode)) { 709 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 710 goto MATCH_ERROR; 711 } 712 713 // step 0b : calculate the moments, pass along to the next steps via stamps->normValue 714 // XXX this step is now skipped -- delete 715 psTrace("psModules.imcombine", 3, "Calculating normalization...\n"); 716 if (!pmSubtractionCalculateMoments(kernels, stamps)) { 717 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 718 goto MATCH_ERROR; 719 } 720 721 // step 1: generate the elements of the matrix equation Ax = B 722 psTrace("psModules.imcombine", 3, "Calculating kernel equations...\n"); 736 723 if (!pmSubtractionCalculateEquation(stamps, kernels, SUBMODE)) { 737 724 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); … … 739 726 } 740 727 741 psTrace("psModules.imcombine", 3, "Solving equation for normalization...\n"); 728 // step 2: solve the matrix equation Ax = B 729 psTrace("psModules.imcombine", 3, "Solving kernel equations...\n"); 742 730 if (!pmSubtractionSolveEquation(kernels, stamps, SUBMODE)) { 743 731 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); … … 746 734 memCheck(" solve equation"); 747 735 748 # if (SEPARATE)749 // set USED -> CALCULATE750 pmSubtractionStampsResetStatus (stamps);751 752 // XXX step 2: calculate kernel parameters753 psTrace("psModules.imcombine", 3, "Calculating equation for kernels...\n");754 if (!pmSubtractionCalculateEquation(stamps, kernels, PM_SUBTRACTION_EQUATION_KERNELS)) {755 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");756 goto MATCH_ERROR;757 }758 memCheck(" calculate equation");759 760 psTrace("psModules.imcombine", 3, "Solving equation for kernels...\n");761 if (!pmSubtractionSolveEquation(kernels, stamps, PM_SUBTRACTION_EQUATION_KERNELS)) {762 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");763 goto MATCH_ERROR;764 }765 memCheck(" solve equation");766 # endif767 736 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations 768 737 if (!deviations) { … … 770 739 goto MATCH_ERROR; 771 740 } 772 773 741 memCheck(" calculate deviations"); 774 742 … … 787 755 // if we hit the max number of iterations and we have rejected stamps, re-solve 788 756 if (numRejected > 0) { 789 // XXX step 1: calculate normalization 757 758 // step 1: generate the elements of the matrix equation Ax = B 790 759 psTrace("psModules.imcombine", 3, "Calculating equation for normalization...\n"); 791 760 if (!pmSubtractionCalculateEquation(stamps, kernels, SUBMODE)) { … … 794 763 } 795 764 796 // s olve normalization765 // step 2: solve the matrix equation Ax = B 797 766 psTrace("psModules.imcombine", 3, "Solving equation for kernels...\n"); 798 767 if (!pmSubtractionSolveEquation(kernels, stamps, SUBMODE)) { … … 801 770 } 802 771 803 # if (SEPARATE)804 // set USED -> CALCULATE805 pmSubtractionStampsResetStatus (stamps);806 807 // XXX step 2: calculate kernel parameters808 psTrace("psModules.imcombine", 3, "Calculating equation for normalization...\n");809 if (!pmSubtractionCalculateEquation(stamps, kernels, PM_SUBTRACTION_EQUATION_KERNELS)) {810 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");811 goto MATCH_ERROR;812 }813 814 // solve kernel parameters815 psTrace("psModules.imcombine", 3, "Solving equation for kernels...\n");816 if (!pmSubtractionSolveEquation(kernels, stamps, PM_SUBTRACTION_EQUATION_KERNELS)) {817 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");818 goto MATCH_ERROR;819 }820 memCheck(" solve equation");821 # endif822 772 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations 823 773 if (!deviations) { … … 837 787 goto MATCH_ERROR; 838 788 } 839 840 789 memCheck("diag outputs"); 841 790 … … 1134 1083 } 1135 1084 1136 # if (SEPARATE)1137 // set USED -> CALCULATE1138 pmSubtractionStampsResetStatus (stamps);1139 1140 psTrace("psModules.imcombine", 3, "Calculating %s kernel coeffs equation...\n", description);1141 if (!pmSubtractionCalculateEquation(stamps, kernels, PM_SUBTRACTION_EQUATION_KERNELS)) {1142 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");1143 return false;1144 }1145 1146 psTrace("psModules.imcombine", 3, "Solving %s kernel coeffs equation...\n", description);1147 if (!pmSubtractionSolveEquation(kernels, stamps, PM_SUBTRACTION_EQUATION_KERNELS)) {1148 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");1149 return false;1150 }1151 # endif1152 1153 1085 psTrace("psModules.imcombine", 3, "Calculate %s deviations...\n", description); 1154 1086 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations … … 1181 1113 } 1182 1114 psTrace("psModules.imcombine", 3, "Recalculate %s deviations...\n", description); 1183 1184 # if (SEPARATE)1185 // set USED -> CALCULATE1186 pmSubtractionStampsResetStatus (stamps);1187 1188 psTrace("psModules.imcombine", 3, "Calculating %s normalization equation...\n", description);1189 if (!pmSubtractionCalculateEquation(stamps, kernels, PM_SUBTRACTION_EQUATION_KERNELS)) {1190 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");1191 return false;1192 }1193 1194 psTrace("psModules.imcombine", 3, "Resolving %s equation...\n", description);1195 if (!pmSubtractionSolveEquation(kernels, stamps, PM_SUBTRACTION_EQUATION_KERNELS)) {1196 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");1197 return false;1198 }1199 psTrace("psModules.imcombine", 3, "Recalculate %s deviations...\n", description);1200 # endif1201 1115 1202 1116 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations … … 1288 1202 1289 1203 bool pmSubtractionParamsScale(int *kernelSize, int *stampSize, psVector *widths, 1290 float fwhm1, float fwhm2, floatscaleRef, float scaleMin, float scaleMax)1204 float scaleRef, float scaleMin, float scaleMax) 1291 1205 { 1292 1206 PS_ASSERT_PTR_NON_NULL(kernelSize, false); … … 1294 1208 PS_ASSERT_VECTOR_NON_NULL(widths, false); 1295 1209 PS_ASSERT_VECTOR_TYPE(widths, PS_TYPE_F32, false); 1296 PS_ASSERT_FLOAT_LARGER_THAN(fwhm1, 0.0, false);1297 PS_ASSERT_FLOAT_LARGER_THAN(fwhm2, 0.0, false);1298 1210 PS_ASSERT_FLOAT_LARGER_THAN(scaleRef, 0.0, false); 1299 1211 PS_ASSERT_FLOAT_LARGER_THAN(scaleMin, 0.0, false); … … 1301 1213 PS_ASSERT_FLOAT_LARGER_THAN(scaleMax, scaleMin, false); 1302 1214 1303 // float diff = sqrtf(PS_SQR(PS_MAX(fwhm1, fwhm2)) - PS_SQR(PS_MIN(fwhm1, fwhm2))); // Difference 1215 float fwhm1; 1216 float fwhm2; 1217 1218 pmSubtractionGetFWHMs(&fwhm1, &fwhm2); 1219 psAssert(isfinite(fwhm1), "fwhm 1 not set"); 1220 psAssert(isfinite(fwhm2), "fwhm 2 not set"); 1221 1222 // float diff = sqrtf(PS_SQR(PS_MAX(fwhm1, fwhm2)) - PS_SQR(PS_MIN(fwhm1, fwhm2))); // Difference 1304 1223 float scale = PS_MAX(fwhm1, fwhm2) / scaleRef; // Scaling factor 1305 1306 // XXX save these values in a static for later use1307 pmSubtractionSetFWHMs(fwhm1, fwhm2);1308 1224 1309 1225 if (isfinite(scaleMin) && scale < scaleMin) { -
trunk/psModules/src/imcombine/pmSubtractionMatch.h
r29004 r29543 104 104 int *stampSize, ///< Half-size of the stamp (footprint) 105 105 psVector *widths, ///< ISIS widths 106 float fwhm1, float fwhm2, ///< FWHMs for inputs107 106 float scaleRef, ///< Reference width for scaling 108 107 float scaleMin, ///< Minimum scaling ratio, or NAN -
trunk/psModules/src/imcombine/pmSubtractionStamps.c
r29019 r29543 51 51 psFree(list->y); 52 52 psFree(list->flux); 53 psFree(list->window); 53 54 psFree(list->window1); 54 55 psFree(list->window2); … … 96 97 97 98 // fprintf (stderr, "xMin, xMax: %d, %d -> ", xMin, xMax); 99 // float xRaw = xMin; 100 // float yRaw = yMin; 98 101 99 102 // Ensure we're not going to go outside the bounds of the image … … 103 106 yMax = PS_MIN(numRows - border - 1, yMax); 104 107 105 if (xMax < xMin) return false; 106 if (yMax < yMin) return false; 108 if (xMax < xMin) { 109 // fprintf (stderr, "%f,%f : x-border\n", xRaw, yRaw); 110 return false; 111 } 112 if (yMax < yMin) { 113 // fprintf (stderr, "%f,%f : y-border\n", xRaw, yRaw); 114 return false; 115 } 107 116 108 117 psAssert (xMin <= xMax, "x mismatch?"); … … 118 127 if (subMask && subMask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 119 128 (PM_SUBTRACTION_MASK_BORDER | PM_SUBTRACTION_MASK_REJ)) { 129 // fprintf (stderr, "%f,%f : masked\n", xRaw, yRaw); 120 130 return false; 121 131 } … … 133 143 } 134 144 145 // if (!found) { 146 // fprintf (stderr, "%f,%f : fails flux test\n", xRaw, yRaw); 147 // } 148 135 149 return found; 136 150 } … … 232 246 list->flux = NULL; 233 247 list->normFrac = normFrac; 248 list->normValue = NAN; 249 list->window = NULL; 234 250 list->window1 = NULL; 235 251 list->window2 = NULL; … … 256 272 out->y = NULL; 257 273 out->flux = NULL; 274 out->window = psMemIncrRefCounter(in->window); 258 275 out->window1 = psMemIncrRefCounter(in->window1); 259 276 out->window2 = psMemIncrRefCounter(in->window2); … … 331 348 stamp->vector = NULL; 332 349 stamp->norm = NAN; 350 stamp->normI1 = NAN; 351 stamp->normI2 = NAN; 352 stamp->normSquare1 = NAN; 353 stamp->normSquare2 = NAN; 354 355 stamp->MxxI1 = NULL; 356 stamp->MyyI1 = NULL; 357 stamp->MxxI2 = NULL; 358 stamp->MyyI2 = NULL; 359 360 stamp->MxxI1raw = NAN; 361 stamp->MyyI1raw = NAN; 362 stamp->MxxI2raw = NAN; 363 stamp->MyyI2raw = NAN; 333 364 334 365 return stamp; … … 431 462 // Take stamps off the top of the (sorted) list 432 463 for (int j = xList->n - 1; j >= 0 && !goodStamp; j--) { 464 // fprintf (stderr, "%d : xList: %ld elements\n", i, xList->n); 433 465 // Chop off the top of the list 434 466 xList->n = j; … … 459 491 yList->data.F32[j], yList->data.F32[j], numCols, numRows, border); 460 492 #endif 461 if (0 && goodStamp) {462 fprintf (stderr, "find: %6.1f < %6.1f < %6.1f, %6.1f < %6.1f %6.1f\n",463 region->x0 + size, xStamp, region->x1 - size,464 region->y0 + size, yStamp, region->y1 - size);465 }466 493 } 467 494 } else { … … 656 683 psImageInit(stamps->window2->image, 0.0); 657 684 685 // Generate a weighting window based on the fwhms (20% larger than the largest) 686 { 687 float fwhm1, fwhm2; 688 689 // XXX this is annoyingly hack-ish 690 pmSubtractionGetFWHMs(&fwhm1, &fwhm2); 691 692 float sigma = 1.5 * PS_MAX(fwhm1, fwhm2) / 2.35; 693 694 psFree (stamps->window); 695 stamps->window = psKernelAlloc(-size, size, -size, size); 696 psImageInit(stamps->window->image, 0.0); 697 698 for (int y = -size; y <= size; y++) { 699 for (int x = -size; x <= size; x++) { 700 stamps->window->kernel[y][x] = exp(-0.5*(x*x + y*y)/(sigma*sigma)); 701 } 702 } 703 } 704 658 705 // generate normalizations for each stamp 659 706 psVector *norm1 = psVectorAlloc(stamps->num, PS_TYPE_F32); … … 678 725 679 726 // storage vector for flux data 680 psStats *stats = psStatsAlloc (PS_STAT_ ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);727 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN); 681 728 psVector *flux1 = psVectorAllocEmpty(2*stamps->num, PS_TYPE_F32); 682 729 psVector *flux2 = psVectorAllocEmpty(2*stamps->num, PS_TYPE_F32); … … 706 753 psAbort ("failed to generate stats"); 707 754 } 708 float f1 = stats-> robustMedian;755 float f1 = stats->sampleMedian; 709 756 710 757 psStatsInit (stats); … … 712 759 psAbort ("failed to generate stats"); 713 760 } 714 float f2 = stats-> robustMedian;761 float f2 = stats->sampleMedian; 715 762 716 763 stamps->window1->kernel[y][x] = f1; … … 728 775 } 729 776 777 #if 0 778 { 779 psFits *fits = NULL; 780 fits = psFitsOpen ("window1.raw.fits", "w"); 781 psFitsWriteImage (fits, NULL, stamps->window1->image, 0, NULL); 782 psFitsClose (fits); 783 fits = psFitsOpen ("window2.raw.fits", "w"); 784 psFitsWriteImage (fits, NULL, stamps->window2->image, 0, NULL); 785 psFitsClose (fits); 786 } 787 #endif 788 730 789 psTrace("psModules.imcombine", 3, "Window total (1): %f, threshold: %f\n", sum1, (1.0 - stamps->normFrac) * sum1); 731 790 psTrace("psModules.imcombine", 3, "Window total (2): %f, threshold: %f\n", sum2, (1.0 - stamps->normFrac) * sum2); 732 791 733 # if ( 0)792 # if (1) 734 793 // this block attempts to calculate the radius based on the first radial moment 735 bool done1 = false;736 bool done2 = false;737 double prior1 = 0.0;738 double prior2 = 0.0;794 double Sr1 = 0.0; 795 double Sr2 = 0.0; 796 double Sf1 = 0.0; 797 double Sf2 = 0.0; 739 798 for (int y = -size; y <= size; y++) { 740 799 for (int x = -size; x <= size; x++) { … … 750 809 float R2 = Sr2 / Sf2; 751 810 752 stamps->normWindow1 = 2.5*R1; 753 stamps->normWindow1 = 2.5*R2; 811 stamps->normWindow1 = 2.0*R1; 812 stamps->normWindow2 = 2.0*R2; 813 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "Kron Radii: %f for 1, %f for 2\n", stamps->normWindow1, stamps->normWindow2); 814 754 815 # else 755 816 // XXX : this block attempts to calculate the radius by looking at the curve of growth (or something vaguely equivalent). … … 778 839 // interpolate to the radius at which delta2 is normFrac: 779 840 stamps->normWindow1 = radius - (stamps->normFrac - delta1) / (delta1o - delta1); 780 fprintf (stderr, "choosing %f (%d) for 1 (%f : %f)\n", stamps->normWindow1, radius, within1, delta1);841 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "choosing %f (%d) for 1 (%f : %f)\n", stamps->normWindow1, radius, within1, delta1); 781 842 done1 = true; 782 843 } … … 785 846 // interpolate to the radius at which delta2 is normFrac: 786 847 stamps->normWindow2 = radius - (stamps->normFrac - delta2) / (delta2o - delta2); 787 fprintf (stderr, "choosing %f (%d) for 2 (%f : %f)\n", stamps->normWindow2, radius, within2, delta2);848 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "choosing %f (%d) for 2 (%f : %f)\n", stamps->normWindow2, radius, within2, delta2); 788 849 done2 = true; 789 850 } … … 833 894 { 834 895 psFits *fits = NULL; 835 fits = psFitsOpen ("window1. fits", "w");896 fits = psFitsOpen ("window1.norm.fits", "w"); 836 897 psFitsWriteImage (fits, NULL, stamps->window1->image, 0, NULL); 837 898 psFitsClose (fits); 838 fits = psFitsOpen ("window2. fits", "w");899 fits = psFitsOpen ("window2.norm.fits", "w"); 839 900 psFitsWriteImage (fits, NULL, stamps->window2->image, 0, NULL); 840 901 psFitsClose (fits); … … 906 967 float M2 = pmSubtractionKernelPenaltySingle(kernel->kernel, zeroNull); 907 968 908 penalty1 = M2 + PS_SQR(fwhm1 / 2.35); // rescale the unconvolved second-moment by the image second moment 909 penalty2 = M2 + PS_SQR(fwhm2 / 2.35); // rescale the unconvolved second-moment by the image second moment 969 if (1) { 970 penalty1 = M2 * PS_SQR(fwhm1 / 2.35); // rescale the unconvolved second-moment by the image second moment 971 penalty2 = M2 * PS_SQR(fwhm2 / 2.35); // rescale the unconvolved second-moment by the image second moment 972 // penalty1 = M2 + PS_SQR(fwhm1 / 2.35); // rescale the unconvolved second-moment by the image second moment 973 // penalty2 = M2 + PS_SQR(fwhm2 / 2.35); // rescale the unconvolved second-moment by the image second moment 974 } else { 975 penalty1 = PS_SQR(fwhm1 / 2.35); // rescale the unconvolved second-moment by the image second moment 976 penalty2 = PS_SQR(fwhm2 / 2.35); // rescale the unconvolved second-moment by the image second moment 977 } 910 978 } 911 979 kernels->penalties1->data.F32[index] = kernels->penalty * penalty1; … … 915 983 psAssert (isfinite(kernels->penalties2->data.F32[index]), "invalid penalty"); 916 984 917 fprintf(stderr, "penalty1: %f, penalty2: %f\n", penalty1, penalty2);985 // fprintf(stderr, "penalty1: %f, penalty2: %f\n", penalty1, penalty2); 918 986 919 987 return true; … … 942 1010 penalty *= 1.0 / sum2; 943 1011 944 if ( 1) {945 fprintf(stderr, "min: %lf, max: %lf, moment: %lf, flux^2: %lf\n", min, max, penalty, sum2);1012 if (0) { 1013 // fprintf(stderr, "min: %lf, max: %lf, moment: %lf, flux^2: %lf\n", min, max, penalty, sum2); 946 1014 // psTrace("psModules.imcombine", 7, "Kernel %d: %f %d %d %f\n", index, fwhm, uOrder, vOrder, penalty); 947 1015 } … … 983 1051 984 1052 if (x < bounds.x0 + size || x > bounds.x1 - size || y < bounds.y0 + size || y > bounds.y1 - size) { 985 psError(PM_ERR_PROG, false, "Stamp %d (%d,%d) is within the region border.\n", i, x, y); 986 return false; 1053 psLogMsg("psModules.imcombine", 3, "Stamp %d (%d,%d) is within the region border.\n", i, x, y); 1054 stamp->status = PM_SUBTRACTION_STAMP_NONE; 1055 continue; 987 1056 } 988 1057 -
trunk/psModules/src/imcombine/pmSubtractionStamps.h
r29004 r29543 25 25 int footprint; ///< Half-size of stamps 26 26 float normFrac; ///< Fraction of flux in window for normalisation window 27 float normValue; ///< calculated normalization 28 float normValue2; ///< calculated normalization 27 29 psKernel *window1; ///< window function generated from ensemble of stamps (input 1) 28 30 psKernel *window2; ///< window function generated from ensemble of stamps (input 2) 29 float normWindow1; ///< Size of window for measuring normalisation 30 float normWindow2; ///< Size of window for measuring normalisation 31 psKernel *window; ///< weighting window function (sigma = 1.1 * MAX(fwhm)) 32 float normWindow1; ///< Size of window for measuring normalisation 33 float normWindow2; ///< Size of window for measuring normalisation 31 34 float sysErr; ///< Systematic error 32 35 float skyErr; ///< increase effective readnoise … … 85 88 psVector *vector; ///< Least-squares vector, or NULL 86 89 double norm; ///< Normalisation difference 90 double normI1; ///< Sum(flux) for image 1 91 double normI2; ///< Sum(flux) for image 2 92 double normSquare1; ///< Sum(flux^2) for image 1 (used for penalty) 93 double normSquare2; ///< Sum(flux^2) for image 2 (used for penalty) 87 94 pmSubtractionStampStatus status; ///< Status of stamp 95 psVector *MxxI1; ///< second moments of convolution images 96 psVector *MyyI1; ///< second moments of convolution images 97 psVector *MxxI2; ///< second moments of convolution images 98 psVector *MyyI2; ///< second moments of convolution images 99 double MxxI1raw; 100 double MyyI1raw; 101 double MxxI2raw; 102 double MyyI2raw; 88 103 } pmSubtractionStamp; 89 104 -
trunk/psModules/src/imcombine/pmSubtractionVisual.c
r29004 r29543 146 146 } 147 147 pmVisualScaleImage(kapa1, canvas, "Subtraction_Stamps", 0, true); 148 psFree(canvas); 148 149 149 150 pmVisualAskUser(&plotStamps); … … 152 153 153 154 /** Plot the least-squares matrix of each stamp */ 154 bool pmSubtractionVisualPlotLeastSquares (pmSubtractionStampList *stamps , bool dual) {155 bool pmSubtractionVisualPlotLeastSquares (pmSubtractionStampList *stamps) { 155 156 156 157 if (!pmVisualTestLevel("ppsub.chisq", 1)) return true; … … 209 210 pmVisualScaleImage(kapa1, canvas32, "Least_Squares", 0, true); 210 211 212 if (0) { 213 static int count = 0; 214 char filename[64]; 215 sprintf (filename, "chisq.%02d.fits", count); 216 count ++; 217 psFits *fits = psFitsOpen (filename, "w"); 218 psFitsWriteImage (fits, NULL, canvas32, 0, NULL); 219 psFitsClose (fits); 220 } 221 211 222 pmVisualAskUser(&plotLeastSquares); 212 223 psFree(canvas); … … 271 282 } 272 283 } 273 fprintf (stderr, "kernel %d, sum %f\n", i, sum);284 // fprintf (stderr, "kernel %d, sum %f\n", i, sum); 274 285 } 275 286 276 287 pmVisualScaleImage(kapa1, output, "Image", 0, true); 288 psFree(output); 277 289 pmVisualAskUser(&plotImage); 278 290 return true; … … 286 298 return false; 287 299 } 300 301 // XXX clear the overlay(s) (red at least!) 288 302 289 303 // get the kernel sizes … … 297 311 if (!isfinite(stamp->flux)) continue; 298 312 if (!stamp->convolutions1 && !stamp->convolutions2) continue; 313 // fprintf (stderr, "flux: %f, maxFlux: %f ", stamp->flux, maxFlux); 299 314 if (!maxStamp) { 300 315 maxFlux = stamp->flux; 301 316 maxStamp = stamp; 317 // fprintf (stderr, "maxStamp %d\n", i); 302 318 continue; 319 } else { 320 // fprintf (stderr, "\n"); 303 321 } 304 322 if (stamp->flux > maxFlux) { … … 337 355 338 356 double sum = 0.0; 357 double sum2 = 0.0; 339 358 for (int y = -footprint; y <= footprint; y++) { 340 359 for (int x = -footprint; x <= footprint; x++) { 341 360 output->data.F32[y + yPix][x + xPix] = kernel->kernel[y][x]; 342 361 sum += kernel->kernel[y][x]; 362 sum2 += PS_SQR(kernel->kernel[y][x]); 343 363 } 344 364 } 345 fprintf (stderr, "kernel %d, sum %f\n", i, sum);365 // fprintf (stderr, "kernel %d, sum %f, sum2: %e\n", i, sum, sum2); 346 366 } 347 367 pmVisualScaleImage(kapa2, output, "Image", 0, true); 348 } 368 369 if (0) { 370 psFits *fits = psFitsOpen("basis.1.fits", "w"); 371 psFitsWriteImage(fits, NULL, output, 0, NULL); 372 psFitsClose(fits); 373 } 374 } 349 375 350 376 if (maxStamp->convolutions2) { … … 371 397 372 398 double sum = 0.0; 399 double sum2 = 0.0; 373 400 for (int y = -footprint; y <= footprint; y++) { 374 401 for (int x = -footprint; x <= footprint; x++) { 375 402 output->data.F32[y + yPix][x + xPix] = kernel->kernel[y][x]; 376 403 sum += kernel->kernel[y][x]; 404 sum2 += PS_SQR(kernel->kernel[y][x]); 377 405 } 378 406 } 379 fprintf (stderr, "kernel %d, sum %f\n", i, sum);407 // fprintf (stderr, "kernel %d, sum %f, sum2: %e\n", i, sum, sum2); 380 408 } 381 409 pmVisualScaleImage(kapa2, output, "Image", 1, true); 410 411 if (0) { 412 psFits *fits = psFitsOpen("basis.2.fits", "w"); 413 psFitsWriteImage(fits, NULL, output, 0, NULL); 414 psFitsClose(fits); 415 } 416 psFree(output); 382 417 } 383 418 … … 676 711 psFree (x); 677 712 psFree (y); 713 psFree (polyValues); 678 714 679 715 pmVisualAskUser(NULL);
Note:
See TracChangeset
for help on using the changeset viewer.
