IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

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

add PATTERN.DEAD.CELLS functions in pmPattern and related I/O bits

Location:
branches/eam_branches/ipp-20220316/psModules/src
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20220316/psModules/src/camera/pmFPAfile.c

    r41892 r42168  
    554554    if (!strcasecmp(type, "PATTERN.ROW.AMP"))     {
    555555        return PM_FPA_FILE_PATTERN_ROW_AMP;
     556    }
     557    if (!strcasecmp(type, "PATTERN.DEAD.CELLS"))     {
     558        return PM_FPA_FILE_PATTERN_DEAD_CELLS;
    556559    }
    557560    if (!strcasecmp(type, "SUBKERNEL"))     {
     
    611614      case PM_FPA_FILE_PATTERN_ROW_AMP:
    612615        return ("PATTERN.ROW.AMP");
     616      case PM_FPA_FILE_PATTERN_DEAD_CELLS:
     617        return ("PATTERN.DEAD.CELLS");
    613618      case PM_FPA_FILE_SUBKERNEL:
    614619        return ("SUBKERNEL");
  • branches/eam_branches/ipp-20220316/psModules/src/camera/pmFPAfile.h

    r41892 r42168  
    5353    PM_FPA_FILE_PATTERN,
    5454    PM_FPA_FILE_PATTERN_ROW_AMP,
     55    PM_FPA_FILE_PATTERN_DEAD_CELLS,
    5556    PM_FPA_FILE_LINEARITY,
    5657    PM_FPA_FILE_EXPNUM,
  • branches/eam_branches/ipp-20220316/psModules/src/camera/pmFPAfileFitsIO.c

    r41892 r42168  
    153153      case PM_FPA_FILE_KH_CORRECT:
    154154      case PM_FPA_FILE_PATTERN_ROW_AMP:
     155      case PM_FPA_FILE_PATTERN_DEAD_CELLS:
    155156        {
    156157          pmHDU *hdu = pmFPAviewThisHDU(view, fpa);
  • branches/eam_branches/ipp-20220316/psModules/src/camera/pmFPAfileIO.c

    r41892 r42168  
    256256        status = pmPatternRowAmpRead(view, file, config);
    257257        break;
     258      case PM_FPA_FILE_PATTERN_DEAD_CELLS:
     259        status = pmPatternDeadCellsRead(view, file, config);
     260        break;
    258261      case PM_FPA_FILE_SX:
    259262      case PM_FPA_FILE_RAW:
     
    367370      case PM_FPA_FILE_KH_CORRECT:
    368371      case PM_FPA_FILE_PATTERN_ROW_AMP:
     372      case PM_FPA_FILE_PATTERN_DEAD_CELLS:
    369373      case PM_FPA_FILE_JPEG:
    370374      case PM_FPA_FILE_KAPA:
     
    459463      return true;
    460464    }
     465    if (file->type == PM_FPA_FILE_PATTERN_DEAD_CELLS) {
     466      psTrace("psModules.camera", 6, "skip write for %s, no write function defined", file->name);
     467      return true;
     468    }
    461469
    462470    // open the file if not yet opened
     
    559567      case PM_FPA_FILE_PATTERN_ROW_AMP:
    560568        psError(PS_ERR_IO, true, "cannot write type PATTERN.ROW.AMP (%s)", file->name);
     569        break;
     570
     571      case PM_FPA_FILE_PATTERN_DEAD_CELLS:
     572        psError(PS_ERR_IO, true, "cannot write type PATTERN.DEAD.CELLS (%s)", file->name);
    561573        break;
    562574
     
    637649      case PM_FPA_FILE_KH_CORRECT:
    638650      case PM_FPA_FILE_PATTERN_ROW_AMP:
     651      case PM_FPA_FILE_PATTERN_DEAD_CELLS:
    639652      case PM_FPA_FILE_LINEARITY:
    640653      case PM_FPA_FILE_EXPNUM:
     
    716729      case PM_FPA_FILE_KH_CORRECT:
    717730      case PM_FPA_FILE_PATTERN_ROW_AMP:
     731      case PM_FPA_FILE_PATTERN_DEAD_CELLS:
    718732      case PM_FPA_FILE_EXPNUM:
    719733        psTrace ("psModules.camera", 6, "NOT freeing %s (%s) : save for further analysis\n", file->filename, file->name);
     
    880894      case PM_FPA_FILE_KH_CORRECT:
    881895      case PM_FPA_FILE_PATTERN_ROW_AMP:
     896      case PM_FPA_FILE_PATTERN_DEAD_CELLS:
    882897      case PM_FPA_FILE_LINEARITY:
    883898      case PM_FPA_FILE_EXPNUM:
     
    10851100      case PM_FPA_FILE_KH_CORRECT:
    10861101      case PM_FPA_FILE_PATTERN_ROW_AMP:
     1102      case PM_FPA_FILE_PATTERN_DEAD_CELLS:
    10871103      case PM_FPA_FILE_SX:
    10881104      case PM_FPA_FILE_RAW:
  • branches/eam_branches/ipp-20220316/psModules/src/detrend/pmDetrendDB.c

    r41892 r42168  
    113113        DETREND_STRING_CASE(KH_CORRECT);
    114114        DETREND_STRING_CASE(PATTERN_ROW_AMP);
     115        DETREND_STRING_CASE(PATTERN_DEAD_CELLS);
    115116    default:
    116117        return NULL;
  • branches/eam_branches/ipp-20220316/psModules/src/detrend/pmDetrendDB.h

    r41892 r42168  
    4242    PM_DETREND_TYPE_KH_CORRECT,
    4343    PM_DETREND_TYPE_PATTERN_ROW_AMP,
     44    PM_DETREND_TYPE_PATTERN_DEAD_CELLS,
    4445} pmDetrendType;
    4546
  • branches/eam_branches/ipp-20220316/psModules/src/detrend/pmPattern.c

    r42092 r42168  
    10051005    psFree(meanMask);
    10061006
     1007    return true;
     1008}
     1009
     1010// Compare the backs (cellBackgrounds) vector to each of the patterns loaded for this chip.
     1011// Choose the one that matches best & mask as appropriate
     1012// can we pass the backgrounds in using an image (8 x 8)
     1013bool pmPatternDeadCells(pmChip *chip, const psVector *backs, psImageMaskType maskVal)
     1014{
     1015    PS_ASSERT_PTR_NON_NULL(chip, false);
     1016    PS_ASSERT_VECTOR_NON_NULL(backs, false);
     1017    PS_ASSERT_VECTOR_SIZE(backs, chip->cells->n, false);
     1018    PS_ASSERT_VECTOR_TYPE(backs, PS_TYPE_F32, false);
     1019
     1020    // Look for the dead cell pattern cube in the analysis metadata.
     1021    // NOTE: not all chips have the pattern, skip if not found.
     1022    bool mdok;
     1023    psImage *deadCellPattern = (psImage *) psMetadataLookupPtr (&mdok, chip->analysis, "PTN.DEAD.CELL");
     1024    if (!mdok) {
     1025        psLogMsg("psModules.detrend", PS_LOG_DETAIL, "No DEAD CELL pattern for chip, skipping\n");
     1026        return true;
     1027    }
     1028
     1029    int numCells = backs->n;            // Number of cells
     1030    int numColsD = deadCellPattern->numCols;
     1031    int numRowsD = deadCellPattern->numRows;
     1032
     1033    assert (backs->n == numRowsD);
     1034
     1035    // The background values need to be normalized (divide by the median).
     1036    // First extract the valid data values
     1037    psVector *valid = psVectorAllocEmpty(backs->n, PS_TYPE_F32); // Mean for each cell
     1038    for (int i = 0; i < backs->n; i++) {
     1039        float value = backs->data.F32[i];
     1040        if (!isfinite(value)) { backs->data.F32[i] = NAN; continue; }
     1041        if (value > 50000.0)  { backs->data.F32[i] = NAN; continue; } // XXX warning: hard-wired value
     1042        psVectorAppend (valid, value);
     1043    }
     1044    if (valid->n == 0) {
     1045        psLogMsg("psModules.detrend", PS_LOG_DETAIL, "No valid backgrounds, skipping\n");
     1046        psFree (valid);
     1047        return true;
     1048    }
     1049
     1050    // Second, calculate the median
     1051    psVectorSortInPlace (valid);
     1052    int midPt = valid->n / 2.0;
     1053    float median = valid->n % 2 ? valid->data.F32[midPt] : 0.5*(valid->data.F32[midPt] + valid->data.F32[midPt-1]);
     1054    psFree (valid);
     1055
     1056    // Finally, renormalize:
     1057    for (int i = 0; i < backs->n; i++) {
     1058        if (!isfinite(backs->data.F32[i])) { continue; }
     1059        backs->data.F32[i] /= median;
     1060    }
     1061
     1062    // there are 2 columns (value & mask) for each mode, plus the constant mode
     1063    int nModes = numColsD / 2 + 1;
     1064   
     1065    psVector *stdev = psVectorAlloc(nModes, PS_TYPE_F32); // Mean for each cell
     1066
     1067    // measure stdev for each comparison
     1068    for (int i = 0; i < nModes; i++) {
     1069        float Sum1 = 0.0;
     1070        float Sum2 = 0.0;
     1071        int   Npts = 0;
     1072
     1073        // choose the column with the background values for this mode
     1074        int nModeColumn = 2*(i - 1);
     1075
     1076        for (int j = 0; j < backs->n; j++) {
     1077
     1078            float valObs = backs->data.F32[j];
     1079            float valRef = (i == 0) ? 0.0 : deadCellPattern->data.F32[j][nModeColumn];
     1080
     1081            if (!isfinite(valObs)) continue;
     1082            if (!isfinite(valRef)) continue;
     1083
     1084            float dS = valObs - valRef;
     1085            Sum1 += dS;
     1086            Sum2 += dS*dS;
     1087            Npts ++;
     1088        }
     1089        if (Npts == 0) {
     1090            // is this is an error?
     1091            // no valid data, ignore this test
     1092            psLogMsg("psModules.detrend", PS_LOG_DETAIL, "No valid backgrounds, skipping\n");
     1093            psFree (stdev);
     1094            return true;
     1095        }
     1096
     1097        float mean = Sum1 / Npts;
     1098        float sigma = sqrt(Sum2 / Npts - mean*mean);
     1099        stdev->data.F32[i] = sigma;
     1100        fprintf (stderr, "mode: %d, stdev: %f\n", i, sigma);
     1101    }
     1102
     1103    // loop over stdev and choose the lowest one
     1104    int   minI = 0;
     1105    float minV = stdev->data.F32[minI];
     1106
     1107    for (int i = 1; i < nModes; i++) {
     1108        if (stdev->data.F32[i] < minV) {
     1109            minI = i;
     1110            minV = stdev->data.F32[i];
     1111        }
     1112    }
     1113    psFree (stdev);
     1114
     1115    if (minI == 0) return true;
     1116
     1117    int nModeColumnMask = 2*(minI - 1) + 1;
     1118
     1119    // now mask bad cells
     1120    for (int i = 0; i < numCells; i++) {
     1121        if (deadCellPattern->data.F32[i][nModeColumnMask] > 0) continue;
     1122
     1123        pmCell *cell = chip->cells->data[i]; // Cell of interest
     1124        pmReadout *ro = cell->readouts->data[0]; // Readout of interest
     1125
     1126        psImage *mask = ro->mask; // mask of interest
     1127        int numCols = mask->numCols, numRows = mask->numRows; // Size of image
     1128       
     1129        for (int y = 0; y < numRows; y++) {
     1130            for (int x = 0; x < numCols; x++) {
     1131                mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= maskVal;
     1132            }
     1133        }
     1134    }
    10071135    return true;
    10081136}
  • branches/eam_branches/ipp-20220316/psModules/src/detrend/pmPattern.h

    r35081 r42168  
    8686
    8787
     88bool pmPatternDeadCells(pmChip *chip, const psVector *backs, psImageMaskType maskVal);
     89
    8890/// @}
    8991#endif
  • branches/eam_branches/ipp-20220316/psModules/src/detrend/pmPatternIO.c

    r41892 r42168  
    482482}
    483483
    484 // read the set of tables, one for each chip
     484// Read the set of tables, one for each chip.  The values are saved on the cell->analysis
     485// metadata of the pmFPAfile associated with the pattern file.  Later, when this is used (e.g.,
     486// ppImageDetrendPatternRowApply), the values are transferred to the cell->analysis metadata of
     487// the pmFPAfile for the image being processed.
    485488bool pmPatternRowAmpReadChips (pmFPAfile *file) {
    486489
     
    560563    return true;
    561564}
     565
     566/**************** PatternDeadCells I/O *************************/
     567
     568bool pmPatternDeadCellsRead (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
     569    {
     570        // read the full model in one pass: require the level to be FPA
     571        if (view->chip != -1) {
     572            psError(PS_ERR_IO, false, "Pattern Dead Cells must be read at the FPA level");
     573            return false;
     574        }
     575
     576        if (!pmPatternDeadCellsReadFPA (file)) {
     577            psError(PS_ERR_IO, false, "Failed to read Pattern Dead Cells for fpa");
     578            return false;
     579        }
     580        return true;
     581    }
     582
     583// read in all chip-level Pattern Dead Cells data for this FPA
     584bool pmPatternDeadCellsReadFPA (pmFPAfile *file) {
     585
     586    if (!pmPatternDeadCellsReadChips (file)) {
     587        psError(PS_ERR_IO, false, "Failed to read Pattern Dead Cells for chips");
     588        return false;
     589    }
     590
     591    return true;
     592}
     593
     594// Read the set of dead cell image cubes, one for each chip.  The values are saved on the
     595// chip->analysis metadata of the pmFPAfile associated with the pattern file.  Later, when this
     596// is used (e.g., ppImageDetrendPatternDeadCellsApply), the values are transferred to the
     597// chip->analysis metadata of the pmFPAfile for the image being processed.
     598bool pmPatternDeadCellsReadChips (pmFPAfile *file) {
     599
     600    bool haveData, status;
     601
     602    // loop over the extensions
     603    // for each extension, use the extname (eg, XY01.ded) to assign to a chip
     604
     605    // move to the start of the file
     606    haveData = psFitsMoveExtNum (file->fits, 1, false);
     607    if (!haveData) {
     608        psError(PS_ERR_IO, false, "Failed to read even the first extension?");
     609        return false;
     610    }
     611
     612    int nGood = 0;
     613    while (haveData) {
     614
     615        // load the header
     616        psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header
     617        if (!header) psAbort("cannot read dead cell header");
     618
     619        // load the full model in one shot
     620        psImage *deadCellData = psFitsReadImage(file->fits, psRegionSet(0,0,0,0), 0); // dead cell patterns
     621        if (!deadCellData) psAbort("cannot read dead cell pattern");
     622       
     623        // determine the chip (not all chips have DEAD CELL patterns)
     624        char *extname = psMetadataLookupStr (&status, header, "EXTNAME");
     625        psLogMsg ("psModules.detrend", 8, "read dead cell pattern for extname %s\n", extname);
     626
     627        // I expect to find a name of the form: chipName.ded (eg, XY01.ded)
     628        // where chipName like 'XY01'
     629        psAssert (strlen(extname) == 8, "invalid extension %s", extname);
     630        psAssert (extname[5] == 'd', "invalid extension %s", extname);
     631        psAssert (extname[6] == 'e', "invalid extension %s", extname);
     632        psAssert (extname[7] == 'd', "invalid extension %s", extname);
     633
     634        char chipName[5];
     635        strncpy (chipName, extname, 4);
     636        chipName[4] = 0;
     637
     638        pmChip *chip = pmConceptsChipFromName (file->fpa, chipName);
     639        if (!chip) psAbort ("invalid chip?");
     640
     641        psMetadataAddImage (chip->analysis, PS_LIST_TAIL, "PTN.DEAD.CELL", PS_META_REPLACE, "", deadCellData);
     642        psFree (deadCellData);
     643        psFree (header);
     644
     645        // move to the next extension
     646        haveData = psFitsMoveExtNum (file->fits, 1, true);
     647        nGood ++;
     648    }
     649    psLogMsg ("psModules.detrend", 4, "read patterns for %d chips from Pattern Dead Cells file\n", nGood);
     650
     651    return true;
     652}
  • branches/eam_branches/ipp-20220316/psModules/src/detrend/pmPatternIO.h

    r41892 r42168  
    4040bool pmPatternRowAmpReadChips (pmFPAfile *file);
    4141
     42bool pmPatternDeadCellsRead (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
     43bool pmPatternDeadCellsReadFPA (pmFPAfile *file);
     44bool pmPatternDeadCellsReadChips (pmFPAfile *file);
     45
    4246#endif
Note: See TracChangeset for help on using the changeset viewer.