jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def draw_cat_box_plot(data, y, ylim, fpath, fname, col_order=["MCAR", "MAR", "MNAR"], hue_order=None, row_order=None):
    g = sns.factorplot(
        x="Missing Fraction",
        y=y,
        hue="Imputation Method",
        col="Missing Type",
        row="metric",
        data=data,
        kind="box",
        size=4,
        col_order=col_order,
        row_order=row_order,
        hue_order=hue_order,
    )
    g.set_titles(row_template="{row_name}", col_template="{col_name}", size=18).set(ylim=ylim)

    plt.tight_layout(rect=(0, 0, 0.85, 1))
    fpath.mkdir(parents=True, exist_ok=True)
    plt.savefig(fpath/fname)
//  [python]
def draw_cat_box_plot(data, y, ylim, fpath, fname, col_order=["MCAR", "MAR", "MNAR"], hue_order=None, row_order=None):
    g = sns.catplot(
        x="Missing Fraction",
        y=y,
        hue="Imputation Method",
        col="Missing Type",
        row="metric",
        data=data,
        kind="box",
        height=4,
        col_order=col_order,
        row_order=row_order,
        hue_order=hue_order,
        margin_titles=True
    )
    g.set_titles(row_template="{row_name}", col_template="{col_name}", size=18).set(ylim=ylim)

    plt.tight_layout(rect=(0, 0, 0.85, 1))
    fpath.mkdir(parents=True, exist_ok=True)
    plt.savefig(fpath/fname)
//  [python]
def plot_catplot(dframe, save_path=os.path.join(root, "results"), y_lbl="", title="", postfix=None, factorplot=False):
    #  Clear all
    plt.clf()

    #  We define a fake subplot that is in fact only the plot.
    plot = plt.figure(figsize=(4, 3)).add_subplot(111)
    # plot.axhline(linewidth=2)
    # plot.axvline(linewidth=2)

    #  We change the fontsize of minor ticks label
    plot.tick_params(axis='both', which='major', labelsize=20)

    # Covert the Numerical axis to
    dframe['Num'] = dframe['Num'].astype('float')
    sns.barplot(x="Overlap", y="Num", hue="Method", palette=flatui, data=dframe,
                linewidth=1, errwidth=1, ci="sd")

    sns.despine(offset=10)

    #  Set title, axes labels
    # plt.title(title)
    plt.ylabel(y_lbl)
    plt.xlabel("Overlap")
    # plt.legend(loc="best", frameon=False, shadow=False)

    fname = os.path.join(save_path, re.sub(
        " ", "_", title).lower() + postfix + ".png")

    plt.savefig(fname, dpi=300, facecolor='w', edgecolor='w', figsize=(4, 3),
                orientation='portrait', papertype=None, format='png',
                transparent=True, bbox_inches="tight", pad_inches=0,
                frameon=None)
//  [python]
def plot_catplot(dframe, save_path=os.path.join(root, "results"), y_lbl="", title="", postfix=None, factorplot=False):
    #  Clear all
    plt.clf()

    #  We define a fake subplot that is in fact only the plot.
    plot = plt.figure(figsize=(4, 3)).add_subplot(111)
    # plot.axhline(linewidth=2)
    # plot.axvline(linewidth=2)

    #  We change the fontsize of minor ticks label
    plot.tick_params(axis='both', which='major', labelsize=20)

    # Covert the Numerical axis to
    dframe['Num'] = dframe['Num'].astype('float')
    sns.catplot(x="Overlap", y="Num", hue="Method", palette=flatui, data=dframe,
                linewidth=1, kind="bar", legend=False, errwidth=1, ci="sd")

    sns.despine(offset=10)

    #  Set title, axes labels
    # plt.title(title)
    plt.ylabel(y_lbl)
    plt.xlabel("Overlap")
    # plt.legend(loc="best", frameon=False, shadow=False)

    fname = os.path.join(save_path, re.sub(
        " ", "_", title).lower() + postfix + ".png")

    plt.savefig(fname, dpi=300, facecolor='w', edgecolor='w', figsize=(4, 3),
                orientation='portrait', papertype=None, format='png',
                transparent=True, bbox_inches="tight", pad_inches=0,
                frameon=None)
//  [python]
def plot_violin(dframe, save_path=os.path.join(root, "results"), y_lbl="", title="", postfix=None):
    #  Clear all
    plt.clf()

    #  We define a fake subplot that is in fact only the plot.
    g = plt.figure(figsize=(4, 3)).add_subplot(111)

    #  We change the fontsize of minor ticks label
    g.tick_params(axis='both', which='major', labelsize=10)

    # Covert the Numerical axis to
    dframe['Num'] = dframe['Num'].astype('float')
    g = sns.violinplot(x="Overlap", y="Num", hue="Method", palette=flatui,
                    inner='point', data=dframe, linewidth=0.25)
    # g = sns.swarmplot(x="Overlap", y="Num", hue="Method", palette=flatui, inner=None, data=dframe, linewidth=0.25)

    sns.despine(offset=10, trim=True)

    #  Set title, axes labels
    g.set_title(title, size=10)
    g.set_ylabel(y_lbl, size=10)
    g.set_xlabel("Overlap", size=10)
    plt.legend(loc="best", fontsize=10)

    fname = os.path.join(save_path, re.sub(
        " ", "_", title).lower() + "_" + postfix + ".png")

    g.figure.savefig(fname, dpi=300, facecolor='w', edgecolor='w', figsize=(4, 3),
              orientation='portrait', papertype=None, format='png',
              transparent=True, bbox_inches="tight", pad_inches=0.1,
              frameon=None)
//  [python]
def plot_violin(dframe, save_path=os.path.join(root, "results"), y_lbl="", title="", postfix=None):
    #  Clear all
    plt.clf()

    #  We define a fake subplot that is in fact only the plot.
    g = plt.figure(figsize=(4, 3)).add_subplot(111)

    #  We change the fontsize of minor ticks label
    g.tick_params(axis='both', which='major', labelsize=10)

    # Covert the Numerical axis to
    dframe['Num'] = dframe['Num'].astype('float')
    g = sns.catplot(x="Overlap", y="Num", hue="Method", palette=flatui,
                    kind='violin', inner='point', data=dframe, linewidth=0.25, legend=False)
    # g = sns.catplot(x="Overlap", y="Num", hue="Method", palette=flatui, kind='swarm', inner=None, data=dframe, linewidth=0.25, legend=False)

    sns.despine(offset=10, trim=True)

    #  Set title, axes labels
    g.set_titles(title, size=10)
    g.set_ylabels(y_lbl, size=10)
    g.set_xlabels("Overlap", size=10)
    plt.legend(loc="best", fontsize=10)

    fname = os.path.join(save_path, re.sub(
        " ", "_", title).lower() + "_" + postfix + ".png")

    g.savefig(fname, dpi=300, facecolor='w', edgecolor='w', figsize=(4, 3),
              orientation='portrait', papertype=None, format='png',
              transparent=True, bbox_inches="tight", pad_inches=0.1,
              frameon=None)
