Beispiel #1
0
def compute_pair_separations_hill_radii(pairs):
    '''
    d = {'pair_inner_radius':[],
          'pair_outer_radius':[],
          's_mass':[],
          's_met':[],
          's_logage':[],
          'pair_inner_sma': [],
          'pair_outer_sma': [],
          'n_planet_in_sys':[],
          'pair_ind':[]}
    '''
    inner_masses, outer_masses = [], []
    for inner_rad, outer_rad in zip(arr(pairs['pair_inner_radius']),
                                    arr(pairs['pair_outer_radius'])):

        inner_masses.append(_get_WM14_mass(inner_rad))
        outer_masses.append(_get_WM14_mass(outer_rad))

    pairs['pair_inner_mass'] = arr(inner_masses)
    pairs['pair_outer_mass'] = arr(outer_masses)

    m_j = arr(pairs['pair_inner_mass']) * u.Mearth
    m_jp1 = arr(pairs['pair_outer_mass']) * u.Mearth
    M_star = arr(pairs['s_mass']) * u.Msun
    a_j = arr(pairs['pair_inner_sma']) * u.au
    a_jp1 = arr(pairs['pair_outer_sma']) * u.au

    R_H = 0.5 * ((m_j + m_jp1) / (3 * M_star))**(1 / 3) * (a_j + a_jp1)
    sep = (a_jp1 - a_j) / R_H

    pairs['R_H'] = R_H.to(u.au).value
    pairs['sep_by_RH'] = sep.cgs.value

    return pairs
Beispiel #2
0
def scatter_p2byp1_vs_p1(pairs):
    # the period ratio P2/P1 tends to be larger than average when P1 is less
    # than about 2-3 days

    a1 = arr(pairs['pair_inner_sma'])
    a2 = arr(pairs['pair_outer_sma'])
    P1 = arr(pairs['pair_inner_period'])
    P2 = arr(pairs['pair_outer_period'])
    aByRstar1 = arr(pairs['pair_inner_abyRstar'])
    aByRstar2 = arr(pairs['pair_outer_abyRstar'])

    plt.close('all')
    f, ax = plt.subplots(figsize=(8, 6))

    ax.scatter(P1, P2 / P1, marker='o', s=5, c='#1f77b4', zorder=2)

    ax.get_yaxis().set_tick_params(which='both', direction='in')
    ax.get_xaxis().set_tick_params(which='both', direction='in')

    ax.set_xlabel('$P_1$, inner period of planet pair [days]',
                  fontsize='medium')
    ax.set_ylabel('$P_2/P_1$, ratio of planet pair periods', fontsize='medium')
    ax.set_xscale('log')
    ax.set_yscale('log')

    savpath = '../results/cks_multis_vs_age/scatter_p2byp1_vs_p1.pdf'

    f.tight_layout(h_pad=0, w_pad=0)
    f.savefig(savpath, bbox_inches='tight')

    print('made {:s}'.format(savpath))
Beispiel #3
0
def hill_radius_pairs_vs_age(pairs, aByRstar_cut=20):

    plt.close('all')
    f, ax = plt.subplots(nrows=1, ncols=1, figsize=(8, 6))

    a1 = arr(pairs['pair_inner_sma'])
    a2 = arr(pairs['pair_outer_sma'])
    P1 = arr(pairs['pair_inner_period'])
    P2 = arr(pairs['pair_outer_period'])
    aByRstar1 = arr(pairs['pair_inner_abyRstar'])
    aByRstar2 = arr(pairs['pair_outer_abyRstar'])

    sep_by_RH = arr(pairs['sep_by_RH'])
    s_logage = arr(pairs['s_logage'])  # really giso_slogage

    sel = (aByRstar1 < aByRstar_cut) & (aByRstar2 < aByRstar_cut)

    ax.scatter(sep_by_RH[sel], 10**(s_logage[sel]) / 1e9)

    ax.set_xlabel('separation in mutual hill radii')
    ax.set_ylabel('age [Gyr]')

    from matplotlib.ticker import MultipleLocator, FormatStrFormatter
    ax.xaxis.set_major_locator(MultipleLocator(10))
    ax.xaxis.set_major_formatter(FormatStrFormatter('%d'))
    #ax.yaxis.set_major_locator(MultipleLocator(10))
    #ax.yaxis.set_major_formatter(FormatStrFormatter('%d'))

    ax.get_yaxis().set_tick_params(which='both', direction='in')
    ax.get_xaxis().set_tick_params(which='both', direction='in')
    ax.grid(True, zorder=-2, which='major', alpha=0.2)

    ax.set_title('{:d} pairs where both planets have '
                 '$a/R_\star<${:d}'.format(len(pairs[sel]), aByRstar_cut))

    f.tight_layout(h_pad=0, w_pad=0)

    savname = (
        '../results/cks_age_plots_old_short_period/' +
        'hill_radius_pairs_vs_age_aByRstar_cut_{:d}.pdf'.format(aByRstar_cut))
    f.savefig(savname, bbox_inches='tight')
    print('saved %s' % savname)
    savname = (
        '../results/cks_age_plots_old_short_period/' +
        'hill_radius_pairs_vs_age_aByRstar_cut_{:d}.png'.format(aByRstar_cut))
    f.savefig(savname, bbox_inches='tight', dpi=350)
    print('saved %s' % savname)
