%matplotlib widget

import pandas as pd
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
import os

import ipywidgets as widgets
from traitlets import Unicode, List, Instance, link, HasTraits
from IPython.display import display, clear_output, HTML, Javascript

display(widgets.Button())

"""
Explanation: Got Scotch?
In this notebook, we're going to create a dashboard that recommends scotches based on their taste profiles.
End of explanation
"""




features = [[2, 2, 2, 0, 0, 2, 1, 2, 2, 2, 2, 2],
 [3, 3, 1, 0, 0, 4, 3, 2, 2, 3, 3, 2],
 [1, 3, 2, 0, 0, 2, 0, 0, 2, 2, 3, 1],
 [4, 1, 4, 4, 0, 0, 2, 0, 1, 2, 1, 0],
 [2, 2, 2, 0, 0, 1, 1, 1, 2, 3, 1, 3],
 [2, 3, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1],
 [0, 2, 0, 0, 0, 1, 1, 0, 2, 2, 3, 1],
 [2, 3, 1, 0, 0, 2, 1, 2, 2, 2, 2, 2],
 [2, 2, 1, 0, 0, 1, 0, 0, 2, 2, 2, 1],
 [2, 3, 2, 1, 0, 0, 2, 0, 2, 1, 2, 3],
 [4, 3, 2, 0, 0, 2, 1, 3, 3, 0, 1, 2],
 [3, 2, 1, 0, 0, 3, 2, 1, 0, 2, 2, 2],
 [4, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2],
 [2, 2, 1, 0, 0, 2, 2, 0, 0, 2, 3, 1],
 [3, 2, 2, 0, 0, 3, 1, 1, 2, 3, 2, 2],
 [2, 2, 2, 0, 0, 2, 2, 1, 2, 2, 2, 2],
 [1, 2, 1, 0, 0, 0, 1, 1, 0, 2, 2, 1],
 [2, 2, 2, 0, 0, 1, 2, 2, 2, 2, 2, 2],
 [2, 2, 3, 1, 0, 2, 2, 1, 1, 1, 1, 3],
 [1, 1, 2, 2, 0, 2, 2, 1, 2, 2, 2, 3],
 [1, 2, 1, 1, 0, 1, 1, 1, 1, 2, 2, 1],
 [3, 1, 4, 2, 1, 0, 2, 0, 2, 1, 1, 0],
 [1, 3, 1, 0, 0, 1, 1, 0, 2, 2, 2, 1],
 [3, 2, 3, 3, 1, 0, 2, 0, 1, 1, 2, 0],
 [2, 2, 2, 0, 1, 2, 2, 1, 2, 2, 1, 2],
 [2, 3, 2, 1, 0, 0, 1, 0, 2, 2, 2, 1],
 [4, 2, 2, 0, 0, 1, 2, 2, 2, 2, 2, 2],
 [3, 2, 2, 1, 0, 1, 2, 2, 1, 2, 3, 2],
 [2, 2, 2, 0, 0, 2, 1, 0, 1, 2, 2, 1],
 [2, 2, 1, 0, 0, 2, 1, 1, 1, 3, 2, 2],
 [2, 3, 1, 1, 0, 0, 0, 0, 1, 2, 2, 1],
 [2, 3, 1, 0, 0, 2, 1, 1, 4, 2, 2, 2],
 [2, 3, 1, 1, 1, 1, 1, 2, 0, 2, 0, 3],
 [2, 3, 1, 0, 0, 2, 1, 1, 1, 1, 2, 1],
 [2, 1, 3, 0, 0, 0, 3, 1, 0, 2, 2, 3],
 [1, 2, 0, 0, 0, 1, 0, 1, 2, 1, 2, 1],
 [2, 3, 1, 0, 0, 1, 2, 1, 2, 1, 2, 2],
 [1, 2, 1, 0, 0, 1, 2, 1, 2, 2, 2, 1],
 [3, 2, 1, 0, 0, 1, 2, 1, 1, 2, 2, 2],
 [2, 2, 2, 2, 0, 1, 0, 1, 2, 2, 1, 3],
 [1, 3, 1, 0, 0, 0, 1, 1, 1, 2, 0, 1],
 [1, 3, 1, 0, 0, 1, 1, 0, 1, 2, 2, 1],
 [4, 2, 2, 0, 0, 2, 1, 4, 2, 2, 2, 2],
 [3, 2, 1, 0, 0, 2, 1, 2, 1, 2, 3, 2],
 [2, 4, 1, 0, 0, 1, 2, 3, 2, 3, 2, 2],
 [1, 3, 1, 0, 0, 0, 0, 0, 0, 2, 2, 1],
 [1, 2, 0, 0, 0, 1, 1, 1, 2, 2, 3, 1],
 [1, 2, 1, 0, 0, 1, 2, 0, 0, 2, 2, 1],
 [2, 3, 1, 0, 0, 2, 2, 2, 1, 2, 2, 2],
 [1, 2, 1, 0, 0, 1, 2, 0, 1, 2, 2, 1],
 [2, 2, 1, 1, 0, 1, 2, 0, 2, 1, 2, 1],
 [2, 3, 1, 0, 0, 1, 1, 2, 1, 2, 2, 2],
 [2, 3, 1, 0, 0, 2, 2, 2, 2, 2, 1, 2],
 [2, 2, 3, 1, 0, 2, 1, 1, 1, 2, 1, 3],
 [1, 3, 1, 1, 0, 2, 2, 0, 1, 2, 1, 1],
 [2, 1, 2, 2, 0, 1, 1, 0, 2, 1, 1, 3],
 [2, 3, 1, 0, 0, 2, 2, 1, 2, 1, 2, 2],
 [4, 1, 4, 4, 1, 0, 1, 2, 1, 1, 1, 0],
 [4, 2, 4, 4, 1, 0, 0, 1, 1, 1, 0, 0],
 [2, 3, 1, 0, 0, 1, 1, 2, 0, 1, 3, 1],
 [1, 1, 1, 1, 0, 1, 1, 0, 1, 2, 1, 1],
 [3, 2, 1, 0, 0, 1, 1, 1, 3, 3, 2, 2],
 [4, 3, 1, 0, 0, 2, 1, 4, 2, 2, 3, 2],
 [2, 1, 1, 0, 0, 1, 1, 1, 2, 1, 2, 1],
 [2, 4, 1, 0, 0, 1, 0, 0, 2, 1, 1, 1],
 [3, 2, 2, 0, 0, 2, 3, 3, 2, 1, 2, 2],
 [2, 2, 2, 2, 0, 0, 2, 0, 2, 2, 2, 3],
 [1, 2, 2, 0, 1, 2, 2, 1, 2, 3, 1, 3],
 [2, 1, 2, 2, 1, 0, 1, 1, 2, 2, 2, 3],
 [2, 3, 2, 1, 1, 1, 2, 1, 0, 2, 3, 1],
 [3, 2, 2, 0, 0, 2, 2, 2, 2, 2, 3, 2],
 [2, 2, 1, 1, 0, 2, 1, 1, 2, 2, 2, 2],
 [2, 4, 1, 0, 0, 2, 1, 0, 0, 2, 1, 1],
 [2, 2, 1, 0, 0, 1, 0, 1, 2, 2, 2, 1],
 [2, 2, 2, 2, 0, 2, 2, 1, 2, 1, 0, 3],
 [2, 2, 1, 0, 0, 2, 2, 2, 3, 3, 3, 2],
 [2, 3, 1, 0, 0, 0, 2, 0, 2, 1, 3, 1],
 [4, 2, 3, 3, 0, 1, 3, 0, 1, 2, 2, 0],
 [1, 2, 1, 0, 0, 2, 0, 1, 1, 2, 2, 1],
 [1, 3, 2, 0, 0, 0, 2, 0, 2, 1, 2, 1],
 [2, 2, 2, 1, 0, 0, 2, 0, 0, 0, 2, 3],
 [1, 1, 1, 0, 0, 1, 0, 0, 1, 2, 2, 1],
 [2, 3, 2, 0, 0, 2, 2, 1, 1, 2, 0, 3],
 [0, 3, 1, 0, 0, 2, 2, 1, 1, 2, 1, 1],
 [2, 2, 1, 0, 0, 1, 0, 1, 2, 1, 0, 3],
 [2, 3, 0, 0, 1, 0, 2, 1, 1, 2, 2, 1]]

