from __future__ import print_function
from IPython.display import display
from ipywidgets import *
from traitlets import *

import numpy as np
import pandas as pd
import bqplot as bq
import datetime as dt

np.random.seed(0)
size = 100
y_data = np.cumsum(np.random.randn(size) * 100.0)
y_data_2 = np.cumsum(np.random.randn(size))
y_data_3 = np.cumsum(np.random.randn(size) * 100.)

x = np.linspace(0.0, 10.0, size)

price_data = pd.DataFrame(np.cumsum(np.random.randn(150, 2).dot([[0.5, 0.8], [0.8, 1.0]]), axis=0) + 100,
                          columns=['Security 1', 'Security 2'],
                          index=pd.date_range(start='01-01-2007', periods=150))

symbol = 'Security 1'
dates_all = price_data.index.values
final_prices = price_data[symbol].values.flatten()

"""
Explanation: bqplot https://github.com/bloomberg/bqplot
A Jupyter - d3.js bridge
bqplot is a jupyter interactive widget library bringing d3.js visualization to the Jupyter notebook.

Apache Licensed

bqplot implements the abstractions of Wilkinson’s “The Grammar of Graphics” as interactive Jupyter widgets.
bqplot provides both
-   high-level plotting procedures with relevant defaults for common chart types,
-   lower-level descriptions of data visualizations meant for complex interactive visualization dashboards and applications involving mouse interactions and user-provided Python callbacks.
Installation:
bash
conda install -c conda-forge bqplot
End of explanation
"""


from bqplot import pyplot as plt

plt.figure(1)
n = 100
plt.plot(np.linspace(0.0, 10.0, n), np.cumsum(np.random.randn(n)), 
         axes_options={'y': {'grid_lines': 'dashed'}})
plt.show()

"""
Explanation: A simple plot with the pyplot API
End of explanation
"""


plt.figure(title='Scatter Plot with colors')
plt.scatter(y_data_2, y_data_3, color=y_data)
plt.show()

"""
Explanation: Scatter Plot
End of explanation
"""


plt.figure()
plt.hist(y_data, colors=['OrangeRed'])
plt.show()

"""
Explanation: Histogram
End of explanation
"""


xs = bq.LinearScale()
ys = bq.LinearScale()
x = np.arange(100)
y = np.cumsum(np.random.randn(2, 100), axis=1) #two random walks

line = bq.Lines(x=x, y=y, scales={'x': xs, 'y': ys}, colors=['red', 'green'])
xax = bq.Axis(scale=xs, label='x', grid_lines='solid')
yax = bq.Axis(scale=ys, orientation='vertical', tick_format='0.2f', label='y', grid_lines='solid')

fig = bq.Figure(marks=[line], axes=[xax, yax], animation_duration=1000)
display(fig)

# update data of the line mark
line.y = np.cumsum(np.random.randn(2, 100), axis=1)

xs = bq.LinearScale()
ys = bq.LinearScale()
x, y = np.random.rand(2, 20)
scatt = bq.Scatter(x=x, y=y, scales={'x': xs, 'y': ys}, default_colors=['blue'])
xax = bq.Axis(scale=xs, label='x', grid_lines='solid')
yax = bq.Axis(scale=ys, orientation='vertical', tick_format='0.2f', label='y', grid_lines='solid')

fig = bq.Figure(marks=[scatt], axes=[xax, yax], animation_duration=1000)
display(fig)

#data updates
scatt.x = np.random.rand(20) * 10
scatt.y = np.random.rand(20)

"""
Explanation: Every component of the figure is an independent widget
End of explanation
"""


xs.min = 4

xs.min = None

xax.label = 'Some label for the x axis'

"""
Explanation: The same holds for the attributes of scales, axes
End of explanation
"""


xs = bq.LinearScale()
ys = bq.LinearScale()
x = np.arange(100)
y = np.cumsum(np.random.randn(2, 100), axis=1) #two random walks

line = bq.Lines(x=x, y=y, scales={'x': xs, 'y': ys}, colors=['red', 'green'])
xax = bq.Axis(scale=xs, label='x', grid_lines='solid')
yax = bq.Axis(scale=ys, orientation='vertical', tick_format='0.2f', label='y', grid_lines='solid')

"""
Explanation: Use bqplot figures as input widgets
End of explanation
"""


def interval_change_callback(change):
    db.value = str(change['new'])

intsel = bq.interacts.FastIntervalSelector(scale=xs, marks=[line])
intsel.observe(interval_change_callback, names=['selected'] )

db = widgets.Label()
db.value = str(intsel.selected)
display(db)

fig = bq.Figure(marks=[line], axes=[xax, yax], animation_duration=1000, interaction=intsel)
display(fig)

line.selected

"""
Explanation: Selections
End of explanation
"""


handdraw = bq.interacts.HandDraw(lines=line)
fig.interaction = handdraw

line.y[0]

"""
Explanation: Handdraw
End of explanation
"""


from bqplot import *

size = 100
np.random.seed(0)
x_data = range(size)
y_data = np.cumsum(np.random.randn(size) * 100.0)

## Enabling moving of points in scatter. Try to click and drag any of the points in the scatter and 
## notice the line representing the mean of the data update

sc_x = LinearScale()
sc_y = LinearScale()

scat = Scatter(x=x_data[:10], y=y_data[:10], scales={'x': sc_x, 'y': sc_y}, default_colors=['blue'],
               enable_move=True)
lin = Lines(scales={'x': sc_x, 'y': sc_y}, stroke_width=4, line_style='dashed', colors=['orange'])
m = Label(value='Mean is %s'%np.mean(scat.y))

def update_line(change):
    with lin.hold_sync():
        lin.x = [np.min(scat.x), np.max(scat.x)]
        lin.y = [np.mean(scat.y), np.mean(scat.y)]
        m.value='Mean is %s'%np.mean(scat.y)
        

update_line(None)

# update line on change of x or y of scatter
scat.observe(update_line, names='x')
scat.observe(update_line, names='y')

ax_x = Axis(scale=sc_x)
ax_y = Axis(scale=sc_y, tick_format='0.2f', orientation='vertical')

fig = Figure(marks=[scat, lin], axes=[ax_x, ax_y])

## In this case on drag, the line updates as you move the points.
with scat.hold_sync():
    scat.enable_move = True
    scat.update_on_move = True
    scat.enable_add = False

display(m, fig)

"""
Explanation: Moving points around
End of explanation
"""


