Beispiel #1
0
def plot_select_sweeps():
    """ Plot Vancomycin & Zosyn to Zosyn 
        Plot Zosyn to Cefazolin
    """
    # abx_settings = {"Vancomycin" : 13,
    #             "Ampicillin" : 0,
    #             "Cefazolin" : 8,
    #             "Ceftriaxone" : 20,#404,
    #             "Cefepime" : 14,
    #             "Zosyn" : 20,#102,
    #             "Ciprofloxacin" : 8,
    #             "Meropenem" : 9,
    #             "Vancomycin_Meropenem" : 9,
    #             "Vancomycin_Zosyn" :  20,#149,
    #             "Vancomycin_Cefepime" : 23,
    #             "Vancomycin_Ceftriaxone" : 31
    #             }
    abx_settings = {
        "Ceftriaxone": 404,
        "Vancomycin_Zosyn": 149,
        "Zosyn": 102,
        "Vancomycin_Ceftriaxone": 31,
        "Vancomycin_Cefepime": 23,
        "Cefepime": 14,
        "Vancomycin": 13,
        "Vancomycin_Meropenem": 9,
        "Meropenem": 9,
        "Cefazolin": 8,
        "Ciprofloxacin": 8,
        "Ampicillin": 0,
    }
    f_name_missrates = 'select_sweep_miss_rates.txt'
    df_predictions = load_predictions()
    df_drugs = get_clinician_prescribing_patterns()
    # df_drugs = for_debugging_plot_select_sweeps(df_drugs, abx_settings)
    opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings)
    opt.solve_and_assign()
    random_covered_rate, clin_covered_rate, ip_covered_rate = opt.get_coverage_rates(
    )
    baseline_clin_miss_rate = 1 - clin_covered_rate
    sweep_one = ("Vancomycin_Zosyn", "Zosyn")
    sweep_two = ("Zosyn", "Cefazolin")
    # sweep_three = ("Zosyn", "Ampicillin")
    sweep_three = ("Ceftriaxone", 'Cefazolin')
    sweep_four = ("Ceftriaxone", 'Ampicillin')
    # fig, ax = plt.subplots(1, 3, figsize=(24,8))

    plt.figure(figsize=(36, 30))
    gs = gridspec.GridSpec(5, 6, wspace=0.5, hspace=0.35)
    ax1a = plt.subplot(gs[0, 2:4])

    ax2a = plt.subplot(gs[1, 1:3])
    ax2b = plt.subplot(gs[1, 3:5])

    ax3a = plt.subplot(gs[2, 1:3])
    ax3b = plt.subplot(gs[2, 3:5])

    ax4a = plt.subplot(gs[3, 1:3])
    ax4b = plt.subplot(gs[3, 3:5])

    ax5a = plt.subplot(gs[4, 1:3])
    ax5b = plt.subplot(gs[4, 3:5])

    axes = [[ax1a], [ax2a, ax2b], [ax3a, ax3b], [ax4a, ax4b], [ax5a, ax5b]]

    # Plot original clinician distribution
    plot_histogram(abx_settings, axes[0][0])
    axes[0][0].set_title("Actual Clinician Allocation")  # hard coded miss rate
    axes[0][0].set_xlabel("Number of Allcations")
    axes[0][0].set_ylabel('')
    with open(f_name_missrates, 'w') as w:
        w.write("Clinician Miss Rate: %.2f\n" %
                (baseline_clin_miss_rate * 100))
    # sweep_one = ('Cefepime', 'Cefazolin')
    for k, sweep in enumerate([sweep_one, sweep_two, sweep_three, sweep_four]):
        opt.reset_df()
        abx_settings_perturbed = {
            key: abx_settings[key]
            for key in abx_settings
        }  #deep copy
        max_deescalation = None
        print("Performing %s to %s sweep" % (sweep[0], sweep[1]))
        random_rates, clin_rates, ip_rates = [], [], []
        c_from_rs, ip_from_rs = [], []

        opt.set_abx_settings(abx_settings_perturbed)
        opt.solve_and_assign()
        r, c, i = opt.get_coverage_rates()
        if k == 0:
            print((1 - c) * 100)
        random_rates.append(1 - r)
        ip_rates.append(1 - i)
        clin_rates.append(1 - c)

        for iter_ in tqdm(range(abx_settings[sweep[0]])):
            abx_settings_perturbed[sweep[0]] -= 1
            abx_settings_perturbed[sweep[1]] += 1
            opt.set_abx_settings(abx_settings_perturbed)
            opt.replace_one(sweep[0], sweep[1])
            opt.solve_and_assign()
            r, c, i = opt.get_coverage_rates()

            random_rates.append(1 - r)
            ip_rates.append(1 - i)
            clin_rates.append(1 - c)

            if 1 - i > baseline_clin_miss_rate and max_deescalation is None:
                # Number of iterations before gettting to baseline clinician error rate
                max_deescalation = abx_settings[
                    sweep[0]] - abx_settings_perturbed[sweep[0]] + 1
                max_deescaltion_miss_rate = ip_rates[len(ip_rates) - 2]
                settings_to_plot = {
                    key: abx_settings_perturbed[key]
                    for key in abx_settings_perturbed
                }
                settings_to_plot[sweep[0]] += 1
                settings_to_plot[sweep[1]] -= 1
                plot_histogram(settings_to_plot, axes[k + 1][0])
                axes[k + 1][0].set_title("Optmized Allocation Fewer %s" %
                                         sweep[0].replace('_', ' & '))
                axes[k + 1][0].set_xlabel('Number of Allocations')
                axes[k + 1][0].set_ylabel('')
                print(max_deescalation)
                d_rate = float(abx_settings[sweep[0]] -
                               (abx_settings_perturbed[sweep[0]] +
                                1)) / abx_settings[sweep[0]]
                with open(f_name_missrates, 'a') as w:
                    w.write("Miss rate of %.2f achieve with %.2f fewer %s\n" %
                            ((max_deescaltion_miss_rate) * 100, d_rate * 100,
                             sweep[0].replace("_", ' & ')))
            # if abx_settings_perturbed == abx_settings:
            #     clin_iter = iter_ # save point on x axis for clinician performance
        if max_deescalation is None:
            max_deescalation = abx_settings[sweep[0]]

        deescalations = [i for i in range(len(random_rates))]
        deescalations.reverse()
        axes[k + 1][1].plot(deescalations,
                            ip_rates,
                            label='Optimized',
                            linewidth=2.0)
        axes[k + 1][1].plot(deescalations,
                            clin_rates,
                            label='Clinician',
                            linewidth=2.0)
        axes[k + 1][1].plot(deescalations,
                            random_rates,
                            label='Random',
                            linewidth=2.0)
        axes[k + 1][1].plot(
            deescalations,
            [baseline_clin_miss_rate for c in range(len(random_rates))],
            linestyle='--',
            color='black')
        axes[k + 1][1].invert_xaxis()
        axes[k + 1][1].set_title("Replacing %s with %s" %
                                 (sweep[0].replace("_", ' & '), sweep[1]))
        axes[k + 1][1].set_xlabel("Number of %s Allocated" %
                                  sweep[0].replace("_", ' & '))
        axes[k + 1][1].set_ylabel("Miss Rate")
        axes[k + 1][1].set_ylim((0.10, 0.40))
        print("Max Re-allocations of %s to %s: %s" %
              (sweep[0], sweep[1], str(max_deescalation)))
        if k == 0:
            axes[k + 1][1].legend(loc='upper left', fontsize='small')

    plt.savefig('select_sweeps.png')
