IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Feb 4, 2023, 12:15:28 PM (3 years ago)
Author:
eugene
Message:

merge changes from trunk: new nonlinearity, allow detections under CTE masks

Location:
branches/eam_branches/ipp-20220316/ppImage
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20220316/ppImage

  • branches/eam_branches/ipp-20220316/ppImage/src/ppImageSetMaskBits.c

    r42148 r42372  
    55#include "ppImage.h"
    66
     7// Structure to hold the properties of a mask value
     8typedef struct {
     9    char *badMaskName;                  // name for "bad" (i.e., mask me please) pixels
     10    char *fallbackName;                 // Fallback name in case a bad mask name is not defined
     11    psImageMaskType defaultMaskValue;   // Default value in case a bad mask name and its fallback are not defined
     12    bool isBad; // include this value as part of the MASK.VALUE entry (generically bad)
     13} pmConfigMaskInfo;
     14
     15static pmConfigMaskInfo ppimagemasks[] = {
     16    // Features of the detector
     17    { "DETECTOR",  NULL,       0x01, true }, // Something is wrong with the detector
     18    { "FLAT",      "DETECTOR", 0x01, true }, // Pixel doesn't flat-field properly
     19    { "DARK",      "DETECTOR", 0x01, true }, // Pixel doesn't dark-subtract properly
     20    { "BLANK",     "DETECTOR", 0x01, true }, // Pixel doesn't contain valid data
     21    { "CTE",       "DETECTOR", 0x01, false }, // Pixel has poor CTE
     22    { "BURNTOOL",  NULL,       0x04, false }, // Pixel has been touched by burntool
     23    // Invalid signal ranges
     24    { "SAT",       NULL,       0x02, true  }, // Pixel is saturated or non-linear
     25    { "LOW",       "SAT",      0x02, true  }, // Pixel is low
     26    { "SUSPECT",   NULL,       0x04, false }, // Pixel is suspected of being bad
     27    // Non-astronomical structures
     28    { "CR",        NULL,       0x08, true  }, // Pixel contains a cosmic ray
     29    { "SPIKE",     NULL,       0x08, false  }, // Pixel contains a diffraction spike
     30    { "GHOST",     NULL,       0x08, false  }, // Pixel contains an optical ghost
     31    { "STREAK",    NULL,       0x08, false  }, // Pixel contains a streak
     32    { "CROSSTALK", NULL,       0x08, false  }, // Pixel contains crosstalk data
     33    { "STARCORE",  NULL,       0x08, false  }, // Pixel contains a bright star core
     34    // Effects of convolution and interpolation
     35    { "CONV.BAD",  NULL,       0x02, true  }, // Pixel is bad after convolution with a bad pixel
     36    { "CONV.POOR", NULL,       0x04, false }, // Pixel is poor after convolution with a bad pixel
     37};
     38
    739bool ppImageSetMaskBits (pmConfig *config, ppImageOptions *options) {
    840
    9     if (!pmConfigMaskSetBits(&options->maskValue, &options->markValue, config)) {
    10         psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
    11         return false;
     41
     42    // Look up recipe values
     43    psMetadata *pprecipe = psMetadataLookupMetadata(NULL, config->recipes, RECIPE_NAME);
     44
     45    psAssert(pprecipe, "We checked this earlier, so it should be here.");
     46    bool doDetectCTE = psMetadataLookupBool(NULL, pprecipe, "DETECT.CTE"); // Do detections on pixels underneath CTE masks
     47
     48    // this function sets the required single-image mask bits
     49    if(!doDetectCTE) {
     50      if (!pmConfigMaskSetBits (&options->maskValue, &options->markValue, config)) {
     51          psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
     52          return false;
     53      }
     54    } else {
     55      psMetadata *maskrecipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
     56      if (!maskrecipe) {
     57          psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
     58          return false;
     59      }
     60      if (!ppImageMaskSetInMetadata(&options->maskValue, &options->markValue, maskrecipe)) {
     61          psError (PS_ERR_UNKNOWN, true, "Unable to determine the mask value");
     62          return false;
     63      }
    1264    }
    1365
     
    66118    return true;
    67119}
     120
     121
     122bool ppImageMaskSetInMetadata(psImageMaskType *outMaskValue, // Value of MASK.VALUE, returned
     123                               psImageMaskType *outMarkValue, // Value of MARK.VALUE, returned
     124                               psMetadata *source  // Source of mask bits
     125    )
     126{
     127    PS_ASSERT_METADATA_NON_NULL(source, false);
     128
     129    // Ensure all the bad mask names exist, and set the value to catch all bad pixels
     130    psImageMaskType maskValue = 0;           // Value to mask to catch all the bad pixels
     131    psImageMaskType allMasks = 0;            // Value to mask to catch all masked bits (to set MARK)
     132
     133    int nMasks = sizeof (ppimagemasks) / sizeof (pmConfigMaskInfo);
     134
     135    for (int i = 0; i < nMasks; i++) {
     136        bool mdok;                      // Status of MD lookup
     137        psImageMaskType value = psMetadataLookupImageMaskFromGeneric(&mdok, source, ppimagemasks[i].badMaskName); // Value of mask
     138        if (!mdok) {
     139            psWarning ("problem with mask value %s\n", ppimagemasks[i].badMaskName);
     140        }
     141
     142        if (!value) {
     143            if (ppimagemasks[i].fallbackName) {
     144                value = psMetadataLookupImageMaskFromGeneric(&mdok, source, ppimagemasks[i].fallbackName);
     145            }
     146            if (!value) {
     147                value = ppimagemasks[i].defaultMaskValue;
     148            }
     149            psMetadataAddImageMask(source, PS_LIST_TAIL, ppimagemasks[i].badMaskName, PS_META_REPLACE, NULL, value);
     150        }
     151        if (ppimagemasks[i].isBad) {
     152            maskValue |= value;
     153        }
     154        allMasks |= value;
     155    }
     156
     157    // search for an unset bit to use for MARK:
     158    psImageMaskType markValue = 0x00;
     159    psImageMaskType markTrial = 0x01;
     160
     161    int nBits = sizeof(psImageMaskType) * 8;
     162    for (int i = 0; !markValue && (i < nBits); i++) {
     163        if (allMasks & markTrial) {
     164            markTrial <<= 1;
     165        } else {
     166            markValue = markTrial;
     167        }
     168    }
     169    if (!markValue) {
     170        psError (PS_ERR_UNKNOWN, true, "Unable to define the MARK bit mask: all bits taken!");
     171        return false;
     172    }
     173
     174    // update the list with the results
     175    psMetadataAddImageMask(source, PS_LIST_TAIL, "MASK.VALUE", PS_META_REPLACE, NULL, maskValue);
     176    psMetadataAddImageMask(source, PS_LIST_TAIL, "MARK.VALUE", PS_META_REPLACE, NULL, markValue);
     177
     178    if (outMaskValue) {
     179        *outMaskValue = maskValue;
     180    }
     181    if (outMarkValue) {
     182        *outMarkValue = markValue;
     183    }
     184
     185    return true;
     186}
     187
Note: See TracChangeset for help on using the changeset viewer.