def subtractMaskedImages(self,
                             templateMaskedImage,
                             scienceMaskedImage,
                             candidateList,
                             templateFwhmPix=None,
                             scienceFwhmPix=None):
        """!Psf-match and subtract two MaskedImages

        Do the following, in order:
        - PSF-match templateMaskedImage to scienceMaskedImage
        - Determine the differential background
        - Return the difference: scienceMaskedImage -
            ((warped templateMaskedImage convolved with psfMatchingKernel) + backgroundModel)

        @param templateMaskedImage: MaskedImage to PSF-match to scienceMaskedImage
        @param scienceMaskedImage: reference MaskedImage
        @param templateFwhmPix: FWHM (in pixels) of the Psf in the template image (image to convolve)
        @param scienceFwhmPix: FWHM (in pixels) of the Psf in the science image
        @param candidateList: a list of footprints/maskedImages for kernel candidates;
                              if None then source detection is run.
            - Currently supported: list of Footprints or measAlg.PsfCandidateF

        @return a pipeBase.Struct containing these fields:
        - subtractedMaskedImage = scienceMaskedImage - (matchedImage + backgroundModel)
        - matchedImage: templateMaskedImage convolved with psfMatchingKernel
        - psfMatchingKernel: PSF matching kernel
        - backgroundModel: differential background model
        - kernelCellSet: SpatialCellSet used to determine PSF matching kernel
        """
        if not candidateList:
            raise RuntimeError(
                "Candidate list must be populated by makeCandidateList")

        results = self.matchMaskedImages(
            templateMaskedImage=templateMaskedImage,
            scienceMaskedImage=scienceMaskedImage,
            candidateList=candidateList,
            templateFwhmPix=templateFwhmPix,
            scienceFwhmPix=scienceFwhmPix,
        )

        subtractedMaskedImage = afwImage.MaskedImageF(scienceMaskedImage, True)
        subtractedMaskedImage -= results.matchedImage
        subtractedMaskedImage -= results.backgroundModel
        results.subtractedMaskedImage = subtractedMaskedImage

        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displayDiffIm = lsstDebug.Info(__name__).displayDiffIm
        maskTransparency = lsstDebug.Info(__name__).maskTransparency
        if not maskTransparency:
            maskTransparency = 0
        if display:
            ds9.setMaskTransparency(maskTransparency)
        if display and displayDiffIm:
            ds9.mtv(subtractedMaskedImage, frame=lsstDebug.frame)
            lsstDebug.frame += 1

        return results
Beispiel #2
0
def selectPsfSources(exposure, matches, psfPolicy):
    """Get a list of suitable stars to construct a PSF."""

    import lsstDebug
    display = lsstDebug.Info(__name__).display
    displayExposure = lsstDebug.Info(__name__).displayExposure     # display the Exposure + spatialCells
    #
    # Unpack policy
    #
    kernelSize = psfPolicy.get("kernelSize")
    borderWidth = psfPolicy.get("borderWidth")
    sizePsfCellX = psfPolicy.get("sizeCellX")
    sizePsfCellY = psfPolicy.get("sizeCellY")
    #
    mi = exposure.getMaskedImage()

    if display and displayExposure:
        disp = afwDisplay.Display(frame=0)
        disp.mtv(mi, title="PSF candidates")

    psfCellSet = afwMath.SpatialCellSet(mi.getBBox(), sizePsfCellX, sizePsfCellY)
    psfStars = []

    for val in matches:
        ref, source = val[0:2]
        if not (ref.getFlagForDetection() & measAlg.Flags.STAR) or \
               (source.getFlagForDetection() & measAlg.Flags.BAD):
            continue

        try:
            cand = measAlg.makePsfCandidate(source, mi)
            #
            # The setXXX methods are class static, but it's convenient to call them on
            # an instance as we don't know Exposure's pixel type (and hence cand's exact type)
            if cand.getWidth() == 0:
                cand.setBorderWidth(borderWidth)
                cand.setWidth(kernelSize + 2*borderWidth)
                cand.setHeight(kernelSize + 2*borderWidth)

            im = cand.getMaskedImage().getImage()
            max = afwMath.makeStatistics(im, afwMath.MAX).getValue()
            if not np.isfinite(max):
                continue

            psfCellSet.insertCandidate(cand)

            if display and displayExposure:
                disp.dot("+", source.getXAstrom() - mi.getX0(), source.getYAstrom() - mi.getY0(),
                         size=4, ctype=afwDisplay.CYAN)
                disp.dot("o", source.getXAstrom() - mi.getX0(), source.getYAstrom() - mi.getY0(),
                         size=4, ctype=afwDisplay.CYAN)
        except Exception:
            continue

        source.setFlagForDetection(source.getFlagForDetection() | measAlg.Flags.STAR)
        psfStars += [source]

    return psfStars, psfCellSet
Beispiel #3
0
    def distort(self, sourceCat, exposure):
        """!Calculate distorted source positions

        CCD images are often affected by optical distortion that makes
        the astrometric solution higher order than linear.  Unfortunately,
        most (all?) matching algorithms require that the distortion be
        small or zero, and so it must be removed.  We do this by calculating
        (un-)distorted positions, based on a known optical distortion model
        in the Ccd.

        The distortion correction moves sources, so we return the distorted bounding box.

        \param[in]     exposure Exposure to process
        \param[in,out] sourceCat  SourceCatalog; getX() and getY() will be used as inputs,
                                with distorted points in "centroid.distorted" field.
        \return bounding box of distorted exposure
        """
        detector = exposure.getDetector()
        pixToTanXYTransform = None
        if detector is None:
            self.log.warn(
                "No detector associated with exposure; assuming null distortion"
            )
        else:
            tanSys = detector.makeCameraSys(TAN_PIXELS)
            pixToTanXYTransform = detector.getTransformMap().get(tanSys)

        if pixToTanXYTransform is None:
            self.log.info("Null distortion correction")
            for s in sourceCat:
                s.set(self.centroidKey, s.getCentroid())
                s.set(self.centroidErrKey, s.getCentroidErr())
                s.set(self.centroidFlagKey, s.getCentroidFlag())
            return exposure.getBBox()

        # Distort source positions
        self.log.info("Applying distortion correction")
        for s in sourceCat:
            centroid = pixToTanXYTransform.forwardTransform(s.getCentroid())
            s.set(self.centroidKey, centroid)
            s.set(self.centroidErrKey, s.getCentroidErr())
            s.set(self.centroidFlagKey, s.getCentroidFlag())

        # Get distorted image size so that astrometry_net does not clip.
        bboxD = afwGeom.Box2D()
        for corner in detector.getCorners(TAN_PIXELS):
            bboxD.include(corner)

        if lsstDebug.Info(__name__).display:
            frame = lsstDebug.Info(__name__).frame
            pause = lsstDebug.Info(__name__).pause
            displayAstrometry(sourceCat=sourceCat,
                              distortedCentroidKey=self.centroidKey,
                              exposure=exposure,
                              frame=frame,
                              pause=pause)

        return afwGeom.Box2I(bboxD)
    def displayDipoles(self, exposure, sources):
        """!Display debugging information on the detected dipoles

        @param exposure  Image the dipoles were measured on
        @param sources   The set of diaSources that were measured"""

        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displayDiaSources = lsstDebug.Info(__name__).displayDiaSources
        maskTransparency = lsstDebug.Info(__name__).maskTransparency
        if not maskTransparency:
            maskTransparency = 90
        ds9.setMaskTransparency(maskTransparency)
        ds9.mtv(exposure, frame=lsstDebug.frame)

        if display and displayDiaSources:
            with ds9.Buffering():
                for source in sources:
                    cenX, cenY = source.get("ipdiffim_DipolePsfFlux_centroid")
                    if np.isinf(cenX) or np.isinf(cenY):
                        cenX, cenY = source.getCentroid()

                    isdipole = source.get("classification.dipole")
                    if isdipole and np.isfinite(isdipole):
                        # Dipole
                        ctype = "green"
                    else:
                        # Not dipole
                        ctype = "red"

                    ds9.dot("o",
                            cenX,
                            cenY,
                            size=2,
                            ctype=ctype,
                            frame=lsstDebug.frame)

                    negCenX = source.get(
                        "ip_diffim_PsfDipoleFlux_neg_centroid_x")
                    negCenY = source.get(
                        "ip_diffim_PsfDipoleFlux_neg_centroid_y")
                    posCenX = source.get(
                        "ip_diffim_PsfDipoleFlux_pos_centroid_x")
                    posCenY = source.get(
                        "ip_diffim_PsfDipoleFlux_pos_centroid_y")
                    if (np.isinf(negCenX) or np.isinf(negCenY)
                            or np.isinf(posCenX) or np.isinf(posCenY)):
                        continue

                    ds9.line([(negCenX, negCenY), (posCenX, posCenY)],
                             ctype="yellow",
                             frame=lsstDebug.frame)

            lsstDebug.frame += 1