feature_names = ['Body', 'Sweetness', 'Smoky', 
                 'Medicinal', 'Tobacco', 'Honey',
                 'Spicy', 'Winey', 'Nutty',
                 'Malty', 'Fruity', 'cluster']

brand_names = ['Aberfeldy',
 'Aberlour',
 'AnCnoc',
 'Ardbeg',
 'Ardmore',
 'ArranIsleOf',
 'Auchentoshan',
 'Auchroisk',
 'Aultmore',
 'Balblair',
 'Balmenach',
 'Belvenie',
 'BenNevis',
 'Benriach',
 'Benrinnes',
 'Benromach',
 'Bladnoch',
 'BlairAthol',
 'Bowmore',
 'Bruichladdich',
 'Bunnahabhain',
 'Caol Ila',
 'Cardhu',
 'Clynelish',
 'Craigallechie',
 'Craigganmore',
 'Dailuaine',
 'Dalmore',
 'Dalwhinnie',
 'Deanston',
 'Dufftown',
 'Edradour',
 'GlenDeveronMacduff',
 'GlenElgin',
 'GlenGarioch',
 'GlenGrant',
 'GlenKeith',
 'GlenMoray',
 'GlenOrd',
 'GlenScotia',
 'GlenSpey',
 'Glenallachie',
 'Glendronach',
 'Glendullan',
 'Glenfarclas',
 'Glenfiddich',
 'Glengoyne',
 'Glenkinchie',
 'Glenlivet',
 'Glenlossie',
 'Glenmorangie',
 'Glenrothes',
 'Glenturret',
 'Highland Park',
 'Inchgower',
 'Isle of Jura',
 'Knochando',
 'Lagavulin',
 'Laphroig',
 'Linkwood',
 'Loch Lomond',
 'Longmorn',
 'Macallan',
 'Mannochmore',
 'Miltonduff',
 'Mortlach',
 'Oban',
 'OldFettercairn',
 'OldPulteney',
 'RoyalBrackla',
 'RoyalLochnagar',
 'Scapa',
 'Speyburn',
 'Speyside',
 'Springbank',
 'Strathisla',
 'Strathmill',
 'Talisker',
 'Tamdhu',
 'Tamnavulin',
 'Teaninich',
 'Tobermory',
 'Tomatin',
 'Tomintoul',
 'Tormore',
 'Tullibardine']

