Example #1
0
    def __call__(
        self,
        xi,
        yi,
        radius=4.0,
        l=5.0,
        a=0.01,
        width=20.0,
        skyRadius=8.0,
        zpt=27.0,
        exptime=1.0,
        enableBGSelection=False,
        display=False,
        verbose=False,
        backupMode="fraserMode",
        trimBGHighPix=False,
        zscale=True,
    ):
        """
        Perform the actual photometry.

        angle in degrees clockwise +-90 degrees from +x
        Length in pixels.
        Coordinates are in iraf coordinates, not numpy.

        -width is the outer dimension of the image region considered.
        That is, 2*width*2*width is the image subsection size.

        set trimBGHighPix to some value ,x, to trim the background
        -this is done by first estimating the background. Then, it trims
        all pixels with value v>bg+x*bgstd. That is, it provides a rough
        sigma cut to get rid of glaringly bright sources that might affect
        the bg estimate.
        -the bg is then restimated.
        """

        x = xi - 0.5
        y = yi - 0.5

        # if l+radius<width or l+skyRadius<width:
        #    raise Exception("Width must be large enough to include both the full aperture, and the sky radius.")

        if a > 90 or a < -90 or l < 0 or radius < 0:
            raise Exception(
                "Keep the angle between -90 and +90 with positive rates please. If you ask me nicely, I may include code to handle this."
            )

        image = self.__lp__(x=x + 1.0, y=y + 1.0, radius=radius, l=l, a=a, w=int(width))
        if display and self.l0 <> None:
            l0 = self.l0
            l1 = self.l1
            l2 = self.l2
            l3 = self.l3

        bgstd = -1.0
        mask = self.mask

        if skyRadius == None:
            skyImage = image * 0.0
            bg = 0.0
        else:
            skyImage = self.__lp__(x=x + 1.0, y=y + 1.0, radius=skyRadius, l=l, a=a, w=int(width), retObj=False)
            bgmask = self.bgmask

            rebinnedSkyImage = num.zeros(num.array(skyImage.shape) / self.repFact)
            (aa, bb) = skyImage.shape
            for ii in range(0, aa, self.repFact):
                for jj in range(0, bb, self.repFact):
                    n = num.sum(bgmask[ii : ii + self.repFact, jj : jj + self.repFact])
                    if n == self.repFact * self.repFact:
                        rebinnedSkyImage[ii / self.repFact, jj / self.repFact] = num.sum(
                            skyImage[ii : ii + self.repFact, jj : jj + self.repFact]
                        )

            w = num.where(rebinnedSkyImage <> 0.0)
            bgf = bgFinder.bgFinder(rebinnedSkyImage[w])
            if not trimBGHighPix:
                bg = bgf.smartBackground(display=display, backupMode=backupMode)
            else:
                bg = bgf.smartBackground(backupMode=backupMode)
            bgstd = num.std(rebinnedSkyImage[w])

            if trimBGHighPix:
                W = num.where(rebinnedSkyImage[w] < bg + trimBGHighPix * bgstd)
                bgf = bgFinder.bgFinder(rebinnedSkyImage[w][W])
                bg = bgf.smartBackground(display=display)
                bgstd = num.std(rebinnedSkyImage[w][W])

        W = num.where(mask <> 0.0)
        flux = num.sum(image) - len(W[0]) * bg / (self.repFact * self.repFact)

        self.nPix = num.sum(mask) / (self.repFact * self.repFact)

        self.sourceFlux = flux
        self.bg = bg
        self.bgstd = bgstd
        self.exptime = exptime
        self.magnitude = zpt - 2.5 * num.log10(self.sourceFlux / self.exptime)

        if display:
            if trimBGHighPix:
                w = num.where(skyImage > (bg + trimBGHighPix * bgstd) / (self.repFact * self.repFact))
                skyImage[w] = 0
            im = skyImage + image

            if zscale:
                (z1, z2) = numdisplay.zscale.zscale(im)
                norm = interval.ManualInterval(z1, z2)

                pyl.imshow(norm(im), interpolation="nearest", origin="lower")
            else:
                w = num.where(im == 0.0)
                im[w] += self.bg * 0.7 / (self.repFact * self.repFact)
                im = num.clip(im, num.min(im), num.max(image))
                pyl.imshow(im, interpolation="nearest", origin="lower")
            if self.l0 <> None:

                pyl.plot(
                    num.linspace(l0.xlim[0], l0.xlim[1], 100),
                    l0(num.linspace(l0.xlim[0], l0.xlim[1], 100)),
                    "w-",
                    lw=2.0,
                )
                pyl.plot(
                    num.linspace(l2.xlim[0], l2.xlim[1], 100),
                    l2(num.linspace(l2.xlim[0], l2.xlim[1], 100)),
                    "w-",
                    lw=2.0,
                )
                # pyl.text((l0.xlim[0]+l0.xlim[1])/2.-5,(l0(l0.xlim[0])+l0(l0.xlim[1]))/2.+5,'$l$',size=20)

                # pyl.plot([l0.xlim[0],l0.xlim[0]+50],[l0(l0.xlim[0]),l0(l0.xlim[0])],'k--')

                mx0 = (l0.xlim[0] + l2.xlim[0]) / 2
                my0 = (l0(l0.xlim[0]) + l2(l2.xlim[0])) / 2
                a0 = num.arctan2(l0(l0.xlim[0]) - my0, l0.xlim[0] - mx0)
                a1 = num.arctan2(l2(l2.xlim[0]) - my0, l2.xlim[0] - mx0)
                a = num.linspace(a0, a1, 25)
                xxx = mx0 - num.cos(a) * radius * self.repFact
                yyy = my0 - num.sin(a) * radius * self.repFact
                pyl.plot(xxx, yyy, "w-", lw=2)
                pyl.plot([mx0, xxx[-6]], [my0, yyy[-6]], "w:", lw=2)
                # pyl.text((mx0+xxx[-6])/2.-5,(my0+yyy[-6])/2.-5,'$r$',size=20)

                mx0 = (l0.xlim[1] + l2.xlim[1]) / 2
                my0 = (l0(l0.xlim[1]) + l2(l2.xlim[1])) / 2
                a0 = num.arctan2(l0(l0.xlim[1]) - my0, l0.xlim[1] - mx0)
                a1 = num.arctan2(l2(l2.xlim[1]) - my0, l2.xlim[1] - mx0)
                a = num.linspace(a0, a1, 25)
                xxx = mx0 + num.cos(a) * radius * self.repFact
                yyy = my0 + num.sin(a) * radius * self.repFact
                pyl.plot(xxx, yyy, "w-", lw=2)

            if enableBGSelection:
                print "Current background value: %.3f" % (self.bg)
                pyl.title("To improve background measurement, zoom on a good\nbackground region, then close.")
                CA = pyl.gca()
                (ox0, ox1) = CA.get_xlim()
                (oy0, oy1) = CA.get_ylim()

                pyl.show()
                (A, B) = im.shape
                (x0, x1) = CA.get_xlim()
                (y0, y1) = CA.get_ylim()
                if ox0 == x0 and ox1 == x1 and oy0 == y0 and oy1 == y1:
                    return

                x0 = max(0, x0) / 10
                y0 = max(0, y0) / 10
                x1 = min(A, x1) / 10
                y1 = min(B, y1) / 10

                rebinnedSkyImage = rebinnedSkyImage[y0:y1, x0:x1]
                w = num.where(rebinnedSkyImage <> 0.0)
                bgf = bgFinder.bgFinder(rebinnedSkyImage[w])
                bg = bgf.smartBackground(display=display)
                bgstd = num.std(rebinnedSkyImage[w])

                W = num.where(mask <> 0.0)
                flux = num.sum(image) - len(W[0]) * bg / (self.repFact * self.repFact)

                self.nPix = num.sum(mask) / (self.repFact * self.repFact)

                self.sourceFlux = flux
                self.bg = bg
                self.bgstd = bgstd
                self.exptime = exptime
                self.magnitude = zpt - 2.5 * num.log10(self.sourceFlux / self.exptime)

            else:
                pyl.show()
        if verbose:
            print num.sum(image), self.sourceFlux, self.bg, zpt - 2.5 * num.log10(flux)