Beispiel #5
0
    def displayDipoles(self, exposure, sources):
        """Display debugging information on the detected dipoles

        Parameters
        ----------
        exposure : `lsst.afw.image.Exposure`
            Image the dipoles were measured on
        sources : `lsst.afw.table.SourceCatalog`
            The set of diaSources that were measured"""

        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displayDiaSources = lsstDebug.Info(__name__).displayDiaSources
        maskTransparency = lsstDebug.Info(__name__).maskTransparency
        if not maskTransparency:
            maskTransparency = 90
        disp = afwDisplay.Display(frame=lsstDebug.frame)
        disp.setMaskTransparency(maskTransparency)
        disp.mtv(exposure)

        if display and displayDiaSources:
            with disp.Buffering():
                for source in sources:
                    cenX, cenY = source.get("ipdiffim_DipolePsfFlux_centroid")
                    if np.isinf(cenX) or np.isinf(cenY):
                        cenX, cenY = source.getCentroid()

                    isdipole = source.get(
                        "ip_diffim_ClassificationDipole_value")
                    if isdipole and np.isfinite(isdipole):
                        # Dipole
                        ctype = afwDisplay.GREEN
                    else:
                        # Not dipole
                        ctype = afwDisplay.RED

                    disp.dot("o", cenX, cenY, size=2, ctype=ctype)

                    negCenX = source.get(
                        "ip_diffim_PsfDipoleFlux_neg_centroid_x")
                    negCenY = source.get(
                        "ip_diffim_PsfDipoleFlux_neg_centroid_y")
                    posCenX = source.get(
                        "ip_diffim_PsfDipoleFlux_pos_centroid_x")
                    posCenY = source.get(
                        "ip_diffim_PsfDipoleFlux_pos_centroid_y")
                    if (np.isinf(negCenX) or np.isinf(negCenY)
                            or np.isinf(posCenX) or np.isinf(posCenY)):
                        continue

                    disp.line([(negCenX, negCenY), (posCenX, posCenY)],
                              ctype=afwDisplay.YELLOW)

            lsstDebug.frame += 1
Beispiel #6
0
    def select(self, exposure, matches, psfPolicy):
        """Get a list of suitable stars to construct a PSF."""

        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displayExposure = lsstDebug.Info(__name__).displayExposure     # display the Exposure + spatialCells
        #
        # Unpack policy
        #
        kernelSize   = psfPolicy["kernelSizeMin"]
        borderWidth  = psfPolicy["borderWidth"]
        #
        mi = exposure.getMaskedImage()

        if display and displayExposure:
            frame = 0
            ds9.mtv(mi, frame=frame, title="PSF candidates")

        psfCandidates = []

        for val in matches:
            ref, source = val[0:2]
            if not (ref.getFlagForDetection() & measAlg.Flags.STAR) or \
                   (source.getFlagForDetection() & measAlg.Flags.BAD):
                continue
            if source.getPsfFlux() <= 0.0:
                continue
            
            try:
                cand = measAlg.makePsfCandidate(source, mi)
                #
                # The setXXX methods are class static, but it's convenient to call them on
                # an instance as we don't know Exposure's pixel type (and hence cand's exact type)
                if cand.getWidth() == 0:
                    cand.setBorderWidth(borderWidth)
                    cand.setWidth(kernelSize + 2*borderWidth)
                    cand.setHeight(kernelSize + 2*borderWidth)

                im = cand.getImage().getImage()
                max = afwMath.makeStatistics(im, afwMath.MAX).getValue()
                if not numpy.isfinite(max):
                    continue

                if display and displayExposure:
                    ds9.dot("+", source.getXAstrom() - mi.getX0(), source.getYAstrom() - mi.getY0(),
                            size=4, frame=frame, ctype=ds9.CYAN)
                    ds9.dot("o", source.getXAstrom() - mi.getX0(), source.getYAstrom() - mi.getY0(),
                            size=4, frame=frame, ctype=ds9.CYAN)
            except Exception, e:
                continue

            source.setFlagForDetection(source.getFlagForDetection() | measAlg.Flags.STAR)
            psfCandidates.append(cand)
