IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 29, 2009, 6:15:31 PM (17 years ago)
Author:
beaumont
Message:

merged with head

Location:
branches/cnb_branches/cnb_branch_20090301
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/cnb_branches/cnb_branch_20090301

  • branches/cnb_branches/cnb_branch_20090301/ppStack

  • branches/cnb_branches/cnb_branch_20090301/ppStack/src/ppStackMatch.c

    r23352 r23594  
    163163
    164164
    165 bool ppStackMatch(pmReadout *readout, psArray **regions, psArray **kernels, float *chi2, float *weighting,
    166                   psArray *sources, const pmPSF *psf, psRandom *rng, const pmConfig *config)
     165bool ppStackMatch(pmReadout *readout, ppStackOptions *options, int index, const pmConfig *config)
    167166{
    168167    assert(readout);
    169     assert(regions && !*regions);
    170     assert(kernels && !*kernels);
     168    assert(options);
    171169    assert(config);
    172     *weighting = 0.0;
    173170
    174171    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSTACK_RECIPE); // ppStack recipe
     
    197194    }
    198195
    199     pmReadout *output = pmReadoutAlloc(NULL); // Output readout, for holding results temporarily
    200 
    201     static int numInput = -1;            // Index of input file
    202     numInput++;
     196    // Match the PSF
     197    if (options->convolve) {
     198        pmReadout *conv = pmReadoutAlloc(NULL); // Conv readout, for holding results temporarily
    203199#ifdef TESTING
    204     // Read previously produced kernel
    205     if (psMetadataLookupBool(NULL, config->arguments, "PPSTACK.DEBUG.STACK")) {
    206         const char *outName = psMetadataLookupStr(NULL, config->arguments, "OUTPUT"); // Output root
    207         assert(outName);
    208         // Read convolution kernel
    209         psString filename = NULL;   // Output filename
    210         psStringAppend(&filename, "%s.%d.kernel", outName, numInput);
    211         psString resolved = pmConfigConvertFilename(filename, config, false, false); // Resolved filename
    212         psFree(filename);
    213         psFits *fits = psFitsOpen(resolved, "r"); // FITS file for subtraction kernel
    214         psFree(resolved);
    215         if (!fits || !pmReadoutReadSubtractionKernels(output, fits)) {
    216             psError(PS_ERR_IO, false, "Unable to read previously produced kernel");
     200        // This is a hack to use the temporary convolved images and kernel generated previously.
     201        // This makes the 'matching' operation much faster, allowing debugging of the stack process easier.
     202        // It implicitly assumes the output root name is the same between invocations.
     203
     204        // Read previously produced kernel
     205        if (psMetadataLookupBool(NULL, config->arguments, "PPSTACK.DEBUG.STACK")) {
     206            pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPSTACK.CONV.KERNEL", index);
     207            psAssert(file, "Require file");
     208
     209            pmFPAview *view = pmFPAviewAlloc(0); // View to readout of interest
     210            view->chip = view->cell = view->readout = 0;
     211            psString filename = pmFPAfileNameFromRule(filerule->rule, file, view); // Filename of interest
     212
     213            // Read convolution kernel
     214            psString resolved = pmConfigConvertFilename(filename, config, false, false); // Resolved filename
     215            psFree(filename);
     216            psFits *fits = psFitsOpen(resolved, "r"); // FITS file for subtraction kernel
     217            psFree(resolved);
     218            if (!fits || !pmReadoutReadSubtractionKernels(conv, fits)) {
     219                psError(PS_ERR_IO, false, "Unable to read previously produced kernel");
     220                psFitsClose(fits);
     221                return false;
     222            }
    217223            psFitsClose(fits);
    218             return false;
    219         }
    220         psFitsClose(fits);
    221 
    222         // Add in variance factor
    223         pmSubtractionKernels *kernels = psMetadataLookupPtr(NULL, output->analysis,
    224                                                             PM_SUBTRACTION_ANALYSIS_KERNEL); // Kernels
    225         float vf = pmSubtractionVarianceFactor(kernels, 0.0, 0.0, false); // Variance factor
    226         psMetadataItem *vfItem = psMetadataLookup(readout->parent->concepts, "CELL.VARFACTOR");
    227         if (!isfinite(vf)) {
    228             vf = 1.0;
    229         }
    230         if (isfinite(vfItem->data.F32)) {
    231             vfItem->data.F32 *= vf;
    232         } else {
    233             vfItem->data.F32 = vf;
    234         }
    235 
    236         // Read image, mask, variance
    237         const char *tempImage = psMetadataLookupStr(NULL, recipe, "TEMP.IMAGE"); // Suffix for image
    238         const char *tempMask = psMetadataLookupStr(NULL, recipe, "TEMP.MASK"); // Suffix for mask
    239         const char *tempVariance = psMetadataLookupStr(NULL, recipe, "TEMP.VARIANCE"); // Suffix for variance map
    240         psString imageName = NULL, maskName = NULL, varianceName = NULL; // Names for convolved images
    241         psStringAppend(&imageName, "%s.%d.%s", outName, numInput, tempImage);
    242         psStringAppend(&maskName, "%s.%d.%s", outName, numInput, tempMask);
    243         psStringAppend(&varianceName, "%s.%d.%s", outName, numInput, tempVariance);
    244 
    245         if (!readImage(&readout->image, imageName, config) || !readImage(&readout->mask, maskName, config) ||
    246             !readImage(&readout->variance, varianceName, config)) {
    247             psError(PS_ERR_IO, false, "Unable to read previously produced image.");
     224
     225            // Add in variance factor
     226            pmSubtractionKernels *kernels = psMetadataLookupPtr(NULL, conv->analysis,
     227                                                                PM_SUBTRACTION_ANALYSIS_KERNEL); // Kernels
     228            float vf = pmSubtractionVarianceFactor(kernels, 0.0, 0.0, false); // Variance factor
     229            psMetadataItem *vfItem = psMetadataLookup(readout->parent->concepts, "CELL.VARFACTOR");
     230            if (!isfinite(vf)) {
     231                vf = 1.0;
     232            }
     233            if (isfinite(vfItem->data.F32)) {
     234                vfItem->data.F32 *= vf;
     235            } else {
     236                vfItem->data.F32 = vf;
     237            }
     238
     239            if (!readImage(&readout->image, options->imageNames->data[index], config) ||
     240                !readImage(&readout->mask, options->maskNames->data[index], config) ||
     241                !readImage(&readout->variance, options->varianceNames->data[index], config)) {
     242                psError(PS_ERR_IO, false, "Unable to read previously produced image.");
     243                psFree(imageName);
     244                psFree(maskName);
     245                psFree(varianceName);
     246                return false;
     247            }
    248248            psFree(imageName);
    249249            psFree(maskName);
    250250            psFree(varianceName);
    251             return false;
    252         }
    253         psFree(imageName);
    254         psFree(maskName);
    255         psFree(varianceName);
    256 
    257         psRegion *region = psMetadataLookupPtr(NULL, output->analysis,
    258                                                PM_SUBTRACTION_ANALYSIS_REGION); // Convolution region
    259 
    260         pmSubtractionAnalysis(readout->analysis, kernels, region,
    261                               readout->image->numCols, readout->image->numRows);
    262 
    263         psKernel *kernel = pmSubtractionKernel(kernels, 0.0, 0.0, false); // Convolution kernel
    264         psKernel *covar = psImageCovarianceCalculate(kernel, readout->covariance); // New covariance matrix
    265         psFree(readout->covariance);
    266         readout->covariance = covar;
    267         psFree(kernel);
    268 
    269     } else {
    270 #endif
    271 
    272         // Normal operations here
    273         if (psMetadataLookupBool(&mdok, config->arguments, "HAVE.PSF")) {
    274             assert(psf);
    275             assert(sources);
     251
     252            psRegion *region = psMetadataLookupPtr(NULL, conv->analysis,
     253                                                   PM_SUBTRACTION_ANALYSIS_REGION); // Convolution region
     254
     255            pmSubtractionAnalysis(readout->analysis, kernels, region,
     256                                  readout->image->numCols, readout->image->numRows);
     257
     258            psKernel *kernel = pmSubtractionKernel(kernels, 0.0, 0.0, false); // Convolution kernel
     259            psKernel *covar = psImageCovarianceCalculate(kernel, readout->covariance); // Covariance matrix
     260            psFree(readout->covariance);
     261            readout->covariance = covar;
     262            psFree(kernel);
     263        } else {
     264#endif
     265
     266            // Normal operations here
     267            psAssert(options->psf, "Require target PSF");
     268            psAssert(options->sourceLists && options->sourceLists->data[index], "Require source list");
    276269
    277270            int order = psMetadataLookupS32(NULL, ppsub, "SPATIAL.ORDER"); // Spatial polynomial order
     
    284277            float rej = psMetadataLookupF32(NULL, ppsub, "REJ"); // Rejection threshold
    285278            float sysError = psMetadataLookupF32(NULL, ppsub, "SYS"); // Relative systematic error in kernel
    286             pmSubtractionKernelsType type = pmSubtractionKernelsTypeFromString(
    287                 psMetadataLookupStr(NULL, ppsub, "KERNEL.TYPE")); // Kernel type
     279            const char *typeStr = psMetadataLookupStr(NULL, ppsub, "KERNEL.TYPE"); // Kernel type
     280            pmSubtractionKernelsType type = pmSubtractionKernelsTypeFromString(typeStr); // Kernel type
    288281            psVector *widths = psMetadataLookupPtr(NULL, ppsub, "ISIS.WIDTHS"); // ISIS Gaussian widths
    289282            psVector *orders = psMetadataLookupPtr(NULL, ppsub, "ISIS.ORDERS"); // ISIS Polynomial orders
     
    308301            }
    309302
    310 #if 0
    311             // Testing the normalisation of the fake image
    312             {
    313                 pmReadout *test = pmReadoutAlloc(NULL); // Test readout
    314                 psArray *sources = psArrayAlloc(1);     // Array of sources
    315                 pmSource *source = pmSourceAlloc();     // Source
    316                 sources->data[0] = source;
    317                 source->peak = pmPeakAlloc(500, 500, 10000, PM_PEAK_LONE);
    318                 source->psfMag = -13.0;
    319                 pmReadoutFakeFromSources(test, 1000, 1000, sources, NULL, NULL, psf, 0.1, 0, false, true);
    320                 float sum = 0.0;
    321                 for (int y = 0; y < test->image->numRows; y++) {
    322                     for (int x = 0; x < test->image->numCols; x++) {
    323                         sum += test->image->data.F32[y][x];
    324                     }
    325                 }
    326                 fprintf(stderr, "Photometry: %f --> %f = -13.0 ???\n", sum, -2.5*log10(sum));
    327 
    328                 psFits *fits = psFitsOpen("testphot.fits", "w");
    329                 psFitsWriteImage(fits, NULL, test->image, 0, NULL);
    330                 psFitsClose(fits);
    331                 exit(0);
    332             }
    333 #endif
    334 
    335303            pmReadout *fake = pmReadoutAlloc(NULL); // Fake readout with target PSF
    336304
    337305            // For the sake of stamps, remove nearby sources
    338             psArray *stampSources = stackSourcesFilter(sources, footprint); // Filtered list of sources
     306            psArray *stampSources = stackSourcesFilter(options->sourceLists->data[index],
     307                                                       footprint); // Filtered list of sources
    339308
    340309            if (!pmReadoutFakeFromSources(fake, readout->image->numCols, readout->image->numRows,
    341                                           stampSources, NULL, NULL, psf, NAN, footprint + size,
     310                                          stampSources, NULL, NULL, options->psf, NAN, footprint + size,
    342311                                          false, true)) {
    343312                psError(PS_ERR_UNKNOWN, false, "Unable to generate fake image with target PSF.");
    344313                psFree(fake);
    345314                psFree(optWidths);
    346                 psFree(output);
     315                psFree(conv);
    347316                return false;
    348317            }
     
    357326                pmHDU *hdu = pmHDUFromCell(readout->parent);
    358327                psString name = NULL;
    359                 psStringAppend(&name, "fake_%03d.fits", numInput);
     328                psStringAppend(&name, "fake_%03d.fits", index);
    360329                pmStackVisualPlotTestImage(fake->image, name);
    361330                psFits *fits = psFitsOpen(name, "w");
     
    367336                pmHDU *hdu = pmHDUFromCell(readout->parent);
    368337                psString name = NULL;
    369                 psStringAppend(&name, "real_%03d.fits", numInput);
     338                psStringAppend(&name, "real_%03d.fits", index);
    370339                pmStackVisualPlotTestImage(readout->image, name);
    371340                psFits *fits = psFitsOpen(name, "w");
     
    381350
    382351            // Do the image matching
    383             if (!pmSubtractionMatch(output, NULL, readout, fake, footprint, stride, regionSize, spacing,
    384                                     threshold, stampSources, stampsName, type, size, order, widths, orders,
    385                                     inner, ringsOrder, binning, penalty, optimum, optWidths, optOrder,
    386                                     optThresh, iter, rej, sysError, maskVal, maskBad, maskPoor, poorFrac,
    387                                     badFrac, PM_SUBTRACTION_MODE_1)) {
    388                 psError(PS_ERR_UNKNOWN, false, "Unable to match images.");
    389                 psFree(fake);
    390                 psFree(optWidths);
    391                 psFree(stampSources);
    392                 psFree(output);
    393                 return false;
     352            pmSubtractionKernels *kernel = psMetadataLookupPtr(&mdok, readout->analysis,
     353                                                               PM_SUBTRACTION_ANALYSIS_KERNEL); // Conv kernel
     354            if (kernel) {
     355                if (!pmSubtractionMatchPrecalc(conv, NULL, readout, fake, readout->analysis,
     356                                               stride, sysError, maskVal, maskBad, maskPoor,
     357                                               poorFrac, badFrac)) {
     358                    psError(PS_ERR_UNKNOWN, false, "Unable to convolve images.");
     359                    psFree(fake);
     360                    psFree(optWidths);
     361                    psFree(stampSources);
     362                    psFree(conv);
     363                    return false;
     364                }
     365            } else {
     366                if (!pmSubtractionMatch(conv, NULL, readout, fake, footprint, stride, regionSize, spacing,
     367                                        threshold, stampSources, stampsName, type, size, order, widths,
     368                                        orders, inner, ringsOrder, binning, penalty,
     369                                        optimum, optWidths, optOrder, optThresh, iter, rej, sysError,
     370                                        maskVal, maskBad, maskPoor, poorFrac, badFrac,
     371                                        PM_SUBTRACTION_MODE_1)) {
     372                    psError(PS_ERR_UNKNOWN, false, "Unable to match images.");
     373                    psFree(fake);
     374                    psFree(optWidths);
     375                    psFree(stampSources);
     376                    psFree(conv);
     377                    return false;
     378                }
    394379            }
    395380
     
    398383                pmHDU *hdu = pmHDUFromCell(readout->parent);
    399384                psString name = NULL;
    400                 psStringAppend(&name, "conv_%03d.fits", numInput);
    401                 pmStackVisualPlotTestImage(output->image, name);
     385                psStringAppend(&name, "conv_%03d.fits", index);
     386                pmStackVisualPlotTestImage(conv->image, name);
    402387                psFits *fits = psFitsOpen(name, "w");
    403388                psFree(name);
    404                 psFitsWriteImage(fits, hdu->header, output->image, 0, NULL);
     389                psFitsWriteImage(fits, hdu->header, conv->image, 0, NULL);
    405390                psFitsClose(fits);
    406391            }
     
    408393                pmHDU *hdu = pmHDUFromCell(readout->parent);
    409394                psString name = NULL;
    410                 psStringAppend(&name, "diff_%03d.fits", numInput);
     395                psStringAppend(&name, "diff_%03d.fits", index);
    411396                pmStackVisualPlotTestImage(fake->image, name);
    412397                psFits *fits = psFitsOpen(name, "w");
    413398                psFree(name);
    414                 psBinaryOp(fake->image, output->image, "-", fake->image);
     399                psBinaryOp(fake->image, conv->image, "-", fake->image);
    415400                psFitsWriteImage(fits, hdu->header, fake->image, 0, NULL);
    416401                psFitsClose(fits);
     
    428413            // Set the variance factor
    429414            psMetadataItem *vfItem = psMetadataLookup(readout->parent->concepts, "CELL.VARFACTOR");
    430             float vf = psMetadataLookupF32(NULL, output->analysis, PM_SUBTRACTION_ANALYSIS_VARFACTOR_1);
     415            float vf = psMetadataLookupF32(NULL, conv->analysis, PM_SUBTRACTION_ANALYSIS_VARFACTOR_1);
    431416            if (!isfinite(vf)) {
    432417                vf = 1.0;
     
    443428            psFree(readout->variance);
    444429            psFree(readout->covariance);
    445             readout->image  = psMemIncrRefCounter(output->image);
    446             readout->mask   = psMemIncrRefCounter(output->mask);
    447             readout->variance = psMemIncrRefCounter(output->variance);
    448             readout->covariance = psImageCovarianceTruncate(output->covariance, COVAR_FRAC);
    449         } else {
    450             // Fake the convolution
    451             psRegion *region = psRegionAlloc(0, readout->image->numCols - 1, 0, readout->image->numRows - 1);
    452             psMetadataAddPtr(output->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_REGION,
    453                              PS_DATA_REGION | PS_META_DUPLICATE_OK, "Fake subtraction region", region);
    454             psFree(region);
    455             pmSubtractionKernels *kernels = pmSubtractionKernelsPOIS(FAKE_SIZE, 0, penalty,
    456                                                                      PM_SUBTRACTION_MODE_1);
    457             // Set solution to delta function
    458             kernels->solution1 = psVectorAlloc(kernels->num + 2, PS_TYPE_F64);
    459             psVectorInit(kernels->solution1, 0.0);
    460             int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation
    461             kernels->solution1->data.F64[normIndex] = 1.0;
    462             psMetadataAddPtr(output->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_KERNEL,
    463                              PS_DATA_UNKNOWN | PS_META_DUPLICATE_OK, "Fake subtraction kernel", kernels);
    464             psFree(kernels);
    465         }
    466 
     430            readout->image  = psMemIncrRefCounter(conv->image);
     431            readout->mask   = psMemIncrRefCounter(conv->mask);
     432            readout->variance = psMemIncrRefCounter(conv->variance);
     433            readout->covariance = psImageCovarianceTruncate(conv->covariance, COVAR_FRAC);
    467434#ifdef TESTING
    468         // Write convolution kernel
     435        }
     436#endif
     437
     438        // Extract the regions and solutions used in the image matching
     439        // This stops them from being freed when we iterate back up the FPA
     440        psArray *regions = options->regions->data[index] = psArrayAllocEmpty(ARRAY_BUFFER); // Match regions
    469441        {
    470             const char *outName = psMetadataLookupStr(NULL, config->arguments, "OUTPUT"); // Output root
    471             assert(outName);
    472 
    473             psString filename = NULL;   // Output filename
    474             psStringAppend(&filename, "%s.%d.kernel", outName, numInput);
    475             psString resolved = pmConfigConvertFilename(filename, config, true, false); // Resolved filename
    476             psFree(filename);
    477             psFits *fits = psFitsOpen(resolved, "w"); // FITS file for subtraction kernel
    478             psFree(resolved);
    479             pmReadoutWriteSubtractionKernels(output, fits);
    480             psFitsClose(fits);
    481         }
    482     }
    483 #endif
    484 
    485     readout->analysis = psMetadataCopy(readout->analysis, output->analysis);
    486 
    487 // Extract the regions and solutions used in the image matching
    488 // This stops them from being freed when we iterate back up the FPA
    489     *regions = psArrayAllocEmpty(ARRAY_BUFFER); // Array of regions
    490     {
    491         psString regex = NULL;          // Regular expression
    492         psStringAppend(&regex, "^%s$", PM_SUBTRACTION_ANALYSIS_REGION);
    493         psMetadataIterator *iter = psMetadataIteratorAlloc(output->analysis, PS_LIST_HEAD, regex); // Iterator
    494         psFree(regex);
    495         psMetadataItem *item = NULL;// Item from iteration
    496         while ((item = psMetadataGetAndIncrement(iter))) {
    497             assert(item->type == PS_DATA_REGION);
    498             *regions = psArrayAdd(*regions, ARRAY_BUFFER, item->data.V);
    499         }
    500         psFree(iter);
    501     }
    502     *kernels = psArrayAllocEmpty(ARRAY_BUFFER); // Array of kernels
    503     {
    504         psString regex = NULL;          // Regular expression
    505         psStringAppend(&regex, "^%s$", PM_SUBTRACTION_ANALYSIS_KERNEL);
    506         psMetadataIterator *iter = psMetadataIteratorAlloc(output->analysis, PS_LIST_HEAD, regex); // Iterator
    507         psFree(regex);
    508         psMetadataItem *item = NULL;// Item from iteration
    509         while ((item = psMetadataGetAndIncrement(iter))) {
    510             assert(item->type == PS_DATA_UNKNOWN);
    511             // Set the normalisation dimensions, since these will be otherwise unavailable when reading the
    512             // images by scans.
    513             pmSubtractionKernels *kernel = item->data.V; // Kernel used in subtraction
    514             kernel->numCols = readout->image->numCols;
    515             kernel->numRows = readout->image->numRows;
    516 
    517             *kernels = psArrayAdd(*kernels, ARRAY_BUFFER, kernel);
    518         }
    519         psFree(iter);
    520     }
    521     assert((*regions)->n == (*kernels)->n);
    522 
    523     // Record chi^2
    524     {
    525         *chi2 = 0.0;
    526         int num = 0;                    // Number of measurements of chi^2
    527         psString regex = NULL;          // Regular expression
    528         psStringAppend(&regex, "^%s$", PM_SUBTRACTION_ANALYSIS_KERNEL);
    529         psMetadataIterator *iter = psMetadataIteratorAlloc(output->analysis, PS_LIST_HEAD, regex); // Iterator
    530         psFree(regex);
    531         psMetadataItem *item = NULL;// Item from iteration
    532         while ((item = psMetadataGetAndIncrement(iter))) {
    533             assert(item->type == PS_DATA_UNKNOWN);
    534             pmSubtractionKernels *kernels = item->data.V; // Convolution kernels
    535             *chi2 += kernels->mean;
    536             num++;
    537         }
    538         psFree(iter);
    539         *chi2 /= psImageCovarianceFactor(readout->covariance) * num;
    540     }
    541 
    542     // Reject image completely if the maximum deconvolution fraction exceeds the limit
    543     float deconv = psMetadataLookupF32(NULL, output->analysis,
    544                                        PM_SUBTRACTION_ANALYSIS_DECONV_MAX); // Maximum deconvolution fraction
    545     if (deconv > deconvLimit) {
    546         psWarning("Maximum deconvolution fraction (%f) exceeds limit (%f) --- rejecting\n",
    547                   deconv, deconvLimit);
    548         psFree(output);
    549         return NULL;
     442            psString regex = NULL;          // Regular expression
     443            psStringAppend(&regex, "^%s$", PM_SUBTRACTION_ANALYSIS_REGION);
     444            psMetadataIterator *iter = psMetadataIteratorAlloc(conv->analysis, PS_LIST_HEAD, regex);
     445            psFree(regex);
     446            psMetadataItem *item = NULL;// Item from iteration
     447            while ((item = psMetadataGetAndIncrement(iter))) {
     448                assert(item->type == PS_DATA_REGION);
     449                regions = psArrayAdd(regions, ARRAY_BUFFER, item->data.V);
     450            }
     451            psFree(iter);
     452        }
     453        psArray *kernels = options->kernels->data[index] = psArrayAllocEmpty(ARRAY_BUFFER); // Match kernels
     454        {
     455            psString regex = NULL;          // Regular expression
     456            psStringAppend(&regex, "^%s$", PM_SUBTRACTION_ANALYSIS_KERNEL);
     457            psMetadataIterator *iter = psMetadataIteratorAlloc(conv->analysis, PS_LIST_HEAD, regex);
     458            psFree(regex);
     459            psMetadataItem *item = NULL;// Item from iteration
     460            while ((item = psMetadataGetAndIncrement(iter))) {
     461                assert(item->type == PS_DATA_UNKNOWN);
     462                // Set the normalisation dimensions, since these will be otherwise unavailable when reading
     463                // the images by scans.
     464                pmSubtractionKernels *kernel = item->data.V; // Kernel used in subtraction
     465                kernel->numCols = readout->image->numCols;
     466                kernel->numRows = readout->image->numRows;
     467
     468                kernels = psArrayAdd(kernels, ARRAY_BUFFER, kernel);
     469            }
     470            psFree(iter);
     471        }
     472        psAssert((regions)->n == (kernels)->n, "Number of match regions and kernels should match");
     473
     474        // Record chi^2
     475        {
     476            double sum = 0.0;           // Sum of chi^2
     477            int num = 0;                // Number of measurements of chi^2
     478            psString regex = NULL;      // Regular expression
     479            psStringAppend(&regex, "^%s$", PM_SUBTRACTION_ANALYSIS_KERNEL);
     480            psMetadataIterator *iter = psMetadataIteratorAlloc(conv->analysis, PS_LIST_HEAD, regex);
     481            psFree(regex);
     482            psMetadataItem *item = NULL;// Item from iteration
     483            while ((item = psMetadataGetAndIncrement(iter))) {
     484                assert(item->type == PS_DATA_UNKNOWN);
     485                pmSubtractionKernels *kernels = item->data.V; // Convolution kernels
     486                sum += kernels->mean;
     487                num++;
     488            }
     489            psFree(iter);
     490            options->matchChi2->data.F32[index] = sum / (psImageCovarianceFactor(readout->covariance) * num);
     491        }
     492
     493        // Reject image completely if the maximum deconvolution fraction exceeds the limit
     494        float deconv = psMetadataLookupF32(NULL, conv->analysis,
     495                                           PM_SUBTRACTION_ANALYSIS_DECONV_MAX); // Max deconvolution fraction
     496        if (deconv > deconvLimit) {
     497            psWarning("Maximum deconvolution fraction (%f) exceeds limit (%f) --- rejecting\n",
     498                      deconv, deconvLimit);
     499            psFree(conv);
     500            return NULL;
     501        }
     502
     503        readout->analysis = psMetadataCopy(readout->analysis, conv->analysis);
     504
     505        psFree(conv);
     506    } else {
     507        // Match the normalisation
     508        float norm = powf(10.0, -0.4 * options->norm->data.F32[index]); // Normalisation
     509        psBinaryOp(readout->image, readout->image, "*", psScalarAlloc(norm, PS_TYPE_F32));
     510        psBinaryOp(readout->variance, readout->variance, "*", psScalarAlloc(PS_SQR(norm), PS_TYPE_F32));
    550511    }
    551512
    552513    // Ensure the background value is zero
    553514    psStats *bg = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics for background
     515    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator
    554516    if (!psImageBackground(bg, NULL, readout->image, readout->mask, maskVal | maskBad, rng)) {
    555517        psWarning("Can't measure background for image.");
     
    565527    if (!psImageBackground(bg, NULL, readout->variance, readout->mask, maskVal | maskBad, rng)) {
    566528        psError(PS_ERR_UNKNOWN, false, "Can't measure mean variance for image.");
    567         psFree(output);
     529        psFree(rng);
     530        psFree(bg);
    568531        return false;
    569532    }
    570     *weighting = 1.0 / (psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN) *
    571                         psImageCovarianceFactor(readout->covariance));
     533    options->weightings->data.F32[index] = 1.0 / (psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN) *
     534                                                  psImageCovarianceFactor(readout->covariance));
    572535    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "PPSTACK.WEIGHTING", 0,
    573                      "Weighting by 1/noise^2 for stack", *weighting);
    574 
     536                     "Weighting by 1/noise^2 for stack", options->weightings->data.F32[index]);
     537
     538    psFree(rng);
    575539    psFree(bg);
    576 
    577 #if 0
    578 #define RADIUS 10                       // Radius of photometry
    579 #define MIN_ERR 0.05                    // Minimum photometric error, mag
    580 #define MAX_MAG -13                     // Maximum magnitude for source
    581 
    582     // Ensure the normalisation is correct
    583     // XXX Ideally, would like to do proper PSF-fit photometry, but will settle for aperture photometry
    584     int numSources = sources->n;        // Number of sources
    585     psVector *ratio = psVectorAlloc(numSources, PS_TYPE_F32); // Flux ratios for sources
    586     psVector *ratioMask = psVectorAlloc(numSources, PS_TYPE_MASK); // Mask for flux ratios
    587     psVectorInit(ratioMask, 0xFF);
    588     psImage *image = readout->image;    // Image of interest
    589     psImage *mask = readout->mask;      // Mask of interest
    590     int numCols = image->numCols, numRows = image->numRows; // Size of image
    591     for (int i = 0; i < numSources; i++) {
    592         pmSource *source = sources->data[i]; // Source of interest
    593         if (!source || source->mode & SOURCE_MASK || !isfinite(source->psfMag) || !isfinite(source->errMag) ||
    594             source->errMag > MIN_ERR || source->psfMag > MAX_MAG) {
    595             continue;
    596         }
    597 
    598         float xSrc, ySrc;              // Source coordinates
    599         coordsFromSource(&xSrc, &ySrc, source);
    600         int xMin = PS_MAX(0, xSrc - RADIUS), xMax = PS_MIN(numCols - 1, xSrc + RADIUS); // Bounds in x
    601         int yMin = PS_MAX(0, ySrc - RADIUS), yMax = PS_MIN(numRows - 1, ySrc + RADIUS); // Bounds in y
    602         int numPix = 0;                 // Number of pixels
    603         float sum = 0.0;                // Sum of pixels
    604         for (int y = yMin; y <= yMax; y++) {
    605             for (int x = xMin; x <= xMax; x++) {
    606                 if (mask->data.PS_TYPE_MASK_DATA[y][x] & maskBad) {
    607                     continue;
    608                 }
    609                 sum += image->data.F32[y][x];
    610                 numPix++;
    611             }
    612         }
    613         if (sum >= 0 && numPix > 0) {
    614             float mag = -2.5 * log10(sum * M_PI * PS_SQR(RADIUS) / numPix); // Instrumental magnitude
    615             ratio->data.F32[i] = mag - source->psfMag;
    616             ratioMask->data.PS_TYPE_MASK_DATA[i] = 0;
    617         }
    618     }
    619 
    620     psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics
    621     if (!psVectorStats(stats, ratio, NULL, ratioMask, 0xFF)) {
    622         psWarning("Unable to measure normalisation --- assuming correct.");
    623     } else {
    624         psLogMsg("ppStack", PS_LOG_INFO, "Renormalising image by %f (+/- %f) mag\n",
    625                  stats->robustMedian, stats->robustStdev);
    626         float norm = powf(10.0, -0.4 * stats->robustMedian); // Normalisation to apply
    627         psBinaryOp(image, image, "*", psScalarAlloc(norm, PS_TYPE_F32));
    628     }
    629     psFree(stats);
    630     psFree(ratio);
    631     psFree(ratioMask);
    632 #endif
    633540
    634541#ifdef TESTING
     
    636543        pmHDU *hdu = pmHDUFromCell(readout->parent);
    637544        psString name = NULL;
    638         psStringAppend(&name, "convolved_%03d.fits", numInput);
    639         pmStackVisualPlotTestImage(output->image, name);
     545        psStringAppend(&name, "convolved_%03d.fits", index);
     546        pmStackVisualPlotTestImage(readout->image, name);
    640547        psFits *fits = psFitsOpen(name, "w");
    641548        psFree(name);
    642         psFitsWriteImage(fits, hdu->header, output->image, 0, NULL);
     549        psFitsWriteImage(fits, hdu->header, readout->image, 0, NULL);
    643550        psFitsClose(fits);
    644551    }
    645552#endif
    646 
    647     psFree(output);
    648553
    649554    return true;
Note: See TracChangeset for help on using the changeset viewer.