22 """Support utilities for Measuring sources""" 23 from __future__
import absolute_import, division, print_function
26 __all__ = [
"DipoleTestImage"]
28 from builtins
import zip
29 from builtins
import str
30 from builtins
import range
31 from builtins
import object
42 import lsst.meas.algorithms
as measAlg
44 from .dipoleFitTask
import DipoleFitAlgorithm
45 from .
import diffimLib
46 from .
import diffimTools
52 def showSourceSet(sSet, xy0=(0, 0), frame=0, ctype=ds9.GREEN, symb=
"+", size=2):
53 """Draw the (XAstrom, YAstrom) positions of a set of Sources. Image has the given XY0""" 57 xc, yc = s.getXAstrom() - xy0[0], s.getYAstrom() - xy0[1]
60 ds9.dot(str(s.getId()), xc, yc, frame=frame, ctype=ctype, size=size)
62 ds9.dot(symb, xc, yc, frame=frame, ctype=ctype, size=size)
70 ctype=None, ctypeUnused=None, ctypeBad=None, size=3,
71 frame=None, title="Spatial Cells"):
72 """Show the SpatialCells. If symb is something that ds9.dot 73 understands (e.g. "o"), the top nMaxPerCell candidates will be 74 indicated with that symbol, using ctype and size""" 76 ds9.mtv(maskedIm, frame=frame, title=title)
78 origin = [-maskedIm.getX0(), -maskedIm.getY0()]
79 for cell
in kernelCellSet.getCellList():
80 displayUtils.drawBBox(cell.getBBox(), origin=origin, frame=frame)
82 goodies = ctypeBad
is None 83 for cand
in cell.begin(goodies):
84 xc, yc = cand.getXCenter() + origin[0], cand.getYCenter() + origin[1]
85 if cand.getStatus() == afwMath.SpatialCellCandidate.BAD:
87 elif cand.getStatus() == afwMath.SpatialCellCandidate.GOOD:
89 elif cand.getStatus() == afwMath.SpatialCellCandidate.UNKNOWN:
95 ds9.dot(symb, xc, yc, frame=frame, ctype=color, size=size)
98 rchi2 = cand.getChi2()
101 ds9.dot(
"%d %.1f" % (cand.getId(), rchi2),
102 xc - size, yc - size - 4, frame=frame, ctype=color, size=size)
106 """Display Dia Sources 112 for plane
in (
"BAD",
"CR",
"EDGE",
"INTERPOlATED",
"INTRP",
"SAT",
"SATURATED"):
113 ds9.setMaskPlaneVisibility(plane,
False)
115 mos = displayUtils.Mosaic()
116 for i
in range(len(sources)):
118 badFlag = isFlagged[i]
119 dipoleFlag = isDipole[i]
120 bbox = source.getFootprint().getBBox()
121 stamp = exposure.Factory(exposure, bbox,
True)
122 im = displayUtils.Mosaic(gutter=1, background=0, mode=
"x")
123 im.append(stamp.getMaskedImage())
124 lab =
"%.1f,%.1f:" % (source.getX(), source.getY())
131 if not badFlag
and not dipoleFlag:
134 mos.append(im.makeMosaic(), lab, ctype)
135 title =
"Dia Sources" 136 mosaicImage = mos.makeMosaic(frame=frame, title=title)
141 resids=False, kernels=False):
142 """Display the Kernel candidates. 143 If kernel is provided include spatial model and residuals; 144 If chi is True, generate a plot of residuals/sqrt(variance), i.e. chi 151 mos = displayUtils.Mosaic(gutter=5, background=0)
153 mos = displayUtils.Mosaic(gutter=5, background=-1)
155 candidateCenters = []
156 candidateCentersBad = []
158 for cell
in kernelCellSet.getCellList():
159 for cand
in cell.begin(
False):
162 resid = cand.getDifferenceImage(diffimLib.KernelCandidateF.ORIG)
166 rchi2 = cand.getChi2()
170 if not showBadCandidates
and cand.isBad():
173 im_resid = displayUtils.Mosaic(gutter=1, background=-0.5, mode=
"x")
176 im = cand.getScienceMaskedImage()
177 im = im.Factory(im,
True)
178 im.setXY0(cand.getScienceMaskedImage().getXY0())
181 if (
not resids
and not kernels):
182 im_resid.append(im.Factory(im,
True))
184 im = cand.getTemplateMaskedImage()
185 im = im.Factory(im,
True)
186 im.setXY0(cand.getTemplateMaskedImage().getXY0())
189 if (
not resids
and not kernels):
190 im_resid.append(im.Factory(im,
True))
194 var = resid.getVariance()
195 var = var.Factory(var,
True)
196 np.sqrt(var.getArray(), var.getArray())
197 resid = resid.getImage()
199 bbox = kernel.shrinkBBox(resid.getBBox())
200 resid = resid.Factory(resid, bbox,
True)
202 kim = cand.getKernelImage(diffimLib.KernelCandidateF.ORIG).convertF()
203 resid = kim.Factory(kim,
True)
204 im_resid.append(resid)
207 ski = afwImage.ImageD(kernel.getDimensions())
208 kernel.computeImage(ski,
False, int(cand.getXCenter()), int(cand.getYCenter()))
212 sbg = background(int(cand.getXCenter()), int(cand.getYCenter()))
213 sresid = cand.getDifferenceImage(sk, sbg)
216 resid = sresid.getImage()
218 bbox = kernel.shrinkBBox(resid.getBBox())
219 resid = resid.Factory(resid, bbox,
True)
222 resid = kim.Factory(kim,
True)
223 im_resid.append(resid)
225 im = im_resid.makeMosaic()
227 lab =
"%d chi^2 %.1f" % (cand.getId(), rchi2)
228 ctype = ds9.RED
if cand.isBad()
else ds9.GREEN
230 mos.append(im, lab, ctype)
232 if False and np.isnan(rchi2):
233 ds9.mtv(cand.getScienceMaskedImage.getImage(), title=
"candidate", frame=1)
234 print(
"rating", cand.getCandidateRating())
236 im = cand.getScienceMaskedImage()
237 center = (candidateIndex, cand.getXCenter() - im.getX0(), cand.getYCenter() - im.getY0())
240 candidateCentersBad.append(center)
242 candidateCenters.append(center)
249 title =
"Candidates & residuals" 250 mosaicImage = mos.makeMosaic(frame=frame, title=title)
256 """Display a Kernel's basis images 258 mos = displayUtils.Mosaic()
260 for k
in kernel.getKernelList():
261 im = afwImage.ImageD(k.getDimensions())
262 k.computeImage(im,
False)
264 mos.makeMosaic(frame=frame, title=
"Kernel Basis Images")
272 numSample=128, keepPlots=True, maxCoeff=10):
273 """Plot the Kernel spatial model.""" 276 import matplotlib.pyplot
as plt
277 import matplotlib.colors
278 except ImportError
as e:
279 print(
"Unable to import numpy and matplotlib: %s" % e)
282 x0 = kernelCellSet.getBBox().getBeginX()
283 y0 = kernelCellSet.getBBox().getBeginY()
291 for cell
in kernelCellSet.getCellList():
292 for cand
in cell.begin(
False):
293 if not showBadCandidates
and cand.isBad():
297 im = cand.getTemplateMaskedImage()
298 except Exception
as e:
301 targetFits = badFits
if cand.isBad()
else candFits
302 targetPos = badPos
if cand.isBad()
else candPos
303 targetAmps = badAmps
if cand.isBad()
else candAmps
306 kp0 = np.array(cand.getKernel(diffimLib.KernelCandidateF.ORIG).getKernelParameters())
307 amp = cand.getCandidateRating()
309 targetFits = badFits
if cand.isBad()
else candFits
310 targetPos = badPos
if cand.isBad()
else candPos
311 targetAmps = badAmps
if cand.isBad()
else candAmps
313 targetFits.append(kp0)
314 targetPos.append(candCenter)
315 targetAmps.append(amp)
317 xGood = np.array([pos.getX()
for pos
in candPos]) - x0
318 yGood = np.array([pos.getY()
for pos
in candPos]) - y0
319 zGood = np.array(candFits)
321 xBad = np.array([pos.getX()
for pos
in badPos]) - x0
322 yBad = np.array([pos.getY()
for pos
in badPos]) - y0
323 zBad = np.array(badFits)
326 xRange = np.linspace(0, kernelCellSet.getBBox().getWidth(), num=numSample)
327 yRange = np.linspace(0, kernelCellSet.getBBox().getHeight(), num=numSample)
330 maxCoeff = min(maxCoeff, kernel.getNKernelParameters())
332 maxCoeff = kernel.getNKernelParameters()
334 for k
in range(maxCoeff):
335 func = kernel.getSpatialFunction(k)
336 dfGood = zGood[:, k] - np.array([func(pos.getX(), pos.getY())
for pos
in candPos])
340 dfBad = zBad[:, k] - np.array([func(pos.getX(), pos.getY())
for pos
in badPos])
342 yMin = min([yMin, dfBad.min()])
343 yMax = max([yMax, dfBad.max()])
344 yMin -= 0.05 * (yMax - yMin)
345 yMax += 0.05 * (yMax - yMin)
347 fRange = np.ndarray((len(xRange), len(yRange)))
348 for j, yVal
in enumerate(yRange):
349 for i, xVal
in enumerate(xRange):
350 fRange[j][i] = func(xVal, yVal)
356 fig.canvas._tkcanvas._root().lift()
360 fig.suptitle(
'Kernel component %d' % k)
363 ax = fig.add_axes((0.1, 0.05, 0.35, 0.35))
366 norm = matplotlib.colors.Normalize(vmin=vmin, vmax=vmax)
367 im = ax.imshow(fRange, aspect=
'auto', norm=norm,
368 extent=[0, kernelCellSet.getBBox().getWidth()-1,
369 0, kernelCellSet.getBBox().getHeight()-1])
370 ax.set_title(
'Spatial polynomial')
371 plt.colorbar(im, orientation=
'horizontal', ticks=[vmin, vmax])
374 ax = fig.add_axes((0.1, 0.55, 0.35, 0.35))
375 ax.plot(-2.5*np.log10(candAmps), zGood[:, k],
'b+')
377 ax.plot(-2.5*np.log10(badAmps), zBad[:, k],
'r+')
378 ax.set_title(
"Basis Coefficients")
379 ax.set_xlabel(
"Instr mag")
380 ax.set_ylabel(
"Coeff")
383 ax = fig.add_axes((0.55, 0.05, 0.35, 0.35))
384 ax.set_autoscale_on(
False)
385 ax.set_xbound(lower=0, upper=kernelCellSet.getBBox().getHeight())
386 ax.set_ybound(lower=yMin, upper=yMax)
387 ax.plot(yGood, dfGood,
'b+')
389 ax.plot(yBad, dfBad,
'r+')
391 ax.set_title(
'dCoeff (indiv-spatial) vs. y')
394 ax = fig.add_axes((0.55, 0.55, 0.35, 0.35))
395 ax.set_autoscale_on(
False)
396 ax.set_xbound(lower=0, upper=kernelCellSet.getBBox().getWidth())
397 ax.set_ybound(lower=yMin, upper=yMax)
398 ax.plot(xGood, dfGood,
'b+')
400 ax.plot(xBad, dfBad,
'r+')
402 ax.set_title(
'dCoeff (indiv-spatial) vs. x')
407 if keepPlots
and not keptPlots:
410 print(
"%s: Please close plots when done." % __name__)
415 print(
"Plots closed, exiting...")
417 atexit.register(show)
422 showCenter=True, showEllipticity=True):
423 """Show a mosaic of Kernel images. 425 mos = displayUtils.Mosaic()
427 x0 = bbox.getBeginX()
428 y0 = bbox.getBeginY()
429 width = bbox.getWidth()
430 height = bbox.getHeight()
433 ny = int(nx*float(height)/width + 0.5)
437 schema = afwTable.SourceTable.makeMinimalSchema()
438 centroidName =
"base_SdssCentroid" 439 shapeName =
"base_SdssShape" 440 control = measBase.SdssCentroidControl()
441 schema.getAliasMap().set(
"slot_Centroid", centroidName)
442 schema.getAliasMap().set(
"slot_Centroid_flag", centroidName+
"_flag")
443 centroider = measBase.SdssCentroidAlgorithm(control, centroidName, schema)
444 sdssShape = measBase.SdssShapeControl()
445 shaper = measBase.SdssShapeAlgorithm(sdssShape, shapeName, schema)
446 table = afwTable.SourceTable.make(schema)
447 table.defineCentroid(centroidName)
448 table.defineShape(shapeName)
454 x = int(ix*(width-1)/(nx-1)) + x0
455 y = int(iy*(height-1)/(ny-1)) + y0
457 im = afwImage.ImageD(kernel.getDimensions())
458 ksum = kernel.computeImage(im,
False, x, y)
459 lab =
"Kernel(%d,%d)=%.2f" % (x, y, ksum)
if False else "" 464 w, h = im.getWidth(), im.getHeight()
465 centerX = im.getX0() + w//2
466 centerY = im.getY0() + h//2
467 src = table.makeRecord()
469 foot.addPeak(centerX, centerY, 1)
470 src.setFootprint(foot)
472 centroider.measure(src, exp)
473 centers.append((src.getX(), src.getY()))
475 shaper.measure(src, exp)
476 shapes.append((src.getIxx(), src.getIxy(), src.getIyy()))
478 mos.makeMosaic(frame=frame, title=title
if title
else "Model Kernel", mode=nx)
480 if centers
and frame
is not None:
482 with ds9.Buffering():
483 for cen, shape
in zip(centers, shapes):
484 bbox = mos.getBBox(i)
486 xc, yc = cen[0] + bbox.getMinX(), cen[1] + bbox.getMinY()
488 ds9.dot(
"+", xc, yc, ctype=ds9.BLUE, frame=frame)
491 ixx, ixy, iyy = shape
492 ds9.dot(
"@:%g,%g,%g" % (ixx, ixy, iyy), xc, yc, frame=frame, ctype=ds9.RED)
498 kernel, background, testSources, config,
499 origVariance=False, nptsFull=1e6, keepPlots=True, titleFs=14):
500 """Plot diffim residuals for LOCAL and SPATIAL models""" 505 for cell
in kernelCellSet.getCellList():
506 for cand
in cell.begin(
True):
508 if not (cand.getStatus() == afwMath.SpatialCellCandidate.GOOD):
511 diffim = cand.getDifferenceImage(diffimLib.KernelCandidateF.ORIG)
512 orig = cand.getScienceMaskedImage()
514 ski = afwImage.ImageD(kernel.getDimensions())
515 kernel.computeImage(ski,
False, int(cand.getXCenter()), int(cand.getYCenter()))
517 sbg = background(int(cand.getXCenter()), int(cand.getYCenter()))
518 sdiffim = cand.getDifferenceImage(sk, sbg)
521 bbox = kernel.shrinkBBox(diffim.getBBox())
522 tdiffim = diffim.Factory(diffim, bbox)
523 torig = orig.Factory(orig, bbox)
524 tsdiffim = sdiffim.Factory(sdiffim, bbox)
527 candidateResids.append(np.ravel(tdiffim.getImage().getArray() /
528 np.sqrt(torig.getVariance().getArray())))
529 spatialResids.append(np.ravel(tsdiffim.getImage().getArray() /
530 np.sqrt(torig.getVariance().getArray())))
532 candidateResids.append(np.ravel(tdiffim.getImage().getArray() /
533 np.sqrt(tdiffim.getVariance().getArray())))
534 spatialResids.append(np.ravel(tsdiffim.getImage().getArray() /
535 np.sqrt(tsdiffim.getVariance().getArray())))
537 fullIm = diffExposure.getMaskedImage().getImage().getArray()
538 fullMask = diffExposure.getMaskedImage().getMask().getArray()
540 fullVar = exposure.getMaskedImage().getVariance().getArray()
542 fullVar = diffExposure.getMaskedImage().getVariance().getArray()
545 bitmaskBad |= afwImage.Mask.getPlaneBitMask(
'NO_DATA')
546 bitmaskBad |= afwImage.Mask.getPlaneBitMask(
'SAT')
547 idx = np.where((fullMask & bitmaskBad) == 0)
548 stride = int(len(idx[0]) // nptsFull)
549 sidx = idx[0][::stride], idx[1][::stride]
550 allResids = fullIm[sidx] / np.sqrt(fullVar[sidx])
552 testFootprints = diffimTools.sourceToFootprintList(testSources, warpedTemplateExposure,
553 exposure, config, Log.getDefaultLogger())
554 for fp
in testFootprints:
555 subexp = diffExposure.Factory(diffExposure, fp[
"footprint"].getBBox())
556 subim = subexp.getMaskedImage().getImage()
558 subvar = afwImage.ExposureF(exposure, fp[
"footprint"].getBBox()).getMaskedImage().getVariance()
560 subvar = subexp.getMaskedImage().getVariance()
561 nonfitResids.append(np.ravel(subim.getArray() / np.sqrt(subvar.getArray())))
563 candidateResids = np.ravel(np.array(candidateResids))
564 spatialResids = np.ravel(np.array(spatialResids))
565 nonfitResids = np.ravel(np.array(nonfitResids))
569 from matplotlib.font_manager
import FontProperties
570 except ImportError
as e:
571 print(
"Unable to import pylab: %s" % e)
577 fig.canvas._tkcanvas._root().lift()
581 fig.suptitle(
"Diffim residuals: Normalized by sqrt(input variance)", fontsize=titleFs)
583 fig.suptitle(
"Diffim residuals: Normalized by sqrt(diffim variance)", fontsize=titleFs)
585 sp1 = pylab.subplot(221)
586 sp2 = pylab.subplot(222, sharex=sp1, sharey=sp1)
587 sp3 = pylab.subplot(223, sharex=sp1, sharey=sp1)
588 sp4 = pylab.subplot(224, sharex=sp1, sharey=sp1)
589 xs = np.arange(-5, 5.05, 0.1)
590 ys = 1. / np.sqrt(2*np.pi)*np.exp(-0.5*xs**2)
592 sp1.hist(candidateResids, bins=xs, normed=
True, alpha=0.5, label=
"N(%.2f, %.2f)" 593 % (np.mean(candidateResids), np.var(candidateResids)))
594 sp1.plot(xs, ys,
"r-", lw=2, label=
"N(0,1)")
595 sp1.set_title(
"Candidates: basis fit", fontsize=titleFs-2)
596 sp1.legend(loc=1, fancybox=
True, shadow=
True, prop=FontProperties(size=titleFs-6))
598 sp2.hist(spatialResids, bins=xs, normed=
True, alpha=0.5, label=
"N(%.2f, %.2f)" 599 % (np.mean(spatialResids), np.var(spatialResids)))
600 sp2.plot(xs, ys,
"r-", lw=2, label=
"N(0,1)")
601 sp2.set_title(
"Candidates: spatial fit", fontsize=titleFs-2)
602 sp2.legend(loc=1, fancybox=
True, shadow=
True, prop=FontProperties(size=titleFs-6))
604 sp3.hist(nonfitResids, bins=xs, normed=
True, alpha=0.5, label=
"N(%.2f, %.2f)" 605 % (np.mean(nonfitResids), np.var(nonfitResids)))
606 sp3.plot(xs, ys,
"r-", lw=2, label=
"N(0,1)")
607 sp3.set_title(
"Control sample: spatial fit", fontsize=titleFs-2)
608 sp3.legend(loc=1, fancybox=
True, shadow=
True, prop=FontProperties(size=titleFs-6))
610 sp4.hist(allResids, bins=xs, normed=
True, alpha=0.5, label=
"N(%.2f, %.2f)" 611 % (np.mean(allResids), np.var(allResids)))
612 sp4.plot(xs, ys,
"r-", lw=2, label=
"N(0,1)")
613 sp4.set_title(
"Full image (subsampled)", fontsize=titleFs-2)
614 sp4.legend(loc=1, fancybox=
True, shadow=
True, prop=FontProperties(size=titleFs-6))
616 pylab.setp(sp1.get_xticklabels()+sp1.get_yticklabels(), fontsize=titleFs-4)
617 pylab.setp(sp2.get_xticklabels()+sp2.get_yticklabels(), fontsize=titleFs-4)
618 pylab.setp(sp3.get_xticklabels()+sp3.get_yticklabels(), fontsize=titleFs-4)
619 pylab.setp(sp4.get_xticklabels()+sp4.get_yticklabels(), fontsize=titleFs-4)
626 if keepPlots
and not keptPlots:
629 print(
"%s: Please close plots when done." % __name__)
634 print(
"Plots closed, exiting...")
636 atexit.register(show)
641 """Calculate first moment of a (kernel) image""" 644 xarr = np.asarray([[el
for el
in range(x)]
for el2
in range(y)])
645 yarr = np.asarray([[el2
for el
in range(x)]
for el2
in range(y)])
648 centx = narr.sum()/sarrSum
650 centy = narr.sum()/sarrSum
655 """Calculate second moment of a (kernel) image""" 659 xarr = np.asarray([[el
for el
in range(x)]
for el2
in range(y)])
660 yarr = np.asarray([[el2
for el
in range(x)]
for el2
in range(y)])
661 narr = sarr*np.power((xarr - centx), 2.)
663 xstd = np.sqrt(narr.sum()/sarrSum)
664 narr = sarr*np.power((yarr - centy), 2.)
665 ystd = np.sqrt(narr.sum()/sarrSum)
670 """Print differences in sky coordinates between source Position and its Centroid mapped through Wcs""" 672 sCentroid = s.getCentroid()
673 sPosition = s.getCoord().getPosition(afwGeom.degrees)
674 dra = 3600*(sPosition.getX() - wcs.pixelToSky(sCentroid).getPosition(afwGeom.degrees).getX())/0.2
675 ddec = 3600*(sPosition.getY() - wcs.pixelToSky(sCentroid).getPosition(afwGeom.degrees).getY())/0.2
676 if np.isfinite(dra)
and np.isfinite(ddec):
681 """Create regions file for ds9 from input source list""" 682 fh = open(outfilename,
"w")
683 fh.write(
"global color=red font=\"helvetica 10 normal\" " 684 "select=1 highlite=1 edit=1 move=1 delete=1 include=1 fixed=0 source\nfk5\n")
687 (ra, dec) = wcs.pixelToSky(s.getCentroid()).getPosition(afwGeom.degrees)
689 (ra, dec) = s.getCoord().getPosition(afwGeom.degrees)
690 if np.isfinite(ra)
and np.isfinite(dec):
691 fh.write(
"circle(%f,%f,2\")\n"%(ra, dec))
697 """Draw the (RA, Dec) positions of a set of Sources. Image has the XY0.""" 698 with ds9.Buffering():
700 (xc, yc) = wcs.skyToPixel(s.getCoord().getRa(), s.getCoord().getDec())
703 ds9.dot(symb, xc, yc, frame=frame, ctype=ctype, size=size)
707 """Plot whisker diagram of astromeric offsets between results.matches""" 708 refCoordKey = results.matches[0].first.getTable().getCoordKey()
709 inCentroidKey = results.matches[0].second.getTable().getCentroidKey()
710 positions = [m.first.get(refCoordKey)
for m
in results.matches]
711 residuals = [m.first.get(refCoordKey).getOffsetFrom(
712 newWcs.pixelToSky(m.second.get(inCentroidKey)))
for 713 m
in results.matches]
714 import matplotlib.pyplot
as plt
716 sp = fig.add_subplot(1, 1, 0)
717 xpos = [x[0].asDegrees()
for x
in positions]
718 ypos = [x[1].asDegrees()
for x
in positions]
719 xpos.append(0.02*(max(xpos) - min(xpos)) + min(xpos))
720 ypos.append(0.98*(max(ypos) - min(ypos)) + min(ypos))
721 xidxs = np.isfinite(xpos)
722 yidxs = np.isfinite(ypos)
723 X = np.asarray(xpos)[xidxs]
724 Y = np.asarray(ypos)[yidxs]
725 distance = [x[1].asArcseconds()
for x
in residuals]
727 distance = np.asarray(distance)[xidxs]
730 bearing = [x[0].asRadians()
for x
in residuals]
732 bearing = np.asarray(bearing)[xidxs]
733 U = (distance*np.cos(bearing))
734 V = (distance*np.sin(bearing))
735 sp.quiver(X, Y, U, V)
736 sp.set_title(
"WCS Residual")
742 """!Utility class for dipole measurement testing 744 Generate an image with simulated dipoles and noise; store the original "pre-subtraction" images 745 and catalogs as well. 746 Used to generate test data for DMTN-007 (http://dmtn-007.lsst.io). 749 def __init__(self, w=101, h=101, xcenPos=[27.], ycenPos=[25.], xcenNeg=[23.], ycenNeg=[25.],
750 psfSigma=2., flux=[30000.], fluxNeg=None, noise=10., gradientParams=None):
766 def _makeDipoleImage(self):
767 """!Generate an exposure and catalog with the given dipole source(s)""" 776 dipole = posImage.clone()
777 di = dipole.getMaskedImage()
778 di -= negImage.getMaskedImage()
782 posDetectedBits = posImage.getMaskedImage().getMask().getArray() == dm.getPlaneBitMask(
"DETECTED")
783 negDetectedBits = negImage.getMaskedImage().getMask().getArray() == dm.getPlaneBitMask(
"DETECTED")
784 pos_det = dm.addMaskPlane(
"DETECTED_POS")
785 neg_det = dm.addMaskPlane(
"DETECTED_NEG")
788 dma[:, :] = posDetectedBits*pos_det + negDetectedBits*neg_det
789 self.diffim, self.posImage, self.posCatalog, self.negImage, self.negCatalog \
790 = dipole, posImage, posCatalog, negImage, negCatalog
792 def _makeStarImage(self, xc=[15.3], yc=[18.6], flux=[2500], schema=None, randomSeed=None):
793 """!Generate an exposure and catalog with the given stellar source(s)""" 797 dataset = TestDataset(bbox, psfSigma=self.
psfSigma, threshold=1.)
799 for i
in range(len(xc)):
800 dataset.addSource(flux=flux[i], centroid=
afwGeom.Point2D(xc[i], yc[i]))
803 schema = TestDataset.makeMinimalSchema()
804 exposure, catalog = dataset.realize(noise=self.
noise, schema=schema, randomSeed=randomSeed)
807 y, x = np.mgrid[:self.
w, :self.
h]
809 gradient = gp[0] + gp[1] * x + gp[2] * y
811 gradient += gp[3] * x*y + gp[4] * x*x + gp[5] * y*y
812 imgArr = exposure.getMaskedImage().getArrays()[0]
815 return exposure, catalog
819 fitResult = alg.fitDipole(source, **kwds)
823 """!Utility function for detecting dipoles. 825 Detect pos/neg sources in the diffim, then merge them. A 826 bigger "grow" parameter leads to a larger footprint which 827 helps with dipole measurement for faint dipoles. 832 Whether to merge the positive and negagive detections into a single source table 833 diffim : `lsst.afw.image.exposure.exposure.ExposureF` 834 Difference image on which to perform detection 835 detectSigma : `float` 836 Threshold for object detection 838 Number of pixels to grow the footprints before merging 840 Minimum bin size for the background (re)estimation (only applies if the default leads to 841 min(nBinX, nBinY) < fit order so the default config parameter needs to be decreased, but not 842 to a value smaller than minBinSize, in which case the fitting algorithm will take over and 843 decrease the fit order appropriately.) 847 sources : `lsst.afw.table.SourceCatalog` 848 If doMerge=True, the merged source catalog is returned OR 849 detectTask : `lsst.meas.algorithms.SourceDetectionTask` 850 schema : `lsst.afw.table.Schema` 851 If doMerge=False, the source detection task and its schema are returned 857 schema = afwTable.SourceTable.makeMinimalSchema()
860 detectConfig = measAlg.SourceDetectionConfig()
861 detectConfig.returnOriginalFootprints =
False 863 psfSigma = diffim.getPsf().computeShape().getDeterminantRadius()
866 detectConfig.thresholdPolarity =
"both" 867 detectConfig.thresholdValue = detectSigma
869 detectConfig.reEstimateBackground =
True 870 detectConfig.thresholdType =
"pixel_stdev" 872 while ((min(diffim.getWidth(), diffim.getHeight()))//detectConfig.background.binSize <
873 detectConfig.background.approxOrderX
and detectConfig.background.binSize > minBinSize):
874 detectConfig.background.binSize = max(minBinSize, detectConfig.background.binSize//2)
877 detectTask = measAlg.SourceDetectionTask(schema, config=detectConfig)
879 table = afwTable.SourceTable.make(schema)
880 catalog = detectTask.makeSourceCatalog(table, diffim, sigma=psfSigma)
884 fpSet = catalog.fpSets.positive
885 fpSet.merge(catalog.fpSets.negative, grow, grow,
False)
886 sources = afwTable.SourceCatalog(table)
887 fpSet.makeSources(sources)
892 return detectTask, schema
def _makeDipoleImage(self)
Generate an exposure and catalog with the given dipole source(s)
def showDiaSources(sources, exposure, isFlagged, isDipole, frame=None)
Lightweight class containing methods for fitting a dipole model in a diffim, used by DipoleFitPlugin...
def makeRegions(sources, outfilename, wcs=None)
def __init__(self, w=101, h=101, xcenPos=[27.], ycenPos=[25.], xcenNeg=[23.], ycenNeg=[25.], psfSigma=2., flux=[30000.], fluxNeg=None, noise=10., gradientParams=None)
Utility class for dipole measurement testing.
MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > * makeMaskedImage(typename std::shared_ptr< Image< ImagePixelT >> image, typename std::shared_ptr< Mask< MaskPixelT >> mask=Mask< MaskPixelT >(), typename std::shared_ptr< Image< VariancePixelT >> variance=Image< VariancePixelT >())
def showKernelSpatialCells(maskedIm, kernelCellSet, showChi2=False, symb="o", ctype=None, ctypeUnused=None, ctypeBad=None, size=3, frame=None, title="Spatial Cells")
std::shared_ptr< Exposure< ImagePixelT, MaskPixelT, VariancePixelT > > makeExposure(MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > &mimage, std::shared_ptr< geom::SkyWcs const > wcs=std::shared_ptr< geom::SkyWcs const >())
def _makeStarImage(self, xc=[15.3], yc=[18.6], flux=[2500], schema=None, randomSeed=None)
Generate an exposure and catalog with the given stellar source(s)
def plotKernelSpatialModel(kernel, kernelCellSet, showBadCandidates=True, numSample=128, keepPlots=True, maxCoeff=10)
def showSourceSetSky(sSet, wcs, xy0, frame=0, ctype=ds9.GREEN, symb="+", size=2)
def plotPixelResiduals(exposure, warpedTemplateExposure, diffExposure, kernelCellSet, kernel, background, testSources, config, origVariance=False, nptsFull=1e6, keepPlots=True, titleFs=14)
def printSkyDiffs(sources, wcs)
def showKernelCandidates(kernelCellSet, kernel, background, frame=None, showBadCandidates=True, resids=False, kernels=False)
def showSourceSet(sSet, xy0=(0, 0), frame=0, ctype=ds9.GREEN, symb="+", size=2)
def detectDipoleSources(self, doMerge=True, diffim=None, detectSigma=5.5, grow=3, minBinSize=32)
Utility function for detecting dipoles.
def calcWidth(arr, centx, centy)
def plotWhisker(results, newWcs)
def showKernelMosaic(bbox, kernel, nx=7, ny=None, frame=None, title=None, showCenter=True, showEllipticity=True)
def showKernelBasis(kernel, frame=None)
def fitDipoleSource(self, source, kwds)