Пример #1
0
    def process(self):

        logging.Trace_setVerbosity("lsst.detection", 5)
        logging.Trace(
            "lsst.detection.DetectionStage", 3,
            'Python DetectionStage process : _rank %i stageId %d' %
            (self._rank, self.stageId))
        activeClipboard = self.inputQueue.getNextDataset()

        ###########
        #
        # Get objects from clipboard
        #
        triggerEvent = activeClipboard.get('triggerVisitEvent')
        filterNameItem = triggerEvent.findUnique('filterName')
        filterName = filterNameItem.getValueString()
        exposureIdItem = triggerEvent.findUnique('exposureId')
        exposureId = exposureIdItem.getValueInt()
        visitTimeItem = triggerEvent.findUnique('visitTime')
        visitTime = visitTimeItem.getValueDouble()
        ###########
        #
        # Log the beginning of Detection stage for this slice
        #
        LogRec(self.detectionLog, Log.INFO) \
                                  <<  "Began detection stage" \
                                  << DataProperty("exposureId", exposureId) \
                                  << DataProperty("visitTime", visitTime) \
                                  << DataProperty("filterName", filterName) \
                                  << LogRec.endr
        #
        # Instantiate a Filter object to get the id of filterName
        #
        dbLocation = dafper.LogicalLocation(
            'mysql://lsst10.ncsa.uiuc.edu:3306/test')
        filterDB = lsst.afw.image.Filter(dbLocation, filterName)
        filterId = filterDB.getId()
        logging.Trace("lsst.detection.DetectionStage", 3,
                      'FilterName %s FilterId %d' % (filterName, filterId))

        differenceImageExposure = activeClipboard.get('DifferenceExposure')

        diaSourceCollection = Detection.detection(
            differenceImageExposure=differenceImageExposure,
            policy=self._policy,
            filterId=filterId,
            useLog=self.detectionLog,
            footprintList=None,
        )

        ###########
        #
        # Post results to clipboard
        #
        activeClipboard.put('DiaSources', diaSourceCollection)

        self.outputQueue.addDataset(activeClipboard)
    def stats(self, cid, diffim, core=5):
        self.dStats.apply(diffim)
        pexLog.Trace("lsst.ip.diffim.JackknifeResampleKernel", 1,
                     "Candidate %d : Residuals all (%d px): %.3f +/- %.3f" % (cid,
                                                                              self.dStats.getNpix(),
                                                                              self.dStats.getMean(),
                                                                              self.dStats.getRms()))

        
        self.dStats.apply(diffim, core)
        pexLog.Trace("lsst.ip.diffim.JackknifeResampleKernel", 1,
                     "Candidate %d : Residuals core (%d px): %.3f +/- %.3f" % (cid,
                                                                               self.dStats.getNpix(),
                                                                               self.dStats.getMean(),
                                                                               self.dStats.getRms()))
Пример #3
0
    def _createPcaBasis(self, kernelCellSet, nStarPerCell, policy):
        """!Create Principal Component basis

        If a principal component analysis is requested, typically when using a delta function basis, 
        perform the PCA here and return a new basis list containing the new principal components.

        @param kernelCellSet: a SpatialCellSet containing KernelCandidates, from which components are derived
        @param nStarPerCell: the number of stars per cell to visit when doing the PCA
        @param policy: input policy controlling the single kernel visitor

        @return
        - nRejectedPca: number of KernelCandidates rejected during PCA loop
        - spatialBasisList: basis list containing the principal shapes as Kernels

        """
        nComponents = self.kConfig.numPrincipalComponents
        imagePca = diffimLib.KernelPcaD()
        importStarVisitor = diffimLib.KernelPcaVisitorF(imagePca)
        kernelCellSet.visitCandidates(importStarVisitor, nStarPerCell)
        if self.kConfig.subtractMeanForPca:
            importStarVisitor.subtractMean()
        imagePca.analyze()

        eigenValues = imagePca.getEigenValues()
        pcaBasisList = importStarVisitor.getEigenKernels()

        eSum = num.sum(eigenValues)
        if eSum == 0.0:
            raise RuntimeError("Eigenvalues sum to zero")
        for j in range(len(eigenValues)):
            pexLog.Trace(
                self.log.getName() + "._solve", 6, "Eigenvalue %d : %f (%f)" %
                (j, eigenValues[j], eigenValues[j] / eSum))

        nToUse = min(nComponents, len(eigenValues))
        trimBasisList = afwMath.KernelList()
        for j in range(nToUse):
            # Check for NaNs?
            kimage = afwImage.ImageD(pcaBasisList[j].getDimensions())
            pcaBasisList[j].computeImage(kimage, False)
            if not (True in num.isnan(kimage.getArray())):
                trimBasisList.push_back(pcaBasisList[j])

        # Put all the power in the first kernel, which will not vary spatially
        spatialBasisList = diffimLib.renormalizeKernelList(trimBasisList)

        # New Kernel visitor for this new basis list (no regularization explicitly)
        singlekvPca = diffimLib.BuildSingleKernelVisitorF(
            spatialBasisList, policy)
        singlekvPca.setSkipBuilt(False)
        kernelCellSet.visitCandidates(singlekvPca, nStarPerCell)
        singlekvPca.setSkipBuilt(True)
        nRejectedPca = singlekvPca.getNRejected()

        return nRejectedPca, spatialBasisList
    def assess(self, cand, kFn1, bgFn1, kFn2, bgFn2, frame0):
        tmi   = cand.getTemplateMaskedImage()
        smi   = cand.getScienceMaskedImage()
        
        im1   = afwImage.ImageD(kFn1.getDimensions())
        kFn1.computeImage(im1, False,
                          afwImage.indexToPosition(int(cand.getXCenter())),
                          afwImage.indexToPosition(int(cand.getYCenter())))
        fk1   = afwMath.FixedKernel(im1)
        bg1   = bgFn1(afwImage.indexToPosition(int(cand.getXCenter())),
                      afwImage.indexToPosition(int(cand.getYCenter())))
        d1    = ipDiffim.convolveAndSubtract(tmi, smi, fk1, bg1)

        ####
        
        im2   = afwImage.ImageD(kFn2.getDimensions())
        kFn2.computeImage(im2, False,
                          afwImage.indexToPosition(int(cand.getXCenter())),
                          afwImage.indexToPosition(int(cand.getYCenter())))
        fk2   = afwMath.FixedKernel(im2)
        bg2   = bgFn2(afwImage.indexToPosition(int(cand.getXCenter())),
                      afwImage.indexToPosition(int(cand.getYCenter())))
        d2    = ipDiffim.convolveAndSubtract(tmi, smi, fk2, bg2)

        if display:
            ds9.mtv(tmi, frame=frame0+0)
            ds9.dot("Cand %d" % (cand.getId()), 0, 0, frame=frame0+0)
            
            ds9.mtv(smi, frame=frame0+1)
            ds9.mtv(im1, frame=frame0+2)
            ds9.mtv(d1,  frame=frame0+3)
            ds9.mtv(im2, frame=frame0+4)
            ds9.mtv(d2,  frame=frame0+5)

        pexLog.Trace("lsst.ip.diffim.JackknifeResampleKernel", 1,
                     "Full Spatial Model")
        self.stats(cand.getId(), d1)

        pexLog.Trace("lsst.ip.diffim.JackknifeResampleKernel", 1,
                     "N-1 Spatial Model")
        self.stats(cand.getId(), d2)
    def jackknifeResample(self, psfmatch, results):
        
        kernel  = results.psfMatchingKernel
        bg      = results.backgroundModel
        cellSet = results.kernelCellSet
        
        goodList = []
        for cell in cellSet.getCellList():
            print
            for cand in cell.begin(False):
                cand = ipDiffim.cast_KernelCandidateF(cand)

                if cand.getStatus() == afwMath.SpatialCellCandidate.GOOD:
                    goodList.append(cand.getId())
                else:
                    # This is so that UNKNOWNs are not processed
                    cand.setStatus(afwMath.SpatialCellCandidate.BAD)

        nStarPerCell = self.config.nStarPerCell
        policy = pexConfig.makePolicy(self.config)
        for idx in range(len(goodList)):
            cid   = goodList[idx]

            print # clear the screen
            pexLog.Trace("lsst.ip.diffim.JackknifeResampleKernel", 1,
                         "Removing candidate %d" % (cid))
            
            cand = self.setStatus(cellSet, cid, afwMath.SpatialCellCandidate.BAD)

            # From _solve
            regionBBox = cellSet.getBBox()
            spatialkv  = ipDiffim.BuildSpatialKernelVisitorF(kernel.getKernelList(), regionBBox, policy)
            cellSet.visitCandidates(spatialkv, nStarPerCell)
            spatialkv.solveLinearEquation()
            jkKernel, jkBg = spatialkv.getSolutionPair()

            #jkResults = psfmatch._solve(cellSet, kernel.getKernelList())
            #jkKernel  = jkResults[1]
            #jkBg      = jkResults[2]

            # lots of windows
            # self.assess(cand, kernel, bg, jkKernel, jkBg, 6*idx+1)

            # only 6 windows
            self.assess(cand, kernel, bg, jkKernel, jkBg, 1)

            self.setStatus(cellSet, cid, afwMath.SpatialCellCandidate.GOOD)
    def runTest(self, mode):
        pexLog.Trace("lsst.ip.diffim.JackknifeResampleKernel", 1,
                     "Mode %s" % (mode))
        if mode == "DF":
            self.config = self.subconfigDF
        elif mode == "DFr":
            self.config = self.subconfigDFr
        elif mode == "AL":
            self.config = self.subconfigAL
        else:
            raise

        psfmatch = ipDiffim.ImagePsfMatchTask(self.config)
        results  = psfmatch.run(self.templateMaskedImage,
                                self.scienceMaskedImage, 
                                "subtractMaskedImages")
        self.jackknifeResample(psfmatch, results)
