Changeset 42382 for trunk/ppImage
- Timestamp:
- Feb 8, 2023, 11:57:40 AM (3 years ago)
- Location:
- trunk/ppImage
- Files:
-
- 13 edited
-
. (modified) (1 prop)
-
src/Makefile.am (modified) (1 diff)
-
src/ppImage.h (modified) (1 diff)
-
src/ppImageArguments.c (modified) (1 diff)
-
src/ppImageDetrendFringe.c (modified) (1 diff)
-
src/ppImageDetrendPattern.c (modified) (5 diffs)
-
src/ppImageDetrendReadout.c (modified) (2 diffs)
-
src/ppImageLoop.c (modified) (2 diffs)
-
src/ppImageOptions.c (modified) (3 diffs)
-
src/ppImageParseCamera.c (modified) (1 diff)
-
src/ppImageRebinReadout.c (modified) (1 diff)
-
src/ppImageReplaceBackground.c (modified) (1 diff)
-
src/ppImageSetMaskBits.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ppImage
- Property svn:mergeinfo changed
/branches/eam_branches/ipp-20220316/ppImage (added) merged: 42148,42158,42161,42166-42167,42171,42185,42214,42372
- Property svn:mergeinfo changed
-
trunk/ppImage/src/Makefile.am
r42340 r42382 1 1 2 bin_PROGRAMS = ppImage 2 3 -
trunk/ppImage/src/ppImage.h
r42340 r42382 47 47 bool doPatternContinuity; // Cell continuity correction 48 48 bool doBackgroundContinuity; // Do mosaic continuity correction 49 bool doPatternDeadCells; // match dead cell background patterns 49 50 bool doFringe; // Fringe subtraction 50 51 bool doPhotom; // Source identification and photometry -
trunk/ppImage/src/ppImageArguments.c
r42340 r42382 119 119 pmConfigFileSetsMD (config->arguments, &argc, argv, "NEWNONLIN", "-newnonlin", "-newnonlinlist"); 120 120 pmConfigFileSetsMD (config->arguments, &argc, argv, "PATTERN.ROW.AMP", "-pattern-row-amplitude", "-not-defined"); 121 pmConfigFileSetsMD (config->arguments, &argc, argv, "PATTERN.DEAD.CELLS", "-pattern-dead-cells", "-not-defined"); 121 122 122 123 if ((argnum = psArgumentGet(argc, argv, "-burntool"))) { -
trunk/ppImage/src/ppImageDetrendFringe.c
r37406 r42382 327 327 pmCell *cell = NULL; 328 328 329 // psTimerStart("apply.fringe"); 330 331 assert (options->doFringe); // do not call if not needed 329 if (!options->doFringe) return true; 330 332 331 assert (inputView->chip != -1); 333 332 assert (inputView->cell == -1); -
trunk/ppImage/src/ppImageDetrendPattern.c
r41894 r42382 5 5 #include "ppImage.h" 6 6 7 #define ESCAPE(STATUS,...) { \7 #define ESCAPE(STATUS,...) { \ 8 8 psError(PS_ERR_UNKNOWN, STATUS, __VA_ARGS__); \ 9 9 psFree(view); \ … … 13 13 static bool doPatternForView (bool *doit, const pmConfig *config, const pmChip *chip, const pmFPAview *view, const char *recipename, const char *recipevalue); 14 14 15 bool ppImageDetrendPatternApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, 16 ppImageOptions *options) 15 bool ppImageDetrendPatternRowApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options); 16 bool ppImageDetrendPatternContinuityApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options); 17 bool ppImageDetrendPatternCellApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options); 18 bool 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 22 bool ppImageDetrendPatternApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options) 17 23 { 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 43 bool ppImageDetrendPatternRowApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options) 44 { 45 bool status; 46 47 if (!options->doPatternRow) return true; 48 21 49 assert(inputView->chip != -1); 22 50 assert(inputView->cell == -1); … … 35 63 // tables, one per chip. Each table lists the typical bias-drift amplitude for cell, 36 64 // measured from a collection of dark images. These values are passed (via 37 // cell->analysis) to pmPatternRow which choose dto apply the correction based on the65 // cell->analysis) to pmPatternRow which chooses to apply the correction based on the 38 66 // ratio of the poisson noise due to the median background (+ read noise) and the 39 67 // typical amplitude. Tests show that if the amplitude / noise < 1/6, then the … … 44 72 // chip. 45 73 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 } 83 109 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 cell94 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; 101 127 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; 104 155 } 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; 136 161 } 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 178 bool 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); 152 187 153 188 // see the comment for PATTERN.ROW; the same rules apply for PATTERN.CELL 154 189 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)) { 197 227 psFree(tweak); 198 228 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 238 bool 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)) { 246 284 psFree(tweak); 247 285 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 295 bool 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 return true; 314 } 315 316 bool 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 // XXX hardwired number 358 if (median < 3.0) { 359 // Chip is bad, mask the whole thing 360 ppImageDetrendPatternDeadCellsMask (chip, maskVal); 361 } 362 psFree (cellBackground); 363 return true; 364 } 365 366 // to apply the dead cell pattern, we need to transfer the pattern for this chip from the 367 // pmFPAfile for the pattern to the one for the image being processed. 368 bool ppImageDetrendPatternDeadCellsApply(pmConfig *config, pmChip *chip, const pmFPAview *inputView, ppImageOptions *options) 369 { 370 bool status; 371 372 if (!options->doPatternDeadCells) return true; 373 374 assert(inputView->chip != -1); 375 assert(inputView->cell == -1); 376 assert(inputView->readout == -1); 377 378 const char *chipName = psMetadataLookupStr(&status, chip->concepts, "CHIP.NAME"); 379 psLogMsg("ppImage", PS_LOG_INFO, "Performing cell pattern correction for %s\n", chipName); 380 381 pmHDU *hdu = pmHDUFromChip(chip); 382 if (psMetadataLookupBool(&status, hdu->header, "PTRN_DED")) { 383 psLogMsg("ppImage", PS_LOG_INFO, "Not performing dead cell pattern correction as it has already been done."); 384 return true; 385 } 386 387 if (!strcmp (chipName, "XY40") || !strcmp (chipName, "XY42")) { 388 // special case : check for BACK_VAL / BACK_ERR > 3 or < 3 389 psLogMsg("ppImage", PS_LOG_INFO, "Using special case for XY40 and XY42"); 390 ppImageDetrendPatternDeadCellsXY42 (chip, options->blankMask); 391 return true; 392 } 393 394 pmFPAfile *pattern = psMetadataLookupPtr(&status, config->files, "PPIMAGE.PATTERN.DEAD.CELLS"); 395 if (!pattern) { 396 psLogMsg("ppImage", PS_LOG_INFO, "Pattern Dead Cells file not found, skipping"); 397 return true; 398 } 399 400 pmFPAview *view = pmFPAviewAlloc(0); // View for local processing 401 *view = *inputView; 402 403 pmChip *patternChip = pmFPAviewThisChip (view, pattern->fpa); 404 405 // grab the pattern from the input pattern file chip 406 psImage *deadCellPattern = (psImage *) psMetadataLookupPtr (&status, patternChip->analysis, "PTN.DEAD.CELL"); 407 if (!deadCellPattern) { 408 psLogMsg("psModules.detrend", PS_LOG_DETAIL, "No DEAD CELL pattern for chip, skipping\n"); 409 psFree (view); 410 return true; 411 } 412 413 // copy the pattern pointer to the chip of the image being processed 414 psMetadataAddImage (chip->analysis, PS_LIST_TAIL, "PTN.DEAD.CELL", PS_META_REPLACE, "", deadCellPattern); 415 416 // extract the MEDIAN_CELL_BACKGROUND values to check for problems 417 int numCells = chip->cells->n; // Number of cells 418 psVector *cellBackground = psVectorAllocEmpty (numCells, PS_DATA_F32); 419 420 pmCell *cell = NULL; 421 while ((cell = pmFPAviewNextCell(view, chip->parent, 1)) != NULL) { 422 if (!cell->process || !cell->file_exists || !cell->data_exists) { 423 psVectorAppend (cellBackground, NAN); 424 continue; 425 } 426 427 // select the HDU for this cell 428 pmHDU *cellHDU = pmHDUFromCell(cell); // HDU of interest 429 430 psF32 value = psMetadataLookupF32(&status, cellHDU->header, "BACK_VAL"); 431 if (!status) { 432 psVectorAppend (cellBackground, NAN); 433 continue; 434 } 435 psVectorAppend (cellBackground, value); 436 } 437 438 // match cellBackground pattern to registered patterns and mask as needed 439 if (!pmPatternDeadCells(chip, cellBackground, options->blankMask)) { 440 psFree(cellBackground); 441 psFree(view); 442 return false; 443 } 444 psFree(cellBackground); 445 psFree(view); 446 447 psMetadataAddBool(hdu->header, PS_LIST_TAIL, "PTRN_DED", PS_META_REPLACE, "PATTERN.DEADCELLS applied", true); 448 return true; 257 449 } 258 450 … … 327 519 } 328 520 521 psVector *ppImageDetrendPatternCellFailures(pmFPAfile *input, const pmFPAview *inputView) { 522 523 bool status = false; 524 pmCell *cell = NULL; 525 526 pmFPAview *view = pmFPAviewAlloc(0); // View for local processing 527 *view = *inputView; 528 529 // extract the MEDIAN_CELL_BACKGROUND values to check for problems 530 psVector *cellBackground = psVectorAllocEmpty (64, PS_DATA_F32); 531 while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) { 532 if (!cell->process || !cell->file_exists || !cell->data_exists) { 533 psVectorAppend (cellBackground, NAN); 534 continue; 535 } 536 537 // select the HDU for this cell 538 pmHDU *hdu = pmHDUFromCell(cell); // HDU of interest 539 540 psF32 value = psMetadataLookupF32(&status, hdu->header, "BACK_VAL"); 541 psVectorAppend (cellBackground, value); 542 } 543 return cellBackground; 544 } -
trunk/ppImage/src/ppImageDetrendReadout.c
r42340 r42382 63 63 // psLogMsg ("ppImage", 6, "check video: %f sec\n", psTimerMark ("detrend.readout")); 64 64 65 // XXX for GPC2, there are some bizzare cell levels that need to be filtered out 66 // Here I measure the median background before overscan subtraction, but an alternative 67 // is to use the overscan-subtracted image. 68 // XX if (0) { 69 // XX psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN); 70 // XX psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); 71 // XX psImageBackground (stats, NULL, input->image, NULL, 0xffff, rng); 72 // XX readoutBackground = stats->robustMedian; 73 // XX } 74 65 75 // Masking on the basis of pixel value needs to be done before anything else, so the values are pristine. 66 76 if (options->doMaskBuild) { … … 113 123 } 114 124 // psLogMsg ("ppImage", 6, "subtract overscan: %f sec\n", psTimerMark ("detrend.readout")); 125 } 126 127 // measure the overscan-subtracted readoutBackground here (or subtract the overscan value?) 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); 131 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); 132 psImageBackground (stats, NULL, input->image, NULL, 0xffff, rng); 133 134 // save this value somewhere 135 pmHDU *hdu = pmHDUFromReadout(input); // HDU of interest 136 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); 138 psFree (stats); 139 psFree (rng); 115 140 } 116 141 -
trunk/ppImage/src/ppImageLoop.c
r39501 r42382 172 172 173 173 // Apply the fringe correction 174 if (options->doFringe) { 175 if (!ppImageDetrendFringeApply(config, chip, view, options)) { 176 ESCAPE("Unable to defringe"); 177 } 174 if (!ppImageDetrendFringeApply(config, chip, view, options)) { 175 ESCAPE("Unable to defringe"); 178 176 } 179 177 … … 183 181 } 184 182 185 // Apply the pattern correction 186 if (options->doPatternRow || options->doPatternCell || options->doPatternContinuity) { 187 if (!ppImageDetrendPatternApply(config,chip,view,options)) { 188 ESCAPE("Unable to apply pattern corrections"); 189 } 183 // Apply the pattern correction (only done if requested) 184 if (!ppImageDetrendPatternApply(config,chip,view,options)) { 185 ESCAPE("Problem applying pattern corrections"); 190 186 } 191 187 -
trunk/ppImage/src/ppImageOptions.c
r42340 r42382 226 226 } 227 227 228 bool mdok; 228 229 int boxcar = psMetadataLookupS32(NULL, recipe, "OVERSCAN.BOXCAR"); 229 230 float gauss = psMetadataLookupF32(NULL, recipe, "OVERSCAN.GAUSS"); 231 float minValid = psMetadataLookupF32(&mdok, recipe, "OVERSCAN.MIN.VALID"); 232 if (!mdok) { minValid = 0.0; } 233 234 float maxValid = psMetadataLookupF32(&mdok, recipe, "OVERSCAN.MAX.VALID"); 235 if (!mdok) { maxValid = (float) 0x10000; } 230 236 231 237 // Fill in the options … … 235 241 options->overscan->constant = psMetadataLookupBool(NULL, recipe, "OVERSCAN.CONSTANT"); 236 242 options->overscan->value = psMetadataLookupF32(NULL, recipe, "OVERSCAN.VALUE"); 243 options->overscan->minValid = minValid; 244 options->overscan->maxValid = maxValid; 245 options->overscan->maskVal = 0x0001; 237 246 238 247 psFree(overscanStats); … … 290 299 options->doPatternCell = psMetadataLookupBool(NULL, recipe, "PATTERN.CELL"); 291 300 options->doPatternContinuity = psMetadataLookupBool(NULL, recipe, "PATTERN.CONTINUITY"); 301 options->doPatternDeadCells = psMetadataLookupBool(NULL, recipe, "PATTERN.DEAD.CELLS"); 292 302 293 303 options->doMaskStats = psMetadataLookupBool(NULL, recipe, "MASK.STATS"); -
trunk/ppImage/src/ppImageParseCamera.c
r42340 r42382 201 201 // an empty or invalid file may have been generated -- we want to skip, not raise an error 202 202 pmFPAfile *PRAfile = psMetadataLookupPtr (NULL, config->files, "PPIMAGE.PATTERN.ROW.AMP"); 203 if (PRAfile) { 204 PRAfile->state |= PM_FPA_STATE_INACTIVE; 205 } 206 } 207 } 208 if (options->doPatternDeadCells) { 209 if (!ppImageDefineFile(config, input->fpa, "PPIMAGE.PATTERN.DEAD.CELLS", "PATTERN.DEAD.CELLS", 210 PM_FPA_FILE_PATTERN_DEAD_CELLS, PM_DETREND_TYPE_PATTERN_DEAD_CELLS)) { 211 psWarning ("Can't find a pattern dead cells source"); 212 // an empty or invalid file may have been generated -- we want to skip, not raise an error 213 pmFPAfile *PRAfile = psMetadataLookupPtr (NULL, config->files, "PPIMAGE.PATTERN.DEAD.CELLS"); 203 214 if (PRAfile) { 204 215 PRAfile->state |= PM_FPA_STATE_INACTIVE; -
trunk/ppImage/src/ppImageRebinReadout.c
r37406 r42382 35 35 36 36 // run the rebin code 37 // XXX EAM 2022.04.21 : this function rebins the signal image and makes an attempt to 38 // generate a mask only with bits raised in masked pixels that have > 50% of input pixels masked. 39 // this step is very expensive because it must count the input mask bits for each pixel. 40 // What is particularly silly is that the mask is not even used in the jpeg image. 37 41 if (!pmReadoutRebin(outReadout, inReadout, options->maskValue, outFile->xBin, outFile->yBin)) { 38 42 psError(PS_ERR_UNKNOWN, false, "Unable to rebin readout."); -
trunk/ppImage/src/ppImageReplaceBackground.c
r41382 r42382 81 81 if (!modelFile || !modelRO) { 82 82 if (!psphotModelBackgroundReadoutFileIndex(config, &roView, "PPIMAGE.CHIP", 0)) { 83 psError(PS_ERR_UNKNOWN, false, "Unable to model background"); 84 return false; 83 int lastError = psErrorCodeLast(); 84 if (lastError == PSPHOT_ERR_DATA) { 85 // a data error in psphotModelBackground* means an empty or bad image: skip background subtraction 86 psErrorStackPrint(stderr, "Unable to model background"); 87 psErrorClear(); 88 return true; 89 } else { 90 psError(PS_ERR_UNKNOWN, false, "Unable to model background"); 91 return false; 92 } 85 93 } 86 94 // the model file should now at least be defined -
trunk/ppImage/src/ppImageSetMaskBits.c
r42293 r42382 79 79 options->blankMask = pmConfigMaskGet("BLANK", config); 80 80 psAssert (options->blankMask, "blank mask not set"); 81 if (options->overscan) { 82 options->overscan->maskVal = options->blankMask; 83 } 81 84 82 85 // mask for saturated data (default to RANGE if not defined)
Note:
See TracChangeset
for help on using the changeset viewer.