Beispiel #2
0
def bootstrap_miss_rates():
    abx_settings = {
        "Vancomycin": 13,
        "Ampicillin": 0,
        "Cefazolin": 8,
        "Ceftriaxone": 404,
        "Cefepime": 14,
        "Zosyn": 102,
        "Ciprofloxacin": 8,
        "Meropenem": 9,
        "Vancomycin_Meropenem": 9,
        "Vancomycin_Zosyn": 149,
        "Vancomycin_Cefepime": 23,
        "Vancomycin_Ceftriaxone": 31
    }

    # Solve once then bootstrap solutions
    df_predictions = load_predictions()
    df_drugs = get_clinician_prescribing_patterns()
    opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings)
    opt.solve_and_assign()

    rs, cs, ls = [], [], []
    l_c_relatives, l_r_relatives = [], []
    for i in tqdm(range(1000)):

        # Don't stratify, only stratify if bootstrapping the solving procedure as well
        df_drugs_b = (opt.df.sample(frac=1.0, replace=True))
        # # Stratified bootstrap
        # df_drugs_b = pd.DataFrame()
        # for abx in abx_settings:
        #     df_temp = (opt.df
        #         .query("med_description == @abx", engine='python')
        #         .sample(frac=1.0, replace=True)
        #     )
        #     df_drugs_b = pd.concat([df_drugs_b, df_temp])

        # Sanity Check
        # for abx in abx_settings:
        #     num_allocations = len(df_drugs_b[df_drugs_b['med_description'] == abx])
        #     assert num_allocations == abx_settings[abx]

        if i == 0:
            print(opt.n)

        r, c, l = opt.get_coverage_rates(df=df_drugs_b)
        rs.append(1 - r)
        cs.append(1 - c)
        ls.append(1 - l)
        l_r_relative = ((rs[-1] - ls[-1]) / rs[-1]) * 100
        l_r_relatives.append(l_r_relative)
        l_c_relative = ((cs[-1] - ls[-1]) / cs[-1]) * 100
        l_c_relatives.append(l_c_relative)

    # Miss Rates
    r_mean = np.mean(rs) * 100
    r_low = np.percentile(rs, 2.5) * 100
    r_high = np.percentile(rs, 97.5) * 100
    r_miss_rate = "%.2f [%.2f, %.2f]" % (r_mean, r_low, r_high)

    c_mean = np.mean(cs) * 100
    c_low = np.percentile(cs, 2.5) * 100
    c_high = np.percentile(cs, 97.5) * 100
    c_miss_rate = "%.2f [%.2f, %.2f]" % (c_mean, c_low, c_high)

    l_mean = np.mean(ls) * 100
    l_low = np.percentile(ls, 2.5) * 100
    l_high = np.percentile(ls, 97.5) * 100
    l_miss_rate = "%.2f [%.2f, %.2f]" % (l_mean, l_low, l_high)

    # Relative Miss Reductions
    l_c_means = np.mean(l_c_relatives)
    l_c_low = np.percentile(l_c_relatives, 2.5)
    l_c_high = np.percentile(l_c_relatives, 97.5)
    l_c_final = "%.2f [%.2f, %.2f]" % (l_c_means, l_c_low, l_c_high)

    l_r_means = np.mean(l_r_relatives)
    l_r_low = np.percentile(l_r_relatives, 2.5)
    l_r_high = np.percentile(l_r_relatives, 97.5)
    l_r_final = "%.2f [%.2f, %.2f]" % (l_r_means, l_r_low, l_r_high)

    return r_miss_rate, c_miss_rate, l_miss_rate, l_r_final, l_c_final