Beispiel #7
0
    def determinePsf(self, exposure, psfCandidateList, metadata=None, flagKey=None):
        """
        @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 psf
        """

        import lsstDebug
        display = lsstDebug.Info(__name__).display 
        displayExposure = display and \
            lsstDebug.Info(__name__).displayExposure     # display the Exposure + spatialCells 
        displayPsfCandidates = display and \
            lsstDebug.Info(__name__).displayPsfCandidates # show the viable candidates 
        displayPsfComponents = display and \
            lsstDebug.Info(__name__).displayPsfComponents # show the basis functions
        showBadCandidates = display and \
            lsstDebug.Info(__name__).showBadCandidates # Include bad candidates (meaningless, methinks)
        displayResiduals = display and \
            lsstDebug.Info(__name__).displayResiduals         # show residuals
        displayPsfMosaic = display and \
            lsstDebug.Info(__name__).displayPsfMosaic   # show mosaic of reconstructed PSF(x,y)
        matchKernelAmplitudes = lsstDebug.Info(__name__).matchKernelAmplitudes # match Kernel amplitudes for spatial plots
        normalizeResiduals = lsstDebug.Info(__name__).normalizeResiduals # Normalise residuals by object amplitude 

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

        #
        # How big should our PSF models be?
        #
        if display:                     # only needed for debug plots
            # construct and populate a spatial cell set
            bbox = mi.getBBox(afwImage.PARENT)
            psfCellSet = afwMath.SpatialCellSet(bbox, self.config.sizeCellX, self.config.sizeCellY)
        else:
            psfCellSet = None
        
        sizes = np.empty(nCand)
        for i, psfCandidate in enumerate(psfCandidateList):
            try:
                if psfCellSet:
                    psfCellSet.insertCandidate(psfCandidate)
            except Exception, e:
                self.debugLog.debug(2, "Skipping PSF candidate %d of %d: %s" % (i, len(psfCandidateList), e))
                continue

            source = psfCandidate.getSource()
            quad = afwEll.Quadrupole(source.getIxx(), source.getIyy(), source.getIxy())
            rmsSize = quad.getTraceRadius()
            sizes[i] = rmsSize
Beispiel #8
0
    def cosmicray(self, exposure, psf):
        """Cosmic ray masking

        @param exposure Exposure to process
        @param psf PSF
        """
        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displayCR = lsstDebug.Info(__name__).displayCR

        assert exposure, "No exposure provided"
        assert psf, "No psf provided"
        # Blow away old mask
        try:
            mask = exposure.getMaskedImage().getMask()
            crBit = mask.getMaskPlane("CR")
            mask.clearMaskPlane(crBit)
        except:
            pass

        if display and displayCR:
            ds9.incrDefaultFrame()
            ds9.mtv(exposure, title="Pre-CR")

        policy = self.config['cosmicray'].getPolicy()
        mi = exposure.getMaskedImage()
        bg = afwMath.makeStatistics(mi, afwMath.MEDIAN).getValue()
        crs = measAlg.findCosmicRays(mi, psf, bg, policy, self._keepCRs)
        num = 0
        if crs is not None:
            mask = mi.getMask()
            crBit = mask.getPlaneBitMask("CR")
            afwDet.setMaskFromFootprintList(mask, crs, crBit)
            num = len(crs)

            if display and displayCR:
                ds9.incrDefaultFrame()
                ds9.mtv(exposure, title="Post-CR")

                ds9.cmdBuffer.pushSize()

                for cr in crs:
                    displayUtils.drawBBox(cr.getBBox(), borderWidth=0.55)

                ds9.cmdBuffer.popSize()

        self.log.log(self.log.INFO, "Identified %d cosmic rays." % num)
        return
Beispiel #9
0
    def __init__(self, config=None, name=None, parentTask=None, log=None):
        self.metadata = dafBase.PropertyList()
        self._parentTask = parentTask

        if parentTask is not None:
            if name is None:
                raise RuntimeError("name is required for a subtask")
            self._name = name
            self._fullName = parentTask._computeFullName(name)
            if config is None:
                config = getattr(parentTask.config, name)
            self._taskDict = parentTask._taskDict
            loggerName = parentTask.log.getName() + '.' + name
        else:
            if name is None:
                name = getattr(self, "_DefaultName", None)
                if name is None:
                    raise RuntimeError(
                        "name is required for a task unless it has attribute _DefaultName"
                    )
                name = self._DefaultName
            self._name = name
            self._fullName = self._name
            if config is None:
                config = self.ConfigClass()
            self._taskDict = dict()
            loggerName = self._fullName
            if log is not None and log.getName():
                loggerName = log.getName() + '.' + loggerName

        self.log = Log.getLogger(loggerName)
        self.config = config
        self._display = lsstDebug.Info(self.__module__).display
        self._taskDict[self._fullName] = self
    def run(self, dataRef):
        """!Compute a few statistics on the image plane of an exposure
        
        @param dataRef: data reference for a calibrated science exposure ("calexp")
        @return a pipeBase Struct containing:
        - mean: mean of image plane
        - meanErr: uncertainty in mean
        - stdDev: standard deviation of image plane
        - stdDevErr: uncertainty in standard deviation
        """
        self.log.info("Processing data ID %s" % (dataRef.dataId, ))
        if self.config.doFail:
            raise pipeBase.TaskError(
                "Raising TaskError by request (config.doFail=True)")

        # Unpersist the raw exposure pointed to by the data reference
        rawExp = dataRef.get("raw")
        maskedImage = rawExp.getMaskedImage()

        # Support extra debug output.
        # -
        import lsstDebug
        display = lsstDebug.Info(__name__).display
        if display:
            frame = 1
            mtv(rawExp, frame=frame, title="exposure")

        # return the pipe_base Struct that is returned by self.stats.run
        return self.stats.run(maskedImage)
Beispiel #11
0
    def __init__(
        self,
        config: Optional[Config] = None,
        name: Optional[str] = None,
        parentTask: Optional[Task] = None,
        log: Optional[Union[logging.Logger,
                            lsst.utils.logging.LsstLogAdapter]] = None,
    ):
        self.metadata = _TASK_METADATA_TYPE()
        self.__parentTask: Optional[weakref.ReferenceType]
        self.__parentTask = parentTask if parentTask is None else weakref.ref(
            parentTask)

        if parentTask is not None:
            if name is None:
                raise RuntimeError("name is required for a subtask")
            self._name = name
            self._fullName = parentTask._computeFullName(name)
            if config is None:
                config = getattr(parentTask.config, name)
            self._taskDict: Dict[
                str, weakref.ReferenceType[Task]] = parentTask._taskDict
            loggerName = parentTask.log.getChild(name).name
        else:
            if name is None:
                name = getattr(self, "_DefaultName", None)
                if name is None:
                    raise RuntimeError(
                        "name is required for a task unless it has attribute _DefaultName"
                    )
                name = self._DefaultName
            self._name = name
            self._fullName = self._name
            if config is None:
                config = self.ConfigClass()
            self._taskDict = dict()
            loggerName = self._fullName
            if log is not None and log.name:
                loggerName = log.getChild(loggerName).name
            elif self._add_module_logger_prefix:
                # Prefix the logger name with the root module name.
                # We want all Task loggers to have this prefix to make
                # it easier to control them. This can be disabled by
                # a Task setting the class property _add_module_logger_prefix
                # to False -- in which case the logger name will not be
                # modified.
                module_name = self.__module__
                module_root = module_name.split(".")[0] + "."
                if not loggerName.startswith(module_root):
                    loggerName = module_root + loggerName

        # Get a logger (that might be a subclass of logging.Logger).
        self.log: lsst.utils.logging.LsstLogAdapter = lsst.utils.logging.getLogger(
            loggerName)
        self.config: Config = config
        if lsstDebug:
            self._display = lsstDebug.Info(self.__module__).display
        else:
            self._display = None
        self._taskDict[self._fullName] = weakref.ref(self)