Beispiel #4
0
def _apply_cks_VI_metallicity_study_filters(df):
    '''
    given df from _get_cks_data, return the boolean indices for the
    subset of interest.

    See Weiss+ 2018, CKS VI, table 1.

    Here we reproduce the "full CKS-Gaia multis sample".  We don't make the
    magnitude-limited cut, because we're gonna compare multis to multis.
    '''

    # row zero, `r0` tuple containing stats
    rows = []
    rows.append(_get_Weiss18_table1_stats(df))

    # not a false positive
    is_fp = arr(df['cks_fp'])
    sel = ~is_fp
    rows.append(_get_Weiss18_table1_stats(df[sel]))

    # radius correction factor <5%, logical or not given in Furlan+2017 table.
    sel &= ((arr(df['fur17_rcorr_avg']) < 1.05) |
            (~np.isfinite(df['fur17_rcorr_avg'])))
    rows.append(_get_Weiss18_table1_stats(df[sel]))

    # not grazing (b<0.9)
    sel &= np.isfinite(arr(df['koi_impact']))
    sel &= arr(df['koi_impact']) < 0.9
    rows.append(_get_Weiss18_table1_stats(df[sel]))

    # SNR>10
    sel &= np.isfinite(arr(df['koi_model_snr']))
    sel &= arr(df['koi_model_snr']) > 10.
    rows.append(_get_Weiss18_table1_stats(df[sel]))

    # Rp < 22.4 Re
    sel &= np.isfinite(arr(df['giso_prad']))
    sel &= arr(df['giso_prad']) < 22.4
    rows.append(_get_Weiss18_table1_stats(df[sel]))

    # You need finite ages, too
    sel &= np.isfinite(arr(df['giso_slogage']))
    rows.append(_get_Weiss18_table1_stats(df[sel]))

    for row in rows:
        print(row)

    weiss_18_table_1 = [
        (1944, 1222, 1176),
        (1788, 1118, 1092),
        (1700, 1060, 1042),
        (1563, 990, 940),
        (1495, 952, 908),
        (1491, 948, 892),
    ]

    for rowind, wrow in enumerate(weiss_18_table_1):
        if wrow == rows[rowind]:
            print('row {:d} matches Weiss+18 Table 1'.format(rowind))
        elif np.abs(np.sum(wrow) - np.sum(rows[rowind])) < 10:
            print('row {:d} is close (w/in 10 planets) of Weiss+18 Table 1'.
                  format(rowind))
        else:
            print('row {:d} is quite different from Weiss+18 Table 1'.format(
                rowind))

    return sel
