Example #1
0
def convolved(theta, **kwargs):
    amp1, reff1, amp2, reff2 = theta  #, amp3, reff3, amp4, reff4 = theta #
    xs, ys = kwargs["xs"], kwargs["ys"]
    xs2, ys2 = kwargs["xs2"], kwargs["ys2"]
    #xs3, ys3 = kwargs["xs3"], kwargs["ys3"]
    #xs4, ys4 = kwargs["xs4"], kwargs["ys4"]
    arcIm = kwargs["arcIm"]
    #x2, y2 = 4013.63699909436, 4780.744281984086 # z10
    #x3, y3 = 4016.430463104877, 4783.919833222558 # z10
    xss, yss = kwargs["xss"], kwargs["yss"]
    star = kwargs["star"]
    #sersic1 = Sersic2D(amplitude=amp1, r_eff=reff1, n=n1, x_0=xs, y_0=ys)
    #sersic2 = Sersic2D(amplitude=amp2, r_eff=reff2, n=n2, x_0=xs2, y_0=ys2)
    #sersic3 = Sersic2D(amplitude=amp3, r_eff=reff3, n=n3, x_0=x3, y_0=y3)
    gauss1 = Gaussian2D(amp1,
                        x_mean=xs,
                        y_mean=ys,
                        x_stddev=reff1,
                        y_stddev=reff1)
    gauss2 = Gaussian2D(amp2,
                        x_mean=xs2,
                        y_mean=ys2,
                        x_stddev=reff2,
                        y_stddev=reff2)
    #gauss3 = Gaussian2D(amp3, x_mean=xs3, y_mean=ys3, x_stddev=reff3, y_stddev=reff3)
    #gauss4 = Gaussian2D(amp4, x_mean=xs4, y_mean=ys4, x_stddev=reff4, y_stddev=reff4)
    combined = gauss1 + gauss2  #+ gauss3 #+ gauss4
    #S1S2_hires = gauss2d(xss, yss, amplitude=amp1, x_mean=xs, y_mean=ys, x_stddev=reff1, y_stddev=reff1, theta=0)
    S1S2 = combined(xss, yss)
    #S1S2 = rebin(S1S2_hires, arcIm.shape)
    S1conv = convolve(S1S2, star)
    return S1conv
Example #2
0
def test_centroid_sym():
    y, x = centered_grid_quadratic(51)
    img = Gaussian2D()(x, y)
    assert np.all(np.isclose(centroid(img), center_of_image(img)))

    y, x = centered_grid((51, 71))
    img = Gaussian2D()(x, y)
    assert np.all(np.isclose(centroid(img), center_of_image(img)))
Example #3
0
def test_subpixel_gauss_2D():
    """
    Test subpixel accuracy of the integrate mode with gaussian 2D model.
    """
    gauss_2D = Gaussian2D(1, 0, 0, 0.1, 0.1)
    values = discretize_model(gauss_2D, (-1, 2), (-1, 2), mode='integrate', factor=100)
    assert_allclose(values.sum(), 2 * np.pi * 0.01, atol=0.00001)
Example #4
0
def plot_heatmap_sigma(sigma,axi=None):
    if axi is None:
      fig,axi = plt.subplots(1)

    s = score_grid()
    board = boardsize()
    N = 201
    fsize = 14
    buff = 30
    r = np.linspace(-board.c2od,board.c2od,N)
    x,y = np.meshgrid(r,r)
    g = Gaussian2D(1,0,0,sigma,sigma)(x,y) #Gaussian throw distribution

    Ex = fft(s,g,normalize_kernel=True) #expected 1-dart score

    aim = np.where(Ex == Ex.max())
    xc,yc = np.median(x[aim]),np.median(y[aim])

    im = axi.imshow(Ex*3,cmap='inferno',origin='lower',extent=[x.min(),x.max(),y.min(),y.max()])
    axi.scatter(xc,yc,color='w',s=40,zorder=4)
    axi.scatter(xc,yc,color='r',s=20,zorder=5)
    axi.set_xticklabels([])
    axi.set_yticklabels([])
    axi.set_title('$\sigma=$%.1f mm'%sigma,fontsize=fsize)
    axi.set_xlim([x.min()-buff,x.max()+buff])
    axi.set_ylim([x.min()-buff,x.max()+buff])

    cbar = plt.colorbar(im,ax=axi)
    cbar.set_label('Expected 3-dart score',fontsize=fsize-3)

    drawBoard(ax=axi,color_on=False,zorder=3)
Example #5
0
    def setup_class(cls):
        cls.model = Gaussian2D(x_stddev=4, y_stddev=4, x_mean=50, y_mean=50)
        cls.data = np.zeros((101, 101))
        cls.model.render(cls.data)

        cls.epsf = EPSFModel(data=cls.data)
        cls.epsf_os2 = EPSFModel(data=cls.data, oversampling=2)
Example #6
0
def test_centroid_asym(xy):
    y_grid, x_grid = centered_grid_quadratic(101)
    xy = np.array(xy)
    xy_expected = xy + center_of_image(x_grid)

    img = Gaussian2D(x_mean=xy[0], y_mean=xy[1])(x_grid, y_grid)
    assert np.all(np.isclose(centroid(img), xy_expected))