Beispiel #12
0
    def detectFootprints(self,
                         exposure,
                         doSmooth=True,
                         sigma=None,
                         clearMask=True):
        """Detect footprints.

        @param exposure Exposure to process; DETECTED{,_NEGATIVE} mask plane will be set in-place.
        @param doSmooth if True, smooth the image before detection using a Gaussian of width sigma
        @param sigma    sigma of PSF (pixels); used for smoothing and to grow detections;
            if None then measure the sigma of the PSF of the exposure
        @param clearMask Clear both DETECTED and DETECTED_NEGATIVE planes before running detection

        @return a lsst.pipe.base.Struct with fields:
        - positive: lsst.afw.detection.FootprintSet with positive polarity footprints (may be None)
        - negative: lsst.afw.detection.FootprintSet with negative polarity footprints (may be None)
        - numPos: number of footprints in positive or 0 if detection polarity was negative
        - numNeg: number of footprints in negative or 0 if detection polarity was positive
        - background: re-estimated background.  None if reEstimateBackground==False
        
        @raise pipe_base TaskError if sigma=None and the exposure has no PSF
        """
        try:
            import lsstDebug
            display = lsstDebug.Info(__name__).display
        except ImportError, e:
            try:
                display
            except NameError:
                display = False
Beispiel #13
0
def estimateBackground(exposure,
                       backgroundConfig,
                       subtract=True,
                       stats=True,
                       statsKeys=None):
    """
    Estimate exposure's background using parameters in backgroundConfig.  
    If subtract is true, make a copy of the exposure and subtract the background.  
    If `stats` is True, measure the mean and variance of the background and
    add them to the background-subtracted exposure's metadata with keys
    "BGMEAN" and "BGVAR", or the keys given in `statsKeys` (2-tuple of strings).
    
    Return background, backgroundSubtractedExposure
    """

    displayBackground = lsstDebug.Info(__name__).displayBackground

    maskedImage = exposure.getMaskedImage()

    background = getBackground(maskedImage, backgroundConfig)

    if not background:
        raise RuntimeError, "Unable to estimate background for exposure"

    bgimg = None

    if displayBackground > 1:
        bgimg = background.getImageF()
        ds9.mtv(bgimg, title="background", frame=3)

    if not subtract:
        return background, None

    bbox = maskedImage.getBBox(afwImage.PARENT)
    backgroundSubtractedExposure = exposure.Factory(exposure, bbox,
                                                    afwImage.PARENT, True)
    copyImage = backgroundSubtractedExposure.getMaskedImage().getImage()
    if bgimg is None:
        bgimg = background.getImageF()
    copyImage -= bgimg

    # Record statistics of the background in the bgsub exposure metadata.
    # (lsst.daf.base.PropertySet)
    if stats:
        if statsKeys is None:
            mnkey = 'BGMEAN'
            varkey = 'BGVAR'
        else:
            mnkey, varkey = statsKeys
        meta = backgroundSubtractedExposure.getMetadata()
        s = afwMath.makeStatistics(bgimg, afwMath.MEAN | afwMath.VARIANCE)
        bgmean = s.getValue(afwMath.MEAN)
        bgvar = s.getValue(afwMath.VARIANCE)
        meta.addDouble(mnkey, bgmean)
        meta.addDouble(varkey, bgvar)

    if displayBackground:
        ds9.mtv(backgroundSubtractedExposure, title="subtracted")

    return background, backgroundSubtractedExposure
Beispiel #14
0
    def debugView(self, image, model):
        """Debug display for the final overscan solution.

        Parameters
        ----------
        image : `lsst.afw.image.Image`
            Input image the overscan solution was determined from.
        model : `numpy.ndarray` or `float`
            Overscan model determined for the image.
        """
        import lsstDebug
        if not lsstDebug.Info(__name__).display:
            return

        calcImage = self.getImageArray(image)
        calcImage, isTransposed = self.transpose(calcImage)
        masked = self.maskOutliers(calcImage)
        collapsed = self.collapseArray(masked)

        num = len(collapsed)
        indices = 2.0 * np.arange(num) / float(num) - 1.0

        if np.ma.is_masked(collapsed):
            collapsedMask = collapsed.mask
        else:
            collapsedMask = np.array(num * [np.ma.nomask])

        import matplotlib.pyplot as plot
        figure = plot.figure(1)
        figure.clear()
        axes = figure.add_axes((0.1, 0.1, 0.8, 0.8))
        axes.plot(indices[~collapsedMask], collapsed[~collapsedMask], 'k+')
        if collapsedMask.sum() > 0:
            axes.plot(indices[collapsedMask], collapsed.data[collapsedMask],
                      'b+')
        if isinstance(model, np.ndarray):
            plotModel = model
        else:
            plotModel = np.zeros_like(indices)
            plotModel += model
        axes.plot(indices, plotModel, 'r-')
        plot.xlabel("centered/scaled position along overscan region")
        plot.ylabel("pixel value/fit value")
        figure.show()
        prompt = "Press Enter or c to continue [chp]..."
        while True:
            ans = input(prompt).lower()
            if ans in (
                    "",
                    " ",
                    "c",
            ):
                break
            elif ans in ("p", ):
                import pdb
                pdb.set_trace()
            elif ans in ("h", ):
                print("[h]elp [c]ontinue [p]db")
        plot.close()
Beispiel #15
0
    def loadAndMatch(self, exposure, sourceCat):
        """!Load reference objects overlapping an exposure and match to sources detected on that exposure

        @param[in] exposure  exposure that the sources overlap
        @param[in] sourceCat  catalog of sources detected on the exposure (an lsst.afw.table.SourceCatalog)

        @return an lsst.pipe.base.Struct with these fields:
        - refCat  reference object catalog of objects that overlap the exposure (with some margin)
            (an lsst::afw::table::SimpleCatalog)
        - matches  a list of lsst.afw.table.ReferenceMatch
        - matchMeta  metadata needed to unpersist matches (an lsst.daf.base.PropertyList)

        @note ignores config.matchDistanceSigma
        """
        import lsstDebug
        debug = lsstDebug.Info(__name__)

        matchMeta = createMatchMetadata(
            exposure, border=self.refObjLoader.config.pixelMargin)
        expMd = self._getExposureMetadata(exposure)

        loadRes = self.refObjLoader.loadPixelBox(
            bbox=expMd.bbox,
            wcs=expMd.wcs,
            filterName=expMd.filterName,
            calib=expMd.calib,
        )

        matchRes = self.matcher.matchObjectsToSources(
            refCat=loadRes.refCat,
            sourceCat=sourceCat,
            wcs=expMd.wcs,
            refFluxField=loadRes.fluxField,
            match_tolerance=None,
        )

        distStats = self._computeMatchStatsOnSky(matchRes.matches)
        self.log.info(
            "Found %d matches with scatter = %0.3f +- %0.3f arcsec; " %
            (len(matchRes.matches), distStats.distMean.asArcseconds(),
             distStats.distStdDev.asArcseconds()))

        if debug.display:
            frame = int(debug.frame)
            displayAstrometry(
                refCat=loadRes.refCat,
                sourceCat=sourceCat,
                matches=matchRes.matches,
                exposure=exposure,
                bbox=expMd.bbox,
                frame=frame,
                title="Matches",
            )

        return pipeBase.Struct(
            refCat=loadRes.refCat,
            matches=matchRes.matches,
            matchMeta=matchMeta,
        )