//  [python]
def pb_support_plot(consensus_data, ordered_genomes, pb_genomes, pb_support_tgt):
    af = luigi.local_target.atomic_file(pb_support_tgt.path)
    with PdfPages(af.tmp_path) as pdf:
        pb_genomes = [x for x in ordered_genomes if x in pb_genomes]  # fix order
        df = json_biotype_counter_to_df(consensus_data, 'IsoSeq Transcript Validation')
        if len(df) == 0:
            # no support information
            return
        df.columns = ['IsoSeq Transcript Validation', 'Number of transcripts', 'genome']
        ax = sns.factorplot(data=df, x='genome', y='Number of transcripts', hue='IsoSeq Transcript Validation',
                            kind='bar', order=pb_genomes)
        ax.set_xticklabels(rotation=90)
        ax.fig.suptitle('Isoforms validated by at least one IsoSeq read')
        multipage_close(pdf, tight_layout=False)
    af.move_to_final_destination()
//  [python]
def pb_support_plot(consensus_data, ordered_genomes, pb_genomes, pb_support_tgt):
    af = luigi.local_target.atomic_file(pb_support_tgt.path)
    with PdfPages(af.tmp_path) as pdf:
        pb_genomes = [x for x in ordered_genomes if x in pb_genomes]  # fix order
        df = json_biotype_counter_to_df(consensus_data, 'IsoSeq Transcript Validation')
        if len(df) == 0:
            # no support information
            return
        df.columns = ['IsoSeq Transcript Validation', 'Number of transcripts', 'genome']
        ax = sns.catplot(data=df, x='genome', y='Number of transcripts', hue='IsoSeq Transcript Validation',
                            kind='bar', row_order=pb_genomes)
        ax.set_xticklabels(rotation=90)
        ax.fig.suptitle('Isoforms validated by at least one IsoSeq read')
        multipage_close(pdf, tight_layout=False)
    af.move_to_final_destination()
//  [python]
def denovo_plot(consensus_data, ordered_genomes, denovo_tgt):
    af = luigi.local_target.atomic_file(denovo_tgt.path)
    with PdfPages(af.tmp_path) as pdf:
        try:
            df = json_biotype_nested_counter_to_df(consensus_data, 'denovo')
        except ValueError:
            # No de novo results. Probably the test set.
            return
        # fix column names because json_biotype_nested_counter_to_df makes assumptions
        df.columns = ['Result', 'Number of transcripts', 'Augustus mode', 'genome']
        has_pb = len(set(df['Augustus mode'])) == 2
        if len(set(df.genome)) > 1:  # if we ran in PB only, we may not have multiple genomes
            if has_pb == True:
                ax = sns.factorplot(data=df, x='genome', y='Number of transcripts', kind='bar', col='Result',
                                    hue='Augustus mode', col_wrap=2, row_order=ordered_genomes, sharex=True,
                                    sharey=False)
            else:
                ax = sns.factorplot(data=df, x='genome', y='Number of transcripts', kind='bar', col='Result',
                                    col_wrap=2, row_order=ordered_genomes, sharex=True, sharey=False)
        else:
            if has_pb == True:
                ax = sns.factorplot(data=df, x='Result', y='Number of transcripts', kind='bar', hue='Augustus mode')
            else:
                ax = sns.factorplot(data=df, x='Result', y='Number of transcripts', kind='bar')
        ax.set_xticklabels(rotation=90)
        ax.fig.suptitle('Incorporation of de-novo predictions')
        ax.fig.subplots_adjust(top=0.9)
        multipage_close(pdf, tight_layout=False)
    af.move_to_final_destination()
//  [python]
def denovo_plot(consensus_data, ordered_genomes, denovo_tgt):
    af = luigi.local_target.atomic_file(denovo_tgt.path)
    with PdfPages(af.tmp_path) as pdf:
        try:
            df = json_biotype_nested_counter_to_df(consensus_data, 'denovo')
        except ValueError:
            # No de novo results. Probably the test set.
            return
        # fix column names because json_biotype_nested_counter_to_df makes assumptions
        df.columns = ['Result', 'Number of transcripts', 'Augustus mode', 'genome']
        has_pb = len(set(df['Augustus mode'])) == 2
        if len(set(df.genome)) > 1:  # if we ran in PB only, we may not have multiple genomes
            if has_pb == True:
                ax = sns.catplot(data=df, x='genome', y='Number of transcripts', kind='bar', col='Result',
                                    hue='Augustus mode', col_wrap=2, row_order=ordered_genomes, sharex=True,
                                    sharey=False)
            else:
                ax = sns.catplot(data=df, x='genome', y='Number of transcripts', kind='bar', col='Result',
                                    col_wrap=2, row_order=ordered_genomes, sharex=True, sharey=False)
        else:
            if has_pb == True:
                ax = sns.catplot(data=df, x='Result', y='Number of transcripts', kind='bar', hue='Augustus mode')
            else:
                ax = sns.catplot(data=df, x='Result', y='Number of transcripts', kind='bar')
        ax.set_xticklabels(rotation=90)
        ax.fig.suptitle('Incorporation of de-novo predictions')
        ax.fig.subplots_adjust(top=0.9)
        multipage_close(pdf, tight_layout=False)
    af.move_to_final_destination()
