- Timestamp:
- Oct 29, 2021, 5:17:26 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/psModules.20211028/src/imcombine/pmStack.c
r41852 r41872 1514 1514 1515 1515 # define MIN_GOOD_PERCENTILE 2 1516 # define SUSPECT_FRACTION 0.65 1517 1518 // Comparison and swap functions for sorting values directly 1519 #define SORT_VV_COMPARE(A,B) (pixelData->data.F32[A] < pixelData->data.F32[B]) 1520 #define SORT_VV_SWAP(TYPE,A,B) { \ 1521 if (A != B) { \ 1522 psF32 tempVal = pixelData->data.F32[A]; \ 1523 pixelData->data.F32[A] = pixelData->data.F32[B]; \ 1524 pixelData->data.F32[B] = tempVal; \ 1525 psF32 tempVar = pixelVariances->data.F32[A]; \ 1526 pixelVariances->data.F32[A] = pixelVariances->data.F32[B]; \ 1527 pixelVariances->data.F32[B] = tempVar; \ 1528 } \ 1529 } 1530 1531 #define SORT_VALUE_AND_VAR(A,B) { PSSORT(A->n, SORT_VV_COMPARE, SORT_VV_SWAP, F32); } 1532 1533 1516 1534 bool pmStackCombineByPercentile( 1517 1535 pmReadout *combined, 1518 1536 psArray *stackData, 1519 psF64 minRange,1537 psF64 rejectFraction, 1520 1538 psF64 maxRange, 1521 1539 psImageMaskType badMaskBits, // treat these bits as 'bad' … … 1541 1559 psFree(stackReadouts); 1542 1560 1543 psVector *pixelData = psVectorAlloc(stackData->n, PS_TYPE_F32); 1544 psVector *pixelMask = psVectorAlloc(stackData->n, PS_TYPE_VECTOR_MASK); 1561 // make sure the output readout matches the inputs, and set to blank by default 1562 pmReadoutUpdateSize(combined, minInputCols, minInputRows, xSize, ySize, true, true, blankMaskBits); 1563 1564 psVector *pixelData = psVectorAlloc(stackData->n, PS_TYPE_F32); 1565 psVector *pixelVariances = psVectorAlloc(stackData->n, PS_TYPE_F32); 1566 psVector *pixelMask = psVectorAlloc(stackData->n, PS_TYPE_VECTOR_MASK); 1567 1568 int nGoodBits[16]; // accumulate the good pixel bits here for fuzzy logic 1569 psAssert (sizeof(psImageMaskType) == 2, "psImageMaskType is not the expected size"); 1570 memset (nGoodBits, 0, 16*sizeof(int)); 1545 1571 1546 1572 for (int y = minInputRows; y < maxInputRows; y++) { … … 1552 1578 pmStackData *data = stackData->data[i]; // Stack data for this input 1553 1579 pmReadout *ro = data->readout; // Readout of interest 1554 psImage *image = ro->image; 1555 psImage *mask = ro->mask; 1580 1581 psImage *image = ro->image; 1582 psImage *variance = ro->variance; 1583 psImage *mask = ro->mask; 1556 1584 1557 1585 int xIn = x - data->readout->col0; 1558 1586 int yIn = y - data->readout->row0; // Coordinates on input readout 1559 1587 1588 // skip obviously bad input data 1560 1589 if (!isfinite(image->data.F32[yIn][xIn])) continue; 1561 if (fabs(image->data.F32[yIn][xIn]) > 1e5) continue; 1562 // XXX need to test the input mask as well here 1563 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & badMaskBits); 1564 1565 // XXX save the count of suspect bits 1566 1567 # if (0) 1590 if (fabs(image->data.F32[yIn][xIn]) > 1e5) continue; // XXX this cut is a bit arbitrary.. 1591 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & badMaskBits) continue; 1592 1568 1593 // count the number of times a given mask bit is set in the input pixels. 1569 1594 // NOTE: since we have explicitly skipped the pixels with any bad bits, these are only 1570 1595 // the suspect bits (nGoodBits is a bit of a misnomer: it is more like 'nSuspectBitsForGoodInputs' 1571 if (1) { 1572 psImageMaskType value = 0x0001; 1573 for (int nbit = 0; nbit < 16; nbit ++) { 1574 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & value) { 1575 // XXX nGoodBits[nbit] ++; 1576 } 1577 value <<= 1; 1596 psImageMaskType value = 0x0001; 1597 for (int nbit = 0; nbit < 16; nbit ++) { 1598 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & value) { 1599 nGoodBits[nbit] ++; 1578 1600 } 1601 value <<= 1; 1579 1602 } 1580 # endif 1603 1604 // pixelWeights->data.F32[nGood] = data->weight; 1605 // pixelExps->data.F32[nGood] = data->exp; 1606 // pixelSources->data.U16[nGood] = i; 1581 1607 1582 1608 pixelData->data.F32[nGood] = image->data.F32[yIn][xIn]; 1609 if (variance) { 1610 // pixelVariances->data.F32[numGood] = variance->data.F32[yIn][xIn] * addVariance->data.F32[i]; 1611 pixelVariances->data.F32[nGood] = variance->data.F32[yIn][xIn]; 1612 } 1613 1583 1614 nGood ++; 1584 1615 } 1585 1616 pixelData->n = nGood; 1586 psVectorSortInPlace (pixelData); 1587 1588 if (nGood < MIN_GOOD_PERCENTILE) { 1617 1618 1619 // rather than define a min and max value, 1620 // what we really want is a symmetric selection about the middle, 1621 // or the output is biased. If N % 2 = 1, then 1622 1623 // we are going to exclude rejectFraction*nGood measurements. But the 1624 // rejection needs to be symmetric 1625 1626 # define AT_LEAST 0 1627 # if (AT_LEAST) 1628 int Ns = MIN(MAX(1, 0.5*rejectFraction * nGood), nGood); 1629 int Ne = nGood - Ns; 1630 int Npt = Ne - Ns; 1631 # else 1632 int Ns = MIN(MAX(0, 0.5*rejectFraction * nGood), nGood); 1633 int Ne = nGood - Ns; 1634 int Npt = Ne - Ns; 1635 # endif 1636 if ((Npt < 1) || (nGood < MIN_GOOD_PERCENTILE)) { 1589 1637 combined->image->data.F32[y][x] = NAN; 1590 1638 combined->variance->data.F32[y][x] = NAN; 1591 combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 1;1639 combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = blankMaskBits; // probably not needed since it was set above. 1592 1640 continue; 1593 1641 } 1594 1642 1595 # if (0) 1596 # define SUSPECT_FRACTION 0.65 1597 // set the mask bits if nGoodBits[i] > f*numGood 1598 if (0) { 1599 psImageMaskType value = 0x0001; 1600 for (int nbit = 0; nbit < 16; nbit ++) { 1601 if (nGoodBits[nbit] > SUSPECT_FRACTION*numGood) { 1602 *goodMask |= value; 1603 } 1604 value <<= 1; 1643 // sort both pixelData and pixelVariance 1644 SORT_VALUE_AND_VAR (pixelData, pixelVariances); 1645 1646 // set the given (suspect) mask bit if nGoodBits[i] > f*nGood 1647 // in other words if more than 65% of the good inputs had one of 1648 // these bits set, then we should set that bit in the output mask 1649 psImageMaskType value = 0x0001; 1650 psImageMaskType outputMask = 0x0000; 1651 for (int nbit = 0; nbit < 16; nbit ++) { 1652 if (nGoodBits[nbit] > SUSPECT_FRACTION*nGood) { 1653 outputMask |= value; 1605 1654 } 1655 value <<= 1; 1606 1656 } 1607 # endif1608 1609 int Ns = MIN(MAX(0, minRange * nGood),nGood); // e.g., 0.1 * 50 = 51610 int Ne = MIN(MAX(0, maxRange * nGood),nGood); // e.g., 0.9 * 50 = 451611 int Npt = Ne - Ns;1612 1657 1613 1658 float sum = 0.0; 1659 float varSum = 0.0; 1614 1660 for (int n = Ns; n < Ne; n++) { 1615 1661 sum += pixelData->data.F32[n]; 1662 varSum += pixelVariances->data.F32[n]; 1616 1663 } 1617 1664 float mean = sum / (float) Npt; 1618 1665 1619 float varSum = 0.0; 1620 for (int n = Ns; n < Ne; n++) { 1621 varSum += SQ(pixelData->data.F32[n] - mean); 1622 } 1666 // alternative: calculate the stdev of the pixel values 1667 // float varSum = 0.0; 1668 // for (int n = Ns; n < Ne; n++) { 1669 // varSum += SQ(pixelData->data.F32[n] - mean); 1670 // } 1623 1671 // variance on the mean (stdev / sqrt(N))^2 1624 float varValue = varSum / (Npt - 1) / Npt; 1625 1626 // XXX this is probably not the correct variance to save 1627 // the predicted variance should be the 1 / sum (1/var) 1672 float varValue = varSum / (Npt*Npt); 1628 1673 1629 1674 combined->image->data.F32[y][x] = mean; 1630 1675 combined->variance->data.F32[y][x] = varValue; 1631 combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0;1676 combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = outputMask; 1632 1677 } 1633 1678 }
Note:
See TracChangeset
for help on using the changeset viewer.