Example #7
0
def test_discretize_oversample():
    gauss_2D = Gaussian2D(amplitude=1.0,
                          x_mean=5.,
                          y_mean=125.,
                          x_stddev=0.75,
                          y_stddev=3)
    values = discretize_model(gauss_2D,
                              x_range=[0, 10],
                              y_range=[100, 135],
                              mode='oversample',
                              factor=10)
    vmax = np.max(values)
    vmax_yx = np.unravel_index(values.argmax(), values.shape)
    values_osf1 = discretize_model(gauss_2D,
                                   x_range=[0, 10],
                                   y_range=[100, 135],
                                   mode='oversample',
                                   factor=1)
    values_center = discretize_model(gauss_2D,
                                     x_range=[0, 10],
                                     y_range=[100, 135],
                                     mode='center')
    assert values.shape == (35, 10)
    assert_allclose(vmax, 0.927, atol=1e-3)
    assert vmax_yx == (25, 5)
    assert_allclose(values_center, values_osf1)
Example #8
0
 def _setPSFModel(self, model):
     if model == 'gaussian':
         self._setGaussianModel()
         self._gaussianModel = Gaussian2D(amplitude=self._amplitude,
                                          x_stddev=self._sx,
                                          y_stddev=self._sy,
                                          x_mean=self._xMean,
                                          y_mean=self._yMean,
                                          theta=self._theta)
         self._gaussianModel.fluxname = 'amplitude'
         self._gaussianModel.xname = 'x_mean'
         self._gaussianModel.yname = 'y_mean'
         self._psfModel = self._gaussianModel
     elif model == 'moffat':
         self._setMoffatModel()
         self._moffatModel = Moffat2D(amplitude=self._amplitude,
                                      x_0=self._x0,
                                      y_0=self._y0,
                                      gamma=self._gamma,
                                      alpha=self._alpha)
         self._moffatModel.fluxname = 'amplitude'
         self._psfModel = self._moffatModel
     elif model == 'integrated gaussian':
         self._setIntGaussianModel()
         self._psfModel = IntegratedGaussianPRF(sigma=self._sigma,
                                                flux=self._flux,
                                                x_0=self._xPeak,
                                                y_0=self._yPeak)
     else:
         self._psfModel = model
Example #9
0
def fit_gaus(image,
             x0,
             y0,
             gate,
             debug,
             fig_name=None,
             centring=False,
             silent=False):
    data_fit = image[y0 - gate:y0 + gate, x0 - gate:x0 + gate]
    if centring:
        if not silent:
            print("centring...")
        # ------------------------------------------------------------------ find brighter pixel and center it!!!!
        bx0, by0 = np.unravel_index(data_fit.argmax(), data_fit.shape)
        if not silent:
            print("bx, by=", bx0, by0)

        sx = by0 - gate
        sy = bx0 - gate

        data_fit = image[y0 - gate + sy:y0 + gate + sy,
                         x0 - gate + sx:x0 + gate + sx]
        # ----------------------------------------------------------------------------------------
    Z3 = data_fit
    X3 = np.arange(0, gate * 2, 1)
    Y3 = np.arange(0, gate * 2, 1)
    X3, Y3 = np.meshgrid(X3, Y3)

    sigma = np.std(Z3)
    g_init = Gaussian2D(amplitude=np.max(Z3), x_mean=gate, y_mean=gate)
    fit_g = fitting.LevMarLSQFitter()
    with warnings.catch_warnings():
        # Ignore model linearity warning from the fitter
        warnings.simplefilter('ignore')
        g = fit_g(g_init, X3, Y3, Z3)
    # print("#####Moffat#########")
    # print(m.x_0.value)
    # print(m.y_0.value)

    Zmm = g(X3, Y3)
    RMSE, Rsquared = R2_calc(Zmm, Z3)
    # print("x=%2.3f  y=%2.3f   R^2=%2.4f" % (m.x_0.value + xs - gate, m.y_0.value + ys - gate, Rsquared))
    amp = np.max(Z3)
    fwhm = (g.x_fwhm + g.y_fwhm) / 2.
    target = [
        x0 - gate + g.x_mean.value, y0 - gate + g.y_mean.value, fwhm, Rsquared,
        amp
    ]
    if debug:
        # plotting(data_fit, par, save=True, filename=fig_name, par=target, gate=gate)
        par = [g.x_mean.value, g.y_mean.value, fwhm]
        plotting(data_fit,
                 par,
                 save=True,
                 filename=fig_name,
                 par=par,
                 err=[0., 0.],
                 tar=target,
                 gate=gate)
    return target
Example #10
0
def make_gauss_kernel(σ=1.0, N=5):
    """create a gaussian convolution kernel for the EPSF smoothing step"""
    mod = Gaussian2D(x_stddev=σ, y_stddev=σ)

    y, x = np.mgrid[-N / 2:N / 2:N * 1j, -N / 2:N / 2:N * 1j]
    ev = mod(y, x)

    return ev / np.sum(ev)
Example #11
0
def test_gaussian_eval_2D_integrate_mode():
    """
    Discretize Gaussian with integrate mode
    """
    model_list = [Gaussian2D(.01, 0, 0, 2, 2),
                  Gaussian2D(.01, 0, 0, 1, 2),
                  Gaussian2D(.01, 0, 0, 2, 1)]

    x = np.arange(-2, 3)
    y = np.arange(-2, 3)

    x, y = np.meshgrid(x, y)

    for model in model_list:
        values = model(x, y)
        disc_values = discretize_model(model, (-2, 3), (-2, 3), mode='integrate')
        assert_allclose(values, disc_values, atol=1e-2)
Example #12
0
 def gauss2D_fit_erf(self, p, fjac=None, x=None, y=None, z=None, err=None):
     '''
     Computes the residuals to be minimized by mpfit, given a model and data.
     '''
     model = Gaussian2D(p[0], p[1], p[2], p[3], p[4], np.radians(p[5]))(x,
                                                                        y)
     status = 0
     return ([status, ((z - model) / err).ravel()])
