IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 26076 for trunk/ppStack


Ignore:
Timestamp:
Nov 9, 2009, 2:53:12 PM (17 years ago)
Author:
Paul Price
Message:

Merging branches/pap (unconvolved stacks, reworked combinePixels function into clearer roles, only throw out most variant pixel on each iteration, throw suspect pixels out as first rejection step) stack development. I think I've got everything, but not entirely sure, since I've already merged this branch once before (for dual convolution).

Location:
trunk/ppStack
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/ppStack

  • trunk/ppStack/src/ppStack.h

    r23573 r26076  
    5959// Perform stacking on a readout
    6060//
    61 // Returns an array of pixels to inspect for each input image
     61// Returns two arrays: pixels to inspect for each input image, and pixels to reject for each input image.
    6262psArray *ppStackReadoutInitial(const pmConfig *config,   // Configuration
    6363                               pmReadout *outRO,   // Output readout
     
    8383                         const psArray *rejected, // Array with pixels rejected in each image
    8484                         const psVector *weightings, // Weighting factors for each image
    85                          const psVector *addVariance // Additional variance for rejection
     85                         const psVector *addVariance, // Additional variance for rejection
     86                         bool safety,                 // Enable safety switch?
     87                         const psVector *norm         // Normalisations to apply
    8688    );
    8789
  • trunk/ppStack/src/ppStackArguments.c

    r23841 r26076  
    148148    psMetadataAddStr(arguments, PS_LIST_TAIL, "-stamps", 0, "Stamps file with x,y,flux per line", NULL);
    149149    psMetadataAddStr(arguments, PS_LIST_TAIL, "-stats", 0, "Statistics file", NULL);
    150     psMetadataAddS32(arguments, PS_LIST_TAIL, "-iter", 0, "Number of rejection iterations", 0);
     150    psMetadataAddF32(arguments, PS_LIST_TAIL, "-combine-iter", 0, "Number of rejection iterations per input", NAN);
    151151    psMetadataAddF32(arguments, PS_LIST_TAIL, "-combine-rej", 0,
    152152                     "Combination rejection thresold (sigma)", NAN);
     
    250250    }
    251251
    252     VALUE_ARG_RECIPE_INT("-iter",              "ITER",            S32, 0);
     252    VALUE_ARG_RECIPE_FLOAT("-combine-iter",    "COMBINE.ITER",    F32);
    253253    VALUE_ARG_RECIPE_FLOAT("-combine-rej",     "COMBINE.REJ",     F32);
    254254    VALUE_ARG_RECIPE_FLOAT("-combine-sys",     "COMBINE.SYS",     F32);
     
    260260    VALUE_ARG_RECIPE_FLOAT("-poor-frac",       "POOR.FRACTION",   F32);
    261261
    262     valueArgRecipeStr(arguments, recipe, "-mask-val",  "MASK.VAL",  recipe);
     262    valueArgRecipeStr(arguments, recipe, "-mask-val",  "MASK.IN",   recipe);
    263263    valueArgRecipeStr(arguments, recipe, "-mask-bad",  "MASK.BAD",  recipe);
    264264    valueArgRecipeStr(arguments, recipe, "-mask-poor", "MASK.POOR", recipe);
  • trunk/ppStack/src/ppStackCamera.c

    r25519 r26076  
    233233
    234234    // Output image
    235     pmFPA *fpa = pmFPAConstruct(config->camera, config->cameraName); // FPA to contain the output
    236     if (!fpa) {
     235    pmFPA *outFPA = pmFPAConstruct(config->camera, config->cameraName); // FPA to contain the output
     236    if (!outFPA) {
    237237        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to construct an FPA from camera configuration.");
    238238        return false;
    239239    }
    240     pmFPAfile *output = pmFPAfileDefineOutput(config, fpa, "PPSTACK.OUTPUT");
    241     psFree(fpa);                        // Drop reference
     240    pmFPAfile *output = pmFPAfileDefineOutput(config, outFPA, "PPSTACK.OUTPUT");
     241    psFree(outFPA);                        // Drop reference
    242242    if (!output) {
    243243        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSTACK.OUTPUT"));
     
    250250    output->save = true;
    251251
    252     if (!pmFPAAddSourceFromFormat(fpa, "Stack", output->format)) {
     252    if (!pmFPAAddSourceFromFormat(outFPA, "Stack", output->format)) {
    253253        psError(PS_ERR_UNKNOWN, false, "Unable to generate output FPA.");
    254         psFree(fpa);
    255254        return false;
    256255    }
     
    294293        targetPSF->save = true;
    295294    }
     295
     296#if 1
     297    // Unconvolved stack
     298    pmFPA *unconvFPA = pmFPAConstruct(config->camera, config->cameraName); // FPA to contain unconvolved output
     299    if (!unconvFPA) {
     300        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to construct an FPA from camera configuration.");
     301        return false;
     302    }
     303    pmFPAfile *unConv = pmFPAfileDefineOutput(config, unconvFPA, "PPSTACK.UNCONV");
     304    psFree(unconvFPA);                  // Drop reference
     305    if (!unConv) {
     306        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSTACK.UNCONV"));
     307        return false;
     308    }
     309    if (unConv->type != PM_FPA_FILE_IMAGE) {
     310        psError(PS_ERR_IO, true, "PPSTACK.UNCONV is not of type IMAGE");
     311        return false;
     312    }
     313    unConv->save = true;
     314
     315    if (!pmFPAAddSourceFromFormat(unconvFPA, "Stack", unConv->format)) {
     316        psError(PS_ERR_UNKNOWN, false, "Unable to generate output FPA.");
     317        return false;
     318    }
     319
     320    // Unconvolved mask
     321    pmFPAfile *unconvMask = pmFPAfileDefineOutput(config, unconvFPA, "PPSTACK.UNCONV.MASK");
     322    if (!unconvMask) {
     323        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSTACK.UNCONV.MASK"));
     324        return false;
     325    }
     326    if (unconvMask->type != PM_FPA_FILE_MASK) {
     327        psError(PS_ERR_IO, true, "PPSTACK.UNCONV.MASK is not of type MASK");
     328        return false;
     329    }
     330    unconvMask->save = true;
     331
     332    // Unconvolved variance
     333    if (haveVariances) {
     334        pmFPAfile *unconvVariance = pmFPAfileDefineOutput(config, unconvFPA, "PPSTACK.UNCONV.VARIANCE");
     335        if (!unconvVariance) {
     336            psError(PS_ERR_IO, false, _("Unable to generate output file from PPSTACK.UNCONV.VARIANCE"));
     337            return false;
     338        }
     339        if (unconvVariance->type != PM_FPA_FILE_VARIANCE) {
     340            psError(PS_ERR_IO, true, "PPSTACK.UNCONV.VARIANCE is not of type VARIANCE");
     341            return false;
     342        }
     343        unconvVariance->save = true;
     344    }
     345#endif
    296346
    297347    // Output JPEGs
  • trunk/ppStack/src/ppStackCleanup.c

    r23341 r26076  
    7474
    7575        if (tempDelete) {
    76             psString imageResolved = pmConfigConvertFilename(options->imageNames->data[i],
     76            psString imageResolved = pmConfigConvertFilename(options->convImages->data[i],
    7777                                                             config, false, false);
    78             psString maskResolved = pmConfigConvertFilename(options->maskNames->data[i],
     78            psString maskResolved = pmConfigConvertFilename(options->convMasks->data[i],
    7979                                                            config, false, false);
    80             psString varianceResolved = pmConfigConvertFilename(options->varianceNames->data[i],
     80            psString varianceResolved = pmConfigConvertFilename(options->convVariances->data[i],
    8181                                                                config, false, false);
    8282            if (unlink(imageResolved) == -1 || unlink(maskResolved) == -1 ||
  • trunk/ppStack/src/ppStackCombineFinal.c

    r25096 r26076  
    1010#include "ppStackLoop.h"
    1111
    12 bool ppStackCombineFinal(ppStackThreadData *stack, ppStackOptions *options, pmConfig *config)
     12//#define TESTING                         // Enable test output
     13
     14bool ppStackCombineFinal(pmReadout *target, ppStackThreadData *stack, psArray *covariances,
     15                         ppStackOptions *options, pmConfig *config, bool safe, bool normalise)
    1316{
    1417    psAssert(stack, "Require stack");
    1518    psAssert(options, "Require options");
    1619    psAssert(config, "Require configuration");
     20
     21    if (!target->mask) {
     22        target->mask = psImageAlloc(target->image->numCols, target->image->numRows, PS_TYPE_IMAGE_MASK);
     23    }
    1724
    1825    stack->lastScan = 0;            // Reset read
     
    3037        }
    3138
    32         // call: ppStackReadoutFinal(config, outRO, readouts, rejected)
     39        // call: ppStackReadoutFinal(config, target, readouts, rejected)
    3340        psThreadJob *job = psThreadJobAlloc("PPSTACK_FINAL_COMBINE"); // Job to start
     41        psArrayAdd(job->args, 1, target);
    3442        psArrayAdd(job->args, 1, thread);
    3543        psArrayAdd(job->args, 1, options);
    3644        psArrayAdd(job->args, 1, config);
     45        PS_ARRAY_ADD_SCALAR(job->args, safe, PS_TYPE_U8);
     46        PS_ARRAY_ADD_SCALAR(job->args, normalise, PS_TYPE_U8);
    3747        if (!psThreadJobAddPending(job)) {
    3848            psFree(job);
     
    4858
    4959    // Sum covariance matrices
    50     double sumWeights = 0.0;            // Sum of weights
    51     for (int i = 0; i < options->num; i++) {
    52         if (options->inputMask->data.U8[i]) {
    53             psFree(options->covariances->data[i]);
    54             options->covariances->data[i] = NULL;
    55             continue;
     60    if (covariances) {
     61        double sumWeights = 0.0;            // Sum of weights
     62        for (int i = 0; i < options->num; i++) {
     63            if (options->inputMask->data.U8[i]) {
     64                psFree(covariances->data[i]);
     65                covariances->data[i] = NULL;
     66                continue;
     67            }
     68            psKernel *covar = covariances->data[i]; // Covariance matrix
     69            if (!covar) {
     70                continue;
     71            }
     72            float weight = options->weightings->data.F32[i]; // Weight to apply
     73            psBinaryOp(covar->image, covar->image, "*", psScalarAlloc(weight, PS_TYPE_F32));
     74            sumWeights += weight;
    5675        }
    57         psKernel *covar = options->covariances->data[i]; // Covariance matrix
    58         if (!covar) {
    59             continue;
     76        if (sumWeights > 0.0) {
     77            target->covariance = psImageCovarianceSum(covariances);
     78            psBinaryOp(target->covariance->image, target->covariance->image, "/",
     79                       psScalarAlloc(sumWeights, PS_TYPE_F32));
     80            psImageCovarianceTransfer(target->variance, target->covariance);
    6081        }
    61         float weight = options->weightings->data.F32[i]; // Weight to apply
    62         psBinaryOp(covar->image, covar->image, "*", psScalarAlloc(weight, PS_TYPE_F32));
    63         sumWeights += weight;
    64     }
    65     if (sumWeights > 0.0) {
    66         pmReadout *outRO = options->outRO;  // Output readout
    67         outRO->covariance = psImageCovarianceSum(options->covariances);
    68         psBinaryOp(outRO->covariance->image, outRO->covariance->image, "/",
    69                    psScalarAlloc(sumWeights, PS_TYPE_F32));
    70         psFree(options->covariances); options->covariances = NULL;
    71         psImageCovarianceTransfer(outRO->variance, outRO->covariance);
     82    } else {
     83        target->covariance = psImageCovarianceNone();
    7284    }
    7385
    7486#ifdef TESTING
    75     pmStackVisualPlotTestImage(outRO->image, "combined_initial.fits");
    76     ppStackWriteImage("combined_final.fits", NULL, outRO->image, config);
     87    static int pass = 0;                // Pass through
     88    psString name = NULL;               // Name of file
     89    psStringAppend(&name, "combined_image_final_%d.fits", pass);
     90    pass++;
     91    ppStackWriteImage(name, NULL, target->image, config);
     92    psStringSubstitute(&name, "mask", "image");
     93    ppStackWriteImage(name, NULL, target->mask, config);
     94    psStringSubstitute(&name, "variance", "mask");
     95    ppStackWriteImage(name, NULL, target->variance, config);
     96    psFree(name);
     97
     98    pmStackVisualPlotTestImage(target->image, "combined_image_final.fits");
    7799#endif
    78100
  • trunk/ppStack/src/ppStackCombineInitial.c

    r23767 r26076  
    99#include "ppStack.h"
    1010#include "ppStackLoop.h"
     11
     12//#define TESTING                         // Enable test output
    1113
    1214bool ppStackCombineInitial(ppStackThreadData *stack, ppStackOptions *options, pmConfig *config)
     
    6062    // Harvest the jobs, gathering the inspection lists
    6163    options->inspect = psArrayAlloc(options->num);
     64    options->rejected = psArrayAlloc(options->num);
    6265    for (int i = 0; i < options->num; i++) {
    6366        if (options->inputMask->data.PS_TYPE_VECTOR_MASK_DATA[i]) {
     
    6568        }
    6669        options->inspect->data[i] = psArrayAllocEmpty(numChunk);
     70        options->rejected->data[i] = psArrayAllocEmpty(numChunk);
    6771    }
    6872    psThreadJob *job;               // Completed job
     
    7175                 "Job has incorrect type: %s", job->type);
    7276        psArray *results = job->results; // Results of job
     77        psAssert(results->n == 2, "Results array has wrong size!");
     78        psArray *inspect = results->data[0]; // Pixels to inspect
     79        psArray *reject = results->data[1];  // Pixels to reject
    7380        for (int i = 0; i < options->num; i++) {
    7481            if (options->inputMask->data.PS_TYPE_VECTOR_MASK_DATA[i]) {
    7582                continue;
    7683            }
    77             options->inspect->data[i] = psArrayAdd(options->inspect->data[i], 1, results->data[i]);
     84            options->inspect->data[i] = psArrayAdd(options->inspect->data[i], 1, inspect->data[i]);
     85            options->rejected->data[i] = psArrayAdd(options->rejected->data[i], 1, reject->data[i]);
    7886        }
    7987        psFree(job);
     
    8391
    8492#ifdef TESTING
    85     ppStackWriteImage("combined_initial.fits", NULL, outRO->image, config);
    86     pmStackVisualPlotTestImage(outRO->image, "combined_initial.fits");
     93    ppStackWriteImage("combined_image_initial.fits", NULL, options->outRO->image, config);
     94    ppStackWriteImage("combined_mask_initial.fits", NULL, options->outRO->mask, config);
     95    ppStackWriteImage("combined_variance_initial.fits", NULL, options->outRO->variance, config);
     96
     97    pmStackVisualPlotTestImage(options->outRO->image, "combined_image_initial.fits");
    8798#endif
    88 
    89     psFree(options->matchChi2); options->matchChi2 = NULL;
    90 
    9199
    92100    if (options->stats) {
  • trunk/ppStack/src/ppStackCombinePrepare.c

    r23576 r26076  
    3333    pmCell *outCell = pmFPAfileThisCell(config->files, view, "PPSTACK.OUTPUT"); // Output cell
    3434    options->outRO = pmReadoutAlloc(outCell); // Output readout
     35
     36    pmCell *unconvCell = pmFPAfileThisCell(config->files, view, "PPSTACK.UNCONV"); // Unconvolved cell
     37    options->unconvRO = pmReadoutAlloc(unconvCell); // Unconvolved readout
     38
    3539    psFree(view);
    3640
     
    3943    psString maskBadStr = psMetadataLookupStr(NULL, recipe, "MASK.BAD"); // Name of bits to mask for bad
    4044    psImageMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels
     45
    4146    if (!pmReadoutStackDefineOutput(options->outRO, col0, row0, numCols, numRows, true, true, maskBad)) {
    4247        psError(PS_ERR_UNKNOWN, false, "Unable to prepare output.");
     
    4449    }
    4550
     51    options->unconvRO->image = psImageCopy(NULL, options->outRO->image, PS_TYPE_F32);
     52//    options->unconvRO->mask = psImageCopy(NULL, options->outRO->mask, PS_TYPE_IMAGE_MASK);
     53    options->unconvRO->col0 = options->outRO->col0;
     54    options->unconvRO->row0 = options->outRO->row0;
     55
     56
     57
    4658    return true;
    4759}
  • trunk/ppStack/src/ppStackConvolve.c

    r23602 r26076  
    99#include "ppStack.h"
    1010#include "ppStackLoop.h"
     11
     12//#define TESTING
     13
    1114
    1215// Update the value of a concept
     
    3942    options->weightings = psVectorAlloc(num, PS_TYPE_F32); // Combination weightings for images (1/noise^2)
    4043    psVectorInit(options->weightings, 0.0);
    41     options->covariances = psArrayAlloc(num); // Covariance matrices
     44    options->origCovars = psArrayAlloc(num);
     45    options->convCovars = psArrayAlloc(num); // Covariance matrices
     46
     47    psVector *renorms = psVectorAlloc(num, PS_TYPE_F32); // Renormalisation values for variances
     48    psVectorInit(renorms, NAN);
    4249
    4350    psList *fpaList = psListAlloc(NULL); // List of input FPAs, for concept averaging
     
    7986        // Background subtraction, scaling and normalisation is performed automatically by the image matching
    8087        psTimerStart("PPSTACK_MATCH");
     88        options->origCovars->data[i] = psMemIncrRefCounter(readout->covariance);
    8189        if (!ppStackMatch(readout, options, i, config)) {
    8290            psErrorStackPrint(stderr, "Unable to match image %d --- ignoring.", i);
     
    8593            continue;
    8694        }
    87         options->covariances->data[i] = psMemIncrRefCounter(readout->covariance);
     95        options->convCovars->data[i] = psMemIncrRefCounter(readout->covariance);
     96
     97        float renorm = psMetadataLookupF32(NULL, readout->analysis, PM_READOUT_ANALYSIS_RENORM);
     98        if (!isfinite(renorm)) {
     99            renorm = 1.0;
     100        }
     101        renorms->data.F32[i] = renorm;
    88102
    89103        if (options->stats) {
     
    114128        pmHDU *hdu = readout->parent->parent->parent->hdu; // HDU for convolved image
    115129        assert(hdu);
    116         ppStackWriteImage(options->imageNames->data[i], hdu->header, readout->image, config);
     130        ppStackWriteImage(options->convImages->data[i], hdu->header, readout->image, config);
    117131        psMetadata *maskHeader = psMetadataCopy(NULL, hdu->header); // Copy of header, for mask
    118132        pmConfigMaskWriteHeader(config, maskHeader);
    119         ppStackWriteImage(options->maskNames->data[i], maskHeader, readout->mask, config);
     133        ppStackWriteImage(options->convMasks->data[i], maskHeader, readout->mask, config);
    120134        psFree(maskHeader);
    121         psImageCovarianceTransfer(readout->variance, readout->covariance);
    122         ppStackWriteImage(options->varianceNames->data[i], hdu->header, readout->variance, config);
     135        ppStackWriteImage(options->convVariances->data[i], hdu->header, readout->variance, config);
    123136#ifdef TESTING
    124137        {
     
    129142            psFree(name);
    130143        }
     144        {
     145            int numCols = readout->image->numCols, numRows = readout->image->numRows;
     146            psImage *sn = psImageAlloc(numCols, numRows, PS_TYPE_F32);
     147            for (int y = 0; y < numRows; y++) {
     148                for (int x = 0; x < numCols; x++) {
     149                    sn->data.F32[y][x] = readout->image->data.F32[y][x] /
     150                        sqrtf(readout->variance->data.F32[y][x]);
     151                }
     152            }
     153            psString name = NULL;
     154            psStringAppend(&name, "signoise_%d.fits", i);
     155            ppStackWriteImage(name, hdu->header, sn, config);
     156            psFree(name);
     157            psFree(sn);
     158        }
    131159#endif
    132160
     
    149177    psFree(rng);
    150178
    151     psFree(options->norm); options->norm = NULL;
    152179    psFree(options->sourceLists); options->sourceLists = NULL;
    153180    psFree(options->psf); options->psf = NULL;
     
    211238            numGood = 0;                    // Number of good images
    212239            for (int i = 0; i < num; i++) {
    213               if (options->inputMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PPSTACK_MASK_ALL) {
     240                if (options->inputMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PPSTACK_MASK_ALL) {
    214241                    continue;
    215242                }
     
    233260    }
    234261
     262    // Correct chi^2 for renormalisation
     263    psBinaryOp(options->matchChi2, options->matchChi2, "/", renorms);
     264    for (int i = 0; i < num; i++) {
     265        psLogMsg("ppStack", PS_LOG_INFO, "Additional variance for image %d: %f\n",
     266                 i, options->matchChi2->data.F32[i]);
     267    }
     268    psFree(renorms);
     269
    235270    return true;
    236271}
  • trunk/ppStack/src/ppStackFiles.c

    r23357 r26076  
    2222/// Output files for the combination
    2323static char *filesCombine[] = { "PPSTACK.OUTPUT", "PPSTACK.OUTPUT.MASK", "PPSTACK.OUTPUT.VARIANCE",
     24                                "PPSTACK.UNCONV", "PPSTACK.UNCONV.MASK", "PPSTACK.UNCONV.VARIANCE",
    2425                                "PPSTACK.OUTPUT.JPEG1", "PPSTACK.OUTPUT.JPEG2", NULL };
    2526
  • trunk/ppStack/src/ppStackLoop.c

    r25738 r26076  
    5656    // Start threading
    5757    ppStackThreadInit();
    58     ppStackThreadData *stack = ppStackThreadDataSetup(options, config);
     58    ppStackThreadData *stack = ppStackThreadDataSetup(options, config, true);
    5959    if (!stack) {
    6060        psError(PS_ERR_IO, false, "Unable to initialise stack threads.");
     
    6262        return false;
    6363    }
    64     psFree(options->cells); options->cells = NULL;
    6564
    6665    // Prepare for combination
     
    9897    // Final combination
    9998    psTrace("ppStack", 2, "Final stack of convolved images....\n");
    100     if (!ppStackCombineFinal(stack, options, config)) {
     99    if (!ppStackCombineFinal(options->outRO, stack, options->convCovars, options, config, false, false)) {
    101100        psError(PS_ERR_UNKNOWN, false, "Unable to perform final combination.");
    102101        psFree(stack);
     
    106105    psLogMsg("ppStack", PS_LOG_INFO, "Stage 5: Final Stack: %f sec", psTimerClear("PPSTACK_STEPS"));
    107106    ppStackMemDump("final");
    108 
    109107
    110108    // Clean up
     
    121119    psFree(stack);
    122120
     121#if 1
     122    // Unconvolved stack --- it's cheap to calculate, compared to everything else!
     123    if (options->convolve) {
     124        // Start threading
     125        ppStackThreadData *stack = ppStackThreadDataSetup(options, config, false);
     126        if (!stack) {
     127            psError(PS_ERR_IO, false, "Unable to initialise stack threads.");
     128            psFree(options);
     129            return false;
     130        }
     131        psTrace("ppStack", 2, "Stack of unconvolved images....\n");
     132        if (!ppStackCombineFinal(options->unconvRO, stack, options->origCovars, options, config, false, true)) {
     133            psError(PS_ERR_UNKNOWN, false, "Unable to perform unconvolved combination.");
     134            psFree(stack);
     135            psFree(options);
     136            return false;
     137        }
     138        psLogMsg("ppStack", PS_LOG_INFO, "Stage 7: Unconvolved Stack: %f sec", psTimerClear("PPSTACK_STEPS"));
     139        ppStackMemDump("unconv");
     140
     141        psFree(stack);
     142    }
     143    psFree(options->cells); options->cells = NULL;
     144#endif
    123145
    124146    // Photometry
     
    129151        return false;
    130152    }
    131     psLogMsg("ppStack", PS_LOG_INFO, "Stage 7: Photometry Analysis: %f sec", psTimerClear("PPSTACK_STEPS"));
     153    psLogMsg("ppStack", PS_LOG_INFO, "Stage 8: Photometry Analysis: %f sec", psTimerClear("PPSTACK_STEPS"));
    132154    ppStackMemDump("photometry");
    133 
    134155
    135156    // Finish up
     
    140161        return false;
    141162    }
    142     psLogMsg("ppStack", PS_LOG_INFO, "Stage 8: Final output: %f sec", psTimerClear("PPSTACK_STEPS"));
     163    psLogMsg("ppStack", PS_LOG_INFO, "Stage 9: Final output: %f sec", psTimerClear("PPSTACK_STEPS"));
    143164    ppStackMemDump("finish");
    144165
    145166    psFree(options);
     167
    146168    return true;
    147169}
  • trunk/ppStack/src/ppStackLoop.h

    r23576 r26076  
    5656// Final combination
    5757bool ppStackCombineFinal(
     58    pmReadout *target,                  // Target readout
    5859    ppStackThreadData *stack,           // Stack
     60    psArray *covariances,               // Covariances
    5961    ppStackOptions *options,            // Options
    60     pmConfig *config                    // Configuration
     62    pmConfig *config,                   // Configuration
     63    bool safe,                          // Allow safe combination?
     64    bool norm                           // Normalise images?
    6165    );
    6266
  • trunk/ppStack/src/ppStackMatch.c

    r26074 r26076  
    167167    )
    168168{
     169#if 1
    169170    bool mdok; // Status of metadata lookups
    170171
     
    192193    psImageMaskType maskBad = pmConfigMaskGet("BLANK", config); // Bits to mask
    193194
     195    psImageCovarianceTransfer(readout->variance, readout->covariance);
    194196    return pmReadoutVarianceRenormalise(readout, maskBad, num, minValid, maxValid);
     197#else
     198    return true;
     199#endif
    195200}
    196201
     
    212217    int size = psMetadataLookupS32(NULL, ppsub, "KERNEL.SIZE"); // Kernel half-size
    213218
    214     psString maskValStr = psMetadataLookupStr(NULL, recipe, "MASK.VAL"); // Name of bits to mask going in
     219    psString maskValStr = psMetadataLookupStr(NULL, ppsub, "MASK.VAL"); // Name of bits to mask going in
    215220    psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask going in to pmSubtractionMatch
    216221    psString maskPoorStr = psMetadataLookupStr(NULL, recipe, "MASK.POOR"); // Name of bits to mask for poor
     
    257262            psFitsClose(fits);
    258263
    259             if (!readImage(&readout->image, options->imageNames->data[index], config) ||
    260                 !readImage(&readout->mask, options->maskNames->data[index], config) ||
    261                 !readImage(&readout->variance, options->varianceNames->data[index], config)) {
     264            if (!readImage(&readout->image, options->convImages->data[index], config) ||
     265                !readImage(&readout->mask, options->convMasks->data[index], config) ||
     266                !readImage(&readout->variance, options->convVariances->data[index], config)) {
    262267                psError(PS_ERR_IO, false, "Unable to read previously produced image.");
    263268                return false;
     
    378383            }
    379384#endif
     385
     386            fprintf(stderr, "vf = %f\n", psImageCovarianceFactor(readout->covariance));
     387
    380388
    381389            if (threads > 0) {
     
    517525            psFree(iter);
    518526            options->matchChi2->data.F32[index] = sum / (psImageCovarianceFactor(readout->covariance) * num);
     527            fprintf(stderr, "chi2 = %f ; vf = %f\n", sum/num, psImageCovarianceFactor(readout->covariance));
    519528        }
    520529
     
    543552    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator
    544553    if (!psImageBackground(bg, NULL, readout->image, readout->mask, maskVal | maskBad, rng)) {
    545       psWarning("Can't measure background for image.");
    546       psErrorClear();
     554        psWarning("Can't measure background for image.");
     555        psErrorClear();
    547556    } else {
    548       if (!psMetadataLookupBool(NULL, config->arguments, "PPSTACK.SKIP.BG.SUB")) {
    549         psLogMsg("ppStack", PS_LOG_INFO, "Correcting convolved image background by %lf (+/- %lf)",
    550                  psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN), psStatsGetValue(bg, PS_STAT_ROBUST_STDEV));
    551         (void)psBinaryOp(readout->image, readout->image, "-",
    552                          psScalarAlloc(psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN), PS_TYPE_F32));
    553       }
     557        if (!psMetadataLookupBool(NULL, config->arguments, "PPSTACK.SKIP.BG.SUB")) {
     558            psLogMsg("ppStack", PS_LOG_INFO, "Correcting convolved image background by %lf (+/- %lf)",
     559                     psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN), psStatsGetValue(bg, PS_STAT_ROBUST_STDEV));
     560            (void)psBinaryOp(readout->image, readout->image, "-",
     561                             psScalarAlloc(psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN), PS_TYPE_F32));
     562        }
    554563    }
    555564
     
    569578    options->weightings->data.F32[index] = 1.0 / (psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN) *
    570579                                                  psImageCovarianceFactor(readout->covariance));
     580    psLogMsg("ppStack", PS_LOG_INFO, "Weighting for image %d is %f\n",
     581             index, options->weightings->data.F32[index]);
    571582    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "PPSTACK.WEIGHTING", 0,
    572583                     "Weighting by 1/noise^2 for stack", options->weightings->data.F32[index]);
  • trunk/ppStack/src/ppStackOptions.c

    r23573 r26076  
    1212        fclose(options->statsFile);
    1313    }
    14     psFree(options->imageNames);
    15     psFree(options->maskNames);
    16     psFree(options->varianceNames);
     14    psFree(options->origImages);
     15    psFree(options->origMasks);
     16    psFree(options->origVariances);
     17    psFree(options->origCovars);
     18    psFree(options->convImages);
     19    psFree(options->convMasks);
     20    psFree(options->convVariances);
    1721    psFree(options->psf);
    1822    psFree(options->inputMask);
     
    2428    psFree(options->matchChi2);
    2529    psFree(options->weightings);
    26     psFree(options->covariances);
     30    psFree(options->convCovars);
    2731    psFree(options->outRO);
     32    psFree(options->unconvRO);
    2833    psFree(options->inspect);
    2934    psFree(options->rejected);
     
    3944    options->stats = NULL;
    4045    options->statsFile = NULL;
    41     options->imageNames = NULL;
    42     options->maskNames = NULL;
    43     options->varianceNames = NULL;
     46    options->origImages = NULL;
     47    options->origMasks = NULL;
     48    options->origVariances = NULL;
     49    options->origCovars = NULL;
     50    options->convImages = NULL;
     51    options->convMasks = NULL;
     52    options->convVariances = NULL;
    4453    options->num = 0;
    4554    options->psf = NULL;
     
    5463    options->matchChi2 = NULL;
    5564    options->weightings = NULL;
    56     options->covariances = NULL;
     65    options->convCovars = NULL;
    5766    options->outRO = NULL;
     67    options->unconvRO = NULL;
    5868    options->inspect = NULL;
    5969    options->rejected = NULL;
  • trunk/ppStack/src/ppStackOptions.h

    r23573 r26076  
    1111    psMetadata *stats;                  // Statistics for output
    1212    FILE *statsFile;                    // File to which to write statistics
    13     psArray *imageNames, *maskNames, *varianceNames; // Filenames for the temporary convolved images
     13    psArray *origImages, *origMasks, *origVariances; // Filenames of the original images
     14    psArray *convImages, *convMasks, *convVariances; // Filenames for the temporary convolved images
     15    psArray *origCovars;                // Original covariances matrices
    1416    int num;                            // Number of inputs
    1517    // Prepare
     
    2628    psVector *matchChi2;                // chi^2 for stamps from matching
    2729    psVector *weightings;               // Combination weightings for images (1/noise^2)
    28     psArray *covariances;               // Covariance matrices
     30    psArray *convCovars;                // Convolved covariance matrices
    2931    // Combine initial
    3032    pmReadout *outRO;                   // Output readout
     33    pmReadout *unconvRO;                // Unconvolved readout
    3134    psArray *inspect;                   // Array of arrays of pixels to inspect
    3235    // Rejection
  • trunk/ppStack/src/ppStackReadout.c

    r23577 r26076  
    2525    psVector *addVariance = options->matchChi2; // Additional variance when rejecting
    2626
    27     psArray *inspect = ppStackReadoutInitial(config, outRO, thread->readouts, mask,
    28                                              weightings, addVariance);
    29 
    30     job->results = inspect;
     27    job->results = ppStackReadoutInitial(config, outRO, thread->readouts, mask,
     28                                         weightings, addVariance);
    3129    thread->busy = false;
    3230
    33     return inspect ? true : false;
     31    return job->results ? true : false;
    3432}
    3533
     
    3937
    4038    psArray *args = job->args;          // Arguments
    41     ppStackThread *thread = args->data[0]; // Thread
    42     ppStackOptions *options = args->data[1]; // Options
    43     pmConfig *config = args->data[2];   // Configuration
    44 
    45     pmReadout *outRO = options->outRO;  // Output readout
     39    pmReadout *target = args->data[0];  // Output readout
     40    ppStackThread *thread = args->data[1]; // Thread
     41    ppStackOptions *options = args->data[2]; // Options
     42    pmConfig *config = args->data[3];   // Configuration
     43    bool safety = PS_SCALAR_VALUE(args->data[4], U8);    // Safety switch on?
     44    bool normalise = PS_SCALAR_VALUE(args->data[5], U8); // Normalise images?
     45
    4646    psVector *mask = options->inputMask; // Mask for inputs
    4747    psArray *rejected = options->rejected; // Rejected pixels
    4848    psVector *weightings = options->weightings; // Weightings (1/noise^2) for each image
    4949    psVector *addVariance = options->matchChi2; // Additional variance when rejecting
    50 
    51     bool status = ppStackReadoutFinal(config, outRO, thread->readouts, mask, rejected,
    52                                       weightings, addVariance); // Status of operation
     50    psVector *norm = normalise ? options->norm : NULL; // Normalisations to apply to images
     51
     52    bool status = ppStackReadoutFinal(config, target, thread->readouts, mask, rejected,
     53                                      weightings, addVariance, safety, norm); // Status of operation
    5354
    5455    thread->busy = false;
     
    6364
    6465    psArray *args = job->args;  // Input arguments
    65     psArray *inspect = args->data[0]; // Array of pixel arrays
    66     int index = PS_SCALAR_VALUE(args->data[1], S32); // Index of interest
    67 
    68     psArray *inputs = inspect->data[index]; // Array of interest
    69     psPixels *output = NULL;    // Output pixel list
    70     for (int i = 0; i < inputs->n; i++) {
    71         psPixels *input = inputs->data[i]; // Input pixel list
    72         if (!input || input->n == 0) {
    73             continue;
    74         }
    75         output = psPixelsConcatenate(output, input);
    76     }
    77 
    78     if (!output) {
    79         // If there are no pixels to inspect, then just fake it
    80         output = psPixelsAllocEmpty(0);
    81     }
    82 
    83     psFree(inputs);
    84     inspect->data[index] = output;
     66    psArray *inspects = args->data[0]; // Array of pixel arrays
     67    psArray *rejects = args->data[1];  // Array of pixel arrays
     68    int index = PS_SCALAR_VALUE(args->data[2], S32); // Index of interest
     69
     70    psArray *inInspects = inspects->data[index]; // Array of interest
     71    psArray *inRejects = rejects->data[index]; // Array of interest
     72    psAssert(inInspects->n == inRejects->n, "Size should be the same");
     73    psPixels *outInspect = NULL, *outReject = NULL; // Output pixel lists
     74    for (int i = 0; i < inInspects->n; i++) {
     75        psPixels *inInspect = inInspects->data[i]; // Input pixel list
     76        if (inInspect && inInspect->n > 0) {
     77            outInspect = psPixelsConcatenate(outInspect, inInspect);
     78        }
     79        psPixels *inReject = inRejects->data[i]; // Input pixel list
     80        if (inReject && inReject->n > 0) {
     81            outReject = psPixelsConcatenate(outReject, inReject);
     82        }
     83    }
     84
     85    // If there are no pixels to inspect, then just fake it
     86    if (!outInspect) {
     87        outInspect = psPixelsAllocEmpty(0);
     88    }
     89    if (!outReject) {
     90        outReject = psPixelsAllocEmpty(0);
     91    }
     92
     93    psFree(inspects->data[index]);
     94    inspects->data[index] = outInspect;
     95    psFree(rejects->data[index]);
     96    rejects->data[index] = outReject;
    8597
    8698    return true;
     
    104116
    105117    bool mdok;                          // Status of MD lookup
    106     int iter = psMetadataLookupS32(NULL, recipe, "ITER"); // Rejection iterations
     118    float iter = psMetadataLookupF32(NULL, recipe, "COMBINE.ITER"); // Rejection iterations
    107119    float combineRej = psMetadataLookupF32(NULL, recipe, "COMBINE.REJ"); // Combination threshold
    108120    float combineSys = psMetadataLookupF32(NULL, recipe, "COMBINE.SYS"); // Combination systematic error
     
    114126    int kernelSize = psMetadataLookupS32(NULL, ppsub, "KERNEL.SIZE"); // Kernel half-size
    115127
    116     psString maskValStr = psMetadataLookupStr(NULL, recipe, "MASK.VAL"); // Name of bits to mask going in
     128    psString maskValStr = psMetadataLookupStr(NULL, recipe, "MASK.IN"); // Name of bits to mask going in
    117129    psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask going in to pmSubtractionMatch
     130    psString maskSuspectStr = psMetadataLookupStr(NULL, recipe, "MASK.SUSPECT"); // Name of suspect mask bits
     131    psImageMaskType maskSuspect = pmConfigMaskGet(maskSuspectStr, config); // Suspect bits
    118132    psString maskBadStr = psMetadataLookupStr(NULL, recipe, "MASK.BAD"); // Name of bits to mask for bad
    119133    psImageMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels
     
    149163    }
    150164
    151     if (!pmStackCombine(outRO, stack, maskVal | maskBad, maskBad, kernelSize, iter,
    152                         combineRej, combineSys, combineDiscard, true, useVariance, safe, false)) {
     165    if (!pmStackCombine(outRO, stack, maskVal | maskBad, maskSuspect, maskBad, kernelSize, iter,
     166                        combineRej, combineSys, combineDiscard, useVariance, safe, false)) {
    153167        psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts with rejection.");
    154168        psFree(stack);
     
    156170    }
    157171
    158     // Save list of pixels to inspect
     172    // Save lists of pixels
    159173    psArray *inspect = psArrayAlloc(num); // List of pixels to inspect
     174    psArray *reject = psArrayAlloc(num);  // List of pixels rejected
    160175    for (int i = 0; i < num; i++) {
    161176        pmStackData *data = stack->data[i]; // Data for this image
     
    168183        }
    169184        inspect->data[i] = psMemIncrRefCounter(data->inspect);
     185        reject->data[i] = psMemIncrRefCounter(data->reject);
    170186    }
    171187    psFree(stack);
     
    173189    sectionNum++;
    174190
    175     return inspect;
     191    psArray *results = psArrayAlloc(2); // Array of results
     192    results->data[0] = inspect;
     193    results->data[1] = reject;
     194
     195    return results;
    176196}
    177197
     
    180200bool ppStackReadoutFinal(const pmConfig *config, pmReadout *outRO, const psArray *readouts,
    181201                         const psVector *mask, const psArray *rejected, const psVector *weightings,
    182                          const psVector *addVariance)
     202                         const psVector *addVariance, bool safety, const psVector *norm)
    183203{
    184204    assert(config);
     
    196216
    197217    bool mdok;                          // Status of MD lookup
    198     int iter = psMetadataLookupS32(NULL, recipe, "ITER"); // Rejection iterations
    199     float combineRej = psMetadataLookupF32(NULL, recipe, "COMBINE.REJ"); // Combination threshold
    200     float combineSys = psMetadataLookupF32(NULL, recipe, "COMBINE.SYS"); // Combination systematic error
    201     float combineDiscard = psMetadataLookupF32(NULL, recipe, "COMBINE.DISCARD"); // Olympic discard fraction
    202218    bool useVariance = psMetadataLookupBool(&mdok, recipe, "VARIANCE"); // Use variance for rejection?
    203219    bool safe = psMetadataLookupBool(&mdok, recipe, "SAFE"); // Be safe when combining small numbers of pixels
    204220
    205     psString maskValStr = psMetadataLookupStr(NULL, recipe, "MASK.VAL"); // Name of bits to mask going in
     221    psString maskValStr = psMetadataLookupStr(NULL, recipe, "MASK.IN"); // Name of bits to mask going in
    206222    psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask going in to pmSubtractionMatch
     223    psString maskSuspectStr = psMetadataLookupStr(NULL, recipe, "MASK.SUSPECT"); // Name of suspect mask bits
     224    psImageMaskType maskSuspect = pmConfigMaskGet(maskSuspectStr, config); // Suspect bits
    207225    psString maskBadStr = psMetadataLookupStr(NULL, recipe, "MASK.BAD"); // Name of bits to mask for bad
    208226    psImageMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels
     
    211229    psArray *stack = psArrayAlloc(num); // Array for stacking
    212230
    213     bool entire = true;                 // Combine entire image?
    214     if (rejected) {
    215         // We have rejection from a previous combination: combine without flagging pixels to inspect
    216         entire = false;
    217         safe = false;
    218         iter = 0;
    219         combineRej = NAN;
    220         combineSys = NAN;
    221     }
     231    // We have rejection from a previous combination: combine without flagging pixels to inspect
     232    safe &= safety;
     233    int iter = 0;
     234    float combineRej = NAN;
     235    float combineSys = NAN;
     236    float combineDiscard = NAN;
    222237
    223238    for (int i = 0; i < num; i++) {
    224239        pmReadout *ro = readouts->data[i];
    225         if (mask->data.U8[i] & (PPSTACK_MASK_REJECT | PPSTACK_MASK_BAD)) {
    226             // Image completely rejected since previous combination
    227             entire = true;
    228             continue;
    229         } else if (mask->data.U8[i]) {
    230             // Image completely rejected before original combination
     240        if (mask->data.U8[i]) {
     241            // Image completely rejected
    231242            continue;
    232243        }
     
    252263        data->reject = rejected ? psMemIncrRefCounter(rejected->data[i]) : NULL;
    253264        stack->data[i] = data;
    254     }
    255 
    256     if (!pmStackCombine(outRO, stack, maskVal | maskBad, maskBad, 0,
    257                         iter, combineRej, combineSys, combineDiscard,
    258                         entire, useVariance, safe, !rejected)) {
     265
     266        if (norm) {
     267            float normalise = powf(10.0, -0.4 * norm->data.F32[i]); // Normalisation
     268            psBinaryOp(ro->image, ro->image, "*", psScalarAlloc(normalise, PS_TYPE_F32));
     269            psBinaryOp(ro->variance, ro->variance, "*", psScalarAlloc(PS_SQR(normalise), PS_TYPE_F32));
     270        }
     271    }
     272
     273    if (!pmStackCombine(outRO, stack, maskVal | maskBad, maskSuspect, maskBad, 0, iter, combineRej,
     274                        combineSys, combineDiscard, useVariance, safe, true)) {
    259275        psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts.");
    260276        psFree(stack);
  • trunk/ppStack/src/ppStackReject.c

    r25466 r26076  
    2323
    2424    int num = options->num;             // Number of inputs
    25     options->rejected = psArrayAlloc(num);
    2625
    2726    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSTACK_RECIPE); // ppStack recipe
     
    5352        psThreadJob *job = psThreadJobAlloc("PPSTACK_INSPECT"); // Job to start
    5453        psArrayAdd(job->args, 1, options->inspect);
     54        psArrayAdd(job->args, 1, options->rejected);
    5555        PS_ARRAY_ADD_SCALAR(job->args, i, PS_TYPE_S32);
    5656        if (!psThreadJobAddPending(job)) {
     
    9292#endif
    9393
    94         psPixels *reject = pmStackReject(options->inspect->data[i], options->numCols, options->numRows,
    95                                          threshold, poorFrac, stride, options->regions->data[i],
    96                                          options->kernels->data[i]); // Rejected pixels
    97 
    9894#ifdef TESTING
    9995        {
    100             psImage *mask = psPixelsToMask(NULL, reject,
     96            psImage *mask = psPixelsToMask(NULL, options->rejected->data[i],
    10197                                           psRegionSet(0, options->numCols - 1, 0, options->numRows - 1),
    10298                                           0xff); // Mask image
    10399            psString name = NULL;           // Name of image
    104             psStringAppend(&name, "reject_%03d.fits", i);
     100            psStringAppend(&name, "pre_reject_%03d.fits", i);
    105101            pmStackVisualPlotTestImage(mask, name);
    106102            psFits *fits = psFitsOpen(name, "w");
     
    111107        }
    112108#endif
     109
     110        psPixels *reject = pmStackReject(options->inspect->data[i], options->numCols, options->numRows,
     111                                         threshold, poorFrac, stride, options->regions->data[i],
     112                                         options->kernels->data[i]); // Rejected pixels
    113113
    114114        psFree(options->inspect->data[i]);
     
    127127                          "exceeds limit (%.3f)", i, frac, imageRej);
    128128                psFree(reject);
    129                 // reject == NULL means reject image completely
    130129                reject = NULL;
    131130                options->inputMask->data.PS_TYPE_VECTOR_MASK_DATA[i] |= PPSTACK_MASK_BAD;
     
    134133        }
    135134
    136         // Images without a list of rejected pixels (the list may be empty) are rejected completely
    137         options->rejected->data[i] = reject;
     135        if (reject) {
     136            // Add to list of pixels already rejected
     137            reject = psPixelsConcatenate(reject, options->rejected->data[i]);
     138            options->rejected->data[i] = psPixelsDuplicates(options->rejected->data[i], reject);
     139        }
     140
     141#ifdef TESTING
     142        {
     143            psImage *mask = psPixelsToMask(NULL, options->rejected->data[i],
     144                                           psRegionSet(0, options->numCols - 1, 0, options->numRows - 1),
     145                                           0xff); // Mask image
     146            psString name = NULL;           // Name of image
     147            psStringAppend(&name, "reject_%03d.fits", i);
     148            pmStackVisualPlotTestImage(mask, name);
     149            psFits *fits = psFitsOpen(name, "w");
     150            psFree(name);
     151            psFitsWriteImage(fits, NULL, mask, 0, NULL);
     152            psFree(mask);
     153            psFitsClose(fits);
     154        }
     155#endif
    138156
    139157        if (options->stats) {
     
    143161                             "Number of pixels rejected", reject ? reject->n : 0);
    144162        }
     163
     164        psFree(reject);
    145165        psLogMsg("ppStack", PS_LOG_INFO, "Time to perform rejection on image %d: %f sec", i,
    146166                 psTimerClear("PPSTACK_REJECT"));
  • trunk/ppStack/src/ppStackSetup.c

    r26020 r26076  
    7272    }
    7373
    74     options->imageNames = psArrayAlloc(num);
    75     options->maskNames = psArrayAlloc(num);
    76     options->varianceNames = psArrayAlloc(num);
     74    options->convImages = psArrayAlloc(num);
     75    options->convMasks = psArrayAlloc(num);
     76    options->convVariances = psArrayAlloc(num);
    7777    for (int i = 0; i < num; i++) {
    7878        psString imageName = NULL, maskName = NULL, varianceName = NULL; // Names for convolved images
     
    8181        psStringAppend(&varianceName, "%s/%s.%d.%s", tempDir, tempName, i, tempVariance);
    8282        psTrace("ppStack", 5, "Temporary files: %s %s %s\n", imageName, maskName, varianceName);
    83         options->imageNames->data[i] = imageName;
    84         options->maskNames->data[i] = maskName;
    85         options->varianceNames->data[i] = varianceName;
     83        options->convImages->data[i] = imageName;
     84        options->convMasks->data[i] = maskName;
     85        options->convVariances->data[i] = varianceName;
    8686    }
    8787    psFree(outputName);
     88
     89    // Original images
     90    options->origImages = psArrayAlloc(num);
     91    options->origMasks = psArrayAlloc(num);
     92    options->origVariances = psArrayAlloc(num);
     93    pmFPAview *view = pmFPAviewAlloc(0);
     94    for (int i = 0; i < num; i++) {
     95        {
     96            pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPSTACK.INPUT", i);
     97            options->origImages->data[i] = pmFPAfileName(file, view, config);
     98        }
     99        {
     100            // We want the convolved mask, since that defines the area that has been tested for outliers
     101            options->origMasks->data[i] = psMemIncrRefCounter(options->convMasks->data[i]);
     102        }
     103        {
     104            pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPSTACK.INPUT.VARIANCE", i);
     105            options->origVariances->data[i] = pmFPAfileName(file, view, config);
     106        }
     107    }
     108    psFree(view);
    88109
    89110    if (!pmConfigMaskSetBits(NULL, NULL, config)) {
  • trunk/ppStack/src/ppStackSources.c

    r25313 r26076  
    188188    }
    189189
     190#if 0
     191    // Position offsets
     192    {
     193        psArray *offsets = pmSourceMatchRelastro(matches, num, tol, iter1, starRej1,
     194                                                  iter2, starRej2, starLimit); // Shifts for each image
     195        if (!offsets) {
     196            psError(PS_ERR_UNKNOWN, false, "Unable to measure offsets");
     197            return false;
     198        }
     199        for (int i = 0; i < num; i++) {
     200            psVector *offset = offsets->data[i];
     201            fprintf(stderr, "Offset %d: %f,%f\n", i, offset->data.F32[0], offset->data.F32[1]);
     202        }
     203        psFree(offsets);
     204    }
     205#endif
     206
    190207#ifdef TESTING
    191208    dumpMatches("source_mags.dat", num, matches, zp, trans);
  • trunk/ppStack/src/ppStackThread.c

    r24796 r26076  
    5656}
    5757
    58 ppStackThreadData *ppStackThreadDataSetup(const ppStackOptions *options, const pmConfig *config)
     58ppStackThreadData *ppStackThreadDataSetup(const ppStackOptions *options, const pmConfig *config, bool conv)
    5959{
    6060    psAssert(options, "Require options");
     
    6262
    6363    const psArray *cells = options->cells; // Array of input cells
    64     const psArray *imageNames = options->imageNames; // Names of images to read
    65     const psArray *maskNames = options->maskNames; // Names of masks to read
    66     const psArray *varianceNames = options->varianceNames; // Names of variance maps to read
    67     const psArray *covariances = options->covariances; // Covariance matrices (already read)
     64    const psArray *imageNames = conv ? options->convImages : options->origImages; // Names of images to read
     65    const psArray *maskNames = conv ? options->convMasks : options->origMasks; // Names of masks to read
     66    const psArray *varianceNames = conv ? options->convVariances : options->origVariances; // Variance names
     67    const psArray *covariances = conv ? options->convCovars : options->origCovars; // Covariance matrices
    6868
    6969    PS_ASSERT_ARRAY_NON_NULL(cells, NULL);
    70     PS_ASSERT_ARRAYS_SIZE_EQUAL(cells, imageNames, NULL);
    71     PS_ASSERT_ARRAYS_SIZE_EQUAL(cells, maskNames, NULL);
    72     PS_ASSERT_ARRAYS_SIZE_EQUAL(cells, varianceNames, NULL);
    73     PS_ASSERT_ARRAYS_SIZE_EQUAL(cells, covariances, NULL);
     70    if (imageNames) {
     71        PS_ASSERT_ARRAYS_SIZE_EQUAL(cells, imageNames, NULL);
     72    }
     73    if (maskNames) {
     74        PS_ASSERT_ARRAYS_SIZE_EQUAL(cells, maskNames, NULL);
     75    }
     76    if (varianceNames) {
     77        PS_ASSERT_ARRAYS_SIZE_EQUAL(cells, varianceNames, NULL);
     78    }
     79    if (covariances) {
     80        PS_ASSERT_ARRAYS_SIZE_EQUAL(cells, covariances, NULL);
     81    }
    7482
    7583    ppStackThreadData *stack = psAlloc(sizeof(ppStackThreadData)); // Thread data, to return
     
    8795            continue;
    8896        }
    89         // Resolved names
    90         psString imageResolved = pmConfigConvertFilename(imageNames->data[i], config, false, false);
    91         psString maskResolved = pmConfigConvertFilename(maskNames->data[i], config, false, false);
    92         psString varianceResolved = pmConfigConvertFilename(varianceNames->data[i], config, false, false);
    93         stack->imageFits->data[i] = psFitsOpen(imageResolved, "r");
    94         stack->maskFits->data[i] = psFitsOpen(maskResolved, "r");
    95         stack->varianceFits->data[i] = psFitsOpen(varianceResolved, "r");
    96         psFree(imageResolved);
    97         psFree(maskResolved);
    98         psFree(varianceResolved);
    99         if (!stack->imageFits->data[i] || !stack->maskFits->data[i] || !stack->varianceFits->data[i]) {
    100             psError(PS_ERR_UNKNOWN, false, "Unable to open convolved files %s, %s, %s",
    101                     (char*)imageNames->data[i], (char*)maskNames->data[i], (char*)varianceNames->data[i]);
    102             return NULL;
    103         }
     97
     98// Open an image
     99#define IMAGE_OPEN(NAMES, FITS, INDEX)          \
     100        if (NAMES) { \
     101            psString resolved = pmConfigConvertFilename((NAMES)->data[INDEX], config, false, false); \
     102            (FITS)->data[INDEX] = psFitsOpen(resolved, "r");                            \
     103            if (!(FITS)->data[INDEX]) { \
     104                psError(PS_ERR_IO, false, "Unable to open file %s", (char*)(NAMES)->data[INDEX]); \
     105                psFree(resolved); \
     106                return NULL; \
     107            } \
     108            psFree(resolved); \
     109        }
     110
     111        IMAGE_OPEN(imageNames, stack->imageFits, i);
     112        IMAGE_OPEN(maskNames, stack->maskFits, i);
     113        IMAGE_OPEN(varianceNames, stack->varianceFits, i);
    104114    }
    105115
     
    116126            }
    117127            pmReadout *ro = pmReadoutAlloc(cell); // Readout for thread
    118             ro->covariance = psMemIncrRefCounter(covariances->data[j]);
     128            if (covariances) {
     129                ro->covariance = psMemIncrRefCounter(covariances->data[j]);
     130            }
    119131            readouts->data[j] = ro;
    120132        }
     
    186198                psFits *varianceFits = stack->varianceFits->data[i]; // FITS file for variance
    187199
    188 
    189                 int zMax = 0;
     200                int zMax = 0;
    190201                bool keepReading = false;
    191                 if (pmReadoutMore(ro, imageFits, 0, &zMax, rows, config)) {
     202
     203                if (imageFits && pmReadoutMore(ro, imageFits, 0, &zMax, rows, config)) {
    192204                    keepReading = true;
    193205                    if (!pmReadoutReadChunk(ro, imageFits, 0, NULL, rows, overlap, config)) {
     
    199211                }
    200212
    201                 if (pmReadoutMoreMask(ro, maskFits, 0, &zMax, rows, config)) {
     213                if (maskFits && pmReadoutMoreMask(ro, maskFits, 0, &zMax, rows, config)) {
    202214                    keepReading = true;
    203215                    if (!pmReadoutReadChunkMask(ro, maskFits, 0, NULL, rows, overlap, config)) {
     
    209221                }
    210222
    211                 if (pmReadoutMoreVariance(ro, varianceFits, 0, &zMax, rows, config)) {
     223                if (varianceFits && pmReadoutMoreVariance(ro, varianceFits, 0, &zMax, rows, config)) {
    212224                    keepReading = true;
    213225                    if (!pmReadoutReadChunkVariance(ro, varianceFits, 0, NULL, rows, overlap, config)) {
     
    263275
    264276    {
    265         psThreadTask *task = psThreadTaskAlloc("PPSTACK_INSPECT", 2);
     277        psThreadTask *task = psThreadTaskAlloc("PPSTACK_INSPECT", 3);
    266278        task->function = &ppStackInspect;
    267279        psThreadTaskAdd(task);
     
    270282
    271283    {
    272         psThreadTask *task = psThreadTaskAlloc("PPSTACK_FINAL_COMBINE", 3);
     284        psThreadTask *task = psThreadTaskAlloc("PPSTACK_FINAL_COMBINE", 6);
    273285        task->function = &ppStackReadoutFinalThread;
    274286        psThreadTaskAdd(task);
  • trunk/ppStack/src/ppStackThread.h

    r23341 r26076  
    3535ppStackThreadData *ppStackThreadDataSetup(
    3636    const ppStackOptions *options,      // Options
    37     const pmConfig *config              // Configuration
     37    const pmConfig *config,             // Configuration
     38    bool conv                           // Use convolved products?
    3839    );
    3940
Note: See TracChangeset for help on using the changeset viewer.