Пример #1
0
    def setUp(self):
        im = afwImage.ImageF(self.monetFile("small.fits"))
        self.mi = afwImage.MaskedImageF(im, afwImage.MaskU(im.getDimensions()),
                                        afwImage.ImageF(im.getDimensions()));
        self.ds = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(100))

        if display:
            ds9.mtv(self.mi.getImage())
            ds9.erase()
            
        for foot in self.ds.getFootprints():
            bbox = foot.getBBox()
            x0, y0 = bbox.getMinX(), bbox.getMinY()
            x1, y1 = bbox.getMaxX(), bbox.getMaxY()
            xc = (x0 + x1)/2.0
            yc = (y0 + y1)/2.0
            
            if display:
                ds9.dot("+", xc, yc, ctype=ds9.BLUE)

                if False:
                    x0 -= 0.5; y0 -= 0.5
                    x1 += 0.5; y1 += 0.5
                    
                    ds9.line([(x0, y0), (x1, y0), (x1, y1), (x0, y1), (x0, y0)], ctype=ds9.RED)

        self.control = algorithms.GaussianCentroidControl()
        schema = afwTable.SourceTable.makeMinimalSchema()
        self.centroider = algorithms.MeasureSourcesBuilder().addAlgorithm(self.control).build(schema)
        self.ssMeasured = afwTable.SourceCatalog(schema)
        self.ssMeasured.table.defineCentroid(self.control.name)
        self.ssTruth = afwTable.SourceCatalog(schema)
        self.readTruth(self.monetFile("positions.dat-original"))
Пример #2
0
def OLDprepareFrames(mos,
                     frame0=1,
                     R=23,
                     medianN=23,
                     onlyVisits=[],
                     force=False):
    """Prepare frames to have their radial profiles measured.
Subtract the first quartile
Set a radius R circle about the centre of Arcturus to NaN
Set a chip with a bad QE value to NaN
Median filter with a medianN x medianN filter

The result is set as mos[-visit]

If onlyVisits is specified, only process those chips [n.b. frame0 is still obeyed]
    """

    visits = sorted(position.keys())

    width, height = mos[visits[0]].getDimensions()

    X, Y = np.meshgrid(np.arange(width), np.arange(height))

    frame = frame0 - 1
    for v in visits:
        frame += 1
        if onlyVisits and v not in onlyVisits:
            continue

        print("Processing %d" % v)

        im = mos[v].clone()
        im[2121:2230, 590:830] = np.nan  # QE for this chip is bad

        ima = im.getArray()
        im[:] -= np.percentile(ima, 25)

        xc, yc = position[v]
        xc -= im.getX0()
        yc -= im.getY0()

        ima[np.hypot(X - xc, Y - yc) < R] = np.nan

        if force or -v not in mos:
            im = utils.medianFilterImage(im, medianN)
            mos[-v] = im
        else:
            im = mos[-v]

        if True:
            ds9.mtv(im, title=v, frame=frame)
        else:
            ds9.erase(frame=frame)
        ds9.dot("o",
                xc,
                yc,
                size=R,
                frame=frame,
                ctype=ds9.GREEN if yc < im.getHeight() else ds9.RED)
    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)
Пример #4
0
    def testText(self):
        """Test drawing text"""
        ds9.erase()

        exp = afwImage.ExposureF(300, 350)
        ds9.mtv(exp, title="parent")  # tells display0 about the image's xy0

        with ds9.Buffering():
            ds9.dot('hello', 200, 200)
            ds9.dot('hello', 200, 210, size=1.25)
            ds9.dot('hello', 200, 220, size=3, fontFamily="times")
            ds9.dot('hello', 200, 230, fontFamily="helvetica bold italic")
Пример #5
0
    def testDrawing(self):
        """Test drawing lines and glyphs"""
        ds9.erase()

        exp = afwImage.ExposureF(300, 350)
        ds9.mtv(exp, title="parent")  # tells display0 about the image's xy0

        with ds9.Buffering():
            ds9.dot('o', 200, 220)
            vertices = [(200, 220), (210, 230), (224, 230), (214, 220), (200, 220)]
            ds9.line(vertices, ctype=ds9.CYAN)
            ds9.line(vertices[:-1], symbs="+x+x", size=3)
Пример #6
0
    def testText(self):
        """Test drawing text"""
        ds9.erase()

        exp = afwImage.ExposureF(300, 350)
        ds9.mtv(exp, title="parent")  # tells display0 about the image's xy0

        with ds9.Buffering():
            ds9.dot('hello', 200, 200)
            ds9.dot('hello', 200, 210, size=1.25)
            ds9.dot('hello', 200, 220, size=3, fontFamily="times")
            ds9.dot('hello', 200, 230, fontFamily="helvetica bold italic")
Пример #7
0
    def testDrawing(self):
        """Test drawing lines and glyphs"""
        ds9.erase()

        exp = afwImage.ExposureF(300, 350)
        ds9.mtv(exp, title="parent") # tells display0 about the image's xy0
        
        with ds9.Buffering():
            ds9.dot('o', 200, 220)
            vertices = [(200, 220), (210, 230), (224, 230), (214, 220), (200, 220)]
            ds9.line(vertices, ctype=ds9.CYAN)
            ds9.line(vertices[:-1], symbs="+x+x", size=3)
Пример #8
0
    def testTwoDisplays(self):
        """Test that we can do things with two frames"""

        exp = afwImage.ExposureF(300, 350)

        for frame in (0, 1):
            ds9.setMaskTransparency(50, frame=frame)

            if frame == 1:
                ds9.setMaskPlaneColor("CROSSTALK", "ignore", frame=frame)
            ds9.mtv(exp, title="parent", frame=frame)

            ds9.erase(frame=frame)
            ds9.dot('o', 205, 180, size=6, ctype=ds9.RED, frame=frame)
Пример #9
0
    def testTwoDisplays(self):
        """Test that we can do things with two frames"""

        exp = afwImage.ExposureF(300, 350)

        for frame in (0, 1):
            ds9.setMaskTransparency(50, frame=frame)

            if frame == 1:
                ds9.setMaskPlaneColor("CROSSTALK", "ignore", frame=frame)
            ds9.mtv(exp, title="parent", frame=frame)

            ds9.erase(frame=frame)
            ds9.dot('o', 205, 180, size=6, ctype=ds9.RED, frame=frame)