//  [python]
def tm_gene_family_plot(tm_data, ordered_genomes, biotypes, gene_family_tgt):
    """transMap gene family collapse plots."""
    try:
        df = json_biotype_nested_counter_to_df(tm_data, 'Gene Family Collapse')
    except ValueError:  # no gene family collapse. probably the test set.
        with gene_family_tgt.open('wb') as outf:
            pass
        return
    df['Gene Family Collapse'] = pd.to_numeric(df['Gene Family Collapse'])
    tot_df = df[['Gene Family Collapse', 'genome', 'count']].\
        groupby(['genome', 'Gene Family Collapse']).aggregate(sum).reset_index()
    tot_df = tot_df.sort_values('Gene Family Collapse')
    af = luigi.local_target.atomic_file(gene_family_tgt.path)
    with PdfPages(af.tmp_path) as pdf:
        g = sns.factorplot(y='count', col='genome', x='Gene Family Collapse', data=tot_df, kind='bar',
                           col_order=ordered_genomes, col_wrap=4)
        g.fig.suptitle('Number of genes collapsed during gene family collapse')
        g.set_xlabels('Number of genes collapsed to one locus')
        g.set_ylabels('Number of genes')
        g.fig.subplots_adjust(top=0.9)
        multipage_close(pdf, tight_layout=False)
        for biotype in biotypes:
            biotype_df = biotype_filter(df, biotype)
            if biotype_df is None:
                continue
            biotype_df = biotype_df.sort_values('Gene Family Collapse')
            g = sns.factorplot(y='count', col='genome', x='Gene Family Collapse', data=biotype_df, kind='bar',
                               col_order=[x for x in ordered_genomes if x in set(biotype_df.genome)], col_wrap=4)
            g.fig.suptitle('Number of genes collapsed during gene family collapse for {}'.format(biotype))
            g.set_xlabels('Number of genes collapsed to one locus')
            g.set_ylabels('Number of genes')
            g.fig.subplots_adjust(top=0.9)
            multipage_close(pdf, tight_layout=False)
    af.move_to_final_destination()
//  [python]
def tm_gene_family_plot(tm_data, ordered_genomes, biotypes, gene_family_tgt):
    """transMap gene family collapse plots."""
    try:
        df = json_biotype_nested_counter_to_df(tm_data, 'Gene Family Collapse')
    except ValueError:  # no gene family collapse. probably the test set.
        with gene_family_tgt.open('wb') as outf:
            pass
        return
    df['Gene Family Collapse'] = pd.to_numeric(df['Gene Family Collapse'])
    tot_df = df[['Gene Family Collapse', 'genome', 'count']].\
        groupby(['genome', 'Gene Family Collapse']).aggregate(sum).reset_index()
    tot_df = tot_df.sort_values('Gene Family Collapse')
    af = luigi.local_target.atomic_file(gene_family_tgt.path)
    with PdfPages(af.tmp_path) as pdf:
        g = sns.catplot(y='count', col='genome', x='Gene Family Collapse', data=tot_df, kind='bar',
                           col_order=ordered_genomes, col_wrap=4)
        g.fig.suptitle('Number of genes collapsed during gene family collapse')
        g.set_xlabels('Number of genes collapsed to one locus')
        g.set_ylabels('Number of genes')
        g.fig.subplots_adjust(top=0.9)
        multipage_close(pdf, tight_layout=False)
        for biotype in biotypes:
            biotype_df = biotype_filter(df, biotype)
            if biotype_df is None:
                continue
            biotype_df = biotype_df.sort_values('Gene Family Collapse')
            g = sns.catplot(y='count', col='genome', x='Gene Family Collapse', data=biotype_df, kind='bar',
                               col_order=[x for x in ordered_genomes if x in set(biotype_df.genome)], col_wrap=4)
            g.fig.suptitle('Number of genes collapsed during gene family collapse for {}'.format(biotype))
            g.set_xlabels('Number of genes collapsed to one locus')
            g.set_ylabels('Number of genes')
            g.fig.subplots_adjust(top=0.9)
            multipage_close(pdf, tight_layout=False)
    af.move_to_final_destination()
//  [python]
def consensus_support_plot(consensus_data, ordered_genomes, biotypes, modes, title, tgt):
    """grouped violin plots of original intron / intron annotation / exon annotation support"""
    def adjust_plot(g, this_title):
        g.set_xticklabels(rotation=90)
        g.fig.suptitle(this_title)
        g.fig.subplots_adjust(top=0.9)
        for ax in g.axes.flat:
            ax.set_ylabel('Percent supported')
            ax.set_ylim(-1, 101)

    dfs = []
    for i, mode in enumerate(modes):
        df = json_to_df_with_biotype(consensus_data, mode)
        if i > 0:
            df = df[mode]
        dfs.append(df)
    df = pd.concat(dfs, axis=1)
    df = pd.melt(df, value_vars=modes, id_vars=['genome', 'biotype'])
    af = luigi.local_target.atomic_file(tgt.path)
    with PdfPages(af.tmp_path) as pdf:
        if len(ordered_genomes) > 1:
            g = sns.factorplot(data=df, y='value', x='genome', col='variable', col_wrap=2, kind='violin', sharex=True,
                               sharey=True, row_order=ordered_genomes, cut=0)
        else:
            g = sns.factorplot(data=df, y='value', x='variable', kind='violin', sharex=True,
                               sharey=True, row_order=ordered_genomes, cut=0)
        adjust_plot(g, title)
        multipage_close(pdf, tight_layout=False)
        title += ' for {}'
        for biotype in biotypes:
            this_title = title.format(biotype)
            biotype_df = biotype_filter(df, biotype)
            if biotype_df is not None:
                if len(ordered_genomes) > 1:
                    g = sns.factorplot(data=biotype_df, y='value', x='genome', col='variable', col_wrap=2,
                                       kind='violin', sharex=True, sharey=True, row_order=ordered_genomes, cut=0)
                else:
                    g = sns.factorplot(data=df, y='value', x='variable', kind='violin', sharex=True,
                                       sharey=True, row_order=ordered_genomes, cut=0)
                adjust_plot(g, this_title)
                multipage_close(pdf, tight_layout=False)
    af.move_to_final_destination()