Example #2
0
    def __call__(self,
                 xi,
                 yi,
                 radius=4.,
                 l=5.,
                 a=0.01,
                 width=20.,
                 skyRadius=8.,
                 zpt=27.0,
                 exptime=1.,
                 enableBGSelection=False,
                 display=False,
                 verbose=False,
                 backupMode='fraserMode',
                 forceBackupMode=False,
                 trimBGHighPix=False,
                 zscale=True,
                 zoomRegion=None):
        """
        Perform the actual photometry.

        Important note: the background is taken as the output from bgfinder.smartBackground.
            First a Guassian is fit to the data.
            If the gaussian standard deviation / gaussian peak is larger than the variable gaussSTDlimit, or if
            forceBackupMode is set to true, the backup mode background value is returned. Otherwise, the peak of the
            gaussian fit is returned.

        angle in degrees clockwise +-90 degrees from +x
        Length in pixels.
        Coordinates are in iraf coordinates, not numpy.

        -width is the outer dimension of the image region considered.
        That is, 2*width*2*width is the image subsection size.

        set trimBGHighPix to some value ,x, to trim the background
        -this is done by first estimating the background. Then, it trims
        all pixels with value v>bg+x*bgstd. That is, it provides a rough
        sigma cut to get rid of glaringly bright sources that might affect
        the bg estimate.
        -the bg is then restimated.

        -when zoomRegion is set [x_low,x_high,y_low,y_high], a 4 int/float array, and enableBGSelection = True, the
        aperture panel will automatically zoom to the region of the image specified by the box coordinates in zoomRegion
        """
        #Single-letter variables = super painful debugging
        #I'll leave them in the function call for backwards compatibility,
        #but will remove below.
        angle = a
        length = l
        del (a, l)

        #Set up some of the True/False statements that gets used repeatedly:
        singleAperture = isinstance(radius, (float, num.float64))
        multipleApertures = isinstance(radius, num.ndarray)
        if not singleAperture | multipleApertures:
            raise Exception(
                'Aperture size not understood. ' +
                'It seems to be neither an array or a single value')
        if enableBGSelection:
            if zoomRegion is not None:
                if isinstance(zoomRegion, (list, num.float64)):
                    if not len(zoomRegion) == 4:
                        raise Exception(
                            'Need four values to specify the corners of the zoom box.'
                        )
                    elif len(zoomRegion) == 4 and not isinstance(
                            zoomRegion[0], (float, int)):
                        raise Exception(
                            'zoomRegion takes floats or ints only.')
                else:
                    raise Exception(
                        'zoomRegion is a 4 float/int array or list ')

        #Check whether aperture(s) is integer: if True convert to float.
        integerAperture = isinstance(radius, (int, num.integer))
        if multipleApertures:
            integerAperture = issubclass(radius.dtype.type, num.integer)
        if integerAperture:
            radius *= 1.
            integerAperture = False

        if display:
            #setup the necessary subplots

            self.dispFig = pyl.figure('Image Display')
            if enableBGSelection:
                #dispFig.subplots_adjust(wspace = 0.0,hspace = 0.0)
                self.dispGS = gridspec.GridSpec(
                    1, 2)  #, height_ratios = [3.5,1], width_ratios = [3.5,1])
                self.dispAx = pyl.subplot(self.dispGS[0])
            else:

                self.dispAx = self.dispFig.add_subplot(111)

        x = xi - 0.5
        y = yi - 0.5

        #if l+radius<width or l+skyRadius<width:
        #    raise Exception("Width must be large enough to include both the full aperture, and the sky radius.")

        #        if angle > 90 or angle < -90 or length < 0 or num.min(radius) < 0:
        if angle > 90 or angle < -90:
            angle = angle % 180.
            if verbose:
                print("Warning! You gave a bad angle. I'll fix it for you.")
        if length < 0:
            length = -length
            if verbose:
                print("Warning! You gave a bad length. I'll fix it for you.")
        if num.min(radius) < 0:
            raise Exception('Aperture radius must be positive!')

        if singleAperture:
            image = self.__lp__(x=x + 1.,
                                y=y + 1.,
                                radius=radius,
                                l=length,
                                a=angle,
                                w=int(width))
            mask = self.mask
        elif multipleApertures:
            image = []
            mask = []
            for jj in range(len(radius)):
                image.append(
                    self.__lp__(x=x + 1.,
                                y=y + 1.,
                                radius=radius[jj],
                                l=length,
                                a=angle,
                                w=int(width)))
                mask.append(self.mask)

        if display and self.l0 <> None:
            l0 = self.l0
            l1 = self.l1
            l2 = self.l2
            l3 = self.l3

        bgstd = -1.

        if skyRadius == None:
            if singleAperture:
                skyImage = image * 0.0
            elif multipleApertures:
                skyImage = image[0] * 0.0
            bg = 0.0
        else:
            skyImage = self.__lp__(x=x + 1.,
                                   y=y + 1.,
                                   radius=skyRadius,
                                   l=length,
                                   a=angle,
                                   w=int(width),
                                   retObj=False)
            bgmask = self.bgmask

            rebinnedSkyImage = num.zeros(
                num.array(skyImage.shape) / self.repFact)
            (aa, bb) = skyImage.shape
            for ii in range(0, aa, self.repFact):
                for jj in range(0, bb, self.repFact):
                    n = num.sum(bgmask[ii:ii + self.repFact,
                                       jj:jj + self.repFact])
                    if n == self.repFact * self.repFact:
                        rebinnedSkyImage[ii / self.repFact,
                                         jj / self.repFact] = num.sum(
                                             skyImage[ii:ii + self.repFact,
                                                      jj:jj + self.repFact])

            w = num.where(rebinnedSkyImage <> 0.0)
            bgf = bgFinder.bgFinder(rebinnedSkyImage[w])
            if display and enableBGSelection:
                bgf.plotAxis = self.dispFig.add_subplot(self.dispGS[1])

            if not trimBGHighPix:
                bg = bgf.smartBackground(display=display,
                                         backupMode=backupMode,
                                         forceBackupMode=forceBackupMode)
                bgstd = num.std(rebinnedSkyImage[w])
            else:
                #trimming BG high pix
                bg = bgf.smartBackground(backupMode=backupMode,
                                         forceBackupMode=forceBackupMode)
                bgstd = num.std(rebinnedSkyImage[w])

                W = num.where(rebinnedSkyImage[w] < bg + trimBGHighPix * bgstd)
                bgf = bgFinder.bgFinder(rebinnedSkyImage[w][W])
                if display and enableBGSelection:
                    bgf.plotAxis = self.dispFig.add_subplot(self.dispGS[1])
                bg = bgf.smartBackground(display=display,
                                         backupMode=backupMode,
                                         forceBackupMode=forceBackupMode)
                bgstd = num.std(rebinnedSkyImage[w][W])

        if singleAperture:
            W = num.where(mask != 0.0)
            flux = num.sum(image) - len(W[0]) * bg / (self.repFact**2)
        elif multipleApertures:
            flux = []
            for jj in range(len(radius)):
                W = num.where(mask[jj] != 0.0)
                flux.append(
                    num.sum(image[jj]) - len(W[0]) * bg / (self.repFact**2))
            flux = num.array(flux)

        self.nPix = num.sum(mask) / (self.repFact**2)
        self.sourceFlux = flux
        self.bg = bg
        self.bgstd = bgstd
        self.exptime = exptime
        self.magnitude = zpt - 2.5 * num.log10(self.sourceFlux / self.exptime)

        if display:
            if trimBGHighPix:
                w = num.where(
                    skyImage *
                    (self.repFact * self.repFact) > (bg +
                                                     trimBGHighPix * bgstd))
                skyImage[w] = 0

            if multipleApertures:
                im = skyImage + image[-1]
            elif singleAperture:
                im = skyImage + image

            if self.zscale:
                (z1, z2) = numdisplay.zscale.zscale(im)
                norm = interval.ManualInterval(z1, z2)
                self.dispAx.imshow(norm(im),
                                   interpolation='nearest',
                                   origin='lower')
            else:
                w = num.where(im == 0.0)
                im[w] += self.bg * 0.7 / (self.repFact * self.repFact)
                im = num.clip(im, num.min(im), num.max(image))
                self.dispAx.imshow(im, interpolation='nearest', origin='lower')
            if self.l0 is not None:
                self.dispAx.plot(num.linspace(l0.xlim[0], l0.xlim[1], 100),
                                 l0(num.linspace(l0.xlim[0], l0.xlim[1], 100)),
                                 'w-',
                                 lw=2.)
                self.dispAx.plot(num.linspace(l2.xlim[0], l2.xlim[1], 100),
                                 l2(num.linspace(l2.xlim[0], l2.xlim[1], 100)),
                                 'w-',
                                 lw=2.)
                mx0 = (l0.xlim[0] + l2.xlim[0]) / 2
                my0 = (l0.ylim[0] + l2.ylim[0]) / 2
                a0 = num.arctan2(l0.ylim[0] - my0, l0.xlim[0] - mx0)
                a1 = num.arctan2(l2.ylim[0] - my0, l2.xlim[0] - mx0)
                a01 = num.linspace(a0, a1, 25)
                outerRadius = radius if singleAperture else radius[-1]
                semiCircX = num.cos(a01) * outerRadius * self.repFact
                semiCircY = num.sin(a01) * outerRadius * self.repFact
                mx1 = (l0.xlim[1] + l2.xlim[1]) / 2
                my1 = (l0.ylim[1] + l2.ylim[1]) / 2
                my0, my1 = ((my1, my0) if ((angle < 0) & (angle > -90)) else
                            (my0, my1))
                self.dispAx.plot(mx0 - semiCircX, my0 - semiCircY, 'w-', lw=2)
                self.dispAx.plot(mx1 + semiCircX, my1 + semiCircY, 'w-', lw=2)

            if enableBGSelection:
                print 'Current background value: %.3f' % (self.bg)
                self.dispAx.set_title(
                    'To improve background measurement, zoom on\na good background region, then close.'
                )

                (ox0, ox1) = self.dispAx.get_xlim()
                (oy0, oy1) = self.dispAx.get_ylim()

                (A, B) = im.shape

                #all of these are needed in _on_lims_change
                self._bgFind = bgf
                self._rbsi = rebinnedSkyImage
                self._AB = im.shape
                self._bgm = backupMode
                self._fbgm = forceBackupMode

                if zoomRegion is not None:
                    # Broad steps to zoom to a specific region
                    self.dispAx.set_xlim(zoomRegion[0] * self.repFact,
                                         zoomRegion[1] * self.repFact)
                    self.dispAx.set_ylim(zoomRegion[2] * self.repFact,
                                         zoomRegion[3] * self.repFact)
                    self._on_xlims_change(self.dispAx)
                    self._on_ylims_change(self.dispAx)

                self.dispAx.callbacks.connect('xlim_changed',
                                              self._on_xlims_change)
                self.dispAx.callbacks.connect('ylim_changed',
                                              self._on_ylims_change)

                pyl.show()

                (x0, x1) = self.dispAx.get_xlim()
                (y0, y1) = self.dispAx.get_ylim()

                x0 = max(0, x0) / self.repFact
                y0 = max(0, y0) / self.repFact
                x1 = min(B, x1) / self.repFact
                y1 = min(A, y1) / self.repFact
                self.bgSamplingRegion = [x0, x1, y0, y1]

                #need to clear the histogram first
                #need to update the positions so that the code below this ifstatement actualy fires
                if ox0 == x0 and ox1 == x1 and oy0 == y0 and oy1 == y1: return

                rebinnedSkyImage = rebinnedSkyImage[int(y0):int(y1),
                                                    int(x0):int(x1)]
                w = num.where(rebinnedSkyImage <> 0.0)
                W = num.where(rebinnedSkyImage[w] < bg + trimBGHighPix * bgstd)
                bgf = bgFinder.bgFinder(rebinnedSkyImage[w][W])
                bg = bgf.smartBackground(display=False,
                                         backupMode=backupMode,
                                         forceBackupMode=forceBackupMode,
                                         verbose=verbose)
                bgstd = num.std(rebinnedSkyImage[w])

                if singleAperture:
                    W = num.where(mask != 0.0)
                    flux = num.sum(image) - len(
                        W[0]) * bg / (self.repFact * self.repFact)
                elif multipleApertures:
                    flux = []
                    for jj in range(len(radius)):
                        W = num.where(mask[jj] != 0.0)
                        flux.append(
                            num.sum(image[jj]) - len(W[0]) * bg /
                            (self.repFact * self.repFact))
                    flux = num.array(flux)

                self.nPix = num.sum(mask) / (self.repFact * self.repFact)
                self.sourceFlux = flux
                self.bg = bg
                self.bgstd = bgstd
                self.exptime = exptime
                self.magnitude = zpt - 2.5 * num.log10(
                    self.sourceFlux / self.exptime)

            else:
                pyl.show()
        if verbose:
            print num.sum(
                image), self.sourceFlux, self.bg, zpt - 2.5 * num.log10(flux)