Пример #10
0
    def setUp(self):
        im = afwImage.ImageF(self.monetFile("small.fits"))
        self.mi = afwImage.MaskedImageF(im, afwImage.Mask(im.getDimensions()),
                                        afwImage.ImageF(im.getDimensions()))
        self.ds = afwDetection.FootprintSet(self.mi,
                                            afwDetection.Threshold(100))

        if display:
            ds9.mtv(self.mi.getImage())
            ds9.erase()

        for foot in self.ds.getFootprints():
            bbox = foot.getBBox()
            x0, y0 = bbox.getMinX(), bbox.getMinY()
            x1, y1 = bbox.getMaxX(), bbox.getMaxY()
            xc = (x0 + x1) / 2.0
            yc = (y0 + y1) / 2.0

            if display:
                ds9.dot("+", xc, yc, ctype=ds9.BLUE)

                if False:
                    x0 -= 0.5
                    y0 -= 0.5
                    x1 += 0.5
                    y1 += 0.5

                    ds9.line([(x0, y0), (x1, y0), (x1, y1), (x0, y1),
                              (x0, y0)],
                             ctype=ds9.RED)
        msConfig = measBase.SingleFrameMeasurementConfig()
        msConfig.algorithms.names = ["base_GaussianCentroid"]
        msConfig.plugins["base_GaussianCentroid"].doFootprintCheck = False
        msConfig.slots.centroid = "base_GaussianCentroid"
        msConfig.slots.shape = None
        msConfig.slots.apFlux = None
        msConfig.slots.modelFlux = None
        msConfig.slots.psfFlux = None
        msConfig.slots.instFlux = None
        msConfig.slots.calibFlux = None
        schema = afwTable.SourceTable.makeMinimalSchema()
        self.task = measBase.SingleFrameMeasurementTask(schema,
                                                        config=msConfig)
        self.ssMeasured = afwTable.SourceCatalog(schema)
        self.ssMeasured.table.defineCentroid("base_GaussianCentroid")
        self.ssTruth = afwTable.SourceCatalog(schema)
        self.ssTruth.table.defineCentroid("base_GaussianCentroid")

        self.readTruth(self.monetFile("positions.dat-original"))
Пример #11
0
def OLDprepareFrames(mos, frame0=1, R=23, medianN=23, onlyVisits=[], force=False):
    """Prepare frames to have their radial profiles measured.
Subtract the first quartile
Set a radius R circle about the centre of Arcturus to NaN
Set a chip with a bad QE value to NaN
Median filter with a medianN x medianN filter

The result is set as mos[-visit]

If onlyVisits is specified, only process those chips [n.b. frame0 is still obeyed]
    """

    visits = sorted(position.keys())

    width, height = mos[visits[0]].getDimensions()

    X, Y = np.meshgrid(np.arange(width), np.arange(height))

    frame = frame0 - 1
    for v in visits:
        frame += 1
        if onlyVisits and v not in onlyVisits:
            continue

        print "Processing %d" % v

        im = mos[v].clone()
        im[2121:2230, 590:830] = np.nan  # QE for this chip is bad

        ima = im.getArray()
        im[:] -= np.percentile(ima, 25)

        xc, yc = position[v]
        xc -= im.getX0()
        yc -= im.getY0()

        ima[np.hypot(X - xc, Y - yc) < R] = np.nan

        if force or not -v in mos:
            im = utils.medianFilterImage(im, medianN)
            mos[-v] = im
        else:
            im = mos[-v]

        if True:
            ds9.mtv(im, title=v, frame=frame)
        else:
            ds9.erase(frame=frame)
        ds9.dot("o", xc, yc, size=R, frame=frame, ctype=ds9.GREEN if yc < im.getHeight() else ds9.RED)
Пример #12
0
    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)
Пример #13
0
    def setUp(self):
	im = afwImage.ImageF(self.monetFile("small.fits"))
        self.mi = afwImage.MaskedImageF(im, afwImage.MaskU(im.getDimensions()),
                                        afwImage.ImageF(im.getDimensions()));
        self.ds = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(100))

        if display:
            ds9.mtv(self.mi.getImage())
            ds9.erase()

        for foot in self.ds.getFootprints():
            bbox = foot.getBBox()
            x0, y0 = bbox.getMinX(), bbox.getMinY()
            x1, y1 = bbox.getMaxX(), bbox.getMaxY()
            xc = (x0 + x1)/2.0
            yc = (y0 + y1)/2.0

            if display:
                ds9.dot("+", xc, yc, ctype=ds9.BLUE)

                if False:
                    x0 -= 0.5; y0 -= 0.5
                    x1 += 0.5; y1 += 0.5

                    ds9.line([(x0, y0), (x1, y0), (x1, y1), (x0, y1), (x0, y0)], ctype=ds9.RED)
        msConfig = measBase.SingleFrameMeasurementConfig()
        msConfig.algorithms.names = ["base_GaussianCentroid"]
        msConfig.slots.centroid = "base_GaussianCentroid"
        msConfig.slots.shape = None
        msConfig.slots.apFlux = None
        msConfig.slots.modelFlux = None
        msConfig.slots.psfFlux = None
        msConfig.slots.instFlux = None
        msConfig.slots.calibFlux = None
        schema = afwTable.SourceTable.makeMinimalSchema()
        self.task = measBase.SingleFrameMeasurementTask(schema, config=msConfig)
        self.ssMeasured = afwTable.SourceCatalog(schema)
        self.ssMeasured.table.defineCentroid("base_GaussianCentroid")
        self.ssTruth = afwTable.SourceCatalog(schema)
        self.ssTruth.table.defineCentroid("base_GaussianCentroid")

        self.readTruth(self.monetFile("positions.dat-original"))
    def setUp(self):
        im = afwImage.ImageF(self.monetFile("small.fits"))
        self.mi = afwImage.MaskedImageF(im, afwImage.MaskU(im.getDimensions()),
                                        afwImage.ImageF(im.getDimensions()))
        self.ds = afwDetection.FootprintSet(self.mi,
                                            afwDetection.Threshold(100))

        if display:
            ds9.mtv(self.mi.getImage())
            ds9.erase()

        for foot in self.ds.getFootprints():
            bbox = foot.getBBox()
            x0, y0 = bbox.getMinX(), bbox.getMinY()
            x1, y1 = bbox.getMaxX(), bbox.getMaxY()
            xc = (x0 + x1) / 2.0
            yc = (y0 + y1) / 2.0

            if display:
                ds9.dot("+", xc, yc, ctype=ds9.BLUE)

                if False:
                    x0 -= 0.5
                    y0 -= 0.5
                    x1 += 0.5
                    y1 += 0.5

                    ds9.line([(x0, y0), (x1, y0), (x1, y1), (x0, y1),
                              (x0, y0)],
                             ctype=ds9.RED)

        self.control = algorithms.GaussianCentroidControl()
        schema = afwTable.SourceTable.makeMinimalSchema()
        self.centroider = algorithms.MeasureSourcesBuilder().addAlgorithm(
            self.control).build(schema)
        self.ssMeasured = afwTable.SourceCatalog(schema)
        self.ssMeasured.table.defineCentroid(self.control.name)
        self.ssTruth = afwTable.SourceCatalog(schema)
        self.readTruth(self.monetFile("positions.dat-original"))
