Changeset 21199 for trunk/ppStack/src/ppStackMatch.c
- Timestamp:
- Jan 28, 2009, 10:49:50 AM (17 years ago)
- File:
-
- 1 edited
-
trunk/ppStack/src/ppStackMatch.c (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ppStack/src/ppStackMatch.c
r21183 r21199 6 6 #include <pslib.h> 7 7 #include <psmodules.h> 8 #include <psphot.h> 8 9 9 10 #include "ppStack.h" … … 47 48 #endif 48 49 50 // Get coordinates from a source 51 static 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 49 66 static psArray *stackSourcesFilter(psArray *sources, // Source list to filter 50 67 int exclusion // Exclusion zone, pixels … … 64 81 continue; 65 82 } 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); 68 84 numGood++; 69 85 } … … 80 96 continue; 81 97 } 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; 84 103 85 104 long numWithin = psTreeWithin(tree, coords, exclusion); // Number within exclusion zone … … 101 120 } 102 121 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() 124 static psImage *stackBackgroundModel(pmReadout *ro, // Readout for which to generate background model 125 const pmConfig *config // Configuration 126 ) 107 127 { 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 109 132 int numCols = image->numCols, numRows = image->numRows; // Size of image 110 133 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; 153 161 } 162 154 163 155 164 bool ppStackMatch(pmReadout *readout, psArray **regions, psArray **kernels, float *chi2, float *weighting, … … 163 172 psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSTACK_RECIPE); // ppStack recipe 164 173 psAssert(recipe, "We've thrown an error on this before."); 174 175 float deconvLimit = psMetadataLookupF32(NULL, recipe, "DECONV.LIMIT"); // Limit on deconvolution fraction 165 176 166 177 // Look up appropriate values from the ppSub recipe … … 195 206 assert(outName); 196 207 // 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"); 209 216 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; 224 233 } 225 234 … … 244 253 psFree(maskName); 245 254 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); 246 261 } else { 247 262 #endif … … 285 300 } 286 301 287 // Generate a fake image to match to288 float minFlux = INFINITY; // Minimum flux for fake image289 {290 psStats *bg = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics for bg291 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 0301 float maxMag = -INFINITY; // Maximum magnitude of sources302 for (int i = 0; i < sources->n; i++) {303 pmSource *source = sources->data[i]; // Source of interest304 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 #endif311 312 313 302 #if 0 314 303 // Testing the normalisation of the fake image … … 318 307 pmSource *source = pmSourceAlloc(); // Source 319 308 sources->data[0] = source; 320 source->peak = pmPeakAlloc(50 , 50, 10000, PM_PEAK_LONE);309 source->peak = pmPeakAlloc(500, 500, 10000, PM_PEAK_LONE); 321 310 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); 323 312 float sum = 0.0; 324 313 for (int y = 0; y < test->image->numRows; y++) { … … 342 331 343 332 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)) { 345 335 psError(PS_ERR_UNKNOWN, false, "Unable to generate fake image with target PSF."); 346 336 psFree(fake); … … 351 341 352 342 // Add the background into the target image 353 psImage *bgImage = stackBackgroundModel(readout, maskVal, stampSources, footprint); // Image of background343 psImage *bgImage = stackBackgroundModel(readout, config); // Image of background 354 344 psBinaryOp(fake->image, fake->image, "+", bgImage); 355 345 psFree(bgImage); 356 346 357 358 347 #ifdef TESTING 359 348 { 349 pmHDU *hdu = pmHDUFromCell(readout->parent); 360 350 psString name = NULL; 361 351 psStringAppend(&name, "fake_%03d.fits", numInput); 362 352 psFits *fits = psFitsOpen(name, "w"); 363 353 psFree(name); 364 psFitsWriteImage(fits, NULL, fake->image, 0, NULL);354 psFitsWriteImage(fits, hdu->header, fake->image, 0, NULL); 365 355 psFitsClose(fits); 366 356 } 367 357 { 358 pmHDU *hdu = pmHDUFromCell(readout->parent); 368 359 psString name = NULL; 369 360 psStringAppend(&name, "real_%03d.fits", numInput); 370 361 psFits *fits = psFitsOpen(name, "w"); 371 362 psFree(name); 372 psFitsWriteImage(fits, NULL, readout->image, 0, NULL);363 psFitsWriteImage(fits, hdu->header, readout->image, 0, NULL); 373 364 psFitsClose(fits); 374 365 } … … 410 401 #ifdef TESTING 411 402 { 403 pmHDU *hdu = pmHDUFromCell(readout->parent); 412 404 psString name = NULL; 413 405 psStringAppend(&name, "conv_%03d.fits", numInput); 414 406 psFits *fits = psFitsOpen(name, "w"); 415 407 psFree(name); 416 psFitsWriteImage(fits, NULL, output->image, 0, NULL);408 psFitsWriteImage(fits, hdu->header, output->image, 0, NULL); 417 409 psFitsClose(fits); 418 410 } 419 411 { 412 pmHDU *hdu = pmHDUFromCell(readout->parent); 420 413 psString name = NULL; 421 414 psStringAppend(&name, "diff_%03d.fits", numInput); … … 423 416 psFree(name); 424 417 psBinaryOp(fake->image, output->image, "-", fake->image); 425 psFitsWriteImage(fits, NULL, fake->image, 0, NULL);418 psFitsWriteImage(fits, hdu->header, fake->image, 0, NULL); 426 419 psFitsClose(fits); 427 420 } … … 548 541 } 549 542 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 550 553 // Renormalise the variances if desired 551 554 if (renorm) { … … 580 583 psFree(bg); 581 584 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 582 655 psFree(output); 583 656
Note:
See TracChangeset
for help on using the changeset viewer.
