예제 #1
0
def plot_curves(df_pcr, df_melt):
    sgrnas = 'on', 'off', 'rxb 11,1', 'mhf 30'

    n = len(sgrnas)
    fig, axes = plt.subplots(n, 2, sharex='col', figsize=(8, 3*n))

    for i, sgrna in enumerate(sgrnas):
        ax_pcr = axes[i,0]
        ax_melt = axes[i,1]

        # Plot the PCR curves.

        label = matplotlib.offsetbox.AnchoredText(sgrna, loc="upper left")
        ax_pcr.add_artist(label)

        q = df_pcr[df_pcr.sgrna == sgrna]

        for key, well in q.groupby(['promoter', 'primers', 'Well Position']):
            promoter, primers, label = key
            ax_pcr.semilogy(
                    well.Cycle,
                    well.Rn,
                    label=label,
                    basey=2,
                    **pick_style(promoter, primers),
            )

        ax_pcr.set_ylim(2**-1, 2**4)
        ax_pcr.set_xlim(1, ax_pcr.get_xlim()[1])
        ax_pcr.set_ylabel("Rn")
        ax_pcr.grid(True)

        # Plot the melting curves.

        q = df_melt[df_melt.sgrna == sgrna]

        for key, well in q.groupby(['promoter', 'primers', 'Well Position']):
            promoter, primers, label = key
            ax_melt.plot(
                    well.Temperature,
                    well.Derivative / 10000,
                    label=label,
                    **pick_style(promoter, primers),
            )

        x = well.Temperature
        ax_melt.set_xlim(x.min(), x.max())
        ax_melt.set_ylim(0, ax_melt.get_ylim()[1])
        ax_melt.set_ylabel("dFluor/dT (×10⁴)")
        ax_melt.grid(True)

    make_legend(axes[0,1], loc="upper left")
    ax_pcr.set_xlabel("Cycle")
    ax_melt.set_xlabel("Temperature (°C)")
    fig.tight_layout()

    return fig
예제 #2
0
def plot_mic_curve(ax, df, time_hr=12):

    # Pick a time to display.
    t = df['minutes'].unique()
    dt = abs(t - (60 * time_hr))
    time_min = t[dt.argmin()]

    df = df.query('minutes == @time_min')

    for key, group in df.groupby(['sgrna', 'theo_mM']):
        sgrna, theo_mM = key
        style = pick_style(sgrna, theo_mM, color_controls=True)

        # Drop points with only one measurement.
        q = group.groupby('tmp_ug_mL').filter(lambda x: len(x) > 1)

        reps = q.groupby('tmp_ug_mL')
        concs = reps.apply(lambda x: x.name)
        means = reps.mean()['read']
        stdevs = reps.std()['read']

        ## Growth curves.

        ax.semilogy(
            concs,
            means,
            **style,
        )

        ## Error bars:

        # I can't just use `ax.errorbar()`, because it doesn't have allow the
        # error bar lines to be styled, and I need the style to distinguish apo
        # from holo.
        x_err = np.array([concs, concs])
        y_err = np.array([means + stdevs / 2, means - stdevs / 2])

        if style['color'] == 'black':
            style['linestyle'] = '-'

        ax.semilogy(
            x_err,
            y_err,
            marker='_',
            **style,
        )

    label = AnchoredText(f"{int(time_hr)} hr", loc='upper right')
    ax.add_artist(label)

    ax.set_xlabel('TMP (µg/mL)')
    ax.set_xlim(0, 64)
    ax.set_xticks([0, 4, 8, 16, 32, 48, 64])
    #ax.xaxis.set_minor_locator(MultipleLocator(4))

    ax.set_ylabel('OD600')
    ax.set_ylim(0.053, 1.2)
    ax.yaxis.set_major_formatter(StrMethodFormatter("{x:.1f}"))
예제 #3
0
def make_legend(ax, **kwargs):
    ax.legend(
            handles=[
                matplotlib.lines.Line2D(
                    [], [], label="J23150",
                    **pick_style('j23150', 'sgrna'),
                ),
                matplotlib.lines.Line2D(
                    [], [], label="J23119",
                    **pick_style('j23119', 'sgrna'),
                ),
                matplotlib.lines.Line2D(
                    [], [], label="16S rRNA",
                    **pick_style('', '16s'),
                ),
            ],
            **kwargs,
    )