Пример #15
0
    def determinePsf(self,
                     exposure,
                     psfCandidateList,
                     metadata=None,
                     flagKey=None):
        """!Determine a PCA PSF model for an exposure given a list of PSF candidates

        \param[in] exposure exposure containing the psf candidates (lsst.afw.image.Exposure)
        \param[in] psfCandidateList a sequence of PSF candidates (each an lsst.meas.algorithms.PsfCandidate);
            typically obtained by detecting sources and then running them through a star selector
        \param[in,out] metadata  a home for interesting tidbits of information
        \param[in] flagKey schema key used to mark sources actually used in PSF determination

        \return a list of
         - psf: the measured PSF, an lsst.meas.algorithms.PcaPsf
         - cellSet: an lsst.afw.math.SpatialCellSet containing the PSF candidates
        """
        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displayExposure = lsstDebug.Info(
            __name__).displayExposure  # display the Exposure + spatialCells
        displayPsfCandidates = lsstDebug.Info(
            __name__).displayPsfCandidates  # show the viable candidates
        displayIterations = lsstDebug.Info(
            __name__).displayIterations  # display on each PSF iteration
        displayPsfComponents = lsstDebug.Info(
            __name__).displayPsfComponents  # show the PCA components
        displayResiduals = lsstDebug.Info(
            __name__).displayResiduals  # show residuals
        displayPsfMosaic = lsstDebug.Info(
            __name__).displayPsfMosaic  # show mosaic of reconstructed PSF(x,y)
        # match Kernel amplitudes for spatial plots
        matchKernelAmplitudes = lsstDebug.Info(__name__).matchKernelAmplitudes
        # Keep matplotlib alive post mortem
        keepMatplotlibPlots = lsstDebug.Info(__name__).keepMatplotlibPlots
        displayPsfSpatialModel = lsstDebug.Info(
            __name__).displayPsfSpatialModel  # Plot spatial model?
        showBadCandidates = lsstDebug.Info(
            __name__).showBadCandidates  # Include bad candidates
        # Normalize residuals by object amplitude
        normalizeResiduals = lsstDebug.Info(__name__).normalizeResiduals
        pause = lsstDebug.Info(
            __name__).pause  # Prompt user after each iteration?

        if display > 1:
            pause = True

        mi = exposure.getMaskedImage()

        if len(psfCandidateList) == 0:
            raise RuntimeError("No PSF candidates supplied.")

        # construct and populate a spatial cell set
        bbox = mi.getBBox()
        psfCellSet = afwMath.SpatialCellSet(bbox, self.config.sizeCellX,
                                            self.config.sizeCellY)
        sizes = []
        for i, psfCandidate in enumerate(psfCandidateList):
            if psfCandidate.getSource().getPsfFluxFlag():  # bad measurement
                continue

            try:
                psfCellSet.insertCandidate(psfCandidate)
            except Exception as e:
                self.log.debug("Skipping PSF candidate %d of %d: %s", i,
                               len(psfCandidateList), e)
                continue
            source = psfCandidate.getSource()

            quad = afwEll.Quadrupole(source.getIxx(), source.getIyy(),
                                     source.getIxy())
            axes = afwEll.Axes(quad)
            sizes.append(axes.getA())
        if len(sizes) == 0:
            raise RuntimeError("No usable PSF candidates supplied")
        nEigenComponents = self.config.nEigenComponents  # initial version

        if self.config.kernelSize >= 15:
            self.log.warn(
                "WARNING: NOT scaling kernelSize by stellar quadrupole moment "
                +
                "because config.kernelSize=%s >= 15; using config.kernelSize as as the width, instead",
                self.config.kernelSize)
            actualKernelSize = int(self.config.kernelSize)
        else:
            medSize = numpy.median(sizes)
            actualKernelSize = 2 * int(self.config.kernelSize *
                                       math.sqrt(medSize) + 0.5) + 1
            if actualKernelSize < self.config.kernelSizeMin:
                actualKernelSize = self.config.kernelSizeMin
            if actualKernelSize > self.config.kernelSizeMax:
                actualKernelSize = self.config.kernelSizeMax

            if display:
                print("Median size=%s" % (medSize, ))
        self.log.trace("Kernel size=%s", actualKernelSize)

        # Set size of image returned around candidate
        psfCandidateList[0].setHeight(actualKernelSize)
        psfCandidateList[0].setWidth(actualKernelSize)

        if self.config.doRejectBlends:
            # Remove blended candidates completely
            blendedCandidates = [
            ]  # Candidates to remove; can't do it while iterating
            for cell, cand in candidatesIter(psfCellSet, False):
                if len(cand.getSource().getFootprint().getPeaks()) > 1:
                    blendedCandidates.append((cell, cand))
                    continue
            if display:
                print("Removing %d blended Psf candidates" %
                      len(blendedCandidates))
            for cell, cand in blendedCandidates:
                cell.removeCandidate(cand)
            if sum(1 for cand in candidatesIter(psfCellSet, False)) == 0:
                raise RuntimeError("All PSF candidates removed as blends")

        if display:
            frame = 0
            if displayExposure:
                ds9.mtv(exposure, frame=frame, title="psf determination")
                maUtils.showPsfSpatialCells(exposure,
                                            psfCellSet,
                                            self.config.nStarPerCell,
                                            symb="o",
                                            ctype=ds9.CYAN,
                                            ctypeUnused=ds9.YELLOW,
                                            size=4,
                                            frame=frame)

        #
        # Do a PCA decomposition of those PSF candidates
        #
        reply = "y"  # used in interactive mode
        for iterNum in range(self.config.nIterForPsf):
            if display and displayPsfCandidates:  # Show a mosaic of usable PSF candidates
                #
                import lsst.afw.display.utils as displayUtils

                stamps = []
                for cell in psfCellSet.getCellList():
                    for cand in cell.begin(not showBadCandidates
                                           ):  # maybe include bad candidates
                        try:
                            im = cand.getMaskedImage()

                            chi2 = cand.getChi2()
                            if chi2 > 1e100:
                                chi2 = numpy.nan

                            stamps.append(
                                (im, "%d%s" %
                                 (maUtils.splitId(cand.getSource().getId(),
                                                  True)["objId"], chi2),
                                 cand.getStatus()))
                        except Exception as e:
                            continue

                if len(stamps) == 0:
                    print(
                        "WARNING: No PSF candidates to show; try setting showBadCandidates=True"
                    )
                else:
                    mos = displayUtils.Mosaic()
                    for im, label, status in stamps:
                        im = type(im)(im, True)
                        try:
                            im /= afwMath.makeStatistics(
                                im, afwMath.MAX).getValue()
                        except NotImplementedError:
                            pass

                        mos.append(
                            im, label, ds9.GREEN
                            if status == afwMath.SpatialCellCandidate.GOOD else
                            ds9.YELLOW if status ==
                            afwMath.SpatialCellCandidate.UNKNOWN else ds9.RED)

                    mos.makeMosaic(frame=8, title="Psf Candidates")

            # Re-fit until we don't have any candidates with naughty chi^2 values influencing the fit
            cleanChi2 = False  # Any naughty (negative/NAN) chi^2 values?
            while not cleanChi2:
                cleanChi2 = True
                #
                # First, estimate the PSF
                #
                psf, eigenValues, nEigenComponents, fitChi2 = \
                    self._fitPsf(exposure, psfCellSet, actualKernelSize, nEigenComponents)
                #
                # In clipping, allow all candidates to be innocent until proven guilty on this iteration.
                # Throw out any prima facie guilty candidates (naughty chi^2 values)
                #
                for cell in psfCellSet.getCellList():
                    awfulCandidates = []
                    for cand in cell.begin(False):  # include bad candidates
                        cand.setStatus(afwMath.SpatialCellCandidate.UNKNOWN
                                       )  # until proven guilty
                        rchi2 = cand.getChi2()
                        if not numpy.isfinite(rchi2) or rchi2 <= 0:
                            # Guilty prima facie
                            awfulCandidates.append(cand)
                            cleanChi2 = False
                            self.log.debug("chi^2=%s; id=%s", cand.getChi2(),
                                           cand.getSource().getId())
                    for cand in awfulCandidates:
                        if display:
                            print("Removing bad candidate: id=%d, chi^2=%f" % \
                                  (cand.getSource().getId(), cand.getChi2()))
                        cell.removeCandidate(cand)

            #
            # Clip out bad fits based on reduced chi^2
            #
            badCandidates = list()
            for cell in psfCellSet.getCellList():
                for cand in cell.begin(False):  # include bad candidates
                    rchi2 = cand.getChi2(
                    )  # reduced chi^2 when fitting PSF to candidate
                    assert rchi2 > 0
                    if rchi2 > self.config.reducedChi2ForPsfCandidates:
                        badCandidates.append(cand)

            badCandidates.sort(key=lambda x: x.getChi2(), reverse=True)
            numBad = numCandidatesToReject(len(badCandidates), iterNum,
                                           self.config.nIterForPsf)
            for i, c in zip(range(numBad), badCandidates):
                if display:
                    chi2 = c.getChi2()
                    if chi2 > 1e100:
                        chi2 = numpy.nan

                    print("Chi^2 clipping %-4d  %.2g" %
                          (c.getSource().getId(), chi2))
                c.setStatus(afwMath.SpatialCellCandidate.BAD)

            #
            # Clip out bad fits based on spatial fitting.
            #
            # This appears to be better at getting rid of sources that have a single dominant kernel component
            # (other than the zeroth; e.g., a nearby contaminant) because the surrounding sources (which help
            # set the spatial model) don't contain that kernel component, and so the spatial modeling
            # downweights the component.
            #

            residuals = list()
            candidates = list()
            kernel = psf.getKernel()
            noSpatialKernel = psf.getKernel()
            for cell in psfCellSet.getCellList():
                for cand in cell.begin(False):
                    candCenter = afwGeom.PointD(cand.getXCenter(),
                                                cand.getYCenter())
                    try:
                        im = cand.getMaskedImage(kernel.getWidth(),
                                                 kernel.getHeight())
                    except Exception as e:
                        continue

                    fit = fitKernelParamsToImage(noSpatialKernel, im,
                                                 candCenter)
                    params = fit[0]
                    kernels = fit[1]
                    amp = 0.0
                    for p, k in zip(params, kernels):
                        amp += p * k.getSum()

                    predict = [
                        kernel.getSpatialFunction(k)(candCenter.getX(),
                                                     candCenter.getY())
                        for k in range(kernel.getNKernelParameters())
                    ]

                    #print cand.getSource().getId(), [a / amp for a in params], predict

                    residuals.append(
                        [a / amp - p for a, p in zip(params, predict)])
                    candidates.append(cand)

            residuals = numpy.array(residuals)

            for k in range(kernel.getNKernelParameters()):
                if False:
                    # Straight standard deviation
                    mean = residuals[:, k].mean()
                    rms = residuals[:, k].std()
                elif False:
                    # Using interquartile range
                    sr = numpy.sort(residuals[:, k])
                    mean = sr[int(0.5*len(sr))] if len(sr) % 2 else \
                        0.5 * (sr[int(0.5*len(sr))] + sr[int(0.5*len(sr))+1])
                    rms = 0.74 * (sr[int(0.75 * len(sr))] -
                                  sr[int(0.25 * len(sr))])
                else:
                    stats = afwMath.makeStatistics(
                        residuals[:, k], afwMath.MEANCLIP | afwMath.STDEVCLIP)
                    mean = stats.getValue(afwMath.MEANCLIP)
                    rms = stats.getValue(afwMath.STDEVCLIP)

                rms = max(
                    1.0e-4,
                    rms)  # Don't trust RMS below this due to numerical issues

                if display:
                    print("Mean for component %d is %f" % (k, mean))
                    print("RMS for component %d is %f" % (k, rms))
                badCandidates = list()
                for i, cand in enumerate(candidates):
                    if numpy.fabs(residuals[i, k] -
                                  mean) > self.config.spatialReject * rms:
                        badCandidates.append(i)

                badCandidates.sort(
                    key=lambda x: numpy.fabs(residuals[x, k] - mean),
                    reverse=True)

                numBad = numCandidatesToReject(len(badCandidates), iterNum,
                                               self.config.nIterForPsf)

                for i, c in zip(range(min(len(badCandidates), numBad)),
                                badCandidates):
                    cand = candidates[c]
                    if display:
                        print("Spatial clipping %d (%f,%f) based on %d: %f vs %f" % \
                              (cand.getSource().getId(), cand.getXCenter(), cand.getYCenter(), k,
                               residuals[badCandidates[i], k], self.config.spatialReject * rms))
                    cand.setStatus(afwMath.SpatialCellCandidate.BAD)

            #
            # Display results
            #
            if display and displayIterations:
                if displayExposure:
                    if iterNum > 0:
                        ds9.erase(frame=frame)
                    maUtils.showPsfSpatialCells(exposure,
                                                psfCellSet,
                                                self.config.nStarPerCell,
                                                showChi2=True,
                                                symb="o",
                                                size=8,
                                                frame=frame,
                                                ctype=ds9.YELLOW,
                                                ctypeBad=ds9.RED,
                                                ctypeUnused=ds9.MAGENTA)
                    if self.config.nStarPerCellSpatialFit != self.config.nStarPerCell:
                        maUtils.showPsfSpatialCells(
                            exposure,
                            psfCellSet,
                            self.config.nStarPerCellSpatialFit,
                            symb="o",
                            size=10,
                            frame=frame,
                            ctype=ds9.YELLOW,
                            ctypeBad=ds9.RED)
                if displayResiduals:
                    while True:
                        try:
                            maUtils.showPsfCandidates(
                                exposure,
                                psfCellSet,
                                psf=psf,
                                frame=4,
                                normalize=normalizeResiduals,
                                showBadCandidates=showBadCandidates)
                            maUtils.showPsfCandidates(
                                exposure,
                                psfCellSet,
                                psf=psf,
                                frame=5,
                                normalize=normalizeResiduals,
                                showBadCandidates=showBadCandidates,
                                variance=True)
                        except:
                            if not showBadCandidates:
                                showBadCandidates = True
                                continue
                        break

                if displayPsfComponents:
                    maUtils.showPsf(psf, eigenValues, frame=6)
                if displayPsfMosaic:
                    maUtils.showPsfMosaic(exposure,
                                          psf,
                                          frame=7,
                                          showFwhm=True)
                    ds9.scale('linear', 0, 1, frame=7)
                if displayPsfSpatialModel:
                    maUtils.plotPsfSpatialModel(
                        exposure,
                        psf,
                        psfCellSet,
                        showBadCandidates=True,
                        matchKernelAmplitudes=matchKernelAmplitudes,
                        keepPlots=keepMatplotlibPlots)

                if pause:
                    while True:
                        try:
                            reply = input(
                                "Next iteration? [ynchpqQs] ").strip()
                        except EOFError:
                            reply = "n"

                        reply = reply.split()
                        if reply:
                            reply, args = reply[0], reply[1:]
                        else:
                            reply = ""

                        if reply in ("", "c", "h", "n", "p", "q", "Q", "s",
                                     "y"):
                            if reply == "c":
                                pause = False
                            elif reply == "h":
                                print("c[ontinue without prompting] h[elp] n[o] p[db] q[uit displaying] " \
                                      "s[ave fileName] y[es]")
                                continue
                            elif reply == "p":
                                import pdb
                                pdb.set_trace()
                            elif reply == "q":
                                display = False
                            elif reply == "Q":
                                sys.exit(1)
                            elif reply == "s":
                                fileName = args.pop(0)
                                if not fileName:
                                    print("Please provide a filename")
                                    continue

                                print("Saving to %s" % fileName)
                                maUtils.saveSpatialCellSet(psfCellSet,
                                                           fileName=fileName)
                                continue
                            break
                        else:
                            print("Unrecognised response: %s" % reply,
                                  file=sys.stderr)

                    if reply == "n":
                        break

        # One last time, to take advantage of the last iteration
        psf, eigenValues, nEigenComponents, fitChi2 = \
            self._fitPsf(exposure, psfCellSet, actualKernelSize, nEigenComponents)

        #
        # Display code for debugging
        #
        if display and reply != "n":
            if displayExposure:
                maUtils.showPsfSpatialCells(exposure,
                                            psfCellSet,
                                            self.config.nStarPerCell,
                                            showChi2=True,
                                            symb="o",
                                            ctype=ds9.YELLOW,
                                            ctypeBad=ds9.RED,
                                            size=8,
                                            frame=frame)
                if self.config.nStarPerCellSpatialFit != self.config.nStarPerCell:
                    maUtils.showPsfSpatialCells(
                        exposure,
                        psfCellSet,
                        self.config.nStarPerCellSpatialFit,
                        symb="o",
                        ctype=ds9.YELLOW,
                        ctypeBad=ds9.RED,
                        size=10,
                        frame=frame)
                if displayResiduals:
                    maUtils.showPsfCandidates(
                        exposure,
                        psfCellSet,
                        psf=psf,
                        frame=4,
                        normalize=normalizeResiduals,
                        showBadCandidates=showBadCandidates)

            if displayPsfComponents:
                maUtils.showPsf(psf, eigenValues, frame=6)

            if displayPsfMosaic:
                maUtils.showPsfMosaic(exposure, psf, frame=7, showFwhm=True)
                ds9.scale("linear", 0, 1, frame=7)
            if displayPsfSpatialModel:
                maUtils.plotPsfSpatialModel(
                    exposure,
                    psf,
                    psfCellSet,
                    showBadCandidates=True,
                    matchKernelAmplitudes=matchKernelAmplitudes,
                    keepPlots=keepMatplotlibPlots)
        #
        # Generate some QA information
        #
        # Count PSF stars
        #
        numGoodStars = 0
        numAvailStars = 0

        avgX = 0.0
        avgY = 0.0

        for cell in psfCellSet.getCellList():
            for cand in cell.begin(False):  # don't ignore BAD stars
                numAvailStars += 1

            for cand in cell.begin(True):  # do ignore BAD stars
                src = cand.getSource()
                if flagKey is not None:
                    src.set(flagKey, True)
                avgX += src.getX()
                avgY += src.getY()
                numGoodStars += 1

        avgX /= numGoodStars
        avgY /= numGoodStars

        if metadata is not None:
            metadata.set("spatialFitChi2", fitChi2)
            metadata.set("numGoodStars", numGoodStars)
            metadata.set("numAvailStars", numAvailStars)
            metadata.set("avgX", avgX)
            metadata.set("avgY", avgY)

        psf = PcaPsf(psf.getKernel(), afwGeom.Point2D(avgX, avgY))

        return psf, psfCellSet