features_df = pd.DataFrame(features, columns=feature_names, index=brand_names)
features_df = features_df.drop('cluster', axis=1)

norm = (features_df ** 2).sum(axis=1).apply('sqrt')
normed_df = features_df.divide(norm, axis=0)
sim_df = normed_df.dot(normed_df.T)

def radar(df, ax=None):
    # calculate evenly-spaced axis angles
    num_vars = len(df.columns)
    theta = 2*np.pi * np.linspace(0, 1-1./num_vars, num_vars)
    # rotate theta such that the first axis is at the top
    theta += np.pi/2
    if not ax:
        fig = plt.figure(figsize=(4, 4))

        ax = fig.add_subplot(1,1,1, projection='polar')
    else:
        ax.clear()
    for d, color in zip(df.itertuples(), sns.color_palette()):
        ax.plot(theta, d[1:], color=color, alpha=0.7)
        ax.fill(theta, d[1:], facecolor=color, alpha=0.5)
    ax.set_xticklabels(df.columns)

    legend = ax.legend(df.index, loc=(0.9, .95))
    return ax

class RadarWidget(HasTraits):

    factors_keys = List(['Aberfeldy'])
    
    def __init__(self, df, **kwargs):
        self.df = df
        super(RadarWidget, self).__init__(**kwargs)
        self.ax = None
        self.factors_keys_changed()
         
    
    def factors_keys_changed(self):
        new_value = self.factors_keys
        if self.ax:
            self.ax.clear()
        self.ax = radar(self.df.loc[new_value], self.ax)

"""
Explanation: Load Data <span style="float: right; font-size: 0.5em"><a href="#Got-Scotch?">Top</a></span>
End of explanation
"""


def get_similar(name, n, top=True):
    a = sim_df[name].sort_values(ascending=False)
    a.name = 'Similarity'
    df = pd.DataFrame(a) #.join(features_df).iloc[start:end]
    return df.head(n) if top else df.tail(n)

"""
Explanation: We now define a get_similar( ) function to return the data of the top n similar scotches to a given scotch.
End of explanation
"""


def on_pick_scotch(Scotch):
    name = Scotch
    # Get top 6 similar whiskeys, and remove this one
    top_df = get_similar(name, 6).iloc[1:]
    # Get bottom 5 similar whiskeys
    df = top_df
    
    # Make table index a set of links that the radar widget will watch
    df.index = ['''<a class="scotch" href="#" data-factors_keys='["{}","{}"]'>{}</a>'''.format(name, i, i) for i in df.index]
    
    tmpl = f'''<p>If you like {name} you might want to try these five brands. Click one to see how its taste profile compares.</p>'''
    prompt_w.value = tmpl
    table.value = df.to_html(escape=False)
    radar_w.factors_keys = [name]
    plot = radar_w.factors_keys_changed()

prompt_w = widgets.HTML(value='Aberfeldy')
display(prompt_w)

table = widgets.HTML(
    value="Hello <b>World</b>"
)
display(table)

radar_w = RadarWidget(df=features_df)

picker_w = widgets.interact(on_pick_scotch, Scotch=list(sim_df.index))

radar_w.factors_keys

"""
Explanation: We also need a function on_pick_scotch that will display a table of the top 5 similar scotches that Radar View watches, based on a given selected Scotch.
End of explanation
"""


