Beispiel #1
0
def GaussMoffatFit(pixels, projected_footprint, amplitude, x_0, gamma, alpha,
                   A, mu, sigma, residuals, i, plot):
    g_init   = models.Moffat1D(amplitude = amplitude, x_0 = x_0, gamma = gamma, alpha=alpha)\
                                           +  models.Gaussian1D(amplitude=A, mean=mu, stddev=sigma)
    g_init.stddev_1.min = 0.5
    g_init.stddev_1.max = 3.
    g_init.amplitude_0.min = 1.
    g_init.amplitude_0.max = A / 10.
    g_init.gamma_0.min = 1.
    g_init.gamma_0.max = 2.
    g_init.alpha_0.min = 1.
    g_init.alpha_0.max = 2.

    fit_g = fitting.LevMarLSQFitter()
    psf = fit_g(g_init, pixels, projected_footprint)

    start = psf.x_0_0 - 10 * psf.stddev_1
    end = psf.x_0_0 + 10 * psf.stddev_1
    integralGM = (integrate.quad(lambda pixels: psf(pixels), start, end))[0]
    integralG = np.sqrt(2 * np.pi) * psf.stddev_1 * psf.amplitude_1
    ''' begin Control plot'''
    if ((not i % 10) and (i < 400) and (plot == True)):
        pl.plot(pixels, psf(pixels), label='Gauss+Moffat')
        pl.yscale('log')
        pl.ylim(1., 1E6)
        pl.plot(pixels, projected_footprint)
        pl.legend()
        pl.show()
    ''' End control plot'''
    '''Filling residuals'''
    residuals[:, i] = psf(pixels) - projected_footprint
    return integralGM, integralG, psf.amplitude_0.value, psf.x_0_0.value, psf.gamma_0.value, psf.alpha_0.value, psf.amplitude_1.value, psf.mean_1.value, psf.stddev_1.value
Beispiel #2
0
def test_moffat_fwhm(gamma):
    ans = 34.641016151377542
    kwargs = {'gamma': gamma, 'alpha': 0.5}
    m1 = models.Moffat1D(**kwargs)
    m2 = models.Moffat2D(**kwargs)
    assert_allclose([m1.fwhm, m2.fwhm], ans)
    assert_array_less(0, [m1.fwhm, m2.fwhm])
Beispiel #3
0
def make_2dspec_image(
    nx=3000,
    ny=1000,
    background=5,
    trace_center=None,
    trace_order=3,
    trace_coeffs={'c0': 0, 'c1': 50, 'c2': 100},
    source_amplitude=10,
    source_alpha=0.1
):
    """
    Create synthetic 2D spectroscopic image with a single source. The spatial (y-axis) position
    of the source along the dispersion (x-axis) direction is modeled using a Chebyshev polynomial.
    The flux units are counts and the noise is modeled as Poisson.

    Parameters
    ----------
    nx : int (default=3000)
        Size of image in X axis which is assumed to be the dispersion axis
    ny : int (default=1000)
        Size of image in Y axis which is assumed to be the spatial axis
    background : int (default=5)
        Level of constant background in counts
    trace_center : int (default=None)
        Zeropoint of the trace. If None, then use center of Y (spatial) axis.
    trace_order : int (default=3)
        Order of the Chebyshev polynomial used to model the source's trace
    trace_coeffs : dict (default={'c0': 0, 'c1': 50, 'c2': 100})
        Dict containing the Chebyshev polynomial coefficients to use in the trace model
    source_amplitude : int (default=10)
        Amplitude of modeled source in counts
    source_alpha : float (default=0.1)
        Power index of the source's Moffat profile. Use small number here to emulate
        extended source.

    Returns
    -------
    ccd_im : `~astropy.nddata.CCDData`
        CCDData instance containing synthetic 2D spectroscopic image
    """
    x = np.arange(nx)
    y = np.arange(ny)
    xx, yy = np.meshgrid(x, y)

    profile = models.Moffat1D()
    profile.amplitude = source_amplitude
    profile.alpha = source_alpha

    if trace_center is None:
        trace_center = ny / 2

    trace_mod = models.Chebyshev1D(degree=trace_order, **trace_coeffs)
    trace = yy - trace_center + trace_mod(xx/nx)
    z = background + profile(trace)
    noisy_image = apply_poisson_noise(z)

    ccd_im = CCDData(noisy_image, unit=u.count)

    return ccd_im
def MoffatFit(pixels, projected_footprint, A, mu, sigma):
    g_init = models.Moffat1D(amplitude=A, x_0=mu, gamma=sigma)
    fit_g = fitting.LevMarLSQFitter()
    psf = fit_g(g_init, pixels, projected_footprint)
    start = psf.x_0 - 5 * psf.gamma
    end = psf.x_0 + 5 * psf.gamma
    integral = (integrate.quad(lambda pixels: psf(pixels), start, end))[0]
    ''' begin Control plot'''
    #pl.plot(pixels, psf(pixels), label='Moffat')
    #pl.yscale('log')
    #pl.ylim(1., 1E6)
    #pl.plot(projected_footprint)
    ''' End control plot'''
    return
Beispiel #5
0
    def model_data(self):

        #Astropy Simplex LSQ Fitter for PSFs
        fitter = fitting.SimplexLSQFitter()

        #Try to fit Moffat in X direction
        try:
            moffatx_init = models.Moffat1D(1.2 * np.max(self.xdata), self.x,
                                           1.0, 1.0)
            moffatx_fit = fitter(moffatx_init, self.X[self.x0:self.x1],
                                 self.xdata[self.x0:self.x1])
            self.xmoff = moffatx_fit(self.Xs)
            self.x_opt = moffatx_fit.x_0.value
        except:
            self.xmoff = np.zeros_like(self.Xs)
            self.x_opt = self.x

        #Try to fit Moffat in Y direction
        try:
            #self.ydata -= np.median(self.ydata)
            moffaty_init = models.Moffat1D(1.2 * np.max(self.ydata), self.y,
                                           1.0, 1.0)
            moffaty_fit = fitter(moffaty_init, self.Y[self.y0:self.y1],
                                 self.ydata[self.y0:self.y1])
            self.ymoff = moffaty_fit(self.Ys)
            self.y_opt = moffaty_fit.x_0.value
        except:
            self.ymoff = np.zeros_like(self.Ys)
            self.y_opt = self.y

        #Update upper and lower bounds for fitting PSF
        self.x0 = max(0, self.x - self.dx)
        self.x1 = min(self.X[-1] - 1, self.x + self.dx)

        self.y0 = max(0, self.y - self.dy)
        self.y1 = min(self.Y[-1] - 1, self.y + self.dy)
Beispiel #6
0
def fit_moffat_1d(data, gamma=2., alpha=1.):
    """Fit a 1D moffat profile to the data and return the fit."""
    # data is assumed to already be chunked to a reasonable size
    ldata = len(data)
    x = np.arange(ldata)

    # Fit model to data
    fit = fitting.LevMarLSQFitter()

    # Moffat1D
    model = models.Moffat1D(amplitude=max(data), x_0=ldata/2, gamma=gamma, alpha=alpha)
    with warnings.catch_warnings():
        # Ignore model linearity warning from the fitter
        warnings.simplefilter('ignore')
        results = fit(model, x, data)

    # previous yield amp, ycenter, xcenter, sigma, offset
    return results