Beispiel #16
0
    def run(self, exposure, fringes, seed=None):
        """Remove fringes from the provided science exposure.

        Primary method of FringeTask.  Fringes are only subtracted if the
        science exposure has a filter listed in the configuration.

        Parameters
        ----------
        exposure : `lsst.afw.image.Exposure`
            Science exposure from which to remove fringes.
        fringes : `lsst.afw.image.Exposure` or `list` thereof
            Calibration fringe files containing master fringe frames.
        seed : `int`, optional
            Seed for random number generation.

        Returns
        -------
        solution : `np.array`
            Fringe solution amplitudes for each input fringe frame.
        rms : `float`
            RMS error for the fit solution for this exposure.
        """
        import lsstDebug
        display = lsstDebug.Info(__name__).display

        if not self.checkFilter(exposure):
            self.log.info(
                "Filter not found in FringeTaskConfig.filters. Skipping fringe correction."
            )
            return

        if seed is None:
            seed = self.config.stats.rngSeedOffset
        rng = numpy.random.RandomState(seed=seed)

        if not hasattr(fringes, '__iter__'):
            fringes = [fringes]

        mask = exposure.getMaskedImage().getMask()
        for fringe in fringes:
            fringe.getMaskedImage().getMask().__ior__(mask)
            if self.config.pedestal:
                self.removePedestal(fringe)

        positions = self.generatePositions(fringes[0], rng)
        fluxes = numpy.ndarray([self.config.num, len(fringes)])
        for i, f in enumerate(fringes):
            fluxes[:, i] = self.measureExposure(f,
                                                positions,
                                                title="Fringe frame")

        expFringes = self.measureExposure(exposure, positions, title="Science")
        solution, rms = self.solve(expFringes, fluxes)
        self.subtract(exposure, fringes, solution)
        if display:
            afwDisplay.Display(frame=getFrame()).mtv(exposure,
                                                     title="Fringe subtracted")
        return solution, rms
Beispiel #17
0
    def measureExposure(self, exposure, positions, title="Fringe"):
        """Measure fringe amplitudes for an exposure

        The fringe amplitudes are measured as the statistic within a square
        aperture.  The statistic within a larger aperture are subtracted so
        as to remove the background.

        Parameters
        ----------
        exposure : `lsst.afw.image.Exposure`
            Exposure to measure the positions on.
        positions : `numpy.array`
            Two-dimensional array containing the positions to sample
            for fringe amplitudes.
        title : `str`, optional
            Title used for debug out plots.

        Returns
        -------
        fringes : `numpy.array`
            Array of measured exposure values at each of the positions
            supplied.
        """
        stats = afwMath.StatisticsControl()
        stats.setNumSigmaClip(self.config.stats.clip)
        stats.setNumIter(self.config.stats.iterations)
        stats.setAndMask(exposure.getMaskedImage().getMask().getPlaneBitMask(
            self.config.stats.badMaskPlanes))

        num = self.config.num
        fringes = numpy.ndarray(num)

        for i in range(num):
            x, y = positions[i]
            small = measure(exposure.getMaskedImage(), x, y, self.config.small,
                            self.config.stats.stat, stats)
            large = measure(exposure.getMaskedImage(), x, y, self.config.large,
                            self.config.stats.stat, stats)
            fringes[i] = small - large

        import lsstDebug
        display = lsstDebug.Info(__name__).display
        if display:
            disp = afwDisplay.Display(frame=getFrame())
            disp.mtv(exposure, title=title)
            if False:
                with disp.Buffering():
                    for x, y in positions:
                        corners = numpy.array([[-1, -1], [1, -1], [1, 1],
                                               [-1, 1], [-1, -1]]) + [[x, y]]
                        disp.line(corners * self.config.small,
                                  ctype=afwDisplay.GREEN)
                        disp.line(corners * self.config.large,
                                  ctype=afwDisplay.BLUE)

        return fringes
Beispiel #18
0
    def display(self, exposure, results, convolvedImage=None):
        """Display detections if so configured

        Displays the ``exposure`` in frame 0, overlays the detection peaks.

        Requires that ``lsstDebug`` has been set up correctly, so that
        ``lsstDebug.Info("lsst.meas.algorithms.detection")`` evaluates `True`.

        If the ``convolvedImage`` is non-`None` and
        ``lsstDebug.Info("lsst.meas.algorithms.detection") > 1``, the
        ``convolvedImage`` will be displayed in frame 1.

        Parameters
        ----------
        exposure : `lsst.afw.image.Exposure`
            Exposure to display, on which will be plotted the detections.
        results : `lsst.pipe.base.Struct`
            Results of the 'detectFootprints' method, containing positive and
            negative footprints (which contain the peak positions that we will
            plot). This is a `Struct` with ``positive`` and ``negative``
            elements that are of type `lsst.afw.detection.FootprintSet`.
        convolvedImage : `lsst.afw.image.Image`, optional
            Convolved image used for thresholding.
        """
        try:
            import lsstDebug
            display = lsstDebug.Info(__name__).display
        except ImportError:
            try:
                display
            except NameError:
                display = False
        if not display:
            return

        afwDisplay.setDefaultMaskTransparency(75)

        disp0 = afwDisplay.Display(frame=0)
        disp0.mtv(exposure, title="detection")

        def plotPeaks(fps, ctype):
            if fps is None:
                return
            with disp0.Buffering():
                for fp in fps.getFootprints():
                    for pp in fp.getPeaks():
                        disp0.dot("+", pp.getFx(), pp.getFy(), ctype=ctype)
        plotPeaks(results.positive, "yellow")
        plotPeaks(results.negative, "red")

        if convolvedImage and display > 1:
            disp1 = afwDisplay.Display(frame=1)
            disp1.mtv(convolvedImage, title="PSF smoothed")

        disp2 = afwDisplay.Display(frame=2)
        disp2.mtv(afwImage.ImageF(np.sqrt(exposure.variance.array)), title="stddev")
