15 Result of deblending a single parent Footprint.
21 Creates a result object for the given parent Footprint 'fp'.
24 peaks: if specified, the list of peaks to use; default is
31 for pki,pk
in enumerate(peaks):
35 self.peaks.append(pkres)
44 Result of deblending a single Peak within a parent Footprint.
46 There is one of these objects for each Peak in the Footprint.
119 return ((
'Per-peak deblend result: outOfBounds: %s, ' +
120 'deblendedAsPsf: %s') %
134 Return a HeavyFootprint containing the flux apportioned to
137 'strayFlux': include stray flux also?
146 self.strayFlux.normalize()
147 heavy = afwDet.mergeHeavyFootprintsF(heavy, self.
strayFlux)
165 self.
origTemplate = t.getImage().Factory(t.getImage(),
True)
206 def deblend(footprint, maskedImage, psf, psffwhm,
211 medianSmoothTemplate=
True,
212 medianFilterHalfsize=2,
213 monotonicTemplate=
True,
214 weightTemplates=
False,
215 log=
None, verbose=
False,
219 assignStrayFlux=
True,
220 strayFluxToPointSources=
'necessary',
221 strayFluxAssignment=
'r-to-peak',
222 rampFluxAtEdge=
False,
225 getTemplateSum=
False,
226 clipStrayFluxFraction=0.001,
227 clipFootprintToNonzero=
True,
230 Deblend a single ``footprint`` in a ``maskedImage``.
232 Each ``Peak`` in the ``Footprint`` will produce a deblended child.
234 psfChisqCut1, psfChisqCut2: used when deciding whether a given
235 peak looks like a point source. We build a small local model of
236 background + peak + neighboring peaks. These are the
237 chi-squared-per-degree-of-freedom cuts (1=without and 2=with terms
238 allowing the peak position to move); larger values will result in
239 more peaks being classified as PSFs.
241 psfChisqCut2b: if the with-decenter fit is accepted, we then
242 apply the computed dx,dy to the source position and re-fit without
243 decentering. The model is accepted if its chi-squared-per-DOF is
244 less than this value.
246 maxNumberOfPeaks: if positive, only deblend the brightest
247 maxNumberOfPeaks peaks in the parent
251 butils = deb.BaselineUtilsF
253 validStrayPtSrc = [
'never',
'necessary',
'always']
254 validStrayAssign = [
'r-to-peak',
'r-to-footprint',
'nearest-footprint']
255 if not strayFluxToPointSources
in validStrayPtSrc:
256 raise ValueError(((
'strayFluxToPointSources: value \"%s\" not in the '
257 +
'set of allowed values: ')
258 % strayFluxToPointSources) + str(validStrayPtSrc))
259 if not strayFluxAssignment
in validStrayAssign:
260 raise ValueError(((
'strayFluxAssignment: value \"%s\" not in the '
261 +
'set of allowed values: ')
262 % strayFluxAssignment) + str(validStrayAssign))
267 component =
'meas_deblender.baseline'
271 pexLogging.Trace.setVerbosity(component, -pexLogging.Log.DEBUG)
273 img = maskedImage.getImage()
274 varimg = maskedImage.getVariance()
275 mask = maskedImage.getMask()
279 peaks = fp.getPeaks()
280 if maxNumberOfPeaks > 0:
281 peaks = peaks[:maxNumberOfPeaks]
286 if not imbb.contains(bb):
287 raise ValueError((
'Footprint bounding-box %s extends outside image '
288 +
'bounding-box %s') % (str(bb), str(imbb)))
289 W,H = bb.getWidth(), bb.getHeight()
290 x0,y0 = bb.getMinX(), bb.getMinY()
291 x1,y1 = bb.getMaxX(), bb.getMaxY()
297 sigma1 = math.sqrt(stats.getValue(afwMath.MEDIAN))
298 log.logdebug(
'Estimated sigma1 = %f' % sigma1)
301 for nm
in [
'SYMM_1SIG',
'SYMM_3SIG',
'MONOTONIC_1SIG']:
302 mask.addMaskPlane(nm)
309 _fitPsfs(fp, peaks, res, log, psf, psffwhm, img, varimg,
310 psfChisqCut1, psfChisqCut2, psfChisqCut2b,
311 tinyFootprintSize=tinyFootprintSize)
314 log.logdebug((
'Creating templates for footprint at x0,y0,W,H = ' +
315 '(%i,%i, %i,%i)') % (x0,y0,W,H))
316 for peaki,pkres
in enumerate(res.peaks):
317 log.logdebug(
'Deblending peak %i of %i' % (peaki, len(res.peaks)))
318 if pkres.skip
or pkres.deblendedAsPsf:
321 cx,cy = pk.getIx(), pk.getIy()
323 log.logdebug(
'Peak center is not inside image; skipping %i' %
325 pkres.setOutOfBounds()
327 log.logdebug(
'computing template for peak %i at (%i,%i)' %
329 S,patched = butils.buildSymmetricTemplate(
330 maskedImage, fp, pk, sigma1,
True, patchEdges)
333 t1, tfoot = S[0], S[1]
337 log.logdebug((
'Peak %i at (%i,%i): failed to build symmetric ' +
338 'template') % (pkres.pki, cx,cy))
339 pkres.setFailedSymmetricTemplate()
346 pkres.setOrigTemplate(t1, tfoot)
349 log.logdebug(
'Checking for significant flux at edge: sigma1=%g' % sigma1)
350 if (rampFluxAtEdge
and
351 butils.hasSignificantFluxAtEdge(t1.getImage(), tfoot, 3*sigma1)):
352 log.logdebug(
"Template %i has significant flux at edge: ramping" % pkres.pki)
354 log, psffwhm, t1, tfoot, fp, maskedImage, x0,x1,y0,y1,
355 psf, pk, sigma1, patchEdges)
356 pkres.setRampedTemplate(t2, tfoot2)
362 if medianSmoothTemplate:
363 filtsize = medianFilterHalfsize * 2 + 1
364 if t1.getWidth() >= filtsize
and t1.getHeight() >= filtsize:
365 log.logdebug(
'Median filtering template %i' % pkres.pki)
368 inimg = t1.Factory(t1,
True)
369 butils.medianFilter(inimg, t1, medianFilterHalfsize)
371 pkres.setMedianFilteredTemplate(t1, tfoot)
373 log.logdebug((
'Not median-filtering template %i: size '
374 +
'%i x %i smaller than required %i x %i') %
375 (pkres.pki, t1.getWidth(), t1.getHeight(),
378 if monotonicTemplate:
379 log.logdebug(
'Making template %i monotonic' % pkres.pki)
380 butils.makeMonotonic(t1, pk)
382 if clipFootprintToNonzero:
383 tfoot.clipToNonzero(t1.getImage())
386 pkres.setTemplate(t1, tfoot)
401 for peaki,pkres
in enumerate(res.peaks):
404 tmimgs.append(pkres.templateMaskedImage)
405 tfoots.append(pkres.templateFootprint)
407 dpsf.append(pkres.deblendedAsPsf)
409 pkx.append(pk.getIx())
410 pky.append(pk.getIy())
411 ibi.append(pkres.pki)
415 A = np.zeros((W * H, len(tmimgs)))
416 b = img.getArray()[y0:y1+1, x0:x1+1].ravel()
418 for mim,i
in zip(tmimgs, ibi):
420 ix0,iy0 = ibb.getMinX(), ibb.getMinY()
422 foot = pkres.templateFootprint
423 ima = mim.getImage().getArray()
424 for sp
in foot.getSpans():
425 sy, sx0, sx1 = sp.getY(), sp.getX0(), sp.getX1()
426 imrow = ima[sy-iy0, sx0-ix0 : 1+sx1-ix0]
428 A[r0 + sx0-x0: r0+1+sx1-x0, i] = imrow
430 X1,r1,rank1,s1 = np.linalg.lstsq(A, b)
434 for mim,i,w
in zip(tmimgs, ibi, X1):
437 res.peaks[i].setTemplateWeight(w)
443 log.logdebug(
'Apportioning flux among %i templates' % len(tmimgs))
444 sumimg = afwImage.ImageF(bb)
448 strayflux = afwDet.HeavyFootprintPtrListF()
452 strayopts |= butils.ASSIGN_STRAYFLUX
453 if strayFluxToPointSources ==
'necessary':
454 strayopts |= butils.STRAYFLUX_TO_POINT_SOURCES_WHEN_NECESSARY
455 elif strayFluxToPointSources ==
'always':
456 strayopts |= butils.STRAYFLUX_TO_POINT_SOURCES_ALWAYS
458 if strayFluxAssignment ==
'r-to-peak':
461 elif strayFluxAssignment ==
'r-to-footprint':
462 strayopts |= butils.STRAYFLUX_R_TO_FOOTPRINT
463 elif strayFluxAssignment ==
'nearest-footprint':
464 strayopts |= butils.STRAYFLUX_NEAREST_FOOTPRINT
466 portions = butils.apportionFlux(maskedImage, fp, tmimgs, tfoots, sumimg,
467 dpsf, pkx, pky, strayflux, strayopts,
468 clipStrayFluxFraction)
470 res.setTemplateSum(sumimg)
474 for j, (pk, pkres)
in enumerate(zip(peaks, res.peaks)):
477 pkres.setFluxPortion(portions[ii])
488 pkres.setStrayFlux(stray)
491 for j, (pk, pkres)
in enumerate(zip(peaks, res.peaks)):
495 for foot,add
in [(pkres.templateFootprint,
True),
496 (pkres.origFootprint,
True),
497 (pkres.strayFlux,
False)]:
500 pks = foot.getPeaks()
509 In the PSF fitting code, we request PSF models for all peaks near
510 the one being fit. This was turning out to be quite expensive in
511 some cases. Here, we cache the PSF models to bring the cost down
512 closer to O(N) rather than O(N^2).
518 im = self.cache.get((cx,cy),
None)
522 self.
cache[(cx,cy)] = im
525 def _fitPsfs(fp, peaks, fpres, log, psf, psffwhm, img, varimg,
526 psfChisqCut1, psfChisqCut2, psfChisqCut2b,
529 Fit a PSF + smooth background models to a small region around each
530 peak (plus other peaks that are nearby) in the given list of
533 fp: Footprint containing the Peaks to model
534 peaks: a list of all the Peak objects within this Footprint
535 fpres: a PerFootprint result object where results will be placed
539 psffwhm: FWHM of the PSF, in pixels
540 img: umm, the Image in which this Footprint finds itself
541 varimg: Variance plane
542 psfChisqCut*: floats: cuts in chisq-per-pixel at which to accept
545 Results go into the fpres.peaks objects.
552 fmask = afwImage.MaskU(fbb)
553 fmask.setXY0(fbb.getMinX(), fbb.getMinY())
559 peakF = [pk.getF()
for pk
in peaks]
561 for pki,(pk,pkres,pkF)
in enumerate(zip(peaks, fpres.peaks, peakF)):
562 log.logdebug(
'Peak %i' % pki)
563 _fitPsf(fp, fmask, pk, pkF, pkres, fbb, peaks, peakF, log, cpsf,
564 psffwhm, img, varimg,
565 psfChisqCut1, psfChisqCut2, psfChisqCut2b,
569 def _fitPsf(fp, fmask, pk, pkF, pkres, fbb, peaks, peaksF, log, psf,
570 psffwhm, img, varimg,
571 psfChisqCut1, psfChisqCut2, psfChisqCut2b,
575 Fit a PSF + smooth background model (linear) to a small region
579 fmask: the Mask plane for pixels in the Footprint
580 pk: the Peak within the Footprint that we are going to fit a PSF model for
581 pkF: the floating-point coordinates of this peak
582 pkres: a PerPeak object that will hold the results for this peak
583 fbb: the bounding-box of this Footprint (a Box2I)
584 peaks: a list of all the Peak objects within this Footprint
585 peaksF: a python list of the floating-point (x,y) peak locations
588 psffwhm: FWHM of the PSF, in pixels
589 img: umm, the Image in which this Footprint finds itself
590 varimg: Variance plane
591 psfChisqCut*: floats: cuts in chisq-per-pixel at which to accept the PSF model
601 R0 = int(math.ceil(psffwhm * 1.))
603 R1 = int(math.ceil(psffwhm * 1.5))
604 cx,cy = pkF.getX(), pkF.getY()
605 psfimg = psf.computeImage(cx, cy)
608 R2 = R1 +
min(psfimg.getWidth(), psfimg.getHeight())/2.
610 pbb = psfimg.getBBox()
612 px0,py0 = psfimg.getX0(), psfimg.getY0()
615 xlo = int(math.floor(cx - R1))
616 ylo = int(math.floor(cy - R1))
617 xhi = int(math.ceil (cx + R1))
618 yhi = int(math.ceil (cy + R1))
621 xlo,xhi = stampbb.getMinX(), stampbb.getMaxX()
622 ylo,yhi = stampbb.getMinY(), stampbb.getMaxY()
623 if xlo > xhi
or ylo > yhi:
624 log.logdebug(
'Skipping this peak: out of bounds')
625 pkres.setOutOfBounds()
629 if tinyFootprintSize>0
and (((xhi - xlo) < tinyFootprintSize)
or
630 ((yhi - ylo) < tinyFootprintSize)):
631 log.logdebug(
'Skipping this peak: tiny footprint / close to edge')
632 pkres.setTinyFootprint()
637 for pk2,pkF2
in zip(peaks, peaksF):
640 if pkF.distanceSquared(pkF2) > R2**2:
642 opsfimg = psf.computeImage(pkF2.getX(), pkF2.getY())
643 if not opsfimg.getBBox(afwImage.LOCAL).overlaps(stampbb):
645 otherpeaks.append(opsfimg)
646 log.logdebug(
'%i other peaks within range' % len(otherpeaks))
653 NT1 = 4 + len(otherpeaks)
657 NP = (1 + yhi - ylo) * (1 + xhi - xlo)
670 ix0,iy0 = img.getX0(), img.getY0()
671 fx0,fy0 = fbb.getMinX(), fbb.getMinY()
672 fslice = (slice(ylo-fy0, yhi-fy0+1), slice(xlo-fx0, xhi-fx0+1))
673 islice = (slice(ylo-iy0, yhi-iy0+1), slice(xlo-ix0, xhi-ix0+1))
674 fmask_sub = fmask .getArray()[fslice]
675 var_sub = varimg.getArray()[islice]
676 img_sub = img .getArray()[islice]
679 psfarr = psfimg.getArray()[pbb.getMinY()-py0: 1+pbb.getMaxY()-py0,
680 pbb.getMinX()-px0: 1+pbb.getMaxX()-px0]
681 px0,px1 = pbb.getMinX(), pbb.getMaxX()
682 py0,py1 = pbb.getMinY(), pbb.getMaxY()
685 valid = (fmask_sub > 0)
686 xx,yy = np.arange(xlo, xhi+1), np.arange(ylo, yhi+1)
687 RR = ((xx - cx)**2)[np.newaxis,:] + ((yy - cy)**2)[:,np.newaxis]
688 valid *= (RR <= R1**2)
689 valid *= (var_sub > 0)
693 log.warn(
'Skipping peak at (%.1f,%.1f): no unmasked pixels nearby'
695 pkres.setNoValidPixels()
699 XX,YY = np.meshgrid(xx, yy)
700 ipixes = np.vstack((XX[valid] - xlo, YY[valid] - ylo)).T
702 inpsfx = (xx >= px0) * (xx <= px1)
703 inpsfy = (yy >= py0) * (yy <= py1)
704 inpsf = np.outer(inpsfy, inpsfx)
705 indx = np.outer(inpsfy, (xx > px0) * (xx < px1))
706 indy = np.outer((yy > py0) * (yy < py1), inpsfx)
711 def _overlap(xlo, xhi, xmin, xmax):
712 assert((xlo <= xmax)
and (xhi >= xmin)
and
713 (xlo <= xhi)
and (xmin <= xmax))
714 xloclamp =
max(xlo, xmin)
716 xhiclamp =
min(xhi, xmax)
717 Xhi = Xlo + (xhiclamp - xloclamp)
718 assert(xloclamp >= 0)
720 return (xloclamp, xhiclamp+1, Xlo, Xhi+1)
722 A = np.zeros((NP, NT2))
726 A[:,I_sky_ramp_x] = ipixes[:,0] + (xlo-cx)
727 A[:,I_sky_ramp_y] = ipixes[:,1] + (ylo-cy)
730 px0,px1 = pbb.getMinX(), pbb.getMaxX()
731 py0,py1 = pbb.getMinY(), pbb.getMaxY()
732 sx1,sx2,sx3,sx4 = _overlap(xlo, xhi, px0, px1)
733 sy1,sy2,sy3,sy4 = _overlap(ylo, yhi, py0, py1)
734 dpx0,dpy0 = px0 - xlo, py0 - ylo
735 psf_y_slice = slice(sy3 - dpy0, sy4 - dpy0)
736 psf_x_slice = slice(sx3 - dpx0, sx4 - dpx0)
737 psfsub = psfarr[psf_y_slice, psf_x_slice]
738 vsub = valid[sy1-ylo: sy2-ylo, sx1-xlo: sx2-xlo]
739 A[inpsf[valid], I_psf] = psfsub[vsub]
743 oldsx = (sx1,sx2,sx3,sx4)
744 sx1,sx2,sx3,sx4 = _overlap(xlo, xhi, px0+1, px1-1)
745 psfsub = (psfarr[psf_y_slice, sx3 - dpx0 + 1: sx4 - dpx0 + 1] -
746 psfarr[psf_y_slice, sx3 - dpx0 - 1: sx4 - dpx0 - 1]) / 2.
747 vsub = valid[sy1-ylo: sy2-ylo, sx1-xlo: sx2-xlo]
748 A[indx[valid], I_dx] = psfsub[vsub]
750 (sx1,sx2,sx3,sx4) = oldsx
753 sy1,sy2,sy3,sy4 = _overlap(ylo, yhi, py0+1, py1-1)
754 psfsub = (psfarr[sy3 - dpy0 + 1: sy4 - dpy0 + 1, psf_x_slice] -
755 psfarr[sy3 - dpy0 - 1: sy4 - dpy0 - 1, psf_x_slice]) / 2.
756 vsub = valid[sy1-ylo: sy2-ylo, sx1-xlo: sx2-xlo]
757 A[indy[valid], I_dy] = psfsub[vsub]
760 for j,opsf
in enumerate(otherpeaks):
762 ino = np.outer((yy >= obb.getMinY()) * (yy <= obb.getMaxY()),
763 (xx >= obb.getMinX()) * (xx <= obb.getMaxX()))
764 dpx0,dpy0 = obb.getMinX() - xlo, obb.getMinY() - ylo
765 sx1,sx2,sx3,sx4 = _overlap(xlo, xhi, obb.getMinX(), obb.getMaxX())
766 sy1,sy2,sy3,sy4 = _overlap(ylo, yhi, obb.getMinY(), obb.getMaxY())
767 opsfarr = opsf.getArray()
768 psfsub = opsfarr[sy3 - dpy0 : sy4 - dpy0, sx3 - dpx0: sx4 - dpx0]
769 vsub = valid[sy1-ylo: sy2-ylo, sx1-xlo: sx2-xlo]
770 A[ino[valid], I_opsf + j] = psfsub[vsub]
776 rw = np.ones_like(RR)
779 rw[ii] = np.maximum(0, 1. - ((rr - R0) / (R1 - R0)))
780 w = np.sqrt(rw[valid] / var_sub[valid])
782 sumr = np.sum(rw[valid])
783 log.log(-9,
'sumr = %g' % sumr)
787 Aw = A * w[:,np.newaxis]
796 im1 = np.zeros((1+yhi-ylo, 1+xhi-xlo))
797 im1[ipixes[:,1], ipixes[:,0]] = A[:, i]
798 plt.subplot(R, C, i+1)
799 plt.imshow(im1, interpolation=
'nearest', origin=
'lower')
800 plt.subplot(R, C, NT2+1)
801 im1 = np.zeros((1+yhi-ylo, 1+xhi-xlo))
802 im1[ipixes[:,1], ipixes[:,0]] = b
803 plt.imshow(im1, interpolation=
'nearest', origin=
'lower')
804 plt.subplot(R, C, NT2+2)
805 im1 = np.zeros((1+yhi-ylo, 1+xhi-xlo))
806 im1[ipixes[:,1], ipixes[:,0]] = w
807 plt.imshow(im1, interpolation=
'nearest', origin=
'lower')
819 X1,r1,rank1,s1 = np.linalg.lstsq(Aw[:,:NT1], bw)
821 X2,r2,rank2,s2 = np.linalg.lstsq(Aw, bw)
822 except np.linalg.LinAlgError, e:
823 log.log(log.WARN,
"Failed to fit PSF to child: %s" % e)
824 pkres.setPsfFitFailed()
827 log.log(-9,
'r1 r2 %g %g' % (r1, r2))
839 dof1 = sumr - len(X1)
840 dof2 = sumr - len(X2)
841 log.log(-9,
'dof1, dof2 %g %g' % (dof1, dof2))
844 if dof1 <= 0
or dof2 <= 0:
845 log.logdebug(
'Skipping this peak: bad DOF %g, %g' % (dof1, dof2))
851 log.logdebug(
'PSF fits: chisq/dof = %g, %g' % (q1,q2))
852 ispsf1 = (q1 < psfChisqCut1)
853 ispsf2 = (q2 < psfChisqCut2)
855 pkres.psfFit1 = (chisq1, dof1)
856 pkres.psfFit2 = (chisq2, dof2)
860 fdx, fdy = X2[I_dx], X2[I_dy]
865 ispsf2 = ispsf2
and (abs(dx) < 1.
and abs(dy) < 1.)
866 log.logdebug(
'isPSF2 -- checking derivatives: dx,dy = %g, %g -> %s' %
867 (dx,dy, str(ispsf2)))
869 pkres.psfFitBigDecenter =
True
874 psfimg2 = psf.computeImage(cx + dx, cy + dy)
876 pbb2 = psfimg2.getBBox()
879 px0,py0 = psfimg2.getX0(), psfimg2.getY0()
880 psfarr = psfimg2.getArray()[pbb2.getMinY()-py0: 1+pbb2.getMaxY()-py0,
881 pbb2.getMinX()-px0: 1+pbb2.getMaxX()-px0]
882 px0,py0 = pbb2.getMinX(), pbb2.getMinY()
883 px1,py1 = pbb2.getMaxX(), pbb2.getMaxY()
888 sx1,sx2,sx3,sx4 = _overlap(xlo, xhi, px0, px1)
889 sy1,sy2,sy3,sy4 = _overlap(ylo, yhi, py0, py1)
890 dpx0,dpy0 = px0 - xlo, py0 - ylo
891 psfsub = psfarr[sy3 - dpy0 : sy4 - dpy0, sx3 - dpx0: sx4 - dpx0]
892 vsub = valid[sy1-ylo: sy2-ylo, sx1-xlo: sx2-xlo]
893 xx,yy = np.arange(xlo, xhi+1), np.arange(ylo, yhi+1)
894 inpsf = np.outer((yy >= py0) * (yy <= py1), (xx >= px0) * (xx <= px1))
895 Ab[inpsf[valid], I_psf] = psfsub[vsub]
897 Aw = Ab * w[:,np.newaxis]
899 Xb,rb,rankb,sb = np.linalg.lstsq(Aw, bw)
904 dofb = sumr - len(Xb)
905 log.log(-9,
'rb, dofb %g %g' %(rb, dofb))
907 ispsf2 = (qb < psfChisqCut2b)
910 log.logdebug(
'shifted PSF: new chisq/dof = %g; good? %s' %
912 pkres.psfFit3 = (chisqb, dofb)
915 if (((ispsf1
and ispsf2)
and (q2 < q1))
or
916 (ispsf2
and not ispsf1)):
920 log.log(-9,
'dof %g' % dof)
921 log.logdebug(
'Keeping shifted-PSF model')
924 pkres.psfFitWithDecenter =
True
930 log.log(-9,
'dof %g' % dof)
931 log.logdebug(
'Keeping unshifted PSF model')
933 ispsf = (ispsf1
or ispsf2)
937 SW,SH = 1+xhi-xlo, 1+yhi-ylo
938 psfmod = afwImage.ImageF(SW,SH)
939 psfmod.setXY0(xlo,ylo)
940 psfderivmodm = afwImage.MaskedImageF(SW,SH)
941 psfderivmod = psfderivmodm.getImage()
942 psfderivmod.setXY0(xlo,ylo)
943 model = afwImage.ImageF(SW,SH)
944 model.setXY0(xlo,ylo)
945 for i
in range(len(Xpsf)):
946 for (x,y),v
in zip(ipixes, A[:,i]*Xpsf[i]):
947 ix,iy = int(x),int(y)
948 model.set(ix, iy, model.get(ix,iy) + float(v))
949 if i
in [I_psf, I_dx, I_dy]:
950 psfderivmod.set(ix, iy, psfderivmod.get(ix,iy) + float(v))
953 psfmod.set(int(x),int(y), float(A[ii, I_psf] * Xpsf[I_psf]))
956 modelfp.addSpan(int(y+ylo), int(x+xlo), int(x+xlo))
959 pkres.psfFitDebugPsf0Img = psfimg
960 pkres.psfFitDebugPsfImg = psfmod
961 pkres.psfFitDebugPsfDerivImg = psfderivmod
962 pkres.psfFitDebugPsfModel = model
963 pkres.psfFitDebugStamp = img.Factory(img, stampbb,
True)
964 pkres.psfFitDebugValidPix = valid
965 pkres.psfFitDebugVar = varimg.Factory(varimg, stampbb,
True)
966 ww = np.zeros(valid.shape, np.float)
968 pkres.psfFitDebugWeight = ww
969 pkres.psfFitDebugRampWeight = rw
976 pkres.psfFitStampExtent = (xlo, xhi, ylo, yhi)
977 pkres.psfFitCenter = (cx,cy)
978 log.log(-9,
'saving chisq,dof %g %g' % (chisq, dof))
979 pkres.psfFitBest = (chisq, dof)
980 pkres.psfFitParams = Xpsf
981 pkres.psfFitFlux = Xpsf[I_psf]
982 pkres.psfFitNOthers = len(otherpeaks)
985 pkres.setDeblendedAsPsf()
989 log.logdebug(
'Deblending as PSF; setting template to PSF model')
992 psfimg = psf.computeImage(cx, cy)
994 psfimg *= Xpsf[I_psf]
995 psfimg = psfimg.convertF()
999 psfbb = psfimg.getBBox()
1000 fpcopy.clipTo(psfbb)
1001 bb = fpcopy.getBBox()
1004 psfmod = afwImage.MaskedImageF(bb)
1005 afwDet.copyWithinFootprintImage(fpcopy, psfimg, psfmod.getImage())
1007 fpcopy.clipToNonzero(psfmod.getImage())
1009 pkres.setTemplate(psfmod, fpcopy)
1012 pkres.setPsfTemplate(psfmod, fpcopy)
1016 x0,x1,y0,y1, psf, pk, sigma1, patchEdges):
1019 butils = deb.BaselineUtilsF
1021 log.logdebug(
'Found significant flux at template edge.')
1032 S = (int(S + 0.5) / 2) * 2 + 1
1034 tbb = tfoot.getBBox()
1041 padim = t1.Factory(tbb)
1042 afwDet.copyWithinFootprintMaskedImage(fpcopy, maskedImage, padim)
1045 edgepix = butils.getSignificantEdgePixels(t1.getImage(), tfoot, -1e6)
1048 xc = int((x0 + x1)/2)
1049 yc = int((y0 + y1)/2)
1051 pbb = psfim.getBBox()
1053 lx,ly = pbb.getMinX(), pbb.getMinY()
1054 psfim.setXY0(lx - xc, ly - yc)
1055 pbb = psfim.getBBox()
1059 if not Sbox.contains(pbb):
1061 psfim = psfim.Factory(psfim, Sbox, afwImage.PARENT,
True)
1062 pbb = psfim.getBBox()
1069 ramped = t1.getImage().Factory(tbb)
1070 Tout = ramped.getArray()
1071 Tin = t1.getImage().getArray()
1072 tx0,ty0 = t1.getX0(), t1.getY0()
1073 ox0,oy0 = ramped.getX0(), ramped.getY0()
1074 P = psfim.getArray()
1077 for span
in edgepix.getSpans():
1079 for x
in range(span.getX0(), span.getX1()+1):
1080 slc = (slice(y+py0 - oy0, y+py1+1 - oy0),
1081 slice(x+px0 - ox0, x+px1+1 - ox0))
1082 Tout[slc] = np.maximum(Tout[slc], Tin[y-ty0, x-tx0] * P)
1086 I = (padim.getImage().getArray() == 0)
1087 padim.getImage().getArray()[I] = ramped.getArray()[I]
1092 rtn,patched = butils.buildSymmetricTemplate(
1093 padim, fpcopy, pk, sigma1,
True, patchEdges)
1095 t2, tfoot2 = rtn[0], rtn[1]
1101 imbb = maskedImage.getBBox()
1103 tbb = tfoot2.getBBox()
1105 t2 = t2.Factory(t2, tbb, afwImage.PARENT,
True)
1107 return t2, tfoot2, patched
boost::shared_ptr< Footprint > growFootprint(Footprint const &foot, int nGrow, bool left, bool right, bool up, bool down)
Grow a Footprint in at least one of the cardinal directions, returning a new Footprint.
a place to record messages and descriptions of the state of processing.
An integer coordinate rectangle.
def setMedianFilteredTemplate
MaskT setMaskFromFootprint(lsst::afw::image::Mask< MaskT > *mask, Footprint const &footprint, MaskT const bitmask)
OR bitmask into all the Mask's pixels that are in the Footprint.
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
def setFailedSymmetricTemplate
HeavyFootprint< ImagePixelT, MaskPixelT, VariancePixelT > makeHeavyFootprint(Footprint const &foot, lsst::afw::image::MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > const &img, HeavyFootprintCtrl const *ctrl=NULL)