Beispiel #3
0
def full_waterfall():
    abx_settings = {
        "Vancomycin": 0,
        "Ampicillin": 0,
        "Cefazolin": 0,
        "Ceftriaxone": 0,
        "Cefepime": 0,
        "Zosyn": 0,
        "Ciprofloxacin": 0,
        "Meropenem": 0,
        "Vancomycin_Meropenem": 697,
        "Vancomycin_Zosyn": 0,
        "Vancomycin_Cefepime": 0,
        "Vancomycin_Ceftriaxone": 0
    }
    abx_rankings = [
        'Vancomycin_Meropenem', 'Vancomycin_Cefepime', 'Vancomycin_Zosyn',
        'Zosyn', 'Vancomycin_Ceftriaxone', 'Meropenem', 'Cefepime',
        'Ceftriaxone', 'Ciprofloxacin', 'Cefazolin', 'Ampicillin', 'Vancomycin'
    ]

    if os.path.exists('df_predictions.csv'):
        df_predictions = pd.read_csv('df_predictions.csv')
    else:
        df_predictions = load_predictions()
        df_predictions.to_csv('df_predictions.csv', index=None)

    if os.path.exists('df_drugs.csv'):
        df_drugs = pd.read_csv('df_drugs.csv')
    else:
        df_drugs = get_clinician_prescribing_patterns()
        df_drugs.to_csv('df_drugs.csv', index=None)

    deplete_idx = 0
    push_from_idx = 0
    push_to_idx = 1
    random_rates = []
    ip_rates = []
    counter = 0
    while abx_settings['Vancomycin'] != 697:  # end of sweep
        opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings)
        opt.solve_and_assign()
        r, c, i = opt.get_coverage_rates()
        random_rates.append(r)
        ip_rates.append(i)

        if counter == 10:
            print(abx_settings)
            counter = 0

        # Make more narrow spectrum
        abx_settings[abx_rankings[push_from_idx]] -= 1
        abx_settings[abx_rankings[push_to_idx]] += 1

        if abx_settings[abx_rankings[deplete_idx]] == 0:
            deplete_idx += 1
            print("Moving deplete index from %s to %s" %
                  (abx_rankings[deplete_idx - 1], abx_rankings[deplete_idx]))

        if push_to_idx == len(abx_rankings) - 1:
            push_to_idx = deplete_idx + 1
            push_from_idx = deplete_idx
        else:
            push_from_idx += 1
            push_to_idx += 1

        counter += 1

    clin_rates = [c for i in range(len(random_rates))]
    df = pd.DataFrame(
        data={
            'clin_rates': clin_rates,
            'random_rates': random_rates,
            'ip_rates': ip_rates
        })
    df.to_csv('summary_sweep.csv')
    fix, ax = plt.subplots(1, 1, figsize=(8, 8))
    ax.plot(range(len(random_rates)), random_rates, label='Random Assignment')
    ax.plot(range(len(random_rates)), ip_rates, label='Integer Programming')
    ax.plot(range(len(random_rates)), c, label='Clinician Benchmark')

    fig_name = "summary_sweep.jpg"
    plt.savefig(fig_name)