Beispiel #19
0
    def __init__(self, config=None, name=None, parentTask=None, log=None):
        """!Create a Task

        @param[in] config       configuration for this task (an instance of self.ConfigClass,
            which is a task-specific subclass of lsst.pex.config.Config), or None. If None:
            - If parentTask specified then defaults to parentTask.config.\<name>
            - If parentTask is None then defaults to self.ConfigClass()
        @param[in] name         brief name of task, or None; if None then defaults to self._DefaultName
        @param[in] parentTask   the parent task of this subtask, if any.
            - If None (a top-level task) then you must specify config and name is ignored.
            - If not None (a subtask) then you must specify name
        @param[in] log          log (an lsst.log.Log) whose name is used as a log name prefix,
            or None for no prefix. Ignored if parentTask specifie, in which case parentTask.log's
            name is used as a prefix.
            The task's log name is `prefix + "." + name` if a prefix exists, else `name`.
            The task's log is then a child logger of parentTask.log (if parentTask specified),
            or a child logger of the log from the argument (if log is not None).

        @throw RuntimeError if parentTask is None and config is None.
        @throw RuntimeError if parentTask is not None and name is None.
        @throw RuntimeError if name is None and _DefaultName does not exist.
        """
        self.metadata = dafBase.PropertyList()
        self._parentTask = parentTask

        if parentTask is not None:
            if name is None:
                raise RuntimeError("name is required for a subtask")
            self._name = name
            self._fullName = parentTask._computeFullName(name)
            if config is None:
                config = getattr(parentTask.config, name)
            self._taskDict = parentTask._taskDict
            loggerName = parentTask.log.getName() + '.' + name
        else:
            if name is None:
                name = getattr(self, "_DefaultName", None)
                if name is None:
                    raise RuntimeError("name is required for a task unless it has attribute _DefaultName")
                name = self._DefaultName
            self._name = name
            self._fullName = self._name
            if config is None:
                config = self.ConfigClass()
            self._taskDict = dict()
            loggerName = self._fullName
            if log is not None and log.getName():
                loggerName = log.getName() + '.' + loggerName

        self.log = Log.getLogger(loggerName)
        self.config = config
        self._display = lsstDebug.Info(self.__module__).display
        self._taskDict[self._fullName] = self
Beispiel #20
0
    def _displayDebug(self, kernelCellSet, spatialKernel, spatialBackground):
        """Provide visualization of the inputs and ouputs to the Psf-matching code

        Parameters
        ----------
        kernelCellSet : `lsst.afw.math.SpatialCellSet`
            The SpatialCellSet used in determining the matching kernel and background
        spatialKernel : `lsst.afw.math.LinearCombinationKernel`
            Spatially varying Psf-matching kernel
        spatialBackground : `lsst.afw.math.Function2D`
            Spatially varying background-matching function
        """
        import lsstDebug
        displayCandidates = lsstDebug.Info(__name__).displayCandidates
        displayKernelBasis = lsstDebug.Info(__name__).displayKernelBasis
        displayKernelMosaic = lsstDebug.Info(__name__).displayKernelMosaic
        plotKernelSpatialModel = lsstDebug.Info(
            __name__).plotKernelSpatialModel
        showBadCandidates = lsstDebug.Info(__name__).showBadCandidates
        maskTransparency = lsstDebug.Info(__name__).maskTransparency
        if not maskTransparency:
            maskTransparency = 0
        afwDisplay.setDefaultMaskTransparency(maskTransparency)

        if displayCandidates:
            diutils.showKernelCandidates(kernelCellSet,
                                         kernel=spatialKernel,
                                         background=spatialBackground,
                                         frame=lsstDebug.frame,
                                         showBadCandidates=showBadCandidates)
            lsstDebug.frame += 1
            diutils.showKernelCandidates(kernelCellSet,
                                         kernel=spatialKernel,
                                         background=spatialBackground,
                                         frame=lsstDebug.frame,
                                         showBadCandidates=showBadCandidates,
                                         kernels=True)
            lsstDebug.frame += 1
            diutils.showKernelCandidates(kernelCellSet,
                                         kernel=spatialKernel,
                                         background=spatialBackground,
                                         frame=lsstDebug.frame,
                                         showBadCandidates=showBadCandidates,
                                         resids=True)
            lsstDebug.frame += 1

        if displayKernelBasis:
            diutils.showKernelBasis(spatialKernel, frame=lsstDebug.frame)
            lsstDebug.frame += 1

        if displayKernelMosaic:
            diutils.showKernelMosaic(kernelCellSet.getBBox(),
                                     spatialKernel,
                                     frame=lsstDebug.frame)
            lsstDebug.frame += 1

        if plotKernelSpatialModel:
            diutils.plotKernelSpatialModel(spatialKernel,
                                           kernelCellSet,
                                           showBadCandidates=showBadCandidates)
Beispiel #21
0
    def selectStars(self, exposure, sourceCat, matches=None):
        """!Return a list of PSF candidates that represent likely stars

        A list of PSF candidates may be used by a PSF fitter to construct a PSF.

        @param[in] exposure  the exposure containing the sources
        @param[in] sourceCat  catalog of sources that may be stars (an lsst.afw.table.SourceCatalog)
        @param[in] matches  a match vector as produced by meas_astrom; required
                            (defaults to None to match the StarSelector API and improve error handling)

        @return an lsst.pipe.base.Struct containing:
        - starCat  catalog of selected stars (a subset of sourceCat)
        """
        import lsstDebug
        debugInfo = lsstDebug.Info(__name__)
        display = debugInfo.display
        pauseAtEnd = debugInfo.pauseAtEnd  # pause when done

        if matches is None:
            raise RuntimeError("CatalogStarSelectorTask requires matches")

        mi = exposure.getMaskedImage()

        if display:
            frame = 1
            ds9.mtv(mi, frame=frame, title="PSF candidates")

        isGoodSource = CheckSource(sourceCat, self.config.fluxLim,
                                   self.config.fluxMax, self.config.badFlags)

        starCat = SourceCatalog(sourceCat.schema)
        with ds9.Buffering():
            for ref, source, d in matches:
                if not ref.get("resolved"):
                    if not isGoodSource(source):
                        symb, ctype = "+", ds9.RED
                    else:
                        starCat.append(source)
                        symb, ctype = "+", ds9.GREEN

                        if display:
                            ds9.dot(symb,
                                    source.getX() - mi.getX0(),
                                    source.getY() - mi.getY0(),
                                    size=4,
                                    frame=frame,
                                    ctype=ctype)

        if display and pauseAtEnd:
            input("Continue? y[es] p[db] ")

        return Struct(starCat=starCat, )
Beispiel #22
0
def getBackground(image, backgroundConfig, nx=0, ny=0, algorithm=None):
    """
    Make a new Exposure which is exposure - background
    """
    backgroundConfig.validate()

    if not nx:
        nx = image.getWidth() // backgroundConfig.binSize + 1
    if not ny:
        ny = image.getHeight() // backgroundConfig.binSize + 1

    displayBackground = lsstDebug.Info(__name__).displayBackground
    if displayBackground:
        import itertools
        ds9.mtv(image, frame=1)
        xPosts = numpy.rint(
            numpy.linspace(0, image.getWidth() + 1, num=nx, endpoint=True))
        yPosts = numpy.rint(
            numpy.linspace(0, image.getHeight() + 1, num=ny, endpoint=True))
        with ds9.Buffering():
            for (xMin, xMax), (yMin, yMax) in itertools.product(
                    zip(xPosts[:-1], xPosts[1:]), zip(yPosts[:-1],
                                                      yPosts[1:])):
                ds9.line([(xMin, yMin), (xMin, yMax), (xMax, yMax),
                          (xMax, yMin), (xMin, yMin)],
                         frame=1)

    sctrl = afwMath.StatisticsControl()
    sctrl.setAndMask(
        reduce(lambda x, y: x | image.getMask().getPlaneBitMask(y),
               backgroundConfig.ignoredPixelMask, 0x0))
    sctrl.setNanSafe(backgroundConfig.isNanSafe)

    pl = pexLogging.Debug("meas.utils.sourceDetection.getBackground")
    pl.debug(
        3, "Ignoring mask planes: %s" %
        ", ".join(backgroundConfig.ignoredPixelMask))

    if not algorithm:
        algorithm = backgroundConfig.algorithm

    bctrl = afwMath.BackgroundControl(algorithm, nx, ny,
                                      backgroundConfig.undersampleStyle, sctrl,
                                      backgroundConfig.statisticsProperty)

    if backgroundConfig.useApprox:
        actrl = afwMath.ApproximateControl(
            afwMath.ApproximateControl.CHEBYSHEV, backgroundConfig.approxOrder)
        bctrl.setApproximateControl(actrl)

    return afwMath.makeBackground(image, bctrl)
