## visualize benchmarks

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
sns.set_style("whitegrid")

palette = "Set3"


def plot_core_macro(fname):
    """
    A very simple visualization of the results..
    """
    p1 = sns.pointplot('percent_train',
                       'macro_F',
                       hue='setting',
                       data=fname,
                       markers=["p"] * 10,
                       ci="sd",
                       linestyles=['-', '--', '-.', ':'] * 5)
    plt.show()

    return 1


def plot_core_micro(fname):
    """
    A very simple visualization of the results..
    """
    p1 = sns.lineplot('percent_train', 'micro_F', hue='setting', data=fname)
    plt.show()

    return 1


palette = "Set3"
cnames = ["percent_train", "micro_F", "macro_F", "setting", "dataset", "time"]


def plot_core_macro_box(fname):

    fnamex = pd.read_csv(fname, sep=" ")
    print(fnamex)
    fnamex.columns = cnames
    print(fnamex.head())

    p1 = sns.boxplot('percent_train', 'macro_F', hue='setting', data=fnamex)
    plt.show()
    return 1


def plot_core_micro_grid(fname):

    fnamex = pd.read_csv(fname, sep=" ")
    fnamex.columns = cnames
    grid = sns.FacetGrid(fnamex, col="dataset", hue="setting", col_wrap=2)
    grid.map(plt.plot, "percent_train", "micro_F", marker="o").add_legend()
    plt.show()


def plot_core_macro_gg(fnamex):
    print(fnamex.columns)
    fx = fnamex.groupby(["setting"
                         ])['macro_F'].mean().sort_values().index.values
    g = sns.FacetGrid(fnamex, col="dataset", hue="setting", col_wrap=3)
    g = (g.map(plt.plot, "percent_train", "macro_F", marker="o",
               linewidth=1).add_legend())
    g.set_xlabels("Train percentage (%)")
    g.set_ylabels("Average Macro F1")
    plt.show()

    ax = sns.boxplot(x="setting",
                     y="macro_F",
                     data=fnamex,
                     color="white",
                     order=fx)
    plt.xticks(rotation=45)
    plt.xlabel("Algorithm")
    plt.ylabel("Average Macro F1")
    plt.show()


def plot_core_micro_gg(fnamex):

    fx = fnamex.groupby(["setting"
                         ])['micro_F'].mean().sort_values().index.values
    print(fnamex.columns)
    g = sns.FacetGrid(fnamex, col="dataset", hue="setting", col_wrap=3)
    g = (g.map(plt.plot, "percent_train", "micro_F", marker="o",
               linewidth=1).add_legend())
    g.set_xlabels("Train percentage (%)")
    g.set_ylabels("Average Micro F1")
    plt.show()

    ax = sns.boxplot(x="setting",
                     y="micro_F",
                     data=fnamex,
                     color="white",
                     order=fx)
    plt.xticks(rotation=45)
    plt.xlabel("Algorithm")
    plt.ylabel("Average Micro F1")
    plt.show()


def plot_core_time_gg(fname):

    fnamex = pd.read_csv(fname, sep=" ")
    fnamex.columns = cnames

    # gx = (ggplot(fnamex, aes('setting', 'time'))
    #       + geom_boxplot()
    #       + theme(axis_text_x=element_text(rotation=90, hjust=1))
    #       + theme_bw()
    #       + facet_wrap('~dataset')
    #       )
    # gx.draw()
    # plt.show()


def plot_core_variability(fname):

    fname = pd.read_csv(fname, separator=" ")
    ## for each dataset, take all variability and get it to a box plot


def plot_core_time(fnamex):

    fnamex.columns = cnames
    print(fnamex.head())
    px = sns.boxplot("setting", "time", data=fnamex)
    plt.show()
    return 1