Beispiel #7
0
def fit_moffat_1d(x, y, gamma=2., alpha=1.):
    """Fit a 1D moffat profile to the data and return the fit."""
    # Fit model to data
    fit = fitting.LevMarLSQFitter()

    x_0 = x[0]

    # Moffat1D
    model = models.Moffat1D(amplitude=max(y),
                            x_0=x_0,
                            gamma=gamma,
                            alpha=alpha)
    with warnings.catch_warnings():
        # Ignore model linearity warning from the fitter
        warnings.simplefilter('ignore')
        results = fit(model, x, y)

    # previous yield amp, ycenter, xcenter, sigma, offset
    return results
Beispiel #8
0
def MoffatFit(pixels, projected_footprint, A, mu, sigma, residuals, i, plot):
    g_init = models.Moffat1D(amplitude=A, x_0=mu, gamma=sigma)
    fit_g = fitting.LevMarLSQFitter()
    psf = fit_g(g_init, pixels, projected_footprint)

    start = psf.x_0 - 5 * psf.gamma
    end = psf.x_0 + 5 * psf.gamma
    integral = (integrate.quad(lambda pixels: psf(pixels), start, end))[0]
    ''' begin Control plot'''
    if ((not i % 10) and (i < 400) and (plot == True)):
        pl.plot(pixels, psf(pixels), label='Moffat')
        pl.yscale('log')
        pl.ylim(1., 1E6)
        pl.plot(pixels, projected_footprint)
        pl.legend()
        pl.show()
        ''' End control plot'''
        '''Filling residuals'''
    #residuals[:, i] = psf(pixels)-projected_footprint
    return integral, psf.x_0.value, psf.gamma.value, psf.alpha.value
Beispiel #9
0
 astmodels.Const1D(amplitude=5.),
 astmodels.Const2D(amplitude=5.),
 astmodels.Disk2D(amplitude=10., x_0=0.5, y_0=1.5, R_0=5.),
 astmodels.Ellipse2D(amplitude=10., x_0=0.5, y_0=1.5, a=2., b=4.,
                     theta=0.1),
 astmodels.Exponential1D(amplitude=10., tau=3.5),
 astmodels.Gaussian1D(amplitude=10., mean=5., stddev=3.),
 astmodels.Gaussian2D(amplitude=10.,
                      x_mean=5.,
                      y_mean=5.,
                      x_stddev=3.,
                      y_stddev=3.),
 astmodels.KingProjectedAnalytic1D(amplitude=10., r_core=5., r_tide=2.),
 astmodels.Logarithmic1D(amplitude=10., tau=3.5),
 astmodels.Lorentz1D(amplitude=10., x_0=0.5, fwhm=2.5),
 astmodels.Moffat1D(amplitude=10., x_0=0.5, gamma=1.2, alpha=2.5),
 astmodels.Moffat2D(amplitude=10., x_0=0.5, y_0=1.5, gamma=1.2, alpha=2.5),
 astmodels.Planar2D(slope_x=0.5, slope_y=1.2, intercept=2.5),
 astmodels.RedshiftScaleFactor(z=2.5),
 astmodels.RickerWavelet1D(amplitude=10., x_0=0.5, sigma=1.2),
 astmodels.RickerWavelet2D(amplitude=10., x_0=0.5, y_0=1.5, sigma=1.2),
 astmodels.Ring2D(amplitude=10., x_0=0.5, y_0=1.5, r_in=5., width=10.),
 astmodels.Sersic1D(amplitude=10., r_eff=1., n=4.),
 astmodels.Sersic2D(amplitude=10.,
                    r_eff=1.,
                    n=4.,
                    x_0=0.5,
                    y_0=1.5,
                    ellip=0.0,
                    theta=0.0),
 astmodels.Sine1D(amplitude=10., frequency=0.5, phase=1.),
Beispiel #10
0
from astropy.modeling import Parameter, Fittable1DModel
from astropy.modeling.polynomial import PolynomialModel