Example #3
0
    def fitMoffat(self,
                  imData,
                  centX,
                  centY,
                  boxSize=25,
                  bgRadius=20,
                  verbose=False,
                  mode='smart',
                  fixAB=False,
                  fitXY=False,
                  fitMaxRadius=-1.,
                  logRadPlot=False):
        """
        Fit a moffat profile to the input data, imData, at point centX,centY.

        - boxSize is the width around the centre used in the fitting.
        - bgRadius is the radius beyond which the background is estimated.
        - verbose=True to see a lot of fittnig output and a radial plot of each fit.
        - logRadPlot=True to see the plot in log radius.
        - mode='smart' is the background determination method used. See bgFinder for details.
        - fixAB=True to fit only the amplitude.
        - fitXY=False *** this is currently not implemented***
        - fitMaxRadius ***not currently implemented***
        """

        self.verbose = verbose

        self.imData = np.copy(imData)
        self.boxSize = boxSize

        self._flatRadial(centX - 0.5,
                         centY - 0.5)  #set the radial distribution pixels

        #w = np.where(self.rDist>bgRadius)
        #bgf = bgFinder.bgFinder(self.fDist[w])
        w = np.where(self.rads > bgRadius)
        bgf = bgFinder.bgFinder(self.subSec[w])
        self.bg = bgf(method=mode)

        #peakGuess = (np.max(self.fDist)-self.bg)/(np.max(self.moffat(self.rDist)))
        peakGuess = (np.max(self.subSec) - self.bg) / (np.max(
            self.moffat(self.rads)))

        if fitXY:
            print 'This is hacky and really slow. Not yet meant for production.'
            self.verbose = False
            best = [1.e8, -1., -1., -1.]
            print 'Fitting XYA'
            deltaX = np.arange(-0.2, 0.2 + 1. / self.repFact,
                               1. / self.repFact / 2.)
            deltaY = np.arange(-0.2, 0.2 + 1. / self.repFact,
                               1. / self.repFact / 2.)
            for ii in range(len(deltaX)):
                for jj in range(len(deltaY)):
                    self._flatRadial(centX + deltaX[ii], centY + deltaY[jj])
                    lsqf = opti.leastsq(self._residFAB, (peakGuess),
                                        args=(self.alpha, self.beta,
                                              fitMaxRadius),
                                        maxfev=1000)
                    res = np.sum(
                        self._residFAB((lsqf[0][0]), self.alpha, self.beta,
                                       fitMaxRadius)**2)
                    if best[0] >= res:
                        best = [res, lsqf[0], deltaX[ii], deltaY[jj]]

            return (best[2], best[3])

        elif fixAB:
            lsqf = opti.leastsq(self._residFAB, (peakGuess),
                                args=(self.alpha, self.beta, fitMaxRadius),
                                maxfev=200)
        else:
            lsqf = opti.leastsq(self._resid,
                                (peakGuess, self.alpha, self.beta),
                                args=(fitMaxRadius),
                                maxfev=250)
        if self.verbose: print lsqf
        self.A = lsqf[0][0]
        if not fixAB:
            self.alpha = lsqf[0][1]
            self.beta = lsqf[0][2]
        if fixAB:
            res = self._residFAB((self.A), self.alpha, self.beta, fitMaxRadius)
        else:
            res = self._resid((self.A, self.alpha, self.beta), fitMaxRadius)
        self.chi = np.sqrt(np.sum(res**2) / (len(res) - 1))
        self.chiFluxNorm = np.sqrt(np.sum((res / self.A)**2) / (len(res) - 1))
        self.fitted = True

        self.PSF = self.moffat(self.R)
        self.PSF /= np.sum(self.PSF)
        self.psf = downSample2d(self.PSF, self.repFact)

        if self.verbose:
            print '   A:%s, alpha:%s, beta:%s' % (self.A, self.alpha,
                                                  self.beta)
            fig = pyl.figure('Radial Profile')
            ax = fig.add_subplot(111)
            pyl.scatter(downSample2d(self.repRads, self.repFact), self.subSec)
            r = np.linspace(0, np.max(self.rads), 100)
            pyl.plot(r, self.A * self.moffat(r) + self.bg, 'r--')
            fw = self.FWHM(fromMoffatProfile=True)
            print 'FWHM: %.3f' % (fw)
            pyl.title('FWHM: {.3f} alpha: {.3f} beta: {.3f}'.format(
                fw, self.alpha, self.beta))
            if logRadPlot: ax.set_xscale('log')
            pyl.show()

        return res