Beispiel #4
0
def perform_abx_sweep():
    """
    Simulates antibiotic delivery sweeping through different abx prescribing contraints. 
    For each abx pair, we add the number of times the two were prescribed in total (N) in actual practice
    and then sweep contraints from the extreme where only the first antbiotic prescribed N times to the other
    extreme where the other antibiotic is prescribed N times. We show how coverage rate changes as we change 
    these contraints for both the IP decision and a random decision.
    """
    abx_settings = {
        "Vancomycin": 13,
        "Ampicillin": 0,
        "Cefazolin": 8,
        "Ceftriaxone": 404,
        "Cefepime": 14,
        "Zosyn": 102,
        "Ciprofloxacin": 8,
        "Meropenem": 9,
        "Vancomycin_Meropenem": 16,
        "Vancomycin_Zosyn": 153,
        "Vancomycin_Cefepime": 23,
        "Vancomycin_Ceftriaxone": 31
    }
    df_predictions = load_predictions()
    df_drugs = get_clinician_prescribing_patterns()
    opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings)
    opt.solve_and_assign()
    random_covered_rate, clin_covered_rate, ip_covered_rate = opt.get_coverage_rates(
    )

    for abx_to_perturb in abx_settings:
        # plt.figure(figsize=(32,24))
        # fig, ax = plt.subplots(3, 4, figsize=(32, 24))
        # gs = gridspec.GridSpec(4, 24, wspace=2.0)
        # ax1a = plt.subplot(gs[0, 0:6])
        # ax1b = plt.subplot(gs[0, 6:12])
        # ax1c = plt.subplot(gs[0, 12:18])
        # ax1d = plt.subplot(gs[0, 18:24])

        # ax2a = plt.subplot(gs[1, 3:9])
        # ax2b = plt.subplot(gs[1, 9:15])
        # ax2c = plt.subplot(gs[1, 15:21])

        # ax3a = plt.subplot(gs[2, 0:6])
        # ax3b = plt.subplot(gs[2, 6:12])
        # ax3c = plt.subplot(gs[2, 12:18])
        # ax3d = plt.subplot(gs[2, 18:24])

        plt.figure(figsize=(24, 32))
        gs = gridspec.GridSpec(4, 6, wspace=0.5)
        ax1a = plt.subplot(gs[0, 0:2])
        ax1b = plt.subplot(gs[0, 2:4])
        ax1c = plt.subplot(gs[0, 4:6])

        ax2a = plt.subplot(gs[1, 0:2])
        ax2b = plt.subplot(gs[1, 2:4])
        ax2c = plt.subplot(gs[1, 4:6])

        ax3a = plt.subplot(gs[2, 0:2])
        ax3b = plt.subplot(gs[2, 2:4])
        ax3c = plt.subplot(gs[2, 4:6])

        ax4a = plt.subplot(gs[3, 1:3])
        ax4b = plt.subplot(gs[3, 3:5])

        axes = [
            ax1a, ax1b, ax1c, ax2a, ax2b, ax2c, ax3a, ax3b, ax3c, ax4a, ax4b
        ]

        skip = 0
        for ind, abx in enumerate(abx_settings):
            if abx == abx_to_perturb:
                skip = 1
                continue
            else:
                abx_settings_perturbed = {
                    key: abx_settings[key]
                    for key in abx_settings
                }
                print("Performing %s to %s sweep" % (abx_to_perturb, abx))
                random_rates, ip_rates = [], []
                # Total selections to sweep over
                total_selections = abx_settings[abx] + abx_settings[
                    abx_to_perturb]
                abx_settings_perturbed[abx_to_perturb] = total_selections
                abx_settings_perturbed[abx] = 0
                opt.set_abx_settings(abx_settings_perturbed)
                opt.solve_and_assign()
                r, c, i = opt.get_coverage_rates()
                random_rates.append(r)
                ip_rates.append(i)
                if abx_settings_perturbed == abx_settings:
                    clin_iter = -1  # save point on x axis for clinician performance
                for iter_ in tqdm(range(total_selections)):
                    abx_settings_perturbed[abx_to_perturb] -= 1
                    abx_settings_perturbed[abx] += 1
                    opt.set_abx_settings(abx_settings_perturbed)
                    opt.solve_and_assign()
                    r, c, i = opt.get_coverage_rates()
                    random_rates.append(r)
                    ip_rates.append(i)

                    if abx_settings_perturbed == abx_settings:
                        clin_iter = iter_  # save point on x axis for clinician performance

            axes[ind - skip].plot(range(total_selections + 1),
                                  random_rates,
                                  label='Random Assignment')
            axes[ind - skip].plot(range(total_selections + 1),
                                  ip_rates,
                                  label='Integer Programming')
            axes[ind - skip].plot(clin_iter + 1,
                                  clin_covered_rate,
                                  marker='o',
                                  label='Clinician Benchmark')
            # forward = lambda x: total_selections - x
            # backward = lambda x: total_selections - x
            # secax = axes[ind-skip].secondary_xaxis('top', functions=(forward, backward))
            axes[ind - skip].set_xlabel("Num %s Administered" % abx)
            # secaxes[ind-skip].set_xlabel("Num %s Administered" % abx_to_perturb)
            axes[ind - skip].set_ylabel("Coverage Rate")
            axes[ind - skip].set_ylim((0.5, 1.))
            axes[ind - skip].set_title("%s to %s Sweep" %
                                       (abx_to_perturb, abx))
            axes[ind - skip].legend()

        dir_ = './tall_grid/'
        os.makedirs(dir_, exist_ok=True)
        fig_name = "./tall_grid/%s_sweeps.jpg" % abx_to_perturb
        plt.savefig(fig_name)