Beispiel #5
0
def scatter_p2byp1_vs_p1_age_percentiles(pairs):

    P1 = arr(pairs['pair_inner_period'])
    P2 = arr(pairs['pair_outer_period'])
    smet = arr(pairs['s_met'])
    slogage = arr(pairs['s_logage'])

    sep = 25
    smet_pctls = [
        np.percentile(smet, pct) for pct in np.arange(0, 100 + sep, sep)
    ]

    slogage_pctls = [
        np.percentile(slogage, pct) for pct in np.arange(0, 100 + 25, 25)
    ]

    # plot pairs by stellar age percentiles
    plt.close('all')
    f, axs = plt.subplots(nrows=2,
                          ncols=2,
                          figsize=(8, 6),
                          sharex=True,
                          sharey=True)
    axs = axs.flatten()

    for ix, ax in enumerate(axs):
        ax.scatter(P1, P2 / P1, marker='o', s=5, c='lightgray', zorder=1)

        if ix == 0:
            sel = slogage < slogage_pctls[ix + 1]
            textstr = 'logage$<${:.2f}\ntot={:d},blue={:d}'.format(
                slogage_pctls[ix + 1], len(pairs), int(len(pairs) * sep / 100))
        elif ix == len(axs) - 1:
            sel = slogage > slogage_pctls[ix]
            textstr = 'logage$>${:.2f}\ntot={:d},blue={:d}'.format(
                slogage_pctls[ix], len(pairs), int(len(pairs) * sep / 100))
        else:
            sel = slogage >= slogage_pctls[ix]
            sel &= slogage < slogage_pctls[ix + 1]
            textstr = 'logage=({:.2f},{:.2f})\ntot={:d},blue={:d}'.format(
                slogage_pctls[ix], slogage_pctls[ix + 1], len(pairs),
                int(len(pairs) * sep / 100))

        ax.scatter(P1[sel],
                   P2[sel] / P1[sel],
                   marker='o',
                   s=3,
                   c='#1f77b4',
                   zorder=2)

        ax.text(0.95,
                0.95,
                textstr,
                horizontalalignment='right',
                verticalalignment='top',
                transform=ax.transAxes,
                fontsize='xx-small')

        ax.set_xscale('log')
        ax.set_yscale('log')
        ax.set_xlim([0.4, 300])
        ax.set_xlim([0.9, 102])
        ax.get_yaxis().set_tick_params(which='both', direction='in')
        ax.get_xaxis().set_tick_params(which='both', direction='in')

    f.tight_layout(h_pad=0, w_pad=0)

    # set labels
    f.add_subplot(111, frameon=False)
    plt.tick_params(labelcolor='none',
                    top=False,
                    bottom=False,
                    left=False,
                    right=False)
    plt.grid(False)
    plt.xlabel('$P_1$, inner period of planet pair [days]', fontsize='medium')
    plt.ylabel('$P_2/P_1$, ratio of planet pair periods', fontsize='medium')

    savpath = '../results/cks_multis_vs_age/scatter_p2byp1_vs_p1_age_percentiles.pdf'

    f.tight_layout(h_pad=0, w_pad=0)
    f.savefig(savpath, bbox_inches='tight')

    print('made {:s}'.format(savpath))
Beispiel #6
0
def split_weiss18_fig1_high_low_met(df, sel):
    # reproduce Weiss+18 CKS VI's Figure 1, the detected system multiplicity
    # function, for high and low metallicity CKS systems.

    u, u_inds, inv_inds, counts = np.unique(df[sel]['id_starname'],
                                            return_index=True,
                                            return_inverse=True,
                                            return_counts=True)
    multiplicity_function = counts  # length: number of systems
    df_multiplicity = counts[inv_inds]  # length: number of transiting planets
    multis = df[sel][df_multiplicity !=
                     1]  # length: number of planets in multi systems

    system_df = df[sel].iloc[
        u_inds]  # length: number of systems. unique stellar properties here!

    # get metallicities for systems with at least two planets
    smet_VII = arr(system_df['cks_smet'])[(counts >= 2)]
    med_smet = np.median(smet_VII)

    sel_highmet = (smet_VII > med_smet)
    bins = np.arange(0.5, 7.5, 1)
    n_highmet, _ = np.histogram(counts[(counts >= 2)][sel_highmet], bins)

    sel_lowmet = (smet_VII <= med_smet)
    n_lowmet, _ = np.histogram(counts[(counts >= 2)][sel_lowmet], bins)

    N = int(np.max(counts))

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

    ind = np.arange(1, N, 1)
    width = 0.35

    rects1 = ax.bar(ind, n_highmet, width)
    rects2 = ax.bar(ind + width, n_lowmet, width)

    ax.set_xlabel('Number of Transiting Planets', fontsize='large')
    ax.set_xlim([0.5, 7.5])
    ax.set_ylabel('Number of Stars', fontsize='large')

    ax.set_xticks(ind + width / 2)
    ax.set_xticklabels(('1', '2', '3', '4', '5', '6'))

    ax.legend((rects1[0], rects2[0]), ('[Fe/H]$>${:.3f}'.format(med_smet),
                                       '[Fe/H]$\le${:.3f}'.format(med_smet)),
              fontsize='xx-small')

    ax.set_title('split CKS+Gaia multis by host star metallicity',
                 fontsize='xx-small')

    def autolabel(rects):
        #Attach a text label above each bar displaying its height
        for rect in rects:
            height = rect.get_height()
            ax.text(rect.get_x() + rect.get_width() / 2.,
                    1.01 * height,
                    '%d' % int(height),
                    ha='center',
                    va='bottom',
                    fontsize='xx-small')

    autolabel(rects1)
    autolabel(rects2)

    f.tight_layout()
    f.savefig(
        '../results/cks_multis_vs_age/cks_gaia_multis_multiplicity_highvlowmet.pdf'
    )