Example #13
0
 def gaussian(self, cen=psf_cen):
     ampl = 1
     theta = 0
     sigma = self.seeing.value / 2 / np.sqrt(2 * np.log(2))
     m = Gaussian2D(ampl, cen[0], cen[1], sigma, sigma, theta)
     self.z = m.evaluate(self.x, self.y, ampl, cen[0], cen[1], sigma, sigma,
                         theta)
     self.sigma = m.x_stddev
     self.fwhm = m.x_fwhm
Example #14
0
def make_seeing_psf():
    scale = 0.2  # arcsec/pixel
    resolution = 0.65  # arcsec
    resolution /= scale

    x, y = np.mgrid[0:100, 0:100]
    psf = Gaussian2D.eval(x, y, 1, 50, 50, resolution)

    return psf
Example #15
0
def make_seeing_psf():
    scale = 0.2 # arcsec/pixel
    resolution = 0.65 # arcsec
    resolution /= scale

    x, y = np.mgrid[0:100, 0:100]
    psf = Gaussian2D.eval(x, y, 1, 50, 50, resolution)
    
    return psf
def makeGaussian_astropy(size,amplitude, std, bpa, center):
	""" Make a square gaussian kernel.

	size is the length of a side of the square
	fwhm is full-width-half-maximum, which
	can be thought of as an effective radius.
	"""

	x, y = np.mgrid[0:size:size,0:size:size]
	return Gaussian2D(amplitude=amplitude, x_mean=center[0], y_mean=center[1], x_stddev=std[0], y_stddev=std[1], theta=bpa*-1, cov_matrix=None)(x,y)
def generate_gaussian(*, amplitude: float, fwhm: float, canvas_radius: float,
                      px_size_nm: float) -> np.ndarray:
    """ Generates a 2D gaussian pattern. """

    stddev = fwhm / px_size_nm * gaussian_fwhm_to_sigma
    model = Gaussian2D(amplitude=amplitude, x_stddev=stddev, y_stddev=stddev)

    x, y = _canvas_meshgrid(canvas_radius, px_size_nm)
    result = model(x, y)

    return result
def gaussian2d(xx, yy, x0, y0, amp, width, e, pa):
    # creates a 2d gaussian (w/ ellipticity and pa) given the
    # mesharrays xx and yy with the x and y values of the 2d array
    sigxp = width
    sigyp = width * np.sqrt((1 - e) / (1 + e))
    model = Gaussian2D(amplitude=amp,
                       x_mean=x0,
                       y_mean=y0,
                       x_stddev=sigxp,
                       y_stddev=sigyp,
                       theta=np.pi * pa / 180)
    return model(xx, yy)
Example #19
0
    def _realisticTransmissionMap(self):
        ima = np.ones(self._shape)
        y, x = np.indices(ima.shape)

        vign_model = Gaussian2D(amplitude=1,
                                x_mean=self._shape[1] / 2,
                                y_mean=self._shape[0] / 2,
                                x_stddev=2 * self._shape[1],
                                y_stddev=2 * self._shape[0])
        vign_im = vign_model(x, y)
        ima *= vign_im
        return ima
Example #20
0
def make_seeing_psf(filt_name):
    psf_file = "seeing_psf_{0:s}.pickle".format(filt_name)

    seeing = 0.8  # arcsec specified at 5000 Angstrom
    wave = filt_wave[filt_name]  # In Angstroms
    print "Seeing at 5000 Angstroms:", seeing

    seeing *= (wave / 5000) ** (-1.0 / 5.0)
    print "Seeing at {0:s} band:".format(filt_name), seeing

    # Make a very over-sampled PSF and do integrals
    # on that... faster than scipy.integrate.
    print "Prep"
    pix_scale = 0.01  # arcsec

    xy1d = np.arange(-10 * seeing, 10 * seeing, pix_scale)

    x, y = np.meshgrid(xy1d, xy1d)

    # Use a 2D Gaussian as our PSF.
    print "Make Gaussian sigma=", seeing / 2.35
    psf = Gaussian2D.eval(x, y, 1, 0, 0, seeing / 2.35, seeing / 2.35, 0)

    # Integrate over each pixel
    print "Integrate and normalize"
    psf *= pix_scale ** 2

    # Normalize
    psf /= psf.sum()

    # Get the radius of each pixel
    r = np.hypot(x, y)

    # Make an encircled energy curve.
    r_save = np.arange(0.025, 2, 0.025)
    ee_save = np.zeros(len(r_save), dtype=float)

    for rr in range(len(r_save)):
        print "Integrating for ", r_save[rr]
        idx = np.where(r < r_save[rr])

        ee_save[rr] = psf[idx].sum()

    print "Save"
    _psf = open(psf_file, "w")
    pickle.dump(r_save, _psf)
    pickle.dump(ee_save, _psf)
    _psf.close()

    return
Example #21
0
def test_gaussian_eval_2D(mode):
    """
    Discretize Gaussian with different modes and check
    if result is at least similar to Gaussian2D.eval()
    """
    model = Gaussian2D(0.01, 0, 0, 1, 1)

    x = np.arange(-2, 3)
    y = np.arange(-2, 3)

    x, y = np.meshgrid(x, y)

    values = model(x, y)
    disc_values = discretize_model(model, (-2, 3), (-2, 3), mode=mode)
    assert_allclose(values, disc_values, atol=1e-2)
Example #22
0
def multi_source_testimage():
    img = np.zeros((301, 301))
    xs = [50, 50, 120.1, 100, 20]
    ys = [50, 57, 130, 20.3, 100.8]
    fluxes = [10, 20, 20, 10, 30]
    model = Gaussian2D(x_mean=0, y_mean=0, x_stddev=1.5, y_stddev=1.5)

    for x, y, f in zip(xs, ys, fluxes):
        model.x_mean = x
        model.y_mean = y
        model.amplitude = f
        model.render(img)

    tab = Table((xs, ys, fluxes, flux_to_magnitude(fluxes)), names=COLUMN_NAMES)

    return img, tab
