Ejemplo n.º 1
0
def plot_kc19_to_2rxs_age_vs_parallax(max_sep=12 * u.arcsec, overwrite=0):
    #
    # Compare KC2019 isochrone ages for things with matches to things without.
    #

    outpath = (
        '../results/crossmatching/kc19_to_2rxs_age_vs_parallax_sep{}.png'.
        format(max_sep.value))

    if not os.path.exists(outpath) or overwrite:

        kc19_match_df, df = match_kc19_to_2rxs(max_sep=max_sep)

        plt.close('all')
        f, ax = plt.subplots(figsize=(4, 3))

        label = 'KC2019: {} sources'.format(len(df))
        ax.scatter(df.age,
                   1 / (1e-3 * df.parallax),
                   label=label,
                   c='gray',
                   marker='o',
                   zorder=2,
                   rasterized=True,
                   s=1,
                   linewidths=0)

        label = ('KC2019 & ROSAT match < {}": {} sources'.format(
            int(max_sep.value), len(kc19_match_df)))

        ax.scatter(kc19_match_df.age,
                   1 / (1e-3 * kc19_match_df.parallax),
                   label=label,
                   c='k',
                   marker='*',
                   zorder=3,
                   rasterized=True,
                   s=5,
                   linewidths=0)

        ax.legend(loc='best', fontsize='xx-small')

        format_ax(ax)

        ax.set_xlabel('KC2019 log10(isochrone age)')
        ax.set_ylabel('dist [pc] = 1/(parallax [arcsec])')
        ax.set_yscale('log')

        f.tight_layout(pad=0.2)
        savefig(f, outpath)

    else:
        print('found {}'.format(outpath))
Ejemplo n.º 2
0
def plot_feros_spectra(spectrum_path, outpath=None, xlim=None):
    hdul = fits.open(spectrum_path)

    d = hdul[0].data

    wav = d[0, 0]
    flx = d[3, 0]

    if isinstance(xlim, list):
        xmin = xlim[0]
        xmax = xlim[1]
        sel = (wav > xmin) & (wav < xmax)

        wav = wav[sel]
        flx = flx[sel]

    spec = Spectrum1D(spectral_axis=wav * u.AA,
                      flux=flx * u.dimensionless_unscaled)

    f, ax = plt.subplots()
    ax.plot(wav, flx, c='k', zorder=3)

    if isinstance(xlim, list):
        exclude_regions = []
        if xmin < 6709.2 and xmax > 6710.2:
            exclude_regions.append(SpectralRegion(6709.2 * u.AA,
                                                  6710.2 * u.AA))
        if xmin < 6679 and xmax > 6681:
            exclude_regions.append(SpectralRegion(6679 * u.AA, 6681 * u.AA))

        cont_flx = fit_generic_continuum(
            spec, exclude_regions=exclude_regions)(spec.spectral_axis)
        ax.plot(wav, cont_flx, c='r', zorder=2)

    ax.set_xlabel('wavelength [angstrom]')
    ax.set_ylabel('relative flux')

    if isinstance(xlim, list):
        ax.set_xlim(xlim)

    format_ax(ax)
    savefig(f, outpath)
Ejemplo n.º 3
0
def test_veloce_continuum_fit():

    specname = '20200131_837.01_Bouma_final_combined.fits'
    spectrum_path = os.path.join(DATADIR, 'Veloce', specname)

    flx_2d, wav_2d = read_veloce(spectrum_path, start=400, end=-400)

    for o in VELOCE_ORDERS:

        flx, wav = flx_2d[o, :], wav_2d[o, :]
        wav, flx = wav[::-1], flx[::-1]  # wavelength increasing order
        cont_flx, cont_norm_spec = fit_continuum(flx, wav, instrument='Veloce')

        #
        # plot the results
        #
        outpath = os.path.join(
            TESTOUTDIR,
            specname.replace(
                '.fits', '_order{}_continuum_fit.png'.format(str(o).zfill(2))))

        plt.close('all')
        f, axs = plt.subplots(nrows=2, ncols=1, figsize=(6, 4))

        axs[0].plot(wav, flx, c='k', zorder=3, lw=1)
        axs[0].plot(wav, cont_flx, c='r', zorder=2, lw=1)

        sel = ((cont_flx > 0) & (cont_norm_spec.flux < 2) &
               (cont_norm_spec.flux > -1))
        axs[1].plot(cont_norm_spec.wavelength[sel],
                    cont_norm_spec.flux[sel],
                    c='k',
                    lw=1)

        axs[0].set_ylabel('flux')
        axs[1].set_ylabel('contnorm flux')
        axs[1].set_xlabel('wavelength [angstrom]')

        for ax in axs:
            format_ax(ax)
        savefig(f, outpath, writepdf=False)