def plot_critical_distance(fname, num_algo=14):

    import Orange
    import matplotlib.pyplot as plt
    from collections import defaultdict
    import operator

    #    print(fname.head())

    names = fname.setting.unique()
    rkx = fname.groupby(['dataset', 'setting'])['macro_F'].mean()
    ranks = defaultdict(list)
    clf_ranks = defaultdict(list)
    for df, clf in rkx.index:
        ranks[df].append((clf, rkx[(df, clf)]))

    for k, v in ranks.items():
        a = dict(v)
        sorted_d = sorted(a.items(), key=operator.itemgetter(1))
        for en, j in enumerate(sorted_d):
            print(en, j[0])
            clf_ranks[j[0]].append(len(sorted_d) - en)

    print(clf_ranks)
    clf_score = {k: np.mean(v) for k, v in clf_ranks.items()}
    names = list(clf_score.keys())
    avranks = list(clf_score.values())
    cd = Orange.evaluation.compute_CD(avranks, num_algo, alpha="0.05")
    Orange.evaluation.graph_ranks(avranks,
                                  names,
                                  cd=cd,
                                  width=6,
                                  textspace=1.5,
                                  reverse=True)
    plt.show()

    rkx = fname.groupby(['dataset', 'setting'])['micro_F'].mean()
    ranks = defaultdict(list)
    clf_ranks = defaultdict(list)
    for df, clf in rkx.index:
        ranks[df].append((clf, rkx[(df, clf)]))

    for k, v in ranks.items():
        a = dict(v)
        sorted_d = sorted(a.items(), key=operator.itemgetter(1))
        for en, j in enumerate(sorted_d):
            print(en, j[0])
            clf_ranks[j[0]].append(len(sorted_d) - en)

    print(clf_ranks)
    clf_score = {k: np.mean(v) for k, v in clf_ranks.items()}
    names = list(clf_score.keys())
    avranks = list(clf_score.values())
    cd = Orange.evaluation.compute_CD(avranks, num_algo, alpha="0.05")
    Orange.evaluation.graph_ranks(avranks,
                                  names,
                                  cd=cd,
                                  width=6,
                                  textspace=1.5,
                                  reverse=True)
    plt.show()

    fname['time'] = 1 / fname['time']
    rkx = fname.groupby(['dataset', 'setting'])['time'].mean()
    ranks = defaultdict(list)
    clf_ranks = defaultdict(list)
    for df, clf in rkx.index:
        ranks[df].append((clf, rkx[(df, clf)]))

    for k, v in ranks.items():
        a = dict(v)
        sorted_d = sorted(a.items(), key=operator.itemgetter(1))
        for en, j in enumerate(sorted_d):
            print(en, j[0])
            clf_ranks[j[0]].append(len(sorted_d) - en)

    print(clf_ranks)
    clf_score = {k: np.mean(v) for k, v in clf_ranks.items()}
    names = list(clf_score.keys())
    avranks = list(clf_score.values())
    cd = Orange.evaluation.compute_CD(avranks, 54, alpha="0.05")
    Orange.evaluation.graph_ranks(avranks,
                                  names,
                                  cd=cd,
                                  width=6,
                                  textspace=1.5,
                                  reverse=True)
    plt.show()


def plot_mean_times(fn):

    ## for each dataset, plot times.
    fx = fnamex.groupby(["setting"])['time'].mean().sort_values().index.values
    rkx = fn.groupby(['dataset', 'setting'])['time'].mean()
    dx2 = rkx.reset_index()

    ax = sns.boxplot(x="setting",
                     y="time",
                     data=fnamex,
                     color="white",
                     order=fx)
    plt.xticks(rotation=45)
    ax.set_xlabel("Algorithm", fontsize=20)
    ax.set_ylabel("Average execution time (s)", fontsize=20)
    ax.set_yscale('log')
    ax.tick_params(labelsize=15)
    plt.show()


def plot_robustness(infile):

    print(infile.head())
    #    infile['percent_train'] = pd.to_numeric(infile['percent_train'])
    infile = infile[infile['percent_train'] < 0.6]
    p1 = sns.boxplot('percent_train', 'macro_F', data=infile)
    p1.set_xlabel("Train percent", fontsize=20)
    p1.set_ylabel("Macro F score", fontsize=20)
    plt.show()

    p1 = sns.boxplot('percent_train', 'micro_F', data=infile)
    p1.set_xlabel("Train percent", fontsize=20)
    p1.set_ylabel("Micro F score", fontsize=20)
    plt.show()

    # gx = (ggplot(infile, aes('macro_F','micro_F'))
    #       + geom_density_2d(aes(color='percent_train'))
    #       +xlab("Macro F score")
    #       +ylab("Micro F score")
    #       + theme(axis_text=element_text(size=15))
    #       + theme(axis_title=element_text(size=15))
    #       + theme_bw()
    # )
    # gx.draw()
    # plt.show()


def generic_grouping(fname, score_name, threshold=1, percentages=True):
    fname = fname[fname['percent_train'] < threshold]
    sub1 = fname[['percent_train', score_name, 'setting', 'dataset']]
    if percentages:
        sub1['dataset'] = sub1['dataset'] + "_" + sub1['percent_train'].astype(
            str)
    grouped = sub1.groupby(['dataset', 'setting']).agg(['mean', 'std'])
    grouped.score_name = np.round(grouped[score_name], 3)
    stdacc = np.round(grouped[score_name, 'std'], 2)
    meanacc = np.round(grouped[score_name, 'mean'], 2)
    acc_agg = meanacc.map(str) + " (" + stdacc.map(str) + ")"

    grouped = grouped.drop([('percent_train', 'mean')],
                           axis=1).drop([('percent_train', 'std')],
                                        axis=1).drop([(score_name, 'std')],
                                                     axis=1)
    grouped[(score_name, 'mean')] = acc_agg
    grouped = grouped.reset_index()
    grouped.columns = ['dataset', 'setting', 'score']

    if percentages:
        df0 = grouped.pivot(index='dataset', columns='setting', values='score')
    else:
        df0 = grouped.pivot(index='dataset', columns='setting',
                            values='score').T
    return df0


def table_to_latex(fname, outfolder="../final_results/tables/", threshold=1):

    df0 = generic_grouping(fname, 'micro_F', threshold)
    df0.to_latex(outfolder + "micro_F.tex", index=True)

    df1 = generic_grouping(fname, 'macro_F', threshold)
    df1.to_latex(outfolder + "macro_F.tex", index=True)

    df2 = generic_grouping(fname, 'time', threshold)
    df2.to_latex(outfolder + "time.tex", index=True)