Example #23
0
def plot_heatmap(parent=None):
    #get the scores on the board
    if parent is not None:
        frame = Frame(parent,width=600,height=500,bg='grey')
        frame.grid(row=0,column=1,padx=10,pady=50)

    s = score_grid()

    board = boardsize()
    N = 201
    buff = 40 #buffer for plotting
    fsize = 14
    r = np.linspace(-board.c2od,board.c2od,N)
    x,y = np.meshgrid(r,r)
    fig,ax = plt.subplots(2,2)
    for j,sigma in enumerate([3,15,30,60]):
      g = Gaussian2D(1,0,0,sigma,sigma)(x,y) #Gaussian throw distribution

      Ex = fft(s,g,normalize_kernel=True) #expected 1-dart score

      axi = ax.flatten()[j]

      aim = np.where(Ex == Ex.max())
      xc,yc = np.median(x[aim]),np.median(y[aim])

      im = axi.imshow(Ex*3,cmap='inferno',origin='lower',extent=[x.min(),x.max(),y.min(),y.max()])
      axi.scatter(xc,yc,color='w',s=40,zorder=4)
      axi.scatter(xc,yc,color='r',s=20,zorder=5)
      axi.set_xticklabels([])
      axi.set_yticklabels([])
      axi.set_title('$\sigma=$%.1f mm'%sigma,fontsize=fsize)
      axi.set_xlim([x.min()-buff,x.max()+buff])
      axi.set_ylim([x.min()-buff,x.max()+buff])

      cbar = plt.colorbar(im,ax=axi)
      cbar.set_label('Expected 3-dart score',fontsize=fsize-3)

      drawBoard(ax=axi,color_on=False,zorder=3)

    plt.tight_layout()
    #plt.show()
    if parent is not None:
        canvas = FigureCanvasTkAgg(fig, master=frame)
        #canvas.show()
        canvas.get_tk_widget().place(x=5,y=5,width=590,height=490) 
    else:
        plt.show()
Example #24
0
def gaussian_fit_psf_photometry(image,
                                obj_pos,
                                box_size=15,
                                bkgd_poly_deg=1,
                                x_std=0.5,
                                y_std=2,
                                theta=np.pi / 4,
                                interpolate=False):
    """
    performs PSF photometry by fitting a plane background model and a gaussian
    :param image: 2D array image
    :param obj_pos: location of the satellite spot (in pixels)
    :param box_size: box size in which to perform the fit
    :param bkgd_poly_deg: degree polynomial with which to it the background
    :param x_std: standard deviation of the gaussian with which to fit the satellite spot - x direction
    :param y_std: standard deviation of the gaussian with which to fit the satellite spot - y direction
    :param theta: angle off 'up' that the spot makes
    :param interpolate: is True will interpolate the image before performing the fit - recommended for non drizzled data
    :return: total satellite spot counts (in counts/sec)
    """

    x_pos = int(obj_pos[1])
    y_pos = int(obj_pos[0])
    frame = image[x_pos - box_size:x_pos + box_size,
                  y_pos - box_size:y_pos + box_size]
    if len(frame[frame == 0]) > (len(frame.flatten()) / 2):
        print(
            'More than half of the frame values are 0 - returning None for the flux'
        )
        return None, None
    else:
        if interpolate:
            frame = interpolateImage(frame)
        x, y = np.meshgrid(np.arange(np.shape(frame)[0]),
                           np.arange(np.shape(frame)[0]))
        p_spot_init = Gaussian2D(x_mean=box_size,
                                 y_mean=box_size,
                                 x_stddev=x_std,
                                 y_stddev=y_std,
                                 theta=theta)
        p_back_init = Polynomial2D(degree=bkgd_poly_deg)
        p_init = p_spot_init + p_back_init
        fit_p = fitting.LevMarLSQFitter()
        p = fit_p(p_init, x, y, frame)
        signal = p[0](x, y)
        return np.sum(signal)
 def KDE_Gaussian(self):
     X = self.X
     Y = self.Y
     Z = self.KDE()
     kg2D_init = Gaussian2D(
         amplitude=np.max(Z),
         x_mean=X[np.unravel_index(np.argmax(Z), Z.shape)],
         y_mean=Y[np.unravel_index(np.argmax(Z), Z.shape)],
         x_stddev=np.std(X),
         y_stddev=np.std(Y),
         bounds={
             'theta': (-2 * np.pi, 2 * np.pi),
             'x_mean': (np.min(X), np.max(X)),
             'y_mean': (np.min(Y), np.max(Y)),
             'x_stddev': (0.001, 1),
             'y_stddev': (0.001, 1)
         })
     kg2D = fitter(kg2D_init, X, Y, Z, weights=Z)
     kde_G = kg2D.evaluate(X, Y, kg2D.amplitude.value, kg2D.x_mean.value,
                           kg2D.y_mean.value, kg2D.x_stddev.value,
                           kg2D.y_stddev.value, kg2D.theta.value)
     return kg2D, kde_G
Example #26
0
def create_frame(background=0, std=100, crpix=None, keys=None):

    size = (100, 100)
    # Update WCS header
    wcs = create_wcs(crpix)
    y, x = numpy.mgrid[:100, :100]

    data = numpy.random.normal(background, std, size)
    model = Gaussian2D(amplitude=30 * background,
                       x_mean=wcs.wcs.crpix[0] - 3.5,
                       y_mean=wcs.wcs.crpix[1] - 12.8,
                       x_stddev=3.0,
                       y_stddev=4.0)
    data += model(x, y)
    hdu = fits.PrimaryHDU(data)

    hdu.header = wcs.to_header()
    if keys:
        for k, v in keys.items():
            hdu.header[k] = v

    return fits.HDUList([hdu])
