IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jan 20, 2011, 11:53:03 AM (15 years ago)
Author:
eugene
Message:

moved subtractionGetStamps to pmSubtractionStamps and renamed as pmSubtractionStampsSelect; added return value to pmSubtractionStampsGetWindow to specify a size retry; if desired normalization window is too large, retry with a larger stamp size; move around structures to prevent annoying build collisions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20101205/psModules/src/imcombine/pmSubtractionStamps.c

    r30289 r30322  
    2727#include "pmSource.h"
    2828
     29#include "pmSubtractionTypes.h"
    2930#include "pmSubtraction.h"
    3031#include "pmSubtractionStamps.h"
     32#include "pmSubtractionVisual.h"
    3133
    3234#define STAMP_LIST_BUFFER 20            // Number of stamps to add to list at a time
     
    367369}
    368370
    369 
    370 pmSubtractionStampList *pmSubtractionStampsFind(pmSubtractionStampList *stamps, const psImage *image1,
    371                                                 const psImage *image2, const psImage *subMask,
    372                                                 const psRegion *region, float thresh1, float thresh2,
    373                                                 int size, int footprint, float spacing, float normFrac,
    374                                                 float sysErr, float skyErr, pmSubtractionMode mode)
     371bool pmSubtractionStampsSelect(pmSubtractionStampList **stamps, // Stamps to read
     372                               const pmReadout *ro1, // Readout 1
     373                               const pmReadout *ro2, // Readout 2
     374                               const psImage *subMask, // Mask for subtraction, or NULL
     375                               psImage *variance,  // Variance map
     376                               const psRegion *region, // Region of interest
     377                               float thresh1,  // Threshold for stamp finding on readout 1
     378                               float thresh2,  // Threshold for stamp finding on readout 2
     379                               float stampSpacing, // Spacing between stamps
     380                               float normFrac,     // Fraction of flux in window for normalisation window
     381                               float sysError,     // Relative systematic error in images
     382                               float skyError,     // Relative systematic error in images
     383                               int size,         // Kernel half-size
     384                               int footprint,     // Convolution footprint for stamps
     385                               pmSubtractionMode mode // Mode for subtraction
     386    )
     387{
     388    PS_ASSERT_PTR_NON_NULL(stamps, false);
     389    PM_ASSERT_READOUT_NON_NULL(ro1, false);
     390    PM_ASSERT_READOUT_NON_NULL(ro2, false);
     391    PS_ASSERT_IMAGE_NON_NULL(subMask, false);
     392    PS_ASSERT_IMAGE_NON_NULL(variance, false);
     393    PS_ASSERT_PTR_NON_NULL(region, false);
     394
     395    psTrace("psModules.imcombine", 3, "Finding stamps...\n");
     396
     397    psImage *image1 = ro1 ? ro1->image : NULL, *image2 = ro2 ? ro2->image : NULL; // Images of interest
     398
     399    *stamps = pmSubtractionStampsFind(*stamps, image1, image2, subMask, region, thresh1, thresh2,
     400                                      size, footprint, stampSpacing, normFrac, sysError, skyError, mode);
     401    if (!*stamps) {
     402        psError(psErrorCodeLast(), false, "Unable to find stamps.");
     403        return false;
     404    }
     405
     406    psTrace("psModules.imcombine", 3, "Extracting stamps...\n");
     407    if (!pmSubtractionStampsExtract(*stamps, ro1->image, ro2->image, variance, size, *region)) {
     408        psError(psErrorCodeLast(), false, "Unable to extract stamps.");
     409        return false;
     410    }
     411
     412    pmSubtractionVisualPlotStamps(*stamps, (pmReadout *) ro1);
     413    return true;
     414}
     415
     416pmSubtractionStampList *pmSubtractionStampsFind(pmSubtractionStampList *stamps,
     417                                                const psImage *image1,
     418                                                const psImage *image2,
     419                                                const psImage *subMask,
     420                                                const psRegion *region,
     421                                                float thresh1,
     422                                                float thresh2,
     423                                                int size,
     424                                                int footprint,
     425                                                float spacing,
     426                                                float normFrac,
     427                                                float sysErr,
     428                                                float skyErr,
     429                                                pmSubtractionMode mode)
    375430{
    376431    if (!image1 && !image2) {
     
    687742}
    688743
    689 
    690 bool pmSubtractionStampsGetWindow(pmSubtractionStampList *stamps, int kernelSize)
     744// we are essentially using aperture photometry to determine the photometric match between the
     745// images.  we need to choose an appropriate-sized aperture for this analysis.  If it is too
     746// large, the measurement will be noisy (and possibly biased) due to the sky noise.  If it is
     747// too small, or inconsistent, the measurement will be biased.  We use Kron-mag like aperture
     748// scaled by the first radial moment.
     749bool pmSubtractionStampsGetWindow(bool *tryAgain, pmSubtractionStampList *stamps, int kernelSize)
    691750{
    692751    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false);
    693752    PS_ASSERT_INT_NONNEGATIVE(kernelSize, false);
    694753
     754    // if we succeed, or fail with an unrecoverable error, do not try again
     755    if (tryAgain) {
     756        *tryAgain = false;
     757    }
     758
    695759    int size = stamps->footprint; // Size of postage stamps
    696760
     761    // window for moments calculations downstream
     762    psFree (stamps->window);
     763    stamps->window = psKernelAlloc(-size, size, -size, size);
     764    psImageInit(stamps->window->image, 0.0);
     765
     766    // window1 and window2 are mean stamp images used here to measure the
     767    // first radial moment, and thus the normalization window
    697768    psFree (stamps->window1);
    698769    stamps->window1 = psKernelAlloc(-size, size, -size, size);
     
    703774    psImageInit(stamps->window2->image, 0.0);
    704775
    705     // Generate a weighting window based on the fwhms (20% larger than the largest)
    706     {
    707         float fwhm1, fwhm2;
    708 
    709         // XXX this is annoyingly hack-ish
    710         pmSubtractionGetFWHMs(&fwhm1, &fwhm2);
    711 
    712         float sigma = 1.5 * PS_MAX(fwhm1, fwhm2) / 2.35;
    713 
    714         psFree (stamps->window);
    715         stamps->window = psKernelAlloc(-size, size, -size, size);
    716         psImageInit(stamps->window->image, 0.0);
    717 
    718         for (int y = -size; y <= size; y++) {
    719             for (int x = -size; x <= size; x++) {
    720                 stamps->window->kernel[y][x] = exp(-0.5*(x*x + y*y)/(sigma*sigma));
    721             }
    722         }
     776    // Generate an initial weighting window based on the fwhms (50% larger than the largest)
     777    float fwhm1, fwhm2;
     778
     779    // XXX this is annoyingly hack-ish
     780    pmSubtractionGetFWHMs(&fwhm1, &fwhm2);
     781   
     782    float sigma = 1.5 * PS_MAX(fwhm1, fwhm2) / 2.35;
     783   
     784    for (int y = -size; y <= size; y++) {
     785        for (int x = -size; x <= size; x++) {
     786            stamps->window->kernel[y][x] = exp(-0.5*(x*x + y*y)/(sigma*sigma));
     787        }
    723788    }
    724789
     
    810875    psTrace("psModules.imcombine", 3, "Window total (2): %f, threshold: %f\n", sum2, (1.0 - stamps->normFrac) * sum2);
    811876
    812 # if (1)
    813     // this block attempts to calculate the radius based on the first radial moment
     877    // attempt to calculate the normalization window based on the first radial moment
    814878    double Sr1 = 0.0;
    815879    double Sr2 = 0.0;
     
    833897    psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "Kron Radii: %f for 1, %f for 2\n", stamps->normWindow1, stamps->normWindow2);
    834898
     899    // if the calculated normWindows are too large, we will fall off the stamps.  In this case, we need to try again.
     900    if ((stamps->normWindow1 > size) || (stamps->normWindow2 > size)) {
     901        if (tryAgain) {
     902            *tryAgain = true;
     903        }
     904        psFree (stats);
     905        psFree (flux1);
     906        psFree (flux2);
     907        psFree (norm1);
     908        psFree (norm2);
     909        return false;
     910    }
     911
     912    // this is an unrecoverable error : something really bogus in the data
     913    if (stamps->normWindow1 == 0) {
     914        psError(PM_ERR_STAMPS, true, "Unable to determine normalisation window size (1).");
     915        psFree (stats);
     916        psFree (flux1);
     917        psFree (flux2);
     918        psFree (norm1);
     919        psFree (norm2);
     920        return false;
     921    }
     922    if (stamps->normWindow2 == 0) {
     923        psError(PM_ERR_STAMPS, true, "Unable to determine normalisation window size (2).");
     924        psFree (stats);
     925        psFree (flux1);
     926        psFree (flux2);
     927        psFree (norm1);
     928        psFree (norm2);
     929        return false;
     930    }
     931
    835932    // Generate a weighting window based on the kron radii
    836     {
    837         float radius = 2.0 * PS_MAX(R1, R2);
    838 
    839         psImageInit(stamps->window->image, 0.0);
    840 
    841         for (int y = -size; y <= size; y++) {
    842             for (int x = -size; x <= size; x++) {
    843                 if (hypot(x,y) > radius) continue;
    844                 stamps->window->kernel[y][x] = 1.0;
    845             }
    846         }
    847     }
    848 
    849     // complain if normWindow1 or normWindow2 are larger than size
    850     psAssert(stamps->normWindow1 < size, "norm Window 1 too large");
    851     psAssert(stamps->normWindow2 < size, "norm Window 2 too large");
    852 
    853 # else
    854     // XXX : this block attempts to calculate the radius by looking at the curve of growth (or something vaguely equivalent).
    855     // It did not do very well (though a true curve-of-growth analysis might be better...)
    856     bool done1 = false;
    857     bool done2 = false;
    858     double prior1 = 0.0;
    859     double prior2 = 0.0;
    860     double delta1o = 1.0;
    861     double delta2o = 1.0;
    862     for (int radius = 1; radius <= size && !(done1 && done2); radius++) {
    863         double within1 = 0.0;
    864         double within2 = 0.0;
    865         for (int y = -radius; y <= radius; y++) {
    866             for (int x = -radius; x <= radius; x++) {
    867                 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(radius)) {
    868                     within1 += stamps->window1->kernel[y][x];
    869                 }
    870                 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(radius)) {
    871                     within2 += stamps->window2->kernel[y][x];
    872                 }
    873             }
    874         }
    875         double delta1 = (within1 - prior1) / within1;
    876         if (!done1 && (fabs(delta1) < stamps->normFrac)) {
    877             // interpolate to the radius at which delta2 is normFrac:
    878             stamps->normWindow1 = radius - (stamps->normFrac - delta1) / (delta1o - delta1);
    879             psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "choosing %f (%d) for 1 (%f : %f)\n", stamps->normWindow1, radius, within1, delta1);
    880             done1 = true;
    881         }
    882         double delta2 = (within2 - prior2) / within2;
    883         if (!done2 && (fabs(delta2) < stamps->normFrac)) {
    884             // interpolate to the radius at which delta2 is normFrac:
    885             stamps->normWindow2 = radius - (stamps->normFrac - delta2) / (delta2o - delta2);
    886             psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "choosing %f (%d) for 2 (%f : %f)\n", stamps->normWindow2, radius, within2, delta2);
    887             done2 = true;
    888         }
    889         psTrace("psModules.imcombine", 5, "Radius %d: %f (%f) and %f (%f)\n", radius, within1, delta1, within2, delta2);
    890 
    891         prior1 = within1;
    892         prior2 = within2;
    893         delta1o = delta1;
    894         delta2o = delta2;
    895 
    896         // if (!done1 && (within1 > (1.0 - stamps->normFrac) * sum1)) {
    897         //     stamps->normWindow1 = radius;
    898         //     done1 = true;
    899         // }
    900         // if (!done2 && (within2 > (1.0 - stamps->normFrac) * sum2)) {
    901         //     stamps->normWindow2 = radius;
    902         //     done2 = true;
    903         // }
    904 
    905     }
    906 # endif
    907 
    908     psTrace("psModules.imcombine", 3, "Normalisation window radii set to %f and %f\n", stamps->normWindow1, stamps->normWindow2);
    909     if (stamps->normWindow1 == 0 || stamps->normWindow1 >= size) {
    910         psError(PM_ERR_STAMPS, true, "Unable to determine normalisation window size (1).");
    911         return false;
    912     }
    913     if (stamps->normWindow2 == 0 || stamps->normWindow2 >= size) {
    914         psError(PM_ERR_STAMPS, true, "Unable to determine normalisation window size (2).");
    915         return false;
     933    float radius = 2.0 * PS_MAX(R1, R2);
     934    psImageInit(stamps->window->image, 0.0);
     935
     936    // we use a top-hat window for the moments analysis
     937    for (int y = -size; y <= size; y++) {
     938        for (int x = -size; x <= size; x++) {
     939            if (hypot(x,y) > radius) continue;
     940            stamps->window->kernel[y][x] = 1.0;
     941        }
    916942    }
    917943
     
    928954        }
    929955    }
    930 
    931 #if 0
    932     {
    933         psFits *fits = NULL;
    934         fits = psFitsOpen ("window1.norm.fits", "w");
    935         psFitsWriteImage (fits, NULL, stamps->window1->image, 0, NULL);
    936         psFitsClose (fits);
    937         fits = psFitsOpen ("window2.norm.fits", "w");
    938         psFitsWriteImage (fits, NULL, stamps->window2->image, 0, NULL);
    939         psFitsClose (fits);
    940     }
    941 #endif
    942956
    943957    psFree (stats);
Note: See TracChangeset for help on using the changeset viewer.