Пример #7
0
def backgroundSubtract(config, maskedImages):
    backgrounds = []
    t0 = time.time()
    algorithm   = config.algorithm
    binsize     = config.binSize
    undersample = config.undersampleStyle
    bctrl       = afwMath.BackgroundControl(algorithm)
    bctrl.setUndersampleStyle(undersample)
    for maskedImage in maskedImages:
        bctrl.setNxSample(maskedImage.getWidth()//binsize + 1)
        bctrl.setNySample(maskedImage.getHeight()//binsize + 1)
        image   = maskedImage.getImage() 
        backobj = afwMath.makeBackground(image, bctrl)

        image  -= backobj.getImageF()
        backgrounds.append(backobj.getImageF())
        del backobj

    t1 = time.time()
    pexLog.Trace("lsst.ip.diffim.backgroundSubtract", 1,
                 "Total time for background subtraction : %.2f s" % (t1-t0))
    return backgrounds
Пример #8
0
 def testTraceFromPython(self):
     pexLog.Trace.setVerbosity("lsst.afw", 3)
     pexLog.Trace("lsst.afw", 2, "Hello")
     pexLog.Trace("lsst.afw", 5, "world")
Пример #9
0
def EventFromInputFileList(inputfile, 
                           datatypePolicy, 
                           expTime=EXP_TIME,
                           slewTime=SLEW_TIME,
                           maxvisits=-1,
                           rootTopicName=ROOT_EVENT_TOPIC, 
                           hostName=EVENT_BROKER,
                           metadataPolicy=None):
    """
    Generate events for the IPSD (and MOPS) pipeline by reading a list of visit
    directories and extracting the relevant information from the FITS files 
    therein.

    The two optional parameters are the exposure time of each exposure in a 
    visit (assumed constant) and the average slew time of the telescope. Both 
    are in seconds. The default to 15 seconds and 5 seconds respecively.

    The script sends one event for the first visit exposure, waits <exp time> 
    sec and then sends an event for the second exposure. At that point, it 
    waits (<exp time> + <slew time>) sec before passing to the next visit.

    The input directory list is a simple text file listing visit directories 
    one per line. Comments start with a '#' and are ignored. It is assumed 
    that the name of each directory in the file is a valid visitId. Also it 
    is assumed that each directory has the following structure:
        visitId/
                0/
                  raw-<visitId>-e000-c<ccdId>-a<ampId>.fits
                1/
                  raw-<visitId>-e001-c<ccdId>-a<ampId>.fits
    
    @param inputfile        name of the directory list file.
    @param datatypePolicy   policy file for the input data.
    @param expTime          assumed exposure per visit in seconds (defaults 
                               to 15 seconds for DC3).
    @param slewTime         assumed average slew time in seconds (defaults 
                               to 5 seconds for DC3). 
    @param rootTopicName    root name for the event's topic. The final topic 
                               will be rootTopicName+'0' or rootTopicName+'1'
                               depending on whether the event refers to the
                               first or second image of the visit.
    @param hostName         hostname of the event broker.
    @param metadataPolicy   policy defining the event metadata types
    
    @return None
    """
    global visitCount
    
    # Create a metadata policy object.
    if metadataPolicy is None:
        mpf = pexPolicy.DefaultPolicyFile("ctrl_dc3pipe", 
                                          "dc3MetadataPolicy.paf", "pipeline")
        metadataPolicy = pexPolicy.Policy.createPolicy(mpf,
                                                       mpf.getRepositoryPath())
    
    # Covenience function.
    def sendEvent(f):
        return(eventFromFitsfile.EventFromInputfile(f, 
                                                    datatypePolicy, 
                                                    metadataPolicy,
                                                    rootTopicName, 
                                                    hostName))
    
    f = open(inputfile)
    for line in f:
        dirName = line.strip()
        if(line.startswith('#')):
            continue
        
        visitCount += 1
        if maxvisits >= 0 and visitCount > maxvisits:
            logger.log(logger.INFO,
                       "Maximum visit count reached (%s); quitting." %
                       maxvisits)
            return 
            
        # Get the list of amp FITS files in each dir.
        fileList0 = glob.glob(os.path.join(dirName, '0', '*.fits'))
        fileList1 = glob.glob(os.path.join(dirName, '1', '*.fits'))
        
        # Simple sanity check.
        if(len(fileList0) != len(fileList1)):
            pexLog.Trace('dc3pipe.eventfrominputfilelist', 1, 
                         'Skipping %s: wrong file count in 0 and 1' \
                         %(dirName))
            continue
        
        # Now we just trust that the i-th file in 0 corresponds to the i-th file
        # in 1... Fortunately, we only need to send one event per image 
        # directory, since all images there are one MEF split into individual 
        # amps.
        sendEvent(fileList0[0])
        # Sleep some.
        time.sleep(expTime)
        # Next event.
        sendEvent(fileList1[0])
        # Sleep expTime + slewTime.
        time.sleep(expTime + slewTime)
    f.close()
    return
Пример #10
0
    def _solve(self, kernelCellSet, basisList, returnOnExcept=False):
        """!Solve for the PSF matching kernel

        @param kernelCellSet: a SpatialCellSet to use in determining the matching kernel 
          (typically as provided by _buildCellSet)
        @param basisList: list of Kernels to be used in the decomposition of the spatially varying kernel 
          (typically as provided by makeKernelBasisList)
        @param returnOnExcept: if True then return (None, None) if an error occurs, else raise the exception

        @return
        - psfMatchingKernel: PSF matching kernel
        - backgroundModel: differential background model

        Raise Exception if unable to determine PSF matching kernel and returnOnExcept False
        """

        import lsstDebug
        display = lsstDebug.Info(__name__).display

        maxSpatialIterations = self.kConfig.maxSpatialIterations
        nStarPerCell = self.kConfig.nStarPerCell
        usePcaForSpatialKernel = self.kConfig.usePcaForSpatialKernel

        # Visitor for the single kernel fit
        policy = pexConfig.makePolicy(self.kConfig)
        if self.useRegularization:
            singlekv = diffimLib.BuildSingleKernelVisitorF(
                basisList, policy, self.hMat)
        else:
            singlekv = diffimLib.BuildSingleKernelVisitorF(basisList, policy)

        # Visitor for the kernel sum rejection
        ksv = diffimLib.KernelSumVisitorF(policy)

        # Main loop
        t0 = time.time()
        try:
            totalIterations = 0
            thisIteration = 0
            while (thisIteration < maxSpatialIterations):

                # Make sure there are no uninitialized candidates as active occupants of Cell
                nRejectedSkf = -1
                while (nRejectedSkf != 0):
                    pexLog.Trace(self.log.getName() + "._solve", 2,
                                 "Building single kernels...")
                    kernelCellSet.visitCandidates(singlekv, nStarPerCell)
                    nRejectedSkf = singlekv.getNRejected()
                    pexLog.Trace(
                        self.log.getName() + "._solve", 2,
                        "Iteration %d, rejected %d candidates due to initial kernel fit"
                        % (thisIteration, nRejectedSkf))

                # Reject outliers in kernel sum
                ksv.resetKernelSum()
                ksv.setMode(diffimLib.KernelSumVisitorF.AGGREGATE)
                kernelCellSet.visitCandidates(ksv, nStarPerCell)
                ksv.processKsumDistribution()
                ksv.setMode(diffimLib.KernelSumVisitorF.REJECT)
                kernelCellSet.visitCandidates(ksv, nStarPerCell)

                nRejectedKsum = ksv.getNRejected()
                pexLog.Trace(
                    self.log.getName() + "._solve", 2,
                    "Iteration %d, rejected %d candidates due to kernel sum" %
                    (thisIteration, nRejectedKsum))

                # Do we jump back to the top without incrementing thisIteration?
                if nRejectedKsum > 0:
                    totalIterations += 1
                    continue

                # At this stage we can either apply the spatial fit to
                # the kernels, or we run a PCA, use these as a *new*
                # basis set with lower dimensionality, and then apply
                # the spatial fit to these kernels

                if (usePcaForSpatialKernel):
                    pexLog.Trace(self.log.getName() + "._solve", 1,
                                 "Building Pca basis")

                    nRejectedPca, spatialBasisList = self._createPcaBasis(
                        kernelCellSet, nStarPerCell, policy)
                    pexLog.Trace(
                        self.log.getName() + "._solve", 2,
                        "Iteration %d, rejected %d candidates due to Pca kernel fit"
                        % (thisIteration, nRejectedPca))

                    # We don't want to continue on (yet) with the
                    # spatial modeling, because we have bad objects
                    # contributing to the Pca basis.  We basically
                    # need to restart from the beginning of this loop,
                    # since the cell-mates of those objects that were
                    # rejected need their original Kernels built by
                    # singleKernelFitter.

                    # Don't count against thisIteration
                    if (nRejectedPca > 0):
                        totalIterations += 1
                        continue
                else:
                    spatialBasisList = basisList

                # We have gotten on to the spatial modeling part
                regionBBox = kernelCellSet.getBBox()
                spatialkv = diffimLib.BuildSpatialKernelVisitorF(
                    spatialBasisList, regionBBox, policy)
                kernelCellSet.visitCandidates(spatialkv, nStarPerCell)
                spatialkv.solveLinearEquation()
                pexLog.Trace(
                    self.log.getName() + "._solve", 3,
                    "Spatial kernel built with %d candidates" %
                    (spatialkv.getNCandidates()))
                spatialKernel, spatialBackground = spatialkv.getSolutionPair()

                # Check the quality of the spatial fit (look at residuals)
                assesskv = diffimLib.AssessSpatialKernelVisitorF(
                    spatialKernel, spatialBackground, policy)
                kernelCellSet.visitCandidates(assesskv, nStarPerCell)
                nRejectedSpatial = assesskv.getNRejected()
                nGoodSpatial = assesskv.getNGood()
                pexLog.Trace(
                    self.log.getName() + "._solve", 2,
                    "Iteration %d, rejected %d candidates due to spatial kernel fit"
                    % (thisIteration, nRejectedSpatial))
                pexLog.Trace(self.log.getName() + "._solve", 2,
                             "%d candidates used in fit" % (nGoodSpatial))

                # If only nGoodSpatial == 0, might be other candidates in the cells
                if nGoodSpatial == 0 and nRejectedSpatial == 0:
                    raise RuntimeError("No kernel candidates for spatial fit")

                if nRejectedSpatial == 0:
                    # Nothing rejected, finished with spatial fit
                    break

                # Otherwise, iterate on...
                thisIteration += 1

            # Final fit if above did not converge
            if (nRejectedSpatial > 0) and (thisIteration
                                           == maxSpatialIterations):
                pexLog.Trace(self.log.getName() + "._solve", 2,
                             "Final spatial fit")
                if (usePcaForSpatialKernel):
                    nRejectedPca, spatialBasisList = self._createPcaBasis(
                        kernelCellSet, nStarPerCell, policy)
                regionBBox = kernelCellSet.getBBox()
                spatialkv = diffimLib.BuildSpatialKernelVisitorF(
                    spatialBasisList, regionBBox, policy)
                kernelCellSet.visitCandidates(spatialkv, nStarPerCell)
                spatialkv.solveLinearEquation()
                pexLog.Trace(
                    self.log.getName() + "._solve", 3,
                    "Spatial kernel built with %d candidates" %
                    (spatialkv.getNCandidates()))
                spatialKernel, spatialBackground = spatialkv.getSolutionPair()

            spatialSolution = spatialkv.getKernelSolution()

        except Exception as e:
            pexLog.Trace(self.log.getName() + "._solve", 1,
                         "ERROR: Unable to calculate psf matching kernel")
            pexLog.Trace(self.log.getName() + "._solve", 2, str(e))
            raise e

        t1 = time.time()
        pexLog.Trace(
            self.log.getName() + "._solve", 1,
            "Total time to compute the spatial kernel : %.2f s" % (t1 - t0))

        if display:
            self._displayDebug(kernelCellSet, spatialKernel, spatialBackground)

        self._diagnostic(kernelCellSet, spatialSolution, spatialKernel,
                         spatialBackground)

        return spatialSolution, spatialKernel, spatialBackground
Пример #11
0
    def matchMaskedImages(self,
                          templateMaskedImage,
                          scienceMaskedImage,
                          candidateList,
                          templateFwhmPix=None,
                          scienceFwhmPix=None):
        """!PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage)

        Do the following, in order:
        - Determine a PSF matching kernel and differential background model
            that matches templateMaskedImage to scienceMaskedImage
        - Convolve templateMaskedImage by the PSF matching kernel

        @param templateMaskedImage: masked image to PSF-match to the reference masked image;
            must be warped to match the reference masked image
        @param scienceMaskedImage: maskedImage whose PSF is to be matched to
        @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:
        - psfMatchedMaskedImage: the PSF-matched masked image =
            templateMaskedImage convolved with psfMatchingKernel.
            This has the same xy0, dimensions and wcs as scienceMaskedImage.
        - psfMatchingKernel: the PSF matching kernel
        - backgroundModel: differential background model
        - kernelCellSet: SpatialCellSet used to solve for the PSF matching kernel

        Raise a RuntimeError if input images have different dimensions
        """

        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displayTemplate = lsstDebug.Info(__name__).displayTemplate
        displaySciIm = lsstDebug.Info(__name__).displaySciIm
        displaySpatialCells = lsstDebug.Info(__name__).displaySpatialCells
        maskTransparency = lsstDebug.Info(__name__).maskTransparency
        if not maskTransparency:
            maskTransparency = 0
        if display:
            ds9.setMaskTransparency(maskTransparency)

        if not candidateList:
            raise RuntimeError(
                "Candidate list must be populated by makeCandidateList")

        if not self._validateSize(templateMaskedImage, scienceMaskedImage):
            pexLog.Trace(self.log.getName(), 1,
                         "ERROR: Input images different size")
            raise RuntimeError("Input images different size")

        if display and displayTemplate:
            ds9.mtv(templateMaskedImage,
                    frame=lsstDebug.frame,
                    title="Image to convolve")
            lsstDebug.frame += 1

        if display and displaySciIm:
            ds9.mtv(scienceMaskedImage,
                    frame=lsstDebug.frame,
                    title="Image to not convolve")
            lsstDebug.frame += 1

        kernelCellSet = self._buildCellSet(templateMaskedImage,
                                           scienceMaskedImage, candidateList)

        if display and displaySpatialCells:
            diUtils.showKernelSpatialCells(scienceMaskedImage,
                                           kernelCellSet,
                                           symb="o",
                                           ctype=ds9.CYAN,
                                           ctypeUnused=ds9.YELLOW,
                                           ctypeBad=ds9.RED,
                                           size=4,
                                           frame=lsstDebug.frame,
                                           title="Image to not convolve")
            lsstDebug.frame += 1

        if templateFwhmPix and scienceFwhmPix:
            self.log.info("Matching Psf FWHM %.2f -> %.2f pix" %
                          (templateFwhmPix, scienceFwhmPix))

        if self.kConfig.useBicForKernelBasis:
            tmpKernelCellSet = self._buildCellSet(templateMaskedImage,
                                                  scienceMaskedImage,
                                                  candidateList)
            nbe = diffimTools.NbasisEvaluator(self.kConfig, templateFwhmPix,
                                              scienceFwhmPix)
            bicDegrees = nbe(tmpKernelCellSet, self.log)
            basisList = makeKernelBasisList(self.kConfig,
                                            templateFwhmPix,
                                            scienceFwhmPix,
                                            alardDegGauss=bicDegrees[0],
                                            metadata=self.metadata)
            del tmpKernelCellSet
        else:
            basisList = makeKernelBasisList(self.kConfig,
                                            templateFwhmPix,
                                            scienceFwhmPix,
                                            metadata=self.metadata)

        spatialSolution, psfMatchingKernel, backgroundModel = self._solve(
            kernelCellSet, basisList)

        psfMatchedMaskedImage = afwImage.MaskedImageF(
            templateMaskedImage.getBBox())
        doNormalize = False
        afwMath.convolve(psfMatchedMaskedImage, templateMaskedImage,
                         psfMatchingKernel, doNormalize)
        return pipeBase.Struct(
            matchedImage=psfMatchedMaskedImage,
            psfMatchingKernel=psfMatchingKernel,
            backgroundModel=backgroundModel,
            kernelCellSet=kernelCellSet,
        )
Пример #12
0
    def _buildCellSet(self, exposure, referencePsfModel):
        """!Build a SpatialCellSet for use with the solve method

        @param exposure: The science exposure that will be convolved; must contain a Psf
        @param referencePsfModel: Psf model to match to

        @return kernelCellSet: a SpatialCellSet to be used by self._solve

        Raise a RuntimeError if the reference Psf model and science Psf model have different dimensions
        """
        scienceBBox = exposure.getBBox()
        sciencePsfModel = exposure.getPsf()
        # The Psf base class does not support getKernel() in general, as there are some Psf
        # classes for which this is not meaningful.
        # Many Psfs we use in practice are KernelPsfs, and this algorithm will work fine for them,
        # but someday it should probably be modified to support arbitrary Psfs.
        referencePsfModel = measAlg.KernelPsf.swigConvert(referencePsfModel)
        sciencePsfModel = measAlg.KernelPsf.swigConvert(sciencePsfModel)
        if referencePsfModel is None or sciencePsfModel is None:
            raise RuntimeError(
                "ERROR: Psf matching is only implemented for KernelPsfs")
        if (referencePsfModel.getKernel().getDimensions() !=
                sciencePsfModel.getKernel().getDimensions()):
            pexLog.Trace(
                self.log.getName(), 1,
                "ERROR: Dimensions of reference Psf and science Psf different; exiting"
            )
            raise RuntimeError, "ERROR: Dimensions of reference Psf and science Psf different; exiting"

        psfWidth, psfHeight = referencePsfModel.getKernel().getDimensions()
        maxKernelSize = min(psfWidth, psfHeight) - 1
        if maxKernelSize % 2 == 0:
            maxKernelSize -= 1
        if self.kConfig.kernelSize > maxKernelSize:
            raise ValueError, "Kernel size (%d) too big to match Psfs of size %d; reduce to at least %d" % (
                self.kConfig.kernelSize, psfWidth, maxKernelSize)

        # Infer spatial order of Psf model!
        #
        # Infer from the number of spatial parameters.
        # (O + 1) * (O + 2) / 2 = N
        # O^2 + 3 * O + 2 * (1 - N) = 0
        #
        # Roots are [-3 +/- sqrt(9 - 8 * (1 - N))] / 2
        #
        nParameters = sciencePsfModel.getKernel().getNSpatialParameters()
        root = num.sqrt(9 - 8 * (1 - nParameters))
        if (root != root // 1):  # We know its an integer solution
            pexLog.Trace(self.log.getName(), 3,
                         "Problem inferring spatial order of image's Psf")
        else:
            order = (root - 3) / 2
            if (order != order // 1):
                pexLog.Trace(self.log.getName(), 3,
                             "Problem inferring spatial order of image's Psf")
            else:
                pexLog.Trace(
                    self.log.getName(), 2,
                    "Spatial order of Psf = %d; matching kernel order = %d" %
                    (order, self.kConfig.spatialKernelOrder))

        regionSizeX, regionSizeY = scienceBBox.getDimensions()
        scienceX0, scienceY0 = scienceBBox.getMin()

        sizeCellX = self.kConfig.sizeCellX
        sizeCellY = self.kConfig.sizeCellY

        kernelCellSet = afwMath.SpatialCellSet(
            afwGeom.Box2I(afwGeom.Point2I(scienceX0, scienceY0),
                          afwGeom.Extent2I(regionSizeX, regionSizeY)),
            sizeCellX, sizeCellY)

        nCellX = regionSizeX // sizeCellX
        nCellY = regionSizeY // sizeCellY
        dimenR = referencePsfModel.getKernel().getDimensions()
        dimenS = sciencePsfModel.getKernel().getDimensions()

        policy = pexConfig.makePolicy(self.kConfig)
        for row in range(nCellY):
            # place at center of cell
            posY = sizeCellY * row + sizeCellY // 2 + scienceY0

            for col in range(nCellX):
                # place at center of cell
                posX = sizeCellX * col + sizeCellX // 2 + scienceX0

                pexLog.Trace(
                    self.log.getName(), 5,
                    "Creating Psf candidate at %.1f %.1f" % (posX, posY))

                # reference kernel image, at location of science subimage
                kernelImageR = referencePsfModel.computeImage(
                    afwGeom.Point2D(posX, posY)).convertF()
                kernelMaskR = afwImage.MaskU(dimenR)
                kernelMaskR.set(0)
                kernelVarR = afwImage.ImageF(dimenR)
                kernelVarR.set(1.0)
                referenceMI = afwImage.MaskedImageF(kernelImageR, kernelMaskR,
                                                    kernelVarR)

                # kernel image we are going to convolve
                kernelImageS = sciencePsfModel.computeImage(
                    afwGeom.Point2D(posX, posY)).convertF()
                kernelMaskS = afwImage.MaskU(dimenS)
                kernelMaskS.set(0)
                kernelVarS = afwImage.ImageF(dimenS)
                kernelVarS.set(1.0)
                scienceMI = afwImage.MaskedImageF(kernelImageS, kernelMaskS,
                                                  kernelVarS)

                # The image to convolve is the science image, to the reference Psf.
                kc = diffimLib.makeKernelCandidate(posX, posY, scienceMI,
                                                   referenceMI, policy)
                kernelCellSet.insertCandidate(kc)

        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displaySpatialCells = lsstDebug.Info(__name__).displaySpatialCells
        maskTransparency = lsstDebug.Info(__name__).maskTransparency
        if not maskTransparency:
            maskTransparency = 0
        if display:
            ds9.setMaskTransparency(maskTransparency)
        if display and displaySpatialCells:
            diUtils.showKernelSpatialCells(exposure.getMaskedImage(),
                                           kernelCellSet,
                                           symb="o",
                                           ctype=ds9.CYAN,
                                           ctypeUnused=ds9.YELLOW,
                                           ctypeBad=ds9.RED,
                                           size=4,
                                           frame=lsstDebug.frame,
                                           title="Image to be convolved")
            lsstDebug.frame += 1
        return kernelCellSet
    def applyVisitor(self, invert=False, xloc=397, yloc=580):
        print '# %.2f %.2f' % (xloc, yloc)
        #if xloc != 1312 and yloc != 160:
        #    return

        imsize = int(3 * self.subconfig1.kernelSize)

        # chop out a region around a known object
        bbox = afwGeom.Box2I(
            afwGeom.Point2I(xloc - imsize / 2, yloc - imsize / 2),
            afwGeom.Point2I(xloc + imsize / 2, yloc + imsize / 2))

        # sometimes the box goes off the image; no big deal...
        try:
            if invert:
                tmi = afwImage.MaskedImageF(
                    self.scienceExposure.getMaskedImage(), bbox,
                    afwImage.LOCAL)
                smi = afwImage.MaskedImageF(
                    self.templateExposure.getMaskedImage(), bbox,
                    afwImage.LOCAL)
            else:
                smi = afwImage.MaskedImageF(
                    self.scienceExposure.getMaskedImage(), bbox,
                    afwImage.LOCAL)
                tmi = afwImage.MaskedImageF(
                    self.templateExposure.getMaskedImage(), bbox,
                    afwImage.LOCAL)
        except Exception:
            return None

        # delta function kernel
        logging.Trace("lsst.ip.diffim.compareLambdaTypes", 1, 'DF run')
        results1 = self.apply(pexConfig.makePolicy(self.subconfig1),
                              self.bskv1, xloc, yloc, tmi, smi)
        kSum1, bg1, dmean1, dstd1, vmean1, kImageOut1, diffIm1, kc1 = results1
        res = 'DF residuals : %.3f +/- %.3f; %.2f, %.2f; %.2f %.2f, %.2f' % (
            self.dStats.getMean(), self.dStats.getRms(), kSum1, bg1, dmean1,
            dstd1, vmean1)
        logging.Trace("lsst.ip.diffim.compareLambdaTypes", 1, res)
        if display:
            ds9.mtv(tmi, frame=1)  # ds9 switches frame 0 and 1 for some reason
            ds9.mtv(smi, frame=0)
            ds9.mtv(kImageOut1, frame=2)
            ds9.mtv(diffIm1, frame=3)
        if writefits:
            tmi.writeFits('t.fits')
            smi.writeFits('s.fits')
            kImageOut1.writeFits('k1.fits')
            diffIm1.writeFits('d1.fits')

        # regularized delta function kernel
        logging.Trace("lsst.ip.diffim.compareLambdaTypes", 1, 'DFrC5 run')
        results2 = self.apply(pexConfig.makePolicy(self.subconfig2),
                              self.bskv2, xloc, yloc, tmi, smi)
        kSum2, bg2, dmean2, dstd2, vmean2, kImageOut2, diffIm2, kc2 = results2
        res = 'DFrC5 residuals : %.3f +/- %.3f; %.2f, %.2f; %.2f %.2f, %.2f' % (
            self.dStats.getMean(), self.dStats.getRms(), kSum2, bg2, dmean2,
            dstd2, vmean2)
        logging.Trace("lsst.ip.diffim.compareLambdaTypes", 1, res)
        if display:
            ds9.mtv(tmi, frame=4)
            ds9.mtv(smi, frame=5)
            ds9.mtv(kImageOut2, frame=6)
            ds9.mtv(diffIm2, frame=7)
        if writefits:
            kImageOut2.writeFits('k2.fits')
            diffIm2.writeFits('d2')

        # regularized delta function kernel
        logging.Trace("lsst.ip.diffim.compareLambdaTypes", 1, 'DFrC9 run')
        results3 = self.apply(pexConfig.makePolicy(self.subconfig3),
                              self.bskv3, xloc, yloc, tmi, smi)
        kSum3, bg3, dmean3, dstd3, vmean3, kImageOut3, diffIm3, kc3 = results3
        res = 'DFrC9 residuals : %.3f +/- %.3f; %.2f, %.2f; %.2f %.2f, %.2f' % (
            self.dStats.getMean(), self.dStats.getRms(), kSum3, bg3, dmean3,
            dstd3, vmean3)
        logging.Trace("lsst.ip.diffim.compareLambdaTypes", 1, res)
        if display:
            ds9.mtv(tmi, frame=8)
            ds9.mtv(smi, frame=9)
            ds9.mtv(kImageOut3, frame=10)
            ds9.mtv(diffIm3, frame=11)
        if writefits:
            kImageOut2.writeFits('k3.fits')
            diffIm2.writeFits('d3')

        # regularized delta function kernel
        logging.Trace("lsst.ip.diffim.compareLambdaTypes", 1, 'DFrF12 run')
        results4 = self.apply(pexConfig.makePolicy(self.subconfig4),
                              self.bskv4, xloc, yloc, tmi, smi)
        kSum4, bg4, dmean4, dstd4, vmean4, kImageOut4, diffIm4, kc4 = results4
        res = 'DFrF12 residuals : %.3f +/- %.3f; %.2f, %.2f; %.2f %.2f, %.2f' % (
            self.dStats.getMean(), self.dStats.getRms(), kSum4, bg4, dmean4,
            dstd4, vmean4)
        logging.Trace("lsst.ip.diffim.compareLambdaTypes", 1, res)
        if display:
            ds9.mtv(tmi, frame=12)
            ds9.mtv(smi, frame=13)
            ds9.mtv(kImageOut4, frame=14)
            ds9.mtv(diffIm4, frame=15)
        if writefits:
            kImageOut2.writeFits('k4.fits')
            diffIm2.writeFits('d4')

        raw_input('Next: ')
Пример #14
0
def detection(differenceImageExposure,
              policy,
              filterId,
              useLog=None,
              footprintList=None):
    """Detect and measure objects in an incoming difference image Exposure
    
    Inputs:
    - differenceImageExposure: an lsst.afw.image.Exposure containing a difference MaskedImage and WCS
    - policy: the policy; required elements are...?
    - footprintList: a sequence of detection footprints on which to force measurement
        
    Returns:
    - an lsst.afw.detection.SourceVector
    """

    if not (useLog):
        useLog = ScreenLog()
        useLog.setScreenVerbose(True)

    logging.Trace("lsst.detection.detection", 3, "filterId = %d" % (filterId))

    ###########
    #
    # Get directives from policy
    #
    thresh = policy.get('thresholdSigma')
    nPixMin = policy.get('numPixMinFootprint')

    ###########
    #
    # Unpack the MaskedImage from the Exposure
    #

    img = differenceImageExposure.getMaskedImage()

    ###########
    #
    # Crudely estimate noise from mean of variance image - should do sigma clipping
    #

    varImg = img.getVariance()
    noise = math.sqrt(afwImage.mean_channel_value(varImg))

    logging.Trace(
        "lsst.detection.detection", 3,
        "thresholdSigma = %r; noise = %r PixMin = %r" %
        (thresh, noise, nPixMin))

    LogRec(useLog, Log.INFO) \
                   <<  "Threshold computation" \
                   << DataProperty("thresholdSigma", thresh) \
                   << DataProperty("noise", noise) \
                   << DataProperty("threshold", thresh*noise) \
                   << LogRec.endr

    ###########
    #
    # Build the DetectionSet for positive sources
    #

    dsPositive = det.DetectionSetF(
        img, det.Threshold(thresh * noise, det.Threshold.VALUE, True), "FP+",
        nPixMin)
    fpVecPositive = dsPositive.getFootprints()
    print "Positive detections: ", len(fpVecPositive)

    LogRec(useLog, Log.INFO) \
                   <<  "Positive detections" \
                   << DataProperty("nPositive", len(fpVecPositive)) \
                   << LogRec.endr

    ###########
    #
    # Build the DetectionSet for negative sources
    #

    dsNegative = det.DetectionSetF(
        img, det.Threshold(thresh * noise, det.Threshold.VALUE, False), "FP-",
        nPixMin)
    fpVecNegative = dsNegative.getFootprints()
    print "Negative detections: ", len(fpVecNegative)

    LogRec(useLog, Log.INFO) \
                   <<  "Negative detections" \
                   << DataProperty("nNegative", len(fpVecNegative)) \
                   << LogRec.endr

    ###########
    #
    # Measure the FootPrints
    #

    imgWCS = differenceImageExposure.getWcs()

    outputDiaSources = afwDet.DiaSourceVec()

    imgMeasure = det.MeasureF(img, "FP+")

    id = 0
    for i in range(len(fpVecPositive)):
        diaPtr = afwDet.DiaSourcePtr()
        diaPtr.setId(id)
        diaPtr.setFilterId(filterId)
        imgMeasure.measureSource(
            diaPtr, fpVecPositive[i],
            0.0)  # NOTE explicit background of zero used for difference image
        pixCoord = afwImage.Coord2D(diaPtr.getColc(), diaPtr.getRowc())
        skyCoord = imgWCS.colRowToRaDec(pixCoord)
        diaPtr.setRa(skyCoord.x())
        diaPtr.setDec(skyCoord.y())
        outputDiaSources.push_back(diaPtr.get())
        id += 1

    imgMeasure = det.MeasureF(img, "FP-")

    for i in range(len(fpVecNegative)):
        diaPtr = afwDet.DiaSourcePtr()
        diaPtr.setId(id)
        diaPtr.setFilterId(filterId)
        imgMeasure.measureSource(
            diaPtr, fpVecNegative[i],
            0.0)  # NOTE explicit background of zero used for difference image
        pixCoord = afwImage.Coord2D(diaPtr.getColc(), diaPtr.getRowc())
        skyCoord = imgWCS.colRowToRaDec(pixCoord)
        diaPtr.setRa(skyCoord.x())
        diaPtr.setDec(skyCoord.y())
        outputDiaSources.push_back(diaPtr.get())
        id += 1

    ###########
    #
    # Return the DiaSources
    #

    return outputDiaSources
Пример #15
0
    def matchExposures(self,
                       templateExposure,
                       scienceExposure,
                       templateFwhmPix=None,
                       scienceFwhmPix=None,
                       candidateList=None,
                       doWarping=True,
                       convolveTemplate=True):
        """!Warp and PSF-match an exposure to the reference

        Do the following, in order:
        - Warp templateExposure to match scienceExposure,
            if doWarping True and their WCSs do not already match
        - Determine a PSF matching kernel and differential background model
            that matches templateExposure to scienceExposure
        - Convolve templateExposure by PSF matching kernel

        @param templateExposure: Exposure to warp and PSF-match to the reference masked image
        @param scienceExposure: Exposure whose WCS and PSF are to be matched to
        @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
        @param doWarping: what to do if templateExposure's and scienceExposure's WCSs do not match:
            - if True then warp templateExposure to match scienceExposure
            - if False then raise an Exception
        @param convolveTemplate: convolve the template image or the science image
            - if True, templateExposure is warped if doWarping, templateExposure is convolved
            - if False, templateExposure is warped if doWarping, scienceExposure is convolved

        @return a pipeBase.Struct containing these fields:
        - matchedImage: the PSF-matched exposure =
            warped templateExposure convolved by psfMatchingKernel. This has:
            - the same parent bbox, Wcs and Calib as scienceExposure
            - the same filter as templateExposure
            - no Psf (because the PSF-matching process does not compute one)
        - psfMatchingKernel: the PSF matching kernel
        - backgroundModel: differential background model
        - kernelCellSet: SpatialCellSet used to solve for the PSF matching kernel

        Raise a RuntimeError if doWarping is False and templateExposure's and scienceExposure's
            WCSs do not match
        """
        if not self._validateWcs(templateExposure, scienceExposure):
            if doWarping:
                self.log.info(
                    "Astrometrically registering template to science image")
                templatePsf = templateExposure.getPsf()
                templateExposure = self._warper.warpExposure(
                    scienceExposure.getWcs(),
                    templateExposure,
                    destBBox=scienceExposure.getBBox())
                templateExposure.setPsf(templatePsf)
            else:
                pexLog.Trace(self.log.getName(), 1,
                             "ERROR: Input images not registered")
                raise RuntimeError("Input images not registered")
        if templateFwhmPix is None:
            if not templateExposure.hasPsf():
                self.log.warn("No estimate of Psf FWHM for template image")
            else:
                templateFwhmPix = self.getFwhmPix(templateExposure.getPsf())

        if scienceFwhmPix is None:
            if not scienceExposure.hasPsf():
                self.log.warn("No estimate of Psf FWHM for science image")
            else:
                scienceFwhmPix = self.getFwhmPix(scienceExposure.getPsf())

        kernelSize = makeKernelBasisList(self.kConfig, templateFwhmPix,
                                         scienceFwhmPix)[0].getWidth()
        candidateList = self.makeCandidateList(templateExposure,
                                               scienceExposure, kernelSize,
                                               candidateList)

        if convolveTemplate:
            results = self.matchMaskedImages(templateExposure.getMaskedImage(),
                                             scienceExposure.getMaskedImage(),
                                             candidateList,
                                             templateFwhmPix=templateFwhmPix,
                                             scienceFwhmPix=scienceFwhmPix)
        else:
            results = self.matchMaskedImages(scienceExposure.getMaskedImage(),
                                             templateExposure.getMaskedImage(),
                                             candidateList,
                                             templateFwhmPix=scienceFwhmPix,
                                             scienceFwhmPix=templateFwhmPix)

        psfMatchedExposure = afwImage.makeExposure(results.matchedImage,
                                                   scienceExposure.getWcs())
        psfMatchedExposure.setFilter(templateExposure.getFilter())
        psfMatchedExposure.setCalib(scienceExposure.getCalib())
        results.warpedExposure = templateExposure
        results.matchedExposure = psfMatchedExposure
        return results
Пример #16
0
def generateAlardLuptonBasisList(config,
                                 targetFwhmPix=None,
                                 referenceFwhmPix=None,
                                 basisDegGauss=None,
                                 metadata=None):
    """Generate an Alard-Lupton kernel basis based upon the Config and
    the input FWHM of the science and template images"""

    if config.kernelBasisSet != "alard-lupton":
        raise RuntimeError(
            "Cannot generate %s basis within generateAlardLuptonBasisList" %
            config.kernelBasisSet)

    kernelSize = config.kernelSize
    fwhmScaling = config.kernelSizeFwhmScaling
    basisNGauss = config.alardNGauss
    basisSigmaGauss = config.alardSigGauss
    basisGaussBeta = config.alardGaussBeta
    basisMinSigma = config.alardMinSig
    if basisDegGauss is None:
        basisDegGauss = config.alardDegGauss

    if len(basisDegGauss) != basisNGauss:
        raise ValueError("len(basisDegGauss) != basisNGauss : %d vs %d" %
                         (len(basisDegGauss), basisNGauss))
    if len(basisSigmaGauss) != basisNGauss:
        raise ValueError("len(basisSigmaGauss) != basisNGauss : %d vs %d" %
                         (len(basisSigmaGauss), basisNGauss))
    if (kernelSize % 2) != 1:
        raise ValueError("Only odd-sized Alard-Lupton bases allowed")

    if (targetFwhmPix is None) or (referenceFwhmPix is
                                   None) or (not config.scaleByFwhm):
        if metadata is not None:
            metadata.add("ALBasisNGauss", basisNGauss)
            metadata.add("ALBasisDegGauss", basisDegGauss)
            metadata.add("ALBasisSigGauss", basisSigmaGauss)
            metadata.add("ALKernelSize", kernelSize)

        return diffimLib.makeAlardLuptonBasisList(kernelSize // 2, basisNGauss,
                                                  basisSigmaGauss,
                                                  basisDegGauss)

    targetSigma = targetFwhmPix / sigma2fwhm
    referenceSigma = referenceFwhmPix / sigma2fwhm
    pexLog.Trace(
        "lsst.ip.diffim.generateAlardLuptonBasisList", 2,
        "Generating matching bases for sigma %.2f pix -> %.2f pix" %
        (targetSigma, referenceSigma))

    # Modify the size of Alard Lupton kernels based upon the images FWHM
    #
    # Note the operation is : template.x.kernel = science
    #
    # Assuming the template and science image Psfs are Gaussians with
    # the Fwhm above, Fwhm_T **2 + Fwhm_K **2 = Fwhm_S **2
    #
    if targetSigma == referenceSigma:
        # Leave defaults as-is
        pass
    elif referenceSigma > targetSigma:
        # Normal convolution

        # First Gaussian has the sigma that comes from the convolution
        # of two Gaussians : Sig_S**2 = Sig_T**2 + Sig_K**2
        #
        # If it's larger than basisMinSigma * basisGaussBeta, make it the
        # second kernel.  Else make it the smallest kernel.  Unless
        # only 1 kernel is asked for.
        kernelSigma = np.sqrt(referenceSigma**2 - targetSigma**2)
        if kernelSigma < basisMinSigma:
            kernelSigma = basisMinSigma

        basisSigmaGauss = []
        if basisNGauss == 1:
            basisSigmaGauss.append(kernelSigma)
            nAppended = 1
        else:
            if (kernelSigma / basisGaussBeta) > basisMinSigma:
                basisSigmaGauss.append(kernelSigma / basisGaussBeta)
                basisSigmaGauss.append(kernelSigma)
                nAppended = 2
            else:
                basisSigmaGauss.append(kernelSigma)
                nAppended = 1

        # Any other Gaussians above basisNGauss=1 come from a scaling
        # relationship: Sig_i+1 / Sig_i = basisGaussBeta
        for i in range(nAppended, basisNGauss):
            basisSigmaGauss.append(basisSigmaGauss[-1] * basisGaussBeta)

        kernelSize = int(fwhmScaling * basisSigmaGauss[-1])
        kernelSize += 0 if kernelSize % 2 else 1  # Make sure it's odd
        kernelSize = min(config.kernelSizeMax,
                         max(kernelSize, config.kernelSizeMin))

    else:
        # Deconvolution; Define the progression of Gaussians using a
        # method to derive a deconvolution sum-of-Gaussians from it's
        # convolution counterpart.  Only use 3 since the algorithm
        # assumes 3 components.
        #
        # http://iopscience.iop.org/0266-5611/26/8/085002  Equation 40

        # Use specializations for deconvolution
        basisNGauss = config.alardNGaussDeconv
        basisMinSigma = config.alardMinSigDeconv

        kernelSigma = np.sqrt(targetSigma**2 - referenceSigma**2)
        if kernelSigma < basisMinSigma:
            kernelSigma = basisMinSigma

        basisSigmaGauss = []
        if (kernelSigma / basisGaussBeta) > basisMinSigma:
            basisSigmaGauss.append(kernelSigma / basisGaussBeta)
            basisSigmaGauss.append(kernelSigma)
            nAppended = 2
        else:
            basisSigmaGauss.append(kernelSigma)
            nAppended = 1

        for i in range(nAppended, basisNGauss):
            basisSigmaGauss.append(basisSigmaGauss[-1] * basisGaussBeta)

        kernelSize = int(fwhmScaling * basisSigmaGauss[-1])
        kernelSize += 0 if kernelSize % 2 else 1  # Make sure it's odd
        kernelSize = min(config.kernelSizeMax,
                         max(kernelSize, config.kernelSizeMin))

        # Now build a deconvolution set from these sigmas
        sig0 = basisSigmaGauss[0]
        sig1 = basisSigmaGauss[1]
        sig2 = basisSigmaGauss[2]
        basisSigmaGauss = []
        for n in range(1, 3):
            for j in range(n):
                sigma2jn = (n - j) * sig1**2
                sigma2jn += j * sig2**2
                sigma2jn -= (n + 1) * sig0**2
                sigmajn = np.sqrt(sigma2jn)
                basisSigmaGauss.append(sigmajn)

        basisSigmaGauss.sort()
        basisNGauss = len(basisSigmaGauss)
        basisDegGauss = [config.alardDegGaussDeconv for x in basisSigmaGauss]

    if metadata is not None:
        metadata.add("ALBasisNGauss", basisNGauss)
        metadata.add("ALBasisDegGauss", basisDegGauss)
        metadata.add("ALBasisSigGauss", basisSigmaGauss)
        metadata.add("ALKernelSize", kernelSize)

    return diffimLib.makeAlardLuptonBasisList(kernelSize // 2, basisNGauss,
                                              basisSigmaGauss, basisDegGauss)
Пример #17
0
    def testSource(self, source, subMi):
        imArr, maArr, varArr = subMi.getArrays()
        flux = source.getApFlux()

        nPixels = subMi.getWidth() * subMi.getHeight()
        nPos, nNeg, fPos, fNeg = self.countPolarity(maArr, imArr)
        nDetPos, nDetNeg = self.countDetected(maArr)
        nMasked = self.countMasked(maArr)
        assert (nPixels == (nMasked + nPos + nNeg))

        # 1) Too many pixels in the detection are masked
        fMasked = (nMasked / nPixels)
        fMaskedTol = self.config.fBadPixels
        if fMasked > fMaskedTol:
            pexLog.Trace(
                "lsst.ip.diffim.DiaSourceAnalysis", 1,
                "Candidate %d : BAD fBadPixels %.2f > %.2f" %
                (source.getId(), fMasked, fMaskedTol))
            return False

        if flux > 0:
            # positive-going source
            fluxRatio = fPos / (fPos + abs(fNeg))
            ngoodRatio = nPos / nPixels
            maskRatio = nPos / (nPos + nMasked)
            npolRatio = nPos / (nPos + nNeg)
        else:
            # negative-going source
            fluxRatio = abs(fNeg) / (fPos + abs(fNeg))
            ngoodRatio = nNeg / nPixels
            maskRatio = nNeg / (nNeg + nMasked)
            npolRatio = nNeg / (nNeg + nPos)

        # 2) Not enough flux in unmasked correct-polarity pixels
        fluxRatioTolerance = self.config.fluxPolarityRatio
        if fluxRatio < fluxRatioTolerance:
            pexLog.Trace(
                "lsst.ip.diffim.DiaSourceAnalysis", 1,
                "Candidate %d : BAD flux polarity %.2f < %.2f (pos=%.2f neg=%.2f)"
                % (source.getId(), fluxRatio, fluxRatioTolerance, fPos, fNeg))
            return False

        # 3) Not enough unmasked pixels of correct polarity
        polarityTolerance = self.config.nPolarityRatio
        if npolRatio < polarityTolerance:
            pexLog.Trace(
                "lsst.ip.diffim.DiaSourceAnalysis", 1,
                "Candidate %d : BAD polarity count %.2f < %.2f (pos=%d neg=%d)"
                % (source.getId(), npolRatio, polarityTolerance, nPos, nNeg))
            return False

        # 4) Too many masked vs. correct polarity pixels
        maskedTolerance = self.config.nMaskedRatio
        if maskRatio < maskedTolerance:
            pexLog.Trace(
                "lsst.ip.diffim.DiaSourceAnalysis", 1,
                "Candidate %d : BAD unmasked count %.2f < %.2f (pos=%d neg=%d mask=%d)"
                % (source.getId(), maskRatio, maskedTolerance, nPos, nNeg,
                   nMasked))
            return False

        # 5) Too few unmasked, correct polarity pixels
        ngoodTolerance = self.config.nGoodRatio
        if ngoodRatio < ngoodTolerance:
            pexLog.Trace(
                "lsst.ip.diffim.DiaSourceAnalysis", 1,
                "Candidate %d : BAD good pixel count %.2f < %.2f (pos=%d neg=%d tot=%d)"
                % (source.getId(), ngoodRatio, ngoodTolerance, nPos, nNeg,
                   nPixels))
            return False

        pexLog.Trace(
            "lsst.ip.diffim.DiaSourceAnalysis", 1,
            "Candidate %d : OK flux=%.2f nPos=%d nNeg=%d nTot=%d nDetPos=%d nDetNeg=%d fPos=%.2f fNeg=%2f"
            % (source.getId(), flux, nPos, nNeg, nPixels, nDetPos, nDetNeg,
               fPos, fNeg))
        return True