Example #27
0
def estimate_fwhm(psf: phot.psf.EPSFModel) -> float:
    """
    Use a 2D symmetric gaussian fit to estimate the FWHM of an empirical psf
    :param psf: psfmodel to estimate
    :return: FWHM in pixel coordinates, takes into account oversampling parameter of EPSF
    """
    from astropy.modeling import fitting
    from astropy.modeling.functional_models import Gaussian2D

    # Not sure if this would work for non-quadratic images
    assert (psf.data.shape[0] == psf.data.shape[1])
    assert (psf.oversampling[0] == psf.oversampling[1])
    dim = psf.data.shape[0]
    center = int(dim / 2)
    gauss_in = Gaussian2D(x_mean=center, y_mean=center, x_stddev=5, y_stddev=5)

    # force a symmetric gaussian
    gauss_in.y_stddev.tied = lambda model: model.x_stddev

    x, y = np.mgrid[:dim, :dim]
    gauss_out = fitting.LevMarLSQFitter()(gauss_in, x, y, psf.data)

    # have to divide by oversampling to get back to original scale
    return gauss_out.x_fwhm / psf.oversampling[0]
Example #28
0
def make_anisocado_model(*,
                         oversampling=2,
                         degree=5,
                         seed=0,
                         offaxis=(0, 14),
                         lowpass=0):
    img = AnalyticalScaoPsf(pixelSize=0.004 / oversampling,
                            N=400 * oversampling + 1,
                            seed=seed).shift_off_axis(*offaxis)
    if lowpass != 0:
        y, x = np.indices(img.shape)
        # find center of PSF image
        x_mean, y_mean = centroid_quadratic(img, fit_boxsize=5)
        img = img * Gaussian2D(x_mean=x_mean,
                               y_mean=y_mean,
                               x_stddev=lowpass * oversampling,
                               y_stddev=lowpass * oversampling)(x, y)
        img /= np.sum(img)

    origin = centroid_quadratic(img, fit_boxsize=5)
    return AnisocadoModel(img,
                          oversampling=oversampling,
                          degree=degree,
                          origin=origin)
 def __init__(self, q=None, u=None):
     self.q = q
     self.u = u
     self.muq = self.q.mean()
     self.muu = self.u.mean()
     self.mu = np.array([self.muq, self.muu])
     max_range = np.max(
         [self.q.max() - self.q.min(),
          self.u.max() - self.u.min()])
     self.X, self.Y = np.meshgrid(
         np.linspace(self.muq - max_range / 2, self.muq + max_range / 2,
                     100),
         np.linspace(self.muu - max_range / 2, self.muu + max_range / 2,
                     100))
     self.cov = (1 / self.q.size) * np.sum([
         np.outer(np.array([Q, U]) - self.mu,
                  np.array([Q, U]) - self.mu)
         for Q, U in zip(self.q, self.u)
     ],
                                           axis=0)
     self.g2D = Gaussian2D(x_mean=self.muq,
                           y_mean=self.muu,
                           cov_matrix=self.cov)
     self.G = self.g2D.evaluate(self.X, self.Y, self.g2D.amplitude.value,
                                self.g2D.x_mean.value,
                                self.g2D.y_mean.value,
                                self.g2D.x_stddev.value,
                                self.g2D.y_stddev.value,
                                self.g2D.theta.value)
     self.stdq = np.sqrt(np.var(self.q))
     self.stdu = np.sqrt(np.var(self.u))
     self.theta = np.rad2deg(self.g2D.theta.value)
     self.r, self.p = pearsonr(self.q, self.u)
     self.L = 2 * self.stdq * self.stdu * np.sqrt(1 - self.r**2) / (
         self.stdq**2 + self.stdu**2)
     self.sig = self.L**(self.q.size - 2)
plt.loglog(Ns, [psf_to_sigma(img, N, 5, 0) for N in Ns])
plt.loglog(Ns, [psf_to_sigma(img, N, 2, 0) for N in Ns])
plt.loglog(Ns, [psf_to_sigma(img, N, 0, 0) for N in Ns])
plt.loglog(Ns, [psf_to_sigma_d(img, N, 10, 0) for N in Ns])
plt.loglog(Ns, [psf_to_sigma_d(img, N, 5, 0) for N in Ns])
plt.loglog(Ns, [psf_to_sigma_d(img, N, 2, 0) for N in Ns])
plt.loglog(Ns, [psf_to_sigma_d(img, N, 0, 0) for N in Ns])
# plt.loglog(Ns,[psf_to_sigma(img, N, 50, 1) for N in Ns])
# plt.loglog(Ns,[psf_to_sigma(img, N, 10, 0) for N in Ns])
# plt.loglog(Ns,[psf_to_sigma(img, N, 0, 0) for N in Ns])

# %%
from astropy.modeling.functional_models import Gaussian2D, AiryDisk2D

y, x = np.mgrid[-10:10:512j, -10:10:512j]
g3 = Gaussian2D(x_stddev=3, y_stddev=3)(x, y)
g15 = Gaussian2D(x_stddev=1.5, y_stddev=1.5)(x, y)
airy = AiryDisk2D(radius=3)(x, y)
figure()

plt.loglog(Ns, [psf_to_sigma(g3, N, 0, 0) for N in Ns])
plt.loglog(Ns, [psf_to_sigma(g15, N, 0, 0) for N in Ns])
plt.loglog(Ns, [psf_to_sigma(airy, N, 0, 0) for N in Ns])
plt.loglog(Ns, [psf_to_sigma(img, N, 0, 0) for N in Ns])