Beispiel #23
0
    def loadAndMatch(self, exposure, sourceCat, bbox=None):
        """!Load reference objects overlapping an exposure and match to sources detected on that exposure

        @param[in] exposure  exposure whose WCS is to be fit
        @param[in] sourceCat  catalog of sourceCat detected on the exposure (an lsst.afw.table.SourceCatalog)
        @param[in] bbox  bounding box go use for finding reference objects; if None, use exposure's bbox

        @return an lsst.pipe.base.Struct with these fields:
        - refCat  reference object catalog of objects that overlap the exposure (with some margin)
            (an lsst::afw::table::SimpleCatalog)
        - matches  astrometric matches, a list of lsst.afw.table.ReferenceMatch
        - matchMeta  metadata about the field (an lsst.daf.base.PropertyList)

        @note ignores config.forceKnownWcs
        """
        with self.distortionContext(sourceCat=sourceCat,
                                    exposure=exposure) as bbox:
            if not self.solver:
                self.makeSubtask("solver")

            astrom = self.solver.useKnownWcs(
                sourceCat=sourceCat,
                exposure=exposure,
                bbox=bbox,
                calculateSip=False,
            )

            if astrom is None or astrom.getWcs() is None:
                raise RuntimeError("Unable to solve astrometry")

            matches = astrom.getMatches()
            matchMeta = astrom.getMatchMetadata()
            if matches is None or len(matches) == 0:
                raise RuntimeError("No astrometric matches")
            self.log.info("%d astrometric matches" % (len(matches)))

            if self._display:
                frame = lsstDebug.Info(__name__).frame
                displayAstrometry(exposure=exposure,
                                  sourceCat=sourceCat,
                                  matches=matches,
                                  frame=frame,
                                  pause=False)

            return pipeBase.Struct(
                refCat=astrom.refCat,
                matches=matches,
                matchMeta=matchMeta,
            )
Beispiel #24
0
    def _displayDebug(self, kernelCellSet, spatialKernel, spatialBackground):
        """!Provide visualization of the inputs and ouputs to the Psf-matching code

        @param kernelCellSet: the SpatialCellSet used in determining the matching kernel and background
        @param spatialKernel: spatially varying Psf-matching kernel
        @param spatialBackground: spatially varying background-matching function

        """
        import lsstDebug
        displayCandidates = lsstDebug.Info(__name__).displayCandidates
        displayKernelBasis = lsstDebug.Info(__name__).displayKernelBasis
        displayKernelMosaic = lsstDebug.Info(__name__).displayKernelMosaic
        plotKernelSpatialModel = lsstDebug.Info(
            __name__).plotKernelSpatialModel
        showBadCandidates = lsstDebug.Info(__name__).showBadCandidates
        maskTransparency = lsstDebug.Info(__name__).maskTransparency
        if not maskTransparency:
            maskTransparency = 0
        ds9.setMaskTransparency(maskTransparency)

        if displayCandidates:
            diutils.showKernelCandidates(kernelCellSet,
                                         kernel=spatialKernel,
                                         background=spatialBackground,
                                         frame=lsstDebug.frame,
                                         showBadCandidates=showBadCandidates)
            lsstDebug.frame += 1
            diutils.showKernelCandidates(kernelCellSet,
                                         kernel=spatialKernel,
                                         background=spatialBackground,
                                         frame=lsstDebug.frame,
                                         showBadCandidates=showBadCandidates,
                                         kernels=True)
            lsstDebug.frame += 1
            diutils.showKernelCandidates(kernelCellSet,
                                         kernel=spatialKernel,
                                         background=spatialBackground,
                                         frame=lsstDebug.frame,
                                         showBadCandidates=showBadCandidates,
                                         resids=True)
            lsstDebug.frame += 1

        if displayKernelBasis:
            diutils.showKernelBasis(spatialKernel, frame=lsstDebug.frame)
            lsstDebug.frame += 1

        if displayKernelMosaic:
            diutils.showKernelMosaic(kernelCellSet.getBBox(),
                                     spatialKernel,
                                     frame=lsstDebug.frame)
            lsstDebug.frame += 1

        if plotKernelSpatialModel:
            diutils.plotKernelSpatialModel(spatialKernel,
                                           kernelCellSet,
                                           showBadCandidates=showBadCandidates)
    def _astrometry(self, sourceCat, exposure, bbox=None):
        """!Solve astrometry to produce WCS

        \param[in] sourceCat Sources on exposure, an lsst.afw.table.SourceCatalog
        \param[in,out] exposure Exposure to process, an lsst.afw.image.ExposureF or D; wcs is updated
        \param[in] bbox Bounding box, or None to use exposure
        \return a pipe.base.Struct with fields:
        - refCat  reference object catalog of objects that overlap the exposure (with some margin)
            (an lsst::afw::table::SimpleCatalog)
        - matches  astrometric matches, a list of lsst.afw.table.ReferenceMatch
        - matchMeta  metadata about the field (an lsst.daf.base.PropertyList)
        """
        self.log.info("Solving astrometry")
        if bbox is None:
            bbox = exposure.getBBox()

        if not self.solver:
            self.makeSubtask("solver")

        astrom = self.solver.determineWcs(sourceCat=sourceCat,
                                          exposure=exposure,
                                          bbox=bbox)

        if astrom is None or astrom.getWcs() is None:
            raise RuntimeError("Unable to solve astrometry")

        matches = astrom.getMatches()
        matchMeta = astrom.getMatchMetadata()
        if matches is None or len(matches) == 0:
            raise RuntimeError("No astrometric matches")
        self.log.info("%d astrometric matches" % (len(matches)))

        # Note that this is the Wcs for the provided positions, which may be distorted
        exposure.setWcs(astrom.getWcs())

        if self._display:
            frame = lsstDebug.Info(__name__).frame
            displayAstrometry(exposure=exposure,
                              sourceCat=sourceCat,
                              matches=matches,
                              frame=frame,
                              pause=False)

        return pipeBase.Struct(
            refCat=astrom.refCat,
            matches=matches,
            matchMeta=matchMeta,
        )
    def measureExposure(self, exposure, positions, title="Fringe"):
        """Measure fringe amplitudes for an exposure

        The fringe amplitudes are measured as the statistic within a square
        aperture.  The statistic within a larger aperture are subtracted so
        as to remove the background.

        @param exposure    Exposure to measure
        @param positions   Array of (x,y) for fringe measurement
        @param title       Title for display
        @return Array of fringe measurements
        """
        stats = afwMath.StatisticsControl()
        stats.setNumSigmaClip(self.config.stats.clip)
        stats.setNumIter(self.config.stats.iterations)
        stats.setAndMask(exposure.getMaskedImage().getMask().getPlaneBitMask(
            self.config.stats.badMaskPlanes))

        num = self.config.num
        fringes = numpy.ndarray(num)

        for i in range(num):
            x, y = positions[i]
            small = measure(exposure.getMaskedImage(), x, y, self.config.small,
                            self.config.stats.stat, stats)
            large = measure(exposure.getMaskedImage(), x, y, self.config.large,
                            self.config.stats.stat, stats)
            fringes[i] = small - large

        import lsstDebug
        display = lsstDebug.Info(__name__).display
        if display:
            frame = getFrame()
            ds9.mtv(exposure, frame=frame, title=title)
            if False:
                with ds9.Buffering():
                    for x, y in positions:
                        corners = numpy.array([[-1, -1], [1, -1], [1, 1],
                                               [-1, 1], [-1, -1]]) + [[x, y]]
                        ds9.line(corners * self.config.small,
                                 frame=frame,
                                 ctype="green")
                        ds9.line(corners * self.config.large,
                                 frame=frame,
                                 ctype="blue")

        return fringes