//  [python]
def consensus_support_plot(consensus_data, ordered_genomes, biotypes, modes, title, tgt):
    """grouped violin plots of original intron / intron annotation / exon annotation support"""
    def adjust_plot(g, this_title):
        g.set_xticklabels(rotation=90)
        g.fig.suptitle(this_title)
        g.fig.subplots_adjust(top=0.9)
        for ax in g.axes.flat:
            ax.set_ylabel('Percent supported')
            ax.set_ylim(-1, 101)

    dfs = []
    for i, mode in enumerate(modes):
        df = json_to_df_with_biotype(consensus_data, mode)
        if i > 0:
            df = df[mode]
        dfs.append(df)
    df = pd.concat(dfs, axis=1)
    df = pd.melt(df, value_vars=modes, id_vars=['genome', 'biotype'])
    af = luigi.local_target.atomic_file(tgt.path)
    with PdfPages(af.tmp_path) as pdf:
        if len(ordered_genomes) > 1:
            g = sns.catplot(data=df, y='value', x='genome', col='variable', col_wrap=2, kind='violin', sharex=True,
                               sharey=True, row_order=ordered_genomes, cut=0)
        else:
            g = sns.catplot(data=df, y='value', x='variable', kind='violin', sharex=True,
                               sharey=True, row_order=ordered_genomes, cut=0)
        adjust_plot(g, title)
        multipage_close(pdf, tight_layout=False)
        title += ' for {}'
        for biotype in biotypes:
            this_title = title.format(biotype)
            biotype_df = biotype_filter(df, biotype)
            if biotype_df is not None:
                if len(ordered_genomes) > 1:
                    g = sns.catplot(data=biotype_df, y='value', x='genome', col='variable', col_wrap=2,
                                       kind='violin', sharex=True, sharey=True, row_order=ordered_genomes, cut=0)
                else:
                    g = sns.catplot(data=df, y='value', x='variable', kind='violin', sharex=True,
                                       sharey=True, row_order=ordered_genomes, cut=0)
                adjust_plot(g, this_title)
                multipage_close(pdf, tight_layout=False)
    af.move_to_final_destination()
//  [python]
def point_catplot(title=None, **kwargs):
    sns.set(font_scale=2)
    # Kind of hardcoded mplrc.
    g = sns.catplot(
        height=10,
        aspect=0.8,
        capsize=0.5,
        errwidth=0.8,
        palette="hls",
        kind="point",
        **kwargs
    )
    g.fig.suptitle(title, y=1.05)
    g.despine(left=True)
    return g
//  [python]
def indel_plot(consensus_data, ordered_genomes, indel_plot_tgt):
    af = luigi.local_target.atomic_file(indel_plot_tgt.path)
    with PdfPages(af.tmp_path) as pdf:
        tm_df = pd.concat([pd.DataFrame.from_dict(consensus_data[genome]['transMap Indels'], orient='index').T
                           for genome in ordered_genomes])
        try:  # this is a hack to deal with weird small input datasets
            tm_df['genome'] = ordered_genomes
        except:
            return
        tm_df['transcript set'] = ['transMap'] * len(tm_df)
        consensus_df = pd.concat([pd.DataFrame.from_dict(consensus_data[genome]['Consensus Indels'], orient='index').T
                                  for genome in ordered_genomes])
        consensus_df['genome'] = ordered_genomes
        consensus_df['transcript set'] = ['Consensus'] * len(consensus_df)
        df = pd.concat([consensus_df, tm_df])
        df = pd.melt(df, id_vars=['genome', 'transcript set'],
                     value_vars=['CodingDeletion', 'CodingInsertion', 'CodingMult3Indel'])
        df.columns = ['Genome', 'Transcript set', 'Type', 'Percent of transcripts']
        g = sns.factorplot(data=df, x='Genome', y='Percent of transcripts', col='Transcript set',
                           hue='Type', kind='bar', row_order=ordered_genomes,
                           col_order=['transMap', 'Consensus'])
        g.set_xticklabels(rotation=90)
        g.fig.subplots_adjust(top=.8)
        g.fig.suptitle('Coding indels')
        multipage_close(pdf, tight_layout=False)
    af.move_to_final_destination()
//  [python]
def indel_plot(consensus_data, ordered_genomes, indel_plot_tgt):
    af = luigi.local_target.atomic_file(indel_plot_tgt.path)
    with PdfPages(af.tmp_path) as pdf:
        tm_df = pd.concat([pd.DataFrame.from_dict(consensus_data[genome]['transMap Indels'], orient='index').T
                           for genome in ordered_genomes])
        try:  # this is a hack to deal with weird small input datasets
            tm_df['genome'] = ordered_genomes
        except:
            return
        tm_df['transcript set'] = ['transMap'] * len(tm_df)
        consensus_df = pd.concat([pd.DataFrame.from_dict(consensus_data[genome]['Consensus Indels'], orient='index').T
                                  for genome in ordered_genomes])
        consensus_df['genome'] = ordered_genomes
        consensus_df['transcript set'] = ['Consensus'] * len(consensus_df)
        df = pd.concat([consensus_df, tm_df])
        df = pd.melt(df, id_vars=['genome', 'transcript set'],
                     value_vars=['CodingDeletion', 'CodingInsertion', 'CodingMult3Indel'])
        df.columns = ['Genome', 'Transcript set', 'Type', 'Percent of transcripts']
        g = sns.catplot(data=df, x='Genome', y='Percent of transcripts', col='Transcript set',
                           hue='Type', kind='bar', row_order=ordered_genomes,
                           col_order=['transMap', 'Consensus'])
        g.set_xticklabels(rotation=90)
        g.fig.subplots_adjust(top=.8)
        g.fig.suptitle('Coding indels')
        multipage_close(pdf, tight_layout=False)
    af.move_to_final_destination()
//  [python]
def generic_barplot(data, pdf, xlabel, ylabel, title, row_order=None, x=None, y=None, hue=None, hue_order=None,
                    order=None, col=None, col_wrap=None, sharex=True, sharey=True, col_order=None, palette=None,
                    close=True):
    g = sns.factorplot(data=data, x=x, y=y, hue=hue, ci=None, kind='bar', hue_order=hue_order, row_order=row_order,
                       col=col, col_wrap=col_wrap, sharex=sharex, sharey=sharey, col_order=col_order, palette=palette,
                       order=order)
    g.set_xticklabels(rotation=90)
    g.fig.suptitle(title)
    g.fig.subplots_adjust(top=.8)
    g.set_axis_labels(xlabel, ylabel)
    try:  # depending on columns, axes could be flat or not
        axes = list(itertools.chain.from_iterable(g.axes))
    except TypeError:
        axes = g.axes
    for ax in axes:
        ax.yaxis.set_major_locator(matplotlib.ticker.MaxNLocator(nbins=10, steps=[1, 2, 5, 10], integer=True))
        ax.margins(y=0.15)
        ax.autoscale(enable=True, axis='y', tight=False)
        ax.set_ylim(0, ax.get_ylim()[1])
    if close == True:
        multipage_close(pdf, tight_layout=False)
    return g