Пример #16
0
def prepareFrames(mos,
                  frame0=1,
                  R=100,
                  medianN=23,
                  onlyVisits=[],
                  nJob=1,
                  force=False):
    """Prepare frames to have their radial profiles measured.
Subtract the first quartile
Set a radius R circle about the centre of Arcturus to NaN
Set a chip with a bad QE value to NaN
Median filter with a medianN x medianN filter

The results are set as mos[-visit]

If onlyVisits is specified, only process those chips [n.b. frame0 is still obeyed]; otherwise
process every visit in the positions dict
    """
    visits = sorted(position.keys())

    visits0 = visits[:]  # needed to keep frame numbers aligned
    if not force:
        visits = [v for v in visits
                  if -v not in mos]  # don't process ones we've already seen
    if onlyVisits:
        visits = [v for v in visits if v in onlyVisits]

    width, height = mos[visits[0]].getDimensions()
    X, Y = np.meshgrid(np.arange(width), np.arange(height))

    for v in visits:
        im = mos[v].clone()
        mos[-v] = im
        im[2121:2230, 590:830] = np.nan  # QE for this chip is bad

        ima = im.getArray()
        im[:] -= np.percentile(ima, 25)

        xc, yc = position[v]
        xc -= im.getX0()
        yc -= im.getY0()

        ima[np.hypot(X - xc, Y - yc) < R] = np.nan
    #
    # multiprocessing
    #
    worker = MedianFilterImageWorker(mos, medianN)
    if nJob > 1:
        pool = multiprocessing.Pool(max([len(visits), nJob]))

        # We use map_async(...).get(9999) instead of map(...) to workaround a python bug
        # in handling ^C in subprocesses (http://bugs.python.org/issue8296)
        for v, im in pool.map_async(worker, visits).get(9999):
            mos[-v] = im

        pool.close()
        pool.join()
    else:
        for v in visits:
            mos[-v] = worker(v)
    #
    # Display
    #
    frame = frame0 - 1
    for v in visits0:
        frame += 1

        if v not in visits:
            continue

        im = mos[-v]

        if True:
            ds9.mtv(im, title=v, frame=frame)
        else:
            ds9.erase(frame=frame)

        xc, yc = position[v]
        xc -= im.getX0()
        yc -= im.getY0()

        ds9.dot("o",
                xc,
                yc,
                size=R,
                frame=frame,
                ctype=ds9.GREEN if yc < im.getHeight() else ds9.RED)
