Changeset 17227
- Timestamp:
- Mar 28, 2008, 5:08:31 PM (18 years ago)
- Location:
- trunk/ppMerge/src
- Files:
-
- 4 added
- 5 edited
-
Makefile.am (modified) (1 diff)
-
ppMerge.c (modified) (3 diffs)
-
ppMerge.h (modified) (1 diff)
-
ppMergeArguments.c (added)
-
ppMergeCamera.c (added)
-
ppMergeFiles.c (added)
-
ppMergeLoop.c (added)
-
ppMergeMask.c (modified) (2 diffs)
-
ppMergeScaleZero.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ppMerge/src/Makefile.am
r15937 r17227 6 6 ppMerge_SOURCES = \ 7 7 ppMerge.c \ 8 ppMergeCheckInputs.c \ 9 ppMergeCombine.c \ 10 ppMergeConfig.c \ 11 ppMergeData.c \ 12 ppMergeMask.c \ 13 ppMergeMaskSuspect.c \ 14 ppMergeMaskBad.c \ 15 ppMergeMaskWrite.c \ 16 ppMergeMaskGrow.c \ 17 ppMergeMaskAverageConcepts.c \ 18 ppMergeOptions.c \ 8 ppMergeArguments.c \ 9 ppMergeCamera.c \ 10 ppMergeFiles.c \ 19 11 ppMergeScaleZero.c \ 20 ppMergeVersion.c 12 ppMergeLoop.c \ 13 ppMergeMask.c 21 14 22 15 23 16 noinst_HEADERS = \ 24 ppMerge.h \ 25 ppMergeCheckInputs.h \ 26 ppMergeCombine.h \ 27 ppMergeConfig.h \ 28 ppMergeData.h \ 29 ppMergeMask.h \ 30 ppMergeOptions.h \ 31 ppMergeScaleZero.h \ 32 ppMergeVersion.h 17 ppMerge.h 33 18 34 19 CLEANFILES = *~ -
trunk/ppMerge/src/ppMerge.c
r15631 r17227 4 4 5 5 #include <stdio.h> 6 #include <string.h> 6 7 #include <pslib.h> 7 8 #include <psmodules.h> 8 9 9 10 #include "ppMerge.h" 10 #include "ppMergeConfig.h"11 #include "ppMergeData.h"12 #include "ppMergeOptions.h"13 #include "ppMergeCheckInputs.h"14 #include "ppMergeCombine.h"15 #include "ppMergeScaleZero.h"16 #include "ppMergeMask.h"17 11 18 12 //#include "ppMem.h" … … 27 21 { 28 22 psLibInit(NULL); 29 psMemSetThreadSafety(false); // Turn off thread safety, for more23 psMemSetThreadSafety(false); 30 24 psTimerStart(TIMERNAME); 31 25 32 // Parse the configuration and arguments 33 // Open the input image(s) 34 // Determine camera, format from header if not already defined 35 // Construct camera in preparation for reading 36 pmConfig *config = ppMergeConfig(argc, argv); 26 psExit exitValue = PS_EXIT_SUCCESS; // Exit value for program 27 28 pmConfig *config = pmConfigRead(&argc, argv, PPMERGE_RECIPE); // Configuration 37 29 if (!config) { 38 psErrorStackPrint(stderr, "Unable to get configuration."); 39 exit(EXIT_FAILURE); 30 psErrorStackPrint(stderr, "Error reading configuration."); 31 exitValue = PS_EXIT_CONFIG_ERROR; 32 goto die; 40 33 } 41 34 35 if (!ppMergeArguments(argc, argv, config)) { 36 psErrorStackPrint(stderr, "Error reading arguments."); 37 exitValue = PS_EXIT_CONFIG_ERROR; 38 goto die; 39 } 40 41 ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of frame 42 switch (type) { 43 case PPMERGE_TYPE_MASK: 44 if (!ppMergeMask(config)) { 45 psErrorStackPrint(stderr, "Error generating mask."); 46 exitValue = PS_EXIT_DATA_ERROR; 47 goto die; 48 } 49 break; 50 case PPMERGE_TYPE_BIAS: 51 case PPMERGE_TYPE_DARK: 52 case PPMERGE_TYPE_SHUTTER: 53 case PPMERGE_TYPE_FLAT: 54 case PPMERGE_TYPE_FRINGE: 55 if (!ppMergeScaleZero(config)) { 56 psErrorStackPrint(stderr, "Error getting scale and zero-points."); 57 exitValue = PS_EXIT_DATA_ERROR; 58 goto die; 59 } 60 if (!ppMergeLoop(config)) { 61 psErrorStackPrint(stderr, "Error performing merge."); 62 exitValue = PS_EXIT_PROG_ERROR; 63 goto die; 64 } 65 break; 66 default: 67 psAbort("Invalid frame type: %x", type); 68 } 69 70 71 // Output the statistics 72 bool mdok; // Status of MD lookup 73 psString statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS.NAME"); // Statistics file name 74 if (mdok && statsName && strlen(statsName) > 0) { 75 psString resolved = pmConfigConvertFilename(statsName, config, true); // Resolved filename 76 FILE *statsFile = fopen(resolved, "w"); // Output statistics file 77 if (!statsFile) { 78 psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.", resolved); 79 psFree(resolved); 80 exitValue = PS_EXIT_CONFIG_ERROR; 81 goto die; 82 } 83 psFree(resolved); 84 psMetadata *stats = psMetadataLookupMetadata(&mdok, config->arguments, "STATS.DATA"); // Statistics 85 if (!stats) { 86 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find statistics"); 87 exitValue = PS_EXIT_PROG_ERROR; 88 goto die; 89 } 90 psString statsOut = psMetadataConfigFormat(stats); // String to write out 91 fprintf(statsFile, "%s", statsOut); 92 psFree(statsOut); 93 fclose(statsFile); 94 } 95 96 97 98 99 #if 0 42 100 // Set various tasks (define optional operations) 43 101 ppMergeOptions *options = ppMergeOptionsParse(config); … … 81 139 } 82 140 83 #if 084 pmFPAPrint(stdout, data->out, true, true);85 #endif86 87 141 // Cleaning up 88 142 psFree(data); 89 143 psFree(options); 144 #endif 145 146 die: 147 psTrace("ppSub", 1, "Finished at %f sec\n", psTimerMark("ppSub")); 148 psTimerStop(); 149 90 150 psFree(config); 91 92 pmConceptsDone();93 151 pmConfigDone(); 94 152 psLibFinalize(); 95 153 96 // ppMemCheck(); 97 98 return EXIT_SUCCESS; 154 exit(exitValue); 99 155 } -
trunk/ppMerge/src/ppMerge.h
r8405 r17227 2 2 #define PP_MERGE_H 3 3 4 #define TIMERNAME "ppMerge" 5 #define PPMERGE_RECIPE "PPMERGE" 4 #define TIMERNAME "ppMerge" // Name for timer 5 #define PPMERGE_RECIPE "PPMERGE" // Recipe name 6 7 // Type of frame to merge 8 typedef enum { 9 PPMERGE_TYPE_UNKNOWN, // Unknown type 10 PPMERGE_TYPE_BIAS, // Bias frame 11 PPMERGE_TYPE_DARK, // (Multi-)Dark frame 12 PPMERGE_TYPE_MASK, // Mask frame 13 PPMERGE_TYPE_SHUTTER, // Shutter frame 14 PPMERGE_TYPE_FLAT, // Flat-field frame (dome or sky) 15 PPMERGE_TYPE_FRINGE, // Fringe frame 16 } ppMergeType; 17 18 // Files, for activation 19 typedef enum { 20 PPMERGE_FILES_ALL, // All files 21 PPMERGE_FILES_INPUT, // Input files 22 PPMERGE_FILES_OUTPUT // Output files 23 } ppMergeFiles; 24 25 // Parse command-line arguments and recipe 26 bool ppMergeArguments(int argc, char *argv[], // Command-line arguments 27 pmConfig *config // Configuration 28 ); 29 30 // Set up camera files 31 bool ppMergeCamera(pmConfig *config // Configuration 32 ); 33 34 // Measure scale and zero-points 35 bool ppMergeScaleZero(pmConfig *config // Configuration 36 ); 37 38 // Main loop to do the merging 39 bool ppMergeLoop(pmConfig *config // Configuration 40 ); 41 42 // Main loop for masks 43 bool ppMergeMask(pmConfig *config // Configuration 44 ); 45 46 // Read nominated input file 47 bool ppMergeFileReadInput(const pmConfig *config, // Configuration 48 pmReadout *readout, // Readout into which to read 49 int num, // Number of file in sequence 50 int rows // Number of rows to read at once 51 ); 52 53 // Open nominated input file 54 bool ppMergeFileOpenInput(pmConfig *config, // Configuration 55 const pmFPAview *view, // View to open 56 int num // Number of file in sequence 57 ); 58 59 // Set the data level for files specified by name; return an array of the files 60 psArray *ppMergeFileDataLevel(const pmConfig *config, // Configuration 61 const char *name, // Name of files 62 pmFPALevel level // Level for file data level 63 ); 64 65 // Activate/deactivate a list of files 66 bool ppMergeFileActivate(const pmConfig *config, // Configuration 67 ppMergeFiles files, // Files to turn on/off 68 bool state // Activation state 69 ); 70 71 // Activate/deactivate a single element for a list; return array of files 72 psArray *ppMergeFileActivateSingle(const pmConfig *config, // Configuration 73 ppMergeFiles files, // Files to turn on/off 74 bool state, // Activation state 75 int num // Number of file in sequence 76 ); 77 78 // Return name of output pmFPAfile 79 psString ppMergeOutputFile(const pmConfig *config // Configuration 80 ); 6 81 7 82 #endif -
trunk/ppMerge/src/ppMergeMask.c
r15937 r17227 5 5 #include <stdio.h> 6 6 #include <string.h> 7 #include <unistd.h>8 7 #include <assert.h> 8 9 9 #include <pslib.h> 10 10 #include <psmodules.h> … … 12 12 13 13 #include "ppMerge.h" 14 #include "ppMergeData.h" 15 #include "ppMergeMask.h" 16 17 18 // Generate a mask 19 bool ppMergeMask(ppMergeData *data, // Data 20 ppMergeOptions *options, // Options 21 pmConfig *config // Configuration 22 ) 14 15 static bool mergeMask(pmConfig *config, // Configuration 16 const pmFPAview *view, // View to chip 17 bool writeOut, // Write output? 18 psRandom *rng, // Random number generator 19 psMetadata *stats // Statistics output 20 ) 23 21 { 24 for (int i = 0; i < 2; i++) { 25 if (!ppMergeMaskSuspect (data, options, config)) { 26 psError(PS_ERR_UNKNOWN, true, "failed on mask suspect.\n"); 27 return false; 28 } 29 30 if (!ppMergeMaskBad (data, options, config)) { 31 psError(PS_ERR_UNKNOWN, true, "failed on mask bad.\n"); 32 return false; 33 } 34 } 35 36 if (!ppMergeMaskAverageConcepts (data, options, config)) { 37 psError(PS_ERR_UNKNOWN, true, "failed on average concepts.\n"); 38 return false; 39 } 40 41 if (!ppMergeMaskGrow (data, options, config)) { 42 psError(PS_ERR_UNKNOWN, true, "failed on mask grow.\n"); 43 return false; 44 } 45 46 if (!ppMergeMaskWrite (data, options, config)) { 47 psError(PS_ERR_UNKNOWN, true, "failed on mask write.\n"); 48 return false; 49 } 22 assert(config); 23 assert(view); 24 assert(view->chip != -1 && view->cell == -1 && view->readout == -1); 25 26 bool mdok; // Status of MD lookup 27 int numFiles = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of input files 28 psStatsOptions meanStat = psMetadataLookupS32(NULL, config->arguments, "MEAN"); // Statistic for mean 29 psStatsOptions stdevStat = psMetadataLookupS32(NULL, config->arguments, "STDEV"); // Statistic for stdev 30 psMaskType maskVal = psMetadataLookupU8(NULL, config->arguments, "MASKVAL"); // Value to mask 31 int sample = psMetadataLookupS32(NULL, config->arguments, "SAMPLE"); // Size of sample for statistics 32 bool chipStats = psMetadataLookupBool(&mdok, config->arguments, "MASK.CHIPSTATS"); // Statistics on chip? 33 float maskSuspect = psMetadataLookupF32(NULL, config->arguments, "MASK.SUSPECT"); // Threshold for suspect pixels 34 float maskBad = psMetadataLookupF32(NULL, config->arguments, "MASK.BAD"); // Threshold for bad pixels 35 pmMaskIdentifyMode maskMode = psMetadataLookupS32(NULL, config->arguments, "MASK.MODE"); // Mode for identifying bad pixels 36 int maskGrow = psMetadataLookupS32(NULL, config->arguments, "MASK.GROW"); // Radius to grow mask 37 psMaskType maskGrowVal = psMetadataLookupU8(NULL, config->arguments, "MASK.GROWVAL"); // Value for grown mask 38 39 psStats *statistics = psStatsAlloc(meanStat | stdevStat); // Statistics for background 40 41 psString outName = ppMergeOutputFile(config); // Name of output file 42 pmChip *outChip = pmFPAfileThisChip(config->files, view, outName); // Output chip 43 psFree(outName); 44 45 // For each input file, get the statistics, which can be calculated at the chip or cell levels 46 psVector *values = psVectorAlloc(sample, PS_TYPE_F32); // Pixel values for statistics 47 pmFPAview *inView = pmFPAviewAlloc(0); // View for input 48 for (int i = 0; i < numFiles; i++) { 49 pmFPAfileActivate(config->files, false, NULL); 50 psArray *files = ppMergeFileActivateSingle(config, PPMERGE_FILES_INPUT, true, i); // Input files 51 pmFPAfile *input = files->data[0]; // Input file 52 psFree(files); 53 pmFPA *inFPA = input->fpa; // Input FPA 54 *inView = *view; 55 56 int valueIndex = 0; // Index for vector of pixel values 57 58 pmCell *inCell; // Input cell 59 while ((inCell = pmFPAviewNextCell(inView, inFPA, 1))) { 60 pmHDU *hdu = pmHDUFromCell(inCell); // HDU for cell 61 if (!hdu || hdu->blankPHU) { 62 // No data here 63 continue; 64 } 65 psTrace("ppMerge", 1, "Getting suspect pixels for file %d chip %d cell %d", 66 i, inView->chip, inView->cell); 67 68 if (!pmFPAfileIOChecks(config, inView, PM_FPA_BEFORE)) { 69 psFree(inView); 70 goto MERGE_MASK_ERROR; 71 } 72 73 if (!ppMergeFileOpenInput(config, view, i)) { 74 psError(PS_ERR_UNKNOWN, false, "Unable to open file %d", i); 75 psFree(inView); 76 goto MERGE_MASK_ERROR; 77 } 78 79 if (inCell->readouts->n > 1) { 80 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 81 "File %d chip %d cell %d contains more than one readout (%ld)", 82 i, inView->chip, inView->cell, inCell->readouts->n); 83 psFree(inView); 84 goto MERGE_MASK_ERROR; 85 } 86 87 pmReadout *readout; 88 if (inCell->readouts && inCell->readouts->n == 1) { 89 readout = psMemIncrRefCounter(inCell->readouts->data[0]); // Input readout 90 } else { 91 readout = pmReadoutAlloc(inCell); 92 } 93 94 if (!ppMergeFileReadInput(config, readout, i, 0)) { 95 psError(PS_ERR_UNKNOWN, false, "Unable to read readout %d", i); 96 psFree(inView); 97 psFree(readout); 98 goto MERGE_MASK_ERROR; 99 } 100 101 pmCell *outCell = pmFPAfileThisCell(config->files, inView, "PPMERGE.OUTPUT.MASK"); // Output cell 102 pmReadout *outRO = NULL; // Output readout 103 if (outCell->readouts && outCell->readouts->n == 1) { 104 outRO = psMemIncrRefCounter(outCell->readouts->data[0]); 105 } else { 106 outRO = pmReadoutAlloc(outCell); 107 } 108 psImage *outMask = outRO->mask; // Output mask image (for iterative generation of mask) 109 110 psImage *image = readout->image, *mask = readout->mask; // Image and mask 111 int numCols = readout->image->numCols, numRows = readout->image->numRows; // Image size 112 int numPix = numCols * numRows; // Number of pixels 113 int numCells = chipStats ? readout->parent->parent->cells->n : 1; // Number of cells 114 int num = PS_MIN(numPix, sample / numCells); // Number of values to add 115 if (!chipStats) { 116 valueIndex = 0; 117 } 118 for (int i = 0; i < num; i++) { 119 int pixel = numPix * psRandomUniform(rng); 120 int x = pixel % numCols; 121 int y = pixel / numCols; 122 if ((mask && (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal)) || 123 !isfinite(image->data.F32[y][x]) || 124 (outMask && (outMask->data.PS_TYPE_MASK_DATA[y][x] & maskVal))) { 125 continue; 126 } 127 128 values->data.F32[valueIndex++] = image->data.F32[y][x]; 129 } 130 131 if (!chipStats) { 132 values->n = valueIndex; 133 if (!psVectorStats(statistics, values, NULL, NULL, 0)) { 134 psError(PS_ERR_UNKNOWN, false, "Unable to do statistics on readout."); 135 psFree(inView); 136 psFree(readout); 137 goto MERGE_MASK_ERROR; 138 } 139 140 if (!pmMaskFlagSuspectPixels(outRO, readout, psStatsGetValue(statistics, meanStat), 141 psStatsGetValue(statistics, stdevStat), maskSuspect, maskVal)) { 142 psError(PS_ERR_UNKNOWN, false, "Unable to find suspect values in file %d", i); 143 psFree(inView); 144 psFree(readout); 145 goto MERGE_MASK_ERROR; 146 } 147 pmCellFreeData(inCell); 148 149 if (!pmFPAfileIOChecks(config, inView, PM_FPA_AFTER)) { 150 psFree(inView); 151 psFree(readout); 152 goto MERGE_MASK_ERROR; 153 } 154 } 155 psFree(readout); 156 psFree(outRO); 157 } 158 159 // Additional run through cells if we want chip-level statistics 160 if (chipStats && valueIndex > 0) { 161 values->n = valueIndex; 162 if (!psVectorStats(statistics, values, NULL, NULL, 0)) { 163 psError(PS_ERR_UNKNOWN, false, "Unable to do statistics on chip."); 164 goto MERGE_MASK_ERROR; 165 } 166 inView->cell = -1; 167 while ((inCell = pmFPAviewNextCell(inView, inFPA, 1))) { 168 pmHDU *hdu = pmHDUFromCell(inCell); // HDU for cell 169 if (!hdu || hdu->blankPHU) { 170 // No data here 171 continue; 172 } 173 pmReadout *readout = inCell->readouts->data[0]; // Readout of interest 174 175 inView->readout = 0; 176 pmReadout *outRO = pmFPAfileThisReadout(config->files, inView, "PPMERGE.OUTPUT.MASK"); 177 178 if (!pmMaskFlagSuspectPixels(outRO, readout, psStatsGetValue(statistics, meanStat), 179 psStatsGetValue(statistics, stdevStat), maskSuspect, maskVal)) { 180 psError(PS_ERR_UNKNOWN, false, "Unable to find suspect values in file %d", i); 181 goto MERGE_MASK_ERROR; 182 } 183 pmCellFreeData(inCell); 184 185 inView->readout = -1; 186 if (!pmFPAfileIOChecks(config, inView, PM_FPA_AFTER)) { 187 psFree(inView); 188 goto MERGE_MASK_ERROR; 189 } 190 } 191 } 192 } 193 psFree(inView); 194 psFree(statistics); statistics = NULL; 195 psFree(values); values = NULL; 196 197 198 // Another run through the chip to threshold on the suspects 199 pmFPAfileActivate(config->files, false, NULL); 200 if (writeOut) { 201 ppMergeFileActivate(config, PPMERGE_FILES_OUTPUT, true); 202 } 203 pmFPA *outFPA = outChip->parent; // Output FPA 204 pmCell *outCell; // Output cell 205 pmFPAview *outView = pmFPAviewAlloc(0); // View into output FPA 206 *outView = *view; 207 while ((outCell = pmFPAviewNextCell(outView, outFPA, 1))) { 208 pmHDU *hdu = pmHDUFromCell(outCell); // HDU for cell 209 if (!hdu || hdu->blankPHU) { 210 // No data here 211 continue; 212 } 213 214 psTrace("ppMerge", 1, "Getting bad pixels for chip %d cell %d", outView->chip, outView->cell); 215 216 assert(outCell->readouts && outCell->readouts->n == 1); 217 pmReadout *outRO = outCell->readouts->data[0]; // Output readout 218 if (!pmMaskIdentifyBadPixels(outRO, maskVal, maskBad, maskMode)) { 219 psError(PS_ERR_UNKNOWN, false, "Unable to mask bad pixels"); 220 goto MERGE_MASK_ERROR; 221 } 222 223 // Supplementary outputs 224 { 225 // The counts image is fairly useless, but it preserves the model 226 pmCell *countsCell = pmFPAfileThisCell(config->files, outView, "PPMERGE.OUTPUT.COUNT"); 227 pmReadout *countsRO = pmReadoutAlloc(countsCell); // Readout with count of inputs per pixel 228 countsRO->image = psImageAlloc(outRO->mask->numCols, outRO->mask->numRows, PS_TYPE_F32); 229 psImageInit(countsRO->image, numFiles); 230 countsRO->data_exists = countsCell->data_exists = countsCell->parent->data_exists = true; 231 psFree(countsRO); 232 233 pmCell *sigmaCell = pmFPAfileThisCell(config->files, outView, "PPMERGE.OUTPUT.SIGMA"); 234 pmReadout *sigmaRO = pmReadoutAlloc(sigmaCell); // Readout with suspect image 235 psImage *suspect = psMetadataLookupPtr(NULL, outRO->analysis, PM_MASK_ANALYSIS_SUSPECT); 236 sigmaRO->image = psImageCopy(sigmaRO->image, suspect, PS_TYPE_F32); 237 psMetadataRemoveKey(outRO->analysis, PM_MASK_ANALYSIS_SUSPECT); 238 sigmaRO->data_exists = sigmaCell->data_exists = sigmaCell->parent->data_exists = true; 239 psFree(sigmaRO); 240 } 241 242 if (maskGrowVal > 0) { 243 psImage *grown = psImageGrowMask(NULL, outRO->mask, maskVal, maskGrow, maskGrowVal); // Grown mask 244 psFree(outRO->mask); 245 outRO->mask = grown; 246 } 247 248 if (writeOut) { 249 if (!pmFPAfileIOChecks(config, outView, PM_FPA_BEFORE)) { 250 psFree(outView); 251 goto MERGE_MASK_ERROR; 252 } 253 254 outRO->data_exists = outCell->data_exists = outChip->data_exists = true; 255 256 // Average concepts 257 psList *cells = psListAlloc(NULL); // List of cells, for concept averaging 258 for (int i = 0; i < numFiles; i++) { 259 pmFPAfile *inFile = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i); // Input file 260 pmCell *inCell = pmFPAviewThisCell(outView, inFile->fpa); // Input cell 261 psListAdd(cells, PS_LIST_TAIL, inCell); 262 } 263 if (!pmConceptsAverageCells(outCell, cells, NULL, NULL, true)) { 264 psError(PS_ERR_UNKNOWN, false, "Unable to average cell concepts."); 265 psFree(cells); 266 psFree(outRO); 267 psFree(outView); 268 return false; 269 } 270 psFree(cells); 271 272 // Statistics on the merged cell using a fake image 273 outRO->image = psImageAlloc(outRO->mask->numCols, outRO->mask->numRows, PS_TYPE_F32); 274 psImageInit(outRO->image, 1.0); 275 if (!ppStatsFPA(stats, outRO->parent->parent->parent, outView, 276 maskVal | pmConfigMask("BLANK", config), config)) { 277 psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to generate stats for image."); 278 psFree(outRO); 279 psFree(outView); 280 return false; 281 } 282 psFree(outRO->image); 283 outRO->image = NULL; 284 285 // Write 286 if (!pmFPAfileIOChecks(config, outView, PM_FPA_AFTER)) { 287 psFree(outView); 288 goto MERGE_MASK_ERROR; 289 } 290 } 291 } 292 psFree(outView); 293 294 ppMergeFileActivate(config, PPMERGE_FILES_ALL, true); 50 295 51 296 return true; 297 298 299 MERGE_MASK_ERROR: 300 psFree(statistics); 301 psFree(values); 302 return false; 52 303 } 53 304 54 bool ppMergeMaskReadoutStats(const pmReadout *readout, 55 const pmReadout *output, 56 ppMergeOptions *options, // Options 57 psRandom *rng) 305 306 307 308 309 bool ppMergeMask(pmConfig *config) 58 310 { 59 PS_ASSERT_PTR_NON_NULL(readout, false); 60 PS_ASSERT_IMAGE_NON_NULL(readout->image, false); 61 PS_ASSERT_IMAGE_NON_EMPTY(readout->image, false); 62 PS_ASSERT_IMAGE_TYPE(readout->image, PS_TYPE_F32, false); 63 if (readout->mask) { 64 PS_ASSERT_IMAGE_NON_EMPTY(readout->mask, false); 65 PS_ASSERT_IMAGES_SIZE_EQUAL(readout->image, readout->mask, false); 66 PS_ASSERT_IMAGE_TYPE(readout->mask, PS_TYPE_MASK, false); 67 } 68 69 psImage *mask = NULL; 70 psImage *image = readout->image; // Image of interest 71 72 if (output) { 73 mask = output->mask; // Corresponding mask 74 } 75 76 if (rng) { 77 psMemIncrRefCounter(rng); 78 } else { 79 rng = psRandomAlloc(PS_RANDOM_TAUS, 0); 80 } 81 82 // XXX note that this now will accept any of several stats options 83 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); 84 stats->nSubsample = options->sample; 85 86 if (!psImageBackground(stats, NULL, image, mask, options->combine->maskVal, rng)) { 87 psError(PS_ERR_UNKNOWN, false, "Failure to measure image statistics.\n"); 88 psFree(stats); 89 psFree(rng); 90 return false; 91 } 92 if (!isfinite(stats->robustMedian) || !isfinite(stats->robustUQ) || !isfinite(stats->robustLQ)) { 93 psError(PS_ERR_UNKNOWN, false, "invalide image statistics (nan).\n"); 94 psFree(stats); 95 psFree(rng); 96 return false; 97 } 98 99 psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "READOUT.MEDIAN", PS_META_REPLACE, "image stats", stats->robustMedian); 100 psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "READOUT.STDEV", PS_META_REPLACE, "image stats", stats->robustStdev); 101 311 assert(config); 312 313 bool mdok; // Status of MD lookup 314 int numFiles = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of inputs 315 bool haveMasks = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.MASKS"); // Do we have masks? 316 bool haveWeights = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.WEIGHTS"); // Do we have weights? 317 int iter = psMetadataLookupS32(NULL, config->arguments, "ITER"); // Number of rejection iterations 318 319 PS_ASSERT_INT_POSITIVE(iter, false); 320 321 pmFPAview *view = pmFPAviewAlloc(0); // View to component of interest 322 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator 323 324 psMetadata *stats = NULL; // Statistics for output 325 if (psMetadataLookup(config->arguments, "STATS.NAME")) { 326 stats = psMetadataAlloc(); 327 psMetadataAddMetadata(config->arguments, PS_LIST_TAIL, "STATS.DATA", 0, "Statistics output", stats); 328 } 329 330 psArray *inputs = ppMergeFileDataLevel(config, "PPMERGE.INPUT", PM_FPA_LEVEL_READOUT); // Input images 331 psFree(inputs); 332 if (haveMasks) { 333 psArray *masks = ppMergeFileDataLevel(config, "PPMERGE.INPUT.MASK", PM_FPA_LEVEL_READOUT); 334 psFree(masks); 335 } 336 if (haveWeights) { 337 psArray *weights = ppMergeFileDataLevel(config, "PPMERGE.INPUT.WEIGHT", PM_FPA_LEVEL_READOUT); 338 psFree(weights); 339 } 340 341 if (!ppMergeFileActivate(config, PPMERGE_FILES_INPUT, true)) { 342 psError(PS_ERR_UNKNOWN, false, "Unable to activate files."); 343 goto PPMERGE_MASK_ERROR; 344 } 345 if (!ppMergeFileActivate(config, PPMERGE_FILES_OUTPUT, true)) { 346 psError(PS_ERR_UNKNOWN, false, "Unable to activate files."); 347 goto PPMERGE_MASK_ERROR; 348 } 349 350 psString outName = ppMergeOutputFile(config); // Name of output file 351 pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, outName); // Output file 352 psFree(outName); 353 assert(output && output->fpa); 354 pmFPA *outFPA = output->fpa; // Output FPA 355 356 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) { 357 goto PPMERGE_MASK_ERROR; 358 } 359 pmChip *outChip; // Chip of interest 360 while ((outChip = pmFPAviewNextChip(view, outFPA, 1))) { 361 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) { 362 goto PPMERGE_MASK_ERROR; 363 } 364 365 for (int i = 0; i < iter; i++) { 366 if (!mergeMask(config, view, (i == iter - 1), rng, stats)) { 367 psError(PS_ERR_UNKNOWN, false, "Unable to merge chip %d", view->chip); 368 goto PPMERGE_MASK_ERROR; 369 } 370 } 371 372 if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) { 373 goto PPMERGE_MASK_ERROR; 374 } 375 } 376 377 psList *fpaList = psListAlloc(NULL);// List of FPAs for concept averaging 378 for (int i = 0; i < numFiles; i++) { 379 pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i); // Input file 380 psListAdd(fpaList, PS_LIST_TAIL, file->fpa); 381 } 382 if (!pmConceptsAverageFPAs(outFPA, fpaList)) { 383 psError(PS_ERR_UNKNOWN, false, "Unable to average FPA concepts."); 384 psFree(fpaList); 385 goto PPMERGE_MASK_ERROR; 386 } 387 psFree(fpaList); 388 389 if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) { 390 goto PPMERGE_MASK_ERROR; 391 } 392 393 psFree(stats); 394 psFree(view); 102 395 psFree(rng); 396 103 397 return true; 398 399 PPMERGE_MASK_ERROR: 400 psFree(stats); 401 psFree(view); 402 psFree(rng); 403 return false; 104 404 } 105 405 106 bool ppMergeMaskChipStats (const pmChip *chip,107 const pmChip *output,108 ppMergeOptions *options,109 psRandom *rng)110 {111 PS_ASSERT_PTR_NON_NULL(chip, false);112 113 // XXX note that this now will accept any of several stats options114 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);115 116 if (rng) {117 psMemIncrRefCounter(rng);118 } else {119 rng = psRandomAlloc(PS_RANDOM_TAUS, 0);120 }121 122 // accumulate a vector of data values using options->sample per readout123 psVector *values = psVectorAllocEmpty(options->sample, PS_TYPE_F32); // Vector containing subsample124 125 for (int nCell = 0; nCell < chip->cells->n; nCell++) {126 pmCell *cell = chip->cells->data[nCell];127 if (cell->readouts->n == 0) continue;128 129 for (int nReadout = 0; nReadout < cell->readouts->n; nReadout++) {130 pmReadout *readout = cell->readouts->data[nReadout];131 if (!readout->image) continue;132 133 psTrace("ppMerge", 4, "Measure statistics for cell %d, readout %d\n", nCell, nReadout);134 135 psImage *image = readout->image; // Image of interest136 137 pmCell *cellOutput = output->cells->data[nCell];138 pmReadout *readoutOutput = NULL;139 psImage *mask = NULL;140 if (cellOutput->readouts->n > 0) {141 readoutOutput = cellOutput->readouts->data[0];142 mask = readoutOutput->mask; // Corresponding mask143 }144 145 // Size of image146 long nx = image->numCols;147 long ny = image->numRows;148 const int Npixels = nx*ny; // Total number of pixels149 const int Nsubset = PS_MIN(options->sample, Npixels); // Number of pixels in subset150 151 values = psVectorRealloc (values, values->n + Nsubset); // make sure we have enough space152 153 // select a subset of the image pixels to measure the stats154 for (long i = 0; i < Nsubset; i++) {155 double frnd = psRandomUniform(rng);156 int pixel = Npixels * frnd;157 int ix = pixel % nx;158 int iy = pixel / nx;159 160 if (!isfinite(image->data.F32[iy][ix])) continue;161 if (mask && (mask->data.U8[iy][ix] & options->combine->maskVal)) continue;162 163 float value = image->data.F32[iy][ix];164 values->data.F32[values->n] = value;165 values->n ++;166 }167 }168 }169 170 // no valid data, skip the chip171 if (!values->n) {172 psFree(values);173 psFree(stats);174 psFree(rng);175 return true;176 }177 178 // calculate the statistics179 if (!psVectorStats (stats, values, NULL, NULL, 0)) {180 psError(PS_ERR_UNKNOWN, false, "Unable to measure statistics for chip");181 psFree(values);182 psFree(stats);183 psFree(rng);184 return false;185 }186 if (!isfinite(stats->robustMedian) || !isfinite(stats->robustUQ) || !isfinite(stats->robustLQ)) {187 psError(PS_ERR_UNKNOWN, false, "invalid image statistics (nan).\n");188 psFree(values);189 psFree(stats);190 psFree(rng);191 return false;192 }193 194 // supply the stats to the readout analysis metadata195 for (int nCell = 0; nCell < chip->cells->n; nCell++) {196 pmCell *cell = chip->cells->data[nCell];197 if (cell->readouts->n == 0) continue;198 199 for (int nReadout = 0; nReadout < cell->readouts->n; nReadout++) {200 pmReadout *readout = cell->readouts->data[nReadout];201 if (!readout->image) continue;202 203 psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "READOUT.MEDIAN", PS_META_REPLACE, "image stats", stats->robustMedian);204 psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "READOUT.STDEV", PS_META_REPLACE, "image stats", stats->robustStdev);205 }206 }207 208 psLogMsg ("ppMerge", PS_LOG_INFO, "statistics for chip: %f +/- %f\n", stats->robustMedian, stats->robustStdev);209 210 psFree(values);211 psFree(stats);212 psFree(rng);213 return true;214 } -
trunk/ppMerge/src/ppMergeScaleZero.c
r16842 r17227 10 10 11 11 #include "ppMerge.h" 12 #include "ppMergeScaleZero.h"13 12 14 13 // Get the scale and zero for each chip of each input 15 bool ppMergeScaleZero(psImage **scales, // The scales for each integration/cell 16 psImage **zeros, // The zeroes for each integration/cell 17 psArray **shutters, // The shutter correction data for each cell 18 ppMergeData *data,// The data 19 const ppMergeOptions *options, // The options 20 const pmConfig *config // The configuration 21 ) 14 bool ppMergeScaleZero(pmConfig *config) 22 15 { 23 assert(data);24 assert(options);25 16 assert(config); 26 17 27 if (!options->scale && !options->zero && !options->shutter) { 28 return true; // We did everything we were asked for 18 ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of frame 19 int numInputs = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of inputs 20 int numCells = psMetadataLookupS32(NULL, config->arguments, "INPUTS.CELLS"); // Number of cells 21 psStatsOptions meanStat = psMetadataLookupS32(NULL, config->arguments, "MEAN"); // Statistic for mean 22 psStatsOptions stdevStat = psMetadataLookupS32(NULL, config->arguments, "STDEV"); // Statistic for stdev 23 psMaskType maskVal = psMetadataLookupU8(NULL, config->arguments, "MASKVAL"); // Value to mask 24 int shutterSize = psMetadataLookupS32(NULL, config->arguments, "SHUTTER.SIZE"); // Size of shutter region 25 26 psVector *gains = NULL; // Gains for each cell 27 psArray *shutters = NULL; // Shutter data for each cell 28 psStats *stats = NULL; // Statistics for background 29 psImage *background = NULL; // Background measurements per cell per file 30 31 switch (type) { 32 case PPMERGE_TYPE_BIAS: 33 case PPMERGE_TYPE_DARK: 34 // Nothing to measure 35 return true; 36 case PPMERGE_TYPE_FLAT: 37 case PPMERGE_TYPE_FRINGE: 38 gains = psVectorAlloc(numCells, PS_TYPE_F32); 39 background = psImageAlloc(numCells, numInputs, PS_TYPE_F32); 40 psImageInit(background, NAN); 41 stats = psStatsAlloc(meanStat); 42 break; 43 case PPMERGE_TYPE_SHUTTER: 44 shutters = psArrayAlloc(numCells); 45 break; 46 case PPMERGE_TYPE_MASK: 47 default: 48 break; 29 49 } 30 31 assert(config->camera); // Need the camera configuration 32 assert(config->arguments); // Need the list of files 33 34 psArray *filenames = psMetadataLookupPtr(NULL, config->arguments, "INPUT"); // The input file names 35 assert(filenames); // It should be here --- it's put here in ppMergeConfig 36 37 // Sanity checks 38 assert(!options->scale || scales); 39 assert(!scales || !*scales || ((*scales)->type.type == PS_TYPE_F32 && 40 (*scales)->numCols == data->numCells && 41 (*scales)->numRows == filenames->n)); 42 assert(!options->zero || zeros); 43 assert(!zeros || !*zeros || ((*zeros)->type.type == PS_TYPE_F32 && 44 (*zeros)->numCols == data->numCells && 45 (*zeros)->numRows == filenames->n)); 46 assert(!options->shutter || shutters); 47 assert(!shutters || !*shutters || (*shutters)->n == data->numCells); 48 49 // Allocate the outputs 50 if (options->scale) { 51 if (*scales) { 52 psFree(*scales); 53 } 54 *scales = psImageAlloc(data->numCells, filenames->n, PS_TYPE_F32); 50 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator 51 pmFPAview *view = NULL; // View into FPA 52 53 for (int i = 0; i < numInputs; i++) { 54 pmFPAfileActivate(config->files, false, NULL); 55 psArray *files = ppMergeFileActivateSingle(config, PPMERGE_FILES_INPUT, true, i); // Activated files 56 pmFPAfile *input = files->data[0]; // Representative file; should be the image (not mask or weight) 57 pmFPA *fpa = input->fpa; // FPA of interest 58 view = pmFPAviewAlloc(0); // View to component of interest 59 int cellNum = 0; // Index for cell 60 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) { 61 goto ERROR; 62 } 63 pmChip *chip; // Chip of interest 64 while ((chip = pmFPAviewNextChip(view, fpa, 1))) { 65 if (!chip->file_exists) { 66 continue; 67 } 68 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) { 69 goto ERROR; 70 } 71 72 pmCell *cell; // Cell of interest 73 while ((cell = pmFPAviewNextCell(view, fpa, 1))) { 74 if (!cell->file_exists) { 75 continue; 76 } 77 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) { 78 goto ERROR; 79 } 80 81 if (!cell->data_exists) { 82 continue; 83 } 84 85 if (cell->readouts->n > 1) { 86 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 87 "File %d chip %d cell %d contains more than one readout (%ld)", 88 i, view->chip, view->cell, cell->readouts->n); 89 goto ERROR; 90 } 91 pmReadout *readout = cell->readouts->data[0]; // Readout of interest 92 93 switch (type) { 94 case PPMERGE_TYPE_FLAT: 95 case PPMERGE_TYPE_FRINGE: { 96 // Extract the gain 97 float gain = psMetadataLookupF32(NULL, cell->concepts, "CELL.GAIN"); // Cell gain 98 if (!isfinite(gain)) { 99 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 100 "CELL.GAIN for file %d chip %d cell %d is not set.", 101 i, view->chip, view->cell); 102 goto ERROR; 103 } 104 gains->data.F32[cellNum] = gain; 105 106 // Measure the background 107 if (!psImageBackground(stats, NULL, readout->image, readout->mask, maskVal, rng)) { 108 psError(PS_ERR_UNKNOWN, false, 109 "Unable to get statistics for file %d chip %d cell %d", 110 i, view->chip, view->cell); 111 goto ERROR; 112 } 113 background->data.F32[i][cellNum] = psStatsGetValue(stats, meanStat); 114 break; 115 } 116 case PPMERGE_TYPE_SHUTTER: { 117 pmShutterCorrectionData *shutter = shutters->data[cellNum]; // Shutter correction data 118 if (!shutter) { 119 shutter = pmShutterCorrectionDataAlloc(readout->image->numCols, 120 readout->image->numRows, 121 shutterSize); 122 shutters->data[cellNum] = shutter; 123 } 124 if (!pmShutterCorrectionAddReadout(shutter, readout, meanStat, stdevStat, 125 maskVal, rng)) { 126 psError(PS_ERR_UNKNOWN, false, 127 "Can't add file %d chip %d cell %d to shutter correction.", 128 i, view->chip, view->cell); 129 goto ERROR; 130 } 131 break; 132 } 133 case PPMERGE_TYPE_MASK: 134 default: 135 psAbort("Should never get here."); 136 } 137 138 cellNum++; 139 140 if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) { 141 goto ERROR; 142 } 143 } 144 145 if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) { 146 goto ERROR; 147 } 148 } 149 150 if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) { 151 goto ERROR; 152 } 153 154 psFree(view); 155 156 #if 0 157 // Reset files for reading again 158 for (int i = 0; i < files->n; i++) { 159 pmFPAfile *file = files->data[i]; // File of interest 160 } 161 #endif 162 psFree(files); 55 163 } 56 if (options->zero) { 57 if (*zeros) { 58 psFree(*zeros); 59 } 60 *zeros = psImageAlloc(data->numCells, filenames->n, PS_TYPE_F32); 164 165 psFree(rng); rng = NULL; 166 psFree(stats); stats = NULL; 167 168 // Store results 169 switch (type) { 170 case PPMERGE_TYPE_FRINGE: 171 psMetadataAddImage(config->arguments, PS_LIST_TAIL, "ZEROS", 0, 172 "Zero to subtract from each input cell", background); 173 // Flow through 174 case PPMERGE_TYPE_FLAT: { 175 // Need to normalize over the focal plane 176 if (psTraceGetLevel("ppMerge") > 9) { 177 for (int i = 0; i < gains->n; i++) { 178 psTrace("ppMerge", 10, "Gain for cell %d is %f\n", i, gains->data.F32[i]); 179 } 180 } 181 psVector *fluxes = NULL; // Solution to fluxes 182 if (!pmFlatNormalize(&fluxes, &gains, background)) { 183 psError(PS_ERR_UNKNOWN, false, "Normalisation failed to converge --- continuing anyway."); 184 psFree(fluxes); 185 goto ERROR; 186 } 187 188 psMetadataAddVector(config->arguments, PS_LIST_TAIL, "SCALES", 0, 189 "Scale to divide into each input file", fluxes); 190 psFree(fluxes); // Drop reference 191 break; 192 } 193 case PPMERGE_TYPE_SHUTTER: 194 psMetadataAddArray(config->arguments, PS_LIST_TAIL, "SHUTTER", 0, 195 "Shutter data", shutters); 196 break; 197 case PPMERGE_TYPE_MASK: 198 default: 199 psAbort("Should never get here."); 61 200 } 62 psRandom *rng = NULL; // Random number generator 63 if (options->shutter) { 64 if (*shutters) { 65 psFree(*shutters); 66 } 67 *shutters = psArrayAlloc(data->numCells); 68 rng = psRandomAlloc(PS_RANDOM_TAUS, 0); 69 } 70 71 bool fromConcepts = false; // Do we get the scale and zero points from the concepts? 72 bool first = true; // Are we on the first cell (that sets the standard for the rest)? 73 bool done = false; // Are we done going through the list? 74 bool mdok = true; // Status of MD lookup 75 for (long i = 0; i < data->in->n && !done; i++) { 76 pmFPA *fpa = data->in->data[i]; // The FPA 77 if (!fpa) { 78 continue; 79 } 80 long cellNum = -1; // Number of the cell 81 psArray *chips = fpa->chips; // The array of chips 82 for (long j = 0; j < chips->n && !done; j++) { 83 pmChip *chip = chips->data[j]; // The chip 84 if (!chip) { 85 continue; 86 } 87 psArray *cells = chip->cells; // The array of cells 88 for (long k = 0; k < cells->n && !done; k++) { 89 pmCell *cell = cells->data[k]; // The cell 90 if (!cell) { 91 continue; 92 } 93 cellNum++; 94 95 if (options->scale) { 96 float scale = psMetadataLookupF32(&mdok, cell->concepts, "PPMERGE.SCALE"); // The scale 97 if (mdok && !isnan(scale)) { 98 if (!first && !fromConcepts) { 99 psWarning("PPMERGE.SCALE and PPMERGE.ZERO have been set " 100 "for some, but not all cells --- we will re-measure it for all cells."); 101 done = true; 102 continue; 103 } 104 fromConcepts = true; 105 (*scales)->data.F32[i][cellNum] = scale; 106 psTrace("ppMerge", 9, "Scale for input %ld, chip %ld, cell %ld: %f\n", 107 i, j, k, scale); 108 } else if (!first && fromConcepts) { 109 psWarning("PPMERGE.SCALE and PPMERGE.ZERO have been set " 110 "for some, but not all cells --- we will re-measure it for all cells."); 111 fromConcepts = false; 112 done = true; 113 continue; 114 } 115 } 116 117 if (options->zero) { 118 float zero = psMetadataLookupF32(&mdok, cell->concepts, "PPMERGE.ZERO"); // The zero 119 if (mdok && !isnan(zero)) { 120 if (!first && !fromConcepts) { 121 psWarning("PPMERGE.SCALE and PPMERGE.ZERO have been set " 122 "for some, but not all cells --- we will re-measure it for all cells."); 123 done = true; 124 continue; 125 } 126 fromConcepts = true; 127 (*zeros)->data.F32[i][cellNum] = zero; 128 psTrace("ppMerge", 9, "Zero for input %ld, chip %ld, cell %ld: %f\n", i, j, k, zero); 129 } else if (!first && fromConcepts) { 130 psWarning("PPMERGE.SCALE and PPMERGE.ZERO have been set " 131 "for some, but not all cells --- we will re-measure it for all cells."); 132 fromConcepts = false; 133 done = true; 134 continue; 135 } 136 } 137 138 first = false; 139 } 140 } 141 } 142 143 if (fromConcepts) { 144 // We've already done everything we need to 145 psFree(rng); 146 return true; 147 } 148 149 psImage *background = psImageAlloc(data->numCells, filenames->n, PS_TYPE_F32); // Background measurements 150 psImageInit(background, NAN); 151 psStats *bgStats = psStatsAlloc(options->mean); // Statistic to measure the background 152 psVector *gains = NULL; // The gains for each cell 153 if (options->scale) { 154 gains = psVectorAlloc(data->numCells, PS_TYPE_F32); 155 } 156 157 pmFPAview *view = pmFPAviewAlloc(0); 158 159 bool status = true; // Status of getting the scale and zero --- did everything go right? 160 for (int i = 0; i < filenames->n; i++) { 161 psString name = filenames->data[i]; // The name of the file 162 if (!name || strlen(name) == 0) { 163 continue; 164 } 165 psTrace("ppMerge", 9, "Opening %s to get background...\n", name); 166 psFits *inFile = data->files->data[i]; // The FITS file to read 167 pmFPA *fpa = data->in->data[i]; // The FPA for this input 168 int cellNum = -1; // Number of the cell 169 psArray *chips = fpa->chips; // Array of chips 170 for (int j = 0; j < chips->n; j++) { 171 pmChip *chip = chips->data[j]; // The chip of interest 172 if (!chip) { 173 continue; 174 } 175 psArray *cells = chip->cells; // Array of cells 176 for (int k = 0; k < cells->n; k++) { 177 pmCell *cell = cells->data[k]; // The cell of interest 178 if (!cell) { 179 continue; 180 } 181 cellNum++; 182 183 if (!pmCellReadHeader(cell, inFile)) { 184 continue; 185 } 186 187 // Scaling by the background 188 if (options->scale || options->zero) { 189 if (!pmCellRead(cell, inFile, config->database)) { 190 // Nothing here 191 pmCellFreeData(cell); 192 continue; 193 } 194 195 if (cell->readouts->n > 1) { 196 psWarning("File %s chip %d cell %d contains more than one " 197 "readout --- ignoring all but the first.\n", name, j, k); 198 status = false; 199 } 200 201 pmReadout *readout = cell->readouts->data[0]; // The readout of interest 202 psImage *image = readout->image; // The pixels of interest 203 if (!image) { 204 pmCellFreeData(cell); 205 continue; 206 } 207 208 // Get the gain 209 if (options->scale) { 210 bool mdok = true; // Status of MD lookup 211 gains->data.F32[cellNum] = psMetadataLookupF32(&mdok, cell->concepts, "CELL.GAIN"); 212 if (!mdok || isnan(gains->data.F32[cellNum])) { 213 psWarning("CELL.GAIN for file %s chip %d cell %d is not " 214 "set.\n", name, j, k); 215 gains->data.F32[cellNum] = NAN; 216 status = false; 217 } 218 } 219 220 // Get the background 221 int sampleSize = (image->numCols * image->numRows) / options->sample; // Size of sample 222 psVector *sample = psVectorAlloc(sampleSize, PS_TYPE_F32); // Sample of the image 223 psVector *sampleMask = NULL; // Mask for sample 224 if (readout->mask) { 225 sampleMask = psVectorAlloc(sampleSize, PS_TYPE_U8); 226 } 227 psImage *mask = readout->mask; // The mask image 228 for (long i = 0; i < sampleSize; i++) { 229 int j = i * options->sample; // Index into image 230 int x = j % image->numCols; // x index 231 int y = j / image->numCols; // y index 232 sample->data.F32[i] = image->data.F32[y][x]; 233 if (readout->mask) { 234 sampleMask->data.U8[i] = mask->data.U8[y][x]; 235 } 236 } 237 status = psVectorStats(bgStats, sample, sampleMask, NULL, options->combine->maskVal); 238 if (!status) { 239 psTrace("ppMerge", 3, "failed to get stats for for %s, cell %d is %f\n", name, cellNum, 240 background->data.F32[i][cellNum]); 241 psErrorClear(); 242 } 243 psFree(sample); 244 psFree(sampleMask); 245 background->data.F32[i][cellNum] = psStatsGetValue(bgStats, options->mean); 246 psTrace("ppMerge", 3, "Background for %s, cell %d is %f\n", name, cellNum, 247 background->data.F32[i][cellNum]); 248 } 249 250 // Shutter correction 251 if (options->shutter) { 252 if (!pmCellRead(cell, inFile, config->database)) { 253 // Nothing here 254 pmCellFreeData(cell); 255 continue; 256 } 257 258 if (cell->readouts->n > 1) { 259 psWarning("File %s chip %d cell %d contains more than one " 260 "readout --- ignoring all but the first.\n", name, j, k); 261 status = false; 262 } 263 pmReadout *readout = cell->readouts->data[0]; // The readout of interest 264 265 pmShutterCorrectionData *shutter = (*shutters)->data[cellNum]; // Shutter correction data 266 if (!shutter) { 267 shutter = pmShutterCorrectionDataAlloc(readout->image->numCols, 268 readout->image->numRows, 269 options->shutterSize); 270 (*shutters)->data[cellNum] = shutter; 271 } 272 if (!pmShutterCorrectionAddReadout(shutter, readout, options->mean, options->stdev, 273 options->combine->maskVal, rng)) { 274 psWarning("Can't add file %s chip %d cell %d to shutter correction --- ignored.", 275 name, j, k); 276 status = false; 277 } 278 } 279 280 281 pmCellFreeData(cell); 282 } 283 pmChipFreeData(chip); 284 } 285 pmFPAFreeData(fpa); 286 } 201 202 psFree(background); 203 psFree(shutters); 204 return true; 205 206 ERROR: 207 // Common path for errors 208 psFree(gains); 209 psFree(background); 210 psFree(shutters); 287 211 psFree(rng); 288 psFree( bgStats);212 psFree(stats); 289 213 psFree(view); 290 291 if (options->scale) { 292 // Need to normalize over the focal plane 293 if (psTraceGetLevel("ppMerge") > 9) { 294 for (int i = 0; i < gains->n; i++) { 295 psTrace("ppMerge", 10, "Gain for cell %d is %f\n", i, gains->data.F32[i]); 296 } 297 } 298 psVector *fluxes = NULL; // Solution to fluxes 299 if (!pmFlatNormalize(&fluxes, &gains, background)) { 300 psWarning("Normalisation failed to converge --- continuing anyway.\n"); 301 status = false; 302 } 303 psFree(gains); 304 305 psImage *scalesDeref = *scales; // Dereference the pointer 306 307 for (int i = 0; i < scalesDeref->numRows; i++) { 308 psF32 bg = fluxes->data.F32[i]; 309 for (int j = 0; j < scalesDeref->numCols; j++) { 310 scalesDeref->data.F32[i][j] = bg; 311 } 312 } 313 } 314 315 if (options->zero) { 316 if (!*zeros) { 317 // This is much faster than copying! 318 *zeros = psMemIncrRefCounter(background); 319 } else { 320 *zeros = psImageCopy(*zeros, background, PS_TYPE_F32); 321 } 322 } 323 324 // Diagnostic stuff 325 if (scales && *scales && psTraceGetLevel("ppMerge") > 9) { 326 psImage *scalesDeref = *scales; // Dereference the pointer 327 for (int i = 0; i < scalesDeref->numRows; i++) { 328 for (int j = 0; j < scalesDeref->numCols; j++) { 329 psTrace("ppMerge", 9, "Scale for exposure %d, cell %d is: %f\n", i, j, 330 scalesDeref->data.F32[i][j]); 331 } 332 } 333 } 334 if (zeros && *zeros && psTraceGetLevel("ppMerge") > 9) { 335 psImage *zerosDeref = *zeros; // Dereference the pointer 336 for (int i = 0; i < zerosDeref->numRows; i++) { 337 for (int j = 0; j < zerosDeref->numCols; j++) { 338 psTrace("ppMerge", 9, "Zero for exposure %d, cell %d is: %f\n", i, j, 339 zerosDeref->data.F32[i][j]); 340 } 341 } 342 } 343 344 psFree(background); 345 346 return status; 214 return false; 347 215 } 348 216
Note:
See TracChangeset
for help on using the changeset viewer.