//  [python]
def generic_barplot(data, pdf, xlabel, ylabel, title, row_order=None, x=None, y=None, hue=None, hue_order=None,
                    order=None, col=None, col_wrap=None, sharex=True, sharey=True, col_order=None, palette=None,
                    close=True):
    g = sns.catplot(data=data, x=x, y=y, hue=hue, ci=None, kind='bar', hue_order=hue_order, row_order=row_order,
                       col=col, col_wrap=col_wrap, sharex=sharex, sharey=sharey, col_order=col_order, palette=palette,
                       order=order)
    g.set_xticklabels(rotation=90)
    g.fig.suptitle(title)
    g.fig.subplots_adjust(top=.8)
    g.set_axis_labels(xlabel, ylabel)
    try:  # depending on columns, axes could be flat or not
        axes = list(itertools.chain.from_iterable(g.axes))
    except TypeError:
        axes = g.axes
    for ax in axes:
        ax.yaxis.set_major_locator(matplotlib.ticker.MaxNLocator(nbins=10, steps=[1, 2, 5, 10], integer=True))
        ax.margins(y=0.15)
        ax.autoscale(enable=True, axis='y', tight=False)
        ax.set_ylim(0, ax.get_ylim()[1])
    if close == True:
        multipage_close(pdf, tight_layout=False)
    return g
//  [python]
def boxplot_thetas_bias(
    df: pd.DataFrame, n_thetas: int, h_sz: float = 2.5, suptitle: str = "", save_as: Union[str, Path] = None,
):
    w_sz = n_thetas * h_sz

    plt.figure(figsize=(w_sz, h_sz))
    plot = sns.factorplot(data=df, col="theta", x="gamma", y="bias", kind="violin", legend_out=True)
    axes = plot.axes.squeeze()
    for ax in axes:
        ax.axhline(y=0.0, color="red", alpha=0.5, linestyle="--")

        # Update title
        t = ax.get_title()
        theta = float(t.split(" = ")[1])
        ax.set_title("$\\theta_0$ = " + f"{theta}")

    # plt.suptitle(suptitle)
    plt.tight_layout()
    if save_as is not None:
        plt.savefig(save_as)
    plt.close()
//  [python]
def boxplot_thetas_bias(
    df: pd.DataFrame, n_thetas: int, h_sz: float = 2.5, suptitle: str = "", save_as: Union[str, Path] = None,
):
    w_sz = n_thetas * h_sz

    plt.figure(figsize=(w_sz, h_sz))
    plot = sns.catplot(data=df, col="theta", x="gamma", y="bias", kind="violin", legend_out=True)
    axes = plot.axes.squeeze()
    for ax in axes:
        ax.axhline(y=0.0, color="red", alpha=0.5, linestyle="--")

        # Update title
        t = ax.get_title()
        theta = float(t.split(" = ")[1])
        ax.set_title("$\\theta_0$ = " + f"{theta}")

    # plt.suptitle(suptitle)
    plt.tight_layout()
    if save_as is not None:
        plt.savefig(save_as)
    plt.close()
//  [python]
def boxplot_cv_gammas(
    df: pd.DataFrame, n_thetas: int, h_sz: float = 2.5, suptitle: str = "", save_as: Union[str, Path] = None,
):

    w_sz = n_thetas * h_sz

    plt.figure(figsize=(w_sz, h_sz))
    plot = sns.factorplot(data=df, col="theta", x="gamma", kind="count", legend_out=True)
    axes = plot.axes.squeeze()
    for ax in axes:
        # Update title
        t = ax.get_title()
        theta = float(t.split(" = ")[1])
        ax.set_title("$\\theta_0$ = " + f"{theta}")

    # plt.suptitle(suptitle)
    plt.tight_layout()
    if save_as is not None:
        plt.savefig(save_as)
    plt.close()
//  [python]
def boxplot_cv_gammas(
    df: pd.DataFrame, n_thetas: int, h_sz: float = 2.5, suptitle: str = "", save_as: Union[str, Path] = None,
):

    w_sz = n_thetas * h_sz

    plt.figure(figsize=(w_sz, h_sz))
    plot = sns.catplot(data=df, col="theta", x="gamma", kind="count", legend_out=True)
    axes = plot.axes.squeeze()
    for ax in axes:
        # Update title
        t = ax.get_title()
        theta = float(t.split(" = ")[1])
        ax.set_title("$\\theta_0$ = " + f"{theta}")

    # plt.suptitle(suptitle)
    plt.tight_layout()
    if save_as is not None:
        plt.savefig(save_as)
    plt.close()
//  [python]
def plot_model_complexity(df, title, error, HUE_COLORS, HUE_ORDER, ORDER):
    df2 = df[df.loss_type == error]
    df2 = df2[df2.samples_type != "job"]
    fg = sns.factorplot(data=df2, x="samples_type", y="loss",
	row="buckets", col="hidden_layer_size",
	hue="alg_name", kind="bar", ci=None, palette=HUE_COLORS,
        hue_order=HUE_ORDER, order=ORDER)

    sup_title = ERROR_NAMES[error]
    fg.fig.suptitle(sup_title, fontsize=75)
    # fg.despine(left=True)
    plt.tight_layout(rect=[0, 0, 1, 0.90])
    plt.show()
    plt.clf()
//  [python]
def plot_model_complexity(df, title, error, HUE_COLORS, HUE_ORDER, ORDER):
    df2 = df[df.loss_type == error]
    df2 = df2[df2.samples_type != "job"]
    fg = sns.catplot(data=df2, x="samples_type", y="loss",
	row="buckets", col="hidden_layer_size",
	hue="alg_name", kind="bar", ci=None, palette=HUE_COLORS,
        hue_order=HUE_ORDER, order=ORDER)

    sup_title = ERROR_NAMES[error]
    fg.fig.suptitle(sup_title, fontsize=75)
    # fg.despine(left=True)
    plt.tight_layout(rect=[0, 0, 1, 0.90])
    plt.show()
    plt.clf()
