IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 42167


Ignore:
Timestamp:
Apr 13, 2022, 10:53:25 AM (4 years ago)
Author:
eugene
Message:

add PATTERN.DEAD.CELLS option; split ppImageDetrendPattern into separate functions for the 4 different options; functions like ppImageDetrendFringeApply and ppImageDetrendPatternApply now test the relevant option and return true if not selected (no need to check the option in the calling function)

Location:
branches/eam_branches/ipp-20220316/ppImage/src
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20220316/ppImage/src/ppImage.h

    r41894 r42167  
    4646    bool doPatternContinuity;           // Cell continuity correction
    4747    bool doBackgroundContinuity;        // Do mosaic continuity correction
     48    bool doPatternDeadCells;            // match dead cell background patterns
    4849    bool doFringe;                      // Fringe subtraction
    4950    bool doPhotom;                      // Source identification and photometry
  • branches/eam_branches/ipp-20220316/ppImage/src/ppImageArguments.c

    r41894 r42167  
    117117    pmConfigFileSetsMD (config->arguments, &argc, argv, "LINEARITY", "-linearity", "-linearlist");
    118118    pmConfigFileSetsMD (config->arguments, &argc, argv, "PATTERN.ROW.AMP", "-pattern-row-amplitude", "-not-defined");
     119    pmConfigFileSetsMD (config->arguments, &argc, argv, "PATTERN.DEAD.CELLS", "-pattern-dead-cells", "-not-defined");
    119120
    120121    if ((argnum = psArgumentGet(argc, argv, "-burntool"))) {
  • branches/eam_branches/ipp-20220316/ppImage/src/ppImageDetrendFringe.c

    r37406 r42167  
    327327    pmCell *cell = NULL;
    328328
    329     // psTimerStart("apply.fringe");
    330 
    331     assert (options->doFringe); // do not call if not needed
     329    if (!options->doFringe) return true;
     330
    332331    assert (inputView->chip != -1);
    333332    assert (inputView->cell == -1);
  • branches/eam_branches/ipp-20220316/ppImage/src/ppImageDetrendPattern.c

    r42166 r42167  
    55#include "ppImage.h"
    66
    7 #define ESCAPE(STATUS,...) {                    \
     7#define ESCAPE(STATUS,...) {                            \
    88        psError(PS_ERR_UNKNOWN, STATUS, __VA_ARGS__);   \
    99        psFree(view);                                   \
     
    1313static bool doPatternForView (bool *doit, const pmConfig *config, const pmChip *chip, const pmFPAview *view, const char *recipename, const char *recipevalue);
    1414
    15 bool ppImageDetrendPatternApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView,
    16                                 ppImageOptions *options)
     15bool ppImageDetrendPatternRowApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options);
     16bool ppImageDetrendPatternContinuityApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options);
     17bool ppImageDetrendPatternCellApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options);
     18bool ppImageDetrendPatternDeadCellsApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options);
     19
     20// Apply the desired pattern corrections (if any).  This function is passed the chip for the
     21// image being processed, but may interact with pmFPAfiles containing the pattern reference information
     22bool ppImageDetrendPatternApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options)
    1723{
    18     pmCell *cell = NULL;
    19 
    20     assert(options->doPatternRow || options->doPatternCell || options->doPatternContinuity); // do not call if not needed
     24    assert(inputView->chip != -1);
     25    assert(inputView->cell == -1);
     26    assert(inputView->readout == -1);
     27
     28    if (!ppImageDetrendPatternRowApply (config, chip, inputView, options)) {
     29        return false;
     30    }
     31    if (!ppImageDetrendPatternContinuityApply (config, chip, inputView, options)) {
     32        return false;
     33    }
     34    if (!ppImageDetrendPatternCellApply (config, chip, inputView, options)) {
     35        return false;
     36    }
     37    if (!ppImageDetrendPatternDeadCellsApply (config, chip, inputView, options)) {
     38        return false;
     39    }
     40    return(true);
     41}
     42
     43bool ppImageDetrendPatternRowApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options)
     44{
     45    bool status;
     46
     47    if (!options->doPatternRow) return true;
     48   
    2149    assert(inputView->chip != -1);
    2250    assert(inputView->cell == -1);
     
    3563    // tables, one per chip.  Each table lists the typical bias-drift amplitude for cell,
    3664    // measured from a collection of dark images.  These values are passed (via
    37     // cell->analysis) to pmPatternRow which choosed to apply the correction based on the
     65    // cell->analysis) to pmPatternRow which chooses to apply the correction based on the
    3866    // ratio of the poisson noise due to the median background (+ read noise) and the
    3967    // typical amplitude.  Tests show that if the amplitude / noise < 1/6, then the
     
    4472    // chip.
    4573
    46     // psTimerStart("apply.pattern");
    47     if (options->doPatternRow) {
    48 
    49         //psLogMsg("ppImage", PS_LOG_INFO, "Log: entering pattern.row routine");
    50         //psWarning ("Entering pattern.row routine");
    51 
    52         bool status;
    53         pmHDU *hdu = pmHDUFromChip(chip);
    54         if (psMetadataLookupBool(NULL,hdu->header,"PTRN_ROW")) {
    55           psLogMsg("ppImage", PS_LOG_INFO, "Not performing row pattern correction as it has already been done.");
    56           goto pattern_continuity;
    57         }
    58 
    59         const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME");
    60         psLogMsg("ppImage", PS_LOG_INFO, "Performing row pattern correction for %s\n", chipName);
    61 
    62         pmFPAfile *input = psMetadataLookupPtr(&status, config->files, "PPIMAGE.INPUT");
    63 
    64         // grab the PATTERN.ROW.AMP file
    65         pmFPAfile *PRAfile = psMetadataLookupPtr (NULL, config->files, "PPIMAGE.PATTERN.ROW.AMP");
    66         if (!PRAfile) {
    67           psLogMsg("ppImage", PS_LOG_INFO, "Pattern Row Amplitude file not found, applying to all (with limits from ROW.SUBSET) ");
    68         }
    69        
    70         pmFPAview *view = pmFPAviewAlloc(0); // View for local processing
    71         *view = *inputView;
    72         while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
    73             //const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME");
    74             //const char *cellName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME");
    75             //psWarning ("Looping through %s, %s\n", chipName, cellName);
    76 
    77             if (!cell->process || !cell->file_exists) {
    78                 continue;
    79             }
    80             if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    81                 ESCAPE(false, "load failure for Cell");
    82             }
     74    pmHDU *hdu = pmHDUFromChip(chip);
     75    if (psMetadataLookupBool(&status, hdu->header, "PTRN_ROW")) {
     76        psLogMsg("ppImage", PS_LOG_INFO, "Not performing row pattern correction as it has already been done.");
     77        return true;
     78    }
     79
     80    const char *chipName = psMetadataLookupStr(&status, chip->concepts, "CHIP.NAME");
     81    psLogMsg("ppImage", PS_LOG_INFO, "Performing row pattern correction for %s\n", chipName);
     82
     83    // XXX we use input->fpa below, but could we just use chip->parent?
     84    pmFPAfile *input = psMetadataLookupPtr(&status, config->files, "PPIMAGE.INPUT");
     85
     86    // grab the PATTERN.ROW.AMP file
     87    pmFPAfile *PRAfile = psMetadataLookupPtr (&status, config->files, "PPIMAGE.PATTERN.ROW.AMP");
     88    if (!PRAfile) {
     89        psLogMsg("ppImage", PS_LOG_INFO, "Pattern Row Amplitude file not found, applying to all (with limits from ROW.SUBSET) ");
     90    }
     91       
     92    pmFPAview *view = pmFPAviewAlloc(0); // View for local processing
     93    *view = *inputView;
     94
     95    pmCell *cell = NULL;
     96    while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
     97        // const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME");
     98        // const char *cellName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME");
     99        // psWarning ("Looping through %s, %s\n", chipName, cellName);
     100
     101        if (!cell->process || !cell->file_exists) {
     102            continue;
     103        }
     104
     105        // this forces pmFPAfileRead of the PATTERN.ROW.AMP file (XXX but is this needed?)
     106        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     107            ESCAPE(false, "load failure for Cell");
     108        }
    83109           
    84             if (!cell->data_exists) {
    85                 continue;
    86             }
    87 
    88             if (cell->readouts->n > 1) {
    89                 psWarning ("Skipping Video Cell for ppImageDetrendPatternApply");
    90                 continue;
    91             }
    92 
    93             // grab the corresponding cell
    94             if (PRAfile) {
    95               pmCell *PRAcell = pmFPAviewThisCell (view, PRAfile->fpa);
    96               psAssert (PRAcell, "found Pattern Row Amplitude file, but not cell?");
    97 
    98               // find the nominal signal amplitude (check the ghost and/or crosstalk recipe file)
    99               float amplitude = psMetadataLookupF32 (&status, PRAcell->analysis, "PTN.ROW.AMP");
    100               if (!status) amplitude = NAN;
     110        if (!cell->data_exists) {
     111            continue;
     112        }
     113
     114        if (cell->readouts->n > 1) {
     115            psWarning ("Skipping Video Cell for ppImageDetrendPatternApply");
     116            continue;
     117        }
     118
     119        // grab the corresponding cell
     120        if (PRAfile) {
     121            pmCell *PRAcell = pmFPAviewThisCell (view, PRAfile->fpa);
     122            psAssert (PRAcell, "found Pattern Row Amplitude file, but not cell?");
     123
     124            // find the nominal signal amplitude (check the ghost and/or crosstalk recipe file)
     125            float amplitude = psMetadataLookupF32 (&status, PRAcell->analysis, "PTN.ROW.AMP");
     126            if (!status) amplitude = NAN;
    101127           
    102               // put the value on the science cell
    103               psMetadataAddF32 (cell->analysis, PS_LIST_TAIL, "PTN.ROW.AMP", PS_META_REPLACE, "", amplitude);
     128            // put the value on the science cell
     129            psMetadataAddF32 (cell->analysis, PS_LIST_TAIL, "PTN.ROW.AMP", PS_META_REPLACE, "", amplitude);
     130        }
     131
     132        bool doPattern = false;
     133        if (!doPatternForView(&doPattern, config, chip, view, RECIPE_NAME, "PATTERN.ROW.SUBSET")) {
     134            ESCAPE(false, "Unable to determine whether row pattern matching should be applied.");
     135        }
     136        if (!doPattern) continue;
     137
     138        // switch to test threaded version
     139        if (true) {
     140            // I need to allocate a view here to be freed by the
     141            // called function below. 
     142            pmFPAview *myView = pmFPAviewAlloc(0); // View for local processing
     143            *myView = *view;
     144
     145            // allocate a job, construct the arguments for this job
     146            psThreadJob *job = psThreadJobAlloc("PPIMAGE_PATTERN_ROW_CELL");
     147            psArrayAdd(job->args, 1, config);
     148            psArrayAdd(job->args, 1, input->fpa);
     149            psArrayAdd(job->args, 1, chip);
     150            psArrayAdd(job->args, 1, cell);
     151            psArrayAdd(job->args, 1, myView);
     152            psArrayAdd(job->args, 1, options);
     153            if (!psThreadJobAddPending(job)) {
     154                return false;
    104155            }
    105 
    106             bool doPattern = false;
    107             if (!doPatternForView(&doPattern, config, chip, view, RECIPE_NAME, "PATTERN.ROW.SUBSET")) {
    108                 ESCAPE(false, "Unable to determine whether row pattern matching should be applied.");
    109             }
    110             if (!doPattern) continue;
    111 
    112             // switch to test threaded version
    113             if (true) {
    114                 // I need to allocate a view here to be freed by the
    115                 // called function below. 
    116                 pmFPAview *myView = pmFPAviewAlloc(0); // View for local processing
    117                 *myView = *view;
    118 
    119                 // allocate a job, construct the arguments for this job
    120                 psThreadJob *job = psThreadJobAlloc("PPIMAGE_PATTERN_ROW_CELL");
    121                 psArrayAdd(job->args, 1, config);
    122                 psArrayAdd(job->args, 1, input->fpa);
    123                 psArrayAdd(job->args, 1, chip);
    124                 psArrayAdd(job->args, 1, cell);
    125                 psArrayAdd(job->args, 1, myView);
    126                 psArrayAdd(job->args, 1, options);
    127                 if (!psThreadJobAddPending(job)) {
    128                     return false;
    129                 }
    130             } else {
    131                 // bump the counter since it must be freed by the function below. 
    132                 psMemIncrRefCounter (view); // View for local processing
    133                 if (!ppImageDetrendPatternApplyCell (config, input->fpa, chip, cell, view, options)) {
    134                     return false;
    135                 }
     156        } else {
     157            // bump the counter since it must be freed by the function below. 
     158            psMemIncrRefCounter (view); // View for local processing
     159            if (!ppImageDetrendPatternApplyCell (config, input->fpa, chip, cell, view, options)) {
     160                return false;
    136161            }
    137 
    138         }
    139 
    140         // wait here for the threaded jobs to finish
    141         // if no threads are allocated, this
    142         if (!psThreadPoolWait(true, true)) {
    143             psError(PS_ERR_UNKNOWN, false, "Unable to apply bias correction.");
    144             return false;
    145         }
    146 
    147         psMetadataAddBool(hdu->header, PS_LIST_TAIL, "PTRN_ROW",PS_META_REPLACE,"PATTERN.ROW correction applied",true);
    148         psFree(view);
    149     }
    150 
    151  pattern_continuity:
     162        }
     163    }
     164
     165    // wait here for the threaded jobs to finish
     166    // if no threads are allocated, this
     167    if (!psThreadPoolWait(true, true)) {
     168        psError(PS_ERR_UNKNOWN, false, "Unable to apply bias correction.");
     169        return false;
     170    }
     171
     172    psMetadataAddBool(hdu->header, PS_LIST_TAIL, "PTRN_ROW",PS_META_REPLACE,"PATTERN.ROW correction applied",true);
     173    psFree(view);
     174   
     175    return true;
     176}
     177
     178bool ppImageDetrendPatternContinuityApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options)
     179{
     180    bool status;
     181
     182    if (!options->doPatternContinuity) return true;
     183
     184    assert(inputView->chip != -1);
     185    assert(inputView->cell == -1);
     186    assert(inputView->readout == -1);
    152187
    153188    // see the comment for PATTERN.ROW; the same rules apply for PATTERN.CELL
    154189
    155     if (options->doPatternContinuity) {
    156         int numCells = chip->cells->n;       // Number of cells
    157         psVector *tweak = psVectorAlloc(numCells, PS_TYPE_U8); // Tweak cell?
    158         pmFPAview *view = pmFPAviewAlloc(0); // View for local processing
    159         *view = *inputView;
    160 
    161         pmHDU *hdu = pmHDUFromChip(chip);
    162         if (psMetadataLookupBool(NULL,hdu->header,"PTRN_CON")) {
    163           psLogMsg("ppImage", PS_LOG_INFO, "Not performing cell continuity correction as it has already been done.");
    164           goto pattern_cell;
    165         }
    166 
    167         const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME");
    168         psLogMsg("ppImage", PS_LOG_INFO, "Performing pattern continuity correction for %s\n", chipName);
    169 
    170         for (int i = 0; i < chip->cells->n; i++) {
    171             view->cell = i;
    172 
    173             pmCell *cell = chip->cells->data[i]; // Cell of interest
    174 
    175             if (cell->readouts->n > 1) {
    176                 psLogMsg("ppImage", PS_LOG_INFO, "Not performing cell continuity correction on video cell.");
    177                 continue;
    178             }
    179 
    180             bool doPattern = false;
    181             if (!doPatternForView(&doPattern, config, chip, view, RECIPE_NAME, "PATTERN.CONTINUITY.SUBSET")) {
    182                 ESCAPE(false, "Unable to determine whether row pattern matching should be applied.");
    183             }
    184 
    185             if (doPattern) {
    186                 tweak->data.U8[i] = 0xFF;
    187             }
    188         }
    189 
    190         // Tweak the cells
    191         if (!pmPatternContinuity(chip, tweak, options->patternCellBG, options->patternCellMean,
    192                                  options->maskValue, options->darkMask,options->patternContinuityEdgeWidth)) {
    193             psFree(tweak);
    194             psFree(view);
    195             return false;
    196         }
     190    int numCells = chip->cells->n;       // Number of cells
     191    psVector *tweak = psVectorAlloc(numCells, PS_TYPE_U8); // Tweak cell?
     192    pmFPAview *view = pmFPAviewAlloc(0); // View for local processing
     193    *view = *inputView;
     194
     195    pmHDU *hdu = pmHDUFromChip(chip);
     196    if (psMetadataLookupBool(&status, hdu->header, "PTRN_CON")) {
     197        psLogMsg("ppImage", PS_LOG_INFO, "Not performing cell continuity correction as it has already been done.");
     198        return true;
     199    }
     200
     201    const char *chipName = psMetadataLookupStr(&status, chip->concepts, "CHIP.NAME");
     202    psLogMsg("ppImage", PS_LOG_INFO, "Performing pattern continuity correction for %s\n", chipName);
     203
     204    for (int i = 0; i < chip->cells->n; i++) {
     205        view->cell = i;
     206
     207        pmCell *cell = chip->cells->data[i]; // Cell of interest
     208
     209        if (cell->readouts->n > 1) {
     210            psLogMsg("ppImage", PS_LOG_INFO, "Not performing cell continuity correction on video cell.");
     211            continue;
     212        }
     213
     214        bool doPattern = false;
     215        if (!doPatternForView(&doPattern, config, chip, view, RECIPE_NAME, "PATTERN.CONTINUITY.SUBSET")) {
     216            ESCAPE(false, "Unable to determine whether row pattern matching should be applied.");
     217        }
     218
     219        if (doPattern) {
     220            tweak->data.U8[i] = 0xFF;
     221        }
     222    }
     223
     224    // Tweak the cells
     225    if (!pmPatternContinuity(chip, tweak, options->patternCellBG, options->patternCellMean,
     226                             options->maskValue, options->darkMask,options->patternContinuityEdgeWidth)) {
    197227        psFree(tweak);
    198228        psFree(view);
    199 
    200         psMetadataAddBool(hdu->header, PS_LIST_TAIL, "PTRN_CON",PS_META_REPLACE,"PATTERN.CONTINUITY correction applied",true);
    201     }
    202 
    203  pattern_cell:
    204    
    205     if (options->doPatternCell) {
    206         int numCells = chip->cells->n;       // Number of cells
    207         psVector *tweak = psVectorAlloc(numCells, PS_TYPE_U8); // Tweak cell?
    208         pmFPAview *view = pmFPAviewAlloc(0); // View for local processing
    209         *view = *inputView;
    210 
    211         pmHDU *hdu = pmHDUFromChip(chip);
    212         if (psMetadataLookupBool(NULL,hdu->header,"PTRN_CEL")) {
    213           psLogMsg("ppImage", PS_LOG_INFO, "Not performing cell pattern correction as it has already been done.");
    214           goto pattern_done;
    215         }
    216 
    217         const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME");
    218         psLogMsg("ppImage", PS_LOG_INFO, "Performing cell pattern correction for %s\n", chipName);
    219 
    220         for (int i = 0; i < chip->cells->n; i++) {
    221             view->cell = i;
    222 
    223             pmCell *cell = chip->cells->data[i]; // Cell of interest
    224 
    225             if (cell->readouts->n > 1) {
    226                 psLogMsg("ppImage", PS_LOG_INFO, "Not performing cell pattern correction on video cell.");
    227                 continue;
    228             }
    229 
    230             bool doPattern = false;
    231             if (!doPatternForView(&doPattern, config, chip, view, RECIPE_NAME, "PATTERN.CELL.SUBSET")) {
    232                 ESCAPE(false, "Unable to determine whether row pattern matching should be applied.");
    233             }
    234             if (doPattern) {
    235                 tweak->data.U8[i] = 0xFF;
    236             }
    237         }
    238 
    239         // Tweak the cells
    240         if (!pmPatternCell(chip, tweak, options->patternCellBG, options->patternCellMean,
    241                            options->maskValue, options->darkMask)) {
    242             psFree(tweak);
    243             psFree(view);
    244             return false;
    245         }
     229        return false;
     230    }
     231    psFree(tweak);
     232    psFree(view);
     233
     234    psMetadataAddBool(hdu->header, PS_LIST_TAIL, "PTRN_CON",PS_META_REPLACE,"PATTERN.CONTINUITY correction applied",true);
     235    return true;
     236}
     237
     238bool ppImageDetrendPatternCellApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options)
     239{
     240    bool status;
     241
     242    if (!options->doPatternCell) return true;
     243
     244    assert(inputView->chip != -1);
     245    assert(inputView->cell == -1);
     246    assert(inputView->readout == -1);
     247
     248    int numCells = chip->cells->n;       // Number of cells
     249    psVector *tweak = psVectorAlloc(numCells, PS_TYPE_U8); // Tweak cell?
     250    pmFPAview *view = pmFPAviewAlloc(0); // View for local processing
     251    *view = *inputView;
     252
     253    pmHDU *hdu = pmHDUFromChip(chip);
     254    if (psMetadataLookupBool(&status, hdu->header, "PTRN_CEL")) {
     255        psLogMsg("ppImage", PS_LOG_INFO, "Not performing cell pattern correction as it has already been done.");
     256        return true;
     257    }
     258
     259    const char *chipName = psMetadataLookupStr(&status, chip->concepts, "CHIP.NAME");
     260    psLogMsg("ppImage", PS_LOG_INFO, "Performing cell pattern correction for %s\n", chipName);
     261
     262    for (int i = 0; i < chip->cells->n; i++) {
     263        view->cell = i;
     264
     265        pmCell *cell = chip->cells->data[i]; // Cell of interest
     266
     267        if (cell->readouts->n > 1) {
     268            psLogMsg("ppImage", PS_LOG_INFO, "Not performing cell pattern correction on video cell.");
     269            continue;
     270        }
     271
     272        bool doPattern = false;
     273        if (!doPatternForView(&doPattern, config, chip, view, RECIPE_NAME, "PATTERN.CELL.SUBSET")) {
     274            ESCAPE(false, "Unable to determine whether row pattern matching should be applied.");
     275        }
     276        if (doPattern) {
     277            tweak->data.U8[i] = 0xFF;
     278        }
     279    }
     280
     281    // Tweak the cells
     282    if (!pmPatternCell(chip, tweak, options->patternCellBG, options->patternCellMean,
     283                       options->maskValue, options->darkMask)) {
    246284        psFree(tweak);
    247285        psFree(view);
    248 
    249         psMetadataAddBool(hdu->header, PS_LIST_TAIL, "PTRN_CEL",PS_META_REPLACE,"PATTERN.CELL correction applied",true);
    250     }
    251 
    252  pattern_done:
    253 
    254     // psLogMsg ("ppImage", 5, "apply pattern: %f sec\n", psTimerMark ("apply.pattern"));
    255 
    256     return(true);
     286        return false;
     287    }
     288    psFree(tweak);
     289    psFree(view);
     290
     291    psMetadataAddBool(hdu->header, PS_LIST_TAIL, "PTRN_CEL",PS_META_REPLACE,"PATTERN.CELL correction applied",true);
     292    return true;
     293}
     294
     295bool ppImageDetrendPatternDeadCellsMask (pmChip *chip, psImageMaskType maskVal) {
     296
     297    int numCells = chip->cells->n;       // Number of cells
     298
     299    // now mask bad cells
     300    for (int i = 0; i < numCells; i++) {
     301        pmCell *cell = chip->cells->data[i]; // Cell of interest
     302        pmReadout *ro = cell->readouts->data[0]; // Readout of interest
     303
     304        psImage *mask = ro->mask; // mask of interest
     305        int numCols = mask->numCols, numRows = mask->numRows; // Size of image
     306       
     307        for (int y = 0; y < numRows; y++) {
     308            for (int x = 0; x < numCols; x++) {
     309                mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= maskVal;
     310            }
     311        }
     312    }
     313
     314}
     315
     316bool ppImageDetrendPatternDeadCellsXY42 (pmChip *chip, psImageMaskType maskVal) {
     317
     318    bool status;
     319
     320    // extract the MEDIAN_CELL_BACKGROUND values to check for problems
     321    int numCells = chip->cells->n;       // Number of cells
     322    psVector *cellBackground = psVectorAllocEmpty (numCells, PS_DATA_F32);
     323
     324    for (int i = 0; i < numCells; i++) {
     325        pmCell *cell = chip->cells->data[i];;
     326
     327        if (!cell->process || !cell->file_exists || !cell->data_exists) continue;
     328       
     329        // select the HDU for this cell
     330        pmHDU *cellHDU = pmHDUFromCell(cell);  // HDU of interest
     331       
     332        psF32 BackValue = psMetadataLookupF32(&status, cellHDU->header, "BACK_VAL");
     333        if (!status) continue;
     334
     335        psF32 BackError = psMetadataLookupF32(&status, cellHDU->header, "BACK_ERR");
     336        if (!status) continue;
     337
     338        if (BackValue == 0.0) continue;
     339        if (BackError == 0.0) continue;
     340
     341        psVectorAppend (cellBackground, BackValue / BackError);
     342    }
     343
     344    if (cellBackground->n < 0.375*numCells) {
     345        // Chip is bad, mask the whole thing
     346        ppImageDetrendPatternDeadCellsMask (chip, maskVal);
     347        psFree (cellBackground);
     348        return true;
     349    }
     350
     351    // Second, calculate the median
     352    psVectorSortInPlace (cellBackground);
     353    int midPt = cellBackground->n / 2.0;
     354    float median = cellBackground->n % 2 ? cellBackground->data.F32[midPt] : 0.5*(cellBackground->data.F32[midPt] + cellBackground->data.F32[midPt-1]);
     355    psFree (cellBackground);
     356
     357    if (median < 3.0) {
     358        // Chip is bad, mask the whole thing
     359        ppImageDetrendPatternDeadCellsMask (chip, maskVal);
     360    }
     361    psFree (cellBackground);
     362    return true;
     363}
     364
     365// to apply the dead cell pattern, we need to transfer the pattern for this chip from the
     366// pmFPAfile for the pattern to the one for the image being processed. 
     367bool ppImageDetrendPatternDeadCellsApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options)
     368{
     369    bool status;
     370
     371    if (!options->doPatternDeadCells) return true;
     372
     373    assert(inputView->chip != -1);
     374    assert(inputView->cell == -1);
     375    assert(inputView->readout == -1);
     376
     377    const char *chipName = psMetadataLookupStr(&status, chip->concepts, "CHIP.NAME");
     378    psLogMsg("ppImage", PS_LOG_INFO, "Performing cell pattern correction for %s\n", chipName);
     379
     380    pmHDU *hdu = pmHDUFromChip(chip);
     381    if (psMetadataLookupBool(&status, hdu->header, "PTRN_DED")) {
     382        psLogMsg("ppImage", PS_LOG_INFO, "Not performing dead cell pattern correction as it has already been done.");
     383        return true;
     384    }
     385
     386    if (!strcmp (chipName, "XY40") || !strcmp (chipName, "XY42")) {
     387        // special case : check for BACK_VAL / BACK_ERR > 3 or < 3
     388        psLogMsg("ppImage", PS_LOG_INFO, "Using special case for XY40 and XY42");
     389        ppImageDetrendPatternDeadCellsXY42 (chip, options->blankMask);
     390        return true;
     391    }
     392
     393    pmFPAfile *pattern = psMetadataLookupPtr(&status, config->files, "PPIMAGE.PATTERN.DEAD.CELLS");
     394    if (!pattern) {
     395        psLogMsg("ppImage", PS_LOG_INFO, "Pattern Dead Cells file not found, skipping");
     396        return true;
     397    }
     398
     399    pmFPAview *view = pmFPAviewAlloc(0); // View for local processing
     400    *view = *inputView;
     401
     402    pmChip *patternChip = pmFPAviewThisChip (view, pattern->fpa);
     403
     404    // grab the pattern from the input pattern file chip
     405    psImage *deadCellPattern = (psImage *) psMetadataLookupPtr (&status, patternChip->analysis, "PTN.DEAD.CELL");
     406    if (!deadCellPattern) {
     407        psLogMsg("psModules.detrend", PS_LOG_DETAIL, "No DEAD CELL pattern for chip, skipping\n");
     408        psFree (view);
     409        return true;
     410    }
     411
     412    // copy the pattern pointer to the chip of the image being processed
     413    psMetadataAddImage (chip->analysis, PS_LIST_TAIL, "PTN.DEAD.CELL", PS_META_REPLACE, "", deadCellPattern);
     414
     415    // extract the MEDIAN_CELL_BACKGROUND values to check for problems
     416    int numCells = chip->cells->n;       // Number of cells
     417    psVector *cellBackground = psVectorAllocEmpty (numCells, PS_DATA_F32);
     418
     419    pmCell *cell = NULL;
     420    while ((cell = pmFPAviewNextCell(view, chip->parent, 1)) != NULL) {
     421        if (!cell->process || !cell->file_exists || !cell->data_exists) {
     422            psVectorAppend (cellBackground, NAN);
     423            continue;
     424        }
     425       
     426        // select the HDU for this cell
     427        pmHDU *cellHDU = pmHDUFromCell(cell);  // HDU of interest
     428       
     429        psF32 value = psMetadataLookupF32(&status, cellHDU->header, "BACK_VAL");
     430        if (!status) {
     431            psVectorAppend (cellBackground, NAN);
     432            continue;
     433        }
     434        psVectorAppend (cellBackground, value);
     435    }
     436
     437    // match cellBackground pattern to registered patterns and mask as needed
     438    if (!pmPatternDeadCells(chip, cellBackground, options->blankMask)) {
     439        psFree(cellBackground);
     440        psFree(view);
     441        return false;
     442    }
     443    psFree(cellBackground);
     444    psFree(view);
     445
     446    psMetadataAddBool(hdu->header, PS_LIST_TAIL, "PTRN_DED", PS_META_REPLACE, "PATTERN.DEADCELLS applied", true);
     447    return true;
    257448}
    258449
  • branches/eam_branches/ipp-20220316/ppImage/src/ppImageDetrendReadout.c

    r42158 r42167  
    126126
    127127    // measure the overscan-subtracted readoutBackground here (or subtract the overscan value?)
    128     if (1) {
    129         psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN);
     128    // XXX this is the measurements and should be independent of the pattern masking
     129    if (options->doPatternDeadCells) {
     130        psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    130131        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
    131132        psImageBackground (stats, NULL, input->image, NULL, 0xffff, rng);
     
    134135        pmHDU *hdu = pmHDUFromReadout(input);  // HDU of interest
    135136        psMetadataAddF32(hdu->header, PS_LIST_TAIL, "BACK_VAL", PS_META_REPLACE, "Median cell background", stats->robustMedian);
     137        psMetadataAddF32(hdu->header, PS_LIST_TAIL, "BACK_ERR", PS_META_REPLACE, "Stdev of cell background", stats->robustStdev);
    136138        psFree (stats);
    137139        psFree (rng);
  • branches/eam_branches/ipp-20220316/ppImage/src/ppImageLoop.c

    r42166 r42167  
    171171        }
    172172
    173         // Apply the pattern correction
    174         // XX if (options->checkCellFailures) {
    175         // XX   if (!ppImageDetrendPatternCellFailures(config,chip,view,options)) {
    176         // XX     ESCAPE("Unable to apply pattern corrections");
    177         // XX   }
    178         // XX }
    179 
    180 
    181173        // Apply the fringe correction
    182         if (options->doFringe) {
    183             if (!ppImageDetrendFringeApply(config, chip, view, options)) {
    184                 ESCAPE("Unable to defringe");
    185             }
     174        if (!ppImageDetrendFringeApply(config, chip, view, options)) {
     175            ESCAPE("Unable to defringe");
    186176        }
    187177
     
    191181        }
    192182
    193         // Apply the pattern correction
    194         if (options->doPatternRow || options->doPatternCell || options->doPatternContinuity) {
    195           if (!ppImageDetrendPatternApply(config,chip,view,options)) {
    196             ESCAPE("Unable to apply pattern corrections");
    197           }
     183        // Apply the pattern correction (only done if requested)
     184        if (!ppImageDetrendPatternApply(config,chip,view,options)) {
     185            ESCAPE("Problem applying pattern corrections");
    198186        }
    199187
  • branches/eam_branches/ipp-20220316/ppImage/src/ppImageOptions.c

    r42161 r42167  
    290290    options->doPatternCell = psMetadataLookupBool(NULL, recipe, "PATTERN.CELL");
    291291    options->doPatternContinuity = psMetadataLookupBool(NULL, recipe, "PATTERN.CONTINUITY");
     292    options->doPatternDeadCells = psMetadataLookupBool(NULL, recipe, "PATTERN.DEAD.CELLS");
    292293
    293294    options->doMaskStats = psMetadataLookupBool(NULL, recipe, "MASK.STATS");
  • branches/eam_branches/ipp-20220316/ppImage/src/ppImageParseCamera.c

    r41894 r42167  
    190190            // an empty or invalid file may have been generated -- we want to skip, not raise an error
    191191            pmFPAfile *PRAfile = psMetadataLookupPtr (NULL, config->files, "PPIMAGE.PATTERN.ROW.AMP");
     192            if (PRAfile) {
     193              PRAfile->state |= PM_FPA_STATE_INACTIVE;
     194            }
     195        }
     196    }
     197    if (options->doPatternDeadCells) {
     198        if (!ppImageDefineFile(config, input->fpa, "PPIMAGE.PATTERN.DEAD.CELLS", "PATTERN.DEAD.CELLS",
     199                               PM_FPA_FILE_PATTERN_DEAD_CELLS, PM_DETREND_TYPE_PATTERN_DEAD_CELLS)) {
     200            psWarning ("Can't find a pattern dead cells source");
     201            // an empty or invalid file may have been generated -- we want to skip, not raise an error
     202            pmFPAfile *PRAfile = psMetadataLookupPtr (NULL, config->files, "PPIMAGE.PATTERN.DEAD.CELLS");
    192203            if (PRAfile) {
    193204              PRAfile->state |= PM_FPA_STATE_INACTIVE;
Note: See TracChangeset for help on using the changeset viewer.