Beispiel #27
0
    def process(self, dataRef):
        """Process focus CCD in preparation for focus measurement

        @param dataRef: Data reference for CCD
        @return Struct(sources: source measurements,
                       ccdId: CCD number,
                       filterName: name of filter,
                       dims: exposure dimensions
                       )
        """
        import lsstDebug
        display = lsstDebug.Info(__name__).display

        exp = self.isr.runDataRef(dataRef).exposure

        if display:
            import lsst.afw.display.ds9 as ds9
            ds9.mtv(exp, title="Post-ISR", frame=1)

        self.installPsf.run(exposure=exp)
        bg, exp = measAlg.estimateBackground(exp, self.config.background, subtract=True)

        if display:
            ds9.mtv(exp, title="Post-background", frame=2)

        dmResults = self.detectAndMeasure.run(exp, dataRef.get("expIdInfo"))
        sources = dmResults.sourceCat

        self.starSelector.run(exp, sources, isStarField="hscPipeline_focus_candidate")

        if display:
            ds9.mtv(exp, title="Post-measurement", frame=3)
            with ds9.Buffering():
                for s in sources:
                    ds9.dot("o", s.getX(), s.getY(), frame=3,
                            ctype=ds9.GREEN if s.get("calib.psf.candidate") else ds9.RED)
            import pdb;pdb.set_trace() # pause to allow inspection

        filterName = exp.getFilter().getName()

        if self.config.doWrite:
            dataRef.put(sources, "src")
            dataRef.put(exp, "visitim")

        return Struct(sources=sources, ccdId=dataRef.dataId["ccd"], filterName=filterName,
                      dims=exp.getDimensions())
    def run(self, exposure, fringes, seed=None):
        """Remove fringes from the provided science exposure.

        Primary method of FringeTask.  Fringes are only subtracted if the
        science exposure has a filter listed in the configuration.

        @param exposure    Science exposure from which to remove fringes
        @param fringes     Exposure or list of Exposures
        @param seed        32-bit unsigned integer for random number generator
        """
        import lsstDebug
        display = lsstDebug.Info(__name__).display

        if not self.checkFilter(exposure):
            return

        if seed is None:
            seed = self.config.stats.rngSeedOffset
        rng = numpy.random.RandomState(seed=seed)

        if not hasattr(fringes, '__iter__'):
            fringes = [fringes]

        mask = exposure.getMaskedImage().getMask()
        for fringe in fringes:
            fringe.getMaskedImage().getMask().__ior__(mask)
            if self.config.pedestal:
                self.removePedestal(fringe)

        # Placeholder implementation for multiple fringe frames
        # This needs to be revisited in DM-4441
        positions = self.generatePositions(fringes[0], rng)
        fluxes = numpy.ndarray([self.config.num, len(fringes)])
        for i, f in enumerate(fringes):
            fluxes[:, i] = self.measureExposure(f,
                                                positions,
                                                title="Fringe frame")

        expFringes = self.measureExposure(exposure, positions, title="Science")
        solution = self.solve(expFringes, fluxes)
        self.subtract(exposure, fringes, solution)
        if display:
            ds9.mtv(exposure, title="Fringe subtracted", frame=getFrame())
Beispiel #29
0
    def __init__(self, *, butler=None, **kwargs):
        # TODO: rename psfRefObjLoader to refObjLoader
        super().__init__(**kwargs)
        self.makeSubtask("isr")
        self.makeSubtask("charImage", butler=butler, refObjLoader=None)

        self.debug = lsstDebug.Info(__name__)
        if self.debug.enabled:
            self.log.info("Running with debug enabled...")
            # If we're displaying, test it works and save displays for later.
            # It's worth testing here as displays are flaky and sometimes
            # can't be contacted, and given processing takes a while,
            # it's a shame to fail late due to display issues.
            if self.debug.display:
                try:
                    import lsst.afw.display as afwDisp
                    afwDisp.setDefaultBackend(self.debug.displayBackend)
                    afwDisp.Display.delAllDisplays()
                    # pick an unlikely number to be safe xxx replace this
                    self.disp1 = afwDisp.Display(987, open=True)

                    im = afwImage.ImageF(2, 2)
                    im.array[:] = np.ones((2, 2))
                    self.disp1.mtv(im)
                    self.disp1.erase()
                    afwDisp.setDefaultMaskTransparency(90)
                except NameError:
                    self.debug.display = False
                    self.log.warn(
                        'Failed to setup/connect to display! Debug display has been disabled'
                    )

        if self.debug.notHeadless:
            pass  # other backend options can go here
        else:  # this stop windows popping up when plotting. When headless, use 'agg' backend too
            plt.interactive(False)

        self.config.validate()
        self.config.freeze()
Beispiel #30
0
    def run(self, calexp):
        """Operate on in-memory data.

        Returns
        -------
        `Struct` instance with produced result.
        """
        _LOG.info("executing %s: calexp=%s", self.getName(), calexp)

        # To test lsstDebug function make a debug.py file with this contents
        # somewhere in PYTHONPATH and run `pipetask` with --debug option:
        #
        #    import lsstDebug
        #    lsstDebug.Info('lsst.ctrl.mpexec.examples.calexpToCoaddTask').display = True
        #
        if lsstDebug.Info(__name__).display:
            _LOG.info("%s: display enabled", __name__)

        # output data, scalar in this case
        data = ExposureF(100, 100)

        # attribute name of struct is the same as a config field name
        return Struct(coadd=data)