//  [python]
def boxplot_final_biases(
    df: pd.DataFrame, n_thetas: int, h_sz: float = 2.5, suptitle: str = "", save_as: Union[str, Path] = None,
):
    df = df.sort_values(by=["theta"])
    df_summary = df.groupby(["theta", "method"]).mean().reset_index()

    w_sz = n_thetas * h_sz

    plt.figure(figsize=(w_sz, h_sz))
    plot = sns.FacetGrid(data=df, col="theta", sharey=False, col_wrap=5)
    plot.map(sns.violinplot, "method", "bias")
    axes = plot.axes.flatten()
    for ax in axes:
        # Add horizontal line
        ax.axhline(y=0.0, color="red", alpha=0.5, linestyle="--")

        # Update title with mean values
        t = ax.get_title()
        theta = float(t.split(" = ")[1])
        theta_summary = df_summary[df_summary["theta"] == theta]
        dml_mean_bias = theta_summary[theta_summary["method"] == "DML"]["bias"].item()
        cv_mean_bias = theta_summary[theta_summary["method"] == "SYNC-ML"]["bias"].item()
        summary_str = "mean bias: DML = {:.4f} | SYNC-ML = {:.4f}".format(dml_mean_bias, cv_mean_bias)
        ax.set_title("$\\theta_0$ = " + f"{theta} \n" + summary_str)
        ax.set(xlabel=None)

    # plt.suptitle(suptitle)
    plt.tight_layout()
    if save_as is not None:
        plt.savefig(save_as)
    plt.close()
//  [python]
def boxplot_final_biases(
    df: pd.DataFrame, n_thetas: int, h_sz: float = 2.5, suptitle: str = "", save_as: Union[str, Path] = None,
):
    df = df.sort_values(by=["theta"])
    df_summary = df.groupby(["theta", "method"]).mean().reset_index()

    w_sz = n_thetas * h_sz

    plt.figure(figsize=(w_sz, h_sz))
    plot = sns.catplot(data=df, col="theta", x="method", y="bias", kind="violin", legend_out=True)
    axes = plot.axes.squeeze()
    for ax in axes:
        # Add horizontal line
        ax.axhline(y=0.0, color="red", alpha=0.5, linestyle="--")

        # Update title with mean values
        t = ax.get_title()
        theta = float(t.split(" = ")[1])
        theta_summary = df_summary[df_summary["theta"] == theta]
        dml_mean_bias = theta_summary[theta_summary["method"] == "DML"]["bias"].item()
        cv_mean_bias = theta_summary[theta_summary["method"] == "SYNC-ML"]["bias"].item()
        summary_str = "mean bias: DML = {:.4f} | SYNC-ML = {:.4f}".format(dml_mean_bias, cv_mean_bias)
        ax.set_title("$\\theta_0$ = " + f"{theta} \n" + summary_str)
        ax.set(xlabel=None)

    # plt.suptitle(suptitle)
    plt.tight_layout()
    if save_as is not None:
        plt.savefig(save_as)
    plt.close()
//  [python]
def execution_time_comparison(self, palette: str = 'Set2'):
        """ Prepare stripplot for execution time """
        timeouts_df = self.metrics_processor.time_execution_table()
        horizons = list(timeouts_df['Horizon'].unique())
        horizons.sort()

        with sns.axes_style('darkgrid'):
            for y_values in ['Fit, seconds', 'Predict, seconds']:
                g = sns.FacetGrid(timeouts_df, col='Horizon', col_order=horizons, palette=palette)
                g.map(sns.stripplot, 'Dataset', y_values, 'Library', dodge=True)
                if self.folder_for_plots is not None:
                    # Save plot into folder
                    fig_name = os.path.join(self.folder_for_plots, f'{y_values}.png')
                    plt.savefig(fig_name)
                    plt.close()
                else:
                    plt.show()
//  [python]
def execution_time_comparison(self, palette: str = 'Set2'):
        """ Prepare stripplot for execution time """
        timeouts_df = self.metrics_processor.time_execution_table()
        horizons = list(timeouts_df['Horizon'].unique())
        horizons.sort()

        with sns.axes_style('darkgrid'):
            for y_values in ['Fit, seconds', 'Predict, seconds']:
                sns.catplot(x='Dataset', y=y_values, hue='Library',
                            col='Horizon', data=timeouts_df, palette=palette,
                            dodge=True, col_order=horizons)
                if self.folder_for_plots is not None:
                    # Save plot into folder
                    fig_name = os.path.join(self.folder_for_plots, f'{y_values}.png')
                    plt.savefig(fig_name)
                    plt.close()
                else:
                    plt.show()
//  [python]
def metrics_comparison(self, metrics: Union[str, list], palette: str = 'Set3'):
        """ Prepare stripplots for metrics """
        if isinstance(metrics, str):
            metrics = [metrics]

        metric_table = self.metrics_processor.metric_table(metrics=metrics)
        horizons = list(metric_table['Horizon'].unique())
        horizons.sort()
        with sns.axes_style('darkgrid'):
            for y_values in metrics:
                g = sns.FacetGrid(metric_table, col='Horizon', col_order=horizons, hue='Library', palette=palette)
                g.map(sns.stripplot, 'Dataset', y_values, dodge=True)
                g.add_legend()
                if self.folder_for_plots is not None:
                    # Save plot into folder
                    fig_name = os.path.join(self.folder_for_plots, f'{y_values}.png')
                    plt.savefig(fig_name)
                    plt.close()
                else:
                    plt.show()
//  [python]
def metrics_comparison(self, metrics: Union[str, list], palette: str = 'Set3'):
        """ Prepare stripplots for metrics """
        if isinstance(metrics, str):
            metrics = [metrics]

        metric_table = self.metrics_processor.metric_table(metrics=metrics)
        horizons = list(metric_table['Horizon'].unique())
        horizons.sort()
        with sns.axes_style('darkgrid'):
            for y_values in metrics:
                sns.catplot(x='Dataset', y=y_values, hue='Library',
                            col='Horizon', data=metric_table, palette=palette,
                            dodge=True, col_order=horizons)
                if self.folder_for_plots is not None:
                    # Save plot into folder
                    fig_name = os.path.join(self.folder_for_plots, f'{y_values}.png')
                    plt.savefig(fig_name)
                    plt.close()
                else:
                    plt.show()
//  [python]
def catplot(self, x, y, kind, hue=None, gene:bool=False, layer=None, **dt_args):
        ad = self.ad

        
        if not gene:
            if hue is None:
                hue = x
                df = ad.obs[[x, y]].copy()
            else:
                df = ad.obs[[x, y, hue]].copy()
        else:
            if hue is None:
                hue = x
                df = ad.obs[[x]].copy()
            else:
                df = ad.obs[[x, hue]].copy()
            df[y] = ad[:, y].to_df(layer)[y]

        dt_colors = self.getAdColors(hue)
        p = sns.catplot(
            data=df,
            x=x,
            y=y,
            kind=kind,
            hue=hue,
            palette=dt_colors,
            **dt_args
        )
        return p