Example #4
0
    cut_widthx = widths[i]
    cut_widthy = widths[i]
    while (np.max(X[0, :]) - np.min(X[0, :])) > cut_widthx:
        cut_widthx = widths[i]
        i += 1
    i = 0
    while (np.max(Y[0, :]) - np.min(Y[0, :])) > cut_widthy:
        cut_widthy = widths[i]
        i += 1
    cut_widthx += 50
    cut_widthy += 50

    for i, im in enumerate(ims):
        #print(np.median(datas[i][1850:2300,650:1390]))
        (A, B) = datas[i].shape
        bgf = bgFinder.bgFinder(datas[i][30:A - 30:10, 30:B - 30:10])
        bg = bgf.fraserMode()

        big = np.zeros((A + cut_widthy * 4 + 1,
                        B + cut_widthx * 4 + 1)).astype('float64') + bg
        big[cut_widthy * 2:A + cut_widthy * 2,
            cut_widthx * 2:cut_widthx * 2 + B] = datas[i]
        cut = big[int(Y[i][0]) + cut_widthy:int(Y[i][0]) + 3 * cut_widthy,
                  int(X[i][0]) + cut_widthx:int(X[i][0]) + 3 * cut_widthx]
        #cut = big[int(meanPos[1])+cut_width:int(meanPos[1])+3*cut_width,int(meanPos[0])+cut_width:int(meanPos[0])+3*cut_width]
        cutouts.append(np.copy(cut))

        if len(cut) == 0:
            normers.append([])
            normed.append(np.zeros((2 * cut_widthy + 1, 2 * cut_widthx + 1)))
        else:
