Exemplo n.º 1
0
    def createCentroidFind(centroidFindType):
        """Create the centroid find object.

        Parameters
        ----------
        centroidFindType : enum 'CentroidFindType'
            Algorithm to find the centroid.

        Returns
        -------
        Child class of centroidDefault
            Centroid find object.

        Raises
        ------
        ValueError
            The centroid find type is not supported.
        """

        if centroidFindType == CentroidFindType.RandomWalk:
            return CentroidRandomWalk()
        elif centroidFindType == CentroidFindType.Otsu:
            return CentroidOtsu()
        elif centroidFindType == CentroidFindType.ConvolveTemplate:
            return CentroidConvolveTemplate()
        else:
            raise ValueError("The %s is not supported." % centroidFindType)
Exemplo n.º 2
0
    def testCompensate(self):

        # Generate a fake algorithm class
        algo = TempAlgo()

        # Test the function of image compensation
        boundaryT = 8
        offAxisCorrOrder = 10
        zcCol = np.zeros(22)
        zcCol[3:] = self.zcCol * 1e-9

        wfsImgIntra = CompensableImage()
        wfsImgExtra = CompensableImage()
        wfsImgIntra.setImg(
            self.fieldXY,
            DefocalType.Intra,
            imageFile=self.imgFilePathIntra,
        )
        wfsImgExtra.setImg(self.fieldXY,
                           DefocalType.Extra,
                           imageFile=self.imgFilePathExtra)

        for wfsImg in [wfsImgIntra, wfsImgExtra]:
            wfsImg.makeMask(self.inst, self.opticalModel, boundaryT, 1)
            wfsImg.setOffAxisCorr(self.inst, offAxisCorrOrder)
            wfsImg.imageCoCenter(self.inst)
            wfsImg.compensate(self.inst, algo, zcCol, self.opticalModel)

        # Get the common region
        intraImg = wfsImgIntra.getImg()
        extraImg = wfsImgExtra.getImg()

        centroid = CentroidRandomWalk()
        binaryImgIntra = centroid.getImgBinary(intraImg)
        binaryImgExtra = centroid.getImgBinary(extraImg)

        binaryImg = binaryImgIntra + binaryImgExtra
        binaryImg[binaryImg < 2] = 0
        binaryImg = binaryImg / 2

        # Calculate the difference
        res = np.sum(np.abs(intraImg - extraImg) * binaryImg)
        self.assertLess(res, 500)
Exemplo n.º 3
0
class TestCentroidRandomWalk(unittest.TestCase):
    """Test the CentroidRandomWalk class."""
    def setUp(self):

        self.centroid = CentroidRandomWalk()

    def testGetCenterAndR(self):

        imgDonut = self._prepareDonutImg(1000)

        realcx, realcy, realR = self.centroid.getCenterAndR(imgDonut)
        self.assertAlmostEqual(realcx, 59.7495, places=3)
        self.assertAlmostEqual(realcy, 59.3421, places=3)
        self.assertAlmostEqual(realR, 47.3616, places=3)

    def _prepareDonutImg(self, seed):

        # Read the image file
        imgFile = os.path.join(
            getModulePath(),
            "tests",
            "testData",
            "testImages",
            "LSST_NE_SN25",
            "z11_0.25_intra.txt",
        )
        imgDonut = np.loadtxt(imgFile)
        # This assumes this "txt" file is in the format
        # I[0,0]   I[0,1]
        # I[1,0]   I[1,1]
        imgDonut = imgDonut[::-1, :]

        # Add the noise to simulate the amplifier image
        np.random.seed(seed=seed)
        d0, d1 = imgDonut.shape
        noise = np.random.rand(d0, d1) * 10

        return imgDonut + noise
Exemplo n.º 4
0
    def __init__(self):

        super(CentroidConvolveTemplate, self).__init__()
        self._centRandomWalk = CentroidRandomWalk()
