//  [python]
def gen_plots(data, bn_data, options):

    # linear plots
    lin_dir = os.path.join(options['out_dir'], 'linear-eval')
    os.makedirs(lin_dir, exist_ok=True)
    linear_data = data[data.result_type=='linear-eval']
    for pretrain_data in linear_data.pretrain_data.unique():
        for variant in ["linear-eval-lr"]: # linear_data['variant'].unique():
            variant_data=linear_data[(linear_data.variant == variant) & 
                (linear_data.pretrain_data == pretrain_data) & 
                (linear_data.pretrain_iters > 0) &
                (linear_data.basetrain != "supervised imagenet init")
                ]

            moco_zero_val = linear_data[(linear_data.pretrain_iters ==0) & (linear_data.basetrain == "moco imagenet init")].result.mean()
            top_bn_val = bn_data.result.max()
            if top_bn_val < 1:
                top_bn_val *= 100

            # hack to "clean up" other analyses 
            variant_data = variant_data[(linear_data.basetrain == 'random init') | (linear_data.basetrain == 'moco imagenet init') | (linear_data.basetrain ==  'supervised imagenet init') ]
            fig, ax = setup_plot(500)

            # variant_data.groupby("basetrain").plot(x="pretrain_iters", y="result", marker="o", ax=ax)
            sns.pointplot(x='pretrain_iters', y='result', hue='basetrain', data=variant_data, marker='o', mew=0, ms=5)
            ax.axhline(moco_zero_val, ls='--', label="moco transfer")

            # TODO(cjrd) hardcoding
            ax.plot(5000, top_bn_val, "xr", label="HPT-BN")

            labels = ["HPT", "MoCo Random Init", "MoCo Direct Transfer", "HPT-BN"]
            handles, _ = ax.get_legend_handles_labels()

            # Slice list to remove first handle
            plt.legend(handles = handles, labels = labels)
            
            plt.xlabel("Pretrain Steps")
            plt.ylabel("Accuracy")
            plt.title(options['data_name'].replace("_", " ").title())

            plt.xscale('log')
            plt.xticks(ticks=variant_data['pretrain_iters'], labels=variant_data['pretrain_iters'], rotation='vertical')

            # logit_y_axis()
            outplot = os.path.join(lin_dir, '{}_pretrain-{}_linear_eval-{}_variant.pdf'.format(pretrain_data, options['data_name'], variant))
            print(outplot)
            fig.savefig(outplot, format='pdf', bbox_inches='tight')


    # finetune plots
    finetune_dir = os.path.join(options['out_dir'], 'finetune-eval')
    os.makedirs(finetune_dir, exist_ok=True)
    finetune_data = data[data.result_type=='finetune']

    for subset in finetune_data.subset.unique():
        for pretrain_data in linear_data.pretrain_data.unique():
            subset_data = finetune_data[(finetune_data.subset == subset) & (finetune_data.pretrain_data == pretrain_data)]
            # take max val across each sample, iter, and basetrain
            # (isn't pandas cool?)
            subset_data = subset_data.groupby(['sample', 'pretrain_iters', 'basetrain']).apply(lambda x: x.loc[x.result.idxmax()])
            if subset_data.empty:
                continue
            
            fig, ax = setup_plot(500)

            sns.pointplot(x='pretrain_iters', y='result', hue='basetrain', data=subset_data, marker='o', mew=0, ms=5)

            plt.xlabel("Pretrain Steps")
            plt.ylabel("Accuracy")
            plt.xscale('symlog')
            plt.xticks(ticks=subset_data['pretrain_iters'], labels=subset_data['pretrain_iters'], rotation='vertical')
            logit_y_axis()
            
            plt.title(options['data_name'].replace("_", " ").title())

            outplot = os.path.join(finetune_dir, '{}_pretrain-{}_fintune-{}_subset.pdf'.format(pretrain_data, options['data_name'], subset))
            print(outplot)
            fig.savefig(outplot, format='pdf', bbox_inches='tight')