IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Oct 28, 2008, 1:49:32 PM (18 years ago)
Author:
Paul Price
Message:

Implementing background subtraction in the place of replacing bad pixels with the background. Bad pixels are automatically identified and set to 0 in the process, so this is effectively the same thing as before, except it subtracts the background as well. The background (from psphot) is built if it doesn't exist.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ppImage/src/ppImageReplaceBackground.c

    r18556 r20444  
    33#endif
    44
    5 # include "ppImage.h"
    6 
    7 enum {MODE_NONE, MODE_MODEL, MODE_VALUE};
     5#include "ppImage.h"
    86
    97// In this function, we perform the psphot analysis routine for the chip-mosaicked images
    10 bool ppImageReplaceBackground (pmConfig *config, pmFPAview *view, ppImageOptions *options) {
     8bool ppImageSubtractBackground(pmConfig *config, const pmFPAview *view, const ppImageOptions *options)
     9{
     10    psAssert(config, "Need configuration");
     11    psAssert(view, "Need view to chip");
     12    psAssert(options, "Need options");
    1113
    12     bool status;
    13     pmCell *cell;
    14     pmReadout *readout;
     14    if (!options->doBG) {
     15        return true;
     16    }
    1517
    16     // find the reference source image
    17     pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PPIMAGE.CHIP");
     18    bool status;                        // Status of MD lookup
     19    pmFPAfile *input = psMetadataLookupPtr(&status, config->files, "PPIMAGE.CHIP"); // File to correct
    1820    if (!status) {
    19         psError(PSPHOT_ERR_CONFIG, false, "PSPHOT.INPUT I/O file is not defined");
     21        psError(PS_ERR_UNEXPECTED_NULL, true, "PPIMAGE.CHIP file is not defined");
    2022        return false;
    2123    }
    2224
    23     // select the appropriate recipe information
    24     psMetadata *ppImageRecipe  = psMetadataLookupPtr (&status, config->recipes, "PPIMAGE");
    25 
    26     // select the appropriate recipe information (needed by psphotModelBackground)
    27     psMetadata *psphotRecipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
    28 
    29     char *replaceSkyModeWord = psMetadataLookupStr (&status, ppImageRecipe, "REPLACE.MODE");
    30     float replaceSkyValue = 0.0;
    31 
    32     int replaceSkyMode = MODE_NONE;
    33     if (!strcasecmp (replaceSkyModeWord, "MODEL")) {
    34         replaceSkyMode = MODE_MODEL;
    35     }
    36     if (!strcasecmp (replaceSkyModeWord, "VALUE")) {
    37         replaceSkyMode = MODE_VALUE;
    38         replaceSkyValue = psMetadataLookupF32 (&status, ppImageRecipe, "REPLACE.VALUE");
    39     }
    40     psAssert (replaceSkyMode != MODE_NONE, "replace sky mode not defined");
    41 
    42     // XXX Should this be options->maskValue or & ~options->satMask? the latter will leave saturated pixels high
    43     // psMaskType maskVal  = options->maskValue & ~options->satMask;
    44     psMaskType maskVal  = options->maskValue;
    45 
    46     pmFPAfile *modelFile = NULL;
    47     if (replaceSkyMode == MODE_MODEL) {
    48         // find the model data, if it exists yet (if not, we build it below)
    49         modelFile = psMetadataLookupPtr(&status, config->files, "PSPHOT.BACKMDL");
    50 
    51         // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    52         psMetadataAddU8 (psphotRecipe, PS_LIST_TAIL, "MASK.PSPHOT", PS_META_REPLACE, "user-defined mask", maskVal);
     25    // The background model file may be defined, though the model hasn't been built
     26    // If so, we will build it below.
     27    pmFPAfile *modelFile = psMetadataLookupPtr(&status, config->files, "PSPHOT.BACKMDL"); // Background model
     28    if (!status) {
     29        psError(PS_ERR_UNEXPECTED_NULL, true, "PSPHOT.BACKMDL file is not defined");
     30        return false;
    5331    }
    5432
    55     // iterate over the cells and readout for this chip
    56     while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
    57         psLogMsg ("ppImagePhotom", 5, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
    58         if (! cell->process || ! cell->file_exists) { continue; }
     33    psMetadata *ppImageRecipe = psMetadataLookupPtr(NULL, config->recipes, RECIPE_NAME);
     34    psAssert(ppImageRecipe, "Need PPIMAGE recipe");
     35    psMetadata *psphotRecipe = psMetadataLookupPtr(NULL, config->recipes, PSPHOT_RECIPE);
     36    psAssert(psphotRecipe, "Need PSPHOT recipe");
    5937
    60         // process each of the readouts
    61         while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
    62             if (! readout->data_exists) { continue; }
    63             if (! readout->mask) { continue; }
     38    // XXX Should this be options->maskValue or options->maskValue & ~options->satMask?
     39    //     The latter will leave saturated pixels high
     40    psMaskType maskVal = options->maskValue;
    6441
    65             // replace masked pixels with values from model (unbinning not needed)
    66             pmReadout *modelReadout = NULL;
    67             psImageBinning *binning = NULL;
    68             psImage *model = NULL;
    69             if (replaceSkyMode == MODE_MODEL) {
    70                 // we are using this pmFPAfile as an I/O file: select readout or create
    71                 if (modelFile) {
    72                     modelReadout = pmFPAviewThisReadout (view, modelFile->fpa);
    73                 }
    74                 if (!modelReadout) {
    75                     psphotModelBackground (config, view, "PPIMAGE.CHIP");
    76                     modelFile = psMetadataLookupPtr(&status, config->files, "PSPHOT.BACKMDL");
    77                     assert (modelFile);
    78                     if (modelFile->mode == PM_FPA_MODE_INTERNAL) {
    79                         modelReadout = modelFile->readout;
    80                     } else {
    81                         modelReadout = pmFPAviewThisReadout (view, modelFile->fpa);
    82                     }
    83                     assert (modelReadout);
    84                 }
    85                 binning = psMetadataLookupPtr(&status, psphotRecipe, "PSPHOT.BACKGROUND.BINNING");
    86                 model = modelReadout->image;
    87             }
     42    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     43    psMetadataAddU8(psphotRecipe, PS_LIST_TAIL, "MASK.PSPHOT", PS_META_REPLACE, "user-defined mask", maskVal);
    8844
    89             psImage *mask = readout->mask;
    90             psImage *image = readout->image;
     45    // Since we are working on a chip-mosaicked image, there should only be a single cell and readout
     46    pmChip *chip = pmFPAviewThisChip(view, input->fpa); // Chip of interest
     47    if (!chip) {
     48        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find chip");
     49        return false;
     50    }
     51    if (chip->cells->n == 0) {
     52        psWarning("Chip has no cells");
     53        return true;
     54    }
     55    if (chip->cells->n > 1) {
     56        psWarning("Chip has %ld cells; only the first will be processed", chip->cells->n);
     57    }
     58    pmCell *cell = chip->cells->data[0]; // Cell of interest
     59    if (!cell || !cell->process || !cell->file_exists) {
     60        // Nothing to process
     61        return true;
     62    }
     63    if (cell->readouts->n == 0) {
     64        psWarning("Cell has no readouts");
     65        return true;
     66    }
     67    if (cell->readouts->n > 1) {
     68        psWarning("Cell has %ld readouts; only the first will be processed", cell->readouts->n);
     69    }
     70    pmReadout *ro = cell->readouts->data[0]; // Readout of interest
     71    if (!ro || !ro->data_exists) {
     72        // Nothing to process
     73        return true;
     74    }
     75    psImage *image = ro->image, *mask = ro->mask; // Image and mask of interest
    9176
    92             for (int iy = 0; iy < image->numRows; iy++) {
    93                 for (int ix = 0; ix < image->numCols; ix++) {
    94                     if (!(mask->data.U8[iy][ix] && maskVal)) continue;
    95                     if (replaceSkyMode == MODE_MODEL) {
    96                         image->data.F32[iy][ix] = psImageUnbinPixel_V2(ix, iy, model, binning);
    97                     } else {
    98                         image->data.F32[iy][ix] = replaceSkyValue;
    99                     }
    100                 }
    101             }
    102         }
     77
     78    pmFPAview roView = *view;           // View to readout
     79    roView.cell = roView.readout = 0;
     80    pmReadout *modelRO = pmFPAviewThisReadout(&roView, modelFile->fpa); // Background model
     81    if (!modelRO) {
     82        // Create the background model
     83        if (!psphotModelBackground(config, &roView, "PPIMAGE.CHIP")) {
     84            psError(PS_ERR_UNKNOWN, false, "Unable to model background");
     85            return false;
     86        }
     87        modelRO = (modelFile->mode == PM_FPA_MODE_INTERNAL) ? modelFile->readout :
     88                   pmFPAviewThisReadout(&roView, modelFile->fpa);
     89        if (!modelRO) {
     90            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find background model");
     91            return false;
     92        }
     93    }
     94    psImageBinning *binning = psMetadataLookupPtr(&status, psphotRecipe,
     95                                                  "PSPHOT.BACKGROUND.BINNING"); // Binning for model
     96    psImage *modelImage = modelRO->image; // Background model
     97
     98    // Do the background subtraction
     99    int numCols = image->numCols, numRows = image->numRows; // Size of image
     100    for (int y = 0; y < numRows; y++) {
     101        for (int x = 0; x < numCols; x++) {
     102            if (mask && mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal) {
     103                image->data.F32[y][x] = 0.0;
     104            } else {
     105                float value = psImageUnbinPixel_V2(x, y, modelImage, binning); // Background value
     106                if (!isfinite(value)) {
     107                    image->data.F32[y][x] = NAN;
     108                    mask->data.PS_TYPE_MASK_DATA[y][x] |= options->badMask;
     109                } else {
     110                    image->data.F32[y][x] -= value;
     111                }
     112            }
     113        }
    103114    }
    104115
    105     if (replaceSkyMode == MODE_MODEL) {
    106         pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL");
    107         pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL.STDEV");
    108     }
     116    pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL");
     117    pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL.STDEV");
    109118
    110119    return true;
Note: See TracChangeset for help on using the changeset viewer.