예제 #4
0
def plot_timecourse(ax, df, mid, sgrna, ligand):
    lig0 = ligand.split('→')[0]

    try:
        q0 = df.loc[sgrna, lig0]
        q1 = df.loc[sgrna, ligand]
        q = pd.concat([q0, q1])
    except KeyError:
        return

    x = q['minutes']
    y = q['fold_change']

    std = q['fold_change_err']
    x_err = np.array([x, x])
    y_err = np.array([y + std / 2, y - std / 2])

    styles = {
        'apo→apo': pick_style('control', 0, color_controls=True),
        'apo→holo': pick_style(sgrna, 1, color_controls=True),
        'holo→apo': pick_style(sgrna, 0, color_controls=True),
        'holo→holo': pick_style('control', 1, color_controls=True),
    }
    style = styles[ligand]

    ax.semilogy(x, y, **style)
    ax.semilogy(x_err, y_err, marker='_', **style)

    if (sgrna, ligand) in mid:
        x_mid = mid[sgrna, ligand]
        y_mid = np.interp(x_mid, x, y)
        y_0 = 1e-3

        ax.axvline(
            x_mid,
            linestyle=':',
            color=style['color'],
            zorder=-10,
        )
예제 #5
0
def plot_growth_curves(ax, df, sgrnas, ref_theo_mM=1):
    df_sgrnas = df[df.sgrna.isin(sgrnas)]

    for key, sele in df_sgrnas.groupby(['sgrna', 'theo_mM', 'path', 'well']):
        sgrna, theo_mM, well, path = key
        style = pick_style(sgrna,
                           theo_mM,
                           color_controls=True,
                           standard_mM=ref_theo_mM)
        #ax.semilogy(sele.minutes/60, sele.read, **style)

        #time_hr = sele.minutes / 60
        #smoothed_reads = savgol_filter(sele.read, 21, 1)
        sele = sele.sort_values('minutes')
        hours, reads = sele.minutes / 60, sele.read

        ax.semilogy(hours, reads, **style)
    'fol1 mhf 30': 'ligRNA⁺',
}

fig, axes = plt.subplots(2, 2, sharex=True, sharey=True)