Beispiel #5
0
def plot_distribution_of_allocated_abx():
    """ Bar plots of allocated abx """
    df = pd.DataFrame()
    abx_settings = {
        "Vancomycin": 13,
        "Ampicillin": 0,
        "Cefazolin": 8,
        "Ceftriaxone": 404,
        "Cefepime": 14,
        "Zosyn": 102,
        "Ciprofloxacin": 8,
        "Meropenem": 9,
        "Vancomycin_Meropenem": 9,
        "Vancomycin_Zosyn": 149,
        "Vancomycin_Cefepime": 23,
        "Vancomycin_Ceftriaxone": 31
    }

    df_predictions = load_predictions()
    df_drugs = get_clinician_prescribing_patterns()
    opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings)

    opt.df = (opt.df.assign(was_covered_dr=opt.df.apply(
        lambda x: opt.compute_was_covered(x), axis=1)))

    # Get counts
    df_final = (opt.df.groupby('med_description').agg(
        num_distinct_csns=('pat_enc_csn_id_coded', 'nunique'),
        num_times_covered_by_dr=('was_covered_dr', 'sum')
    ).reset_index().assign(med_description=lambda x: [
        m.replace('_', ' & ') + " [%s/%s]" % (nc, nd) for m, nd, nc in zip(
            x.med_description, x.num_distinct_csns, x.num_times_covered_by_dr)
    ]))

    fig, ax = plt.subplots(1, 1, figsize=(12, 12))
    df_final = df_final.sort_values('num_distinct_csns', ascending=False)
    sns.barplot(x="num_distinct_csns",
                y="med_description",
                ci=None,
                data=df_final,
                ax=ax,
                color='red')
    sns.barplot(x="num_times_covered_by_dr",
                y="med_description",
                ci=None,
                data=df_final,
                ax=ax,
                color='blue')
    ax.set_ylabel("")
    ax.set_xlabel("Number of Allocations")
    ax.set_title(
        "Clinician Antibiotic Selections and Fraction of Patients Covered")
    # ax.set_xlim((0, 550))
    # Save Figure
    # plt.gcf().subplots_adjust(left=0.25)
    # plt.savefig('abx_distribution.png')
    plt.show()

    # Save Miss Rates For Each antibiotic
    fname = 'clinicians_miss_rates_by_abx.csv'
    df_miss_rates = (df_final.assign(num_misses=lambda x: [
        csn - n_c
        for csn, n_c in zip(x.num_distinct_csns, x.num_times_covered_by_dr)
    ]))

    df_miss_rates.to_csv(fname, index=None)