# %%
from sympy import Function, Sum, symbols, ln, Eq
from sympy.abc import N, i

η, ζ = symbols('ζ,η')
def KDE_fit(x, y):
    """
    A function that performs a gaussian KDE on x/y data, then fits the result with a sum
    of 2 2D gaussians
    
    Parameters
    ----------
    x : array-like
        x data
    y : array-like
        y data
        
    Returns
    -------
    KDE_bandwidth : float
        Cross-validated kernel bandwidth
    KD_fit_sqresid : float
        The mean squared residual (fit - KDE)^2
    amp_0 : float
        amplitude of largest gaussian
    xmean_0 : float
        x mean of largest gaussian
    ymean_0 : float
        y mean of largest gaussian
    major_std_0 : float
        Standard deviation along major axis of largest gaussian
    theta_0 : float
        Radians between positive X-axis and the major axis of the largest gaussian
    ecc_0 : float
        Eccentricity of an ellipse, taken at an arbitrary height of the largest gaussian
    amp_1 : float
        amplitude of smallest gaussian
    xmean_1 : float
        x mean of smallest gaussian
    ymean_1 : float
        y mean of smallest gaussian
    major_std_1 : float
        Standard deviation along major axis of smallest gaussian
    theta_1 : float
        Radians between positive X-axis and the major axis of the largest gaussian
    ecc_1 : float
        Eccentricity of an ellipse, taken at an arbitrary height of the smallest gaussian
    """

    data = np.vstack([x, y]).T
    #Grid search for best KDE bandwidth
    params = {
        'bandwidth': np.linspace(np.min(np.diff(y)), np.max(np.diff(y)), 100)
    }
    grid = GridSearchCV(KernelDensity(), params)
    grid.fit(data)

    KDE_bandwidth = grid.best_estimator_.bandwidth

    kde = grid.best_estimator_
    X, Y = np.meshgrid(np.linspace(np.min(x), np.max(x), 100),
                       np.linspace(np.min(y), np.max(y), 100))

    xy = np.vstack([X.ravel(), Y.ravel()]).T
    #compute the KDE on a 100x100 grid of points
    Z = np.exp(kde.score_samples(xy)).reshape(X.shape)

    #fit KDE estimation with 2 Gaussian model
    g2D_init1 = Gaussian2D(amplitude=np.max(Z),
                           x_mean=X[np.unravel_index(np.argmax(Z), Z.shape)],
                           y_mean=Y[np.unravel_index(np.argmax(Z), Z.shape)],
                           x_stddev=np.std(x),
                           y_stddev=np.std(y),
                           theta=0,
                           bounds={
                               'theta': (0, np.pi),
                               'x_mean': (np.min(x), np.max(x)),
                               'y_mean': (np.min(y), np.max(y)),
                               'x_stddev': (0.001, 1),
                               'y_stddev': (0.001, 1)
                           })
    g2D_init2 = Gaussian2D(amplitude=np.median(Z),
                           x_mean=np.median(x),
                           y_mean=np.median(y),
                           x_stddev=np.std(x),
                           y_stddev=np.std(y),
                           theta=0,
                           bounds={
                               'theta': (0, np.pi),
                               'x_mean': (np.min(x), np.max(x)),
                               'y_mean': (np.min(y), np.max(y)),
                               'x_stddev': (0.001, 1),
                               'y_stddev': (0.001, 1)
                           })
    g2D_init = g2D_init1 + g2D_init2

    fitter = fitting.LevMarLSQFitter()

    g2D = fitter(g2D_init, X, Y, Z)

    KD_fit_sqresid = np.mean(np.power(Z - g2D(X, Y), 2.0))

    #Sort by largest and smallest amplitude gaussian
    i_large = np.argmax([g2D.amplitude_0, g2D.amplitude_1])
    i_small = np.argmin([g2D.amplitude_0, g2D.amplitude_1])
    g2D_large = g2D[i_large]
    g2D_small = g2D[i_small]

    amp_0 = g2D_large.amplitude.value
    amp_1 = g2D_small.amplitude.value

    xmean_0 = g2D_large.x_mean.value
    xmean_1 = g2D_small.x_mean.value

    ymean_0 = g2D_large.y_mean.value
    ymean_1 = g2D_small.y_mean.value

    if g2D_large.x_stddev >= g2D_large.y_stddev:

        major_std_0 = g2D_large.x_stddev.value
        theta_0 = g2D_large.theta.value
        ecc_0 = np.sqrt(1.0 - (g2D_large.y_stddev.value /
                               g2D_large.x_stddev.value)**2.0)

    else:

        major_std_0 = g2D_large.y_stddev.value

        if g2D_large.theta <= np.pi / 2:
            theta_0 = np.pi / 2 + g2D_large.theta.value

        elif g2D_large.theta > np.pi / 2:
            theta_0 = g2D_large.theta.value - np.pi / 2

        ecc_0 = np.sqrt(1.0 - (g2D_large.x_stddev.value /
                               g2D_large.y_stddev.value)**2.0)

    if g2D_small.x_stddev >= g2D_small.y_stddev:

        major_std_1 = g2D_small.x_stddev.value
        theta_1 = g2D_small.theta.value
        ecc_1 = np.sqrt(1.0 - (g2D_small.y_stddev.value /
                               g2D_small.x_stddev.value)**2.0)

    else:

        major_std_1 = g2D_small.y_stddev.value

        if g2D_small.theta <= np.pi / 2:
            theta_1 = np.pi / 2 + g2D_small.theta.value

        elif g2D_small.theta > np.pi / 2:
            theta_1 = g2D_small.theta.value - np.pi / 2

        ecc_1 = np.sqrt(1.0 - (g2D_small.x_stddev.value /
                               g2D_small.y_stddev.value)**2.0)

    return (KDE_bandwidth, KD_fit_sqresid, amp_0, xmean_0, ymean_0,
            major_std_0, theta_0, ecc_0, amp_1, xmean_1, ymean_1, major_std_1,
            theta_1, ecc_1)