//  [python]
def catplot(self, x, y, kind, hue=None, gene:bool=False, layer=None, **dt_args):
        ad = self.ad

        
        if not gene:
            if hue is None:
                hue = x
                df = ad.obs[[x, y]].copy()
            else:
                df = ad.obs[[x, y, hue]].copy()
        else:
            if hue is None:
                hue = x
                df = ad.obs[[x]].copy()
            else:
                df = ad.obs[[x, hue]].copy()
            df[y] = ad[:, y].to_df(layer)[y]

        dt_colors = self.getAdColors(hue)
        p = sns.catplot(
            df,
            x=x,
            y=y,
            kind=kind,
            hue=hue,
            palette=dt_colors,
            **dt_args
        )
        return p
//  [python]
def plotFetchedValues(avalancheDir, dataDF, xName, yName, plotName, scenario=None):
    """plot values of dataDF

    Parameters
    -----------
    dataDF: pandas dataFrame
        dataframe with simulation info and pointValues
    xName: str
        name of column used for x axis
    yName: str
        name of column used for y axis
    plotName: str
        name of plot
    scenario: str
        name of column used for coloring
    """

    if dataDF[xName].dtype.name == "object" or dataDF[yName].dtype.name == "object":
        g = sns.factorplot(data=dataDF, x=xName, y=yName, hue=scenario)
    else:
        g = sns.jointplot(data=dataDF, x=xName, y=yName, hue=scenario)
    outDir = pathlib.Path(avalancheDir, "Outputs", "out1Peak")

    pU.saveAndOrPlot({"pathResult": outDir}, plotName, g.fig)
//  [python]
def plotFetchedValues(avalancheDir, dataDF, xName, yName, plotName, scenario=None):
    """plot values of dataDF

    Parameters
    -----------
    dataDF: pandas dataFrame
        dataframe with simulation info and pointValues
    xName: str
        name of column used for x axis
    yName: str
        name of column used for y axis
    plotName: str
        name of plot
    scenario: str
        name of column used for coloring
    """

    if dataDF[xName].dtype.name == "object" or dataDF[yName].dtype.name == "object":
        g = sns.catplot(data=dataDF, x=xName, y=yName, hue=scenario)
    else:
        g = sns.jointplot(data=dataDF, x=xName, y=yName, hue=scenario)
    outDir = pathlib.Path(avalancheDir, "Outputs", "out1Peak")

    pU.saveAndOrPlot({"pathResult": outDir}, plotName, g.fig)
//  [python]
def draw_stateful(df2, resource):
    df = df2[df2["Resource"] == resource]

    avgs = df.groupby(['Limit']).mean().reset_index()
    print (avgs)
    avgs["Benchmark"] = "Mean"
    df = pd.concat([df,avgs], axis=0, ignore_index=True, sort=False)

    # fig, ax = plt.subplots(figsize=(15,3))
    set_style()
    ax = sns.barplot(x="Benchmark", y="Execution Time Improvement", hue="Limit", data=df, 
                    palette=("Purples"))
    ax.set_xticklabels(rotation=90)
    ax.figure.tight_layout()

    plt.legend(loc=("upper center"),
            bbox_to_anchor=(.50, 1.40),
            ncol=5,
            prop={'size': 15},
            title="Adaptation Limit",
    )
    ax.set_ylim(df["Execution Time Improvement"].min()-0.02, df["Execution Time Improvement"].max()+0.02)
    ax.set_ylabel('Speedup \nover Shared', fontsize = 20)
    ax.set_xlabel("")
    for i, bar in enumerate(ax.patches):
        bar.set_edgecolor('black')

    plt.savefig("fig-adaptive-{}.pdf".format(resource), bbox_inches='tight')
//  [python]
def draw_stateful(df2, resource):
    df = df2[df2["Resource"] == resource]

    avgs = df.groupby(['Limit']).mean().reset_index()
    print (avgs)
    avgs["Benchmark"] = "Mean"
    df = pd.concat([df,avgs], axis=0, ignore_index=True, sort=False)

    # fig, ax = plt.subplots(figsize=(15,3))
    set_style()
    ax = sns.catplot(x="Benchmark", y="Execution Time Improvement", hue="Limit", data=df, kind="bar", 
                    palette=("Purples"), height=6, aspect=1.2, legend=False)
    ax.set_xticklabels(rotation=90)
    ax.fig.tight_layout()

    plt.legend(loc=("upper center"),
            bbox_to_anchor=(.50, 1.40),
            ncol=5,
            prop={'size': 15},
            title="Adaptation Limit",
    )
    ax.axes.flatten()[0].set_ylim(df["Execution Time Improvement"].min()-0.02, df["Execution Time Improvement"].max()+0.02)
    ax.axes.flatten()[0].set_ylabel('Speedup \nover Shared', fontsize = 20)
    axes = ax.axes.flatten()
    for ax in axes:
        ax.set_xlabel("")
        for i, bar in enumerate(ax.patches):
            bar.set_edgecolor('black')

    plt.savefig("fig-adaptive-{}.pdf".format(resource), bbox_inches='tight')
//  [python]
def plot_pipelines_compression_factor(
        self, data, pipelines_settings, input_stage, output_stage, compression_features, baseline, title=None,
    ):
        sns.set(style="darkgrid", font_scale=1.5)

        # Filter pipelines and prepare 'Pipeline' column
        data = data[data["Pipeline ID"].isin(pipelines_settings.keys())]
        data["Pipeline"] = data["Pipeline ID"].map({s: d["name"] for s, d in pipelines_settings.items()})

        # Filter stages
        input_df = data[data["Stage ID"] == input_stage].reset_index()
        output_df = data[data["Stage ID"] == output_stage].reset_index()

        for cc in compression_features.keys():
            output_df[cc] = input_df[cc].divide(output_df[cc])

        melted_df = pd.melt(
            output_df,
            id_vars=["Pipeline"],
            value_vars=compression_features,
            var_name="Metrics",
            value_name="Compression",
        )

        pallete = {k: v["color"] for k, v in compression_features.items()}

        if len(data) == 0:
            raise Exception("No data in CSV")

        g = sns.factorplot(
            x="Pipeline",
            y="Compression",
            hue="Metrics",
            data=melted_df,
            size=8,
            kind="bar",
            alpha=0.5,
            palette=pallete,
            legend_out=True,
        )

        if title is not None:
            plt.suptitle(title, fontweight="bold")
            plt.subplots_adjust(top=0.9)

        if baseline:
            plt.hlines(baseline["value"], *g.ax.get_xlim(), **baseline["style"], label=baseline["name"])

        g.despine(left=True, bottom=False)
        g.set_ylabels("Compression Factor")