registry = {
    'Gaussian1D':
    models.Gaussian1D(1.0, 1.0, 1.0),
    'GaussianAbsorption1D':
    models.GaussianAbsorption1D(1.0, 1.0, 1.0),
    'Lorentz1D':
    models.Lorentz1D(1.0, 1.0, 1.0),
    'MexicanHat1D':
    models.MexicanHat1D(1.0, 1.0, 1.0),
    'Trapezoid1D':
    models.Trapezoid1D(1.0, 1.0, 1.0, 1.0),
    'Moffat1D':
    models.Moffat1D(1.0, 1.0, 1.0, 1.0),
    'ExponentialCutoffPowerLaw1D':
    models.ExponentialCutoffPowerLaw1D(1.0, 1.0, 1.0, 1.0),
    'BrokenPowerLaw1D':
    models.BrokenPowerLaw1D(1.0, 1.0, 1.0, 1.0),
    'LogParabola1D':
    models.LogParabola1D(1.0, 1.0, 1.0, 1.0),
    'PowerLaw1D':
    models.PowerLaw1D(1.0, 1.0, 1.0),
    'Linear1D':
    models.Linear1D(1.0, 0.0),
    'Const1D':
    models.Const1D(0.0),
    'Redshift':
    models.Redshift(0.0),
    'Scale':
Beispiel #11
0
def fit_ellipse_for_source(
    friendid=None,
    detectid=None,
    coords=None,
    shotid=None,
    subcont=True,
    convolve_image=False,
    pixscale=pixscale,
    imsize=imsize,
    wave_range=None,
):

    if detectid is not None:

        global deth5

        detectid_obj = detectid

        if detectid_obj <= 2190000000:
            det_info = deth5.root.Detections.read_where("detectid == detectid_obj")[0]
            linewidth = det_info["linewidth"]
            wave_obj = det_info["wave"]
            redshift = wave_obj / (1216) - 1
        else:
            det_info = conth5.root.Detections.read_where("detectid == detectid_obj")[0]
            redshift = 0
            wave_obj = 4500

        coords_obj = SkyCoord(det_info["ra"], det_info["dec"], unit="deg")

        shotid_obj = det_info["shotid"]
        fwhm = surveyh5.root.Survey.read_where("shotid == shotid_obj")["fwhm_virus"][0]
        amp = det_info["multiframe"]

        if wave_range is not None:
            wave_range_obj = wave_range
        else:
            if detectid_obj <= 2190000000:
                wave_range_obj = [wave_obj - 2 * linewidth, wave_obj + 2 * linewidth]
            else:
                wave_range_obj = [4100, 4200]

        if coords is not None:
            coords_obj = coords

        if shotid is not None:
            shotid_obj = shotid
            fwhm = surveyh5.root.Survey.read_where("shotid == shotid_obj")[
                "fwhm_virus"
            ][0]

        try:
            hdu = make_narrowband_image(
                coords=coords_obj,
                shotid=shotid_obj,
                wave_range=wave_range_obj,
                imsize=imsize * u.arcsec,
                pixscale=pixscale * u.arcsec,
                subcont=subcont,
                convolve_image=convolve_image,
                include_error=True,
            )

        except:
            print("Could not make narrowband image for {}".format(detectid))
            return np.nan, np.nan

    elif friendid is not None:

        global friend_cat

        sel = friend_cat["friendid"] == friendid
        group = friend_cat[sel]
        coords_obj = SkyCoord(ra=group["icx"][0] * u.deg, dec=group["icy"][0] * u.deg)
        wave_obj = group["icz"][0]
        redshift = wave_obj / (1216) - 1
        linewidth = group["linewidth"][0]
        shotid_obj = group["shotid"][0]
        fwhm = group["fwhm"][0]
        amp = group["multiframe"][0]

        if wave_range is not None:
            wave_range_obj = wave_range
        else:
            wave_range_obj = [wave_obj - 2 * linewidth, wave_obj + 2 * linewidth]

        if shotid is not None:
            shotid_obj = shotid
            fwhm = surveyh5.root.Survey.read_where("shotid == shotid_obj")[
                "fwhm_virus"
            ][0]

        try:
            hdu = make_narrowband_image(
                coords=coords_obj,
                shotid=shotid_obj,
                wave_range=wave_range_obj,
                imsize=imsize * u.arcsec,
                pixscale=pixscale * u.arcsec,
                subcont=subcont,
                convolve_image=convolve_image,
                include_error=True,
            )
        except:
            print("Could not make narrowband image for {}".format(friendid))
            return None

    elif coords is not None:
        coords_obj = coords

        if wave_range is not None:
            wave_range_obj = wave_range
        else:
            print(
                "You need to supply wave_range=[wave_start, wave_end] for collapsed image"
            )

        if shotid is not None:
            shotid_obj = shotid
            fwhm = surveyh5.root.Survey.read_where("shotid == shotid_obj")[
                "fwhm_virus"
            ][0]
        else:
            print("Enter the shotid to use (eg. 20200123003)")

        hdu = make_narrowband_image(
            coords=coords_obj,
            shotid=shotid_obj,
            wave_range=wave_range_obj,
            imsize=imsize * u.arcsec,
            pixscale=pixscale * u.arcsec,
            subcont=subcont,
            convolve_image=convolve_image,
            include_error=True,
        )
    else:
        print("You must provide a detectid, friendid or coords/wave_range/shotid")
        return np.nan, np.nan

    w = wcs.WCS(hdu[0].header)

    if friendid is not None:

        sel_friend_group = friend_cat["friendid"] == friendid
        group = friend_cat[sel_friend_group]
        eps = 1 - group["a2"][0] / group["b2"][0]
        pa = group["pa"][0] * np.pi / 180.0 - 90
        sma = group["a"][0] * 3600 / pixscale

        coords = SkyCoord(ra=group["icx"][0] * u.deg, dec=group["icy"][0] * u.deg)
        wave_obj = group["icz"][0]
        redshift = wave_obj / (1216) - 1
        linewidth = np.nanmedian(group["linewidth"])
        shotid_obj = group["shotid"][0]
        fwhm = group["fwhm"][0]

        geometry = EllipseGeometry(
            x0=w.wcs.crpix[0], y0=w.wcs.crpix[0], sma=sma, eps=eps, pa=pa
        )
    else:
        geometry = EllipseGeometry(
            x0=w.wcs.crpix[0], y0=w.wcs.crpix[0], sma=20, eps=0.2, pa=20.0
        )

    geometry = EllipseGeometry(
        x0=w.wcs.crpix[0], y0=w.wcs.crpix[0], sma=20, eps=0.2, pa=20.0
    )
    # geometry.find_center(hdu.data)
    # aper = EllipticalAperture((geometry.x0, geometry.y0), geometry.sma,
    #                          geometry.sma*(1 - geometry.eps), geometry.pa)

    # plt.imshow(hdu.data, origin='lower')
    # aper.plot(color='white')

    ellipse = Ellipse(hdu[0].data)
    isolist = ellipse.fit_image()
    iso_tab = isolist.to_table()

    if len(iso_tab) == 0:
        geometry.find_center(hdu[0].data, verbose=False, threshold=0.5)
        ellipse = Ellipse(hdu[0].data, geometry)
        isolist = ellipse.fit_image()
        iso_tab = isolist.to_table()

    if len(iso_tab) == 0:
        return np.nan, np.nan, np.nan

        try:
            # compute iso's manually in steps of 3 pixels
            ellipse = Ellipse(hdu[0].data)  # reset ellipse
            iso_list = []
            for sma in np.arange(1, 60, 2):
                iso = ellipse.fit_isophote(sma)
                if np.isnan(iso.intens):
                    # print('break at {}'.format(sma))
                    break
                else:
                    iso_list.append(iso)
            isolist = IsophoteList(iso_list)
            iso_tab = isolist.to_table()
        except:
            return np.nan, np.nan, np.nan

    try:
        model_image = build_ellipse_model(hdu[0].data.shape, isolist)
        residual = hdu[0].data - model_image
    except:
        return np.nan, np.nan, np.nan

    sma = iso_tab["sma"] * pixscale
    const_arcsec_to_kpc = cosmo.kpc_proper_per_arcmin(redshift).value / 60.0

    def arcsec_to_kpc(sma):
        dist = const_arcsec_to_kpc * sma
        return dist

    def kpc_to_arcsec(dist):
        sma = dist / const_arcsec_to_kpc
        return sma

    dist_kpc = (
        sma * u.arcsec.to(u.arcmin) * u.arcmin * cosmo.kpc_proper_per_arcmin(redshift)
    )
    dist_arcsec = kpc_to_arcsec(dist_kpc)

    # print(shotid_obj, fwhm)
    # s_exp1d = models.Exponential1D(amplitude=0.2, tau=-50)

    alpha = 3.5
    s_moffat = models.Moffat1D(
        amplitude=1,
        gamma=(0.5 * fwhm) / np.sqrt(2 ** (1.0 / alpha) - 1.0),
        x_0=0.0,
        alpha=alpha,
        fixed={"amplitude": False, "x_0": True, "gamma": True, "alpha": True},
    )

    s_init = models.Exponential1D(amplitude=0.2, tau=-50)

    fit = fitting.LevMarLSQFitter()
    s_r = fit(s_init, dist_kpc, iso_tab["intens"])

    # Fitting can be done using the uncertainties as weights.
    # To get the standard weighting of 1/unc^2 for the case of
    # Gaussian errors, the weights to pass to the fitting are 1/unc.
    # fitted_line = fit(line_init, x, y, weights=1.0/yunc)

    # s_r = fit(s_init, dist_kpc, iso_tab['intens'])#, weights=iso_tab['intens']/iso_tab['intens_err'] )

    print(s_r)
    try:
        r_n = -1.0 * s_r.tau  # _0 #* const_arcsec_to_kpc
    except:
        r_n = np.nan  # r_n = -1. * s_r.tau_0
    try:
        sel_iso = np.where(dist_kpc >= 2 * r_n)[0][0]
    except:
        sel_iso = -1

    aper = EllipticalAperture(
        (isolist.x0[sel_iso], isolist.y0[sel_iso]),
        isolist.sma[sel_iso],
        isolist.sma[sel_iso] * (1 - isolist.eps[sel_iso]),
        isolist.pa[sel_iso],
    )

    phottable = aperture_photometry(hdu[0].data, aper, error=hdu[1].data)
    flux = phottable["aperture_sum"][0] * 10 ** -17 * u.erg / (u.cm ** 2 * u.s)
    flux_err = phottable["aperture_sum_err"][0] * 10 ** -17 * u.erg / (u.cm ** 2 * u.s)

    lum_dist = cosmo.luminosity_distance(redshift).to(u.cm)
    lum = flux * 4.0 * np.pi * lum_dist ** 2
    lum_err = flux_err * 4.0 * np.pi * lum_dist ** 2

    if detectid:
        name = detectid
    elif friendid:
        name = friendid

    # Get Image data from Elixer
    catlib = catalogs.CatalogLibrary()
    try:
        cutout = catlib.get_cutouts(
            position=coords_obj,
            side=imsize,
            aperture=None,
            dynamic=False,
            filter=["r", "g", "f606W"],
            first=True,
            allow_bad_image=False,
            allow_web=True,
        )[0]
    except:
        print("Could not get imaging for " + str(name))

    zscale = ZScaleInterval(contrast=0.5, krej=1.5)
    vmin, vmax = zscale.get_limits(values=hdu[0].data)

    fig = plt.figure(figsize=(20, 12))
    fig.suptitle(
        "{}  ra={:3.2f}, dec={:3.2f}, wave={:5.2f}, z={:3.2f}, mf={}".format(
            name, coords_obj.ra.value, coords_obj.dec.value, wave_obj, redshift, amp
        ),
        fontsize=22,
    )

    ax1 = fig.add_subplot(231, projection=w)
    plt.imshow(hdu[0].data, vmin=vmin, vmax=vmax)
    plt.xlabel("RA")
    plt.ylabel("Dec")
    plt.colorbar()
    plt.title("Image summed across 4*linewidth")

    ax2 = fig.add_subplot(232, projection=w)
    plt.imshow(model_image, vmin=vmin, vmax=vmax)
    plt.xlabel("RA")
    plt.ylabel("Dec")
    plt.colorbar()
    plt.title("model")

    ax3 = fig.add_subplot(233, projection=w)
    plt.imshow(residual, vmin=vmin, vmax=vmax)
    plt.xlabel("RA")
    plt.ylabel("Dec")
    plt.colorbar()
    plt.title("residuals (image-model)")
    # fig = plt.figure(figsize=(10,5))

    im_zscale = ZScaleInterval(contrast=0.5, krej=2.5)
    im_vmin, im_vmax = im_zscale.get_limits(values=cutout["cutout"].data)

    ax4 = fig.add_subplot(234, projection=cutout["cutout"].wcs)

    plt.imshow(
        cutout["cutout"].data,
        vmin=im_vmin,
        vmax=im_vmax,
        origin="lower",
        cmap=plt.get_cmap("gray"),
        interpolation="none",
    )

    plt.text(
        0.8,
        0.9,
        cutout["instrument"] + cutout["filter"],
        transform=ax4.transAxes,
        fontsize=20,
        color="w",
    )
    plt.contour(hdu[0].data, transform=ax4.get_transform(w))
    plt.xlabel("RA")
    plt.ylabel("Dec")
    aper.plot(
        color="white", linestyle="dashed", linewidth=2, transform=ax4.get_transform(w)
    )

    ax5 = fig.add_subplot(235)
    plt.errorbar(
        dist_kpc.value,
        iso_tab["intens"],
        yerr=iso_tab["intens_err"] * iso_tab["intens"],
        linestyle="none",
        marker="o",
        label="Lya SB profile",
    )

    plt.plot(dist_kpc, s_r(dist_kpc), color="r", label="Lya exp SB model", linewidth=2)

    plt.xlabel("Semi-major axis (kpc)")
    # plt.xlabel('Semi-major axis (arcsec)')
    plt.ylabel("Flux ({})".format(10 ** -17 * (u.erg / (u.s * u.cm ** 2))))
    plt.text(0.4, 0.7, "r_n={:3.2f}".format(r_n), transform=ax5.transAxes, fontsize=16)
    plt.text(
        0.4, 0.6, "L_lya={:3.2e}".format(lum), transform=ax5.transAxes, fontsize=16
    )
    secax = ax5.secondary_xaxis("top", functions=(kpc_to_arcsec, kpc_to_arcsec))
    secax.set_xlabel("Semi-major axis (arcsec)")
    # secax.set_xlabel('Semi-major axis (kpc)')
    plt.xlim(0, 100)

    # plt.plot(sma, s_r(sma), label='moffat psf')

    # plt.plot(dist_kpc.value, s1(kpc_to_arcsec(dist_kpc.value)),
    #        linestyle='dashed', linewidth=2,
    #         color='green', label='PSF seeing:{:3.2f}'.format(fwhm))

    # These two are the exact same
    # s1 = models.Moffat1D()
    # s1.amplitude = iso_tab['intens'][0]
    # alpha=3.5
    # s1.gamma = 0.5*(fwhm*const_arcsec_to_kpc)/ np.sqrt(2 ** (1.0 / alpha) - 1.0)
    # s1.alpha = alpha
    # plt.plot(r_1d, moffat_1d, color='orange')

    #    plt.plot(dist_kpc.value, (s1(dist_kpc.value)),
    #            linestyle='dashed', linewidth=2,
    #             color='blue', label='PSF seeing:{:3.2f}'.format(fwhm))

    E = Extract()
    E.load_shot(shotid_obj)
    moffat_psf = E.moffat_psf(seeing=fwhm, boxsize=imsize, scale=pixscale)
    moffat_shape = np.shape(moffat_psf)
    xcen = int(moffat_shape[1] / 2)
    ycen = int(moffat_shape[2] / 2)
    moffat_1d = (
        moffat_psf[0, xcen:-1, ycen] / moffat_psf[0, xcen, ycen] * iso_tab["intens"][0]
    )
    r_1d = moffat_psf[1, xcen:-1, ycen]
    E.close()

    plt.plot(
        arcsec_to_kpc(pixscale * np.arange(80)),
        iso_tab["intens"][0] * (moffat_psf[0, 80:-1, 80] / moffat_psf[0, 80, 80]),
        linestyle="dashed",
        color="green",
        label="PSF seeing:{:3.2f}".format(fwhm),
    )
    plt.legend()

    if friendid is not None:
        ax6 = fig.add_subplot(236, projection=cutout["cutout"].wcs)
        plot_friends(friendid, friend_cat, cutout, ax=ax6, label=False)
    plt.savefig("fit2d_{}.png".format(name))

    # filename = 'param_{}.txt'.format(name)
    # np.savetxt(filename, (r_n.value, lum.value))

    return r_n, lum, lum_err
Beispiel #12
0
Image_Data_All2 = Image_Data_All[300:400]
Image_Data_All2= np.nan_to_num(Image_Data_All2)

#Define a running median calculator
def RunMedian(x,N):
    idx = np.arange(N) + np.arange(len(x)-N+1)[:,None]
    b = [row[row>0] for row in x[idx]]
    return np.array(map(np.median,b))


#Create the Gaussian and Moffat fits and creates Fit_Data and Fit_Data2
#which contains the parameters for the two models (Moffat still does not work correct)
x = np.linspace(-50,50,100)
Gauss_Model = models.Gaussian1D(amplitude = 1000., mean = 0, stddev = 1., )
Gauss_Model.mean.fixed = False
Moffat_Model = models.Moffat1D(amplitude = 1000, x_0 = 0, gamma = 1, alpha = 2)
Fitting_Model = fitting.LevMarLSQFitter()

Fit_Data_1 = []
Fit_Data_2 = []


for i in range(0, Image_Data_All2.shape[1]):
    Fit_Data_1.append(Fitting_Model(Gauss_Model, x, Image_Data_All2[:,i]))

x2 = np.empty((1024,3))

for n in range(1024):
    x2[n,:] = Fit_Data_1[n].parameters

Amp_Data_1 = x2[:,0]
def RunMedian(x, N):
    idx = np.arange(N) + np.arange(len(x) - N + 1)[:, None]
    b = [row[row > 0] for row in x[idx]]
    return np.array(map(np.median, b))


#Create the Gaussian and Moffat fits and creates Fit_Data and Fit_Data2
#which contains the parameters for the two models (Moffat still does not work correct)
x = np.linspace(-50, 50, 100)
Gauss_Model = models.Gaussian1D(
    amplitude=1000.,
    mean=0,
    stddev=1.,
)
Gauss_Model.mean.fixed = False
Moffat_Model = models.Moffat1D(amplitude=1000, x_0=0, gamma=1, alpha=2)
Fitting_Model = fitting.LevMarLSQFitter()

Fit_Data_1 = []
Fit_Data_2 = []

#Normal Gauss Model Fitting

for i in range(0, Image_Data_All2.shape[1]):
    Fit_Data_1.append(Fitting_Model(Gauss_Model, x, Image_Data_All2[:, i]))

x2 = np.empty((1024, 3))

for n in range(1024):
    x2[n, :] = Fit_Data_1[n].parameters
    else:
        print('Sigma Clipping Complete')

Mean_Poly_Fit = np.ma.polyfit(Mean_Range, Mean_Data_Clipped, Polydegree)
Mean_Range_Fit = np.linspace(0, Image_Pixel_Data.shape[1] - 1,
                             Image_Pixel_Data.shape[1])
Mean_Data_Fit = Mean_Poly_Fit[0] * Mean_Range_Fit**2 + Mean_Poly_Fit[
    1] * Mean_Range_Fit**1 + Mean_Poly_Fit[2]

plt.plot(Mean_Data_1)
plt.plot(Mean_Data_Fit)
plt.show()

#Normal Moffat Model Fitting

Moffat_Model = models.Moffat1D(amplitude=1000, x_0=0, gamma=1, alpha=2)

Fit_Data_2 = []

for i in range(0, Image_Pixel_Data.shape[1]):
    if Fit_Data_2:  # true if not an empty list
        Moffat_Model = models.Moffat1D(amplitude=Ampl_Data_1[-1],
                                       x_0=Mean_Data_Fit[i],
                                       gamma=1.3,
                                       alpha=0.9)
        Moffat_Model.x_0.fixed = True
    Fit_Data_2.append(Fitting_Model(Moffat_Model, x, Image_Pixel_Data[:, i]))
    Fit_Data_2[0] = Fitting_Model(
        models.Moffat1D(amplitude=Ampl_Data_1[0],
                        x_0=Mean_Data_Fit[0],
                        gamma=1.3,
Beispiel #15
0
def moffatModel(pars):
    amp, mu, sigma = pars
    moff = models.Moffat1D(amplitude=amp, x_0=mu, gamma=sigma)
    return moff
fit = fitting.LevMarLSQFitter()
gaus_1 = models.Gaussian1D(amplitude=np.amax(c1_height), mean=0.5*np.pi, stddev=0.05*np.pi)
gaus_2 = models.Gaussian1D(amplitude=np.amax(c2_height), mean=0.5*np.pi, stddev=0.05*np.pi)
th_fit = 0.5 * (c1_th[1:] + c1_th[:-1])  # np.linspace(c_min,c_max,len(c1_height))
th_plot = np.linspace(c_min,c_max,10000)
gausfit_1 = fit(gaus_1, th_fit, c1_height)
# ax_CC[0].plot(th_plot, gausfit_1(th_plot), ls=':', lw=0.9, color='black')
gausfit_2 = fit(gaus_2, th_fit, c2_height)
# ax_CC[1].plot(th_plot, gausfit_2(th_plot), ls=':', lw=0.9, color='black')

c1_stddev = 1. * gausfit_1.stddev # * 2.355 se fwhm 
c2_stddev = 1. * gausfit_2.stddev
print('c1_stddev = {:.3f} pi'.format(c1_stddev / np.pi))
print('c2_stddev = {:.3f} pi'.format(c2_stddev / np.pi))

moff_1 = models.Moffat1D(amplitude=np.amax(c1_height), x_0=0.5*np.pi, gamma=1, alpha=1)
moff_2 = models.Moffat1D(amplitude=np.amax(c2_height), x_0=0.5*np.pi, gamma=1, alpha=1)
th_fit = 0.5 * (c1_th[1:] + c1_th[:-1])  # np.linspace(c_min,c_max,len(c1_height))
th_plot = np.linspace(c_min,c_max,10000)
moffit_1 = fit(moff_1, th_fit, c1_height)
ax_CC[0].plot(th_plot, moffit_1(th_plot), ls='--', lw=0.9, color='black')
moffit_2 = fit(moff_2, th_fit, c2_height)
ax_CC[1].plot(th_plot, moffit_2(th_plot), ls='--', lw=0.9, color='black')

# fig_CC.tight_layout()

for i in range(2):
	ax_CC[i].grid(ls=':',which='both')
	ax_CC[i].set_xlim(c_min,c_max)
	# ax_CC[i].xaxis.set_major_locator(tck.MultipleLocator(0.15 / 2 * np.pi))
	ax_CC[i].set_xticks(np.array([0.350, 0.425, 0.500, 0.575, 0.650]) * np.pi)
Beispiel #17
0
def psfSubtract(fits,
                pos,
                redshift=None,
                vwindow=1000,
                radius=5,
                mode='scale2D',
                errLimit=3,
                inst='PCWI'):
    global lines, skylines

    ##### EXTRACT DATA FROM FITS
    data = fits[0].data  #data cube
    head = fits[0].header  #header

    #ROTATE (TEMPORARILY) SO THAT AXIS 2 IS 'IN-SLICE' for KCWI DATA
    if instrument == 'KCWI':
        data_rot = np.zeros((data.shape[0], data.shape[2], data.shape[1]))
        for wi in range(len(data)):
            data_rot[wi] = np.rot90(data[wi], k=1)
        data = data_rot
        pos = (pos[1], pos[0])

    w, y, x = data.shape  #Cube dimensions
    X = np.arange(x)  #Create domains X,Y and W
    Y = np.arange(y)
    W = np.array([
        head["CRVAL3"] + head["CD3_3"] * (i - head["CRPIX3"]) for i in range(w)
    ])

    ##### CREATE USEFUl VARIABLES & DATA STRUCTURES
    cmodel = np.zeros_like(data)  #Cube to store 3D continuum model
    usewav = np.ones_like(
        W, dtype=bool
    )  #Boolean array for whether or not to use wavelengths in fitting
    Xs = np.linspace(X[0], X[-1],
                     10 * x)  #Smooth X-Y domains for PSF modelling
    Ys = np.linspace(Y[0], Y[-1], 10 * y)
    ydist = 3600 * np.sqrt(
        np.cos(head["CRVAL2"] * np.pi / 180) * head["CD1_2"]**2 +
        head["CD2_2"]**2)  #X & Y pixel sizes in arcseconds
    xdist = 3600 * np.sqrt(
        np.cos(head["CRVAL2"] * np.pi / 180) * head["CD1_1"]**2 +
        head["CD2_1"]**2)
    ry = int(round(radius / ydist))  #X and Y 'radius' extent in pixels
    rx = int(round(radius / xdist))

    ##### EXCLUDE EMISSION LINE WAVELENGTHS
    usewav[W < head["WAVGOOD0"]] = 0
    usewav[W > head["WAVGOOD1"]] = 0
    if redshift != None:
        for line in lines:
            wc = (redshift + 1) * line
            dw = (vwindow * 1e5 / 3e10) * wc
            a, b = params.getband(wc - dw, wc + dw, head)
            usewav[a:b] = 0

    ##### OPTIMIZE CENTROID

    xc, yc = pos  #Take input position tuple

    x0, x1 = max(0, xc - rx), min(x,
                                  xc + rx + 1)  #Get bounding box for PSF fit
    y0, y1 = max(0, yc - ry), min(y, yc + ry + 1)

    img = np.sum(data[usewav, y0:y1, x0:x1], axis=0)  #Create white light image

    xdomain, xdata = range(x1 - x0), np.sum(
        img, axis=0)  #Get X and Y PSF profiles/domains
    ydomain, ydata = range(y1 - y0), np.sum(img, axis=1)

    fit = fitting.SimplexLSQFitter()  #Get astropy fitter class

    moffat_bounds = {'amplitude': (0, float("inf"))}
    xMoffInit = models.Moffat1D(max(xdata), x_0=xc - x0,
                                bounds=moffat_bounds)  #Initial guesses
    yMoffInit = models.Moffat1D(max(ydata), x_0=yc - y0, bounds=moffat_bounds)

    xMoffFit = fit(xMoffInit, xdomain, xdata)  #Fit Moffat1Ds to each axis
    yMoffFit = fit(yMoffInit, ydomain, ydata)

    xc_new = xMoffFit.x_0.value + x0
    yc_new = yMoffFit.x_0.value + y0

    #If the new centroid is beyond our anticipated error range away... just use scale method
    if abs(xc - xc_new) * xdist > errLimit or abs(yc -
                                                  yc_new) * ydist > errLimit:
        mode = 'scale2D'

        #Otherwise, update the box to center better on our continuum source
    else:
        xc, yc = int(round(xc_new)), int(
            round(yc_new))  #Round to nearest integer
        x0, x1 = max(0, xc - rx), min(x, xc + rx + 1)  #Get new ranges
        y0, y1 = max(0, yc - ry), min(y, yc + ry + 1)
        xc = max(0, min(x - 1, xc))  #Bound new variables to within image
        yc = max(0, min(y - 1, yc))

    #This method creates a 2D continuum image and scales it at each wavelength.
    if mode == 'scale2D':

        print 'scale2D',

        ##### CREATE CROPPED CUBE
        cube = data[:, y0:y1, x0:x1].copy(
        )  #Create smaller working cube to isolate continuum source

        ##### CREATE 2D CONTINUUM IMAGE
        cont2d = np.mean(cube[usewav], axis=0)  #Create 2D continuum image

        fitter = fitting.LinearLSQFitter()

        ##### BUILD 3D CONTINUUM MODEL
        for i in range(cube.shape[0]):

            A0 = max(0,
                     float(np.sum(cube[i])) /
                     np.sum(cont2d))  #Initial guess for scaling factor

            scale_init = models.Scale()

            scale_fit = fitter(scale_init, np.ndarray.flatten(cont2d),
                               np.ndarray.flatten(cube[i]))

            model = scale_fit.factor.value * cont2d  #Add this wavelength layer to the model

            data[i, y0:y1, x0:x1] -= model  #Subtract from data cube

            cmodel[i, y0:y1, x0:x1] += model  #Add to larger model cube

    #This method just fits a simple line to the spectrum each spaxel; for flat continuum sources.
    elif mode == 'lineFit':

        print 'lineFit',
        #Define custom astropy model class (just a line)
        @custom_model
        def line(xx, m=0, c=0):
            return m * xx + c

        #Run through pixels in 2D region
        for yi in range(y0, y1):
            for xi in range(x0, x1):

                m_init = line()  #Create initial guess model
                m = fit(m_init, W[usewav], data[usewav, yi,
                                                xi])  #Optimize model

                model = m(W)

                cmodel[:, yi, xi] += model
                data[:, yi, xi] -= model

    #This method extracts a central spectrum and fits it to each spaxel
    elif mode == 'specFit':

        print 'specFit',
        #Define custom astropy model class (just a line)
        @custom_model
        def line(xx, m=0, c=0):
            return m * xx + c

        ##### GET QSO SPECTRUM
        q_spec = data[:, yc, xc].copy()
        q_spec_fit = q_spec[usewav == 1]

        #Run through slices
        for yi in range(y0, y1):

            print yi,
            sys.stdout.flush()

            #If this not the main QSO slice
            if yi != yc:

                #Extract QSO spectrum for this slice
                s_spec = data[:, yi, xc].copy()
                s_spec_fit = s_spec[usewav == 1]

                #Estimate wavelength shift needed
                corr = scipy.signal.correlate(s_spec, q_spec)
                corrs = scipy.ndimage.filters.gaussian_filter1d(corr, 5.0)
                w_offset = (np.nanargmax(corrs) - len(corrs) / 2) / 2.0

                #Find wavelength offset (px) for this slice
                chisq = lambda x: s_spec_fit[10:-10] - x[
                    0] * scipy.ndimage.interpolation.shift(
                        q_spec_fit, x[1], order=4, mode='reflect')[10:-10]

                p0 = [np.max(s_spec) / np.max(q_spec), w_offset]

                lbound = [0.0, -5]
                ubound = [5.1, 5]
                for j in range(len(p0)):
                    if p0[j] < lbound[j]: p0[j] = lbound[j]
                    elif p0[j] > ubound[j]: p0[j] = ubound[j]

                p_fit = scipy.optimize.least_squares(chisq,
                                                     p0,
                                                     bounds=(lbound, ubound),
                                                     jac='3-point')

                A0, dw0 = p_fit.x

                q_spec_shifted = scipy.ndimage.interpolation.shift(
                    q_spec_fit, dw0, order=3, mode='reflect')

            else:
                q_spec_shifted = q_spec_fit
                A0 = 0.5
                dw0 = 0

            lbound = [0.0, -5]
            ubound = [20.0, 5]

            for xi in range(x0, x1):

                spec = data[:, yi, xi]
                spec_fit = spec[usewav == 1]

                #First fit to find wav offset for this slice
                chisq = lambda x: spec_fit - x[
                    0] * scipy.ndimage.interpolation.shift(
                        q_spec_fit, x[1], order=3, mode='reflect')

                p0 = [A0, dw0]
                for j in range(len(p0)):
                    if p0[j] < lbound[j]: p0[j] = lbound[j]
                    elif p0[j] > ubound[j]: p0[j] = ubound[j]
                    #elif abs(p0[j]<1e-6): p0[j]=0

                sys.stdout.flush()
                p_fit = scipy.optimize.least_squares(chisq,
                                                     p0,
                                                     bounds=(lbound, ubound),
                                                     jac='3-point')

                A, dw = p_fit.x

                m_spec = A * scipy.ndimage.interpolation.shift(
                    q_spec, dw, order=4, mode='reflect')

                #Do a linear fit to residual and correct linear errors
                residual = data[:, yi, xi] - m_spec

                ydata = residual[usewav == 1]
                xdata = W[usewav == 1]

                #m_init = line() #Create initial guess model
                #m = fit(m_init, xdata, ydata) #Optimize model

                #linefit = m(W)

                model = m_spec
                #residual = data[:,yi,xi] - model

                if 0 and abs(yi - yc) < 1 and abs(xi - xc) < 1:

                    plt.figure(figsize=(16, 8))

                    plt.subplot(311)
                    plt.title(r"$A=%.4f,d\lambda=%.3fpx$" % (A, dw))
                    plt.plot(W, spec, 'bx', alpha=0.5)
                    plt.plot(W[usewav == 1], spec[usewav == 1], 'kx')
                    plt.plot(W, A * q_spec, 'g-', alpha=0.8)
                    plt.plot(W, model, 'r-')
                    plt.xlim([W[0], W[-1]])
                    plt.ylim([1.5 * min(spec), max(spec) * 1.5])
                    plt.subplot(312)
                    plt.xlim([W[0], W[-1]])

                    plt.plot(W, residual, 'gx')
                    plt.ylim([1.5 * min(residual), max(spec) * 1.5])

                    plt.subplot(313)
                    plt.hist(residual)

                    plt.tight_layout()
                    plt.show()

                cmodel[:, yi, xi] += model
                data[:, yi, xi] -= model
    #ROTATE BACK IF ROTATED AT START
    if instrument == 'KCWI':
        data_rot = np.zeros((data.shape[0], data.shape[2], data.shape[1]))
        cmodel_rot = np.zeros((data.shape[0], data.shape[2], data.shape[1]))
        for wi in range(len(data)):
            data_rot[wi] = np.rot90(data[wi], k=3)
            cmodel_rot[wi] = np.rot90(cmodel[wi], k=3)
        data = data_rot
        cmodel = cmodel_rot

    return data, cmodel
Beispiel #18
0
fitsimage_1.info()

fits1 = fitsimage_1[0]

#print(fits1.data.shape)

#print(fits1.header)

Image_Data_0 = fits1.data[:,0]
Image_Data2_0 = Image_Data_0[325:375]
Image_Data_All = fits1.data[:,:]
Image_Data_All2 = Image_Data_All[325:375]
x = np.linspace(-50,50,50)

Gauss_Model = models.Gaussian1D(amplitude = 1000., mean = 0, stddev = 1.)
Moffat_Model = models.Moffat1D(amplitude = 1000., x_0 = 0, gamma = 2., alpha = 1.)


Fitting_Model = fitting.LevMarLSQFitter()



Fit_Data = []
Fit_Data_2 = []

for i in range(0, Image_Data_All2.shape[1]):
    Fit_Data.append(Fitting_Model(Gauss_Model, x, Image_Data_All2[:,i]))

for i in range(0, Image_Data_All2.shape[1]):
    Fit_Data_2.append(Fitting_Model(Moffat_Model, x, Image_Data_All2[:,i]))
Beispiel #19
0
def get_mask(fits, regfile):

    print "\tGenerating 2D mask from region file"

    #EXTRACT/CREATE USEFUL VARS############
    data3D = fits[0].data
    head3D = fits[0].header

    W, Y, X = data3D.shape  #Dimensions
    mask = np.zeros((Y, X), dtype=int)  #Mask to be filled in
    x, y = np.arange(X), np.arange(Y)  #Create X/Y image coordinate domains
    xx, yy = np.meshgrid(x, y)  #Create meshgrid of X, Y
    ww = np.array([
        head3D["CRVAL3"] + head3D["CD3_3"] * (i - head3D["CRPIX3"])
        for i in range(W)
    ])

    yPS = np.sqrt(
        np.cos(head3D["CRVAL2"] * np.pi / 180) * head3D["CD1_2"]**2 +
        head3D["CD2_2"]**2)  #X & Y plate scales (deg/px)
    xPS = np.sqrt(
        np.cos(head3D["CRVAL2"] * np.pi / 180) * head3D["CD1_1"]**2 +
        head3D["CD2_1"]**2)

    fit = fitting.SimplexLSQFitter()  #Get astropy fitter class
    Lfit = fitting.LinearLSQFitter()

    usewav = np.ones_like(ww, dtype=bool)
    usewav[ww < head3D["WAVGOOD0"]] = 0
    usewav[ww > head3D["WAVGOOD1"]] = 0

    data2D = np.sum(data3D[usewav], axis=0)
    med = np.median(data2D)

    #BUILD MASK############################
    if regfile[0].coord_format == 'image':

        rr = np.sqrt((xx - x0)**2 + (yy - y0)**2)
        mask[rr <= R] = i + 1

    elif regfile[0].coord_format == 'fk5':

        #AIC = 2k + n Log(RSS/n) [ - (2k**2 +2k )/(n-k-1) ]
        def AICc(dat, mod, k):
            RSS = np.sum((dat - mod)**2)
            n = np.size(dat)
            return 2 * k + n * np.log(RSS / n)  #+ (2*k**2 + 2*k)/(n-k-1)

        head2D = head3D.copy()  #Create a 2D header by modifying 3D header
        for key in [
                "NAXIS3", "CRPIX3", "CD3_3", "CRVAL3", "CTYPE3", "CNAME3",
                "CUNIT3"
        ]:
            head2D.remove(key)
        head2D["NAXIS"] = 2
        head2D["WCSDIM"] = 2
        wcs = WCS(head2D)
        ra, dec = wcs.wcs_pix2world(xx, yy, 0)  #Get meshes of RA/DEC

        for i, reg in enumerate(regfile):

            ra0, dec0, R = reg.coord_list  #Extract location and default radius
            rr = np.sqrt(
                (np.cos(dec * np.pi / 180) * (ra - ra0))**2 +
                (dec - dec0)**2)  #Create meshgrid of distance to source

            if np.min(rr) > R:
                continue  #Skip any sources more than one default radius outside the FOV

            else:

                yc, xc = np.where(rr == np.min(rr))  #Take input position tuple
                xc, yc = xc[0], yc[0]

                rx = 2 * int(round(
                    R / xPS))  #Convert angular radius to distance in pixels
                ry = 2 * int(round(R / yPS))

                x0, x1 = max(0, xc - rx), min(X, xc + rx +
                                              1)  #Get bounding box for PSF fit
                y0, y1 = max(0, yc - ry), min(Y, yc + ry + 1)

                img = np.mean(data3D[usewav, y0:y1, x0:x1],
                              axis=0)  #Not strictly a white-light image
                img -= np.median(img)  #Correct in case of bad sky subtraction

                xdomain, xdata = range(x1 - x0), np.mean(
                    img, axis=0)  #Get X and Y domains/data
                ydomain, ydata = range(y1 - y0), np.mean(img, axis=1)

                moffat_bounds = {'amplitude': (0, float("inf"))}
                xMoffInit = models.Moffat1D(
                    max(xdata), x_0=xc - x0,
                    bounds=moffat_bounds)  #Initial guess Moffat profiles
                yMoffInit = models.Moffat1D(max(ydata),
                                            x_0=yc - y0,
                                            bounds=moffat_bounds)
                xLineInit = models.Linear1D(slope=0, intercept=np.mean(xdata))
                yLineInit = models.Linear1D(slope=0, intercept=np.mean(ydata))

                xMoffFit = fit(xMoffInit, xdomain,
                               xdata)  #Fit Moffat1Ds to each axis
                yMoffFit = fit(yMoffInit, ydomain, ydata)
                xLineFit = Lfit(xLineInit, xdomain,
                                xdata)  #Fit Linear1Ds to each axis
                yLineFit = Lfit(yLineInit, ydomain, ydata)

                kMoff = len(xMoffFit.parameters
                            )  #Get number of parameters in each model
                kLine = len(xLineFit.parameters)

                xMoffAICc = AICc(
                    xdata, xMoffFit(xdomain),
                    kMoff)  #Get Akaike Information Criterion for each
                xLineAICc = AICc(xdata, xLineFit(xdomain), kLine)
                yMoffAICc = AICc(ydata, yMoffFit(ydomain), kMoff)
                yLineAICc = AICc(ydata, yLineFit(ydomain), kLine)

                xIsMoff = xMoffAICc < xLineAICc  # Determine if Moffat is a better fit than a simple line
                yIsMoff = yMoffAICc < yLineAICc

                if xIsMoff and yIsMoff:  #If source has detectable moffat profile (i.e. bright source) expand mask

                    xfwhm = xMoffFit.gamma.value * 2 * np.sqrt(
                        2**(1 / xMoffFit.alpha.value) - 1)  #Get FWHMs
                    yfwhm = yMoffFit.gamma.value * 2 * np.sqrt(
                        2**(1 / yMoffFit.alpha.value) - 1)

                    R = 2 * max(xfwhm * xPS, yfwhm * yPS)

                mask[rr < R] = i + 1

    return mask
Beispiel #20
0
    # ------Gaussian smoothing for tip-tilt uncertainties----------
    final_kernel = con.convolve(added_kernel, gaussian_kernel, normalize_kernel=True)
    if not plot_breakdown: final_kernel.normalize(mode='integral')
    if plot2d: fig = plot_kernel(final_kernel, 'Convolved')

    # ------plotting 1D cross-sections of the 2D kernels----------
    portion = int(fraction_to_plot * (size/2)) + 1
    if plot_breakdown:
        ax.plot(np.arange(portion), airy_kernel.array[size/2][size/2 : size/2 + portion], c='r', lw=1, label='Airy (%.2F")'%radius_arcsec)
        ax.plot(np.arange(portion), moffat_kernel.array[size/2][size/2 : size/2 + portion], c='brown', lw=1, label='Moffat (%.2F")'%fwhm_arcsec)
        ax.plot(np.arange(portion), added_kernel.array[size/2][size/2 : size/2 + portion], c='gray', lw=1, label='Airy + Moffat', linestyle='--')
        ax.plot(np.arange(portion), gaussian_kernel.array[size/2][size/2 : size/2 + portion], c='g', lw=1, label='Gaussian (%.2F")'%gaussian_blur_arcsec)
        fwhm_guess = 0.1#fwhm_arcsec / 4.
        gamma_guess = (fwhm_guess/arcsec_per_pixel)/(2 * np.sqrt(np.power(2, 1./beta) - 1))
        fitted_moffat = fitting.LevMarLSQFitter()(models.Moffat1D(x_0=0, alpha=beta, gamma=gamma_guess, \
                                                                  fixed={'alpha':True, 'x_0':True, 'gamma':False, 'amplitude':False}), \
                                                  np.arange(portion), final_kernel.array[size / 2][size / 2: size / 2 + portion])
        print fitted_moffat #
        fitted_moffat_fwhm_pix = fitted_moffat.gamma * (2 * np.sqrt(np.power(2, 1./fitted_moffat.alpha) - 1))
        fitted_moffat_fwhm_arcsec = fitted_moffat_fwhm_pix * arcsec_per_pixel
        ax.plot(np.arange(portion), fitted_moffat(np.arange(portion)), c='goldenrod', lw=1, label='Fitted Moffat (%.2F")'%fitted_moffat_fwhm_arcsec)
        rms = np.sqrt(np.sum((fitted_moffat(np.arange(portion)) - final_kernel.array[size / 2][size / 2: size / 2 + portion])**2))
        print 'RMS = %.3E'%rms #
        label = 'Convolved: Strehl %.1F'%strehl
    else:
        label = '%s band: Strehl %.1F'%(band, strehl)
    ax.plot(np.arange(portion), final_kernel.array[size/2][size/2 : size/2 + portion], lw=2, label=label)

ax.legend()
ax.set_xlim(0, 0.2 / arcsec_per_pixel)
ax.set_xticklabels(['%.2F' % (float(item) * arcsec_per_pixel) for item in ax.get_xticks()])
Beispiel #21
0
def gausMoffatModel(pars):
    moffatAmp, x0, gamma, alpha, gausAmp, mu, gausSigma = pars
    moff = models.Moffat1D(amplitude=moffatAmp, x_0=x0, gamma=gamma, alpha=alpha)
    gaus = models.Gaussian1D(amplitude=gausAmp, mean=mu, stddev=gausSigma)
    model = gaus + moff
    return model
Beispiel #22
0
def fit_moffat_1d(data,
                  gamma=2.,
                  alpha=1.,
                  sigma_factor=0.,
                  center_at=None,
                  weighted=False):
    """Fit a 1D moffat profile to the data and return the fit.

    Parameters
    ----------
    data: 2D data array
        The input sigma to use
    gamma: float (optional)
        The input gamma to use
    alpha: float (optional)
        The input alpha to use
    sigma_factor: float (optional)
        If sigma>0 then sigma clipping of the data is performed
        at that level
    center_at: float or None
        None by default, set to value to use as center
    weighted: bool
        if weighted is True, then weight the values by basic
        uncertainty hueristic

    Returns
    -------
    The fitted 1D moffat model for the data

    """
    # data is assumed to already be chunked to a reasonable size
    ldata = len(data)

    # guesstimate mean
    if center_at:
        x0 = 0
    else:
        x0 = int(ldata / 2.)

    # assumes negligable background
    if weighted:
        z = np.nan_to_num(1. / np.sqrt(data))  # use as weight

    x = np.arange(ldata)

    # Initialize the fitter
    fitter = fitting.LevMarLSQFitter()
    if sigma_factor > 0:
        fit = fitting.FittingWithOutlierRemoval(fitter,
                                                sigma_clip,
                                                niter=3,
                                                sigma=sigma_factor)
    else:
        fit = fitter

    # Moffat1D + constant
    model = (models.Moffat1D(
        amplitude=max(data), x_0=x0, gamma=gamma, alpha=alpha) +
             models.Polynomial1D(c0=data.min(), degree=0))

    with warnings.catch_warnings():
        # Ignore model linearity warning from the fitter
        warnings.simplefilter('ignore')
        if weighted:
            results = fit(model, x, data, weights=z)
        else:
            results = fit(model, x, data)

    # previous yield amp, ycenter, xcenter, sigma, offset
    # if sigma clipping is used, results is a tuple of data, model
    if sigma_factor > 0:
        return results[1]
    else:
        return results