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.FootprintSet(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.FootprintSet(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.FootprintSet(im, threshold) # # Here's another way to set a mask plane (we chose not to do so in the FootprintSet 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 setUp(self): """Build up three different sets of objects that are to be merged""" pos1 = [(40, 40), (220, 35), (40, 48), (220, 50), (67, 67), (150, 50), (40, 90), (70, 160), (35, 255), (70, 180), (250, 200), (120, 120), (170, 180), (100, 210), (20, 210), ] pos2 = [(43, 45), (215, 31), (171, 258), (211, 117), (48, 99), (70, 160), (125, 45), (251, 33), (37, 170), (134, 191), (79, 223), (258, 182) ] pos3 = [(70, 170), (219, 41), (253, 173), (253, 192)] box = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Point2I(300, 300)) psfsig = 1. kernelSize = 41 flux = 1000 # Create a different sized psf for each image and insert them at the # desired positions im1 = afwImage.MaskedImageD(box) psf1 = afwDetect.GaussianPsf(kernelSize, kernelSize, psfsig) im2 = afwImage.MaskedImageD(box) psf2 = afwDetect.GaussianPsf(kernelSize, kernelSize, 2*psfsig) im3 = afwImage.MaskedImageD(box) psf3 = afwDetect.GaussianPsf(kernelSize, kernelSize, 1.3*psfsig) insertPsf(pos1, im1, psf1, kernelSize, flux) insertPsf(pos2, im2, psf2, kernelSize, flux) insertPsf(pos3, im3, psf3, kernelSize, flux) schema = afwTable.SourceTable.makeMinimalSchema() self.idFactory = afwTable.IdFactory.makeSimple() self.table = afwTable.SourceTable.make(schema, self.idFactory) # Create SourceCatalogs from these objects fp1 = afwDetect.FootprintSet( im1, afwDetect.Threshold(0.001), "DETECTED") self.catalog1 = afwTable.SourceCatalog(self.table) fp1.makeSources(self.catalog1) fp2 = afwDetect.FootprintSet( im2, afwDetect.Threshold(0.001), "DETECTED") self.catalog2 = afwTable.SourceCatalog(self.table) fp2.makeSources(self.catalog2) fp3 = afwDetect.FootprintSet( im3, afwDetect.Threshold(0.001), "DETECTED") self.catalog3 = afwTable.SourceCatalog(self.table) fp3.makeSources(self.catalog3)
def clipImage(im, minClip, maxClip): """Clip an image to lie between minClip and maxclip (None to ignore)""" if re.search("::MaskedImage<", im.__repr__()): mi = im else: mi = afwImage.makeMaskedImage(im, afwImage.MaskU(im.getDimensions())) if minClip is not None: ds = afwDetect.FootprintSet(mi, afwDetect.Threshold(-minClip, afwDetect.Threshold.VALUE, False)) afwDetect.setImageFromFootprintList(mi.getImage(), ds.getFootprints(), minClip) if maxClip is not None: ds = afwDetect.FootprintSet(mi, afwDetect.Threshold(maxClip)) afwDetect.setImageFromFootprintList(mi.getImage(), ds.getFootprints(), maxClip)
def detector_crosstalk(ccd, aggressor_amp, dnthresh=None, nsig=5, signal_extractor=extract_mean_signal, min_fp_size=50): """ Compute detector crosstalk from a spot image in the aggressor amplifier. dnthresh is the threshold in DN for detecting the illuminated column in the aggressor amplifier; if set to None, then nsig*clipped_stdev above median is used for the threshold. """ image = ccd.unbiased_and_trimmed_image(aggressor_amp) # # Extract footprint of spot image using nominal detection # threshold. # if dnthresh is None: median, stdev = get_stats(image, ccd.stat_ctrl) # dnthresh = median + nsig*stdev dnthresh = (np.max(image.getImage().getArray()) + median)/2. # print "dnthresh =", dnthresh threshold = afwDetect.Threshold(dnthresh) fp_set = afwDetect.FootprintSet(image, threshold) try: footprint, peak_value = get_footprint(fp_set, min_fp_size, dnthresh) except IndexError: raise RuntimeError('index error in get_footprint') agg_mean = signal_extractor(ccd, aggressor_amp, footprint)[0] ratios = dict([(amp, signal_extractor(ccd, amp, footprint) / agg_mean) for amp in ccd]) # for amp in ratios: # if ratios[amp][0] > 0.1: # ratios[amp] = (0, 0) return ratios
def testMergeFootprints(self): # YYYY """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.FootprintSet(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 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.FootprintSet(self.im, threshold, "BINNED1") if grow: fs = afwDetect.FootprintSet(fs, grow, True) msk = self.im.getMask() afwDetect.setMaskFromFootprintList(msk, fs.getFootprints(), msk.getPlaneBitMask("DETECTED")) del msk self.fs = fs self.checkPeaks(dwidth, dheight, frame=3)
def remove_small_sources_thresholding(exposure, min_radius_arcsec, random_state=None): mi = exposure.getMaskedImage() mask = mi.getMask() noise_array = utils.make_noise_image(mi, random_state) threshold = afwDet.Threshold(mask.getPlaneBitMask(['DETECTED'])) fp_det = afwDet.FootprintSet(mask, threshold, afwDet.Threshold.BITMASK) area_min = np.pi * (min_radius_arcsec / utils.pixscale)**2 fp_list = [] for fp in fp_det.getFootprints(): if fp.getArea() < area_min: fp_list.append(fp) fp_small = afwDet.FootprintSet(mi.getBBox()) fp_small.setFootprints(fp_list) mask.addMaskPlane('SMALL') fp_small.setMask(mask, 'SMALL') exp_clean = exposure.clone() mi_clean = exp_clean.getMaskedImage() replace = mask.getArray() & mask.getPlaneBitMask('SMALL') != 0 mi_clean = exp_clean.getMaskedImage() mi_clean.getImage().getArray()[replace] = noise_array[replace] return exp_clean
def clean_use_hsc_mask(exposure, ref_plane='THRESH_HIGH', rgrow=None, random_state=None, bright_object_mask=True): # generate array of gaussian noise mi = exposure.getMaskedImage() mask = mi.getMask() noise_array = utils.make_noise_image(mi, random_state) threshold = afwDet.Threshold(mask.getPlaneBitMask(['DETECTED'])) fp_det = afwDet.FootprintSet(mask, threshold, afwDet.Threshold.BITMASK) fp_list = [] for fp in fp_det.getFootprints(): hfp = afwDet.HeavyFootprintF(fp, mi) pix = hfp.getMaskArray() check = (pix & mask.getPlaneBitMask(ref_plane)!=0).sum() if check > 0: fp_list.append(fp) fpset_replace = afwDet.FootprintSet(mi.getBBox()) fpset_replace.setFootprints(fp_list) if rgrow: fpset_replace = afwDet.FootprintSet(fpset_replace, rgrow, True) mask.addMaskPlane('CLEANED') fpset_replace.setMask(mask, 'CLEANED') exp_clean = exposure.clone() mi_clean = exp_clean.getMaskedImage() replace = mask.getArray() & mask.getPlaneBitMask('CLEANED') != 0 if bright_object_mask: replace |= mask.getArray() & mask.getPlaneBitMask('BRIGHT_OBJECT') != 0 mi_clean.getImage().getArray()[replace] = noise_array[replace] return exp_clean
def testFootprintPeaks(self): """Test that we can extract the peaks from a Footprint""" fs = afwDetect.FootprintSet(self.ms, afwDetect.Threshold(10), "OBJECT") foot = fs.getFootprints()[0] self.assertEqual(len(foot.getPeaks()), 5)
def processSingle(self, sensorRef): """Process a single CCD Besides the regular ISR, also masks cosmic-rays and divides each processed image by the dark time to generate images of the dark rate. The dark time is provided by the 'getDarkTime' method. """ exposure = CalibTask.processSingle(self, sensorRef) if self.config.doRepair: psf = measAlg.DoubleGaussianPsf( self.config.psfSize, self.config.psfSize, self.config.psfFwhm / (2 * math.sqrt(2 * math.log(2)))) exposure.setPsf(psf) self.repair.run(exposure, keepCRs=False) if self.config.crGrow > 0: mask = exposure.getMaskedImage().getMask().clone() mask &= mask.getPlaneBitMask("CR") fpSet = afwDet.FootprintSet(mask, afwDet.Threshold(0.5)) fpSet = afwDet.FootprintSet(fpSet, self.config.crGrow, True) fpSet.setMask(exposure.getMaskedImage().getMask(), "CR") mi = exposure.getMaskedImage() mi /= self.getDarkTime(exposure) return exposure
def find_channels_with_saturation(eimage, full_well): """ Find all channels in an eimage that have pixel values above full well. Parameters ---------- eimage: lsst.afw.image.ImageF The "eimage" containing the image data in units of electrons per pixel. This is the image prior to electronic readout (i.e., conversion to ADU, addition of bias, dark current, crosstalk, etc.). For LSST CCDs, the eimages have parallel transfer directions along the x-axis, hence channels correspond to rows in eimages. full_well: int The pixel full well/saturation value in electrons. Returns ------- set of ints: The y-indices of the channels with saturated pixels. """ threshold = afw_detect.Threshold(full_well) fp_set = afw_detect.FootprintSet(eimage, threshold) channels = [] for fp in fp_set.getFootprints(): for span in fp.spans: channels.append(span.getY()) return set(channels)
def testMakeHeavy(self): """Test that we can make a FootprintSet heavy""" fs = afwDetect.FootprintSet(self.mi, afwDetect.Threshold(1)) ctrl = afwDetect.HeavyFootprintCtrl(afwDetect.HeavyFootprintCtrl.NONE) fs.makeHeavy(self.mi, ctrl) if display: ds9.mtv(self.mi, frame=0, title="input") #ds9.mtv(omi, frame=1, title="output") omi = self.mi.Factory(self.mi.getDimensions()) for foot in fs.getFootprints(): self.assertNotEqual(afwDetect.cast_HeavyFootprint(foot, self.mi), None) afwDetect.cast_HeavyFootprint(foot, self.mi).insert(omi) for foot in fs.getFootprints(): self.assertNotEqual(afwDetect.HeavyFootprintF.cast(foot), None) afwDetect.HeavyFootprintF.cast(foot).insert(omi) self.assertTrue( np.all( np.equal(self.mi.getImage().getArray(), omi.getImage().getArray())))
def gain(self, amp, jmargin=None, max_npix=9, buff=1): if jmargin is None: jmargins = list(range(10)) else: jmargins = (jmargin, ) self._generate_stats(amp) values = [] fp_sets = [] for j in jmargins: margin = self.noise * (j + 3) threshold = afwDetect.Threshold(self.median + margin) fp_set = afwDetect.FootprintSet(self.ccd[amp], threshold) fp_sets.append(fp_set) signals = [ self._footprint_signal(fp, buff) for fp in fp_set.getFootprints() if fp.getNpix() < max_npix ] try: stats = afwMath.makeStatistics(signals, afwMath.MEANCLIP) mean = stats.getValue() values.append(self.fe55_yield / mean) except: pass my_gain = np.median(values) return my_gain
def testGrowCircular(self): """Grow footprints in all 4 directions using the FootprintSet/FootprintControl constructor """ im = afwImage.MaskedImageF(11, 11) im[5, 5, afwImage.LOCAL] = (10, 0x0, 0.0) fs = afwDetect.FootprintSet(im, afwDetect.Threshold(10)) self.assertEqual(len(fs.getFootprints()), 1) radius = 3 # How much to grow by for fctrl in ( afwDetect.FootprintControl(), afwDetect.FootprintControl(True), afwDetect.FootprintControl(True, True), ): grown = afwDetect.FootprintSet(fs, radius, fctrl) afwDetect.setMaskFromFootprintList(im.getMask(), grown.getFootprints(), 0x10) if display: ds9.mtv(im) foot = grown.getFootprints()[0] if not fctrl.isCircular()[0]: self.assertEqual(foot.getArea(), 1) elif fctrl.isCircular()[0]: assert radius == 3 if fctrl.isIsotropic()[1]: self.assertEqual(foot.getArea(), 29) else: self.assertEqual(foot.getArea(), 25)
def setUp(self): config = SingleFrameMeasurementTask.ConfigClass() config.slots.apFlux = 'base_CircularApertureFlux_12_0' self.schema = afwTable.SourceTable.makeMinimalSchema() self.measureSources = SingleFrameMeasurementTask(self.schema, config=config) bbox = afwGeom.BoxI(afwGeom.PointI(0, 0), afwGeom.ExtentI(self.width, self.height)) self.cellSet = afwMath.SpatialCellSet(bbox, 100) self.footprintSet = afwDetection.FootprintSet( self.mi, afwDetection.Threshold(self.detectThresh), "DETECTED") self.catalog = self.measure(self.footprintSet, self.exposure) for source in self.catalog: try: cand = measAlg.makePsfCandidate(source, self.exposure) self.cellSet.insertCandidate(cand) except Exception as e: print(e) continue
def makeThresholdMask(maskedImage, threshold, growFootprints=1, maskName='SAT'): """Mask pixels based on threshold detection @param[in,out] maskedImage afw.image.MaskedImage to process; the mask is altered @param[in] threshold detection threshold @param[in] growFootprints amount by which to grow footprints of detected regions @param[in] maskName mask plane name @return a list of defects (meas.algrithms.Defect) of regions set in the mask. """ # find saturated regions thresh = afwDetection.Threshold(threshold) fs = afwDetection.FootprintSet(maskedImage, thresh) if growFootprints > 0: fs = afwDetection.FootprintSet(fs, growFootprints) fpList = fs.getFootprints() # set mask mask = maskedImage.getMask() bitmask = mask.getPlaneBitMask(maskName) afwDetection.setMaskFromFootprintList(mask, fpList, bitmask) return defectListFromFootprintList(fpList, growFootprints=0)
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.FootprintSet(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 detectObjectsInExp(exp, nSigma=10, nPixMin=10, grow=0): """Quick and dirty object detection for an expsure. Return the footPrintSet for the objects in a preferably-postISR exposure. Parameters ---------- exp : `lsst.afw.image.Exposure` The exposure to detect objects in. nSigma : `float` The number of sigma for detection. nPixMin : `int` The minimum number of pixels in an object for detection. grow : `int` The number of pixels to grow the footprint by after detection. Returns ------- footPrintSet : `lsst.afw.detection.FootprintSet` The set of footprints in the image. """ median = np.nanmedian(exp.image.array) exp.image -= median threshold = afwDetect.Threshold(nSigma, afwDetect.Threshold.STDEV) footPrintSet = afwDetect.FootprintSet(exp.getMaskedImage(), threshold, "DETECTED", nPixMin) if grow > 0: isotropic = True footPrintSet = afwDetect.FootprintSet(footPrintSet, grow, isotropic) exp.image += median # add back in to leave background unchanged return footPrintSet
def createCandidate(self, threshold=0.1): """Create a PSF candidate from self.exp @param threshold: Threshold for creating footprints on image """ source = self.catalog.addNew() fpSet = afwDet.FootprintSet(self.exp.getMaskedImage(), afwDet.Threshold(threshold), "DETECTED") if display: ds9.mtv(self.exp, frame=1) for fp in fpSet.getFootprints(): for peak in fp.getPeaks(): ds9.dot("x", peak.getIx(), peak.getIy(), frame=1) # There might be multiple footprints; only the one around self.x,self.y should go in the source found = False for fp in fpSet.getFootprints(): if fp.contains(afwGeom.Point2I(self.x, self.y)): found = True break self.assertTrue( found, "Unable to find central peak in footprint: faulty test") source.setFootprint(fp) return measAlg.PsfCandidateF(source, self.exp, self.x, self.y)
def interpolateFromMask(maskedImage, fwhm, growSaturatedFootprints=1, maskNameList=['SAT'], fallbackValue=None): """Interpolate over defects identified by a particular set of mask planes. Parameters ---------- maskedImage : `lsst.afw.image.MaskedImage` Image to process. fwhm : scalar FWHM of double Gaussian smoothing kernel. growSaturatedFootprints : scalar, optional Number of pixels to grow footprints for saturated pixels. maskNameList : `List` of `str`, optional Mask plane name. fallbackValue : scalar, optional Value of last resort for interpolation. """ mask = maskedImage.getMask() if growSaturatedFootprints > 0 and "SAT" in maskNameList: # If we are interpolating over an area larger than the original masked region, we need # to expand the original mask bit to the full area to explain why we interpolated there. growMasks(mask, radius=growSaturatedFootprints, maskNameList=['SAT'], maskValue="SAT") thresh = afwDetection.Threshold(mask.getPlaneBitMask(maskNameList), afwDetection.Threshold.BITMASK) fpSet = afwDetection.FootprintSet(mask, thresh) defectList = Defects.fromFootprintList(fpSet.getFootprints()) interpolateDefectList(maskedImage, defectList, fwhm, fallbackValue=fallbackValue) return maskedImage
def makeThresholdMask(maskedImage, threshold, growFootprints=1, maskName='SAT'): """Mask pixels based on threshold detection. Parameters ---------- maskedImage : `lsst.afw.image.MaskedImage` Image to process. Only the mask plane is updated. threshold : scalar Detection threshold. growFootprints : scalar, optional Number of pixels to grow footprints of detected regions. maskName : str, optional Mask plane name, or list of names to convert Returns ------- defectList : `lsst.meas.algorithms.Defects` Defect list constructed from pixels above the threshold. """ # find saturated regions thresh = afwDetection.Threshold(threshold) fs = afwDetection.FootprintSet(maskedImage, thresh) if growFootprints > 0: fs = afwDetection.FootprintSet(fs, rGrow=growFootprints, isotropic=False) fpList = fs.getFootprints() # set mask mask = maskedImage.getMask() bitmask = mask.getPlaneBitMask(maskName) afwDetection.setMaskFromFootprintList(mask, fpList, bitmask) return Defects.fromFootprintList(fpList)
def detectObjectsInExp(exp, nSigma, nPixMin, grow=0): """Run a very basic but fast threshold-based object detection on an exposure Return the footPrintSet for the objects in a postISR exposure. Parameters ---------- exp : `lsst.afw.image.Exposure` Image in which to detect objects. nSigma : `float` nSigma above image's stddev at which to set the detection threshold. nPixMin : `int` Minimum number of pixels for detection. grow : `int` Grow the detected footprint by this many pixels. Returns ------- footPrintSet : `lsst.afw.detection.FootprintSet` FootprintSet containing the detections. """ threshold = afwDetect.Threshold(nSigma, afwDetect.Threshold.STDEV) footPrintSet = afwDetect.FootprintSet(exp.getMaskedImage(), threshold, "DETECTED", nPixMin) if grow > 0: isotropic = True footPrintSet = afwDetect.FootprintSet(footPrintSet, grow, isotropic) return footPrintSet
def testGrowLRUD2(self): """Grow footprints in various directions using the FootprintSet/FootprintControl constructor Check that overlapping grown Footprints give the expected answers """ ngrow = 3 # How much to grow by for fctrl, xy in [ (afwDetect.FootprintControl(True, True, False, False), [(4, 5), (5, 6), (6, 5)]), (afwDetect.FootprintControl(False, False, True, True), [(5, 4), (6, 5), (5, 6)]), ]: im = afwImage.MaskedImageF(11, 11) for x, y in xy: im[x, y, afwImage.LOCAL] = (10, 0x0, 0.0) fs = afwDetect.FootprintSet(im, afwDetect.Threshold(10)) self.assertEqual(len(fs.getFootprints()), 1) grown = afwDetect.FootprintSet(fs, ngrow, fctrl) im.getMask().set(0) afwDetect.setMaskFromFootprintList(im.getMask(), grown.getFootprints(), 0x10) if display: ds9.mtv(im) self.assertEqual(len(grown.getFootprints()), 1) foot = grown.getFootprints()[0] npix = 1 + 2 * ngrow npix += 3 + 2 * ngrow # 3: distance between pair of set pixels 000X0X000 self.assertEqual(foot.getArea(), npix)
def subtractXTalk(mi, coeffs, minPixelToMask=45000, crosstalkStr="CROSSTALK"): """Subtract the crosstalk from MaskedImage mi given a set of coefficients The pixels affected by signal over minPixelToMask have the crosstalkStr bit set """ sctrl = afwMath.StatisticsControl() sctrl.setAndMask(mi.getMask().getPlaneBitMask("DETECTED")) bkgd = afwMath.makeStatistics(mi, afwMath.MEDIAN, sctrl).getValue() # # These are the pixels that are bright enough to cause crosstalk (more precisely, # the ones that we label as causing crosstalk; in reality all pixels cause crosstalk) # tempStr = "TEMP" # mask plane used to record the bright pixels that we need to mask mi.getMask().addMaskPlane(tempStr) try: fs = afwDetect.FootprintSet(mi, afwDetect.Threshold(minPixelToMask), tempStr) mi.getMask().addMaskPlane(crosstalkStr) afwDisplay.getDisplay().setMaskPlaneColor(crosstalkStr, afwDisplay.MAGENTA) fs.setMask(mi.getMask(), crosstalkStr) # the crosstalkStr bit will now be set whenever # we subtract crosstalk crosstalk = mi.getMask().getPlaneBitMask(crosstalkStr) width, height = mi.getDimensions() for i in range(nAmp): bbox = afwGeom.BoxI(afwGeom.PointI(i*(width//nAmp), 0), afwGeom.ExtentI(width//nAmp, height)) ampI = mi.Factory(mi, bbox) for j in range(nAmp): if i == j: continue bbox = afwGeom.BoxI(afwGeom.PointI(j*(width//nAmp), 0), afwGeom.ExtentI(width//nAmp, height)) if (i + j)%2 == 1: ampJ = afwMath.flipImage(mi.Factory(mi, bbox), True, False) # no need for a deep copy else: ampJ = mi.Factory(mi, bbox, afwImage.LOCAL, True) msk = ampJ.getMask() if np.all(msk.getArray() & msk.getPlaneBitMask("SAT")): # Bad amplifier; ignore it completely --- its effect will come out in the bias continue msk &= crosstalk ampJ -= bkgd ampJ *= coeffs[j][i] ampI -= ampJ # # Clear the crosstalkStr bit in the original bright pixels, where tempStr is set # msk = mi.getMask() temp = msk.getPlaneBitMask(tempStr) xtalk_temp = crosstalk | temp np_msk = msk.getArray() mask_indicies = np.where(np.bitwise_and(np_msk, xtalk_temp) == xtalk_temp) np_msk[mask_indicies] &= getattr(np, np_msk.dtype.name)(~crosstalk) finally: msk.removeAndClearMaskPlane(tempStr, True) # added in afw #1853
def clipImage(im, minClip, maxClip): """Clip an image to lie between minClip and maxclip (None to ignore)""" if isinstance(im, MaskedImage): mi = im else: mi = makeMaskedImage(im, Mask(im.getDimensions())) if minClip is not None: ds = afwDetect.FootprintSet( mi, afwDetect.Threshold(-minClip, afwDetect.Threshold.VALUE, False)) afwDetect.setImageFromFootprintList( mi.getImage(), ds.getFootprints(), minClip) if maxClip is not None: ds = afwDetect.FootprintSet(mi, afwDetect.Threshold(maxClip)) afwDetect.setImageFromFootprintList( mi.getImage(), ds.getFootprints(), maxClip)
def subtractCrosstalkYagi(mi, coeffs1List, coeffs2List, gainsPreampSig, minPixelToMask=45000, crosstalkStr="CROSSTALK"): """Subtract the crosstalk from MaskedImage mi given a set of coefficients based on procedure presented in Yagi et al. 2012, PASP in publication; arXiv:1210.8212 The pixels affected by signal over minPixelToMask have the crosstalkStr bit set """ ####sctrl = afwMath.StatisticsControl() ####sctrl.setAndMask(mi.getMask().getPlaneBitMask("DETECTED")) ####bkgd = afwMath.makeStatistics(mi, afwMath.MEDIAN, sctrl).getValue() # # These are the pixels that are bright enough to cause crosstalk (more precisely, # the ones that we label as causing crosstalk; in reality all pixels cause crosstalk) # if True: tempStr = "TEMP" # mask plane used to record the bright pixels that we need to mask mi.getMask().addMaskPlane(tempStr) fs = afwDetect.FootprintSet(mi, afwDetect.Threshold(minPixelToMask), tempStr) mi.getMask().addMaskPlane(crosstalkStr) ds9.setMaskPlaneColor(crosstalkStr, ds9.MAGENTA) fs.setMask(mi.getMask(), crosstalkStr) # the crosstalkStr bit will now be set # whenever we subtract crosstalk crosstalk = mi.getMask().getPlaneBitMask(crosstalkStr) if True: # This python implementation is fairly fast image = mi.getImage() xtalk = afwImage.ImageF(image.getDimensions()) xtalk.set(0) for i in range(4): xAmp, xOff = getAmplifier(xtalk, i, i) for j in range(4): if i == j: continue gainRatio = gainsPreampSig[j] / gainsPreampSig[i] jAmp, jOff = getAmplifier(image, j, i) xAmp.scaledPlus(gainRatio*coeffs1List[i][j], jAmp) xOff.scaledPlus(gainRatio*coeffs2List[i][j], jOff) image -= xtalk else: nAmp = 4 subtractCrosstalk(mi, nAmp, coeffs1List, coeffs2List, gainsPreampSig) # # Clear the crosstalkStr bit in the original bright pixels, where tempStr is set # msk = mi.getMask() temp = msk.getPlaneBitMask(tempStr) xtalk_temp = crosstalk | temp np_msk = msk.getArray() np_msk[np.where(np.bitwise_and(np_msk, xtalk_temp) == xtalk_temp)] &= ~crosstalk try: msk.removeAndClearMaskPlane(tempStr, True) # added in afw #1853 except AttributeError: ds9.setMaskPlaneVisibility(tempStr, False)
def Clusterfind_max_timecode_one_file(filename, winow_xmin=0, winow_xmax=999, winow_ymin=0, winow_ymax=999, glitch_threshold=20000, checkerboard_phase=None, npix_min=1): if str(filename).find('.DS') != -1: return import lsst.afw.detection as afwDetect import string, os cluster_sizes = [] timecodes = [] files = [] thresholdValue = 1 npixMin = npix_min grow = 0 isotropic = False image = TimepixToExposure(filename, winow_xmin, winow_xmax, winow_ymin, winow_ymax) threshold = afwDetect.Threshold(thresholdValue) footPrintSet = afwDetect.FootprintSet(image, threshold, npixMin) footPrintSet = afwDetect.FootprintSet(footPrintSet, grow, isotropic) footPrints = footPrintSet.getFootprints() for footprintnum, footprint in enumerate(footPrints): npix = afwDetect.Footprint.getNpix(footprint) cluster_sizes.append(npix) # if npix >= 4: box = footprint.getBBox() bbox_xmin = box.getMinX() bbox_xmax = box.getMaxX() + 1 bbox_ymin = box.getMinY() bbox_ymax = box.getMaxY() + 1 data = image.getArray()[bbox_ymin:bbox_ymax, bbox_xmin:bbox_xmax] # x,y,t,chisq = CentroidTimepixCluster(data, fit_function = 'gaus') # timecodes.append(t) ## centroid_x, centroid_y = footprint.getCentroid() ## x += bbox_xmin ## y += bbox_ymin if checkerboard_phase is not None: print('WARNING - Not yet implemented') exit() if (bbox_xmin + bbox_ymin) % 2 == checkerboard_phase: timecode -= 1 timecodes.append(GetMaxClusterTimecode(data)) return timecodes
def testFootprints2(self): """Check that we found the correct number of objects using FootprintSet""" ds = afwDetect.FootprintSet(self.ms, 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.FootprintSet(self.ms.getImage(), 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 testSetFromFootprint(self): """Test setting mask/image pixels from a Footprint list""" mi = afwImage.MaskedImageF(lsst.geom.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.FootprintSet(mi, afwDetect.Threshold(15)) objects = ds.getFootprints() afwDetect.setMaskFromFootprintList(mi.getMask(), objects, 0x1) self.assertEqual(mi.getMask()[4, 2, afwImage.LOCAL], 0x0) self.assertEqual(mi.getMask()[3, 6, afwImage.LOCAL], 0x1) self.assertEqual(mi.getImage()[3, 6, afwImage.LOCAL], 20) for ft in objects: ft.spans.setImage(mi.getImage(), 5.0) self.assertEqual(mi.getImage()[4, 2, afwImage.LOCAL], 10) self.assertEqual(mi.getImage()[3, 6, afwImage.LOCAL], 5) if display: ds9.mtv(mi, frame=1) # # Check Footprint.contains() while we are about it # self.assertTrue(objects[0].contains(lsst.geom.Point2I(7, 5))) self.assertFalse(objects[0].contains(lsst.geom.Point2I(10, 6))) self.assertFalse(objects[0].contains(lsst.geom.Point2I(7, 6))) self.assertFalse(objects[0].contains(lsst.geom.Point2I(4, 2))) self.assertTrue(objects[1].contains(lsst.geom.Point2I(3, 6))) # Verify the FootprintSet footprint list setter can accept inputs from # the footprint list getter # Create a copy of the ds' FootprintList dsFpList = ds.getFootprints() footprintListCopy = [afwDetect.Footprint().assign(f) for f in dsFpList] # Use the FootprintList setter with the output from the getter ds.setFootprints(ds.getFootprints()[:-1]) dsFpListNew = ds.getFootprints() self.assertTrue(len(dsFpListNew) == len(footprintListCopy)-1) for new, old in zip(dsFpListNew, footprintListCopy[:-1]): self.assertEqual(new, old)