Ejemplo n.º 4
0
def match_kc19_to_2rxs(max_sep=12 * u.arcsec):
    """
    2RXS has RA/dec of ROSAT sources in J2000.

    Cut on the ROSAT detection likelihood to be >=9. Following the
    Boller et al (2016) abstract, this is "conservative".
    Cut on the "Sflag' screening flag (0=good, not equal to 0 = screening flag
    set).

    https://ui.adsabs.harvard.edu/abs/2016A%26A...588A.103B/abstract
    """

    csvpath = '../data/kc19_to_2rxs_within_{}_arcsec.csv'.format(max_sep.value)

    if not os.path.exists(csvpath):

        #
        # Get 2RXS sources. From Boller+2016, they were taken with the PSPC between
        # June 1990 and Aug 1991.
        #
        with fits.open("../data/Boller_2016_2RXS_ROSAT_sources.fits") as hdul:
            t = Table(hdul[1].data)

        sel = (t['ExiML'] >= 9) & (t['Sflag'] == 0)

        t = t[sel]

        rosat_coord = SkyCoord(nparr(t['_RAJ2000']),
                               nparr(t['_DEJ2000']),
                               frame='icrs',
                               unit=(u.deg, u.deg),
                               equinox=Time(2000.0, format='jyear'),
                               obstime=Time(1991.0, format='jyear'))

        #
        # Get Kounkel & Covey 2019 sources with gaia info crossmatched. Set an
        # annoyingly high 1" absolute tolerance on the ra/dec match between what I
        # got from gaiadr2.source table, and what was listed in KC19 table 1.  Use
        # the gaiadr2.source ra/dec (in this case, "_x", not "_y"). rtol is set as
        # what it needed to be to pass. Set the correct equinox and estimate of
        # observing time by the Gaia satellite, and include the proper motions.
        #
        df = pd.read_csv('../data/kounkel_table1_sourceinfo.csv')

        for k_x, k_y in zip(['ra_x', 'dec_x'], ['ra_y', 'dec_y']):
            np.testing.assert_allclose(nparr(df[k_x]),
                                       nparr(df[k_y]),
                                       rtol=3e-2,
                                       atol=1 / 3600)

        kc19_coord = SkyCoord(nparr(df.ra_x),
                              nparr(df.dec_x),
                              frame='icrs',
                              unit=(u.deg, u.deg),
                              pm_ra_cosdec=nparr(df.pmra) * u.mas / u.yr,
                              pm_dec=nparr(df.pmdec) * u.mas / u.yr,
                              equinox=Time(2015.5, format='jyear'),
                              obstime=Time(2015.5, format='jyear'))

        kc19_coord_rosat_epoch = kc19_coord.apply_space_motion(
            new_obstime=Time(1991.0, format='jyear'))

        #
        # For each ROSAT coordinate, get the nearest KC2019 match. Ensure they are
        # each in the same equinox system (J2000.0).  Examine the separation
        # distribution of the match.
        #

        idx, d2d, _ = rosat_coord.match_to_catalog_sky(
            kc19_coord_rosat_epoch.transform_to(rosat_coord))

        sel = (d2d < 1000 * u.arcsec)  # ~1/3rd of a degree

        bins = np.logspace(-2, 3, 11)

        plt.close('all')
        f, ax = plt.subplots(figsize=(4, 3))
        ax.hist(d2d[sel].to(u.arcsec).value,
                bins=bins,
                cumulative=False,
                color='black',
                fill=False,
                linewidth=0.5)

        format_ax(ax)

        ax.set_xlabel('2RXS to nearest KC19 source [arcsec]')
        ax.set_ylabel('Number per bin')
        ax.set_xscale('log')
        ax.set_yscale('log')

        f.tight_layout(pad=0.2)
        outpath = '../results/crossmatching/kc19_to_2rxs_separation.png'
        savefig(f, outpath)

        #
        # The above shows a hint of a bump at like ~10 arcsec. This is roughly the
        # level of positional uncertainty expected from ROSAT (Ayres+2004,
        # https://ui.adsabs.harvard.edu/abs/2004ApJ...608..957A/abstract).  6" was
        # the design specification accuracy. Seems like 12" (2x the expected
        # positional uncertainty) is a decent place to set the cut. It will give
        # ~1.5k matches.
        #

        sep_constraint = (d2d < max_sep)

        rosat_matches = t[sep_constraint]
        kc19_match_df = df.iloc[idx[sep_constraint]]

        kc19_match_df['has_2RXS_match'] = 1

        kc19_match_df['2RXS_match_dist_arcsec'] = (d2d[sep_constraint].to(
            u.arcsec).value)

        kc19_match_df['2RXS_name'] = rosat_matches['_2RXS']

        kc19_match_df['2RXS_ExiML'] = rosat_matches['ExiML']

        kc19_match_df.to_csv(csvpath, index=False)
        print('made {}'.format(csvpath))

    else:
        kc19_match_df = pd.read_csv(csvpath)
        df = pd.read_csv('../data/kounkel_table1_sourceinfo.csv')

    return kc19_match_df, df
