Changeset 34368
- Timestamp:
- Aug 30, 2012, 6:10:52 AM (14 years ago)
- Location:
- branches/eam_branches/ipp-20120805/psphot/src
- Files:
-
- 4 edited
-
psphot.h (modified) (2 diffs)
-
psphotDeblendSatstars.c (modified) (4 diffs)
-
psphotReadout.c (modified) (2 diffs)
-
psphotVisual.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20120805/psphot/src/psphot.h
r34360 r34368 281 281 bool psphotVisualShowSatStars (psMetadata *recipe, pmPSF *psf, psArray *sources); 282 282 bool psphotVisualShowPSFModel (pmReadout *readout, pmPSF *psf); 283 bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal );283 bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal, pmSourceMode showmode); 284 284 bool psphotVisualPlotRadialProfiles (psMetadata *recipe, psArray *sources, pmSourceMode showmode); 285 285 bool psphotVisualShowFlags (psArray *sources); … … 295 295 bool psphotVisualClose(void); 296 296 297 int psphotKapaChannel (int channel); 298 void plotline (int myKapa, Graphdata *graphdata, float x0, float y0, float x1, float y1); 299 300 297 301 bool psphotPetrosian (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal); 298 302 bool psphotPetrosianRadialBins (pmSource *source, float radiusMax, float skynoise); -
branches/eam_branches/ipp-20120805/psphot/src/psphotDeblendSatstars.c
r34360 r34368 1 1 # include "psphotInternal.h" 2 3 typedef struct { 4 float min; 5 float max; 6 float lower20; 7 float upper20; 8 int Npts; 9 } QuickStats; 10 11 bool psImageQuickStats (QuickStats *stats, psImage *image, psRegion region); 12 13 bool psphotTestRadialModel (pmSource *source, psVector **logRmodelOut, psVector **logFmodelOut, psVector *logFlux, psVector *logRad, float Rmax); 14 bool psphotTestRadialModelSub (pmSource *source, psVector *logRmodel, psVector *logFmodel, float Xo, float Yo, float Rmax, psImageMaskType maskVal); 15 bool psphotVisualRadialProfileSatstar (pmSource *source, psImageMaskType maskVal); 16 float InterpolateValues (float X0, float Y0, float X1, float Y1, float X); 17 bool psphotVisualScaleImage (int kapaFD, psImage *inImage, psImage *inMask, const char *name, float factor, int channel); 2 18 3 19 // for now, let's store the detections on the readout->analysis for each readout … … 17 33 18 34 bool psphotDeblendSatstarsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int fileIndex) { 35 36 int N; 37 pmSource *source; 38 bool status; 39 40 psTimerStart ("psphot.deblend.sat"); 41 42 // find the currently selected readout 43 pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, fileIndex); // File of interest 44 psAssert (file, "missing file?"); 45 46 pmReadout *readout = pmFPAviewThisReadout(view, file->fpa); 47 psAssert (readout, "missing readout?"); 48 49 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 50 psAssert (detections, "missing detections?"); 51 52 psArray *sources = detections->newSources; 53 psAssert (sources, "missing sources?"); 54 55 if (!sources->n) { 56 psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping satstar blend"); 57 return true; 58 } 59 60 // select the appropriate recipe information 61 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE); 62 psAssert (recipe, "missing recipe?"); 63 64 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 65 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 66 assert (maskVal); 67 68 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 69 psImageMaskType maskSat = psMetadataLookupImageMask(&status, recipe, "MASK.SAT"); // Mask value for bad pixels 70 assert (maskSat); 71 72 float SATURATION = NAN; 73 { 74 // XXX do we need to set this differently from the value used to mark saturated pixels? 75 pmCell *cell = readout->parent; 76 77 // do not completely trust the values in the header... 78 float CELL_SATURATION = psMetadataLookupF32 (&status, cell->concepts, "CELL.SATURATION"); 79 float MIN_SATURATION = psMetadataLookupF32 (&status, recipe, "DEBLEND_MIN_SATURATION"); 80 if (!status || !isfinite(MIN_SATURATION)) { 81 MIN_SATURATION = 40000.0; 82 } 83 if (!isfinite(CELL_SATURATION)) { 84 SATURATION = MIN_SATURATION; 85 } else { 86 SATURATION = PS_MAX(MIN_SATURATION, CELL_SATURATION); 87 } 88 } 89 90 // source analysis is done in peak order (brightest first) 91 // we use an index for this so the spatial sorting is kept 92 psVector *SN = psVectorAlloc (sources->n, PS_DATA_F32); 93 for (int i = 0; i < SN->n; i++) { 94 source = sources->data[i]; 95 SN->data.F32[i] = source->moments->SN; 96 } 97 psVector *index = psVectorSortIndex (NULL, SN); 98 // this results in an index of increasing SN 99 100 // psphotVisualPlotRadialProfiles (recipe, sources, PM_SOURCE_MODE_SATSTAR); 101 102 int BIG_RADIUS = 250; 103 int BIG_SIGMA = BIG_RADIUS / 4.0; 104 105 int display = psphotKapaChannel (1); 106 psphotVisualScaleImage (display, (psImage *) source->pixels->parent, NULL, "image", 1.0, 0); 107 108 // examine sources in decreasing SN order 109 for (int i = sources->n - 1; i >= 0; i--) { 110 N = index->data.U32[i]; 111 source = sources->data[N]; 112 113 bool isSat = source->mode & PM_SOURCE_MODE_SATSTAR; 114 115 // for fairly bright stars, check the pixels near the peak again 116 if (source->moments->Peak > 0.5*SATURATION) { 117 // pmSourceRoughClass does this analysis, but uses a small (5x5) window. 118 // here we use a larger window since stacks can have some funny features 119 psRegion inner; 120 QuickStats stats; 121 // grow out the search radius until we have lower20 < 0.1*SATURATION 122 for (int radius = 2; radius < 30; radius ++) { 123 inner = psRegionForSquare (source->peak->x, source->peak->y, radius); 124 inner = psRegionForImage (source->maskView, inner); 125 psImageQuickStats (&stats, readout->image, inner); 126 if ((stats.Npts > 1) && (stats.lower20 < 0.1*SATURATION)) break; 127 } 128 int Nsatpix = psImageCountPixelMask (source->maskView, inner, maskSat); 129 // fprintf (stderr, "test object: %d,%d : %d vs %d : %f - %f - %f - %f\n", 130 // source->peak->x, source->peak->y, Nsatpix, stats.Npts, 131 // stats.min, stats.lower20, stats.upper20, stats.max); 132 if (Nsatpix > 1) isSat = true; 133 } 134 if (!isSat) continue; 135 136 // For saturated stars, choose a much larger box NOTE this is slightly sleazy, but 137 // only slightly: pmSourceRedefinePixels uses the readout to pass the pointers to 138 // the parent image data. I guess the API could be simplified: we could recover 139 // this from the source in the function 140 141 pmReadout tmpReadout; 142 tmpReadout.image = (psImage *)source->pixels->parent; 143 tmpReadout.mask = (psImage *)source->maskView->parent; 144 tmpReadout.variance = (psImage *)source->variance->parent; 145 146 // re-allocate image, weight, mask arrays for each peak with box big enough to fit BIG_RADIUS 147 pmSourceRedefinePixels (source, &tmpReadout, source->peak->x, source->peak->y, BIG_RADIUS + 2); 148 149 psTrace ("psphot", 4, "retrying moments for %d, %d\n", source->peak->x, source->peak->y); 150 status = pmSourceMoments (source, BIG_RADIUS, BIG_SIGMA, 0.0, 5.0, maskVal); 151 source->mode |= PM_SOURCE_MODE_BIG_RADIUS; 152 153 // XXX visualize, model, and subtract 154 if (!psphotVisualRadialProfileSatstar (source, maskVal)) { 155 break; 156 } 157 158 // generate radial profile, store on the source structure 159 } 160 // show the image after object have been subtracted 161 psphotVisualScaleImage (display, (psImage *) source->pixels->parent, NULL, "image", 1.0, 1); 162 163 psFree (SN); 164 psFree (index); 165 166 psLogMsg ("psphot", PS_LOG_INFO, "deblend satstar: %f sec\n", psTimerMark ("psphot.deblend.sat")); 167 return true; 168 } 169 170 bool psphotDeblendSatstarsReadoutOld (pmConfig *config, const pmFPAview *view, const char *filerule, int fileIndex) { 19 171 20 172 int N; … … 78 230 psVector *index = psVectorSortIndex (NULL, SN); 79 231 // this results in an index of increasing SN 80 81 psphotVisualPlotRadialProfiles (recipe, sources, PM_SOURCE_MODE_SATSTAR);82 232 83 233 // examine sources in decreasing SN order … … 222 372 } 223 373 224 bool psphotDeblendSatstarsReadoutOld (pmConfig *config, const pmFPAview *view, const char *filerule, int fileIndex) { 225 226 int N; 227 pmSource *source; 228 bool status; 229 230 psTimerStart ("psphot.deblend.sat"); 231 232 int Nblend = 0; 233 float SAT_MIN_RADIUS = 5.0; 234 235 // find the currently selected readout 236 pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, fileIndex); // File of interest 237 psAssert (file, "missing file?"); 238 239 pmReadout *readout = pmFPAviewThisReadout(view, file->fpa); 240 psAssert (readout, "missing readout?"); 241 242 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 243 psAssert (detections, "missing detections?"); 244 245 psArray *sources = detections->newSources; 246 psAssert (sources, "missing sources?"); 247 248 if (!sources->n) { 249 psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping satstar blend"); 250 return true; 251 } 252 253 // select the appropriate recipe information 254 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE); 255 psAssert (recipe, "missing recipe?"); 256 257 pmCell *cell = readout->parent; 258 259 float SATURATION = NAN; 260 261 // do not completely trust the values in the header... 262 float CELL_SATURATION = psMetadataLookupF32 (&status, cell->concepts, "CELL.SATURATION"); 263 float MIN_SATURATION = psMetadataLookupF32 (&status, recipe, "DEBLEND_MIN_SATURATION"); 264 if (!status || !isfinite(MIN_SATURATION)) { 265 MIN_SATURATION = 40000.0; 266 } 267 if (!isfinite(CELL_SATURATION)) { 268 SATURATION = MIN_SATURATION; 374 static bool skipDisplay = false; 375 bool psphotVisualRadialProfileSatstar (pmSource *source, psImageMaskType maskVal) { 376 377 int kapaImage = -1; 378 int kapaGraph = -1; 379 Graphdata graphdata; 380 381 if (!pmVisualTestLevel("psphot.satstar", 3)) { 382 skipDisplay = true; 383 } 384 385 float Rmax = 320.0; 386 387 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 388 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 389 390 int nPts = source->pixels->numRows * source->pixels->numCols; 391 psVector *rg = psVectorAllocEmpty (nPts, PS_TYPE_F32); 392 psVector *Rg = psVectorAllocEmpty (nPts, PS_TYPE_F32); 393 psVector *fg = psVectorAllocEmpty (nPts, PS_TYPE_F32); 394 psVector *Fg = psVectorAllocEmpty (nPts, PS_TYPE_F32); 395 psVector *rb = psVectorAllocEmpty (nPts, PS_TYPE_F32); 396 psVector *Rb = psVectorAllocEmpty (nPts, PS_TYPE_F32); 397 psVector *fb = psVectorAllocEmpty (nPts, PS_TYPE_F32); 398 399 int ng = 0; 400 int nb = 0; 401 402 float Xo = NAN; 403 float Yo = NAN; 404 405 if (source->modelPSF) { 406 Xo = source->modelPSF->params->data.F32[PM_PAR_XPOS] - source->pixels->col0; 407 Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS] - source->pixels->row0; 269 408 } else { 270 SATURATION = PS_MAX(MIN_SATURATION, CELL_SATURATION); 271 } 272 float SAT_TEST_LEVEL = 0.5*SATURATION; 273 274 // we need sources spatially-sorted to find overlaps 275 sources = psArraySort (sources, pmSourceSortByY); 276 277 // source analysis is done in peak order (brightest first) 278 // we use an index for this so the spatial sorting is kept 279 psVector *SN = psVectorAlloc (sources->n, PS_DATA_F32); 280 for (int i = 0; i < SN->n; i++) { 281 source = sources->data[i]; 282 SN->data.F32[i] = source->peak->rawFlux; 283 } 284 psVector *index = psVectorSortIndex (NULL, SN); 285 // this results in an index of increasing SN 286 287 // examine sources in decreasing SN order 288 for (int i = sources->n - 1; i >= 0; i--) { 289 N = index->data.U32[i]; 290 source = sources->data[N]; 291 292 // XXX filter? if (source->mode & PM_SOURCE_MODE_SATSTAR) continue; 293 if (source->mode & PM_SOURCE_MODE_BLEND) continue; 294 if (source->peak->rawFlux < SAT_TEST_LEVEL) continue; 295 296 // save these for reference below 297 int xPeak = source->peak->x; 298 int yPeak = source->peak->y; 299 300 // generate a basic contour (set of x,y coordinates at-or-below flux level) 301 psArray *contour = pmSourceContour (source->pixels, xPeak, yPeak, SAT_TEST_LEVEL); 302 if (contour == NULL) continue; 303 304 // contour consists of a set of X,Y coords giving the boundary 305 psVector *xVec = contour->data[0]; 306 psVector *yVec = contour->data[1]; 307 if (xVec->n < 5) { 308 psFree(contour); 309 continue; 310 } 311 312 // find the center of the contour (let's just use mid[x,y]) 313 int xMin = xVec->data.F32[0]; 314 int xMax = xVec->data.F32[0]; 315 int yMin = yVec->data.F32[0]; 316 int yMax = yVec->data.F32[0]; 317 for (int j = 0; j < xVec->n; j++) { 318 xMin = PS_MIN (xMin, xVec->data.F32[j]); 319 xMax = PS_MAX (xMax, xVec->data.F32[j]); 320 yMin = PS_MIN (yMin, yVec->data.F32[j]); 321 yMax = PS_MAX (yMax, yVec->data.F32[j]); 322 } 323 int xCenter = 0.5*(xMin + xMax); 324 int yCenter = 0.5*(yMin + yMax); 325 psFree (contour); 326 327 psAssert (xCenter >= source->pixels->col0, "invalid shift in object center"); 328 psAssert (xCenter < source->pixels->col0 + source->pixels->numCols, "invalid shift in object center"); 329 psAssert (yCenter >= source->pixels->row0, "invalid shift in object center"); 330 psAssert (yCenter < source->pixels->row0 + source->pixels->numRows, "invalid shift in object center"); 331 332 // reset the peak for this source to the value of the center pixel 333 source->peak->x = xCenter; 334 source->peak->y = yCenter; 335 source->peak->xf = xCenter; 336 source->peak->yf = yCenter; 409 Xo = source->moments->Mx - source->pixels->col0; 410 Yo = source->moments->My - source->pixels->row0; 411 } 412 413 for (int iy = 0; iy < source->pixels->numRows; iy++) { 414 for (int ix = 0; ix < source->pixels->numCols; ix++) { 415 if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) { 416 rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ; 417 // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ; 418 Rb->data.F32[nb] = log10(rb->data.F32[nb]); 419 fb->data.F32[nb] = log10(source->pixels->data.F32[iy][ix]); 420 nb++; 421 } else { 422 rg->data.F32[ng] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ; 423 // rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ; 424 Rg->data.F32[ng] = log10(rg->data.F32[ng]); 425 Fg->data.F32[ng] = source->pixels->data.F32[iy][ix]; 426 fg->data.F32[ng] = log10(Fg->data.F32[ng]); 427 ng++; 428 } 429 } 430 } 431 rg->n = ng; 432 Rg->n = ng; 433 fg->n = ng; 434 Fg->n = ng; 435 rb->n = nb; 436 Rb->n = nb; 437 fb->n = nb; 438 439 if (!skipDisplay) { 440 kapaImage = psphotKapaChannel (1); 441 if (kapaImage == -1) return false; 442 443 kapaGraph = psphotKapaChannel (2); 444 if (kapaGraph == -1) return false; 445 446 KapaSection section; // put the positive profile in one and the residuals in another? 447 448 // first section : mag vs CR nSigma 449 section.dx = 1.0; 450 section.dy = 0.5; 451 section.x = 0.0; 452 section.y = 0.0; 453 section.bg = -1; 454 section.name = NULL; 455 psStringAppend (§ion.name, "linlog"); 456 KapaSetSection (kapaGraph, §ion); 457 psFree (section.name); 458 459 // first section : mag vs CR nSigma 460 section.dx = 1.0; 461 section.dy = 0.5; 462 section.x = 0.0; 463 section.y = 0.5; 464 section.bg = -1; 465 section.name = NULL; 466 psStringAppend (§ion.name, "loglog"); 467 KapaSetSection (kapaGraph, §ion); 468 psFree (section.name); 469 470 KapaInitGraph (&graphdata); 471 472 // ** linlog ** 473 KapaSelectSection (kapaGraph, "linlog"); 474 475 // examine sources to set data range 476 graphdata.xmin = -0.05; 477 graphdata.xmax = Rmax + 0.05; 478 graphdata.ymin = -0.05; 479 graphdata.ymax = +8.05; 480 KapaSetLimits (kapaGraph, &graphdata); 481 482 KapaSetFont (kapaGraph, "helvetica", 14); 483 KapaBox (kapaGraph, &graphdata); 484 KapaSendLabel (kapaGraph, "radius (pixels)", KAPA_LABEL_XM); 485 KapaSendLabel (kapaGraph, "log flux (counts)", KAPA_LABEL_YM); 486 487 graphdata.color = KapaColorByName ("black"); 488 graphdata.ptype = 2; 489 graphdata.size = 0.5; 490 graphdata.style = 2; 491 KapaPrepPlot (kapaGraph, ng, &graphdata); 492 KapaPlotVector (kapaGraph, ng, rg->data.F32, "x"); 493 KapaPlotVector (kapaGraph, ng, fg->data.F32, "y"); 494 495 graphdata.color = KapaColorByName ("red"); 496 graphdata.ptype = 0; 497 graphdata.size = 0.3; 498 graphdata.style = 2; 499 KapaPrepPlot (kapaGraph, nb, &graphdata); 500 KapaPlotVector (kapaGraph, nb, rb->data.F32, "x"); 501 KapaPlotVector (kapaGraph, nb, fb->data.F32, "y"); 502 503 // ** loglog ** 504 KapaSelectSection (kapaGraph, "loglog"); 505 506 // examine sources to set data range 507 graphdata.xmin = -1.51; 508 graphdata.xmax = log10(Rmax) + 0.02; 509 graphdata.ymin = -5.05; 510 graphdata.ymax = +8.05; 511 graphdata.color = KapaColorByName ("black"); 512 KapaSetLimits (kapaGraph, &graphdata); 513 514 KapaSetFont (kapaGraph, "helvetica", 14); 515 KapaBox (kapaGraph, &graphdata); 516 KapaSendLabel (kapaGraph, "log radius (pixels)", KAPA_LABEL_XM); 517 KapaSendLabel (kapaGraph, "log flux (counts)", KAPA_LABEL_YM); 518 519 graphdata.color = KapaColorByName ("black"); 520 graphdata.ptype = 2; 521 graphdata.size = 0.5; 522 graphdata.style = 2; 523 KapaPrepPlot (kapaGraph, ng, &graphdata); 524 KapaPlotVector (kapaGraph, ng, Rg->data.F32, "x"); 525 KapaPlotVector (kapaGraph, ng, fg->data.F32, "y"); 526 527 graphdata.color = KapaColorByName ("red"); 528 graphdata.ptype = 0; 529 graphdata.size = 0.3; 530 graphdata.style = 2; 531 KapaPrepPlot (kapaGraph, nb, &graphdata); 532 KapaPlotVector (kapaGraph, nb, Rb->data.F32, "x"); 533 KapaPlotVector (kapaGraph, nb, fb->data.F32, "y"); 534 } 535 536 // measure the radial profile 537 psVector *logFmodel = NULL; 538 psVector *logRmodel = NULL; 539 psphotTestRadialModel (source, &logRmodel, &logFmodel, Rg, Fg, Rmax); 540 541 if (!skipDisplay) { 542 graphdata.color = KapaColorByName ("red"); 543 graphdata.ptype = 2; 544 graphdata.size = 1.0; 545 graphdata.style = 2; 546 KapaPrepPlot (kapaGraph, logRmodel->n, &graphdata); 547 KapaPlotVector (kapaGraph, logRmodel->n, logRmodel->data.F32, "x"); 548 KapaPlotVector (kapaGraph, logRmodel->n, logFmodel->data.F32, "y"); 549 } 550 551 // subtract the model from the images 552 psphotTestRadialModelSub (source, logRmodel, logFmodel, Xo, Yo, Rmax, maskVal); 553 554 psFree (logRmodel); 555 psFree (logFmodel); 556 557 if (!skipDisplay && source->modelPSF) { 558 // generate model profiles (major and minor axis): 559 // create a model with theta = 0.0 so major and minor axes are equiv to x and y: 560 psEllipseShape rawShape, rotShape; 561 562 rawShape.sx = source->modelPSF->params->data.F32[PM_PAR_SXX] / M_SQRT2; 563 rawShape.sy = source->modelPSF->params->data.F32[PM_PAR_SYY] / M_SQRT2; 564 rawShape.sxy = source->modelPSF->params->data.F32[PM_PAR_SXY]; 565 566 psEllipseAxes axes = psEllipseShapeToAxes (rawShape, 20.0); 567 568 axes.theta = 0.0; 569 570 rotShape = psEllipseAxesToShape (axes); 571 572 psVector *params = psVectorAlloc(source->modelPSF->params->n, PS_TYPE_F32); 573 for (int i = 0; i < source->modelPSF->params->n; i++) { 574 params->data.F32[i] = source->modelPSF->params->data.F32[i]; 575 } 576 params->data.F32[PM_PAR_SXX] = rotShape.sx * M_SQRT2; 577 params->data.F32[PM_PAR_SYY] = rotShape.sy * M_SQRT2; 578 params->data.F32[PM_PAR_SXY] = rotShape.sxy; 579 params->data.F32[PM_PAR_XPOS] = 0.0; 580 params->data.F32[PM_PAR_YPOS] = 0.0; 581 582 psVector *rmod = psVectorAlloc(Rmax*10, PS_TYPE_F32); 583 psVector *fmaj = psVectorAlloc(Rmax*10, PS_TYPE_F32); 584 psVector *fmin = psVectorAlloc(Rmax*10, PS_TYPE_F32); 585 586 psVector *coord = psVectorAlloc(2, PS_TYPE_F32); 587 588 float r = 0.0; 589 for (int i = 0; i < rmod->n; i++) { 590 r = i*0.1; 591 rmod->data.F32[i] = r; 592 593 coord->data.F32[1] = r; 594 coord->data.F32[0] = 0.0; 595 fmaj->data.F32[i] = log10(source->modelPSF->modelFunc (NULL, params, coord)); 596 597 coord->data.F32[0] = r; 598 coord->data.F32[1] = 0.0; 599 fmin->data.F32[i] = log10(source->modelPSF->modelFunc (NULL, params, coord)); 600 } 601 psFree (coord); 602 psFree (params); 603 604 float FWHM_MAJOR = 2.0*source->modelPSF->modelRadius (source->modelPSF->params, 0.5*source->modelPSF->params->data.F32[PM_PAR_I0]); 605 float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major); 606 if (FWHM_MAJOR < FWHM_MINOR) PS_SWAP (FWHM_MAJOR, FWHM_MINOR); 607 608 psEllipseMoments emoments; 609 emoments.x2 = source->moments->Mxx; 610 emoments.xy = source->moments->Mxy; 611 emoments.y2 = source->moments->Myy; 612 axes = psEllipseMomentsToAxes (emoments, 20.0); 613 float MOMENTS_MAJOR = 2.355*axes.major; 614 float MOMENTS_MINOR = 2.355*axes.minor; 615 616 float logHM = log10(0.5*source->modelPSF->params->data.F32[PM_PAR_I0]); 617 618 // reset source Add/Sub state to recorded 619 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 620 621 // ** linlog ** 622 KapaSelectSection (kapaGraph, "linlog"); 623 KapaGetGraphData (kapaGraph, &graphdata); 624 graphdata.color = KapaColorByName ("blue"); 625 graphdata.ptype = 0; 626 graphdata.size = 0.0; 627 graphdata.style = 0; 628 KapaPrepPlot (kapaGraph, rmod->n, &graphdata); 629 KapaPlotVector (kapaGraph, rmod->n, rmod->data.F32, "x"); 630 KapaPlotVector (kapaGraph, rmod->n, fmin->data.F32, "y"); 631 plotline (kapaGraph, &graphdata, graphdata.xmin, logHM, graphdata.xmax, logHM); 632 plotline (kapaGraph, &graphdata, 0.5*FWHM_MINOR, graphdata.ymin, 0.5*FWHM_MINOR, graphdata.ymax); 633 graphdata.ltype = 1; 634 plotline (kapaGraph, &graphdata, 0.5*MOMENTS_MINOR, graphdata.ymin, 0.5*MOMENTS_MINOR, graphdata.ymax); 635 graphdata.ltype = 0; 337 636 338 // temporary array for overlapping objects we find 339 psArray *overlap = psArrayAllocEmpty (100); 340 341 // search backwards for overlapping sources 342 for (int j = N - 1; j >= 0; j--) { 343 pmSource *testSource = sources->data[j]; 344 if (testSource->peak->x < source->pixels->col0) continue; 345 if (testSource->peak->x >= source->pixels->col0 + source->pixels->numCols) continue; 346 if (testSource->peak->y < source->pixels->row0) break; 347 if (testSource->peak->y >= source->pixels->row0 + source->pixels->numRows) { 348 fprintf (stderr, "warning: invalid condition\n"); 349 continue; 350 } 351 psArrayAdd (overlap, 100, testSource); 352 } 353 354 // search forwards for overlapping sources 355 for (int j = N + 1; j < sources->n; j++) { 356 pmSource *testSource = sources->data[j]; 357 if (testSource->peak->x < source->pixels->col0) continue; 358 if (testSource->peak->x >= source->pixels->col0 + source->pixels->numCols) continue; 359 if (testSource->peak->y < source->pixels->row0) { 360 fprintf (stderr, "warning: invalid condition\n"); 361 continue; 362 } 363 if (testSource->peak->y >= source->pixels->row0 + source->pixels->numRows) break; 364 psArrayAdd (overlap, 100, testSource); 365 } 366 367 if (overlap->n == 0) { 368 psFree (overlap); 369 continue; 370 } 371 372 // now find the contour which is at 0.5*SAT_TEST_LEVEL (xPeak, yPeak is valid high pixel) 373 contour = pmSourceContour (source->pixels, xPeak, yPeak, 0.5*SAT_TEST_LEVEL); 374 if (contour == NULL) { 375 psFree (overlap); 376 continue; 377 } 637 graphdata.color = KapaColorByName ("green"); 638 graphdata.ptype = 0; 639 graphdata.size = 0.0; 640 graphdata.style = 0; 641 KapaPrepPlot (kapaGraph, rmod->n, &graphdata); 642 KapaPlotVector (kapaGraph, rmod->n, rmod->data.F32, "x"); 643 KapaPlotVector (kapaGraph, rmod->n, fmaj->data.F32, "y"); 644 plotline (kapaGraph, &graphdata, 0.5*FWHM_MAJOR, graphdata.ymin, 0.5*FWHM_MAJOR, graphdata.ymax); 645 graphdata.ltype = 1; 646 plotline (kapaGraph, &graphdata, 0.5*MOMENTS_MAJOR, graphdata.ymin, 0.5*MOMENTS_MAJOR, graphdata.ymax); 647 graphdata.ltype = 0; 378 648 379 // any peaks within this contour should be dropped (mark as blend, drop after loop is done) 380 // also drop any peaks which are too close to this peak 381 psVector *xv = contour->data[0]; 382 psVector *yv = contour->data[1]; 383 for (int k = 0; k < overlap->n; k++) { 384 pmSource *testSource = overlap->data[k]; 385 float radius = hypot((testSource->peak->x - xCenter), (testSource->peak->y - yCenter)); 386 if (radius < SAT_MIN_RADIUS) { 387 testSource->mode |= PM_SOURCE_MODE_BLEND; 388 Nblend ++; 389 continue; 390 } 391 for (int j = 0; j < xv->n; j+=2) { 392 if (fabs(yv->data.F32[j] - testSource->peak->y) > 0.5) continue; 393 if (xv->data.F32[j+0] > testSource->peak->x) break; 394 if (xv->data.F32[j+1] < testSource->peak->x) break; 395 testSource->mode |= PM_SOURCE_MODE_BLEND; 396 Nblend ++; 397 j = xv->n; // skip rest of contour 398 } 399 } 400 psFree (overlap); 401 psFree (contour); 402 } 403 404 // drop the sources marked as BLEND 405 for (int i = 0; i < sources->n;) { 406 pmSource *source = sources->data[i]; 407 408 if (!(source->mode & PM_SOURCE_MODE_BLEND)) { 409 i++; 410 continue; 411 } 412 413 // shuffle the remaining sources forward 414 for (int j = i; j < sources->n - 1; j++) { 415 sources->data[j] = sources->data[j+1]; 416 } 417 psFree (source); 418 sources->n --; 419 } 420 421 psFree (SN); 422 psFree (index); 423 424 psLogMsg ("psphot", PS_LOG_INFO, "found %d satstar blend peaks, leaving %ld sources: %f sec\n", Nblend, sources->n, psTimerMark ("psphot.deblend.sat")); 649 for (int i = 0; i < rmod->n; i++) { 650 rmod->data.F32[i] = log10(rmod->data.F32[i]); 651 } 652 653 // ** loglog ** 654 KapaSelectSection (kapaGraph, "loglog"); 655 KapaGetGraphData (kapaGraph, &graphdata); 656 graphdata.color = KapaColorByName ("blue"); 657 graphdata.ptype = 0; 658 graphdata.size = 0.0; 659 graphdata.style = 0; 660 KapaPrepPlot (kapaGraph, rmod->n, &graphdata); 661 KapaPlotVector (kapaGraph, rmod->n, rmod->data.F32, "x"); 662 KapaPlotVector (kapaGraph, rmod->n, fmin->data.F32, "y"); 663 664 graphdata.color = KapaColorByName ("green"); 665 graphdata.ptype = 0; 666 graphdata.size = 0.0; 667 graphdata.style = 0; 668 KapaPrepPlot (kapaGraph, rmod->n, &graphdata); 669 KapaPlotVector (kapaGraph, rmod->n, rmod->data.F32, "x"); 670 KapaPlotVector (kapaGraph, rmod->n, fmaj->data.F32, "y"); 671 672 psFree (rmod); 673 psFree (fmin); 674 psFree (fmaj); 675 } 676 677 if (!skipDisplay) { 678 KiiCenter (kapaImage, source->peak->xf, source->peak->yf, 1); 679 psphotVisualScaleImage (kapaImage, (psImage *) source->pixels->parent, NULL, "image", 1.0, 1); 680 KiiOverlay overlay; 681 overlay.x = source->peak->xf; 682 overlay.y = source->peak->yf; 683 overlay.dx = 5; 684 overlay.dy = 5; 685 overlay.angle = 0.0; 686 overlay.type = KiiOverlayTypeByName ("circle"); 687 KiiLoadOverlay (kapaImage, &overlay, 1, "red"); 688 overlay.x = source->moments->Mx; 689 overlay.y = source->moments->My; 690 overlay.dx = 8; 691 overlay.dy = 8; 692 overlay.angle = 0.0; 693 overlay.type = KiiOverlayTypeByName ("circle"); 694 KiiLoadOverlay (kapaImage, &overlay, 1, "blue"); 695 } 696 697 psFree (rg); 698 psFree (Rg); 699 psFree (fg); 700 psFree (Fg); 701 psFree (rb); 702 psFree (Rb); 703 psFree (fb); 704 705 if (skipDisplay) return true; 706 707 // pause and wait for user input: 708 // continue, save (provide name), ?? 709 char key[10]; 710 fprintf (stdout, "[q]uit satstar? [e]rase and continue? [o]verplot and continue? [s]kip rest of stars? : "); 711 if (!fgets(key, 8, stdin)) { 712 psWarning("Unable to read option"); 713 } 714 if (key[0] == 'e') { 715 KapaClearPlots (kapaGraph); 716 } 717 if (key[0] == 'q') { 718 return false; 719 } 720 if (key[0] == 's') { 721 skipDisplay = true; 722 } 425 723 return true; 426 724 } 725 726 bool psphotTestRadialModel (pmSource *source, psVector **logRmodelOut, psVector **logFmodelOut, psVector *logRad, psVector *logFlux, float Rmax) { 727 728 // we have log(radius) & log(flux). find the median flux in log radial bins 729 730 float logRmax = log10(Rmax); 731 float logRdel = 0.1; 732 733 psVector *logRmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32); 734 psVector *logFmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32); 735 736 pmSourceRadialProfileSortPair (logRad, logFlux); 737 738 psStats *fluxStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 739 psVector *flux = psVectorAllocEmpty (100, PS_TYPE_F32); 740 741 int bin = 0; 742 for (int i = 0; i < logRmodel->n; i++) { 743 744 // bin (i) has log radius range (i*logRdel : (i+1)*logRdel) 745 float lRmin = logRdel*(i + 0); 746 float lRmax = logRdel*(i + 1); 747 748 // reset the flux vector 749 flux->n = 0; 750 psStatsInit (fluxStats); 751 752 while (logRad->data.F32[bin] < lRmax) { 753 if (isfinite(logFlux->data.F32[bin])) { 754 psVectorAppend (flux, logFlux->data.F32[bin]); 755 } 756 bin ++; 757 } 758 759 // we have the set of fluxes for this bin; find the median values 760 761 float Rmin = pow(10.0, lRmin); 762 float Rmax = pow(10.0, lRmax); 763 764 float Rmean = (2.0/3.0) * (pow(Rmax, 3.0) - pow(Rmin, 3.0)) / (PS_SQR(Rmax) - PS_SQR(Rmin)); 765 logRmodel->data.F32[i] = log10(Rmean); 766 767 float Area = M_PI * (PS_SQR(Rmax) - PS_SQR(Rmin)); 768 if (flux->n < 0.25*Area) { 769 logFmodel->data.F32[i] = NAN; 770 continue; 771 } 772 773 psVectorStats (fluxStats, flux, NULL, NULL, 0); 774 if (fluxStats->robustMedian > 0.0) { 775 logFmodel->data.F32[i] = log10(fluxStats->robustMedian); 776 } else { 777 logFmodel->data.F32[i] = -3.0; 778 } 779 // fprintf (stderr, "R: %f, F: %f +/- %f\n", Rmean, fluxStats->robustMedian, fluxStats->robustStdev); 780 } 781 782 // now how do i use this to subtract a model?? 783 *logRmodelOut = logRmodel; 784 *logFmodelOut = logFmodel; 785 786 // need to free stuff 787 psFree (fluxStats); 788 psFree (flux); 789 790 return true; 791 } 792 793 bool psphotTestRadialModelSub (pmSource *source, psVector *logRmodel, psVector *logFmodel, float Xo, float Yo, float Rmax, psImageMaskType maskVal) { 794 795 int alt; 796 float logRdel = 0.1; 797 798 for (int iy = 0; iy < source->pixels->numRows; iy++) { 799 for (int ix = 0; ix < source->pixels->numCols; ix++) { 800 if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) continue; 801 802 float radius = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ; 803 float logR = log10(radius); 804 805 int bin = (int)(logR / logRdel); 806 807 // we are going to interpolate if possible, or extrapolate if necessary 808 if (bin >= logRmodel->n - 1) bin = logRmodel->n - 1; 809 if (bin < 0) bin = 0; 810 811 // interpolate to the current radial position 812 // XXX BIG HACK : skip nan bins for now 813 814 float logF0 = logFmodel->data.F32[bin]; 815 float logR0 = logRmodel->data.F32[bin]; 816 if (!isfinite(logF0)) continue; 817 818 // interpolate between closest two bins if possible, extrapolate on ends 819 if (logR < logR0) { 820 alt = (bin > 0) ? bin - 1 : bin + 1; 821 } else { 822 alt = (bin < logRmodel->n - 1) ? bin + 1 : bin - 1; 823 } 824 825 float logF1 = logFmodel->data.F32[alt]; 826 float logR1 = logRmodel->data.F32[alt]; 827 if (!isfinite(logF1)) continue; 828 829 // XXX use linear flux, not logFlux 830 float logF = InterpolateValues (logR0, logF0, logR1, logF1, logR); 831 float flux = pow (10.0, logF); 832 833 // float flux = InterpolateValues (logR0, logF0, logR1, logF1, logR); 834 source->pixels->data.F32[iy][ix] -= flux; 835 } 836 } 837 return true; 838 } 839 840 // only valid for F32 841 bool psImageQuickStats (QuickStats *stats, psImage *image, psRegion region) { 842 843 psAssert (image->type.type == PS_TYPE_F32, "unsupported image type"); 844 845 int Npix = (region.y1 - region.y0) * (region.x1 - region.x0); 846 psVector *tmp = psVectorAllocEmpty (Npix, PS_TYPE_F32); 847 848 int bin = 0; 849 for (int iy = region.y0; iy < region.y1; iy++) { 850 for (int ix = region.x0; ix < region.x1; ix++) { 851 if (!isfinite(image->data.F32[iy][ix])) continue; 852 tmp->data.F32[bin] = image->data.F32[iy][ix]; 853 bin ++; 854 } 855 } 856 tmp->n = bin; 857 858 if (bin < 1) { 859 stats->min = NAN; 860 stats->lower20 = NAN; 861 stats->upper20 = NAN; 862 stats->max = NAN; 863 stats->Npts = 0; 864 psFree (tmp); 865 return true; 866 } 867 868 869 psVectorSortInPlace (tmp); 870 871 int N20 = 0.2*tmp->n; 872 int N80 = 0.8*tmp->n; 873 int Nmax = tmp->n - 1; 874 875 stats->min = tmp->data.F32[0]; 876 stats->lower20 = tmp->data.F32[N20]; 877 stats->upper20 = tmp->data.F32[N80]; 878 stats->max = tmp->data.F32[Nmax]; 879 stats->Npts = bin; 880 psFree (tmp); 881 882 return true; 883 } -
branches/eam_branches/ipp-20120805/psphot/src/psphotReadout.c
r34360 r34368 128 128 } 129 129 130 // find blended neighbors of very saturated stars (detections->newSources)131 if (!psphotDeblendSatstars (config, view, filerule)) {132 psError (PSPHOT_ERR_UNKNOWN, false, "failed on satstar deblend analysis");133 return psphotReadoutCleanup (config, view, filerule);134 }135 136 130 // mark blended peaks PS_SOURCE_BLEND (detections->newSources) 137 131 // XXX I've deactivated this because it was preventing galaxies close to stars from being … … 147 141 psError (PSPHOT_ERR_UNKNOWN, false, "failed to determine rough classifications"); 148 142 return psphotReadoutCleanup (config, view, filerule); 143 } 144 145 // find blended neighbors of very saturated stars (detections->newSources) 146 if (!psphotDeblendSatstars (config, view, filerule)) { 147 psError (PSPHOT_ERR_UNKNOWN, false, "failed on satstar deblend analysis"); 148 return psphotReadoutCleanup (config, view, filerule); 149 149 } 150 150 -
branches/eam_branches/ipp-20120805/psphot/src/psphotVisual.c
r34360 r34368 1273 1273 } 1274 1274 1275 staticvoid plotline (int myKapa, Graphdata *graphdata, float x0, float y0, float x1, float y1)1275 void plotline (int myKapa, Graphdata *graphdata, float x0, float y0, float x1, float y1) 1276 1276 { 1277 1277 float x[2], y[2]; … … 1285 1285 } 1286 1286 1287 bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal ) {1287 bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal, pmSourceMode showmode) { 1288 1288 1289 1289 Graphdata graphdata; 1290 1291 float Rmax = (showmode & PM_SOURCE_MODE_SATSTAR) ? 100.0 : 30.0; 1290 1292 1291 1293 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); … … 1310 1312 Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS] - source->pixels->row0; 1311 1313 } else { 1312 Xo = source->moments->Mx ;1313 Yo = source->moments->My ;1314 Xo = source->moments->Mx - source->pixels->col0; 1315 Yo = source->moments->My - source->pixels->row0; 1314 1316 } 1315 1317 1316 1318 for (int iy = 0; iy < source->pixels->numRows; iy++) { 1317 1319 for (int ix = 0; ix < source->pixels->numCols; ix++) { 1318 if ( source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {1320 if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) { 1319 1321 rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ; 1320 1322 // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ; … … 1339 1341 // examine sources to set data range 1340 1342 graphdata.xmin = -0.05; 1341 graphdata.xmax = +30.05;1343 graphdata.xmax = Rmax + 0.05; 1342 1344 graphdata.ymin = -0.05; 1343 1345 graphdata.ymax = +8.05; … … 1370 1372 // examine sources to set data range 1371 1373 graphdata.xmin = -1.51; 1372 graphdata.xmax = +1.51;1374 graphdata.xmax = log10(Rmax) + 0.02; 1373 1375 graphdata.ymin = -0.05; 1374 1376 graphdata.ymax = +8.05; … … 1422 1424 params->data.F32[PM_PAR_YPOS] = 0.0; 1423 1425 1424 psVector *rmod = psVectorAlloc( 300, PS_TYPE_F32);1425 psVector *fmaj = psVectorAlloc( 300, PS_TYPE_F32);1426 psVector *fmin = psVectorAlloc( 300, PS_TYPE_F32);1426 psVector *rmod = psVectorAlloc(Rmax*10, PS_TYPE_F32); 1427 psVector *fmaj = psVectorAlloc(Rmax*10, PS_TYPE_F32); 1428 psVector *fmin = psVectorAlloc(Rmax*10, PS_TYPE_F32); 1427 1429 1428 1430 psVector *coord = psVectorAlloc(2, PS_TYPE_F32); … … 1569 1571 if (!(source->mode & showmode)) continue; 1570 1572 1571 psphotVisualPlotRadialProfile (myKapa, source, maskVal); 1573 psphotVisualPlotRadialProfile (myKapa, source, maskVal, showmode); 1574 1575 if (pmVisualTestLevel("psphot.image", 1)) { 1576 int display = psphotKapaChannel (1); 1577 KiiCenter (display, source->peak->xf, source->peak->yf, 1); 1578 KiiOverlay overlay; 1579 overlay.x = source->peak->xf; 1580 overlay.y = source->peak->yf; 1581 overlay.dx = 5; 1582 overlay.dy = 5; 1583 overlay.angle = 0.0; 1584 overlay.type = KiiOverlayTypeByName ("circle"); 1585 KiiLoadOverlay (display, &overlay, 1, "red"); 1586 overlay.x = source->moments->Mx; 1587 overlay.y = source->moments->My; 1588 overlay.dx = 8; 1589 overlay.dy = 8; 1590 overlay.angle = 0.0; 1591 overlay.type = KiiOverlayTypeByName ("circle"); 1592 KiiLoadOverlay (display, &overlay, 1, "blue"); 1593 } 1572 1594 1573 1595 // pause and wait for user input:
Note:
See TracChangeset
for help on using the changeset viewer.