for ax, ligrna in zip(axes.flat, ligrnas):
    legend_entries = []

    for theo in [True, False]:
        q = df.query('ligrna == @ligrna and theo == @theo')
        q_mean = q.groupby('well').agg({
            'od600': 'mean',
            'rel_od600': 'mean',
            'x': 'mean',
        })
        trend_style = pick_style(ligrna, not theo)
        trend_style['label'] = '_nolabel_'
        data_style = {
            'linestyle': 'none',
            'marker': 'o',
            'markeredgecolor': 'none' if theo else trend_style['color'],
            'markerfacecolor': trend_style['color'] if theo else 'none',
        }

        ax.set_title(titles[ligrna])
        data, = ax.plot(q.x, q.rel_od600, **data_style)
        trend, = ax.plot(q_mean.x, q_mean.rel_od600, **trend_style)

        legend_entries.append((
            (data, trend),
            '1 mM theo' if theo else '0 mM theo',
예제 #7
0
def plot_growth_curve(ax, df, tmp_ug_mL=32.0):
    # Pick a TMP concentration to display.
    c = df['tmp_ug_mL'].unique()
    dc = abs(c - (tmp_ug_mL))
    tmp_ug_mL = c[dc.argmin()]

    df = df.query('tmp_ug_mL == @tmp_ug_mL')

    for key, group in df.groupby(['sgrna', 'theo_mM']):
        sgrna, theo_mM = key
        style = pick_style(sgrna, theo_mM, color_controls=True)

        reps = group.groupby('minutes')
        times = reps.apply(lambda x: x.name) / 60
        means = reps.mean()['read']
        log_means = 10**reps['read'].agg(lambda x: np.mean(np.log10(x)))
        medians = reps.median()['read']
        stdevs = reps.std()['read']

        x = times
        y = medians

        ## Growth curves.

        # Plotting the means is smoother, but more affected by outliers
        # (especially for the positive control on a log-scale).
        ax.semilogy(x, y, **style)

        ## Error bars:

        # I can't just use `ax.errorbar()`, because it doesn't have allow the
        # error bar lines to be styled, and I need the style to distinguish apo
        # from holo.
        x_err = np.array([times, times])
        y_err = np.array([y + stdevs / 2, y - stdevs / 2])

        # Stagger the apo and holo error bars, so they don't overlap.
        k = 6
        i = k // 2 * int(theo_mM)

        if style['color'] == 'black':
            style['linestyle'] = '-'

        ax.semilogy(
            x_err[:, i::k],
            y_err[:, i::k],
            marker='_',
            **style,
        )

    label = AnchoredText(f"{tmp_ug_mL} µg/mL TMP", loc='upper left')
    ax.add_artist(label)

    ## Axis decorations:
    ax.set_xlabel('time (h)')
    ax.set_xticks([0, 4, 8, 12, 16, 20])
    ax.set_xlim(0, 20)

    ax.set_ylabel('OD600')
    ax.set_ylim(0.053, 1.00)
    ax.yaxis.set_major_formatter(StrMethodFormatter("{x:.1f}"))
예제 #8
0
ligands = sorted(df.index.get_level_values('ligand_after').unique(),
        key=lambda x: [False, True].index(x))
times = df.index.get_level_values('time').unique()

fig, axes = plt.subplots(
        len(ligands),
        len(sgrnas),
        figsize=(4*len(sgrnas), 4*len(ligands)),
        sharex=True,
        squeeze=False,
)

for i, ligand in enumerate(ligands):
    for j, sgrna in enumerate(sgrnas):
        ax = axes[i,j]
        fit_style = pick_style(sgrna, ligand)
        data_style = pick_data_style(sgrna, ligand)

        q = df.loc[sgrna, ligand]

        t = q.index.get_level_values('time')
        y = q['fold_change']

        ax.plot(t, y, label='_', **data_style)

        fit = fit_decay(q)
        t_fit = np.linspace(0, max(t), 500)
        y_fit = decay(t_fit, fit.k, fit.y0, fit.y_inf)
        label = f'''\
k={fit.k:.1e} ± {fit.k_std:.1e}
y0={fit.y0:.1e} ± {fit.y0_std:.1e}
예제 #9
0
def plot_fits(rxns, stem, subtract_intercept=False, figure_mode=False):
    rows, cols = load_keys(rxns)

    if figure_mode:
        subtract_intercept = True

    size_in = 1.5 if figure_mode else 3.0
    fig_size_in = size_in * len(cols), size_in * len(rows)
    fig, axes = plt.subplots(
            len(rows), len(cols),
            figsize=fig_size_in,
            squeeze=False,
            sharex=True,
            sharey=figure_mode,
    )
    max_t = 0
    min_a420 = {x: inf for x in itertools.product(rows.values(), cols.values())}
    max_a420 = {x: -inf for x in itertools.product(rows.values(), cols.values())}

    for _, rxn in iter_reactions(rxns):
        b = rxn.fit[1] if subtract_intercept else 0
        t, y = rxn.t_min, rxn.a420 - b
        i, j = rxn.i_min, rxn.i_max

        fit_style = pick_style(rxn.sgrna, not rxn.ligand)
        fit_style['label'] = rxn.well
        data_style = fit_style.copy(); data_style.pop('dashes', None)
        data_style.update(marker='+', linestyle='none', label='_nolabel_')
        trim_style = data_style.copy()
        trim_style.update(marker='_', markerfacecolor='none')

        row_key, col_key = rxn.keys
        row = rows[rxn.meta[row_key]]
        col = cols[rxn.meta[col_key]]
        ax = axes[row,col]

        ax.plot(t.iloc[:i], y.iloc[:i], **trim_style)
        ax.plot(t.iloc[i:j], y.iloc[i:j], **data_style)
        ax.plot(t.iloc[j:], y.iloc[j:], **trim_style)

        if rxn.miller != nan:
            ax.plot(t, rxn.linear_fit(t) - b, **fit_style)

        if figure_mode:
            min_a420[row,col] = 0
            max_a420[row,col] = 1
        else:
            min_a420[row,col] = min(min_a420[row,col], min(rxn.a420 - b))
            max_a420[row,col] = max(max_a420[row,col], max(rxn.a420 - b))

        if figure_mode:
            max_t = 20
        else:
            max_t = max(max_t, max(rxn.t_min))

        label = '\n'.join(textwrap.wrap(
            f'{rxn.meta[row_key]} {rxn.meta[col_key]}',
            width=9, break_long_words=False,
        ))
        if not figure_mode:
            ax.legend(title=label, loc='upper left')

    for i, row in enumerate(axes):
        for j, ax in enumerate(row):
            ax.set_ylim(min_a420[i,j], max_a420[i,j])

    for ax in axes[-1,:]:
        ax.set_xlabel('time (min)')
    for ax in axes[:,-1 if figure_mode else 0]:
        box = dict(facecolor='yellow')
        ax.set_ylabel('ΔA420' if subtract_intercept else 'A420')
    for ax in axes.flat:
        ax.set_xlim(0, max_t)

    if figure_mode:
        for ax in axes.flat:
            ax.yaxis.set_tick_params(left=False, labelleft=False)
        for ax in axes[:,-1]:
            ax.yaxis.set_tick_params(right=True, labelright=True)
            ax.yaxis.set_label_position("right")

    finalize_plot(fig, stem, 'fits')