Ejemplo n.º 5
0
def get_toi837_li_equivalent_width():

    spectrum_path = '../data/spectra/TOI-837_FEROS.fits'
    plotpath = '../results/TOI_837/feros_spectrum_get_li_equivalent_width.png'

    #
    # fit out the continuum to get the continuum normalized flux, over the
    # window of 6670 angstrom to 6713 angstrom.
    #
    xlim = [6670, 6713]

    hdul = fits.open(spectrum_path)
    d = hdul[0].data
    wav = d[0, 0]
    flx = d[3, 0]

    if isinstance(xlim, list):
        xmin = xlim[0]
        xmax = xlim[1]
        sel = (wav > xmin) & (wav < xmax)

        wav = wav[sel]
        flx = flx[sel]

    spec = Spectrum1D(spectral_axis=wav * u.AA,
                      flux=flx * u.dimensionless_unscaled)

    if isinstance(xlim, list):
        exclude_regions = []
        if xmin < 6709.2 and xmax > 6710.2:
            exclude_regions.append(SpectralRegion(6709.2 * u.AA,
                                                  6710.2 * u.AA))
        if xmin < 6679 and xmax > 6681:
            exclude_regions.append(SpectralRegion(6679 * u.AA, 6681 * u.AA))

    cont_flx = (fit_generic_continuum(spec, exclude_regions=exclude_regions)(
        spec.spectral_axis))

    cont_norm_spec = spec / cont_flx

    #
    # to fit gaussians, look at 1-flux.
    #
    full_spec = Spectrum1D(spectral_axis=cont_norm_spec.wavelength,
                           flux=(1 - cont_norm_spec.flux))

    #
    # get the Li EW
    #
    region = SpectralRegion(6708.5 * u.AA, 6711.5 * u.AA)
    li_equiv_width = equivalent_width(cont_norm_spec, regions=region)
    li_centroid = centroid(full_spec, region)

    #
    # fit a gaussian too, and get ITS equiv width
    # https://specutils.readthedocs.io/en/stable/fitting.html
    #
    g_init = models.Gaussian1D(amplitude=0.2 * u.dimensionless_unscaled,
                               mean=6709.7 * u.AA,
                               stddev=0.5 * u.AA)
    g_fit = fit_lines(full_spec, g_init, window=(region.lower, region.upper))
    y_fit = g_fit(full_spec.wavelength)

    fitted_spec = Spectrum1D(spectral_axis=full_spec.wavelength,
                             flux=(1 - y_fit) * u.dimensionless_unscaled)
    fitted_li_equiv_width = equivalent_width(fitted_spec, regions=region)

    #
    # print bestfit params
    #
    print(42 * '=')
    print('got Li equiv width of {}'.format(li_equiv_width))
    print('got fitted Li equiv width of {}'.format(fitted_li_equiv_width))
    print('got Li centroid of {}'.format(li_centroid))
    print('fit gaussian1d params are\n{}'.format(repr(g_fit)))
    print(42 * '=')

    #
    # plot the results
    #
    f, axs = plt.subplots(nrows=4, ncols=1, figsize=(6, 8))

    axs[0].plot(wav, flx, c='k', zorder=3)
    axs[0].plot(wav, cont_flx, c='r', zorder=2)

    axs[1].plot(cont_norm_spec.wavelength, cont_norm_spec.flux, c='k')

    axs[2].plot(cont_norm_spec.wavelength, cont_norm_spec.flux, c='k')

    axs[3].plot(full_spec.wavelength, full_spec.flux, c='k')
    axs[3].plot(full_spec.wavelength, y_fit, c='g')

    txt = ('gaussian1d\namplitude:{:.3f}\nmean:{:.3f}\nstd:{:.3f}\nEW:{:.3f}'.
           format(g_fit.amplitude.value, g_fit.mean.value, g_fit.stddev.value,
                  fitted_li_equiv_width))
    axs[3].text(0.95,
                0.95,
                txt,
                ha='right',
                va='top',
                transform=axs[3].transAxes,
                fontsize='xx-small')

    axs[0].set_ylabel('flux')
    axs[1].set_ylabel('contnorm flux')
    axs[2].set_ylabel('contnorm flux [zoom]')
    axs[3].set_ylabel('1 - (contnorm flux)')

    if isinstance(xlim, list):
        for ax in axs:
            ax.set_xlim(xlim)

    axs[2].set_xlim([6708.5, 6711.5])
    axs[3].set_xlim([6708.5, 6711.5])
    axs[-1].set_xlabel('wavelength [angstrom]')

    for ax in axs:
        format_ax(ax)
    outpath = '../results/TOI_837/toi837_li_equivalent_width_routine.png'
    savefig(f, outpath)