import matplotlib.pyplot as plt

import numpy as np
import pandas as pd

from bokeh.layouts import layout
from bokeh.layouts import widgetbox

from bokeh.embed import file_html

from bokeh.io import show
from bokeh.io import output_notebook 

from bokeh.models import Text
from bokeh.models import Plot
from bokeh.models import Slider
from bokeh.models import Circle

from bokeh.models import Range1d
from bokeh.models import CustomJS
from bokeh.models import HoverTool
from bokeh.models import LinearAxis
from bokeh.models import ColumnDataSource
from bokeh.models import SingleIntervalTicker

from bokeh.palettes import Spectral6

output_notebook()

def gendata():
    xs = np.linspace(0,6*np.pi)
    ws = np.linspace(.1,2.,20)
    ys = [np.sin(x*ws) for x in xs]
    return xs, ws, ys

xs, ws, ys = gendata()
ws_int = list(range(len(ws)))

data = pd.DataFrame(ys)

sources = {}

for w, _ in enumerate(ws):
    new_df = pd.DataFrame({'x':xs,'fun':data[w]})
    sources['_' + str(w)] = ColumnDataSource(new_df)

dictionary_of_sources = dict(zip([w for w in ws_int], ['_%s' % w for w in ws_int]))

dictionary_of_sources

js_source_array = str(dictionary_of_sources).replace("'", "")
js_source_array

xdr = Range1d(min(xs), max(xs))
ydr = Range1d(-2, 2)
plot = Plot(
    x_range=xdr,
    y_range=ydr,
    plot_width=800,
    plot_height=400,
    outline_line_color=None,
    toolbar_location=None, 
    min_border=20,
)

AXIS_FORMATS = dict(
    minor_tick_in=None,
    minor_tick_out=None,
    major_tick_in=None,
    major_label_text_font_size="10pt",
    major_label_text_font_style="normal",
    axis_label_text_font_size="10pt",

    axis_line_color='#AAAAAA',
    major_tick_line_color='#AAAAAA',
    major_label_text_color='#666666',

    major_tick_line_cap="round",
    axis_line_cap="round",
    axis_line_width=1,
    major_tick_line_width=1,
)

xaxis = LinearAxis(ticker=SingleIntervalTicker(interval=1), axis_label="x", **AXIS_FORMATS)
yaxis = LinearAxis(ticker=SingleIntervalTicker(interval=20), axis_label="sin(w*x)", **AXIS_FORMATS)   
plot.add_layout(xaxis, 'below')
plot.add_layout(yaxis, 'left')

renderer_source = sources['_%s' % ws_int[0]]
circle_glyph = Circle(
    x='x', y='fun', size=20, fill_alpha=0.8, fill_color='#7c7e71',
    line_color='#7c7e71', line_width=0.5, line_alpha=0.5)

circle_renderer = plot.add_glyph(renderer_source, circle_glyph)



# Add the slider
code = """
    var w = slider.value,
        sources = %s,
        new_source_data = sources[w].data;
    renderer_source.data = new_source_data;
""" % js_source_array

callback = CustomJS(args=sources, code=code)
slider = Slider(start=ws_int[0], end=ws_int[-1], value=1, step=1, title="w", callback=callback)
callback.args["renderer_source"] = renderer_source
callback.args["slider"] = slider
#callback.args["text_source"] = text_source

show(layout([[plot], [slider]], sizing_mode='scale_width'))

