IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 16605


Ignore:
Timestamp:
Feb 22, 2008, 9:28:00 AM (18 years ago)
Author:
Paul Price
Message:

Merging in branch development. ppStack now works with incremental reads. Needs some cleanup, but it works.

Location:
trunk/ppStack/src
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/ppStack/src/Makefile.am

    r14626 r16605  
    99        ppStackCamera.c         \
    1010        ppStackLoop.c           \
     11        ppStackPSF.c            \
    1112        ppStackReadout.c        \
     13        ppStackPhotometry.c     \
    1214        ppStackVersion.c        \
    1315        ppStackMatch.c
  • trunk/ppStack/src/ppStack.h

    r15844 r16605  
    1919    );
    2020
     21// Determine target PSF for input images
     22pmPSF *ppStackPSF(const pmConfig *config, // Configuration
     23                  int numCols, int numRows, // Size of image
     24                  const psList *list    // List of input PSFs
     25    );
     26
    2127// Perform stacking on a readout
    22 bool ppStackReadout(pmConfig *config,   // Configuration
    23                     const pmFPAview *view // View for readout
     28bool ppStackReadout(const pmConfig *config,   // Configuration
     29                    pmReadout *outRO,   // Output readout
     30                    const psArray *readouts, // Input readouts
     31                    const psArray *regions, // Array with array of regions used in each PSF matching
     32                    const psArray *kernels // Array with array of kernels used in each PSF matching
     33    );
     34
     35// Perform photometry on stack
     36bool ppStackPhotometry(pmConfig *config, // Configuration
     37                       const pmReadout *readout, // Readout to be photometered
     38                       const pmFPAview *view // View to readout
    2439    );
    2540
     
    3550
    3651/// Convolve image to match specified seeing
    37 bool ppStackMatch(pmReadout *output,    ///< Convolved readout
    38                   const pmReadout *input, ///< Readout to be convolved
     52bool ppStackMatch(pmReadout *readout, ///< Readout to be convolved; replaced with output
     53                  psArray **regions, // Array of regions used in each PSF matching, returned
     54                  psArray **kernels, // Array of kernels used in each PSF matching, returned
    3955                  const pmReadout *sourcesRO, ///< Readout with sources
    4056                  const pmPSF *psf,     ///< Target PSF
  • trunk/ppStack/src/ppStackArguments.c

    r16015 r16605  
    116116    psMetadataAddU8(arguments,  PS_LIST_TAIL, "-mask-blank", 0, "Mask value for blank region", 0);
    117117    psMetadataAddF32(arguments, PS_LIST_TAIL, "-threshold-mask", 0, "Threshold for mask deconvolution", NAN);
     118    psMetadataAddS32(arguments, PS_LIST_TAIL, "-rows", 0, "Rows to read at once", 128);
    118119    psMetadataAddBool(arguments, PS_LIST_TAIL, "-photometry", 0, "Do photometry on stacked image?", false);
    119120    psMetadataAddS32(arguments, PS_LIST_TAIL, "-psf-instances", 0, "Number of instances for PSF generation", 5);
     
    160161    VALUE_ARG_RECIPE_MASK("-mask-blank",      "MASK.BLANK");
    161162    VALUE_ARG_RECIPE_FLOAT("-threshold-mask", "THRESHOLD.MASK", F32);
     163    VALUE_ARG_RECIPE_INT("-rows",             "ROWS",           S32, 0);
    162164
    163165    VALUE_ARG_RECIPE_INT("-psf-instances", "PSF.INSTANCES", S32, 0);
  • trunk/ppStack/src/ppStackCamera.c

    r15844 r16605  
    1010
    1111#include "ppStack.h"
     12
     13
     14#if 0
     15// Define an output convolved image file
     16static pmFPAfile *defineOutputConvolved(const char *name, // FPA file name
     17                                        pmFPA *fpa, // FPA to bind
     18                                        const pmConfig *config, // Configuration
     19                                        pmFPAfileType type // Expected type
     20    )
     21{
     22    pmFPAfile *file = pmFPAfileDefineOutput(config, fpa, name);
     23    if (!file) {
     24        psError(PS_ERR_UNKNOWN, false, "Unable to define output convolved file %s", name);
     25        return NULL;
     26    }
     27    if (file->type != PM_FPA_FILE_IMAGE) {
     28        psError(PS_ERR_IO, true, "PPSTACK.OUTCONV is not of type %s", pmFPAfileStringFromType(type));
     29        return NULL;
     30    }
     31
     32    return file;
     33}
     34
     35// Define an input convolved image file, using the output as a basis
     36static pmFPAfile *defineInputConvolved(const char *inputName, // Input FPA file name
     37                                       pmFPAfile *outFile, // Corresponding output FPA file
     38                                       pmConfig *config, // Configuration
     39                                       pmFPAfileType type // Expected type
     40    )
     41{
     42    pmFPAview *view = pmFPAviewAlloc(0); // View into sky cells
     43    view->chip = view->cell = view->readout = 0;
     44
     45    psString imageName = pmFPANameFromRule(outFile->filerule, outFile->fpa, view);
     46    psArray *imageNames = psArrayAlloc(1);
     47    imageNames->data[0] = imageName;
     48    psMetadataAddArray(config->arguments, PS_LIST_TAIL, "INCONV.FILENAMES", PS_META_REPLACE,
     49                       "Filenames of input convolved image files", imageNames);
     50    psFree(imageNames);
     51    bool found = false;                 // Found the file?
     52    pmFPAfile *imageFile = pmFPAfileDefineFromArgs(&found, config, "PPSTACK.INCONV",
     53                                                   "INCONV.FILENAMES");
     54    psMetadataRemoveKey(config->arguments, "INCONV.FILENAMES");
     55    if (!imageFile || !found) {
     56        psError(PS_ERR_UNKNOWN, false, "Unable to define %s file", inputName);
     57        return NULL;
     58    }
     59    if (imageFile->type != type) {
     60        psError(PS_ERR_IO, true, "PPSTACK.INCONV is not of type %s",
     61                pmFPAfileStringFromType(type));
     62        return NULL;
     63    }
     64
     65    return imageFile;
     66}
     67#endif
     68
     69
    1270
    1371bool ppStackCamera(pmConfig *config)
     
    138196            }
    139197        }
     198
     199#if 0
     200        // Output convolved files
     201        pmFPAfile *outconvImage  = defineOutputConvolved("PPSTACK.OUTCONV", imageFile->fpa, config,
     202                                                         PM_FPA_FILE_IMAGE);
     203        pmFPAfile *outconvMask   = defineOutputConvolved("PPSTACK.OUTCONV.MASK", imageFile->fpa, config,
     204                                                         PM_FPA_FILE_MASK);
     205        pmFPAfile *outconvWeight = defineOutputConvolved("PPSTACK.OUTCONV.WEIGHT", imageFile->fpa, config,
     206                                                         PM_FPA_FILE_WEIGHT);
     207        if (!outconvImage || !outconvMask || !outconvWeight) {
     208            return false;
     209        }
     210
     211        // Input convolved files
     212        pmFPAfile *inconvImage  = defineInputConvolved("PPSTACK.INCONV", outconvImage, config,
     213                                                       PM_FPA_FILE_IMAGE);
     214        pmFPAfile *inconvMask   = defineInputConvolved("PPSTACK.INCONV.MASK", outconvMask, config,
     215                                                       PM_FPA_FILE_MASK);
     216        pmFPAfile *inconvWeight = defineInputConvolved("PPSTACK.INCONV.WEIGHT", outconvWeight, config,
     217                                                       PM_FPA_FILE_WEIGHT);
     218        if (!inconvImage || !inconvMask || !inconvWeight) {
     219            return false;
     220        }
     221#endif
    140222
    141223        psMetadataAddF32(imageFile->fpa->analysis, PS_LIST_TAIL, "PPSTACK.WEIGHTING", 0,
     
    241323    }
    242324
     325
    243326    // Output PSF
    244327    if (havePSFs) {
  • trunk/ppStack/src/ppStackLoop.c

    r15224 r16605  
    1111#include "ppStack.h"
    1212
     13// Here follows lists of files for activation/deactivation at various stages.  Each must be NULL-terminated.
     14
     15#if 0
     16// All files in the system
     17static char *allFiles[] = { "PPSTACK.INPUT", "PPSTACK.INPUT.MASK", "PPSTACK.INPUT.WEIGHT",
     18                            "PPSTACK.OUTPUT", "PPSTACK.OUTPUT.MASK", "PPSTACK.OUTPUT.WEIGHT",
     19                            "PSPHOT.PSF.SAVE", "PSPHOT.PSF.LOAD", "PPSTACK.SOURCES",
     20                            "PSPHOT.OUTPUT", "PSPHOT.RESID", "PSPHOT.BACKMDL", "PSPHOT.BACKMDL.STDEV",
     21                            "PSPHOT.BACKGND", "PSPHOT.BACKSUB", "SOURCE.PLOT.MOMENTS",
     22                            "SOURCE.PLOT.PSFMODEL", "SOURCE.PLOT.APRESID", "PSPHOT.INPUT.CMF",
     23                            0 };
     24#endif
     25
     26// Files required in preparation for convolution
     27static char *prepareFiles[] = { "PSPHOT.PSF.LOAD", "PPSTACK.SOURCES", 0 };
     28
     29// Files required for the convolution
     30static char *convolveFiles[] = { "PPSTACK.INPUT", "PPSTACK.INPUT.MASK", "PPSTACK.INPUT.WEIGHT", 0 };
     31
     32// Output files for the combination
     33static char *combineFiles[] = { "PPSTACK.OUTPUT", "PPSTACK.OUTPUT.MASK", "PPSTACK.OUTPUT.WEIGHT", 0 };
     34
     35// Files for photometry
     36static char *photFiles[] = { "PSPHOT.OUTPUT", "PSPHOT.RESID", "PSPHOT.BACKMDL",
     37                             "PSPHOT.BACKMDL.STDEV", "PSPHOT.BACKGND", "PSPHOT.BACKSUB",
     38                             "SOURCE.PLOT.MOMENTS", "SOURCE.PLOT.PSFMODEL", "SOURCE.PLOT.APRESID",
     39                             "PSPHOT.INPUT.CMF", 0 };
     40
     41//#define CONVOLVED_ALREADY               // Already have the convolution products --- testing
     42
     43
     44// Activate/deactivate a list of files
     45static void fileActivation(pmConfig *config, // Configuration
     46                           char **files, // Files to turn on/off
     47                           bool state   // Activation state
     48    )
     49{
     50    assert(config);
     51    assert(files);
     52
     53    for (int i = 0; files[i] != NULL; i++) {
     54        pmFPAfileActivate(config->files, state, files[i]);
     55    }
     56    return;
     57}
     58
     59// Activate/deactivate a single element for a list; return array of files
     60static psArray *fileActivationSingle(pmConfig *config, // Configuration
     61                                     char **files, // Files to turn on/off
     62                                     bool state,   // Activation state
     63                                     int num // Number of file in sequence
     64                                     )
     65{
     66    assert(config);
     67    assert(files);
     68
     69    psList *list = psListAlloc(NULL);   // List of files
     70
     71    for (int i = 0; files[i] != NULL; i++) {
     72        pmFPAfile *file = pmFPAfileActivateSingle(config->files, state, files[i], num); // Activated file
     73        psListAdd(list, PS_LIST_TAIL, file);
     74    }
     75
     76    psArray *array = psListToArray(list);
     77    psFree(list);
     78
     79    return array;
     80}
     81
     82#if 0
     83// Set the data level for a list of files
     84static void fileSetDataLevel(pmConfig *config, // Configuration
     85                             char **files, // Files for which to set level
     86                             pmFPALevel level // Level to set
     87                             )
     88{
     89    assert(config);
     90    assert(files);
     91
     92    for (int i = 0; files[i] != NULL; i++) {
     93        psArray *selected = pmFPAfileSelect(config->files, files[i]); // Selected files of interest
     94        for (int j = 0; j < selected->n; j++) {
     95            pmFPAfile *file = selected->data[j];
     96            assert(file);
     97            file->dataLevel = level;
     98        }
     99        psFree(selected);
     100    }
     101    return;
     102}
     103#endif
     104
     105// Iterate down the hierarchy, loading files; we can get away with this because we're working on skycells
     106static pmFPAview *filesIterateDown(pmConfig *config // Configuration
     107                                  )
     108{
     109    assert(config);
     110
     111    pmFPAview *view = pmFPAviewAlloc(0);// Pointer into FPA hierarchy
     112    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     113        return NULL;
     114    }
     115    view->chip = 0;
     116    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     117        return NULL;
     118    }
     119    view->cell = 0;
     120    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     121        return NULL;
     122    }
     123    view->readout = 0;
     124    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     125        return NULL;
     126    }
     127    return view;
     128}
     129
     130// Iterate up the hierarchy, writing files; we can get away with this because we're working on skycells
     131static bool filesIterateUp(pmConfig *config // Configuration
     132                           )
     133{
     134    assert(config);
     135
     136    pmFPAview *view = pmFPAviewAlloc(0);// Pointer into FPA hierarchy
     137    view->chip = view->cell = view->readout = 0;
     138    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     139        return false;
     140    }
     141    view->readout = -1;
     142    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     143        return false;
     144    }
     145    view->cell = -1;
     146    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     147        return false;
     148    }
     149    view->chip = -1;
     150    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     151        return false;
     152    }
     153    return true;
     154}
     155
     156#ifndef CONVOLVED_ALREADY
     157// Write an image to a FITS file
     158static bool writeImage(const char *name, // Name of image
     159                       psMetadata *header, // Header
     160                       const psImage *image // Image
     161                       )
     162{
     163    assert(name);
     164    assert(image);
     165
     166    psFits *fits = psFitsOpen(name, "w");
     167    if (!fits) {
     168        psError(PS_ERR_IO, false, "Unable to open FITS file to write image.");
     169        return false;
     170    }
     171    if (!psFitsWriteImage(fits, header, image, 0, NULL)) {
     172        psError(PS_ERR_IO, false, "Unable to write FITS image.");
     173        return false;
     174    }
     175    psFitsClose(fits);
     176    return true;
     177}
     178#endif
     179
     180
    13181bool ppStackLoop(pmConfig *config)
    14182{
     183    assert(config);
     184
    15185    psMaskType maskBlank = psMetadataLookupU8(NULL, config->arguments, "MASK.BLANK"); // Mask for blank reg.
    16186
     
    32202    }
    33203
    34     pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PPSTACK.INPUT"); // Token input file
    35     if (!input) {
    36         psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find input data!\n");
    37         return false;
    38     }
    39204    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PPSTACK.OUTPUT"); // Output file
    40205    if (!output) {
    41         psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find output data!\n");
    42         return false;
    43     }
    44 
    45     pmFPAview *view = pmFPAviewAlloc(0); // Pointer into FPA hierarchy
    46     pmHDU *lastHDU = NULL;              // Last HDU that was updated
    47 
    48     // Iterate over the FPA hierarchy
    49     if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    50         return false;
    51     }
    52 
    53     pmChip *chip;                       // Chip of interest
    54     while ((chip = pmFPAviewNextChip(view, input->fpa, 1)) != NULL) {
    55         if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    56             return false;
    57         }
    58 
    59         pmCell *cell;                // Cell of interest
    60         while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
    61             if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     206        psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find output data!");
     207        return false;
     208    }
     209    int num = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of inputs
     210    int numScans = psMetadataLookupS32(NULL, config->arguments, "ROWS"); // Number of scans to read at once
     211    psMetadata *ppsub = psMetadataLookupMetadata(NULL, config->recipes, "PPSUB"); // PPSUB recipe
     212    int overlap = 2 * psMetadataLookupS32(NULL, ppsub, "KERNEL.SIZE"); // Overlap by kernel size between consecutive scans
     213
     214    // Preparation iteration: Load the sources, and get a target PSF model
     215    pmReadout *sources = NULL;          // Readout with sources to use for PSF matching
     216    pmPSF *targetPSF = NULL;            // Target PSF
     217    {
     218        pmFPAfileActivate(config->files, false, NULL);
     219        fileActivation(config, prepareFiles, true);
     220        pmFPAview *view = filesIterateDown(config);
     221        if (!view) {
     222            return false;
     223        }
     224
     225        // We want to hang on to the 'sources' even when its host FPA is blown away
     226        sources = psMemIncrRefCounter(pmFPAfileThisReadout(config->files, view, "PPSTACK.SOURCES"));
     227        if (!sources) {
     228            psError(PS_ERR_UNKNOWN, true, "Unable to find sources.");
     229            psFree(view);
     230            return false;
     231        }
     232
     233        // Generate list of PSFs
     234        psMetadataIterator *fileIter = psMetadataIteratorAlloc(config->files, PS_LIST_HEAD,
     235                                                               "^PPSTACK.INPUT$"); // Iterator
     236        psMetadataItem *fileItem; // Item from iteration
     237        psList *psfList = psListAlloc(NULL); // List of PSFs for PSF envelope
     238        int numCols = 0, numRows = 0;   // Size of image
     239        while ((fileItem = psMetadataGetAndIncrement(fileIter))) {
     240            assert(fileItem->type == PS_DATA_UNKNOWN);
     241            pmFPAfile *inputFile = fileItem->data.V; // An input file
     242            pmChip *chip = pmFPAviewThisChip(view, inputFile->fpa); // The chip: holds the PSF
     243            pmPSF *psf = psMetadataLookupPtr(NULL, chip->analysis, "PSPHOT.PSF"); // PSF
     244            if (!psf) {
     245                psError(PS_ERR_UNKNOWN, false, "Unable to find PSF.");
     246                psFree(view);
     247                psFree(sources);
     248                psFree(fileIter);
     249                psFree(psfList);
    62250                return false;
    63251            }
    64 
    65             // Put version information into the header
     252            psListAdd(psfList, PS_LIST_TAIL, psf);
     253
     254            pmCell *cell = pmFPAviewThisCell(view, inputFile->fpa); // Cell of interest
    66255            pmHDU *hdu = pmHDUFromCell(cell);
    67             if (hdu && hdu != lastHDU) {
    68                 if (!hdu->header) {
    69                     hdu->header = psMetadataAlloc();
    70                 }
    71                 ppStackVersionMetadata(hdu->header);
    72                 lastHDU = hdu;
    73             }
    74 
    75             pmReadout *readout;         // Readout of interest
    76             while ((readout = pmFPAviewNextReadout(view, input->fpa, 1))) {
    77                 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     256            assert(hdu && hdu->header);
     257            int naxis1 = psMetadataLookupS32(NULL, hdu->header, "NAXIS1"); // Number of columns
     258            int naxis2 = psMetadataLookupS32(NULL, hdu->header, "NAXIS2"); // Number of rows
     259            if (naxis1 <= 0 || naxis2 <= 0) {
     260                psError(PS_ERR_UNKNOWN, false, "Unable to determine size of image from PSF.");
     261                psFree(view);
     262                psFree(sources);
     263                psFree(fileIter);
     264                psFree(psfList);
     265                return false;
     266            }
     267            if (numCols == 0 && numRows == 0) {
     268                numCols = naxis1;
     269                numRows = naxis2;
     270            }
     271        }
     272        psFree(fileIter);
     273        psFree(view);
     274
     275        targetPSF = ppStackPSF(config, numCols, numRows, psfList);
     276        psFree(psfList);
     277        if (!targetPSF) {
     278            psError(PS_ERR_UNKNOWN, false, "Unable to determine output PSF.");
     279            psFree(sources);
     280            return false;
     281        }
     282
     283        filesIterateUp(config);
     284    }
     285
     286    const char *suffix = "conv.fits";   // Suffix for convolved images; ultimately this will be from recipe
     287    const char *outName = psMetadataLookupStr(NULL, config->arguments, "OUTPUT"); // Output root
     288    assert(outName);
     289    psArray *imageNames = psArrayAlloc(num);
     290    psArray *maskNames = psArrayAlloc(num);
     291    psArray *weightNames = psArrayAlloc(num);
     292    for (int i = 0; i < num; i++) {
     293        psString imageName = NULL, maskName = NULL, weightName = NULL; // Names for convolved images
     294        psStringAppend(&imageName, "%s.im-%d.%s", outName, i, suffix);
     295        psStringAppend(&maskName, "%s.mk-%d.%s", outName, i, suffix);
     296        psStringAppend(&weightName, "%s.wt-%d.%s", outName, i, suffix);
     297        imageNames->data[i] = imageName;
     298        maskNames->data[i] = maskName;
     299        weightNames->data[i] = weightName;
     300    }
     301
     302    // Generate convolutions and write them to disk
     303    psArray *cells = psArrayAlloc(num); // Cells for convolved images --- a handle for reading again
     304    psArray *subKernels = psArrayAlloc(num); // Subtraction kernels --- required in the stacking
     305    psArray *subRegions = psArrayAlloc(num); // Subtraction regions --- required in the stacking
     306    for (int i = 0; i < num; i++) {
     307        pmFPAfileActivate(config->files, false, NULL);
     308        psArray *files = fileActivationSingle(config, convolveFiles, true, i);
     309        pmFPAview *view = filesIterateDown(config);
     310        if (!view) {
     311            psFree(sources);
     312            psFree(targetPSF);
     313            return false;
     314        }
     315
     316        pmReadout *readout = pmFPAviewThisReadout(view, ((pmFPAfile*)files->data[0])->fpa); // Input readout
     317        psFree(view);
     318
     319#ifndef CONVOLVED_ALREADY
     320        // Background subtraction, scaling and normalisation is performed automatically by the image matching
     321        psArray *regions = NULL, *kernels = NULL; // Regions and kernels used in subtraction
     322        if (!ppStackMatch(readout, &regions, &kernels, sources, targetPSF, config)) {
     323            psError(PS_ERR_UNKNOWN, false, "Unable to match image %d --- ignoring.", i);
     324            psFree(sources);
     325            psFree(targetPSF);
     326            return false;
     327        }
     328
     329        subRegions->data[i] = regions;
     330        subKernels->data[i] = kernels;
     331
     332        // Write the temporary convolved files
     333        pmHDU *hdu = readout->parent->parent->parent->hdu; // HDU for convolved image
     334        assert(hdu);
     335        writeImage(imageNames->data[i],  hdu->header, readout->image);
     336        writeImage(maskNames->data[i],   hdu->header, readout->mask);
     337        writeImage(weightNames->data[i], hdu->header, readout->weight);
     338#endif
     339
     340        cells->data[i] = psMemIncrRefCounter(readout->parent);
     341        filesIterateUp(config);
     342    }
     343    psFree(sources);
     344    psFree(targetPSF);
     345
     346    // Stack the convolved files
     347    {
     348        pmFPAfileActivate(config->files, false, NULL);
     349        fileActivation(config, combineFiles, true);
     350        if (psMetadataLookupBool(&mdok, config->arguments, "PHOTOMETRY")) {
     351            fileActivation(config, photFiles, true);
     352        }
     353        pmFPAview *view = filesIterateDown(config);
     354        if (!view) {
     355            psFree(cells);
     356            psFree(subKernels);
     357            psFree(subRegions);
     358            return false;
     359        }
     360        pmCell *outCell = pmFPAfileThisCell(config->files, view, "PPSTACK.OUTPUT"); // Output cell
     361        pmReadout *outRO = pmReadoutAlloc(outCell); // Output readout
     362
     363        psArray *readouts = psArrayAlloc(num); // Readouts for convolved images
     364        for (int i = 0; i < num; i++) {
     365            readouts->data[i] = pmReadoutAlloc(cells->data[i]); // Readout into which to read
     366        }
     367        psFree(cells);
     368
     369        // FITS files
     370        psArray *imageFits  = psArrayAlloc(num);
     371        psArray *maskFits   = psArrayAlloc(num);
     372        psArray *weightFits = psArrayAlloc(num);
     373        for (int i = 0; i < num; i++) {
     374            imageFits->data[i] = psFitsOpen(imageNames->data[i], "r");
     375            maskFits->data[i] = psFitsOpen(maskNames->data[i], "r");
     376            weightFits->data[i] = psFitsOpen(weightNames->data[i], "r");
     377        }
     378
     379        // Read convolutions by chunks
     380        bool more = true;               // More to read?
     381        for (int numChunk = 0; more; numChunk++) {
     382            for (int i = 0; i < num; i++) {
     383                pmReadout *readout = readouts->data[i];
     384                assert(readout);
     385
     386                if (!pmReadoutReadChunk(readout, imageFits->data[i], 0, numScans, overlap) ||
     387                    !pmReadoutReadChunkMask(readout, maskFits->data[i], 0, numScans, overlap) ||
     388                    !pmReadoutReadChunkWeight(readout, weightFits->data[i], 0, numScans, overlap)) {
     389                    psError(PS_ERR_IO, false, "Unable to read chunk %d for file %d", numChunk, i);
     390                    psFree(readouts);
     391                    psFree(subKernels);
     392                    psFree(subRegions);
     393                    psFree(outRO);
     394                    psFree(view);
    78395                    return false;
    79396                }
    80 
    81                 // Perform the analysis
    82                 if (!ppStackReadout(config, view)) {
    83                     psError(PS_ERR_UNKNOWN, false, "Unable to stack images.\n");
    84                     return false;
    85                 }
    86 
    87                 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    88                     return false;
    89                 }
    90             }
    91 
    92             // Perform statistics on the cell
    93             if (stats) {
    94                 ppStatsFPA(stats, output->fpa, view, maskBlank, config);
    95             }
    96 
    97             if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     397            }
     398
     399#ifdef TESTING
     400            {
     401                pmReadout *ro = readouts->data[0];
     402                psTrace("ppStack", 1, "Stack: [%d:%d,%d:%d]\n", ro->col0, ro->col0 + ro->image->numCols,
     403                        ro->row0, ro->row0 + ro->image->numRows);
     404            }
     405#endif
     406
     407            if (!ppStackReadout(config, outRO, readouts, subRegions, subKernels)) {
     408                psError(PS_ERR_UNKNOWN, false, "Unable to stack images.\n");
     409                psFree(readouts);
     410                psFree(subKernels);
     411                psFree(subRegions);
     412                psFree(outRO);
     413                psFree(view);
    98414                return false;
    99415            }
    100         }
    101 
    102         if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    103             return false;
    104         }
    105     }
    106 
    107     if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    108         return false;
    109     }
    110 
    111     psFree(view);
     416
     417            for (int i = 0; i < num && more; i++) {
     418                pmReadout *readout = readouts->data[i];
     419                assert(readout);
     420                more &= pmReadoutMore(readout, imageFits->data[i], 0, numScans);
     421                more &= pmReadoutMoreMask(readout, maskFits->data[i], 0, numScans);
     422                more &= pmReadoutMoreWeight(readout, weightFits->data[i], 0, numScans);
     423            }
     424        }
     425
     426        psFree(readouts);
     427        psFree(subKernels);
     428        psFree(subRegions);
     429        for (int i = 0; i < num; i++) {
     430            psFitsClose(imageFits->data[i]);
     431            psFitsClose(maskFits->data[i]);
     432            psFitsClose(weightFits->data[i]);
     433        }
     434
     435        if (psMetadataLookupBool(&mdok, config->arguments, "PHOTOMETRY") &&
     436            !ppStackPhotometry(config, outRO, view)) {
     437            psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry on output.");
     438            psFree(outRO);
     439            psFree(view);
     440            return false;
     441        }
     442
     443        // Statistics on output
     444        if (stats) {
     445            ppStatsFPA(stats, outCell->parent->parent, view, maskBlank, config);
     446        }
     447
     448        // Put version information into the header
     449        pmHDU *hdu = pmHDUFromCell(outRO->parent);
     450        if (!hdu) {
     451            psError(PS_ERR_UNKNOWN, false, "Unable to find HDU for output.");
     452            return false;
     453        }
     454        if (!hdu->header) {
     455            hdu->header = psMetadataAlloc();
     456        }
     457        ppStackVersionMetadata(hdu->header);
     458
     459        // Write out the output files
     460        fileActivation(config, combineFiles, true);
     461        filesIterateUp(config);
     462
     463        psFree(outRO);
     464        psFree(view);
     465    }
     466
    112467
    113468    // Write out summary statistics
  • trunk/ppStack/src/ppStackMatch.c

    r15850 r16605  
    99#include "ppStack.h"
    1010
     11#define ARRAY_BUFFER 16                 // Number to add to array at a time
     12
     13
    1114//#define TESTING
    1215
    13 bool ppStackMatch(pmReadout *output, const pmReadout *input, const pmReadout *sourcesRO,
    14                   const pmPSF *psf, const pmConfig *config)
     16bool ppStackMatch(pmReadout *readout, psArray **regions, psArray **kernels,
     17                  const pmReadout *sourcesRO, const pmPSF *psf, const pmConfig *config)
    1518{
     19    assert(readout);
     20    assert(regions && !*regions);
     21    assert(kernels && !*kernels);
     22    assert(sourcesRO);
     23    assert(psf);
     24    assert(config);
     25
    1626    // Look up appropriate values from the ppSub recipe
    1727    bool mdok;                          // Status of MD lookup
     
    6878    pmReadout *fake = pmReadoutAlloc(NULL); // Fake readout with target PSF
    6979
    70     if (!pmReadoutFakeFromSources(fake, input->image->numCols, input->image->numRows, sources, NULL, NULL,
     80    if (!pmReadoutFakeFromSources(fake, readout->image->numCols, readout->image->numRows, sources, NULL, NULL,
    7181                                  psf, powf(10.0, -0.4 * maxMag), 0, false)) {
    7282        psError(PS_ERR_UNKNOWN, false, "Unable to generate fake image with target PSF.");
     
    8595
    8696    // Do the image matching
    87     if (!pmSubtractionMatch(output, NULL, input, fake, footprint, regionSize, spacing, threshold,
     97    pmReadout *output = pmReadoutAlloc(NULL); // Output readout, for holding results temporarily
     98    if (!pmSubtractionMatch(output, NULL, readout, fake, footprint, regionSize, spacing, threshold,
    8899                            sources, stampsName, type, size, order, widths, orders, inner, ringsOrder,
    89100                            binning, optimum, optWidths, optOrder, optThresh, iter, rej, maskBad,
     
    92103        psFree(fake);
    93104        psFree(optWidths);
     105        psFree(output);
    94106        return false;
    95107    }
     
    97109    psFree(optWidths);
    98110
     111    // Replace original images with convolved
     112    psFree(readout->image);
     113    psFree(readout->mask);
     114    psFree(readout->weight);
     115    readout->image  = psMemIncrRefCounter(output->image);
     116    readout->mask   = psMemIncrRefCounter(output->mask);
     117    readout->weight = psMemIncrRefCounter(output->weight);
     118
     119    // Extract the regions and solutions used in the image matching
     120    // This stops them from being freed when we iterate back up the FPA
     121    *regions = psArrayAllocEmpty(ARRAY_BUFFER); // Array of regions
     122    {
     123        psString regex = NULL;          // Regular expression
     124        psStringAppend(&regex, "^%s$", PM_SUBTRACTION_ANALYSIS_REGION);
     125        psMetadataIterator *iter = psMetadataIteratorAlloc(output->analysis, PS_LIST_HEAD, regex); // Iterator
     126        psFree(regex);
     127        psMetadataItem *item = NULL;// Item from iteration
     128        while ((item = psMetadataGetAndIncrement(iter))) {
     129            assert(item->type == PS_DATA_REGION);
     130            *regions = psArrayAdd(*regions, ARRAY_BUFFER, item->data.V);
     131        }
     132        psFree(iter);
     133    }
     134    *kernels = psArrayAllocEmpty(ARRAY_BUFFER); // Array of kernels
     135    {
     136        psString regex = NULL;          // Regular expression
     137        psStringAppend(&regex, "^%s$", PM_SUBTRACTION_ANALYSIS_KERNEL);
     138        psMetadataIterator *iter = psMetadataIteratorAlloc(output->analysis, PS_LIST_HEAD, regex); // Iterator
     139        psFree(regex);
     140        psMetadataItem *item = NULL;// Item from iteration
     141        while ((item = psMetadataGetAndIncrement(iter))) {
     142            assert(item->type == PS_DATA_UNKNOWN);
     143            // Set the normalisation dimensions, since these will be otherwise unavailable when reading the
     144            // images by scans.
     145            pmSubtractionKernels *kernel = item->data.V; // Kernel used in subtraction
     146            kernel->numCols = readout->image->numCols;
     147            kernel->numRows = readout->image->numRows;
     148
     149            *kernels = psArrayAdd(*kernels, ARRAY_BUFFER, kernel);
     150        }
     151        psFree(iter);
     152    }
     153    assert((*regions)->n == (*kernels)->n);
     154
     155
     156    psFree(output);
     157
    99158    return true;
    100159}
  • trunk/ppStack/src/ppStackReadout.c

    r15849 r16605  
    1010#include "ppStack.h"
    1111
    12 #define ARRAY_BUFFER 16                 // Number to add to array at a time
    1312#define WCS_TOLERANCE 0.001             // Tolerance for WCS
    1413
    15 //#define NO_CONVOLUTION                  // Don't perform convolutions?
    16 //#define CONVOLUTION_FILES               // Write convolutions?
    1714//#define REJECTION_FILES                 // Write rejection mask?
    1815//#define INSPECTION_FILES                // Write inspection mask?
    1916
    20 bool ppStackReadout(pmConfig *config, const pmFPAview *view)
     17static int sectionNum = 0;              // Section number; for debugging outputs
     18
     19
     20bool ppStackReadout(const pmConfig *config, pmReadout *outRO, const psArray *readouts,
     21                    const psArray *regions, const psArray *kernels)
    2122{
     23    assert(config);
     24    assert(outRO);
     25    assert(readouts);
     26    assert(regions);
     27    assert(kernels);
     28    assert(readouts->n == regions->n);
     29    assert(regions->n == kernels->n);
     30
     31
    2232    // Get the recipe values
    23     bool mdok;                          // Status of MD lookup
    2433    int iter = psMetadataLookupS32(NULL, config->arguments, "ITER"); // Rejection iterations
    2534    float combineRej = psMetadataLookupF32(NULL, config->arguments, "COMBINE.REJ"); // Combination threshold
     
    2736    psMaskType maskBlank = psMetadataLookupU8(NULL, config->arguments, "MASK.BLANK"); // Mask for blank reg.
    2837    float threshold = psMetadataLookupF32(NULL, config->arguments, "THRESHOLD.MASK"); // Threshold for mask deconvolution
    29     bool photometry = psMetadataLookupBool(&mdok, config->arguments, "PHOTOMETRY"); // Perform photometry?
    30     int psfInstances = psMetadataLookupS32(&mdok, config->arguments, "PSF.INSTANCES"); // Number of instances for PSF
    31     float psfRadius = psMetadataLookupF32(NULL, config->arguments, "PSF.RADIUS"); // Radius for PSF
    32     const char *psfModel = psMetadataLookupStr(NULL, config->arguments, "PSF.MODEL"); // Model for PSF
    33     int psfOrder = psMetadataLookupS32(&mdok, config->arguments, "PSF.ORDER"); // Spatial order for PSF
    34 
    35     // Get the output target
    36     pmCell *outCell = pmFPAfileThisCell(config->files, view, "PPSTACK.OUTPUT"); // Output cell
    37     pmReadout *outRO = pmReadoutAlloc(outCell); // Output readout
    38     pmFPA *outFPA = outCell->parent->parent; // Output FPA
    39 
    40     int num = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of inputs
    41     assert(num > 0);
    42 
    43     // Get the input sources
    44     psArray *stack = psArrayAllocEmpty(ARRAY_BUFFER); // The stack of inputs
    45     pmReadout *sources = pmFPAfileThisReadout(config->files, view, "PPSTACK.SOURCES"); // Sources for stamps
    46     psMetadataIterator *fileIter = psMetadataIteratorAlloc(config->files, PS_LIST_HEAD,
    47                                                            "^PPSTACK.INPUT$"); // Iterator over input files
    48     psMetadataItem *fileItem;           // Item from iteration
    49     int fileNum = 0;                    // Number of file
    50     psList *psfList = psListAlloc(NULL); // List of PSFs for PSF envelope
    51     pmPSF *outPSF = NULL;               // Ouptut PSF
    52     int numCols = 0, numRows = 0;       // Size of image
    53     while ((fileItem = psMetadataGetAndIncrement(fileIter))) {
    54         assert(fileItem->type == PS_DATA_UNKNOWN);
    55         pmFPAfile *inputFile = fileItem->data.V; // An input file
    56         pmReadout *ro = pmFPAviewThisReadout(view, inputFile->fpa); // Corresponding readout
    57         pmCell *cell = ro->parent;      // The cell
    58         pmChip *chip = cell->parent;    // The chip: holds the PSF
    59 
    60         bool mdok;                      // Status of MD lookup
    61         pmPSF *psf = psMetadataLookupPtr(&mdok, chip->analysis, "PSPHOT.PSF");
    62         if (mdok && psf) {
    63             psListAdd(psfList, PS_LIST_TAIL, psf);
    64             if (numCols == 0 && numRows == 0) {
    65                 numCols = ro->image->numCols;
    66                 numRows = ro->image->numRows;
    67             }
    68         }
    69     }
    70 
    71     bool convolve = false;              // Convolve the input images?
    72     if (psfList->n > 0) {
    73         psArray *psfArray = psListToArray(psfList); // Array of PSFs
    74         outPSF = pmPSFEnvelope(numCols, numRows, psfArray, psfInstances, psfRadius, psfModel,
    75                                psfOrder, psfOrder);
    76         psFree(psfArray);
    77         if (!outPSF) {
    78             psError(PS_ERR_UNKNOWN, false, "Unable to determine output PSF.");
    79             // XXX Free stuff
    80             return false;
    81         }
    82         convolve = true;
    83         PS_ASSERT_PTR_NON_NULL(sources, false);
    84     }
    85 
    86     // Iterate through again to get the convolved images (or not)
    87 
    88     psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics
    89     psRandom *rng = psRandomAlloc(0, PS_RANDOM_TAUS); // Random number generator
     38
     39    int num = readouts->n;              // Number of inputs
     40    psArray *stack = psArrayAlloc(num); // Array for stacking
     41
     42    pmCell *outCell = outRO->parent;    // Output cell
     43    pmChip *outChip = outCell->parent;  // Output chip
     44    pmFPA *outFPA = outChip->parent;    // Output FPA
     45
    9046    float totExposure = 0.0;            // Total exposure time
    9147    psList *fpaList = psListAlloc(NULL); // List of input FPAs, for concept averaging
    9248    psList *cellList = psListAlloc(NULL); // List of input cells, for concept averaging
    93 
    94     psMetadataIteratorSet(fileIter, PS_LIST_HEAD);
    95     fileNum = 0;
    96     while ((fileItem = psMetadataGetAndIncrement(fileIter))) {
    97         assert(fileItem->type == PS_DATA_UNKNOWN);
    98         pmFPAfile *inputFile = fileItem->data.V; // An input file
    99         pmReadout *ro = pmFPAviewThisReadout(view, inputFile->fpa); // Corresponding readout
     49    for (int i = 0; i < num; i++) {
     50        pmReadout *ro = readouts->data[i];
     51        assert(ro);
     52        pmFPA *fpa = ro->parent->parent->parent; // Parent FPA
    10053
    10154        bool mdok;                      // Status of MD lookup
    102         float weighting = psMetadataLookupF32(&mdok, inputFile->fpa->analysis,
    103                                               "PPSTACK.WEIGHTING"); // Relative weighting
     55        float weighting = psMetadataLookupF32(&mdok, fpa->analysis, "PPSTACK.WEIGHTING"); // Relative weight
    10456        if (!mdok || !isfinite(weighting)) {
    105             psWarning("No WEIGHTING supplied for image %d --- set to unity.", fileNum);
     57            psWarning("No WEIGHTING supplied for image %d --- set to unity.", i);
    10658            weighting = 1.0;
    10759        }
    108         float scale = psMetadataLookupF32(&mdok, inputFile->fpa->analysis, "PPSTACK.SCALE"); // Rel. scale
    109         if (!mdok || !isfinite(scale)) {
    110             psWarning("No SCALE supplied for image %d --- set to unity.", fileNum);
    111             scale = 1.0;
    112         }
    11360
    11461        float exposure = psMetadataLookupF32(NULL, ro->parent->concepts, "CELL.EXPOSURE"); // Exposure time
    115 #if 0
    11662        if (!isfinite(exposure)) {
    11763            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    11864                    "CELL.EXPOSURE is not set for input file %ld", stack->n);
    119             psFree(stats);
    120             psFree(rng);
    121             psFree(fileIter);
    12265            psFree(fpaList);
    12366            psFree(cellList);
    124             psFree(outRO);
    12567            psFree(stack);
    12668            return false;
    12769        }
    128 #endif
    12970        totExposure += exposure;        // Total exposure time
    13071
    131         // Generate convolved version of input
    132         pmReadout *convolved;
    133         if (convolve) {
    134             convolved = pmReadoutAlloc(NULL); // Convolved version of input readout
    135             // Background subtraction, scaling and normalisation is performed automatically by the image
    136             // matching
    137             if (!ppStackMatch(convolved, ro, sources, outPSF, config)) {
    138                 psWarning("Unable to match image %d --- ignoring.", fileNum);
    139                 psErrorClear();
    140                 psFree(convolved);
    141                 // XXX Free the bad image so it's not taking up good memory!
    142                 continue;
    143             }
    144 
    145 #ifdef CONVOLUTION_FILES
    146             if (convolved->image) {
    147                 psString name = NULL;           // Name of image
    148                 psStringAppend(&name, "convolved%03d_image.fits", fileNum);
    149                 psFits *fits = psFitsOpen(name, "w");
    150                 psFree(name);
    151                 psFitsWriteImage(fits, NULL, convolved->image, 0, NULL);
    152                 psFitsClose(fits);
    153             }
    154             if (convolved->mask) {
    155                 psString name = NULL;           // Name of image
    156                 psStringAppend(&name, "convolved%03d_mask.fits", fileNum);
    157                 psFits *fits = psFitsOpen(name, "w");
    158                 psFree(name);
    159                 psFitsWriteImage(fits, NULL, convolved->mask, 0, NULL);
    160                 psFitsClose(fits);
    161             }
    162             if (convolved->weight) {
    163                 psString name = NULL;           // Name of image
    164                 psStringAppend(&name, "convolved%03d_weight.fits", fileNum);
    165                 psFits *fits = psFitsOpen(name, "w");
    166                 psFree(name);
    167                 psFitsWriteImage(fits, NULL, convolved->weight, 0, NULL);
    168                 psFitsClose(fits);
    169             }
    170 #endif // CONVOLUTION_FILES
    171 
    172         } else {
    173             // No convolution --- just use the unconvolved images as the "convolved" images, with some tweaks
    174             convolved = psMemIncrRefCounter(ro);
    175             sources = NULL;
    176 
    177             // Brain-dead background subtraction
    178             if (!psImageBackground(stats, NULL, ro->image, ro->mask, maskBad, rng)) {
    179                 psError(PS_ERR_UNKNOWN, false, "Unable to get image background on image %ld", stack->n);
    180                 psFree(stats);
    181                 psFree(rng);
    182                 psFree(fileIter);
    183                 psFree(fpaList);
    184                 psFree(cellList);
    185                 psFree(stack);
    186                 psFree(outRO);
    187                 psFree(convolved);
    188                 return false;
    189             }
    190             psTrace("ppStack", 3, "Background for image %d is %f\n", fileNum, stats->robustMedian);
    191             (void)psBinaryOp(ro->image, ro->image, "-", psScalarAlloc(stats->robustMedian, PS_TYPE_F32));
    192 
    193             // Apply scaling
    194             (void)psBinaryOp(ro->image, ro->image, "*", psScalarAlloc(1.0 / scale, PS_TYPE_F32));
    195 
    196             // Normalise each input by the exposure time
    197             float exposure = psMetadataLookupF32(NULL, ro->parent->concepts, "CELL.EXPOSURE");// Exposure time
    198             if (!isfinite(exposure)) {
    199                 psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    200                         "CELL.EXPOSURE is not set for input file %ld", stack->n);
    201                 psFree(stats);
    202                 psFree(rng);
    203                 psFree(fileIter);
    204                 psFree(fpaList);
    205                 psFree(cellList);
    206                 psFree(outRO);
    207                 psFree(convolved);
    208                 psFree(stack);
    209                 return false;
    210             }
    211 
    212             (void)psBinaryOp(ro->image, ro->image, "/", psScalarAlloc(exposure, PS_TYPE_F32));
    213             if (ro->weight) {
    214                 (void)psBinaryOp(ro->weight, ro->weight, "/", psScalarAlloc(exposure, PS_TYPE_F32));
    215             }
    216         }
    217 
    218         if (fileNum == 0) {
     72#if 0
     73        if (i == 0) {
    21974            // Copy astrometry over
    220             pmFPA *fpa = ro->parent->parent->parent; // Template FPA
    22175            pmHDU *hdu = fpa->hdu; // Template HDU
    22276            pmHDU *outHDU = outFPA->hdu; // Output HDU
     
    22478                psWarning("Unable to find HDU at FPA level to copy astrometry.");
    22579            } else {
    226                 if (!pmAstromReadWCS(outFPA, outCell->parent, hdu->header, 1.0)) {
     80                if (!pmAstromReadWCS(outFPA, outChip, hdu->header, 1.0)) {
    22781                    psErrorClear();
    22882                    psWarning("Unable to read WCS astrometry from input FPA.");
     
    23185                        outHDU->header = psMetadataAlloc();
    23286                    }
    233                     if (!pmAstromWriteWCS(outHDU->header, outFPA, outCell->parent, WCS_TOLERANCE)) {
     87                    if (!pmAstromWriteWCS(outHDU->header, outFPA, outChip, WCS_TOLERANCE)) {
    23488                        psErrorClear();
    23589                        psWarning("Unable to write WCS astrometry to output FPA.");
     
    23892            }
    23993        }
    240 
    241         // Don't need the original any more!
    242         psFree(ro);
     94#endif
    24395
    24496        // Ensure there is a mask, or pmStackCombine will complain
    245         if (!convolved->mask) {
    246             convolved->mask = psImageAlloc(convolved->image->numCols, convolved->image->numRows,
    247                                            PS_TYPE_MASK);
    248             psImageInit(convolved->mask, 0);
    249         }
    250 
    251         psListAdd(fpaList, PS_LIST_TAIL, inputFile->fpa);
     97        if (!ro->mask) {
     98            ro->mask = psImageAlloc(ro->image->numCols, ro->image->numRows, PS_TYPE_MASK);
     99            psImageInit(ro->mask, 0);
     100        }
     101
     102        psListAdd(fpaList, PS_LIST_TAIL, fpa);
    252103        psListAdd(cellList, PS_LIST_TAIL, ro->parent);
    253104
    254         pmStackData *data = pmStackDataAlloc(convolved, weighting); // Data to stack
    255         psFree(convolved);
    256         psArrayAdd(stack, ARRAY_BUFFER, data);
    257         psFree(data);                   // Drop reference
    258 
    259         fileNum++;
    260     }
    261     psFree(fileIter);
    262     psFree(stats);
    263     psFree(rng);
    264 
    265     if (fileNum == 0) {
    266         psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Not enough good files to combine.");
    267         psFree(fpaList);
    268         psFree(cellList);
    269         psFree(stack);
    270         psFree(outRO);
    271         return false;
     105        stack->data[i] = pmStackDataAlloc(ro, weighting);
    272106    }
    273107
     
    277111        psFree(cellList);
    278112        psFree(stack);
    279         psFree(outRO);
    280113        return false;
    281114    }
     
    283116#ifdef INSPECTION_FILES
    284117    {
    285         psFits *fits = psFitsOpen("combined.fits", "w");
     118        psString name = NULL;           // Name of image
     119        psStringAppend(&name, "combined_%03d.fits", sectionNum);
     120        psFits *fits = psFitsOpen(name, "w");
     121        psFree(name);
    286122        psFitsWriteImage(fits, NULL, outRO->image, 0, NULL);
    287123        psFitsClose(fits);
     
    291127        pmStackData *data = stack->data[i]; // Data for this image
    292128        psImage *inspected = psPixelsToMask(NULL, data->pixels,
    293                                             psRegionSet(0, data->readout->image->numCols,
    294                                                         0, data->readout->image->numRows),
     129                                            psRegionSet(0, data->readout->image->numCols - 1,
     130                                                        0, data->readout->image->numRows - 1),
    295131                                            maskBlank);
    296132        psString name = NULL;           // Name of image
    297         psStringAppend(&name, "inspect%03d.fits", i);
     133        psStringAppend(&name, "inspect_%03d_%03d.fits", sectionNum, i);
    298134        psFits *fits = psFitsOpen(name, "w");
    299135        psFree(name);
     
    304140#endif
    305141
    306     for (int i = 0; i < stack->n; i++) {
     142    // Reject pixels
     143    for (int i = 0; i < num; i++) {
    307144        pmStackData *data = stack->data[i]; // Data for this image
    308         pmReadout *readout = data->readout; // Readout for this image
    309 
    310         // Extract the regions and solutions used in the image matching
    311         psArray *regions = psArrayAllocEmpty(ARRAY_BUFFER); // Array of regions
    312         {
    313             psMetadataIterator *iter = psMetadataIteratorAlloc(readout->analysis, PS_LIST_HEAD,
    314                                                                "^SUBTRACTION.REGION$"); // Iterator
    315             psMetadataItem *item = NULL;// Item from iteration
    316             while ((item = psMetadataGetAndIncrement(iter))) {
    317                 assert(item->type == PS_DATA_REGION);
    318                 regions = psArrayAdd(regions, ARRAY_BUFFER, item->data.V);
    319             }
    320             psFree(iter);
    321         }
    322         psArray *solutions = psArrayAllocEmpty(ARRAY_BUFFER); // Array of solutions
    323         {
    324             psMetadataIterator *iter = psMetadataIteratorAlloc(readout->analysis, PS_LIST_HEAD,
    325                                                                "^SUBTRACTION.SOLUTION$"); // Iterator
    326             psMetadataItem *item = NULL;// Item from iteration
    327             while ((item = psMetadataGetAndIncrement(iter))) {
    328                 assert(item->type == PS_DATA_VECTOR);
    329                 solutions = psArrayAdd(solutions, ARRAY_BUFFER, item->data.V);
    330             }
    331             psFree(iter);
    332         }
    333         assert(regions->n == solutions->n);
    334 
    335         pmSubtractionKernels *kernels = psMetadataLookupPtr(NULL, readout->analysis,
    336                                                             "SUBTRACTION.KERNEL"); // Kernels
    337 
    338         psPixels *reject = pmStackReject(data->pixels, threshold, regions,
    339                                          solutions, kernels); // List of pixels to reject
     145        pmReadout *readout = data->readout; // Readout of interest
     146        int col0 = readout->col0, row0 = readout->row0; // Offset for readout
     147        int numCols = readout->image->numCols, numRows = readout->image->numRows; // Size of image
     148
     149        psRegion *valid = psRegionAlloc(col0, col0 + numCols, row0, row0 + numRows); // Valid region for rej
     150        psPixels *reject = pmStackReject(data->pixels, valid, threshold, regions->data[i],
     151                                         kernels->data[i]); // Pixels to reject
     152        psFree(valid);
    340153        psFree(data->pixels);
    341154        data->pixels = reject;
    342 
    343         psFree(solutions);
    344         psFree(regions);
    345155    }
    346156
     
    352162        }
    353163        psImage *rejected = psPixelsToMask(NULL, data->pixels,
    354                                            psRegionSet(0, data->readout->image->numCols,
    355                                                        0, data->readout->image->numRows),
     164                                           psRegionSet(0, data->readout->image->numCols - 1,
     165                                                       0, data->readout->image->numRows - 1),
    356166                                           maskBlank);
    357167        psString name = NULL;           // Name of image
    358         psStringAppend(&name, "reject%03d.fits", i);
     168        psStringAppend(&name, "reject_%03d_%03d.fits", sectionNum, i);
    359169        psFits *fits = psFitsOpen(name, "w");
    360170        psFree(name);
     
    370180        psFree(cellList);
    371181        psFree(stack);
    372         psFree(outRO);
    373182        return false;
    374     }
    375 
    376     if (!convolve) {
    377         // Restore image to counts using the total exposure time
    378         (void)psBinaryOp(outRO->image, outRO->image, "*", psScalarAlloc(totExposure, PS_TYPE_F32));
    379         if (outRO->weight) {
    380             (void)psBinaryOp(outRO->weight, outRO->weight, "*", psScalarAlloc(totExposure, PS_TYPE_F32));
    381         }
    382183    }
    383184
     
    397198    psFree(cellList);
    398199
    399     if (photometry) {
    400         pmFPAfile *photFile = psMetadataLookupPtr(NULL, config->files, "PSPHOT.INPUT");
    401         pmFPACopy(photFile->fpa, outRO->parent->parent->parent);
    402 
    403         if (!psphotReadout(config, view)) {
    404             psWarning("Unable to perform photometry on stacked image.");
    405             psErrorStackPrint(stderr, "Error stack from photometry:");
    406             psErrorClear();
    407         }
    408 
    409         pmFPAfileActivate(config->files, false, "PSPHOT.INPUT");
    410     }
    411 
    412200    psFree(stack);
    413     psFree(outRO);                      // Drop reference
     201
     202    sectionNum++;
    414203
    415204    return true;
Note: See TracChangeset for help on using the changeset viewer.