- Timestamp:
- Mar 5, 2012, 5:19:48 PM (14 years ago)
- Location:
- branches/meh_branches/ppstack_test
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/meh_branches/ppstack_test
- Property svn:mergeinfo changed
-
branches/meh_branches/ppstack_test/psModules
- Property svn:mergeinfo set to
-
branches/meh_branches/ppstack_test/psModules/src/detrend/pmPattern.c
r27676 r33415 6 6 7 7 #include "pmPattern.h" 8 9 #define PATTERN_ROW_BKG_FIX 1 8 10 9 11 … … 89 91 psImageInit(corr, NAN); 90 92 93 #ifdef PATTERN_ROW_BKG_FIX 94 // CZW: 2011-11-30 95 // Define the vectors to hold the "x" and "y" slope trends. 96 // Briefly, the slope trend in the y-axis is a due to variations in the 0-th order term 97 // of the PATTERN.ROW fit between individual rows across the cell. Similarly, the 1-st 98 // order term of the PATTERN.ROW fit defines the trend in the x-axis (as that's what we 99 // are fitting with PATTERN.ROW in the first place). However, the thing we're trying to 100 // fix with PATTERN.ROW is the detector level bias wiggles. These should be overlaid on 101 // the true sky level. Therefore, simply applying the PATTERN.ROW correction will 102 // introduce cell-to-cell sky variations as these two trends are removed. To avoid this, 103 // We store the 0th and 1st order values used for each row, and then fit a polynomial to 104 // these results. By re-adding these systematic trends back, we can remove the row-to-row 105 // variations without improperly removing the real sky trend. 106 psVector *yaxisData = psVectorAlloc(numRows, PS_TYPE_F32); // Data to fit to the constant term 107 psVector *yaxisMask = psVectorAlloc(numRows, PS_TYPE_VECTOR_MASK); // Mask for rows with no fit 108 psVector *xaxisData = psVectorAlloc(numRows, PS_TYPE_F32); // Data to fit to the linear term 109 psVectorInit(yaxisMask, 0); 110 #endif 91 111 for (int y = 0; y < numRows; y++) { 92 112 psVectorInit(clipMask, 0); … … 105 125 // Not enough points to fit 106 126 patternMaskRow(ro, y, maskBad); 127 #ifdef PATTERN_ROW_BKG_FIX 128 // Ignore this row in our subsequent fits, because the fit failed. 129 yaxisMask->data.PS_TYPE_VECTOR_MASK_DATA[y] = 0xFF; 130 #endif 107 131 continue; 108 132 } … … 111 135 psErrorClear(); 112 136 patternMaskRow(ro, y, maskBad); 113 continue; 114 } 115 116 poly->coeff[0] -= background; 137 #ifdef PATTERN_ROW_BKG_FIX 138 // Ignore this row in our subsequent fits, because the fit failed. 139 yaxisMask->data.PS_TYPE_VECTOR_MASK_DATA[y] = 0xFF; 140 #endif 141 continue; 142 } 143 #ifndef PATTERN_ROW_BKG_FIX 144 poly->coeff[0] -= background; 145 #else 146 // Store the results we found for this row. 147 yaxisData->data.F32[y] = poly->coeff[0]; 148 xaxisData->data.F32[y] = poly->coeff[1]; 149 psTrace("pattern",1,"%d %g %g\n",y,poly->coeff[0],poly->coeff[1]); 150 151 // yaxisData->data.F32[y] = 0.0; 152 /* xaxisData->data.F32[y] = 0.0; */ 153 154 #endif 117 155 memcpy(corr->data.F64[y], poly->coeff, (order + 1) * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 118 156 psVector *solution = psPolynomial1DEvalVector(poly, indices); // Solution vector … … 121 159 psErrorClear(); 122 160 patternMaskRow(ro, y, maskBad); 161 #ifdef PATTERN_ROW_BKG_FIX 162 yaxisMask->data.PS_TYPE_VECTOR_MASK_DATA[y] = 0xFF; 163 #endif 123 164 continue; 124 165 } … … 126 167 for (int x = 0; x < numCols; x++) { 127 168 image->data.F32[y][x] -= solution->data.F32[x]; 169 psTrace("pattern",5,"A: %d %d %g\n",x,y,solution->data.F32[x]); 128 170 } 129 171 psFree(solution); 130 172 } 131 173 174 #ifdef PATTERN_ROW_BKG_FIX 175 // Put the global trends back that were removed by the PATTERN.ROW correction. 176 // Set up the indices for the polynomial 177 psVector *yaxisIndices = psVectorAlloc(numRows, PS_TYPE_F32); 178 norm = 2.0 / (float)numRows; 179 for (int y = 0; y < numRows; y++) { 180 yaxisIndices->data.F32[y] = y * norm - 1.0; 181 psTrace("psModules.detrend.pattern",10,"%d %f %f\n",y,yaxisIndices->data.F32[y],yaxisData->data.F32[y]); 182 } 183 184 // Fit the trend of the constant term, producing the y-axis global trend 185 psStatsInit(clip); 186 psPolynomial1D *yaxisPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1); // Polynomial to fit. 187 if (!psVectorClipFitPolynomial1D(yaxisPoly,clip,yaxisMask,0xFF,yaxisData, NULL, yaxisIndices)) { 188 psWarning("Unable to fit polynomial to y-axis trend"); 189 psErrorClear(); 190 // If we've failed, we need to do something, so add back in the background level, and 191 // expect that the final image will have background mismatches. 192 for (int y = 0; y < numRows; y++) { 193 for (int x = 0; x < numCols; x++) { 194 image->data.F32[y][x] += background; 195 corr->data.F64[y][0] -= background; 196 } 197 } 198 } 199 else { 200 psVector *solution = psPolynomial1DEvalVector(yaxisPoly,yaxisIndices); 201 if (!solution) { 202 psWarning("Unable to evaluate polynomial"); 203 psErrorClear(); 204 // If we've failed, we need to do something, so add back in the background level, and 205 // expect that the final image will have background mismatches. 206 for (int y = 0; y < numRows; y++) { 207 for (int x = 0; x < numCols; x++) { 208 image->data.F32[y][x] += background; 209 corr->data.F64[y][0] -= background; 210 } 211 } 212 } 213 else { 214 for (int y = 0; y < numRows; y++) { 215 for (int x = 0; x < numCols; x++) { 216 image->data.F32[y][x] += solution->data.F32[y]; 217 corr->data.F64[y][0] -= solution->data.F32[y]; 218 psTrace("pattern",5,"B: %d %d %g\n",x,y,solution->data.F32[x]); 219 } 220 } 221 } 222 psFree(solution); 223 } 224 225 // Fit the trend of the linear term, producing the x-axis global trend 226 // We can use the same mask vector, as the same rows failed the row-fit earlier. 227 psStatsInit(clip); 228 psPolynomial1D *xaxisPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1); // Polynomial to fit. 229 if (!psVectorClipFitPolynomial1D(xaxisPoly,clip,yaxisMask,0xFF,xaxisData, NULL, yaxisIndices)) { 230 psWarning("Unable to fit polynomial to x-axis trend"); 231 psErrorClear(); 232 } 233 else { 234 psVector *solution = psPolynomial1DEvalVector(xaxisPoly,yaxisIndices); 235 if (!solution) { 236 psWarning("Unable to evaluate polynomial"); 237 psErrorClear(); 238 } 239 else { 240 for (int y = 0; y < numRows; y++) { 241 for (int x = 0; x < numCols; x++) { 242 image->data.F32[y][x] += solution->data.F32[y] * indices->data.F32[x]; 243 corr->data.F64[y][1] -= solution->data.F32[y] ; 244 psTrace("pattern",5,"C: %d %d %g %g\n",x,y,solution->data.F32[x],indices->data.F32[x]); 245 } 246 } 247 } 248 psFree(solution); 249 } 250 psFree(yaxisPoly); 251 psFree(xaxisPoly); 252 psFree(yaxisIndices); 253 psFree(yaxisMask); 254 psFree(yaxisData); 255 psFree(xaxisData); 256 // End PATTERN_ROW_BKG_FIX global trend replacement 257 #endif 258 132 259 psMetadataAddImage(ro->analysis, PS_LIST_TAIL, PM_PATTERN_ROW_CORRECTION, PS_META_REPLACE, 133 260 "Pattern row correction", corr); … … 382 509 383 510 511 512 bool pmPatternContinuity(pmChip *chip, const psVector *tweak, psStatsOptions bgStat, psStatsOptions cellStat, 513 psImageMaskType maskVal, psImageMaskType maskBad, int edgeWidth) 514 { 515 PS_ASSERT_PTR_NON_NULL(chip, false); 516 PS_ASSERT_VECTOR_NON_NULL(tweak, false); 517 PS_ASSERT_VECTOR_SIZE(tweak, chip->cells->n, false); 518 PS_ASSERT_VECTOR_TYPE(tweak, PS_TYPE_U8, false); 519 520 int numCells = tweak->n; // Number of cells 521 522 psVector *meanMask = psVectorAlloc(numCells, PS_TYPE_VECTOR_MASK); // Mask for means 523 psVectorInit(meanMask, 0); 524 525 // Mask bits 526 enum { 527 PM_PATTERN_IGNORE = 0x01, // Ignore this cell 528 PM_PATTERN_TWEAK = 0x02, // Tweak this cell 529 PM_PATTERN_ERROR = 0x04, // Error in calculating background 530 PM_PATTERN_ALL = 0xFF, // All causes 531 }; 532 533 // Count number of cells to tweak 534 int numTweak = 0; // Number of cells to tweak 535 int numIgnore = 0; // Number of cells to ignore 536 for (int i = 0; i < numCells; i++) { 537 pmCell *cell = chip->cells->data[i]; // Cell of interest 538 if (!cell || !cell->data_exists || !cell->process || 539 cell->readouts->n == 0 || cell->readouts->n > 1 || !cell->readouts->data[0]) { 540 numIgnore++; 541 meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = PM_PATTERN_IGNORE; 542 continue; 543 } 544 if (tweak->data.U8[i]) { 545 meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = PM_PATTERN_TWEAK; 546 numTweak++; 547 } 548 } 549 if (numTweak == 0) { 550 // Nothing to do 551 psFree(meanMask); 552 return true; 553 } 554 555 // Measure mean of each cell edge, and use that to determine the cell offsets. 556 557 psStats *bgStats = psStatsAlloc(bgStat); // Statistics on background 558 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator 559 560 psRegion region = {0,0,0,0}; 561 562 /* These images hold the edge data for the OTA structure. */ 563 psImage *A = psImageAlloc(8,8,PS_TYPE_F64); // Top edge 564 psImage *B = psImageAlloc(8,8,PS_TYPE_F64); // Bottom edge 565 psImage *C = psImageAlloc(8,8,PS_TYPE_F64); // Right edge 566 psImage *D = psImageAlloc(8,8,PS_TYPE_F64); // Left edge 567 psImageInit(A,0.0); 568 psImageInit(B,0.0); 569 psImageInit(C,0.0); 570 psImageInit(D,0.0); 571 572 for (int i = 0; i < numCells; i++) { 573 if (meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PM_PATTERN_IGNORE) { 574 continue; 575 } 576 pmCell *cell = chip->cells->data[i]; // Cell of interest 577 pmReadout *ro = cell->readouts->data[0]; // Readout of interest 578 579 psStatsInit(bgStats); 580 581 // Convert cell iterator i into an xy coordinate on the grid of cells 582 int y = (i % 8); 583 int x = (i - y) / 8; 584 585 for (int j = 0; j < 4; j++) { 586 if (j == 0) { // Region B 587 region = psRegionSet(0,ro->image->numCols, 588 0,edgeWidth); 589 } 590 else if (j == 1) { // Region A 591 region = psRegionSet(0,ro->image->numCols, 592 ro->image->numRows - edgeWidth,ro->image->numRows); 593 } 594 else if (j == 2) { // Region D 595 region = psRegionSet(0,edgeWidth, 596 0,ro->image->numRows); 597 } 598 else if (j == 3) { // Region C 599 region = psRegionSet(ro->image->numCols - edgeWidth,ro->image->numCols, 600 0,ro->image->numRows); 601 } 602 psImage *subset = psImageSubset(ro->image,region); 603 psImage *submask = psImageSubset(ro->mask,region); 604 605 if (!psImageBackground(bgStats, NULL, subset, submask, maskVal, rng)) { 606 psWarning("Unable to measure background for cell %d on edge %d\n", i, j); 607 psErrorClear(); 608 meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] |= PM_PATTERN_ERROR; 609 if (j == 0) { B->data.F64[y][x] = NAN; } 610 else if (j == 1) { A->data.F64[y][x] = NAN; } 611 else if (j == 2) { C->data.F64[y][x] = NAN; } 612 else if (j == 3) { D->data.F64[y][x] = NAN; } 613 psFree(subset); 614 psFree(submask); 615 continue; // Move on to next edge, as only part of this cell may be a problem 616 } 617 618 // If the returned value is zero, assume something is wrong. Do I still need this? 619 if (psStatsGetValue(bgStats,bgStat) < 1e-6) { 620 if (j == 0) { B->data.F64[y][x] = NAN; } 621 else if (j == 1) { A->data.F64[y][x] = NAN; } 622 else if (j == 2) { C->data.F64[y][x] = NAN; } 623 else if (j == 3) { D->data.F64[y][x] = NAN; } 624 } 625 // If we have an error for this cell/edge, make sure we mask the value 626 if (meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PM_PATTERN_ERROR) { 627 if (j == 0) { B->data.F64[y][x] = NAN; } 628 else if (j == 1) { A->data.F64[y][x] = NAN; } 629 else if (j == 2) { C->data.F64[y][x] = NAN; } 630 else if (j == 3) { D->data.F64[y][x] = NAN; } 631 } 632 else { // Set the value to match what we got from the edge box. 633 if (j == 0) { B->data.F64[y][x] = psStatsGetValue(bgStats,bgStat); } 634 else if (j == 1) { A->data.F64[y][x] = psStatsGetValue(bgStats,bgStat); } 635 else if (j == 2) { C->data.F64[y][x] = psStatsGetValue(bgStats,bgStat); } 636 else if (j == 3) { D->data.F64[y][x] = psStatsGetValue(bgStats,bgStat); } 637 } 638 639 for (int u = 0; u < subset->numCols; u++) { 640 for (int v = 0; v < subset->numRows; v++) { 641 psTrace("psModules.detrend.cont",10,"BOX: %d %d (%d %d) (%d %d) %f %d", 642 i,j,x,y,u,v,subset->data.F32[v][u],submask->data.PS_TYPE_IMAGE_MASK_DATA[v][u]); 643 } 644 } 645 646 psFree(subset); 647 psFree(submask); 648 649 } 650 psTrace("psModules.detrend.cont",5, "OTA: %d (%d %d) A: %f B: %f C: %f D: %f", 651 i,x,y, 652 A->data.F64[y][x],B->data.F64[y][x],C->data.F64[y][x],D->data.F64[y][x]); 653 } 654 psFree(bgStats); 655 psFree(rng); 656 657 // We've now allocated all the edge values, so we can now minimize the offsets. 658 // This involves solving the equation A x = b, where 659 // A is the (64x64 for GPC1) matrix containing the edges that match for each cell 660 // x is the solution vector 661 // b is the combination of offsets across each cell boundary for each cell. 662 // Below "XX" is used as the matrix A, and "solution" is used as both b and x 663 // (due to the way psMatrixLUSolve operates). 664 psVector *solution = psVectorAlloc(64,PS_TYPE_F64); 665 psImage *XX = psImageAlloc(64,64,PS_TYPE_F64); 666 psVectorInit(solution,0.0); 667 psImageInit(XX,0.0); 668 669 for (int i = 0; i < numCells; i++) { 670 // Accumulate all the possible edge differences we can for this cell. 671 // As we do so, make a note of the correlations by incrementing the element of the matrix. 672 int y = (i % 8); 673 int x = (i - y) / 8; 674 int j; 675 double critical_value = 0.0; 676 if (meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PM_PATTERN_IGNORE) { 677 continue; 678 } 679 if (x + 1 < 8) { // We have a neighbor adjacent in the +x direction 680 j = 8 * (x + 1) + y; // Determine that neighbor's index 681 if (fabs(C->data.F64[y][x]) > fabs(D->data.F64[y][x+1])) { 682 critical_value = 2.0 * fabs(D->data.F64[y][x+1]); 683 } 684 else { 685 critical_value = 2.0 * fabs(C->data.F64[y][x]); 686 } 687 if (critical_value < 25) { critical_value = 25; } 688 psTrace("psModules.detrend.cont",5,"CmD %d %d %d %d %g %g %g", // diagnostic 689 i,x,y,j, 690 C->data.F64[y][x], 691 D->data.F64[y][x+1], 692 critical_value 693 ); 694 if (!(meanMask->data.PS_TYPE_VECTOR_MASK_DATA[j] & PM_PATTERN_IGNORE)&& // If there are no errors with the neighbor, 695 (isfinite(C->data.F64[y][x]))&&(isfinite(D->data.F64[y][x+1]))&& // and all edges have valid values, 696 (fabs(C->data.F64[y][x] - D->data.F64[y][x+1]) < critical_value) // and there are no large discontinuities, 697 ) { 698 solution->data.F64[i] += C->data.F64[y][x] - D->data.F64[y][x+1]; // Take the difference 699 XX->data.F64[i][i] += 1; // increment our relation with ourself 700 XX->data.F64[i][j] += -1; // decrement our relation with the neighbor 701 } 702 } 703 if (x - 1 > -1) { // etc. 704 j = 8 * (x - 1) + y; 705 if (fabs(C->data.F64[y][x-1]) > fabs(D->data.F64[y][x])) { 706 critical_value = 2.0 * fabs(D->data.F64[y][x]); 707 } 708 else { 709 critical_value = 2.0 * fabs(C->data.F64[y][x-1]); 710 } 711 if (critical_value < 25) { critical_value = 25; } 712 psTrace("psModules.detrend.cont",5,"DmC %d %d %d %d %g %g %g", 713 i,x,y,j, 714 D->data.F64[y][x], 715 C->data.F64[y][x-1], 716 critical_value 717 ); 718 719 if (!(meanMask->data.PS_TYPE_VECTOR_MASK_DATA[j] & PM_PATTERN_IGNORE)&& 720 (isfinite(D->data.F64[y][x]))&&(isfinite(C->data.F64[y][x-1]))&& 721 (fabs(D->data.F64[y][x] - C->data.F64[y][x-1]) < critical_value) 722 ) { 723 solution->data.F64[i] += D->data.F64[y][x] - C->data.F64[y][x-1]; 724 XX->data.F64[i][i] += 1; 725 XX->data.F64[i][j] += -1; 726 } 727 } 728 if (y + 1 < 8) { 729 j = 8 * x + (y + 1); 730 psTrace("psModules.detrend.cont",5,"AmB %d %d %d %d %g %g", 731 i,x,y,j, 732 A->data.F64[y][x], 733 B->data.F64[y+1][x] 734 ); 735 if (fabs(A->data.F64[y][x]) > fabs(B->data.F64[y+1][x])) { 736 critical_value = 2.0 * fabs(B->data.F64[y+1][x]); 737 } 738 else { 739 critical_value = 2.0 * fabs(A->data.F64[y][x]); 740 } 741 if (critical_value < 25) { critical_value = 25; } 742 if (!(meanMask->data.PS_TYPE_VECTOR_MASK_DATA[j] & PM_PATTERN_IGNORE)&& 743 (isfinite(A->data.F64[y][x]))&&(isfinite(B->data.F64[y+1][x]))&& 744 (fabs(A->data.F64[y][x] - B->data.F64[y+1][x]) < critical_value) 745 ) { 746 solution->data.F64[i] += A->data.F64[y][x] - B->data.F64[y+1][x]; 747 XX->data.F64[i][i] += 1; 748 XX->data.F64[i][j] += -1; 749 } 750 } 751 if (y - 1 > -1) { 752 j = 8 * x + (y - 1); 753 psTrace("psModules.detrend.cont",5,"BmA %d %d %d %d %g %g", 754 i,x,y,j, 755 B->data.F64[y][x], 756 A->data.F64[y-1][x] 757 ); 758 if (fabs(A->data.F64[y-1][x]) > fabs(B->data.F64[y][x])) { 759 critical_value = 2.0 * fabs(B->data.F64[y][x]); 760 } 761 else { 762 critical_value = 2.0 * fabs(A->data.F64[y-1][x]); 763 } 764 if (critical_value < 25) { critical_value = 25; } 765 if (!(meanMask->data.PS_TYPE_VECTOR_MASK_DATA[j] & PM_PATTERN_IGNORE)&& 766 (isfinite(B->data.F64[y][x]))&&(isfinite(A->data.F64[y-1][x]))&& 767 (fabs(B->data.F64[y][x] - A->data.F64[y-1][x]) < critical_value) 768 ) { 769 solution->data.F64[i] += B->data.F64[y][x] - A->data.F64[y-1][x]; 770 XX->data.F64[i][i] += 1; 771 XX->data.F64[i][j] += -1; 772 } 773 } 774 } 775 double max_XX = 0; 776 double solution_V = 0; 777 int i_peak = -1; 778 for (int i = 0; i < numCells; i++) { // If any cells have no value of themself, set the matrix to 1.0. 779 if (XX->data.F64[i][i] == 0.0) { 780 XX->data.F64[i][i] = 1.0; 781 } 782 if (XX->data.F64[i][i] > max_XX) { 783 max_XX = XX->data.F64[i][i]; 784 solution_V = solution->data.F64[i]; 785 i_peak = i; 786 } 787 } 788 psTrace("psModules.detrend.cont",5,"fixed point: %d %g\n", 789 i_peak,solution_V); 790 791 for (int i = 0; i < numCells; i++) { 792 /* if (!((XX->data.F64[i][i] == 1.0)&& */ 793 /* (solution->data.F64[i] == 0.0))) { */ 794 solution->data.F64[i] -= solution_V; 795 if (i != i_peak) { 796 for (int j = 0; j < numCells; j++) { 797 XX->data.F64[i][j] -= XX->data.F64[i_peak][j]; 798 } 799 } 800 /* } */ 801 } 802 for (int i = 0; i < numCells; i++) { 803 XX->data.F64[i_peak][i] = 0.0; 804 } 805 XX->data.F64[i_peak][i_peak] = 1.0; 806 807 808 #if (1) 809 for (int i = 0; i < numCells; i++) { // print matrix A 810 psTrace("psModules.detrend.cont",5,"A: %3d % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f", 811 i, 812 XX->data.F64[i][0], XX->data.F64[i][1], XX->data.F64[i][2], XX->data.F64[i][3], 813 XX->data.F64[i][4], XX->data.F64[i][5], XX->data.F64[i][6], XX->data.F64[i][7], 814 XX->data.F64[i][8], XX->data.F64[i][9], XX->data.F64[i][10], XX->data.F64[i][11], 815 XX->data.F64[i][12], XX->data.F64[i][13], XX->data.F64[i][14], XX->data.F64[i][15], 816 XX->data.F64[i][16], XX->data.F64[i][17], XX->data.F64[i][18], XX->data.F64[i][19], 817 XX->data.F64[i][20], XX->data.F64[i][21], XX->data.F64[i][22], XX->data.F64[i][23], 818 XX->data.F64[i][24], XX->data.F64[i][25], XX->data.F64[i][26], XX->data.F64[i][27], 819 XX->data.F64[i][28], XX->data.F64[i][29], XX->data.F64[i][30], XX->data.F64[i][31], 820 XX->data.F64[i][32], XX->data.F64[i][33], XX->data.F64[i][34], XX->data.F64[i][35], 821 XX->data.F64[i][36], XX->data.F64[i][37], XX->data.F64[i][38], XX->data.F64[i][39], 822 XX->data.F64[i][40], XX->data.F64[i][41], XX->data.F64[i][42], XX->data.F64[i][43], 823 XX->data.F64[i][44], XX->data.F64[i][45], XX->data.F64[i][46], XX->data.F64[i][47], 824 XX->data.F64[i][48], XX->data.F64[i][49], XX->data.F64[i][50], XX->data.F64[i][51], 825 XX->data.F64[i][52], XX->data.F64[i][53], XX->data.F64[i][54], XX->data.F64[i][55], 826 XX->data.F64[i][56], XX->data.F64[i][57], XX->data.F64[i][58], XX->data.F64[i][59], 827 XX->data.F64[i][60], XX->data.F64[i][61], XX->data.F64[i][62], XX->data.F64[i][63] 828 ); 829 } 830 831 for (int i = 0; i < numCells; i++) { // print vector b 832 psTrace("psModules.detrend.cont",5,"b: %d %f", 833 i, 834 solution->data.F64[i] 835 ); 836 } 837 #endif 838 839 // Solve the Ax=b equation 840 // psMatrixLUSolve(XX,solution); 841 psMatrixGJSolve(XX,solution); 842 #if (1) 843 for (int i = 0; i < numCells; i++) { // print vector b 844 psTrace("psModules.detrend.cont",5,"x: %d %f", 845 i, 846 solution->data.F64[i] 847 ); 848 } 849 #endif 850 851 /* old code to remove the minimum solution value from the set, to give a "minimal set of offsets." Mathematically unnecessary. */ 852 /* double min = 99e99; */ 853 /* for (int i = 0; i < numCells; i++) { */ 854 /* if (solution->data.F64[i] < min) { */ 855 /* min = solution->data.F64[i]; */ 856 /* } */ 857 /* psTrace("psModules.detrend.cont",5,"x: %d %f %f ", */ 858 /* i, */ 859 /* solution->data.F64[i],min */ 860 /* ); */ 861 /* } */ 862 /* for (int i = 0; i < numCells; i++) { */ 863 /* if (solution->data.F64[i] != 0.0) { */ 864 /* solution->data.F64[i] -= min; */ 865 /* } */ 866 /* } */ 867 868 // Cleanup 869 psFree(XX); 870 psFree(A); 871 psFree(B); 872 psFree(C); 873 psFree(D); 874 875 // Correct cells based on the offsets calculated, and store the result in the analysis metadata. 876 for (int i = 0; i < numCells; i++) { 877 if (meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PM_PATTERN_IGNORE) { 878 continue; 879 } 880 if (!(meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PM_PATTERN_TWEAK)) { 881 continue; 882 } 883 pmCell *cell = chip->cells->data[i]; // Cell of interest 884 pmReadout *ro = cell->readouts->data[0]; // Readout of interest 885 886 float correction = solution->data.F64[i]; 887 const char *cellName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME"); // Name of cell 888 psLogMsg("psModules.detrend", PS_LOG_DETAIL, "Correcting background of cell %s by %f", 889 cellName, correction); 890 psBinaryOp(ro->image, ro->image, "-", psScalarAlloc(correction, PS_TYPE_F32)); 891 psMetadataAddF32(ro->analysis, PS_LIST_TAIL, PM_PATTERN_CELL_CORRECTION, PS_META_REPLACE, 892 "Pattern cell correction solution", correction); 893 } 894 895 psFree(solution); 896 psFree(meanMask); 897 898 return true; 899 } 900 901 bool pmPatternContinuityApply(pmReadout *ro, psImageMaskType maskBad) 902 { 903 PM_ASSERT_READOUT_NON_NULL(ro, false); 904 PM_ASSERT_READOUT_IMAGE(ro, false); 905 906 bool mdok; // Status of MD lookup 907 float corr = psMetadataLookupF32(&mdok, ro->analysis, PM_PATTERN_CELL_CORRECTION); // Correction to apply 908 if (!mdok) { 909 // No correction to apply 910 return true; 911 } 912 913 psImage *image = ro->image, *mask = ro->mask; // Image and mask of interest 914 int numCols = image->numCols, numRows = image->numRows; // Size of image 915 916 if (!isfinite(corr)) { 917 for (int y = 0; y < numRows; y++) { 918 for (int x = 0; x < numCols; x++) { 919 image->data.F32[y][x] = NAN; 920 } 921 } 922 if (mask) { 923 for (int y = 0; y < numRows; y++) { 924 for (int x = 0; x < numCols; x++) { 925 mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= maskBad; 926 } 927 } 928 } 929 } else { 930 for (int y = 0; y < numRows; y++) { 931 for (int x = 0; x < numCols; x++) { 932 image->data.F32[y][x] += corr; 933 } 934 } 935 } 936 937 return true; 938 } 939 940
Note:
See TracChangeset
for help on using the changeset viewer.
