def doTestPeaks(self, dwidth=0, dheight=0, x0=0, y0=0, threshold=10, callback=None, polarity=True, grow=0): """Worker routine for tests polarity: True if should search for +ve pixels""" self.doSetUp(dwidth, dheight, x0, y0) if not polarity: self.im *= -1 if callback: callback() # # Sort self.peaks in decreasing peak height to match Footprint.getPeaks() # for i, peaks in enumerate(self.peaks): self.peaks[i] = sorted([(x, y, self.im.getImage().get(x, y)) for x, y in peaks], lambda x, y: cmpPeaks(self.im, x, y)) threshold = afwDetect.Threshold(threshold, afwDetect.Threshold.VALUE, polarity) fs = afwDetect.makeFootprintSet(self.im, threshold, "BINNED1") self.fs = fs if grow: fs = afwDetect.makeFootprintSet(fs, grow, True) msk = self.im.getMask() afwDetect.setMaskFromFootprintList(msk, fs.getFootprints(), msk.getPlaneBitMask("DETECTED")) del msk self.checkPeaks(dwidth, dheight, frame=3)
def testGrow(self): """Grow footprints using the FootprintSet constructor""" ds = afwDetect.makeFootprintSet(self.im, afwDetect.Threshold(10)) self.assertEqual(len(ds.getFootprints()), len(self.objects)) grown = afwDetect.makeFootprintSet(ds, 1, False) self.assertEqual(len(ds.getFootprints()), len(self.objects)) self.assertGreater(len(grown.getFootprints()), 0) self.assertLessEqual(len(grown.getFootprints()), len(ds.getFootprints()))
def psf(self, exposure, sources): """Measure the PSF @param exposure Exposure to process @param sources Measured sources on exposure """ assert exposure, "No exposure provided" assert sources, "No sources provided" psfPolicy = self.config['psf'] selName = psfPolicy['selectName'] selPolicy = psfPolicy['select'].getPolicy() algName = psfPolicy['algorithmName'] algPolicy = psfPolicy['algorithm'].getPolicy() self.log.log(self.log.INFO, "Measuring PSF") # # Run an extra detection step to mask out faint stars # if False: print "RHL is cleaning faint sources" import lsst.afw.math as afwMath sigma = 1.0 gaussFunc = afwMath.GaussianFunction1D(sigma) gaussKernel = afwMath.SeparableKernel(15, 15, gaussFunc, gaussFunc) im = exposure.getMaskedImage().getImage() convolvedImage = im.Factory(im.getDimensions()) afwMath.convolve(convolvedImage, im, gaussKernel) del im fs = afwDet.makeFootprintSet(convolvedImage, afwDet.createThreshold(4, "stdev")) fs = afwDet.makeFootprintSet(fs, 3, True) fs.setMask(exposure.getMaskedImage().getMask(), "DETECTED") starSelector = measAlg.makeStarSelector(selName, selPolicy) psfCandidateList = starSelector.selectStars(exposure, sources) psfDeterminer = measAlg.makePsfDeterminer(algName, algPolicy) psf, cellSet = psfDeterminer.determinePsf(exposure, psfCandidateList) # The PSF candidates contain a copy of the source, and so we need to explicitly propagate new flags for cand in psfCandidateList: cand = measAlg.cast_PsfCandidateF(cand) src = cand.getSource() if src.getFlagForDetection() & measAlg.Flags.PSFSTAR: ident = src.getId() src = sources[ident] assert src.getId() == ident src.setFlagForDetection(src.getFlagForDetection() | measAlg.Flags.PSFSTAR) exposure.setPsf(psf) return psf, cellSet
def run(frame=6): im = afwImage.MaskedImageF(afwGeom.Extent2I(14, 10)) # # Populate the image with objects that we should detect # objects = [] objects.append([(4, 1, 10), (3, 2, 10), (4, 2, 20), (5, 2, 10), (4, 3, 10)]) objects.append([(9, 7, 30), (10, 7, 29), (12, 7, 28), (10, 8, 27), (11, 8, 26), (10, 4, -5)]) objects.append([(3, 8, 10), (4, 8, 10)]) for obj in objects: for x, y, I in obj: im.getImage().set(x, y, I) im.getVariance().set(1) im.getVariance().set(10, 4, 0.5 ** 2) # # Detect the objects at 10 counts or above # level = 10 fs = afwDetect.makeFootprintSet(im, afwDetect.Threshold(level), "DETECTED") showPeaks(im, fs, frame=frame) # # Detect the objects at -10 counts or below. N.b. the peak's at -5, so it isn't detected # polarity = False # look for objects below background threshold = afwDetect.Threshold(level, afwDetect.Threshold.VALUE, polarity) fs2 = afwDetect.makeFootprintSet(im, threshold, "DETECTED_NEGATIVE") print "Detected %d objects below background" % len(fs2.getFootprints()) # # Search in S/N (n.b. the peak's -10sigma) # threshold = afwDetect.Threshold(level, afwDetect.Threshold.PIXEL_STDEV, polarity) fs2 = afwDetect.makeFootprintSet(im, threshold) # # Here's another way to set a mask plane (we chose not to do so in the makeFootprintSet call) # msk = im.getMask() afwDetect.setMaskFromFootprintList(msk, fs2.getFootprints(), msk.getPlaneBitMask("DETECTED_NEGATIVE")) if frame is not None: ds9.mtv(msk, isMask=True, frame=frame) # # Merge the positive and negative detections, growing both sets by 1 pixel # fs.merge(fs2, 1, 1) # # Set EDGE so we can see the grown Footprints # afwDetect.setMaskFromFootprintList(msk, fs.getFootprints(), msk.getPlaneBitMask("EDGE")) if frame is not None: ds9.mtv(msk, isMask=True, frame=frame) showPeaks(fs=fs, frame=frame)
def testMergeFootprints(self): """Merge positive and negative Footprints""" x0, y0 = 5, 6 dwidth, dheight = 6, 7 def callback(): x, y, I = x0 + 10, y0 + 4, -20 self.im.getImage().set(x, y, I) peaks2.append((x, y, I)) for grow1, grow2 in [(1, 1), (3, 3), (6, 6), ]: peaks2 = [] self.doTestPeaks(threshold=10, callback=callback, grow=0, x0=x0, y0=y0, dwidth=dwidth, dheight=dheight) threshold = afwDetect.Threshold(10, afwDetect.Threshold.VALUE, False) fs2 = afwDetect.makeFootprintSet(self.im, threshold) msk = self.im.getMask() afwDetect.setMaskFromFootprintList(msk, fs2.getFootprints(), msk.getPlaneBitMask("DETECTED_NEGATIVE")) self.fs.merge(fs2, grow1, grow2) self.peaks[-2] += peaks2 if grow1 + grow2 > 2: # grow merged all peaks self.peaks[0] = sorted(sum(self.peaks, []), lambda x, y: cmpPeaks(self.im, x, y)) afwDetect.setMaskFromFootprintList(msk, self.fs.getFootprints(), msk.getPlaneBitMask("EDGE")) self.checkPeaks(frame=3)
def testMergeFootprintsEngulf(self): """Merge two Footprints when growing one Footprint totally replaces the other""" def callback(): self.im.set(0) self.peaks, self.objects = [], [] for x, y, I in [[6, 4, 20], [6, 5, 10]]: self.im.getImage().set(x, y, I) self.peaks.append([[6, 4]]) x, y, I = 8, 4, -20 self.im.getImage().set(x, y, I) peaks2.append((x, y, I)) grow1, grow2 = 0, 3 peaks2 = [] self.doTestPeaks(threshold=10, callback=callback, grow=0) threshold = afwDetect.Threshold(10, afwDetect.Threshold.VALUE, False) fs2 = afwDetect.makeFootprintSet(self.im, threshold) msk = self.im.getMask() afwDetect.setMaskFromFootprintList(msk, fs2.getFootprints(), msk.getPlaneBitMask("DETECTED_NEGATIVE")) self.fs.merge(fs2, grow1, grow2) self.peaks[0] += peaks2 self.peaks[0] = sorted(sum(self.peaks, []), lambda x, y: cmpPeaks(self.im, x, y)) afwDetect.setMaskFromFootprintList(msk, self.fs.getFootprints(), msk.getPlaneBitMask("EDGE")) self.checkPeaks(frame=3)
def testFootprints2(self): """Check that we found the correct number of objects using makeFootprintSet""" ds = afwDetect.makeFootprintSet(self.im, afwDetect.Threshold(10)) objects = ds.getFootprints() self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i])
def testFootprintsImage(self): """Check that we can search Images as well as MaskedImages""" ds = afwDetect.makeFootprintSet(self.im, afwDetect.Threshold(10)) objects = ds.getFootprints() self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i])
def threshold(image, threshold, positive, log=None): thresh = afwDet.createThreshold(threshold, "value", positive) feet = afwDet.makeFootprintSet(image, thresh) if log is not None: log.log(log.INFO, "Found %d footprints" % len(feet.getFootprints())) pixels = afwImage.ImageU(image.getDimensions()) pixels.set(0) for foot in feet.getFootprints(): foot.insertIntoImage(pixels, 1) return pixels
def testThresholdMultiplier(self): """Inclusion threshold multiplier""" thresh = 10 multiplier = 2.0 ds = afwDetect.makeFootprintSet(self.im, afwDetect.Threshold(thresh), multiplier) objects = [obj for obj in self.objects if obj.val >= thresh*multiplier] self.assertEqual(len(ds.getFootprints()), len(objects)) for obj, foot in zip(objects, ds.getFootprints()): self.assertEqual(obj, foot)
def testFootprints(self): """Check that we found the correct number of objects using makeFootprintSet""" ds = afwDetect.makeFootprintSet(self.ms, afwDetect.Threshold(10), "DETECTED") objects = ds.getFootprints() if display: ds9.mtv(self.ms, frame=0) self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i])
def writeDefects(self, maskFile, ccd, format=None): """Given a Mask, find the defects for each amp in the specified CCD (0-indexed). If format is provided, it's expected to be used as "format % (ccd, amp)" to generate a .paf filename to write the defects too. If it's "-", write to stdout""" # Metadata should have validity range keywords, but it doesn't. if False: metaData = afwImage.readMetadata(maskFile, 0) hdu = ccd + 2 im = afwImage.ImageF(maskFile, hdu) im -= 1 im *= -1 mask = afwImage.MaskU(im.getBBox(afwImage.PARENT)) mask.set(0x0) mask = afwImage.makeMaskedImage(im, mask) for amp in self.ampList(): subMask = mask.Factory(mask, self.getTrimSecBBox(amp), afwImage.LOCAL) ds = afwDetection.makeFootprintSet(subMask, afwDetection.Threshold(0.5), "INTRP") if False: ds9.setDefaultFrame(amp) ds9.mtv(subMask) ds9.dot("Amp %d" % amp, 0, 0) if not format: return if format == "-": fd = sys.stdout else: fd = open(format % (ccd, amp), "w") print >> fd, """\ #<?cfg paf policy ?> # # Defects for CCD%03d amp %02d generated from %s, HDU %d # # Coordinates are trimmed and per-amp not per-CCD. If you change this, the ISR will have to change # # Generated by $HeadURL$ # """ % (ccd, amp, maskFile, hdu), for foot in ds.getFootprints(): afwDetectionUtils.writeFootprintAsDefects(fd, foot)
def testFootprintSetImageId(self): """Check that we can insert a FootprintSet into an Image, setting relative IDs""" ds = afwDetect.makeFootprintSet(self.im, afwDetect.Threshold(10)) objects = ds.getFootprints() idImage = ds.insertIntoImage(True) if display: ds9.mtv(idImage, frame=2) for i in range(len(objects)): for sp in objects[i].getSpans(): for x in range(sp.getX0(), sp.getX1() + 1): self.assertEqual(idImage.get(x, sp.getY()), i + 1)
def testFootprintsMasks(self): """Check that detectionSets have the proper mask bits set""" ds = afwDetect.makeFootprintSet(self.ms, afwDetect.Threshold(10), "OBJECT") objects = ds.getFootprints() if display: ds9.mtv(self.ms, frame=1) mask = self.ms.getMask() for i in range(len(objects)): for sp in objects[i].getSpans(): for x in range(sp.getX0(), sp.getX1() + 1): self.assertEqual(mask.get(x, sp.getY()), mask.getPlaneBitMask("OBJECT"))
def writeDefects(self, maskFile, ccd, format=None): """Given a Mask, find the defects for each amp in the specified CCD (0-indexed). If format is provided, it's expected to be used as "format % (ccd, amp)" to generate a .paf filename to write the defects too. If it's "-", write to stdout""" # Metadata should have validity range keywords, but it doesn't. if False: metaData = afwImage.readMetadata(maskFile, 0) hdu = ccd + 2 im = afwImage.ImageF(maskFile, hdu) im -= 1 im *= -1 mask = afwImage.MaskU(im.getBBox(afwImage.PARENT)); mask.set(0x0) mask = afwImage.makeMaskedImage(im, mask) for amp in self.ampList(): subMask = mask.Factory(mask, self.getTrimSecBBox(amp), afwImage.LOCAL) ds = afwDetection.makeFootprintSet(subMask, afwDetection.Threshold(0.5), "INTRP") if False: ds9.setDefaultFrame(amp) ds9.mtv(subMask) ds9.dot("Amp %d" % amp, 0, 0) if not format: return if format == "-": fd = sys.stdout else: fd = open(format % (ccd, amp), "w") print >> fd, """\ #<?cfg paf policy ?> # # Defects for CCD%03d amp %02d generated from %s, HDU %d # # Coordinates are trimmed and per-amp not per-CCD. If you change this, the ISR will have to change # # Generated by $HeadURL$ # """ % (ccd, amp, maskFile, hdu), for foot in ds.getFootprints(): afwDetectionUtils.writeFootprintAsDefects(fd, foot)
def testFootprints(self): """Check that we found the correct number of objects using makeFootprintSet""" level = 0x2 ds = afwDetect.makeFootprintSet(self.mim.getMask(), afwDetect.createThreshold(level, "bitmask")) objects = ds.getFootprints() if 0 and display: ds9.mtv(self.mim, frame=0) self.assertEqual(len(objects), len([o for o in self.objects if (o.val & level)])) i = 0 for o in self.objects: if o.val & level: self.assertEqual(o, objects[i]) i += 1
def testFootprints3(self): """Check that we found the correct number of objects using makeFootprintSet and PIXEL_STDEV""" threshold = 4.5 # in units of sigma self.ms.set(2, 4, (10, 0x0, 36)) # not detected (high variance) y, x = self.objects[2].spans[0][0:2] self.ms.set(x, y, (threshold, 0x0, 1.0)) ds = afwDetect.makeFootprintSet(self.ms, afwDetect.createThreshold(threshold, "pixel_stdev"), "OBJECT") objects = ds.getFootprints() self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i])
def testGrow2(self): """Grow some more interesting shaped Footprints. Informative with display, but no numerical tests""" #Can't set mask plane as the image is not a masked image. ds = afwDetect.makeFootprintSet(self.im, afwDetect.Threshold(10)) idImage = afwImage.ImageU(self.im.getDimensions()) idImage.set(0) i = 1 for foot in ds.getFootprints()[0:1]: gfoot = afwDetect.growFootprint(foot, 3, False) gfoot.insertIntoImage(idImage, i) i += 1 if display: ds9.mtv(self.im, frame=0) ds9.mtv(idImage, frame=1)
def testFootprintsImageId(self): """Check that we can insert footprints into an Image""" ds = afwDetect.makeFootprintSet(self.im, afwDetect.Threshold(10)) objects = ds.getFootprints() idImage = afwImage.ImageU(self.im.getDimensions()) idImage.set(0) for foot in objects: foot.insertIntoImage(idImage, foot.getId()) if False: ds9.mtv(idImage, frame=2) for i in range(len(objects)): for sp in objects[i].getSpans(): for x in range(sp.getX0(), sp.getX1() + 1): self.assertEqual(idImage.get(x, sp.getY()), objects[i].getId())
def testSetFromFootprint(self): """Test setting mask/image pixels from a Footprint list""" mi = afwImage.MaskedImageF(afwGeom.Extent2I(12, 8)) im = mi.getImage() # # Objects that we should detect # self.objects = [] self.objects += [Object(10, [(1, 4, 4), (2, 3, 5), (3, 4, 4)])] self.objects += [Object(20, [(5, 7, 8), (5, 10, 10), (6, 8, 9)])] self.objects += [Object(20, [(6, 3, 3)])] im.set(0) # clear image for obj in self.objects: obj.insert(im) if False and display: ds9.mtv(mi, frame=0) ds = afwDetect.makeFootprintSet(mi, afwDetect.Threshold(15)) objects = ds.getFootprints() afwDetect.setMaskFromFootprintList(mi.getMask(), objects, 0x1) self.assertEqual(mi.getMask().get(4, 2), 0x0) self.assertEqual(mi.getMask().get(3, 6), 0x1) self.assertEqual(mi.getImage().get(3, 6), 20) afwDetect.setImageFromFootprintList(mi.getImage(), objects, 5.0) self.assertEqual(mi.getImage().get(4, 2), 10) self.assertEqual(mi.getImage().get(3, 6), 5) if False and display: ds9.mtv(mi, frame=1) # # Check Footprint.contains() while we are about it # self.assertTrue(objects[0].contains(afwGeom.Point2I(7, 5))) self.assertFalse(objects[0].contains(afwGeom.Point2I(10, 6))) self.assertFalse(objects[0].contains(afwGeom.Point2I(7, 6))) self.assertFalse(objects[0].contains(afwGeom.Point2I(4, 2))) self.assertTrue(objects[1].contains(afwGeom.Point2I(3, 6)))
def testInf(self): """Test detection for images with Infs""" im = afwImage.MaskedImageF(afwGeom.Extent2I(10, 20)) im.set(0) import numpy for x in range(im.getWidth()): im.set(x, im.getHeight() - 1, (numpy.Inf, 0x0, 0)) ds = afwDetect.makeFootprintSet(im, afwDetect.createThreshold(100)) objects = ds.getFootprints() afwDetect.setMaskFromFootprintList(im.getMask(), objects, 0x10) if display: ds9.mtv(im) self.assertEqual(len(objects), 1)
im = 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() # # Find sources # threshold = afwDetect.Threshold(5, afwDetect.Threshold.STDEV) npixMin = 5 # we didn't smooth fs = afwDetect.makeFootprintSet(mi, threshold, "DETECTED", npixMin) grow, isotropic = 1, False fs = afwDetect.makeFootprintSet(fs, grow, isotropic) fs.setMask(mi.getMask(), "DETECTED") return mi, fs #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def SpatialCellSetDemo(filename=None): """A demonstration of the use of a SpatialCellSet""" im, fs = readImage(filename) if display: ds9.mtv(im, frame=0, title="Input")
def testGC(self): """Check that FootprintSets are automatically garbage collected (when MemoryTestCase runs)""" ds = afwDetect.makeFootprintSet(afwImage.MaskedImageF(afwGeom.Extent2I(10, 20)), afwDetect.Threshold(10))
t1.getPosition()[0], t2.getPosition()[0], t3.getPosition()[0]) minDec = min(t0.getPosition()[1], t1.getPosition()[1], t2.getPosition()[1], t3.getPosition()[1]) maxDec = max(t0.getPosition()[1], t1.getPosition()[1], t2.getPosition()[1], t3.getPosition()[1]) if eFile.startswith('eimage'): # There shouldn't be many sources in negative print 'Making negative footprint detections.' detSetN = afwDetection.makeFootprintSet( useEImForBG, afwDetection.createThreshold(5, 'stdev', False)) footprintsN = detSetN.getFootprints() if len(footprintsN) > 0: raise RuntimeError, '*** Unexpected negative source.' else: print ' No negative footprints found, as expected.' regOut = open(outDir + 'pDet.reg', 'w') print 'Making positive footprint detections.' detSetP = afwDetection.makeFootprintSet( useEImForBG, afwDetection.createThreshold(5, "stdev")) footprintsP = detSetP.getFootprints() nf = len(footprintsP) detxs = [] detys = [] nCts = []
t1 = wcs.pixelToSky(eIm.getWidth(), 0) t2 = wcs.pixelToSky(0, eIm.getHeight()) t3 = wcs.pixelToSky(eIm.getWidth(), eIm.getHeight()) minRA = min(t0.getPosition()[0], t1.getPosition()[0], t2.getPosition()[0], t3.getPosition()[0]) maxRA = max(t0.getPosition()[0], t1.getPosition()[0], t2.getPosition()[0], t3.getPosition()[0]) minDec = min(t0.getPosition()[1], t1.getPosition()[1], t2.getPosition()[1], t3.getPosition()[1]) maxDec = max(t0.getPosition()[1], t1.getPosition()[1], t2.getPosition()[1], t3.getPosition()[1]) if eFile.startswith('eimage'): # There shouldn't be many sources in negative print 'Making negative footprint detections.' detSetN = afwDetection.makeFootprintSet(useEImForBG, afwDetection.createThreshold(5, 'stdev', False)) footprintsN = detSetN.getFootprints() if len(footprintsN) > 0: raise RuntimeError, '*** Unexpected negative source.' else: print ' No negative footprints found, as expected.' regOut = open(outDir + 'pDet.reg', 'w') print 'Making positive footprint detections.' detSetP = afwDetection.makeFootprintSet(useEImForBG, afwDetection.createThreshold(5, "stdev")) footprintsP = detSetP.getFootprints() nf = len(footprintsP) detxs = []; detys = []; nCts = []; estSizePix = [] n = 0; boxSize = 2; circleSize = 20 print 'Considering %i positive footprints.' % len(footprintsP) fAllFPP = open(outDir + 'fAllFPP.reg', 'w') for fp in footprintsP:
def findMatchingFootprints(eIm, eHDUList, wcs, ra, dec, rmags, baRatio, objId, option, a_disk, b_disk, a_bulge, b_bulge, diskFluxNorm, bulgeFluxNorm, pa_d, raEdge, decEdge, dxMin, dyMin, matchArcsec, plotno, ePath): # Get the set of footprints from the FITS image, setting the # threshold by either count value or STDEV. footprintsP is the list # of positive footprints for that particular FITS file, con- # sisting of a set of pixels. getFootprints() returns the # footprints of detected objects. # Don't set the detection limit too bright, or sources will # sometimes be missed. detSetP = afwDetection.makeFootprintSet( eIm, afwDetection.createThreshold(2., 'value')) #eIm, afwDetection.createThreshold(28., 'stdev')) footprintsP = detSetP.getFootprints() nf = len(footprintsP) b1 = 1.999*1 - 0.327 b4 = 1.999*4 - 0.327 detxs = []; detys = []; nCts = []; estSizePix = [] detMinx = []; detMaxx = []; detMiny = []; detMaxy = [] detMaxRad2 = [] n = 0; boxSize = 2 minCtsBrightThresh = 1000 #print 'Considering %i positive footprints.' % len(footprintsP) for fp in footprintsP: if n % 10000 == 0: print '%i of %i positive footprints analyzed.' % (n, nf) # Return "a list of BBoxs whose union contains exactly the pixels in # foot, neither more or less." # This looks at each boundary box in the list of boundary boxes (bboxes) # and gets the minimum and maximum x and y values of the list of coordinates, # and calculates the x and y lengths of the boundary box (dx, dy). # Lots of times they're only 1 pixel in length. fAllFPP is a file # containing the center x,y coordinates of each footprint, as well as dx and dy. # minx, maxx, miny, and maxy will be the very minimum and maximum values of # all the footprints for all the boundary boxes in the list. Create a # rectangular footprint: bboxes = afwDetection.footprintToBBoxList(fp) minx = 1e100; maxx = -1e100; miny = 1e100; maxy = -1e100 for bbox in bboxes: x0, y0 = bbox.getMinX(), bbox.getMinY() x1, y1 = bbox.getMaxX(), bbox.getMaxY() dx = x1 - x0; dy = y1 - y0 minx = min([minx, x0, x1]); maxx = max([maxx, x0, x1]) miny = min([miny, y0, y1]); maxy = max([maxy, y0, y1]) oldminx = minx; oldmaxx = maxx oldminy = miny; oldmaxy = maxy # The footprint regions are sometimes skewed, so center them # as best we can by finding the maximum pixel and then weighting # around that. # eIm.get(x,y) returns the number of counts (t0) in that pixel. # DS9 uses 1-based coords, so add 1 highPixx = -1; highPixy = -1; highPixVal = -1.e100 for x in range(minx, maxx+1): for y in range(miny, maxy+1): t0 = eIm.get(x, y) if t0 > highPixVal: highPixx = x; highPixy = y; highPixVal = t0 # Now we know the max pixel. Work in an aperture around it. Use the # footprints to set the maximum extent of the aperture. # Check to make sure the distance of the pixel in question is equal # to or less that the maximum radius of the aperture. # ctsWtSumx(or y) is the weighted center coordinate of the object # in the x (or y) direction. # detxs is a list of ctsWtSumx for each footprint. # Only keep the eImages that are above a minimum brightness threshold # and above a minimum x or y width in terms of pixels. tCts = 0; ctsWtSumx = 0; ctsWtSumy = 0; nPix = 0 t0 = (maxx - highPixx)**2 t1 = (minx - highPixx)**2 maxx2 = max(t0, t1) t0 = (maxy - highPixy)**2 t1 = (miny - highPixy)**2 maxy2 = max(t0, t1) maxRad2 = maxx2 + maxy2 dx = abs(maxx - minx) dy = abs(maxy - miny) if dx >= dxMin or dy >= dyMin: for x in range(minx, maxx+1): for y in range(miny, maxy+1): r2 = (x-highPixx)**2 + (y-highPixy)**2 if r2 > maxRad2: continue t0 = eIm.get(x, y) tCts += t0 ctsWtSumx += x * t0; ctsWtSumy += y * t0 nPix += 1 if tCts > minCtsBrightThresh: ctsWtSumx /= float(tCts); ctsWtSumy /= float(tCts) # Now iterate it again over a smaller region to improve # your chances of hitting the center. minx = int(ctsWtSumx - dx/5.); maxx = int(ctsWtSumx + dx/5.) miny = int(ctsWtSumy - dy/5.); maxy = int(ctsWtSumy + dy/5.) if maxx > 3999: maxx = 3999 if minx < 1: minx = 0 if maxy > 4071: maxy = 4071 if miny < 1: miny = 0 highPixx = -1; highPixy = -1; highPixVal = -1.e100 for x in range(minx, maxx+1): for y in range(miny, maxy+1): t0 = eIm.get(x, y) if t0 > highPixVal: highPixx = x; highPixy = y; highPixVal = t0 tCts = 0; ctsWtSumx = 0; ctsWtSumy = 0; nPix = 0 t0 = (maxx - highPixx)**2 t1 = (minx - highPixx)**2 maxx2 = max(t0, t1) t0 = (maxy - highPixy)**2 t1 = (miny - highPixy)**2 maxy2 = max(t0, t1) maxRad2 = maxx2 + maxy2 for x in range(minx, maxx+1): for y in range(miny, maxy+1): r2 = (x-highPixx)**2 + (y-highPixy)**2 if r2 > maxRad2: continue t0 = eIm.get(x, y) tCts += t0 ctsWtSumx += x * t0; ctsWtSumy += y * t0 nPix += 1 ctsWtSumx /= float(tCts); ctsWtSumy /= float(tCts) minx = oldminx maxx = oldmaxx miny = oldminy maxy = oldmaxy t0 = (maxx - ctsWtSumx)**2 t1 = (minx - ctsWtSumx)**2 maxx2 = max(t0, t1) t0 = (maxy - ctsWtSumy)**2 t1 = (miny - ctsWtSumy)**2 maxy2 = max(t0, t1) maxRad2 = maxx2 + maxy2 detxs.append(ctsWtSumx); detys.append(ctsWtSumy) nCts.append(tCts); estSizePix.append(nPix) detMinx.append(int(ctsWtSumx-dx/2.)); detMaxx.append(int(ctsWtSumx+dx/2.)) detMiny.append(int(ctsWtSumy-dy/2.)); detMaxy.append(int(ctsWtSumy+dy/2.)) detMaxRad2.append(maxRad2) n += 1 # At this point you have data for bright enough, wide enough footprints. detxs = numpy.array(detxs); detys = numpy.array(detys) nCts = numpy.array(nCts); estSizePix = numpy.array(estSizePix) detMinx = numpy.array(detMinx); detMaxx = numpy.array(detMaxx) detMiny = numpy.array(detMiny); detMaxy = numpy.array(detMaxy) #brightRAs = numpy.zeros(len(detxs)) #brightDecs = numpy.zeros(len(detxs)) brightRAs = wcs.pixelToSky(detxs, detys).getPosition()[0] brightDecs = wcs.pixelToSky(detxs, detys).getPosition()[1] # for each value of your original coordinates of interest, # create a list (t0) of the square of the distance between each bright # coordinate and the galaxy coordinates. t1 is the index of the minimum distance # squared, so t0[t1] is the minimum distance squared. The match to your # coordinates is brightRAs[t1] and BrightDecs[t1]. #matchDistArcsec = numpy.zeros(len(ra))id psi = [] psiFit = [] psiCatRaDec = [] psiCatXY = [] psiImageRaDec = [] psiImageXY = [] pa_d = [] aFit = [] bFit = [] baRatioFit = [] idx = [] tidx = [] distArcsec = [] gal_code = ['Lowba_bulge_Only', 'Lowba_disk_Only', 'Lowba_bulge_and_Disk'] #gal_code = ['Bulge_Only', 'Disk_Only', 'Bulge_and_Disk'] for i in range(len(ra)): # Assuming distance is small, keep it linear t0 = (brightRAs - ra[i])**2 + (brightDecs - dec[i])**2 t1 = numpy.argmin(t0) diffArcsec = numpy.sqrt(t0[t1]) * 3600. if diffArcsec <= matchArcsec: idx.append(i) tidx.append(t1) distArcsec.append(diffArcsec) ra = ra[idx] dec = dec[idx] raEdge = raEdge[idx] decEdge = decEdge[idx] raCat = raEdge - ra decCat = decEdge - dec psiCatRaDec.append(positionAngle(raCat, decCat)) xyCtrCat = wcs.skyToPixel(ra, dec) xCtrCat, yCtrCat = xyCtrCat xyPixPos = wcs.skyToPixel(raEdge, decEdge) xPixPos, yPixPos = xyPixPos xCat = xPixPos - xCtrCat yCat = yPixPos - yCtrCat psiCatXY.append(positionAngle(xCat, yCat)) distArcsec = numpy.array(distArcsec) brightRAs = brightRAs[tidx] brightDecs = brightDecs[tidx] ra = ra[idx] dec = dec[idx] raEdge = raEdge[idx] decEdge = decEdge[idx] detMinx = detMinx[tidx] detMaxx = detMaxx[tidx] detMiny = detMiny[tidx] detMaxy = detMaxy[tidx] xwidth = abs(detMaxx - detMinx) ywidth = abs(detMaxy - detMiny) detxs = detxs[tidx] detys = detys[tidx] pa_d = pa_d[idx] Rad2Max = max((xwidth/2.)**2, (ywidth/2.)**2) nbins = int(max(xwidth/2., ywidth/2.)) rmags = rmags[idx] baRatio = baRatio[idx] option = option[idx] objId = objId[idx] a_disk = a_disk[idx] b_disk = b_disk[idx] a_bulge = a_bulge[idx] #for m in range(nbins[i]): b_bulge = b_bulge[idx] diskFluxNorm = diskFluxNorm[idx] bulgeFluxNorm = bulgeFluxNorm[idx] # Now you've got the object and its radius. To calculate the flux as a # function of radius, I(r), break the radius squared into multiple segments # and bin the number of counts. Then divide the total number of counts # in each bin by the area, if you want. print 'len(detxs), len(objId), len(rmags), len(a_disk), len(detMinx), len(detMaxy): ' print len(detxs), len(objId), len(rmags), len(a_disk), len(detMinx), len(detMaxy) for i in range(len(detxs)): if i != -1: print 'Galaxy ID: ', objId[i] print 'rmags: ', rmags[i] print 'a_disk: ', a_disk[i] print 'b_disk: ', b_disk[i] print 'a_bulge: ', a_bulge[i] print 'b_bulge: ', b_bulge[i] print 'diskFluxNorm: ', diskFluxNorm[i] print 'bulgeFluxNorm: ', bulgeFluxNorm[i] print 'detMinx: ', detMinx[i] print 'detMaxx: ', detMaxx[i] print 'detMiny: ', detMiny[i] print 'detMaxy: ', detMaxy[i] print 'pa_d: ', pa_d[i] print 'detxs: ', detxs[i] print 'detys: ', detys[i] print 'ra (cat): ', ra[i] print 'dec (cat): ', dec[i] print 'raEdge, decEdge: ', raEdge[i], decEdge[i] print 'psiCatXY: xPixPos, xCtrCat, yPixPos, yCtrCat' print xPixPos[i], xCtrCat[i], yPixPos[i], yCtrCat[i] tCts = numpy.zeros(nbins[i]) I_R = numpy.zeros(nbins[i]) nPix = numpy.zeros(nbins[i]) mew = numpy.zeros(nbins[i]) rErr = numpy.zeros(nbins[i]) Err_Up = numpy.zeros(nbins[i]) Err_Dn = numpy.zeros(nbins[i]) a2Bin = numpy.zeros(nbins[i]) aBin = numpy.zeros(nbins[i]) AveABin = numpy.zeros(nbins[i]) xBdry = [] yBdry = [] ellipticity = b_disk[i]/a_disk[i] # Create an image plot for each footprint. C = numpy.zeros(((detMaxy[i]-detMiny[i]+1), (detMaxx[i]-detMinx[i]+1)), numpy.int) for y in range (detMiny[i], detMaxy[i], 1): for x in range(detMinx[i], detMaxx[i], 1): C[y-detMiny[i], x-detMinx[i]] = eIm.get(x,y) # Find the boundaries of an eimage using the pixel count threshold # as the discriminator. Break the eimage into anglar bins (say, # 50,so the distant outliers are less likely to be included)and # select the minimum value in each bin. The original purpose was # to get data points for fitting ellipses to galactic disks. n = 50 deltaAng = 2.*math.pi/float(n) xBdry = [] yBdry = [] theta = [] radDist2 = [] xVal = [] yVal = [] angleDeg = [] for j in range(n): radDist2.append([]) xVal.append([]) yVal.append([]) angleDeg.append([]) # This section is devoted to finding psi, the angle of # the ellipse's rotation CCW with respect to the positive # x-axis countMin = 12 count = 0 for x in range(detMinx[i] + 1, detMaxx[i]-1, 1): xp = float(x - detMinx[i]) for y in range(detMiny[i], detMaxy[i], 1): yp = float(y - detMiny[i]) if C[yp, xp] < countMin: if C[yp, xp-1] < countMin or C[yp, xp+1] < countMin: y0 = float(y) - detys[i] x0 = float(x) - detxs[i] Angle = xyPosAngle(x0, y0) m = int(Angle/deltaAng) radDist2[m].append(x0**2 + y0**2) xVal[m].append(xp) yVal[m].append(yp) angleDeg[m].append(Angle*180./math.pi) for j in range(n): if len(radDist2[j]) >= 1.: t1 = numpy.argmin(radDist2[j]) xBdry.append(xVal[j][t1]) yBdry.append(yVal[j][t1]) theta.append(angleDeg[j][t1]) z, a, b, psiAve = fitellipse([xBdry, yBdry]) aFit.append(a) bFit.append(b) if a >= b and a != None and b !=None: baRatioFit.append(b/a) elif b > a and a != None and b !=None: baRatioFit.append(a/b) else: baRatioFit.append(None) if psiAve != None: psiFit.append(float(psiAve)*180./math.pi) else: psiFit.append(None) print 'psiFit: ', psiFit[i] if a and b and psiAve and z != None: xEllipse, yEllipse = ellipse(aFit[-1], bFit[-1], psiAve, detxs[i]-detMinx[i], detys[i]-detMiny[i]) daMax2 = a*a/float(nbins[i]) else: print 'a, b, psiAve, or z = None for i = ', i, a, b, psiAve, z psiImageXY.append(None) psiImageRaDec.append(None) print 'psiImageXY, psiImageRaDec: ', psiImageXY[i], psiImageRaDec[i] continue xMajor = aFit[-1]*math.cos(psiAve) + detxs[i]-detMinx[i] yMajor = aFit[-1]*math.sin(psiAve) + detys[i]-detMiny[i] print 'xMajor, yMajor = ', xMajor, yMajor x0 = xMajor - detxs[i] y0 = yMajor - detys[i] psiImageXY.append(positionAngle(x0, y0)) ra3 = wcs.pixelToSky(xMajor, yMajor).getPosition()[0] dec3 = wcs.pixelToSky(xMajor, yMajor).getPosition()[1] print 'ra3, brightRAs[i], dec3, brightDecs[i] = ', ra3, brightRAs[i], brightDecs[i], dec3 xyMajor3 = wcs.skyToPixel(ra3, dec3) xMajor3, yMajor3 = xyMajor3 print "xMajor3, yMajor3 = ", xMajor3, yMajor3 xyMajor2 = wcs.skyToPixel(raEdge[i], decEdge[i]) xMajor2, yMajor2 = xyMajor2 print 'brightRAs[i], brightDecs[i]:' print brightRAs[i], brightDecs[i] ra0 = ra3 - brightRAs[i] dec0 = dec3 - brightDecs[i] psiImageRaDec.append(positionAngle(ra0, dec0)) t0 = 0. for m in range(nbins[i]): t0 += daMax2 a2Bin[m] = t0 aBin[m] = math.sqrt(t0) AveABin[0] = 10.**(math.log10(aBin[0])/2.) for m in range(nbins[i]-1): Ave = (math.log10(aBin[m+1]) + math.log10(aBin[m]))/2. AveABin[m+1] = 10.**Ave xbin = [] ybin = [] for x in range(detMinx[i], detMaxx[i]+1): for y in range(detMiny[i], detMaxy[i]+1): xprime = x - detxs[i] yprime = y - detys[i] aXY2 = (xprime*math.cos(psiAve) + yprime*math.sin(psiAve ))**2 + (xprime*math.sin(psiAve) - yprime*math.cos(psiAve)/(b/a))**2 if aXY2 > a*a: continue nval = min(int(aXY2/daMax2), nbins[i]-1) tCts[nval] += eIm.get(x,y) nPix[nval] += 1 if nval <= 4: xbin.append(x - detMinx[i]) ybin.append(y - detMiny[i]) sumCts = 0 sumPix = 0 for m in range(nbins[i]): sumCts += tCts[m] sumPix += nPix[m] #mew, the mean, is in counts/pixel mew[m] = tCts[m]/nPix[m] for m in range(nbins[i]): # I(R) in units of counts per square arcsec: if mew[m] == 0: I_R[m] = numpy.nan else: I_R[m] = mew[m]/.04 rErr[m] = math.sqrt(tCts[m])/nPix[m]/.04 I_Reff = max(I_R)/math.e for m in range(nbins[i]): if I_R[m] < I_Reff: R_eff = 10**(math.log10(AveABin[m]) - (math.log10(I_R[m]) - math.log10(I_Reff))/(math.log10(I_R[m]) - math.log10(I_R[m-1]))*(math.log10(AveABin[m]) - math.log10(AveABin[m-1]))) break print 'xwidth, ywidth (in pixels) = ', abs(detMaxx[i] - detMinx[i]), abs(detMaxy[i] - detMiny[i]) print 'Total Counts = %i, Total Pixels = %i' % (sumCts, sumPix) print 'log_Radius(") log_Intensity n = 1 and 4 n = 1 n = 4 Pixels Counts Mean Sigma' #Prepare Sersic n=1 and n = 4 model profiles for comparison In1 = numpy.zeros(nbins[i]) In4 = numpy.zeros(nbins[i]) InBoth = numpy.zeros(nbins[i]) for m in range(nbins[i]): In1[m] = I_Reff*math.exp(-b1*((AveABin[m]/R_eff) - 1)) In4[m] = I_Reff*math.exp(-b4*(((AveABin[m]/R_eff)**0.25) - 1)) InBoth[m] = (diskFluxNorm[i]*In1[m] + bulgeFluxNorm[i]*In4[m])/(diskFluxNorm[i] + bulgeFluxNorm[i]) for m in range(nbins[i]): # Convert pixels to arcsec (0.2 arcsec/pixel, roughly) AveABin[m] = math.log10(AveABin[m]*.2) if I_R[m] != None: Err_Up[m] = math.log10(I_R[m] + rErr[m]) - math.log10(I_R[m]) if I_R[m] > rErr[m]: Err_Dn[m] = math.log10(I_R[m]) - math.log10(I_R[m] - rErr[m]) else: Err_Dn[m] = 5 I_R[m] = math.log10(I_R[m]) if In1[m] != 0.: In1[m] = math.log10(In1[m]) else: In1[m] = numpy.nan if In4[m] != 0.: In4[m] = math.log10(In4[m]) else: In4[m] = numpy.nan if InBoth[m] != 0.: InBoth[m] = math.log10(InBoth[m]) else: InBoth[m] = numpy.nan if m > 8 and I_R[m] is 'nan' and I_R[m-1] is 'nan' and I_R[m-2] is 'nan' and I_R[m-3] is 'nan': nbins[i] = nbins[:(nbins[i]-m+1)] for m in range(nbins[i]): print '%11.2f %11.2f %11.2f %11.2f %11.2f %11.2f %11.2f %11.2f %11.2f' % (AveABin[m], I_R[m], InBoth[m], In1[m], In4[m], nPix[m], tCts[m], mew[m], rErr[m]) fig = plt.figure() fig.suptitle('Galaxy %s, (ra,dec)=(%5.2f, %5.2f), %d pixels \n%d counts; Gal_ID %s R_eff = %5.2f arcsecs, PA = %5.2f deg.\n%s' %(gal_code[option[i]], brightRAs[i], brightDecs[i], sumPix, sumCts, objId[i], R_eff*.2, pa_d[i], ePath), fontsize=9) ax = fig.add_subplot(121) im = plt.imshow(C, aspect ='equal', origin='lower', cmap = plt.cm.gray, interpolation = 'nearest') cir = Circle((detxs[i]-detMinx[i],detys[i]-detMiny[i]), radius = .25, ec='r', fc = 'r') cir2 = Circle((xMajor, yMajor), radius = .25, ec='g', fc = 'g') print 'semi-major axis direction at (', xMajor, ', ', yMajor, ')' ax.add_patch(cir) ax.add_patch(cir2) line5, = ax.plot(xBdry, yBdry, 'r.') line6, = ax.plot(xEllipse, yEllipse, 'm.') line7, = ax.plot(xbin, ybin, 'y.') xcolname = 'log [Radius (arcsec)]' ycolname = 'Intensity (Log_10[Counts/Area])' ax2 = fig.add_subplot(122) plt.xlabel(xcolname, fontsize=10) plt.ylabel(ycolname, fontsize=10) line1 = ax2.errorbar(AveABin, I_R, yerr=[Err_Dn, Err_Up], fmt = 'bo', ms = 2) line2, = ax2.plot(AveABin, In1, 'm--') line3, = ax2.plot(AveABin, In4, 'g-.') line4, = ax2.plot(AveABin, InBoth, 'r-') props = font_manager.FontProperties(size=12) leg = ax2.legend([line1[0], line2, line3, line4], ['eImage', 'n=1', 'n=4', 'n=1+4'], loc='upper right', prop=props) plt.text(0.1, 0.1, 'r = %5.2f\nb/a = %5.3f' % (rmags[i], baRatio[i]), transform = ax2.transAxes) plt.savefig('%s/Sers70cM12%sh.png' % (gal_code[option[i]], objId[i]), format = 'png') plotno += 1 plt.clf() print 'Length of the following variables:' print len(detxs), len(detys), len(xPixPos), len(yPixPos), len(psiImageXY), len(psiImageRaDec), len(psiCatXY), len(psiCatRaDec), len(psiFit), len(a_disk), len(b_disk), len(aFit), len(bFit) print 'objId ra2-raEdge dec2-decEdge detxs detys xPixPos yPixPos a_disk b_disk a b b/a catalog b/a fit' for i in range(len(detxs)): if aFit[i] and bFit[i] and a_disk[i] and b_disk[i] and psiFit[i] != None: print '%8i %7.2e %7.2e %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f' % (objId[i], ra2[i]-raEdge[i], dec2[i]-decEdge[i], detxs[i], detys[i], xPixPos[i], yPixPos[i], a_disk[i], b_disk[i], aFit[i], bFit[i], b_disk[i]/a_disk[i], bFit[i]/aFit[i]) print 'objId pa_d psiCatRD psiImRD psiCatXY psiImXY psiFit b/a cat b/a fit' for i in range(len(detxs)): if aFit[i] and bFit[i] and a_disk[i] and b_disk[i] and psiFit[i] != None: print '%8i %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f' % (objId[i], pa_d[i], psiCatRaDec[i], psiImageRaDec[i], psiCatXY[i], psiImageXY[i], psiFit[i], b_disk[i]/a_disk[i], bFit[i]/aFit[i]) return plotno
def detectFootprints(exposure, positiveThreshold, psf=None, negativeThreshold=None, npixMin=1): """Detect sources above positiveThreshold in the provided exposure returning the detectionSet. Only sources with at least npixMin are considered If negativeThreshold, return a pair of detectionSets, dsPositive, dsNegative """ assert positiveThreshold or negativeThreshold # or both if positiveThreshold: positiveThreshold = afwDetection.Threshold(positiveThreshold) if negativeThreshold: negativeThreshold = afwDetection.Threshold(negativeThreshold) # # Unpack variables # maskedImage = exposure.getMaskedImage() if not psf: # no need to convolve if we don't know the PSF convolvedImage = maskedImage goodBBox = maskedImage.getBBox() else: convolvedImage = maskedImage.Factory(maskedImage.getBBox()) if display: afwDisplay.Display().mtv(maskedImage) # # Smooth the Image # psf.convolve(convolvedImage, maskedImage, convolvedImage.getMask().getMaskPlane("EDGE")) # # Only search psf-smooth part of frame # goodBBox = psf.getKernel().shrinkBBox(maskedImage.getBBox()) middle = convolvedImage.Factory(convolvedImage, goodBBox) dsNegative = None if negativeThreshold is not None: # detect negative sources dsNegative = afwDetection.makeDetectionSet(middle, negativeThreshold, "DETECTED_NEGATIVE", npixMin) if not afwDisplay.getMaskPlaneColor("DETECTED_NEGATIVE"): afwDisplay.setMaskPlaneColor("DETECTED_NEGATIVE", afwDisplay.CYAN) dsPositive = None if positiveThreshold is not None: dsPositive = afwDetection.makeFootprintSet(middle, positiveThreshold, "DETECTED", npixMin) # # ds only searched the middle but it belongs to the entire MaskedImage # dsPositive.setRegion(maskedImage.getBBox()) if dsNegative: dsNegative.setRegion(maskedImage.getBBox()) # # We want to grow the detections into the edge by at least one pixel so that it sees the EDGE bit # grow, isotropic = 1, False dsPositive = afwDetection.FootprintSetF(dsPositive, grow, isotropic) dsPositive.setMask(maskedImage.getMask(), "DETECTED") if dsNegative: dsNegative = afwDetection.FootprintSetF(dsNegative, grow, isotropic) dsNegative.setMask(maskedImage.getMask(), "DETECTED_NEGATIVE") # # clean up # del middle if negativeThreshold: if positiveThreshold: return dsPositive, dsNegative return dsPositive, dsNegative else: return dsPositive