Example #5
0
    def fitMoffat(self,imData,centX,centY,
                  boxSize=25,bgRadius=20,
                  verbose=False,mode='smart',fixAB=False,
                  fitXY=False,fitMaxRadius=-1.,logRadPlot=False):

        """
        Fit a moffat profile to the input data, imData, at point centX,centY.

        - boxSize is the width around the centre used in the fitting.
        - bgRadius is the radius beyond which the background is estimated.
        - verbose=True to see a lot of fittnig output and a radial plot of each fit.
        - logRadPlot=True to see the plot in log radius.
        - mode='smart' is the background determination method used. See bgFinder for details.
        - fixAB=True to fit only the amplitude.
        - fitXY=False *** this is currently not implemented***
        - fitMaxRadius ***not currently implemented***
        """



        self.verbose = verbose

        self.imData = imData*1.0
        self.boxSize = boxSize

        self._flatRadial(centX-0.5,centY-0.5)#set the radial distribution pixels

        #w = num.where(self.rDist>bgRadius)
        #bgf = bgFinder.bgFinder(self.fDist[w])
        w = num.where(self.rads>bgRadius)
        bgf = bgFinder.bgFinder(self.subSec[w])
        self.bg = bgf(method=mode)

        #peakGuess = (num.max(self.fDist)-self.bg)/(num.max(self.moffat(self.rDist)))
        peakGuess = (num.max(self.subSec)-self.bg)/(num.max(self.moffat(self.rads)))

        if fitXY:
            print 'This is hacky and really slow. Not really meant for production.'
            self.verbose = False
            best = [1.e8,-1.,-1.,-1.]
            print 'Fitting XYA'
            deltaX = num.arange(-0.2,0.2+1./self.repFact,1./self.repFact/2.)
            deltaY = num.arange(-0.2,0.2+1./self.repFact,1./self.repFact/2.)
            for ii in range(len(deltaX)):
                for jj in range(len(deltaY)):
                    self._flatRadial(centX+deltaX[ii],centY+deltaY[jj])
                    lsqf = opti.leastsq(self._residFAB,(peakGuess),args=(self.alpha,self.beta,fitMaxRadius),maxfev=1000)
                    res = num.sum(self._residFAB((lsqf[0][0]),self.alpha,self.beta,fitMaxRadius)**2)
                    if best[0]>= res:
                        best = [res,lsqf[0],deltaX[ii],deltaY[jj]]

            return (best[2],best[3])

        elif fixAB:
            lsqf = opti.leastsq(self._residFAB,(peakGuess),args=(self.alpha,self.beta,fitMaxRadius),maxfev=200)
        else:
            lsqf = opti.leastsq(self._resid,(peakGuess,self.alpha,self.beta),args=(fitMaxRadius),maxfev=250)
        if self.verbose: print lsqf
        self.A = lsqf[0][0]
        if not fixAB:
            self.alpha = lsqf[0][1]
            self.beta = lsqf[0][2]
        if fixAB:
            res=self._residFAB((self.A),self.alpha,self.beta,fitMaxRadius)
        else:
            res=self._resid((self.A,self.alpha,self.beta),fitMaxRadius)
        self.chi = num.sqrt(num.sum(res**2)/(len(res)-1))
        self.fitted = True

        self.PSF = self.moffat(self.R)
        self.PSF /= num.sum(self.PSF)
        self.psf = downSample2d(self.PSF,self.repFact)


        if self.verbose:
            print '   A:%s, alpha:%s, beta:%s'%(self.A,self.alpha,self.beta)
            fig = pyl.figure('Radial Profile')
            ax = fig.add_subplot(111)
            pyl.scatter(downSample2d(self.repRads,self.repFact),self.subSec)
            r = num.linspace(0,num.max(self.rads),100)
            pyl.plot(r,self.A*self.moffat(r)+self.bg,'r--')
            fw = self.FWHM(fromMoffatProfile=True)
            print 'FWHM: %.3f'%(fw)
            pyl.title('FWHM: %.3f alpha: %.3f beta: %.3f'%(fw,self.alpha,self.beta))
            if logRadPlot: ax.set_xscale('log')
            pyl.show()

        return res