Пример #17
0
                for i, c in zip(range(min(len(badCandidates), numBad)),
                                badCandidates):
                    cand = candidates[c]
                    if display:
                        print "Spatial clipping %d (%f,%f) based on %d: %f vs %f" % \
                              (cand.getSource().getId(), cand.getXCenter(), cand.getYCenter(), k,
                               residuals[badCandidates[i],k], self.config.spatialReject * rms)
                    cand.setStatus(afwMath.SpatialCellCandidate.BAD)

            #
            # Display results
            #
            if display and displayIterations:
                if displayExposure:
                    if iter > 0:
                        ds9.erase(frame=frame)
                    maUtils.showPsfSpatialCells(exposure,
                                                psfCellSet,
                                                self.config.nStarPerCell,
                                                showChi2=True,
                                                symb="o",
                                                size=8,
                                                frame=frame,
                                                ctype=ds9.YELLOW,
                                                ctypeBad=ds9.RED,
                                                ctypeUnused=ds9.MAGENTA)
                    if self.config.nStarPerCellSpatialFit != self.config.nStarPerCell:
                        maUtils.showPsfSpatialCells(
                            exposure,
                            psfCellSet,
                            self.config.nStarPerCellSpatialFit,
Пример #18
0
def imagePca(mosaics,
             visits=None,
             nComponent=3,
             log=False,
             rng=30,
             showEigen=True,
             showResiduals=False,
             showOriginal=True,
             showRecon=False,
             normalizeEimages=True,
             scale=False,
             frame0=0,
             verbose=False):

    if showOriginal and showRecon:
        raise RuntimeError(
            "You may not specify both showOriginal and showRecon")

    try:
        rng[0]
    except TypeError:
        rng = [rng, rng]

    if not visits:
        visits = sorted(mosaics.keys())

    mosaics = mosaics.copy()
    for v in visits:
        mosaics[v] = mosaics[v].clone()

    pca = afwImage.ImagePcaF()
    mask = None
    for v in visits:
        im = mosaics[v]
        if not mask:
            mask = im.Factory(im.getDimensions())
            maska = mask.getArray()
            X, Y = np.meshgrid(np.arange(mask.getWidth()),
                               np.arange(mask.getHeight()))
            maska[np.where(np.hypot(X - 571, Y - 552) > 531)] = np.nan
            del maska

            mask[168:184, 701:838] = np.nan
            mask[667:733, 420:556] = np.nan
            mask[653:677, 548:570] = np.nan
            mask[1031:1047, 274:414] = np.nan

            if False:
                mask[866:931, 697:828] = np.nan
                mask[267:334, 145:276] = np.nan

        im += mask

        pca.addImage(im, afwMath.makeStatistics(im, afwMath.SUM).getValue())
    pca.analyze()

    eValues = np.array(pca.getEigenValues())
    eValues /= eValues[0]
    eImages = pca.getEigenImages()
    #
    # Fiddle eigen images (we don't care about orthogonality)
    #
    if False:
        f10 = 0.1
        f20 = -0.3
        f30 = 0.55
        eImages[1].getArray()[:] += f10 * eImages[0].getArray()
        eImages[2].getArray()[:] += f20 * eImages[0].getArray()
        eImages[3].getArray()[:] += f30 * eImages[0].getArray()

    if nComponent:
        eImages = eImages[:nComponent]
    else:
        nComponent = len(eImages)
    #
    # Normalize
    #
    good = np.where(np.isfinite(eImages[0].getArray()))
    if normalizeEimages:
        for eim in eImages:
            eima = eim.getArray()
            eima /= 1e-3 * np.sqrt(np.sum(eima[good]**2))
    #
    # Plot/display eigen values/images
    #
    frame = frame0
    if showEigen:
        for i in range(len(eImages)):
            ds9.mtv(eImages[i], frame=frame, title="%d %.2g" % (i, eValues[i]))
            ds9.ds9Cmd("scale linear; scale mode zscale")
            frame += 1

        pyplot.clf()
        if log:
            eValues = np.log10(eValues)
        pyplot.plot(eValues)
        pyplot.plot(eValues, marker='o')
        pyplot.xlim(-0.5, len(eValues))
        pyplot.ylim(max(-5, pyplot.ylim()[0]), 0.05 if log else 1.05)
        pyplot.xlabel("n")
        pyplot.ylabel(r"$lg(\lambda)$" if log else r"$\lambda$")
        pyplot.show()

    if showOriginal or showRecon or showResiduals:
        #
        # Expand input images in the (modified) eImages
        #
        A = np.empty(nComponent * nComponent).reshape((nComponent, nComponent))
        b = np.empty(nComponent)
        for v in visits:
            im = mosaics[v]
            if scale:
                im /= afwMath.makeStatistics(im, afwMath.MEANCLIP).getValue()

            for i in range(nComponent):
                b[i] = np.dot(eImages[i].getArray()[good], im.getArray()[good])

                for j in range(i, nComponent):
                    A[i, j] = np.dot(eImages[i].getArray()[good],
                                     eImages[j].getArray()[good])
                    A[j, i] = A[i, j]

            x = np.linalg.solve(A, b)
            #print v, A, b, x
            print "%d [%s] %s" % (v, ", ".join(["%9.2e" % _ for _ in x / x[0]
                                                ]), labels.get(v, ""))

            recon = eImages[0].clone()
            recon *= x[0]
            recona = recon.getArray()
            for i in range(1, nComponent):
                recona += x[i] * eImages[i].getArray()

            mtv = True
            if showOriginal or showRecon:
                if mtv:
                    ds9.mtv(im if showOriginal else recon,
                            frame=frame,
                            title=v)
                else:
                    ds9.erase(frame=frame)
                s0 = afwMath.makeStatistics(recon, afwMath.MEDIAN).getValue()
                s0 -= 0.5 * rng[0]
                ds9.ds9Cmd("scale linear; scale limits %g %g" %
                           (s0, s0 + rng[0]),
                           frame=frame)
                ds9.dot("%s %d" % ("orig" if showOriginal else "resid", v),
                        int(0.5 * im.getWidth()),
                        int(0.15 * im.getHeight()),
                        frame=frame,
                        ctype=ds9.RED)
                if labels.has_key(v):
                    ds9.dot(labels[v],
                            int(0.5 * im.getWidth()),
                            int(0.85 * im.getHeight()),
                            frame=frame,
                            ctype=ds9.RED)

                frame += 1

            if showResiduals:
                recon -= im
                if mtv:
                    ds9.mtv(recon, frame=frame)
                else:
                    ds9.erase(frame=frame)
                s0 = 0
                s0 -= 0.5 * rng[1]
                ds9.ds9Cmd("scale linear; scale limits %g %g" %
                           (s0, s0 + rng[1]),
                           frame=frame)

                frame += 1

    return eImages
Пример #19
0
def diffs(mosaics,
          visits,
          refVisit=None,
          scale=True,
          raw=None,
          rng=20,
          IRatioMax=1.0,
          frame0=0,
          verbose=False):
    """Display a series of differences and/or scaled differences
    (scale = True, False, (True, False), ...)
    """

    visits = list(visits)  # in case it's an iterator, and to get a copy

    if refVisit is None:
        refVisit = visits[0]

    ref = mosaics[refVisit]
    nameRef = str(refVisit)
    refMedian = float(np.median(ref.getArray()))

    visits = [v for v in visits if v != refVisit]

    try:
        scale[0]
    except TypeError:
        scale = (scale, )

    frame = frame0
    goodVisits = [refVisit]
    for v2 in visits:
        for s in scale:
            nameA, nameB = str(v2), nameRef
            diff = mosaics[v2].clone()

            IRatio = np.median(mosaics[v2].getArray()) / refMedian
            if IRatioMax and IRatio > IRatioMax and IRatio < 1 / IRatioMax:
                if verbose:
                    print "Skipping %d [ratio = %.2f]" % (v2, IRatio)
                break

            if s == scale[0]:
                goodVisits.append(v2)

            if s:
                diff /= IRatio
                nameA = "%s/%.2f" % (nameA, IRatio)

            diffa = diff.getArray()
            good = np.where(np.isfinite(diffa))
            v2Median = np.mean(diffa[good])

            if raw:
                title = nameA
            else:
                diff -= ref
                if IRatio < 1:
                    diff *= -1
                    nameA, nameB = nameB, nameA

                if verbose:
                    print "%s %5.1f%% %-s" % (v2, 100 * np.mean(diffa[good]) /
                                              v2Median, labels.get(v2, ""))

                title = "%s - %s" % (nameA, nameB)
                if not s:
                    title += " [rat=%.2f]" % (IRatio)

            if True:
                ds9.mtv(diff, title=title, frame=frame)
            else:
                ds9.erase(frame=frame)

            ds9.dot(title,
                    int(0.5 * diff.getWidth()),
                    int(0.05 * diff.getHeight()),
                    frame=frame,
                    ctype=ds9.RED)
            if labels.has_key(v2):
                ds9.dot(labels[v2],
                        int(0.5 * diff.getWidth()),
                        int(0.95 * diff.getHeight()),
                        frame=frame,
                        ctype=ds9.RED)

            s0 = 0 if (s and not raw) else afwMath.makeStatistics(
                diff, afwMath.MEDIAN).getValue()
            s0 -= 0.5 * rng
            ds9.ds9Cmd("scale linear; scale limits %g %g" % (s0, s0 + rng),
                       frame=frame)

            frame += 1

    return list(sorted(goodVisits))
Пример #20
0
                for i, c in zip(range(min(len(badCandidates), numBad)), badCandidates):
                    cand = candidates[c]
                    if display:
                        print "Spatial clipping %d (%f,%f) based on %d: %f vs %f" % \
                              (cand.getSource().getId(), cand.getXCenter(), cand.getYCenter(), k,
                               residuals[badCandidates[i],k], self.config.spatialReject * rms)
                    cand.setStatus(afwMath.SpatialCellCandidate.BAD)

            #
            # Display results
            #
            if display and displayIterations:
                if displayExposure:
                    if iter > 0:
                        ds9.erase(frame=frame)
                    maUtils.showPsfSpatialCells(exposure, psfCellSet, self.config.nStarPerCell, showChi2=True,
                                                symb="o", size=8, frame=frame,
                                                ctype=ds9.YELLOW, ctypeBad=ds9.RED, ctypeUnused=ds9.MAGENTA)
                    if self.config.nStarPerCellSpatialFit != self.config.nStarPerCell:
                        maUtils.showPsfSpatialCells(exposure, psfCellSet, self.config.nStarPerCellSpatialFit,
                                                    symb="o", size=10, frame=frame,
                                                    ctype=ds9.YELLOW, ctypeBad=ds9.RED)
                if displayResiduals:
                    while True:
                        try:
                            maUtils.showPsfCandidates(exposure, psfCellSet, psf=psf, frame=4,
                                                      normalize=normalizeResiduals,
                                                      showBadCandidates=showBadCandidates)
                            maUtils.showPsfCandidates(exposure, psfCellSet, psf=psf, frame=5,
                                                      normalize=normalizeResiduals,
Пример #21
0
def imagePca(mosaics, visits=None, nComponent=3, log=False, rng=30,
             showEigen=True, showResiduals=False, showOriginal=True, showRecon=False,
             normalizeEimages=True, scale=False, frame0=0, verbose=False):

    if showOriginal and showRecon:
        raise RuntimeError("You may not specify both showOriginal and showRecon")

    try:
        rng[0]
    except TypeError:
        rng = [rng, rng]

    if not visits:
        visits = sorted(mosaics.keys())

    mosaics = mosaics.copy()
    for v in visits:
        mosaics[v] = mosaics[v].clone()

    pca = afwImage.ImagePcaF()
    mask = None
    for v in visits:
        im = mosaics[v]
        if not mask:
            mask = im.Factory(im.getDimensions())
            maska = mask.getArray()
            X, Y = np.meshgrid(np.arange(mask.getWidth()), np.arange(mask.getHeight()))
            maska[np.where(np.hypot(X - 571, Y - 552) > 531)] = np.nan
            del maska

            mask[ 168: 184, 701:838] = np.nan
            mask[ 667: 733, 420:556] = np.nan
            mask[ 653: 677, 548:570] = np.nan
            mask[1031:1047, 274:414] = np.nan

            if False:
                mask[866:931, 697:828] = np.nan
                mask[267:334, 145:276] = np.nan

        im += mask

        pca.addImage(im, afwMath.makeStatistics(im, afwMath.SUM).getValue())
    pca.analyze()

    eValues = np.array(pca.getEigenValues())
    eValues /= eValues[0]
    eImages = pca.getEigenImages()
    #
    # Fiddle eigen images (we don't care about orthogonality)
    #
    if False:
        f10 =  0.1
        f20 = -0.3
        f30 =  0.55
        eImages[1].getArray()[:] += f10*eImages[0].getArray()
        eImages[2].getArray()[:] += f20*eImages[0].getArray()
        eImages[3].getArray()[:] += f30*eImages[0].getArray()

    if nComponent:
        eImages = eImages[:nComponent]
    else:
        nComponent = len(eImages)
    #
    # Normalize
    #
    good = np.where(np.isfinite(eImages[0].getArray()))
    if normalizeEimages:
        for eim in eImages:
            eima = eim.getArray()
            eima /= 1e-3*np.sqrt(np.sum(eima[good]**2))
    #
    # Plot/display eigen values/images
    #
    frame = frame0
    if showEigen:
        for i in range(len(eImages)):
            ds9.mtv(eImages[i], frame=frame, title="%d %.2g" % (i, eValues[i]))
            ds9.ds9Cmd("scale linear; scale mode zscale")
            frame += 1

        pyplot.clf()
        if log:
            eValues = np.log10(eValues)
        pyplot.plot(eValues)
        pyplot.plot(eValues, marker='o')
        pyplot.xlim(-0.5, len(eValues))
        pyplot.ylim(max(-5, pyplot.ylim()[0]), 0.05 if log else 1.05)
        pyplot.xlabel("n")
        pyplot.ylabel(r"$lg(\lambda)$" if log else r"$\lambda$")
        pyplot.show()

    if showOriginal or showRecon or showResiduals:
        #
        # Expand input images in the (modified) eImages
        #
        A = np.empty(nComponent*nComponent).reshape((nComponent, nComponent))
        b = np.empty(nComponent)
        for v in visits:
            im = mosaics[v]
            if scale:
                im /= afwMath.makeStatistics(im, afwMath.MEANCLIP).getValue()

            for i in range(nComponent):
                b[i] = np.dot(eImages[i].getArray()[good], im.getArray()[good])

                for j in range(i, nComponent):
                    A[i, j] = np.dot(eImages[i].getArray()[good], eImages[j].getArray()[good])
                    A[j, i] = A[i, j]

            x = np.linalg.solve(A, b)
            #print v, A, b, x
            print "%d [%s] %s" % (v, ", ".join(["%9.2e" % _ for _ in x/x[0]]), labels.get(v, ""))

            recon = eImages[0].clone(); recon *= x[0]
            recona = recon.getArray()
            for i in range(1, nComponent):
                recona += x[i]*eImages[i].getArray()

            mtv = True
            if showOriginal or showRecon:
                if mtv:
                    ds9.mtv(im if showOriginal else recon, frame=frame, title=v)
                else:
                    ds9.erase(frame=frame)
                s0 = afwMath.makeStatistics(recon, afwMath.MEDIAN).getValue()
                s0 -= 0.5*rng[0]
                ds9.ds9Cmd("scale linear; scale limits %g %g" % (s0, s0 + rng[0]), frame=frame)
                ds9.dot("%s %d" % ("orig" if showOriginal else "resid", v),
                        int(0.5*im.getWidth()), int(0.15*im.getHeight()), frame=frame, ctype=ds9.RED)
                if labels.has_key(v):
                    ds9.dot(labels[v], int(0.5*im.getWidth()), int(0.85*im.getHeight()),
                            frame=frame, ctype=ds9.RED)

                frame += 1

            if showResiduals:
                recon -= im
                if mtv:
                    ds9.mtv(recon, frame=frame)
                else:
                    ds9.erase(frame=frame)
                s0 = 0
                s0 -= 0.5*rng[1]
                ds9.ds9Cmd("scale linear; scale limits %g %g" % (s0, s0 + rng[1]), frame=frame)

                frame += 1

    return eImages
Пример #22
0
def diffs(mosaics, visits, refVisit=None, scale=True, raw=None,
          rng=20, IRatioMax=1.0, frame0=0, verbose=False):
    """Display a series of differences and/or scaled differences
    (scale = True, False, (True, False), ...)
    """

    visits = list(visits)               # in case it's an iterator, and to get a copy

    if refVisit is None:
        refVisit = visits[0]

    ref = mosaics[refVisit]
    nameRef = str(refVisit)
    refMedian = float(np.median(ref.getArray()))

    visits = [v for v in visits if v != refVisit]

    try:
        scale[0]
    except TypeError:
        scale = (scale,)

    frame = frame0
    goodVisits = [refVisit]
    for v2 in visits:
        for s in scale:
            nameA, nameB = str(v2), nameRef
            diff = mosaics[v2].clone()

            IRatio = np.median(mosaics[v2].getArray())/refMedian
            if IRatioMax and IRatio > IRatioMax and IRatio < 1/IRatioMax:
                if verbose:
                    print "Skipping %d [ratio = %.2f]" % (v2, IRatio)
                break

            if s == scale[0]:
                goodVisits.append(v2)

            if s:
                diff /= IRatio
                nameA = "%s/%.2f" % (nameA, IRatio)

            diffa = diff.getArray()
            good = np.where(np.isfinite(diffa))
            v2Median = np.mean(diffa[good])

            if raw:
                title = nameA
            else:
                diff -= ref
                if IRatio < 1:
                    diff *= -1
                    nameA, nameB = nameB, nameA

                if verbose:
                    print "%s %5.1f%% %-s" % (v2, 100*np.mean(diffa[good])/v2Median, labels.get(v2, ""))

                title = "%s - %s" % (nameA, nameB)
                if not s:
                    title += " [rat=%.2f]" % (IRatio)

            if True:
                ds9.mtv(diff, title=title, frame=frame)
            else:
                ds9.erase(frame=frame)

            ds9.dot(title, int(0.5*diff.getWidth()), int(0.05*diff.getHeight()),
                    frame=frame, ctype=ds9.RED)
            if labels.has_key(v2):
                ds9.dot(labels[v2], int(0.5*diff.getWidth()), int(0.95*diff.getHeight()),
                        frame=frame, ctype=ds9.RED)

            s0 = 0 if (s and not raw) else afwMath.makeStatistics(diff, afwMath.MEDIAN).getValue()
            s0 -= 0.5*rng
            ds9.ds9Cmd("scale linear; scale limits %g %g" % (s0, s0 + rng), frame=frame)

            frame += 1

    return list(sorted(goodVisits))
Пример #23
0
def prepareFrames(mos, frame0=1, R=100, medianN=23, onlyVisits=[], nJob=1, force=False):
    """Prepare frames to have their radial profiles measured.
Subtract the first quartile
Set a radius R circle about the centre of Arcturus to NaN
Set a chip with a bad QE value to NaN
Median filter with a medianN x medianN filter

The results are set as mos[-visit]

If onlyVisits is specified, only process those chips [n.b. frame0 is still obeyed]; otherwise
process every visit in the positions dict
    """
    visits = sorted(position.keys())

    visits0 = visits[:]  # needed to keep frame numbers aligned
    if not force:
        visits = [v for v in visits if not -v in mos]  # don't process ones we've already seen
    if onlyVisits:
        visits = [v for v in visits if v in onlyVisits]

    width, height = mos[visits[0]].getDimensions()
    X, Y = np.meshgrid(np.arange(width), np.arange(height))

    for v in visits:
        im = mos[v].clone()
        mos[-v] = im
        im[2121:2230, 590:830] = np.nan  # QE for this chip is bad

        ima = im.getArray()
        im[:] -= np.percentile(ima, 25)

        xc, yc = position[v]
        xc -= im.getX0()
        yc -= im.getY0()

        ima[np.hypot(X - xc, Y - yc) < R] = np.nan
    #
    # multiprocessing
    #
    worker = MedianFilterImageWorker(mos, medianN)
    if nJob > 1:
        pool = multiprocessing.Pool(max([len(visits), nJob]))

        # We use map_async(...).get(9999) instead of map(...) to workaround a python bug
        # in handling ^C in subprocesses (http://bugs.python.org/issue8296)
        for v, im in pool.map_async(worker, visits).get(9999):
            mos[-v] = im

        pool.close()
        pool.join()
    else:
        for v in visits:
            mos[-v] = worker(v)
    #
    # Display
    #
    frame = frame0 - 1
    for v in visits0:
        frame += 1

        if v not in visits:
            continue

        im = mos[-v]

        if True:
            ds9.mtv(im, title=v, frame=frame)
        else:
            ds9.erase(frame=frame)

        xc, yc = position[v]
        xc -= im.getX0()
        yc -= im.getY0()

        ds9.dot("o", xc, yc, size=R, frame=frame, ctype=ds9.GREEN if yc < im.getHeight() else ds9.RED)