Beispiel #6
0
    #     w.write("Clinician miss rate:%s\n" % c)
    #     w.write("Optimized miss rate:%s\n" % l)
    #     w.write("Relative Reduction Miss Rate Optimized to Random:%s\n" % lr)
    #     w.write("Relative Reduction Miss Rate Optimized to Clinician:%s\n" % lc)

    # plot_select_sweeps()
    # plot_distribution_of_allocated_abx()
    # bootstrap_miss_rates()

    abx_settings = {
        "Ceftriaxone": 404,
        "Vancomycin_Zosyn": 149,
        "Zosyn": 102,
        "Vancomycin_Ceftriaxone": 31,
        "Vancomycin_Cefepime": 23,
        "Cefepime": 14,
        "Vancomycin": 13,
        "Vancomycin_Meropenem": 9,
        "Meropenem": 9,
        "Cefazolin": 8,
        "Ciprofloxacin": 8,
        "Ampicillin": 0,
    }

    f_name_missrates = 'individual_sweep_test.txt'
    df_predictions = load_predictions()
    df_drugs = get_clinician_prescribing_patterns()
    opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings)
    plot_sweeps(opt)
    # perform_sweep(opt, abx_1='Vancomycin_Meropenem', abx_2='Vancomycin', ax=ax, fname=f_name_missrates, legend=True)
    # plt.show()