def testSetIntegerOffset(self): """Test that we can offset by positive and negative amounts""" self.inImage.set(50, 50, 400) if False and display: frame = 0 ds9.mtv(self.inImage, frame=frame) ds9.pan(50, 50, frame=frame) ds9.dot("+", 50, 50, frame=frame) for algorithm in ("lanczos5", "bilinear", "nearest"): for delta in [-0.49, 0.51]: for dx, dy in [(2, 3), (-2, 3), (-2, -3), (2, -3)]: outImage = afwMath.offsetImage(self.inImage, dx + delta, dy + delta, algorithm) if False and display: frame += 1 ds9.mtv(outImage, frame=frame) ds9.pan(50, 50, frame=frame) ds9.dot("+", 50 + dx + delta - outImage.getX0(), 50 + dy + delta - outImage.getY0(), frame=frame)
def makeAndMeasure(self, measureKron, a, b, theta, dx=0.0, dy=0.0, nsigma=6, kfac=2, nIterForRadius=1, xcen=None, ycen=None, makeImage=True, apCorrValue=None, # if a numeric value, use as the constant value of aperture correction ): """Make and measure an elliptical Gaussian""" if xcen is None: xcen = 0.5*self.width + dx if ycen is None: ycen = 0.5*self.height + dy # # Make the object # if a < b: a, b = b, a theta += 90 if self.objImg is None: makeImage = True if makeImage: self.objImg = makeGalaxy(self.width, self.height, self.flux, a, b, theta, dx, dy, afwGeom.Point2I(10, 10), xcen=xcen, ycen=ycen) if display: ds9.mtv(self.objImg, frame=ds9Frame, title="%g %g" % (a, b)) doApplyApCorr = "noButWarn" if apCorrValue != None: addApCorrMap(self.objImg, apCorrValue) doApplyApCorr = "yes" if display: if not makeImage: ds9.erase(frame=ds9Frame) ds9.dot("+", xcen - self.objImg.getX0(), ycen - self.objImg.getY0(), size=1, ctype=ds9.RED, frame=ds9Frame) ds9.pan(xcen - self.objImg.getX0(), ycen - self.objImg.getY0(), frame=ds9Frame) c, s = math.cos(math.radians(theta)), math.sin(math.radians(theta)) # N.b. add 1/12 in quadrature to allow for pixellisation ds9.dot("@:%f,%f,%f" % (nsigma**2*((a**2 + 1/12.0)*c**2 + (b**2 + 1/12.0)*s**2), nsigma**2*(a**2 - b**2)*c*s, nsigma**2*((a**2 + 1/12.0)*s**2 + (b**2 + 1/12.0)*c**2)), xcen - self.objImg.getX0(), ycen - self.objImg.getY0(), size=1, ctype=ds9.RED, frame=ds9Frame, silent=True) # # Do the measuring # FWHM = 5 ksize = 25 # size of desired kernel self.objImg.setPsf(measAlg.DoubleGaussianPsf(ksize, ksize, FWHM/(2*math.sqrt(2*math.log(2))), 1, 0.1)) return measureKron(self.objImg, xcen, ycen, nsigma, kfac, nIterForRadius, doApplyApCorr)
def showMedpict(fileName="events.dat", events=None, image=None): medpictEvents = ras.readEventFile(fileName) # # Look for events that medpict missed # if events: x = np.empty(len(medpictEvents)) y = np.empty(len(medpictEvents)) for i, ev in enumerate(medpictEvents): x[i] = ev.x y[i] = ev.y for ev in events: if events: d = np.hypot(x - ev.x, y - ev.y) dmin = np.min(d) if dmin > 0: print "medpict missed:", " ".join([str(_) for _ in zip(x[d == dmin], y[d == dmin])]) ds9.dot("o", ev.x, ev.y, size=5, ctype=ds9.GREEN) if False: ds9.pan(ev.x, ev.y) ds9.flush() import pdb; pdb.set_trace() # # Look for events that the DM stack missed # if events: x = np.empty(len(events)) y = np.empty(len(events)) for i, ev in enumerate(events): x[i] = ev.x y[i] = ev.y with ds9.Buffering(): for ev in medpictEvents: if events: d = np.hypot(x - ev.x, y - ev.y) dmin = np.min(d) if dmin > 0: print "DM missed:", " ".join([str(_) for _ in zip(x[d == dmin], y[d == dmin])]) ds9.dot("o", ev.x, ev.y, size=5, ctype=ds9.RED) if False: ds9.pan(ev.x, ev.y) ds9.flush() import pdb; pdb.set_trace()
def makeAndMeasure(self, measureKron, a, b, theta, dx=0.0, dy=0.0, nsigma=6, kfac=2, nIterForRadius=1, xcen=None, ycen=None, makeImage=True): """Make and measure an elliptical Gaussian""" if xcen is None: xcen = 0.5*self.width + dx if ycen is None: ycen = 0.5*self.height + dy # # Make the object # if a < b: a, b = b, a theta += 90 if self.objImg is None: makeImage = True if makeImage: self.objImg = makeGalaxy(self.width, self.height, self.flux, a, b, theta, dx, dy, afwGeom.Point2I(10, 10), xcen=xcen, ycen=ycen) if display: ds9.mtv(self.objImg, frame=ds9Frame, title="%g %g" % (a, b)) if display: if not makeImage: ds9.erase(frame=ds9Frame) ds9.dot("+", xcen - self.objImg.getX0(), ycen - self.objImg.getY0(), size=1, ctype=ds9.RED, frame=ds9Frame) ds9.pan(xcen - self.objImg.getX0(), ycen - self.objImg.getY0(), frame=ds9Frame) c, s = math.cos(math.radians(theta)), math.sin(math.radians(theta)) # N.b. add 1/12 in quadrature to allow for pixellisation ds9.dot("@:%f,%f,%f" % (nsigma**2*((a**2 + 1/12.0)*c**2 + (b**2 + 1/12.0)*s**2), nsigma**2*(a**2 - b**2)*c*s, nsigma**2*((a**2 + 1/12.0)*s**2 + (b**2 + 1/12.0)*c**2)), xcen - self.objImg.getX0(), ycen - self.objImg.getY0(), size=1, ctype=ds9.RED, frame=ds9Frame, silent=True) # # Do the measuring # FWHM = 5 ksize = 25 # size of desired kernel self.objImg.setPsf(measAlg.DoubleGaussianPsf(ksize, ksize, FWHM/(2*math.sqrt(2*math.log(2))), 1, 0.1)) return measureKron(self.objImg, xcen, ycen, nsigma, kfac, nIterForRadius)
def __call__(self, ev): if ev.inaxes != self.axes: return if ev.key and ev.key in ("p"): dist = np.hypot(self.xs - ev.xdata, self.ys - ev.ydata) dist[np.where(np.isnan(dist))] = 1e30 which = np.where(dist == min(dist)) x = self.x[which][0] y = self.y[which][0] for frame in self.frames: ds9.pan(x, y, frame=frame) ds9.cmdBuffer.flush() else: pass
def __call__(self, ev): if ev.inaxes != self.axes: return if ev.key and ev.key in ("p"): dist = numpy.hypot(self.xs - ev.xdata, self.ys - ev.ydata) dist[numpy.where(numpy.isnan(dist))] = 1e30 which = numpy.where(dist == min(dist)) x = self.x[which][0] y = self.y[which][0] for frame in self.frames: ds9.pan(x, y, frame=frame) ds9.cmdBuffer.flush() else: pass
def acsEventCallback(key, source, im, frame): """Callback for event handlers to find COSMOS ACS cutout. \param key Key struck \param source The Source under the cursor \param im The (HSC) image cutout displayed in frame \param frame The frame that the HSC data's displayed in (we'll use the next one) We also use the following static members of utils.EventHandler (if set): sizeCutout The size of the HSC cutout (arcsec; default: 4.0) scale Make the COSMOS image with pixel size scale*HSC's pixel size (default 0.25 => 0.42mas) Use as e.g. utils.eventCallbacks['c'] = cosmos.acsEventCallback """ sizeCutout = utils.EventHandler.sizeCutout if hasattr(utils.EventHandler, "sizeCutout") else 4.0 # arcsec scale = utils.EventHandler.scale if hasattr(utils.EventHandler, "scale") else 0.25 # Pixel size scaling pos = source.get("coord") exp = getCosmosCutout(*pos.getPosition(), sizeX=sizeCutout) if im and exp and exp.getWcs(): # # Resample and rotate to the HSC orientation # warpingControl = afwMath.WarpingControl("lanczos3") rat = im.getWcs().pixelScale().asArcseconds()/exp.getWcs().pixelScale().asArcseconds() hsize = int(0.5*exp.getWidth()/(scale*rat)) rexp = afwImage.ExposureF(2*hsize + 1, 2*hsize + 1) rexp.setWcs(afwImage.Wcs(pos.getPosition(), afwGeom.Point2D(hsize, hsize), im.getWcs().getCDMatrix()*scale)) afwMath.warpExposure(rexp, exp, warpingControl) else: print "\nI'm unable to remap the cosmos image to your coordinates, sorry" rexp = exp.getMaskedImage().getImage() frame += 1 rim = rexp if hasattr(rim, "getMaskedImage"): rim = rim.getMaskedImage().getImage() if hasattr(rim, "getImage"): rim = rim.getImage() ds9.mtv(rim, frame=frame) if hasattr(rexp, "getWcs"): cen = rexp.getWcs().skyToPixel(pos) - afwGeom.PointD(rexp.getXY0()) ds9.pan(*cen, frame=frame) ds9.dot('+', *cen, frame=frame)
def testSetIntegerOffset(self): """Test that we can offset by positive and negative amounts""" self.inImage.set(50, 50, 400) if False and display: frame = 0 ds9.mtv(self.inImage, frame=frame) ds9.pan(50, 50, frame=frame) ds9.dot("+", 50, 50, frame=frame) for delta in [-0.49, 0.51]: for dx, dy in [(2, 3), (-2, 3), (-2, -3), (2, -3)]: outImage = afwMath.offsetImage(self.inImage, dx + delta, dy + delta, self.algorithm) if False and display: frame += 1 ds9.mtv(outImage, frame=frame) ds9.pan(50, 50, frame=frame) ds9.dot("+", 50 + dx + delta - outImage.getX0(), 50 + dy + delta - outImage.getY0(), frame=frame)
def getClumps(self, sigma=1.0, display=False): if self._num <= 0: raise RuntimeError("No candidate PSF sources") psfImage = self.getImage() # # Embed psfImage into a larger image so we can smooth when measuring it # width, height = psfImage.getWidth(), psfImage.getHeight() largeImg = psfImage.Factory(afwGeom.ExtentI(2*width, 2*height)) largeImg.set(0) bbox = afwGeom.BoxI(afwGeom.PointI(width, height), afwGeom.ExtentI(width, height)) subLargeImg = psfImage.Factory(largeImg, bbox, afwImage.LOCAL) subLargeImg <<= psfImage del subLargeImg # # Now measure that image, looking for the highest peak. Start by building an Exposure # msk = afwImage.MaskU(largeImg.getDimensions()) msk.set(0) var = afwImage.ImageF(largeImg.getDimensions()) var.set(1) mpsfImage = afwImage.MaskedImageF(largeImg, msk, var) mpsfImage.setXY0(afwGeom.PointI(-width, -height)) del msk del var exposure = afwImage.makeExposure(mpsfImage) # # Next run an object detector # maxVal = afwMath.makeStatistics(psfImage, afwMath.MAX).getValue() threshold = maxVal - sigma*math.sqrt(maxVal) if threshold <= 0.0: threshold = maxVal threshold = afwDetection.Threshold(threshold) ds = afwDetection.FootprintSet(mpsfImage, threshold, "DETECTED") # # And measure it. This policy isn't the one we use to measure # Sources, it's only used to characterize this PSF histogram # psfImageConfig = measurement.SourceMeasurementConfig() psfImageConfig.slots.centroid = "centroid.sdss" psfImageConfig.slots.psfFlux = "flux.psf" psfImageConfig.slots.apFlux = "flux.naive" psfImageConfig.slots.modelFlux = None psfImageConfig.slots.instFlux = None psfImageConfig.slots.calibFlux = None psfImageConfig.slots.shape = "shape.sdss" psfImageConfig.algorithms.names = ["flags.pixel", "shape.sdss", "flux.psf", "flux.naive"] psfImageConfig.centroider.name = "centroid.sdss" psfImageConfig.algorithms["flux.naive"].radius = 3.0 psfImageConfig.validate() gaussianWidth = 1.5 # Gaussian sigma for detection convolution exposure.setPsf(algorithmsLib.DoubleGaussianPsf(11, 11, gaussianWidth)) schema = afwTable.SourceTable.makeMinimalSchema() measureSources = psfImageConfig.makeMeasureSources(schema) catalog = afwTable.SourceCatalog(schema) psfImageConfig.slots.setupTable(catalog.table) ds.makeSources(catalog) # # Show us the Histogram # if display: frame = 1 dispImage = mpsfImage.Factory(mpsfImage, afwGeom.BoxI(afwGeom.PointI(width, height), afwGeom.ExtentI(width, height)), afwImage.LOCAL) ds9.mtv(dispImage,title="PSF Selection Image", frame=frame) clumps = list() # List of clumps, to return e = None # thrown exception IzzMin = 1.0 # Minimum value for second moments IzzMax = (self._xSize/8.0)**2 # Max value ... clump r < clumpImgSize/8 # diameter should be < 1/4 clumpImgSize apFluxes = [] for i, source in enumerate(catalog): measureSources.applyWithPeak(source, exposure) if source.getCentroidFlag(): continue x, y = source.getX(), source.getY() apFluxes.append(source.getApFlux()) val = mpsfImage.getImage().get(int(x) + width, int(y) + height) psfClumpIxx = source.getIxx() psfClumpIxy = source.getIxy() psfClumpIyy = source.getIyy() if display: if i == 0: ds9.pan(x, y, frame=frame) ds9.dot("+", x, y, ctype=ds9.YELLOW, frame=frame) ds9.dot("@:%g,%g,%g" % (psfClumpIxx, psfClumpIxy, psfClumpIyy), x, y, ctype=ds9.YELLOW, frame=frame) if psfClumpIxx < IzzMin or psfClumpIyy < IzzMin: psfClumpIxx = max(psfClumpIxx, IzzMin) #psfClumpIxy = 0.0 psfClumpIyy = max(psfClumpIyy, IzzMin) if display: ds9.dot("@:%g,%g,%g" % (psfClumpIxx, psfClumpIxy, psfClumpIyy), x, y, ctype=ds9.RED, frame=frame) det = psfClumpIxx*psfClumpIyy - psfClumpIxy*psfClumpIxy try: a, b, c = psfClumpIyy/det, -psfClumpIxy/det, psfClumpIxx/det except ZeroDivisionError: a, b, c = 1e4, 0, 1e4 clumps.append(Clump(peak=val, x=x, y=y, a=a, b=b, c=c, ixx=psfClumpIxx, ixy=psfClumpIxy, iyy=psfClumpIyy)) if len(clumps) == 0: msg = "Failed to determine center of PSF clump" if e: msg += ": %s" % e raise RuntimeError(msg) # if it's all we got return it if len(clumps) == 1: return clumps # which clump is the best? # if we've undistorted the moments, stars should only have 1 clump # use the apFlux from the clump measureSources, and take the highest # ... this clump has more psf star candidate neighbours than the others. # get rid of any that are huge, and thus poorly defined goodClumps = [] for clump in clumps: if clump.ixx < IzzMax and clump.iyy < IzzMax: goodClumps.append(clump) # if culling > IzzMax cost us all clumps, we'll have to take what we have if len(goodClumps) == 0: goodClumps = clumps # use the 'brightest' clump iBestClump = numpy.argsort(apFluxes)[0] clumps = [clumps[iBestClump]] return clumps
def testZoomPan(self): ds9.pan(205, 180) ds9.zoom(4) ds9.zoom(4, 205, 180, frame=1)
def getClumps(self, sigma=1.0, display=False): if self._num <= 0: raise RuntimeError("No candidate PSF sources") psfImage = self.getImage() # # Embed psfImage into a larger image so we can smooth when measuring it # width, height = psfImage.getWidth(), psfImage.getHeight() largeImg = psfImage.Factory(afwGeom.ExtentI(2 * width, 2 * height)) largeImg.set(0) bbox = afwGeom.BoxI(afwGeom.PointI(width, height), afwGeom.ExtentI(width, height)) largeImg.assign(psfImage, bbox, afwImage.LOCAL) # # Now measure that image, looking for the highest peak. Start by building an Exposure # msk = afwImage.MaskU(largeImg.getDimensions()) msk.set(0) var = afwImage.ImageF(largeImg.getDimensions()) var.set(1) mpsfImage = afwImage.MaskedImageF(largeImg, msk, var) mpsfImage.setXY0(afwGeom.PointI(-width, -height)) del msk del var exposure = afwImage.makeExposure(mpsfImage) # # Next run an object detector # maxVal = afwMath.makeStatistics(psfImage, afwMath.MAX).getValue() threshold = maxVal - sigma * math.sqrt(maxVal) if threshold <= 0.0: threshold = maxVal threshold = afwDetection.Threshold(threshold) ds = afwDetection.FootprintSet(mpsfImage, threshold, "DETECTED") # # And measure it. This policy isn't the one we use to measure # Sources, it's only used to characterize this PSF histogram # schema = SourceTable.makeMinimalSchema() psfImageConfig = SingleFrameMeasurementConfig() psfImageConfig.slots.centroid = "base_SdssCentroid" psfImageConfig.plugins["base_SdssCentroid"].doFootprintCheck = False psfImageConfig.slots.psfFlux = None # "base_PsfFlux" psfImageConfig.slots.apFlux = "base_CircularApertureFlux_3_0" psfImageConfig.slots.modelFlux = None psfImageConfig.slots.instFlux = None psfImageConfig.slots.calibFlux = None psfImageConfig.slots.shape = "base_SdssShape" # Formerly, this code had centroid.sdss, flux.psf, flux.naive, # flags.pixel, and shape.sdss psfImageConfig.algorithms.names = [ "base_SdssCentroid", "base_CircularApertureFlux", "base_SdssShape" ] psfImageConfig.algorithms["base_CircularApertureFlux"].radii = [3.0] psfImageConfig.validate() task = SingleFrameMeasurementTask(schema, config=psfImageConfig) sourceCat = SourceCatalog(schema) gaussianWidth = 1.5 # Gaussian sigma for detection convolution exposure.setPsf(algorithmsLib.DoubleGaussianPsf(11, 11, gaussianWidth)) ds.makeSources(sourceCat) # # Show us the Histogram # if display: frame = 1 dispImage = mpsfImage.Factory( mpsfImage, afwGeom.BoxI(afwGeom.PointI(width, height), afwGeom.ExtentI(width, height)), afwImage.LOCAL) ds9.mtv(dispImage, title="PSF Selection Image", frame=frame) clumps = list() # List of clumps, to return e = None # thrown exception IzzMin = 1.0 # Minimum value for second moments IzzMax = ( self._xSize / 8.0)**2 # Max value ... clump radius should be < clumpImgSize/8 apFluxes = [] task.run( sourceCat, exposure) # notes that this is backwards for the new framework for i, source in enumerate(sourceCat): if source.getCentroidFlag(): continue x, y = source.getX(), source.getY() apFluxes.append(source.getApFlux()) val = mpsfImage.getImage().get(int(x) + width, int(y) + height) psfClumpIxx = source.getIxx() psfClumpIxy = source.getIxy() psfClumpIyy = source.getIyy() if display: if i == 0: ds9.pan(x, y, frame=frame) ds9.dot("+", x, y, ctype=ds9.YELLOW, frame=frame) ds9.dot("@:%g,%g,%g" % (psfClumpIxx, psfClumpIxy, psfClumpIyy), x, y, ctype=ds9.YELLOW, frame=frame) if psfClumpIxx < IzzMin or psfClumpIyy < IzzMin: psfClumpIxx = max(psfClumpIxx, IzzMin) psfClumpIyy = max(psfClumpIyy, IzzMin) if display: ds9.dot("@:%g,%g,%g" % (psfClumpIxx, psfClumpIxy, psfClumpIyy), x, y, ctype=ds9.RED, frame=frame) det = psfClumpIxx * psfClumpIyy - psfClumpIxy * psfClumpIxy try: a, b, c = psfClumpIyy / det, -psfClumpIxy / det, psfClumpIxx / det except ZeroDivisionError: a, b, c = 1e4, 0, 1e4 clumps.append( Clump(peak=val, x=x, y=y, a=a, b=b, c=c, ixx=psfClumpIxx, ixy=psfClumpIxy, iyy=psfClumpIyy)) if len(clumps) == 0: msg = "Failed to determine center of PSF clump" if e: msg += ": %s" % e raise RuntimeError(msg) # if it's all we got return it if len(clumps) == 1: return clumps # which clump is the best? # if we've undistorted the moments, stars should only have 1 clump # use the apFlux from the clump measurement, and take the highest # ... this clump has more psf star candidate neighbours than the others. # get rid of any that are huge, and thus poorly defined goodClumps = [] for clump in clumps: if clump.ixx < IzzMax and clump.iyy < IzzMax: goodClumps.append(clump) # if culling > IzzMax cost us all clumps, we'll have to take what we have if len(goodClumps) == 0: goodClumps = clumps # use the 'brightest' clump iBestClump = numpy.argsort(apFluxes)[0] clumps = [clumps[iBestClump]] return clumps
def testDetection(self): """Test CR detection.""" # # Subtract background # bctrl = afwMath.BackgroundControl(afwMath.Interpolate.NATURAL_SPLINE) bctrl.setNxSample(int(self.mi.getWidth() / 256) + 1) bctrl.setNySample(int(self.mi.getHeight() / 256) + 1) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) im = self.mi.getImage() try: backobj = afwMath.makeBackground(im, bctrl) except Exception as e: print >> sys.stderr, e, bctrl.setInterpStyle(afwMath.Interpolate.CONSTANT) backobj = afwMath.makeBackground(im, bctrl) im -= backobj.getImageF() if display: frame = 0 ds9.mtv(self.mi, frame=frame, title="Raw") # raw frame if self.mi.getWidth() > 256: ds9.pan(944 - self.mi.getX0(), 260 - self.mi.getY0()) # # Mask known bad pixels # measAlgorithmsDir = lsst.utils.getPackageDir('meas_algorithms') badPixels = defects.policyToBadRegionList( os.path.join(measAlgorithmsDir, "policy", "BadPixels.paf")) # did someone lie about the origin of the maskedImage? If so, adjust bad pixel list if self.XY0.getX() != self.mi.getX0() or self.XY0.getY( ) != self.mi.getY0(): dx = self.XY0.getX() - self.mi.getX0() dy = self.XY0.getY() - self.mi.getY0() for bp in badPixels: bp.shift(-dx, -dy) algorithms.interpolateOverDefects(self.mi, self.psf, badPixels) stats = afwMath.makeStatistics(self.mi.getImage(), afwMath.MEANCLIP | afwMath.STDEVCLIP) background = stats.getValue(afwMath.MEANCLIP) crConfig = algorithms.FindCosmicRaysConfig() crs = algorithms.findCosmicRays(self.mi, self.psf, background, pexConfig.makePolicy(crConfig)) if display: ds9.mtv(self.mi, frame=frame + 1, title="CRs removed") if self.mi.getWidth() > 256: ds9.pan(944 - self.mi.getX0(), 260 - self.mi.getY0()) print("Detected %d CRs" % len(crs)) if display and False: for cr in crs: bbox = cr.getBBox() bbox.shift(afwGeom.ExtentI(-self.mi.getX0(), -self.mi.getY0())) ds9.line([(bbox.getMinX() - 0.5, bbox.getMinY() - 0.5), (bbox.getMaxX() + 0.5, bbox.getMinY() - 0.5), (bbox.getMaxX() + 0.5, bbox.getMaxY() + 0.5), (bbox.getMinX() - 0.5, bbox.getMaxY() + 0.5), (bbox.getMinX() - 0.5, bbox.getMinY() - 0.5)], frame=frame + 1) if self.nCR is not None: self.assertEqual(len(crs), self.nCR)
class CosmicRayTestCase(unittest.TestCase): """A test case for Cosmic Ray detection""" def setUp(self): self.FWHM = 5 # pixels self.psf = algorithms.DoubleGaussianPsf( 29, 29, self.FWHM / (2 * sqrt(2 * log(2)))) self.mi = afwImage.MaskedImageF(imageFile) self.XY0 = afwGeom.PointI(0, 0) # origin of the subimage we use if imageFile == imageFile0: if True: # use full image, trimmed to data section self.XY0 = afwGeom.PointI(32, 2) self.mi = self.mi.Factory( self.mi, afwGeom.BoxI(self.XY0, afwGeom.PointI(2079, 4609)), afwImage.LOCAL) self.mi.setXY0(afwGeom.PointI(0, 0)) self.nCR = 1076 # number of CRs we should detect else: # use sub-image if True: self.XY0 = afwGeom.PointI(824, 140) self.nCR = 10 else: self.XY0 = afwGeom.PointI(280, 2750) self.nCR = 2 self.mi = self.mi.Factory( self.mi, afwGeom.BoxI(self.XY0, afwGeom.ExtentI(256, 256), afwImage.LOCAL)) self.mi.setXY0(afwGeom.PointI(0, 0)) else: self.nCR = None self.mi.getMask().addMaskPlane("DETECTED") def tearDown(self): del self.mi del self.psf def testDetection(self): """Test CR detection""" # # Subtract background # bctrl = afwMath.BackgroundControl(afwMath.Interpolate.NATURAL_SPLINE) bctrl.setNxSample(int(self.mi.getWidth() / 256) + 1) bctrl.setNySample(int(self.mi.getHeight() / 256) + 1) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) im = self.mi.getImage() try: backobj = afwMath.makeBackground(im, bctrl) except Exception, e: print >> sys.stderr, e, bctrl.setInterpStyle(afwMath.Interpolate.CONSTANT) backobj = afwMath.makeBackground(im, bctrl) im -= backobj.getImageF() if display: frame = 0 ds9.mtv(self.mi, frame=frame, title="Raw") # raw frame if self.mi.getWidth() > 256: ds9.pan(944 - self.mi.getX0(), 260 - self.mi.getY0()) # # Mask known bad pixels # badPixels = defects.policyToBadRegionList( os.path.join(os.environ["MEAS_ALGORITHMS_DIR"], "policy", "BadPixels.paf")) # did someone lie about the origin of the maskedImage? If so, adjust bad pixel list if self.XY0.getX() != self.mi.getX0() or self.XY0.getY( ) != self.mi.getY0(): dx = self.XY0.getX() - self.mi.getX0() dy = self.XY0.getY() - self.mi.getY0() for bp in badPixels: bp.shift(-dx, -dy) algorithms.interpolateOverDefects(self.mi, self.psf, badPixels) stats = afwMath.makeStatistics(self.mi.getImage(), afwMath.MEANCLIP | afwMath.STDEVCLIP) background = stats.getValue(afwMath.MEANCLIP) crConfig = algorithms.FindCosmicRaysConfig() crs = algorithms.findCosmicRays(self.mi, self.psf, background, pexConfig.makePolicy(crConfig)) if display: ds9.mtv(self.mi, frame=frame + 1, title="CRs removed") if self.mi.getWidth() > 256: ds9.pan(944 - self.mi.getX0(), 260 - self.mi.getY0()) print "Detected %d CRs" % len(crs) if display and False: for cr in crs: bbox = cr.getBBox() bbox.shift(afwGeom.ExtentI(-self.mi.getX0(), -self.mi.getY0())) ds9.line([(bbox.getMinX() - 0.5, bbox.getMinY() - 0.5), (bbox.getMaxX() + 0.5, bbox.getMinY() - 0.5), (bbox.getMaxX() + 0.5, bbox.getMaxY() + 0.5), (bbox.getMinX() - 0.5, bbox.getMaxY() + 0.5), (bbox.getMinX() - 0.5, bbox.getMinY() - 0.5)], frame=frame + 1) if self.nCR is not None: self.assertEqual(len(crs), self.nCR)
def makeAndMeasure(self, objFlux, alpha, b, dx=0.0, dy=0.0): """Make and measure a PSF""" xcen, ycen = 0.5*self.width + 11 + dx, 0.5*self.height + 12 + dy # # Create the PSF # psf = self.makePsf(alpha, b, self.psfFlux) # # Make the object # self.objImg = None if not self.objImg: gal = afwImage.ImageF(self.width, self.height) gal.setXY0(10, 10) obj = self.makePsf(alpha, b, objFlux).computeImage(afwGeom.PointD(xcen, ycen)) obj *= objFlux/obj.getArray().sum() if False: # requires support for gal[obj.getBBox(), afwImage.PARENT] gal[obj.getBBox(afwImage.PARENT), afwImage.PARENT] = obj.convertF() else: gal.Factory(gal, obj.getBBox(afwImage.PARENT), afwImage.PARENT)[:] <<= obj.convertF() self.objImg = afwImage.makeExposure(afwImage.makeMaskedImage(gal)) self.objImg.setPsf(psf) self.objImg.getMaskedImage().getVariance()[:] = 1.0 if display: ds9.mtv(self.objImg, frame=ds9Frame, title="%g %g" % (alpha, b)) ds9.dot("+", xcen - self.objImg.getX0(), ycen - self.objImg.getY0(), size=1, ctype=ds9.RED, frame=ds9Frame) ds9.pan(xcen - self.objImg.getX0(), ycen - self.objImg.getY0(), frame=ds9Frame) # # Do the measuring # msConfig = measAlg.SourceMeasurementConfig() msConfig.algorithms.names.add("flux.sinc") msConfig.algorithms.names.add("flux.psf") msConfig.algorithms.names.add("flux.deconvolvedPsf") msConfig.algorithms.names.remove("correctfluxes") msConfig.slots.apFlux = "flux.sinc" msConfig.algorithms["flux.deconvolvedPsf"].priority = 2.01 # i.e. run after other flux algorithms #msConfig.algorithms["flux.deconvolvedPsf"].deconvolutionKernelSigma = 0.4 msConfig.algorithms["flux.deconvolvedPsf"].coeff = self.coeff msConfig.algorithms["flux.deconvolvedPsf"].psfFlux = self.psfFlux msConfig.algorithms["flux.deconvolvedPsf"].flux0 = self.flux0 #msConfig.algorithms["flux.deconvolvedPsf"].niter = 15 #msConfig.algorithms["flux.deconvolvedPsf"].rmsTol = 1e-4 schema = afwTable.SourceTable.makeMinimalSchema() ms = msConfig.makeMeasureSources(schema) # add our fields table = afwTable.SourceTable.make(schema) msConfig.slots.setupTable(table) source = table.makeRecord() ss = afwDetection.FootprintSet(self.objImg.getMaskedImage(), afwDetection.Threshold(0.1)) feet = ss.getFootprints() assert(len(feet) > 0) fp = ss.getFootprints()[0] source.setFootprint(fp) center = afwGeom.Point2D(xcen, ycen) ms.apply(source, self.objImg, center) flux = source.get("flux.deconvolvedPsf") fluxErr = source.get("flux.deconvolvedPsf.err") flags = source.get("flux.deconvolvedPsf.flags") if display: xc, yc = xcen - self.objImg.getX0(), ycen - self.objImg.getY0() ds9.dot("x", xc, yc, ctype=ds9.MAGENTA, size=1, frame=ds9Frame) displayUtils.drawFootprint(fp, XY0=self.objImg.getXY0()) shape = source.getShape() return flux, fluxErr, flags, source.get("flux.psf")