IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jan 28, 2009, 10:49:50 AM (17 years ago)
Author:
Paul Price
Message:

Merging pap_branch_20090108: fixed photometric normalisation. Conflicts resolved, code compiles.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ppStack/src/ppStackMatch.c

    r21183 r21199  
    66#include <pslib.h>
    77#include <psmodules.h>
     8#include <psphot.h>
    89
    910#include "ppStack.h"
     
    4748#endif
    4849
     50// Get coordinates from a source
     51static void coordsFromSource(float *x, float *y, const pmSource *source)
     52{
     53    assert(x && y);
     54    assert(source);
     55
     56    if (source->modelPSF) {
     57        *x = source->modelPSF->params->data.F32[PM_PAR_XPOS];
     58        *y = source->modelPSF->params->data.F32[PM_PAR_YPOS];
     59    } else {
     60        *x = source->peak->xf;
     61        *y = source->peak->yf;
     62    }
     63    return;
     64}
     65
    4966static psArray *stackSourcesFilter(psArray *sources, // Source list to filter
    5067                                   int exclusion // Exclusion zone, pixels
     
    6481            continue;
    6582        }
    66         x->data.F32[numGood] = source->peak->xf;
    67         y->data.F32[numGood] = source->peak->yf;
     83        coordsFromSource(&x->data.F32[numGood], &y->data.F32[numGood], source);
    6884        numGood++;
    6985    }
     
    8096            continue;
    8197        }
    82         coords->data.F64[0] = source->peak->xf;
    83         coords->data.F64[1] = source->peak->yf;
     98        float xSource, ySource;         // Coordinates of source
     99        coordsFromSource(&xSource, &ySource, source);
     100
     101        coords->data.F64[0] = xSource;
     102        coords->data.F64[1] = ySource;
    84103
    85104        long numWithin = psTreeWithin(tree, coords, exclusion); // Number within exclusion zone
     
    101120}
    102121
    103 #define BG_SIZE 64                      // Large box half-size in which to measure background
    104 
    105 // Generate a background model of the readout we're matching
    106 psImage *stackBackgroundModel(pmReadout *ro, psImageMaskType maskVal, const psArray *sources, int size)
     122// Add background into the fake image
     123// Based on ppSubBackground()
     124static psImage *stackBackgroundModel(pmReadout *ro, // Readout for which to generate background model
     125                                     const pmConfig *config // Configuration
     126    )
    107127{
    108     psImage *image = ro->image, *mask = ro->mask; // Image and mask of readout
     128    psAssert(ro && ro->image, "Need readout image");
     129    psAssert(config, "Need configuration");
     130
     131    psImage *image = ro->image;         // Image of interest
    109132    int numCols = image->numCols, numRows = image->numRows; // Size of image
    110133
    111     psImage *bgImage = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Background image
    112     psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics for measuring background
    113     psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator
    114 
    115     for (int i = 0; i < sources->n; i++) {
    116         pmSource *source = sources->data[i]; // Source of interest
    117         if (!source) {
    118             continue;
    119         }
    120 
    121         int x = source->peak->xf + 0.5, y = source->peak->yf + 0.5; // Coordinates of source
    122 
    123         int xMin = PS_MAX(x - BG_SIZE, 0), xMax = PS_MIN(x + BG_SIZE, numCols);
    124         int yMin = PS_MAX(y - BG_SIZE, 0), yMax = PS_MIN(y + BG_SIZE, numCols);
    125 
    126         psRegion region = psRegionSet(xMin, xMax, yMin, yMax); // Region of interest
    127         psImage *subImage = psImageSubset(image, region); // Subimage
    128         psImage *subMask = psImageSubset(mask, region); // Subimage mask
    129         if (!psImageBackground(stats, NULL, subImage, subMask, maskVal, rng)) {
    130             // Can't do anything about it
    131             psErrorClear();
    132             continue;
    133         }
    134         psFree(subImage);
    135         psFree(subMask);
    136 
    137         float value = stats->robustMedian; // Value to set background to
    138 
    139         int uMin = PS_MAX(x - size, 0), uMax = PS_MIN(x + size, numCols);
    140         int vMin = PS_MAX(y - size, 0), vMax = PS_MIN(y + size, numCols);
    141 
    142         for (int v = vMin; v < vMax; v++) {
    143             for (int u = uMin; u < uMax; u++) {
    144                 bgImage->data.F32[v][u] = value;
    145             }
    146         }
    147     }
    148 
    149     psFree(stats);
    150     psFree(rng);
    151 
    152     return bgImage;
     134    psMetadata *ppStackRecipe = psMetadataLookupPtr(NULL, config->recipes, PPSTACK_RECIPE);
     135    psAssert(ppStackRecipe, "Need PPSTACK recipe");
     136    psMetadata *psphotRecipe = psMetadataLookupPtr(NULL, config->recipes, PSPHOT_RECIPE);
     137    psAssert(psphotRecipe, "Need PSPHOT recipe");
     138
     139    psString maskBadStr = psMetadataLookupStr(NULL, ppStackRecipe, "MASK.BAD");// Name of bits to mask for bad
     140    psMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels
     141
     142    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     143    psMetadataAddU8(psphotRecipe, PS_LIST_TAIL, "MASK.PSPHOT", PS_META_REPLACE, "user-defined mask", maskBad);
     144
     145    psImage *binned = psphotBackgroundModel(ro, config); // Binned background model
     146    psImageBinning *binning = psMetadataLookupPtr(NULL, psphotRecipe,
     147                                                  "PSPHOT.BACKGROUND.BINNING"); // Binning for model
     148    psAssert(binning, "Need binning parameters");
     149    psImage *unbinned = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Unbinned background model
     150    if (!psImageUnbin(unbinned, binned, binning)) {
     151        psError(PS_ERR_UNKNOWN, false, "Unable to unbin background model");
     152        psFree(unbinned);
     153        return NULL;
     154    }
     155
     156    // XXX should these really be here?? (probably not...)
     157    // pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL");
     158    // pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL.STDEV");
     159
     160     return unbinned;
    153161}
     162
    154163
    155164bool ppStackMatch(pmReadout *readout, psArray **regions, psArray **kernels, float *chi2, float *weighting,
     
    163172    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSTACK_RECIPE); // ppStack recipe
    164173    psAssert(recipe, "We've thrown an error on this before.");
     174
     175    float deconvLimit = psMetadataLookupF32(NULL, recipe, "DECONV.LIMIT"); // Limit on deconvolution fraction
    165176
    166177    // Look up appropriate values from the ppSub recipe
     
    195206        assert(outName);
    196207        // Read convolution kernel
    197         {
    198             psString filename = NULL;   // Output filename
    199             psStringAppend(&filename, "%s.%d.kernel", outName, numInput);
    200             psString resolved = pmConfigConvertFilename(filename, config, false, false); // Resolved filename
    201             psFree(filename);
    202             psFits *fits = psFitsOpen(resolved, "r"); // FITS file for subtraction kernel
    203             psFree(resolved);
    204             if (!fits || !pmReadoutReadSubtractionKernels(output, fits)) {
    205                 psError(PS_ERR_IO, false, "Unable to read previously produced kernel");
    206                 psFitsClose(fits);
    207                 return false;
    208             }
     208        psString filename = NULL;   // Output filename
     209        psStringAppend(&filename, "%s.%d.kernel", outName, numInput);
     210        psString resolved = pmConfigConvertFilename(filename, config, false, false); // Resolved filename
     211        psFree(filename);
     212        psFits *fits = psFitsOpen(resolved, "r"); // FITS file for subtraction kernel
     213        psFree(resolved);
     214        if (!fits || !pmReadoutReadSubtractionKernels(output, fits)) {
     215            psError(PS_ERR_IO, false, "Unable to read previously produced kernel");
    209216            psFitsClose(fits);
    210 
    211             // Add in variance factor
    212             pmSubtractionKernels *kernels = psMetadataLookupPtr(NULL, output->analysis,
    213                                                                 PM_SUBTRACTION_ANALYSIS_KERNEL); // Kernels
    214             float vf = pmSubtractionVarianceFactor(kernels, 0.0, 0.0, false); // Variance factor
    215             psMetadataItem *vfItem = psMetadataLookup(readout->parent->concepts, "CELL.VARFACTOR");
    216             if (!isfinite(vf)) {
    217                 vf = 1.0;
    218             }
    219             if (isfinite(vfItem->data.F32)) {
    220                 vfItem->data.F32 *= vf;
    221             } else {
    222                 vfItem->data.F32 = vf;
    223             }
     217            return false;
     218        }
     219        psFitsClose(fits);
     220
     221        // Add in variance factor
     222        pmSubtractionKernels *kernels = psMetadataLookupPtr(NULL, output->analysis,
     223                                                            PM_SUBTRACTION_ANALYSIS_KERNEL); // Kernels
     224        float vf = pmSubtractionVarianceFactor(kernels, 0.0, 0.0, false); // Variance factor
     225        psMetadataItem *vfItem = psMetadataLookup(readout->parent->concepts, "CELL.VARFACTOR");
     226        if (!isfinite(vf)) {
     227            vf = 1.0;
     228        }
     229        if (isfinite(vfItem->data.F32)) {
     230            vfItem->data.F32 *= vf;
     231        } else {
     232            vfItem->data.F32 = vf;
    224233        }
    225234
     
    244253        psFree(maskName);
    245254        psFree(weightName);
     255
     256        psRegion *region = psMetadataLookupPtr(NULL, output->analysis,
     257                                               PM_SUBTRACTION_ANALYSIS_REGION); // Convolution region
     258
     259        pmSubtractionAnalysis(readout->analysis, kernels, region,
     260                              readout->image->numCols, readout->image->numRows);
    246261    } else {
    247262#endif
     
    285300            }
    286301
    287             // Generate a fake image to match to
    288             float minFlux = INFINITY;       // Minimum flux for fake image
    289             {
    290                 psStats *bg = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics for bg
    291                 if (!psImageBackground(bg, NULL, readout->image, readout->mask, maskVal, rng)) {
    292                     psWarning("Can't measure background for image.");
    293                     psErrorClear();
    294                 } else {
    295                     minFlux = bg->robustStdev;
    296                 }
    297                 psFree(bg);
    298             }
    299 
    300 #if 0
    301             float maxMag = -INFINITY;   // Maximum magnitude of sources
    302             for (int i = 0; i < sources->n; i++) {
    303                 pmSource *source = sources->data[i]; // Source of interest
    304                 if (source->psfMag > maxMag && source->psfMag <= MAG_IGNORE &&
    305                     !(source->mode & SOURCE_MASK)) {
    306                     maxMag = source->psfMag;
    307                 }
    308             }
    309             minFlux = PS_MIN(FAINT_SOURCE_FRAC * powf(10.0, -0.4 * maxMag), minFlux);
    310 #endif
    311 
    312 
    313302#if 0
    314303            // Testing the normalisation of the fake image
     
    318307                pmSource *source = pmSourceAlloc();     // Source
    319308                sources->data[0] = source;
    320                 source->peak = pmPeakAlloc(50, 50, 10000, PM_PEAK_LONE);
     309                source->peak = pmPeakAlloc(500, 500, 10000, PM_PEAK_LONE);
    321310                source->psfMag = -13.0;
    322                 pmReadoutFakeFromSources(test, 100, 100, sources, NULL, NULL, psf, 0.1, 0, false, true);
     311                pmReadoutFakeFromSources(test, 1000, 1000, sources, NULL, NULL, psf, 0.1, 0, false, true);
    323312                float sum = 0.0;
    324313                for (int y = 0; y < test->image->numRows; y++) {
     
    342331
    343332            if (!pmReadoutFakeFromSources(fake, readout->image->numCols, readout->image->numRows,
    344                                           stampSources, NULL, NULL, psf, minFlux, 0, false, true)) {
     333                                          stampSources, NULL, NULL, psf, NAN, footprint + size,
     334                                          false, true)) {
    345335                psError(PS_ERR_UNKNOWN, false, "Unable to generate fake image with target PSF.");
    346336                psFree(fake);
     
    351341
    352342            // Add the background into the target image
    353             psImage *bgImage = stackBackgroundModel(readout, maskVal, stampSources, footprint); // Image of background
     343            psImage *bgImage = stackBackgroundModel(readout, config); // Image of background
    354344            psBinaryOp(fake->image, fake->image, "+", bgImage);
    355345            psFree(bgImage);
    356346
    357 
    358347#ifdef TESTING
    359348            {
     349                pmHDU *hdu = pmHDUFromCell(readout->parent);
    360350                psString name = NULL;
    361351                psStringAppend(&name, "fake_%03d.fits", numInput);
    362352                psFits *fits = psFitsOpen(name, "w");
    363353                psFree(name);
    364                 psFitsWriteImage(fits, NULL, fake->image, 0, NULL);
     354                psFitsWriteImage(fits, hdu->header, fake->image, 0, NULL);
    365355                psFitsClose(fits);
    366356            }
    367357            {
     358                pmHDU *hdu = pmHDUFromCell(readout->parent);
    368359                psString name = NULL;
    369360                psStringAppend(&name, "real_%03d.fits", numInput);
    370361                psFits *fits = psFitsOpen(name, "w");
    371362                psFree(name);
    372                 psFitsWriteImage(fits, NULL, readout->image, 0, NULL);
     363                psFitsWriteImage(fits, hdu->header, readout->image, 0, NULL);
    373364                psFitsClose(fits);
    374365            }
     
    410401#ifdef TESTING
    411402            {
     403                pmHDU *hdu = pmHDUFromCell(readout->parent);
    412404                psString name = NULL;
    413405                psStringAppend(&name, "conv_%03d.fits", numInput);
    414406                psFits *fits = psFitsOpen(name, "w");
    415407                psFree(name);
    416                 psFitsWriteImage(fits, NULL, output->image, 0, NULL);
     408                psFitsWriteImage(fits, hdu->header, output->image, 0, NULL);
    417409                psFitsClose(fits);
    418410            }
    419411            {
     412                pmHDU *hdu = pmHDUFromCell(readout->parent);
    420413                psString name = NULL;
    421414                psStringAppend(&name, "diff_%03d.fits", numInput);
     
    423416                psFree(name);
    424417                psBinaryOp(fake->image, output->image, "-", fake->image);
    425                 psFitsWriteImage(fits, NULL, fake->image, 0, NULL);
     418                psFitsWriteImage(fits, hdu->header, fake->image, 0, NULL);
    426419                psFitsClose(fits);
    427420            }
     
    548541    }
    549542
     543    // Reject image completely if the maximum deconvolution fraction exceeds the limit
     544    float deconv = psMetadataLookupF32(NULL, output->analysis,
     545                                       PM_SUBTRACTION_ANALYSIS_DECONV_MAX); // Maximum deconvolution fraction
     546    if (deconv > deconvLimit) {
     547        psWarning("Maximum deconvolution fraction (%f) exceeds limit (%f) --- rejecting\n",
     548                  deconv, deconvLimit);
     549        psFree(output);
     550        return NULL;
     551    }
     552
    550553    // Renormalise the variances if desired
    551554    if (renorm) {
     
    580583    psFree(bg);
    581584
     585
     586#if 0
     587#define RADIUS 10                       // Radius of photometry
     588#define MIN_ERR 0.05                    // Minimum photometric error, mag
     589#define MAX_MAG -13                     // Maximum magnitude for source
     590
     591    // Ensure the normalisation is correct
     592    // XXX Ideally, would like to do proper PSF-fit photometry, but will settle for aperture photometry
     593    int numSources = sources->n;        // Number of sources
     594    psVector *ratio = psVectorAlloc(numSources, PS_TYPE_F32); // Flux ratios for sources
     595    psVector *ratioMask = psVectorAlloc(numSources, PS_TYPE_MASK); // Mask for flux ratios
     596    psVectorInit(ratioMask, 0xFF);
     597    psImage *image = readout->image;    // Image of interest
     598    psImage *mask = readout->mask;      // Mask of interest
     599    int numCols = image->numCols, numRows = image->numRows; // Size of image
     600    for (int i = 0; i < numSources; i++) {
     601        pmSource *source = sources->data[i]; // Source of interest
     602        if (!source || source->mode & SOURCE_MASK || !isfinite(source->psfMag) || !isfinite(source->errMag) ||
     603            source->errMag > MIN_ERR || source->psfMag > MAX_MAG) {
     604            continue;
     605        }
     606
     607        float xSrc, ySrc;              // Source coordinates
     608        coordsFromSource(&xSrc, &ySrc, source);
     609        int xMin = PS_MAX(0, xSrc - RADIUS), xMax = PS_MIN(numCols - 1, xSrc + RADIUS); // Bounds in x
     610        int yMin = PS_MAX(0, ySrc - RADIUS), yMax = PS_MIN(numRows - 1, ySrc + RADIUS); // Bounds in y
     611        int numPix = 0;                 // Number of pixels
     612        float sum = 0.0;                // Sum of pixels
     613        for (int y = yMin; y <= yMax; y++) {
     614            for (int x = xMin; x <= xMax; x++) {
     615                if (mask->data.PS_TYPE_MASK_DATA[y][x] & maskBad) {
     616                    continue;
     617                }
     618                sum += image->data.F32[y][x];
     619                numPix++;
     620            }
     621        }
     622        if (sum >= 0 && numPix > 0) {
     623            float mag = -2.5 * log10(sum * M_PI * PS_SQR(RADIUS) / numPix); // Instrumental magnitude
     624            ratio->data.F32[i] = mag - source->psfMag;
     625            ratioMask->data.PS_TYPE_MASK_DATA[i] = 0;
     626        }
     627    }
     628
     629    psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics
     630    if (!psVectorStats(stats, ratio, NULL, ratioMask, 0xFF)) {
     631        psWarning("Unable to measure normalisation --- assuming correct.");
     632    } else {
     633        psLogMsg("ppStack", PS_LOG_INFO, "Renormalising image by %f (+/- %f) mag\n",
     634                 stats->robustMedian, stats->robustStdev);
     635        float norm = powf(10.0, -0.4 * stats->robustMedian); // Normalisation to apply
     636        psBinaryOp(image, image, "*", psScalarAlloc(norm, PS_TYPE_F32));
     637    }
     638    psFree(stats);
     639    psFree(ratio);
     640    psFree(ratioMask);
     641#endif
     642
     643#ifdef TESTING
     644    {
     645        pmHDU *hdu = pmHDUFromCell(readout->parent);
     646        psString name = NULL;
     647        psStringAppend(&name, "convolved_%03d.fits", numInput);
     648        psFits *fits = psFitsOpen(name, "w");
     649        psFree(name);
     650        psFitsWriteImage(fits, hdu->header, output->image, 0, NULL);
     651        psFitsClose(fits);
     652    }
     653#endif
     654
    582655    psFree(output);
    583656
Note: See TracChangeset for help on using the changeset viewer.