Example #32
0
    def fit_gaussian(self, plot=True, verbose=False, save=None, **kwargs):
        """
        Perform a fit of a 2D gaussian. 
        Input:
            - plot: (optional) bool. If True, makes a plot of the image with 
            the contours of the gaussian
            - verbose: (optional) bool. If True, prints the verbose of mpdfit
            - additional optional keywords can be 'amp', 'centerx', 'centery', 
                'sigmax','sigmay','fwhm' or 'theta' to set the value of the 
                first guess of the fit. theta must be between 0 and 90
            - save: (optional) string with the name to save a pdf of the fit (only
                    valid if plot=True)
                    and a ds9 reg file (still to be implemented)
        Output:
            - fit_result: a dictionary with the parameters of the best fit. 
            The entries are 'AMP' 'X' 'FWHMX' 'Y' 'FWHMY' 'FWHM' 'THETA' 'ell' 
            - fit_error: a dictionary with the parameters of the error on the previous parameters (same entries)
            - chi2: value of the chi square
            - chi2_reduced: value of the reduced chi squared
        """

        # We first set a default guess
        filtered_image = gaussian_filter(self.subimage, 2)
        #        if save is not None:
        #            fits.writeto(save+'_initial.fits',self.subimage,clobber=True)
        argmax = np.nanargmax(filtered_image)
        ymax, xmax = np.unravel_index(argmax, self.subimage.shape)
        amp = np.nanmax(self.subimage)
        centerx = xmax - self.subimage_half_size_x  # the x center is in the range -subimage_half_size_x .. subimage_half_size_x
        centery = ymax - self.subimage_half_size_y  # the y center is in the range -subimage_half_size_y .. subimage_half_size_y
        guess_dico = {
            'amp': amp,
            'centerx': centerx,
            'centery': centery,
            'sigx': 2.,
            'sigy': 2.,
            'theta': 0.
        }
        for k, v in kwargs.items():
            if k in guess_dico.keys():
                guess_dico[k] = v
            elif k == 'fwhm':
                guess_dico['sigx'] = fwhm2sig(v)
                guess_dico['sigy'] = fwhm2sig(v)
            elif k == 'fwhmx':
                guess_dico['sigx'] = fwhm2sig(v)
            elif k == 'fwhmy':
                guess_dico['sigy'] = fwhm2sig(v)
            else:
                raise TypeError('Keyword {0:s} not understood'.format(k))

        # We also set default boundaries
        parinfo = [
            {
                'fixed': 0,
                'limited': [1, 1],
                'limits': [0., 2 * np.max([guess_dico['amp'], amp])]
            },  # Force the amplitude to be >0
            {
                'fixed':
                0,
                'limited': [1, 1],
                'limits': [
                    -self.subimage_half_size_x + 1,
                    self.subimage_half_size_x - 2
                ]
            },  # We restrain the center to be 1px 
            {
                'fixed':
                0,
                'limited': [1, 1],
                'limits': [
                    -self.subimage_half_size_y + 1,
                    self.subimage_half_size_y - 2
                ]
            },  # away from the edge
            {
                'fixed': 0,
                'limited': [1, 1],
                'limits': [0.5, np.max([10., guess_dico['sigx']])]
            },  # sigma_x between 0.5 and 10px
            {
                'fixed': 0,
                'limited': [1, 1],
                'limits': [0.5, np.max([10., guess_dico['sigy']])]
            },  # sigma_y between 0.5 and 10px
            {
                'fixed': 0,
                'limited': [1, 1],
                'limits': [0, 180.]
            }
        ]  # We limit theta beween 0 and 90 deg

        x_vect = np.arange(-self.subimage_half_size_x,
                           self.subimage_half_size_x)
        y_vect = np.arange(-self.subimage_half_size_y,
                           self.subimage_half_size_y)
        x_array, y_array = np.meshgrid(x_vect, y_vect)
        fa = {
            'x': x_array,
            'y': y_array,
            'z': self.subimage,
            'err': np.ones_like(self.subimage) * self.sky_rms
        }
        guess = [
            guess_dico['amp'], guess_dico['centerx'], guess_dico['centery'],
            guess_dico['sigx'], guess_dico['sigy'], guess_dico['theta']
        ]
        m = mpfit.mpfit(self.gauss2D_fit_erf,
                        guess,
                        functkw=fa,
                        parinfo=parinfo,
                        quiet=(not verbose) * 1)
        if m.status == 0:
            print(
                'Fit failed. Try to help the minimizer by providing a better first guess'
            )
            if plot:
                plt.close(1)
                fig = plt.figure(1, figsize=(4.5, 3))
                gs = gridspec.GridSpec(1,
                                       2,
                                       height_ratios=[1],
                                       width_ratios=[1, 0.06])
                gs.update(left=0.1,
                          right=0.9,
                          bottom=0.1,
                          top=0.93,
                          wspace=0.2,
                          hspace=0.03)
                ax1 = plt.subplot(gs[0, 0])  # Area for the first plot
                ax3 = plt.subplot(gs[0, 1])  # Area for the second plot
                im = ax1.imshow(
                    self.subimage,
                    cmap='Greys',
                    origin='lower',
                    interpolation='nearest',
                    extent=[
                        self.guess_x - self.subimage_half_size_x,
                        self.guess_x + self.subimage_half_size_x - 1,
                        self.guess_y - self.subimage_half_size_y,
                        self.guess_y + self.subimage_half_size_y - 1
                    ],
                    vmin=np.nanmin(self.subimage),
                    vmax=np.nanmax(self.subimage))
                ax1.set_xlabel('X in px')
                ax1.set_ylabel('Y in px')
                ax1.grid(True, c='w')
                ax1.text(0.95, 0.01, 'Fit failed',verticalalignment='bottom', horizontalalignment='right',\
                       transform=ax1.transAxes,color='red', fontsize=15)
                fig.colorbar(im, cax=ax3)
                if save is not None:
                    fig.savefig(save + '.pdf')
            null_dico = {
                'AMP': 0,
                'X': 0,
                'Y': 0,
                'FWHMX': 0,
                'FWHMY': 0,
                'FWHM': 0,
                'THETA': 0,
                'ell': 0
            }
            return null_dico, null_dico, 0., 0.
        residuals = self.gauss2D_fit_erf(m.params,
                                         x=x_array,
                                         y=y_array,
                                         z=self.subimage,
                                         err=np.ones_like(self.subimage) *
                                         self.sky_rms)[1].reshape(
                                             self.subimage.shape)
        chi2 = np.sum(residuals**2)
        chi2_reduced = chi2 / m.dof
        sig = np.array([m.params[3], m.params[4]])
        sig_error = np.array([m.perror[3], m.perror[4]])
        error_ell = 4 / (np.sum(sig)**2) * np.sqrt(np.sum(
            (sig * sig_error)**2))
        fwhm = sig2fwhm(sig)
        fwhm_error = sig2fwhm(sig_error)
        fit_result = {'AMP':m.params[0],'X':m.params[1]+self.guess_x,'FWHMX':fwhm[0],\
                      'Y':m.params[2]+self.guess_y,'FWHMY':fwhm[1],'FWHM':np.mean(fwhm),'THETA':m.params[5],'ell':(sig[1]-sig[0])/np.mean(sig)}
        fit_error = { 'AMP':m.perror[0],'X':m.perror[1],'Y':m.perror[2],'FWHMX':fwhm_error[0],\
                     'FWHMY':fwhm_error[1],'FWHM':np.mean(fwhm_error),'THETA': m.perror[5],\
                      'ell':error_ell}
        print('X={0:4.2f}+/-{1:4.2f} Y={2:4.2f}+/-{3:4.2f} FWHM={4:3.2f}+/-{5:4.2f} ell={6:4.2f}+/-{7:4.2f}'.format(fit_result['X'],\
              fit_error['X'],fit_result['Y'],fit_error['Y'],fit_result['FWHM'],fit_error['FWHM'],fit_result['ell'],fit_error['ell'],))
        print('AMP={0:4.2e}+/-{1:3.2e} theta={2:3.1f}+/-{3:3.1f}deg SKY={4:4.2f}+/-{5:4.2f}'.format(fit_result['AMP'],\
              fit_error['AMP'],fit_result['THETA'],fit_error['THETA'],self.sky_median,self.sky_rms))
        print('DOF={0:d} CHI2={1:.1f} CHI2_r={2:.1f}'.format(
            m.dof, chi2, chi2_reduced))
        if plot:
            plt.close(1)
            fig = plt.figure(1, figsize=(7.5, 3))
            gs = gridspec.GridSpec(1,
                                   3,
                                   height_ratios=[1],
                                   width_ratios=[1, 1, 0.06])
            gs.update(left=0.1,
                      right=0.9,
                      bottom=0.1,
                      top=0.93,
                      wspace=0.2,
                      hspace=0.03)
            ax1 = plt.subplot(gs[0, 0])  # Area for the first plot
            ax2 = plt.subplot(gs[0, 1])  # Area for the second plot
            ax3 = plt.subplot(gs[0, 2])  # Area for the second plot
            im = ax1.imshow(self.subimage,
                            cmap='CMRmap',
                            origin='lower',
                            interpolation='nearest',
                            extent=[
                                self.guess_x - self.subimage_half_size_x,
                                self.guess_x + self.subimage_half_size_x - 1,
                                self.guess_y - self.subimage_half_size_y,
                                self.guess_y + self.subimage_half_size_y - 1
                            ],
                            vmin=np.nanmin(self.subimage),
                            vmax=np.nanmax(self.subimage))
            ax1.set_xlabel('X in px')
            ax1.set_ylabel('Y in px')
            ax1.contour(x_array + self.guess_x,
                        y_array + self.guess_y,
                        self.sky_median +
                        Gaussian2D(m.params[0], m.params[1], m.params[2],
                                   m.params[3], m.params[4],
                                   np.radians(m.params[5]))(x_array, y_array),
                        3,
                        colors='w')
            ax1.grid(True, c='w')
            im2 = ax2.imshow(
                residuals,
                cmap='CMRmap',
                origin='lower',
                interpolation='nearest',
                extent=[
                    self.guess_x - self.subimage_half_size_x,
                    self.guess_x + self.subimage_half_size_x - 1,
                    self.guess_y - self.subimage_half_size_y,
                    self.guess_y + self.subimage_half_size_y - 1
                ],
                vmin=np.nanmin(self.subimage),
                vmax=np.nanmax(self.subimage)
            )  #, extent=[np.min(x_array),np.max(x_array),np.min(y_array),np.max(y_array)])
            ax2.set_xlabel('X in px')
            ax2.grid(True, c='w')
            fig.colorbar(im, cax=ax3)
            if save is not None:
                fig.savefig(save + '.pdf')
        return fit_result, fit_error, chi2, chi2_reduced