Exemplo n.º 5
0
class CentroidConvolveTemplate(CentroidDefault):
    """CentroidDefault child class to get the centroid of donut by
    convolution with a template donut image."""
    def __init__(self):

        super(CentroidConvolveTemplate, self).__init__()
        self._centRandomWalk = CentroidRandomWalk()

    def getImgBinary(self, imgDonut):
        """Get the binary image.

        Parameters
        ----------
        imgDonut : numpy.ndarray
            Donut image to do the analysis.

        Returns
        -------
        numpy.ndarray [int]
            Binary image of donut.
        """

        return self._centRandomWalk.getImgBinary(imgDonut)

    def getCenterAndR(self, imgDonut, templateDonut=None, peakThreshold=0.95):
        """Get the centroid data and effective weighting radius.

        Parameters
        ----------
        imgDonut : numpy.ndarray
            Donut image.
        templateDonut : None or numpy.ndarray, optional
            Template image for a single donut. If set to None
            then the image will be convolved with itself. (The Default is None)
        peakThreshold : float, optional
            This value is a specifies a number between 0 and 1 that is
            the fraction of the highest pixel value in the convolved image.
            The code then sets all pixels with a value below this to 0 before
            running the K-means algorithm to find peaks that represent possible
            donut locations. (The default is 0.95)

        Returns
        -------
        float
            Centroid x.
        float
            Centroid y.
        float
            Effective weighting radius.
        """

        imgBinary = self.getImgBinary(imgDonut)

        if templateDonut is None:
            templateBinary = copy(imgBinary)
        else:
            templateBinary = self.getImgBinary(templateDonut)

        return self.getCenterAndRfromImgBinary(
            imgBinary,
            templateBinary=templateBinary,
            peakThreshold=peakThreshold,
        )

    def getCenterAndRfromImgBinary(self,
                                   imgBinary,
                                   templateBinary=None,
                                   peakThreshold=0.95):
        """Get the centroid data and effective weighting radius.

        Parameters
        ----------
        imgBinary : numpy.ndarray
            Binary image of donut.
        templateBinary : None or numpy.ndarray, optional
            Binary image of template for a single donut. If set to None
            then the image will be convolved with itself. (The Default is None)
        peakThreshold : float, optional
            This value is a specifies a number between 0 and 1 that is
            the fraction of the highest pixel value in the convolved image.
            The code then sets all pixels with a value below this to 0 before
            running the K-means algorithm to find peaks that represent possible
            donut locations. (The default is 0.95)

        Returns
        -------
        float
            Centroid x.
        float
            Centroid y.
        float
            Effective weighting radius.
        """

        x, y, radius = self.getCenterAndRfromTemplateConv(
            imgBinary,
            templateImgBinary=templateBinary,
            nDonuts=1,
            peakThreshold=peakThreshold,
        )

        return x[0], y[0], radius

    def getCenterAndRfromTemplateConv(
        self,
        imageBinary,
        templateImgBinary=None,
        nDonuts=1,
        peakThreshold=0.95,
        dbscanEps=5.0,
    ):
        """
        Get the centers of the donuts by convolving a binary template image
        with the binary image of the donut or donuts.

        Peaks will appear as bright spots in the convolved image. Since we
        use binary images the brightness of the stars does not matter and
        the peaks of any stars in the image should have about the same
        brightness if the template is correct.

        Parameters
        ----------
        imageBinary: numpy.ndarray
            Binary image of postage stamp.
        templateImgBinary: None or numpy.ndarray, optional
            Binary image of template donut. If set to None then the image
            is convolved with itself. (The default is None)
        nDonuts: int, optional
            Number of donuts there should be in the binary image. If the number
            is >= 1 then K-Means clustering will be used to return the
            specified number of donut centers. However, this can also be set to
            -1 if the number of donuts is unknown and it will perform DBSCAN
            clustering to find and return a set of donut centers.
            (The default is 1)
        peakThreshold: float, optional
            This value is a specifies a number between 0 and 1 that is
            the fraction of the highest pixel value in the convolved image.
            The code then sets all pixels with a value below this to 0 before
            running the K-means algorithm to find peaks that represent possible
            donut locations. (The default is 0.95)
        dbscanEps: float, optional
            Maximum distance scikit-learn DBSCAN algorithm allows "between two
            samples for one to considered in the neighborhood of the other".
            (The default is 5.0)

        Returns
        -------
        list
            X pixel coordinates for donut centroid.
        list
            Y pixel coordinates for donut centroid.
        float
            Effective weighting radius calculated using the template image.
        """

        if templateImgBinary is None:
            templateImgBinary = copy(imageBinary)

        nDonutsAssertStr = "nDonuts must be an integer >= 1 or -1"
        assert ((nDonuts >= 1) |
                (nDonuts == -1)) & (type(nDonuts) is int), nDonutsAssertStr

        # We set the mode to be "same" because we need to return the same
        # size image to the code.
        tempConvolve = correlate(imageBinary, templateImgBinary, mode="same")

        # Then we rank the pixel values keeping only those above
        # some fraction of the highest value.
        rankedConvolve = np.argsort(tempConvolve.flatten())[::-1]
        cutoff = len(
            np.where(tempConvolve.flatten() > peakThreshold *
                     np.max(tempConvolve))[0])
        rankedConvolveCutoff = rankedConvolve[:cutoff]
        nx, ny = np.unravel_index(rankedConvolveCutoff, np.shape(imageBinary))

        # Donut centers lists
        centX = []
        centY = []

        if nDonuts >= 1:
            # Then to find peaks in the image we use K-Means with the
            # specified number of donuts
            kmeans = KMeans(n_clusters=nDonuts)
            labels = kmeans.fit_predict(np.array([nx, ny]).T)

            # Then in each cluster we take the brightest pixel as the centroid
            for labelNum in range(nDonuts):
                nxLabel, nyLabel = np.unravel_index(
                    rankedConvolveCutoff[labels == labelNum][0],
                    np.shape(imageBinary))
                centX.append(nxLabel)
                centY.append(nyLabel)
        elif nDonuts == -1:
            # Use DBSCAN to find clusters of points when the
            # number of donuts is unknown
            labels = DBSCAN(eps=dbscanEps).fit_predict(np.array([ny, nx]).T)

            # Save the centroid as the brightest pixel
            # within each identified cluster
            for labelNum in np.unique(labels):
                nxLabel, nyLabel = np.unravel_index(
                    rankedConvolveCutoff[labels == labelNum][0],
                    np.shape(imageBinary))
                centX.append(nxLabel)
                centY.append(nyLabel)

        # Get the radius of the donut from the template image
        radius = np.sqrt(np.sum(templateImgBinary) / np.pi)

        return centX, centY, radius
Exemplo n.º 6
0
    def setUp(self):

        self.centroid = CentroidRandomWalk()
Exemplo n.º 7
0
    def __init__(self):
        """CentroidDefault child class to get the centroid of donut by
    convolution with a template donut image."""

        super(CentroidConvolveTemplate, self).__init__()
        self._centRandomWalk = CentroidRandomWalk()