//  [python]
def plot_pipelines_compression_factor(
        self, data, pipelines_settings, input_stage, output_stage, compression_features, baseline, title=None,
    ):
        sns.set(style="darkgrid", font_scale=1.5)

        # Filter pipelines and prepare 'Pipeline' column
        data = data[data["Pipeline ID"].isin(pipelines_settings.keys())]
        data["Pipeline"] = data["Pipeline ID"].map({s: d["name"] for s, d in pipelines_settings.items()})

        # Filter stages
        input_df = data[data["Stage ID"] == input_stage].reset_index()
        output_df = data[data["Stage ID"] == output_stage].reset_index()

        for cc in compression_features.keys():
            output_df[cc] = input_df[cc].divide(output_df[cc])

        melted_df = pd.melt(
            output_df,
            id_vars=["Pipeline"],
            value_vars=compression_features,
            var_name="Metrics",
            value_name="Compression",
        )

        pallete = {k: v["color"] for k, v in compression_features.items()}

        if len(data) == 0:
            raise Exception("No data in CSV")

        g = sns.catplot(
            x="Pipeline",
            y="Compression",
            hue="Metrics",
            data=melted_df,
            height=8,
            kind="bar",
            alpha=0.5,
            palette=pallete,
            legend_out=True,
        )

        if title is not None:
            plt.suptitle(title, fontweight="bold")
            plt.subplots_adjust(top=0.9)

        if baseline:
            plt.hlines(baseline["value"], *g.ax.get_xlim(), **baseline["style"], label=baseline["name"])

        g.despine(left=True, bottom=False)
        g.set_ylabels("Compression Factor")
//  [python]
def draw_cat_plot():
    # Create DataFrame for cat plot using `pd.melt` using just the values from 'cholesterol', 'gluc', 'smoke', 'alco', 'active', and 'overweight'.
    df_cat = pd.melt(frame=df,id_vars=['cardio'],value_vars=['cholesterol', 'gluc', 'smoke', 'alco', 'active', 'overweight'])


    # Group and reformat the data to split it by 'cardio'. Show the counts of each feature. You will have to rename one of the columns for the catplot to work correctly.
    df_cat = pd.DataFrame(df_cat.groupby(['variable', 'value', 'cardio'])['value'].count()).rename(columns={'value': 'total'}).reset_index()

    # Draw the catplot with 'sns.catplot()'
    fig=sns.factorplot(x='variable', y='total',data=df_cat, hue='value', kind='bar', col= 'cardio').fig


    # Do not modify the next two lines
    fig.savefig('catplot.png')
    return fig
//  [python]
def draw_cat_plot():
    # Create DataFrame for cat plot using `pd.melt` using just the values from 'cholesterol', 'gluc', 'smoke', 'alco', 'active', and 'overweight'.
    df_cat = pd.melt(frame=df,id_vars=['cardio'],value_vars=['cholesterol', 'gluc', 'smoke', 'alco', 'active', 'overweight'])


    # Group and reformat the data to split it by 'cardio'. Show the counts of each feature. You will have to rename one of the columns for the catplot to work correctly.
    df_cat = pd.DataFrame(df_cat.groupby(['variable', 'value', 'cardio'])['value'].count()).rename(columns={'value': 'total'}).reset_index()

    # Draw the catplot with 'sns.catplot()'
    fig=sns.catplot(x='variable', y='total',data=df_cat, hue='value', kind='bar', col= 'cardio').fig


    # Do not modify the next two lines
    fig.savefig('catplot.png')
    return fig
//  [python]
def cat(g_dt, g_x_ax, g_y_ax, g_hue, g_ci, g_seed, g_kind, g_palette):
    if g_hue == '':
        sns.factorplot(
            data=g_dt,
            x=g_x_ax,
            y=g_y_ax,
            ci=g_ci,
            seed=g_seed,
            kind=g_kind,
            palette=g_palette
        )
    else:
        sns.factorplot(
            data=g_dt,
            x=g_x_ax,
            y=g_y_ax,
            hue=g_hue,
            ci=g_ci,
            seed=g_seed,
            kind=g_kind,
            palette=g_palette
        )
    plt.show()
    plt.close()
//  [python]
def cat(g_dt, g_x_ax, g_y_ax, g_hue, g_ci, g_seed, g_kind, g_palette):
    # https://seaborn.pydata.org/generated/seaborn.catplot.html#seaborn.catplot
    if g_hue == '':
        sns.catplot(
            data=g_dt,
            x=g_x_ax,
            y=g_y_ax,
            ci=g_ci,
            seed=g_seed,
            kind=g_kind,
            palette=g_palette
        )
    else:
        sns.catplot(
            data=g_dt,
            x=g_x_ax,
            y=g_y_ax,
            hue=g_hue,
            ci=g_ci,
            seed=g_seed,
            kind=g_kind,
            palette=g_palette
        )
    plt.show()
    plt.close()
//  [python]
def draw_stateless(df2, resource):
    df = df2[df2["Resource"] == resource]
    avgs = df.groupby(['Limit','Mult']).mean().reset_index()
    print (avgs)
    avgs["Benchmark"] = "Mean"
    df = pd.concat([df,avgs], axis=0, ignore_index=True, sort=False)

    set_style()
    ax = sns.factorplot(x="Benchmark", y="Execution Time Improvement", hue="Limit", col="Mult", data=df, kind="bar", 
                    palette=("Purples"),  size=6, aspect=0.9, legend=False)
    ax.set_xticklabels(rotation=90)
    ax.fig.tight_layout()
    plt.legend(loc=("upper center"),
            bbox_to_anchor=(-.5, 1.49),
            ncol=5,
            prop={'size': 20},
            title="Adaptation Limit",
    
    )
    ax.axes.flatten()[0].set_ylim(df["Execution Time Improvement"].min()-0.02, df["Execution Time Improvement"].max()+0.02)
    ax.axes.flatten()[0].set_ylabel('Speedup \nover Shared', fontsize = 20)

    axes = ax.axes.flatten()
    for ax in axes:
        ax.set_xlabel("")
        for i, bar in enumerate(ax.patches):
            bar.set_edgecolor('black')

    plt.savefig("fig-adaptive-{}.pdf".format(resource), bbox_inches='tight')