IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 17083


Ignore:
Timestamp:
Mar 20, 2008, 5:08:17 PM (18 years ago)
Author:
Paul Price
Message:

Modernising ppMerge to use the pmFPAfile system of reading/writing, and to use a similar configuration system. The hope is that this will make things easier to maintain.

Location:
branches/pap_branch_080320/ppMerge/src
Files:
4 added
20 deleted
5 edited

Legend:

Unmodified
Added
Removed
  • branches/pap_branch_080320/ppMerge/src/Makefile.am

    r15937 r17083  
    66ppMerge_SOURCES =               \
    77        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          \
    1911        ppMergeScaleZero.c      \
    20         ppMergeVersion.c
     12        ppMergeLoop.c           \
     13        ppMergeMask.c
    2114
    2215
    2316noinst_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
    3318
    3419CLEANFILES = *~
  • branches/pap_branch_080320/ppMerge/src/ppMerge.c

    r15631 r17083  
    44
    55#include <stdio.h>
     6#include <string.h>
    67#include <pslib.h>
    78#include <psmodules.h>
    89
    910#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"
    1711
    1812//#include "ppMem.h"
     
    2721{
    2822    psLibInit(NULL);
    29     psMemSetThreadSafety(false);           // Turn off thread safety, for more
     23    psMemSetThreadSafety(false);
    3024    psTimerStart(TIMERNAME);
    3125
    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
    3729    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;
    4033    }
    4134
     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
    42100    // Set various tasks (define optional operations)
    43101    ppMergeOptions *options = ppMergeOptionsParse(config);
     
    81139    }
    82140
    83 #if 0
    84     pmFPAPrint(stdout, data->out, true, true);
    85 #endif
    86 
    87141    // Cleaning up
    88142    psFree(data);
    89143    psFree(options);
     144#endif
     145
     146 die:
     147    psTrace("ppSub", 1, "Finished at %f sec\n", psTimerMark("ppSub"));
     148    psTimerStop();
     149
    90150    psFree(config);
    91 
    92     pmConceptsDone();
    93151    pmConfigDone();
    94152    psLibFinalize();
    95153
    96 //    ppMemCheck();
    97 
    98     return EXIT_SUCCESS;
     154    exit(exitValue);
    99155}
  • branches/pap_branch_080320/ppMerge/src/ppMerge.h

    r8405 r17083  
    22#define PP_MERGE_H
    33
    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
     8typedef 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
     19typedef 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
     26bool ppMergeArguments(int argc, char *argv[], // Command-line arguments
     27                      pmConfig *config  // Configuration
     28    );
     29
     30// Set up camera files
     31bool ppMergeCamera(pmConfig *config     // Configuration
     32    );
     33
     34// Measure scale and zero-points
     35bool ppMergeScaleZero(pmConfig *config  // Configuration
     36    );
     37
     38// Main loop to do the merging
     39bool ppMergeLoop(pmConfig *config       // Configuration
     40    );
     41
     42// Main loop for masks
     43bool ppMergeMask(pmConfig *config       // Configuration
     44    );
     45
     46// Read nominated input file
     47bool 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
     54bool 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
     60psArray *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
     66bool 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
     72psArray *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
     79psString ppMergeOutputFile(const pmConfig *config // Configuration
     80    );
    681
    782#endif
  • branches/pap_branch_080320/ppMerge/src/ppMergeMask.c

    r15937 r17083  
    55#include <stdio.h>
    66#include <string.h>
    7 #include <unistd.h>
    87#include <assert.h>
     8
    99#include <pslib.h>
    1010#include <psmodules.h>
     
    1212
    1313#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
     15static 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                      )
    2321{
    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     }
    50 
     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    psArray *suspects = psArrayAlloc(outChip->cells->n); // Images with suspected pixels
     47    psVector *values = psVectorAlloc(sample, PS_TYPE_F32); // Pixel values for statistics
     48    pmFPAview *inView = pmFPAviewAlloc(0); // View for input
     49    for (int i = 0; i < numFiles; i++) {
     50        pmFPAfileActivate(config->files, false, NULL);
     51        psArray *files = ppMergeFileActivateSingle(config, PPMERGE_FILES_INPUT, true, i); // Input files
     52        pmFPAfile *input = files->data[0]; // Input file
     53        psFree(files);
     54        pmFPA *inFPA = input->fpa;  // Input FPA
     55        *inView = *view;
     56
     57        int valueIndex = 0;             // Index for vector of pixel values
     58
     59        pmCell *inCell;                 // Input cell
     60        while ((inCell = pmFPAviewNextCell(inView, inFPA, 1))) {
     61            pmHDU *hdu = pmHDUFromCell(inCell); // HDU for cell
     62            if (!hdu || hdu->blankPHU) {
     63                // No data here
     64                continue;
     65            }
     66            psTrace("ppMerge", 1, "Getting suspect pixels for file %d chip %d cell %d",
     67                    i, inView->chip, inView->cell);
     68
     69            if (!pmFPAfileIOChecks(config, inView, PM_FPA_BEFORE)) {
     70                psFree(inView);
     71                goto MERGE_MASK_ERROR;
     72            }
     73
     74            if (!ppMergeFileOpenInput(config, view, i)) {
     75                psError(PS_ERR_UNKNOWN, false, "Unable to open file %d", i);
     76                psFree(inView);
     77                goto MERGE_MASK_ERROR;
     78            }
     79
     80            if (inCell->readouts->n > 1) {
     81                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     82                        "File %d chip %d cell %d contains more than one readout (%ld)",
     83                        i, inView->chip, inView->cell, inCell->readouts->n);
     84                psFree(inView);
     85                goto MERGE_MASK_ERROR;
     86            }
     87
     88            pmReadout *readout;
     89            if (inCell->readouts && inCell->readouts->n == 1) {
     90                readout = psMemIncrRefCounter(inCell->readouts->data[0]); // Input readout
     91            } else {
     92                readout = pmReadoutAlloc(inCell);
     93            }
     94
     95            if (!ppMergeFileReadInput(config, readout, i, 0)) {
     96                psError(PS_ERR_UNKNOWN, false, "Unable to read readout %d", i);
     97                psFree(inView);
     98                psFree(readout);
     99                goto MERGE_MASK_ERROR;
     100            }
     101
     102            psImage *outMask = NULL;    // Output mask image (for iterative generation of mask)
     103            pmCell *outCell = pmFPAfileThisCell(config->files, inView, "PPMERGE.OUTPUT.MASK"); // Output cell
     104            if (outCell->readouts && outCell->readouts->n == 1) {
     105                pmReadout *outRO = outCell->readouts->data[0]; // Output readout
     106                if (outRO) {
     107                    outMask = outRO->mask;
     108                }
     109            }
     110
     111            psImage *image = readout->image, *mask = readout->mask; // Image and mask
     112            int numCols = readout->image->numCols, numRows = readout->image->numRows; // Image size
     113            int numPix = numCols * numRows; // Number of pixels
     114            int numCells = chipStats ? readout->parent->parent->cells->n : 1; // Number of cells
     115            int num = PS_MIN(numPix, sample / numCells); // Number of values to add
     116            if (!chipStats) {
     117                valueIndex = 0;
     118            }
     119            for (int i = 0; i < num; i++) {
     120                int pixel = numPix * psRandomUniform(rng);
     121                int x = pixel % numCols;
     122                int y = pixel / numCols;
     123                if ((mask && (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal)) ||
     124                    !isfinite(image->data.F32[y][x]) ||
     125                    (outMask && (outMask->data.PS_TYPE_MASK_DATA[y][x] & maskVal))) {
     126                    continue;
     127                }
     128
     129                values->data.F32[valueIndex++] = image->data.F32[y][x];
     130            }
     131
     132            if (!chipStats) {
     133                values->n = valueIndex;
     134                if (!psVectorStats(statistics, values, NULL, NULL, 0)) {
     135                    psError(PS_ERR_UNKNOWN, false, "Unable to do statistics on readout.");
     136                    psFree(inView);
     137                    psFree(readout);
     138                    goto MERGE_MASK_ERROR;
     139                }
     140
     141                psMetadataAddF32(readout->analysis, PS_LIST_TAIL, PM_MASK_ANALYSIS_MEAN, PS_META_REPLACE,
     142                                 "Mean value of readout", psStatsGetValue(statistics, meanStat));
     143                psMetadataAddF32(readout->analysis, PS_LIST_TAIL, PM_MASK_ANALYSIS_STDEV, PS_META_REPLACE,
     144                                 "Stdev value of readout", psStatsGetValue(statistics, stdevStat));
     145                suspects->data[inView->cell] = pmMaskFlagSuspectPixels(suspects->data[inView->cell],
     146                                                                       readout, maskSuspect, maskVal);
     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        }
     157
     158        // Additional run through cells if we want chip-level statistics
     159        if (chipStats && valueIndex > 0) {
     160            values->n = valueIndex;
     161            if (!psVectorStats(statistics, values, NULL, NULL, 0)) {
     162                psError(PS_ERR_UNKNOWN, false, "Unable to do statistics on chip.");
     163                goto MERGE_MASK_ERROR;
     164            }
     165            inView->cell = -1;
     166            while ((inCell = pmFPAviewNextCell(inView, inFPA, 1))) {
     167                pmHDU *hdu = pmHDUFromCell(inCell); // HDU for cell
     168                if (!hdu || hdu->blankPHU) {
     169                    // No data here
     170                    continue;
     171                }
     172                pmReadout *readout = inCell->readouts->data[0]; // Readout of interest
     173
     174                psMetadataAddF32(readout->analysis, PS_LIST_TAIL, PM_MASK_ANALYSIS_MEAN, PS_META_REPLACE,
     175                                 "Mean value of chip", psStatsGetValue(statistics, meanStat));
     176                psMetadataAddF32(readout->analysis, PS_LIST_TAIL, PM_MASK_ANALYSIS_STDEV, PS_META_REPLACE,
     177                                 "Stdev value of chip", psStatsGetValue(statistics, stdevStat));
     178                suspects->data[inView->cell] = pmMaskFlagSuspectPixels(suspects->data[inView->cell],
     179                                                                       readout, maskSuspect, maskVal);
     180                pmCellFreeData(inCell);
     181
     182                if (!pmFPAfileIOChecks(config, inView, PM_FPA_AFTER)) {
     183                    psFree(inView);
     184                    goto MERGE_MASK_ERROR;
     185                }
     186            }
     187        }
     188    }
     189    psFree(inView);
     190    psFree(statistics); statistics = NULL;
     191    psFree(values); values = NULL;
     192
     193
     194    // Another run through the chip to threshold on the suspects
     195    pmFPAfileActivate(config->files, false, NULL);
     196    if (writeOut) {
     197        ppMergeFileActivate(config, PPMERGE_FILES_OUTPUT, true);
     198    }
     199    pmFPA *outFPA = outChip->parent;    // Output FPA
     200    pmCell *outCell;                    // Output cell
     201    pmFPAview *outView = pmFPAviewAlloc(0); // View into output FPA
     202    *outView = *view;
     203    while ((outCell = pmFPAviewNextCell(outView, outFPA, 1))) {
     204        pmHDU *hdu = pmHDUFromCell(outCell); // HDU for cell
     205        if (!hdu || hdu->blankPHU) {
     206            // No data here
     207            continue;
     208        }
     209
     210        psTrace("ppMerge", 1, "Getting bad pixels for chip %d cell %d", outView->chip, outView->cell);
     211
     212        pmReadout *outRO = NULL;    // Output readout
     213        if (outCell->readouts && outCell->readouts->n == 1) {
     214            outRO = psMemIncrRefCounter(outCell->readouts->data[0]);
     215        } else {
     216            outRO = pmReadoutAlloc(outCell);
     217        }
     218
     219        psImage *mask = pmMaskIdentifyBadPixels(suspects->data[outView->cell], maskVal, numFiles, maskBad,
     220                                                maskMode);
     221        psFree(suspects->data[outView->cell]);
     222        suspects->data[outView->cell] = NULL;
     223        if (maskGrowVal > 0) {
     224            outRO->mask = psImageGrowMask(outRO->mask, mask, maskVal, maskGrow, maskGrowVal);
     225            psFree(mask);
     226        } else {
     227            psFree(outRO->mask);
     228            outRO->mask = mask;
     229        }
     230
     231        outRO->data_exists = outCell->data_exists = outChip->data_exists = true;
     232
     233        if (writeOut) {
     234            if (!pmFPAfileIOChecks(config, outView, PM_FPA_BEFORE)) {
     235                psFree(outView);
     236                goto MERGE_MASK_ERROR;
     237            }
     238
     239            // Average concepts
     240            psList *cells = psListAlloc(NULL); // List of cells, for concept averaging
     241            for (int i = 0; i < numFiles; i++) {
     242                pmFPAfile *inFile = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i); // Input file
     243                pmCell *inCell = pmFPAviewThisCell(outView, inFile->fpa); // Input cell
     244                psListAdd(cells, PS_LIST_TAIL, inCell);
     245            }
     246            if (!pmConceptsAverageCells(outCell, cells, NULL, NULL, true)) {
     247                psError(PS_ERR_UNKNOWN, false, "Unable to average cell concepts.");
     248                psFree(cells);
     249                psFree(outRO);
     250                psFree(outView);
     251                return false;
     252            }
     253            psFree(cells);
     254
     255            // Statistics on the merged cell using a fake image
     256            outRO->image = psImageAlloc(outRO->mask->numCols, outRO->mask->numRows, PS_TYPE_F32);
     257            psImageInit(outRO->image, 1.0);
     258            if (!ppStatsFPA(stats, outRO->parent->parent->parent, outView,
     259                            maskVal | pmConfigMask("BLANK", config), config)) {
     260                psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to generate stats for image.");
     261                psFree(outRO);
     262                psFree(outView);
     263                return false;
     264            }
     265            psFree(outRO->image);
     266            outRO->image = NULL;
     267
     268            // Write
     269            if (!pmFPAfileIOChecks(config, outView, PM_FPA_AFTER)) {
     270                psFree(outView);
     271                goto MERGE_MASK_ERROR;
     272            }
     273        }
     274        psFree(outRO);
     275    }
     276    psFree(outView);
     277
     278    ppMergeFileActivate(config, PPMERGE_FILES_ALL, true);
     279
     280    psFree(suspects);
    51281    return true;
     282
     283
     284MERGE_MASK_ERROR:
     285    psFree(suspects);
     286    psFree(statistics);
     287    psFree(values);
     288    return false;
    52289}
    53290
    54 bool ppMergeMaskReadoutStats(const pmReadout *readout,
    55                              const pmReadout *output,
    56                              ppMergeOptions *options, // Options
    57                              psRandom *rng)
     291
     292
     293
     294
     295bool ppMergeMask(pmConfig *config)
    58296{
    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 
     297    assert(config);
     298
     299    bool mdok;                          // Status of MD lookup
     300    int numFiles = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of inputs
     301    bool haveMasks = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.MASKS"); // Do we have masks?
     302    bool haveWeights = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.WEIGHTS"); // Do we have weights?
     303    int iter = psMetadataLookupS32(NULL, config->arguments, "ITER"); // Number of rejection iterations
     304
     305    PS_ASSERT_INT_POSITIVE(iter, false);
     306
     307    pmFPAview *view = pmFPAviewAlloc(0); // View to component of interest
     308    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator
     309
     310    psMetadata *stats = NULL;           // Statistics for output
     311    if (psMetadataLookup(config->arguments, "STATS.NAME")) {
     312        stats = psMetadataAlloc();
     313        psMetadataAddMetadata(config->arguments, PS_LIST_TAIL, "STATS.DATA", 0, "Statistics output", stats);
     314    }
     315
     316    psArray *inputs = ppMergeFileDataLevel(config, "PPMERGE.INPUT", PM_FPA_LEVEL_READOUT); // Input images
     317    psFree(inputs);
     318    if (haveMasks) {
     319        psArray *masks = ppMergeFileDataLevel(config, "PPMERGE.INPUT.MASK", PM_FPA_LEVEL_READOUT);
     320        psFree(masks);
     321    }
     322    if (haveWeights) {
     323        psArray *weights = ppMergeFileDataLevel(config, "PPMERGE.INPUT.WEIGHT", PM_FPA_LEVEL_READOUT);
     324        psFree(weights);
     325    }
     326
     327    if (!ppMergeFileActivate(config, PPMERGE_FILES_INPUT, true)) {
     328        psError(PS_ERR_UNKNOWN, false, "Unable to activate files.");
     329        goto PPMERGE_MASK_ERROR;
     330    }
     331    if (!ppMergeFileActivate(config, PPMERGE_FILES_OUTPUT, false)) {
     332        psError(PS_ERR_UNKNOWN, false, "Unable to activate files.");
     333        goto PPMERGE_MASK_ERROR;
     334    }
     335
     336    psString outName = ppMergeOutputFile(config); // Name of output file
     337    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, outName); // Output file
     338    psFree(outName);
     339    assert(output && output->fpa);
     340    pmFPA *outFPA = output->fpa;        // Output FPA
     341
     342    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     343        goto PPMERGE_MASK_ERROR;
     344    }
     345    pmChip *outChip;                    // Chip of interest
     346    while ((outChip = pmFPAviewNextChip(view, outFPA, 1))) {
     347        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     348            goto PPMERGE_MASK_ERROR;
     349        }
     350
     351        for (int i = 0; i < iter; i++) {
     352            if (!mergeMask(config, view, (i == iter - 1), rng, stats)) {
     353                psError(PS_ERR_UNKNOWN, false, "Unable to merge chip %d", view->chip);
     354                goto PPMERGE_MASK_ERROR;
     355            }
     356        }
     357
     358        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     359            goto PPMERGE_MASK_ERROR;
     360        }
     361    }
     362
     363    psList *fpaList = psListAlloc(NULL);// List of FPAs for concept averaging
     364    for (int i = 0; i < numFiles; i++) {
     365        pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i); // Input file
     366        psListAdd(fpaList, PS_LIST_TAIL, file->fpa);
     367    }
     368    if (!pmConceptsAverageFPAs(outFPA, fpaList)) {
     369        psError(PS_ERR_UNKNOWN, false, "Unable to average FPA concepts.");
     370        psFree(fpaList);
     371        goto PPMERGE_MASK_ERROR;
     372    }
     373    psFree(fpaList);
     374
     375    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     376        goto PPMERGE_MASK_ERROR;
     377    }
     378
     379    psFree(stats);
     380    psFree(view);
    102381    psFree(rng);
     382
    103383    return true;
     384
     385PPMERGE_MASK_ERROR:
     386    psFree(stats);
     387    psFree(view);
     388    psFree(rng);
     389    return false;
    104390}
    105391
    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 options
    114     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 readout
    123     psVector *values = psVectorAllocEmpty(options->sample, PS_TYPE_F32); // Vector containing subsample
    124 
    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 interest
    136 
    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 mask
    143             }
    144 
    145             // Size of image
    146             long nx = image->numCols;
    147             long ny = image->numRows;
    148             const int Npixels = nx*ny;  // Total number of pixels
    149             const int Nsubset = PS_MIN(options->sample, Npixels); // Number of pixels in subset
    150            
    151             values = psVectorRealloc (values, values->n + Nsubset); // make sure we have enough space
    152 
    153             // select a subset of the image pixels to measure the stats
    154             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 chip
    171     if (!values->n) {
    172         psFree(values);
    173         psFree(stats);
    174         psFree(rng);
    175         return true;
    176     }
    177 
    178     // calculate the statistics
    179     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 metadata
    195     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 }
  • branches/pap_branch_080320/ppMerge/src/ppMergeScaleZero.c

    r16842 r17083  
    1010
    1111#include "ppMerge.h"
    12 #include "ppMergeScaleZero.h"
    1312
    1413// 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     )
     14bool ppMergeScaleZero(pmConfig *config)
    2215{
    23     assert(data);
    24     assert(options);
    2516    assert(config);
    2617
    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    int sample = psMetadataLookupS32(NULL, config->arguments, "SAMPLE"); // Maximum size of sample
     26    bool chipStats = false;             // Do statistics on full chip instead of cell?
     27
     28    psVector *gains = NULL;             // Gains for each cell
     29    psArray *shutters = NULL;           // Shutter data for each cell
     30    psStats *stats = NULL;              // Statistics for background
     31    psImage *background = NULL;         // Background measurements per cell per file
     32
     33    switch (type) {
     34      case PPMERGE_TYPE_BIAS:
     35      case PPMERGE_TYPE_DARK:
     36        // Nothing to measure
     37        return true;
     38      case PPMERGE_TYPE_FLAT:
     39      case PPMERGE_TYPE_FRINGE:
     40        gains = psVectorAlloc(numCells, PS_TYPE_F32);
     41        background = psImageAlloc(numCells, numInputs, PS_TYPE_F32);
     42        psImageInit(background, NAN);
     43        stats = psStatsAlloc(meanStat);
     44        break;
     45      case PPMERGE_TYPE_SHUTTER:
     46        shutters = psArrayAlloc(numCells);
     47        break;
     48      case PPMERGE_TYPE_MASK:
     49        stats = psStatsAlloc(meanStat | stdevStat);
     50      default:
     51        break;
    2952    }
    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);
    55     }
    56     if (options->zero) {
    57         if (*zeros) {
    58             psFree(*zeros);
    59         }
    60         *zeros = psImageAlloc(data->numCells, filenames->n, PS_TYPE_F32);
    61     }
    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) {
     53    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator
     54    pmFPAview *view = NULL;             // View into FPA
     55
     56    psVector *values = psVectorAlloc(sample, PS_TYPE_F32); // Values for statistics
     57
     58    for (int i = 0; i < numInputs; i++) {
     59        pmFPAfileActivate(config->files, false, NULL);
     60        psArray *files = ppMergeFileActivateSingle(config, PPMERGE_FILES_INPUT, true, i); // Activated files
     61        pmFPAfile *input = files->data[0]; // Representative file; should be the image (not mask or weight)
     62        pmFPA *fpa = input->fpa;        // FPA of interest
     63        view = pmFPAviewAlloc(0);       // View to component of interest
     64        int cellNum = 0;                // Index for cell
     65        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     66            goto ERROR;
     67        }
     68        pmChip *chip;                   // Chip of interest
     69        while ((chip = pmFPAviewNextChip(view, fpa, 1))) {
     70            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     71                goto ERROR;
     72            }
     73
     74            int valueIndex = 0;         // Index into values vector
     75
     76            pmCell *cell;               // Cell of interest
     77            while ((cell = pmFPAviewNextCell(view, fpa, 1))) {
     78                if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     79                    goto ERROR;
     80                }
     81
     82                if (!cell->data_exists) {
    9183                    continue;
    9284                }
     85
     86                if (cell->readouts->n > 1) {
     87                    psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     88                            "File %d chip %d cell %d contains more than one readout (%ld)",
     89                            i, view->chip, view->cell, cell->readouts->n);
     90                    goto ERROR;
     91                }
     92                pmReadout *readout = cell->readouts->data[0]; // Readout of interest
     93
     94                switch (type) {
     95                  case PPMERGE_TYPE_FLAT:
     96                  case PPMERGE_TYPE_FRINGE: {
     97                      // Extract the gain
     98                      float gain = psMetadataLookupF32(NULL, cell->concepts, "CELL.GAIN"); // Cell gain
     99                      if (!isfinite(gain)) {
     100                          psError(PS_ERR_BAD_PARAMETER_VALUE, false,
     101                                  "CELL.GAIN for file %d chip %d cell %d is not set.",
     102                                  i, view->chip, view->cell);
     103                          goto ERROR;
     104                      }
     105                      gains->data.F32[cellNum] = gain;
     106
     107                      // Measure the background
     108                      if (!psImageBackground(stats, NULL, readout->image, readout->mask, maskVal, rng)) {
     109                          psError(PS_ERR_UNKNOWN, false,
     110                                  "Unable to get statistics for file %d chip %d cell %d",
     111                                  i, view->chip, view->cell);
     112                          goto ERROR;
     113                      }
     114                      background->data.F32[cellNum][i] = psStatsGetValue(stats, meanStat);
     115                      break;
     116                  }
     117                  case PPMERGE_TYPE_SHUTTER: {
     118                      pmShutterCorrectionData *shutter = shutters->data[cellNum]; // Shutter correction data
     119                      if (!shutter) {
     120                          shutter = pmShutterCorrectionDataAlloc(readout->image->numCols,
     121                                                                 readout->image->numRows,
     122                                                                 shutterSize);
     123                          shutters->data[cellNum] = shutter;
     124                      }
     125                      if (!pmShutterCorrectionAddReadout(shutter, readout, meanStat, stdevStat,
     126                                                         maskVal, rng)) {
     127                          psError(PS_ERR_UNKNOWN, false,
     128                                  "Can't add file %d chip %d cell %d to shutter correction.",
     129                                  i, view->chip, view->cell);
     130                          goto ERROR;
     131                      }
     132                      break;
     133                  }
     134                  case PPMERGE_TYPE_MASK: {
     135                      psImage *image = readout->image, *mask = readout->mask; // Image and mask
     136                      int numCols = readout->image->numCols, numRows = readout->image->numRows; // Image size
     137                      int numPix = numCols * numRows; // Number of pixels
     138                      int numCells = chipStats ? readout->parent->parent->cells->n : 1; // Number of cells
     139                      int num = PS_MIN(numPix, sample / numCells); // Number of values to add
     140                      if (!chipStats) {
     141                          valueIndex = 0;
     142                      }
     143                      for (int i = 0; i < num; i++) {
     144                          int pixel = numPix * psRandomUniform(rng);
     145                          int x = pixel % numCols;
     146                          int y = pixel / numCols;
     147                          if ((mask && (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal)) ||
     148                              !isfinite(image->data.F32[y][x])) {
     149                              continue;
     150                          }
     151
     152                          values->data.F32[valueIndex++] = image->data.F32[y][x];
     153                      }
     154
     155                      if (!chipStats) {
     156                          if (!psVectorStats(stats, values, NULL, NULL, 0)) {
     157                              psError(PS_ERR_UNKNOWN, false, "Unable to do statistics on readout.");
     158                              goto ERROR;
     159                          }
     160
     161                          psMetadataAddF32(cell->analysis, PS_LIST_TAIL, PM_MASK_ANALYSIS_MEAN, 0,
     162                                           "Mean value of readout", psStatsGetValue(stats, meanStat));
     163                          psMetadataAddF32(cell->analysis, PS_LIST_TAIL, PM_MASK_ANALYSIS_STDEV, 0,
     164                                           "Stdev value of readout", psStatsGetValue(stats, stdevStat));
     165                      }
     166                      break;
     167                  }
     168                  default:
     169                    psAbort("Should never get here.");
     170                }
     171
    93172                cellNum++;
    94173
    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;
     174                if ((type != PPMERGE_TYPE_MASK || !chipStats) &&
     175                    !pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     176                    goto ERROR;
     177                }
     178            }
     179
     180            // Additional run through cells if we want chip-level statistics for masks
     181            if (type == PPMERGE_TYPE_MASK && chipStats) {
     182                if (!psVectorStats(stats, values, NULL, NULL, 0)) {
     183                    psError(PS_ERR_UNKNOWN, false, "Unable to do statistics on chip.");
     184                    goto ERROR;
     185                }
     186                while ((cell = pmFPAviewNextCell(view, fpa, 1))) {
     187                    if (!cell->data_exists) {
    113188                        continue;
    114189                    }
    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;
     190                    psMetadataAddF32(cell->analysis, PS_LIST_TAIL, PM_MASK_ANALYSIS_MEAN, 0,
     191                                     "Mean value of chip", psStatsGetValue(stats, meanStat));
     192                    psMetadataAddF32(cell->analysis, PS_LIST_TAIL, PM_MASK_ANALYSIS_STDEV, 0,
     193                                     "Stdev value of chip", psStatsGetValue(stats, stdevStat));
     194                    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     195                        goto ERROR;
    135196                    }
    136197                }
    137 
    138                 first = false;
    139             }
    140         }
     198            }
     199
     200            if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     201                goto ERROR;
     202            }
     203        }
     204
     205        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     206            goto ERROR;
     207        }
     208
     209        psFree(view);
     210
     211#if 0
     212        // Reset files for reading again
     213        for (int i = 0; i < files->n; i++) {
     214            pmFPAfile *file = files->data[i]; // File of interest
     215        }
     216#endif
     217        psFree(files);
    141218    }
    142219
    143     if (fromConcepts) {
    144         // We've already done everything we need to
    145         psFree(rng);
    146         return true;
     220    psFree(rng); rng = NULL;
     221    psFree(stats); stats = NULL;
     222
     223    // Store results
     224    switch (type) {
     225      case PPMERGE_TYPE_FRINGE:
     226        psMetadataAddImage(config->arguments, PS_LIST_TAIL, "ZEROS", 0,
     227                           "Zero to subtract from each input cell", background);
     228        // Flow through
     229      case PPMERGE_TYPE_FLAT: {
     230          // Need to normalize over the focal plane
     231          if (psTraceGetLevel("ppMerge") > 9) {
     232              for (int i = 0; i < gains->n; i++) {
     233                  psTrace("ppMerge", 10, "Gain for cell %d is %f\n", i, gains->data.F32[i]);
     234              }
     235          }
     236          psVector *fluxes = NULL;        // Solution to fluxes
     237          if (!pmFlatNormalize(&fluxes, &gains, background)) {
     238              psError(PS_ERR_UNKNOWN, false, "Normalisation failed to converge --- continuing anyway.");
     239              psFree(fluxes);
     240              goto ERROR;
     241          }
     242
     243          psMetadataAddVector(config->arguments, PS_LIST_TAIL, "SCALES", 0,
     244                              "Scale to divide into each input file", fluxes);
     245          psFree(fluxes);               // Drop reference
     246          break;
     247      }
     248      case PPMERGE_TYPE_SHUTTER:
     249        psMetadataAddArray(config->arguments, PS_LIST_TAIL, "SHUTTER", 0,
     250                           "Shutter data", shutters);
     251        break;
     252      default:
     253        psAbort("Should never get here.");
    147254    }
    148255
    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     }
     256    psFree(background);
     257    psFree(shutters);
     258    return true;
     259
     260ERROR:
     261    // Common path for errors
     262    psFree(gains);
     263    psFree(background);
     264    psFree(shutters);
    287265    psFree(rng);
    288     psFree(bgStats);
     266    psFree(stats);
    289267    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;
     268    return false;
    347269}
    348270
Note: See TracChangeset for help on using the changeset viewer.