from bokeh.plotting import figure, output_file, show

output_file("test.html")

p = figure()

print(type(p))

p.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=2)

show(p)

"""
Explanation: cf. https://bokeh.pydata.org/en/latest/docs/installation.html
End of explanation
"""


# Standard imports
from bokeh.io import output_notebook, show

output_notebook()

# Plot a complex chart with interactive hover in a few lines of code

from bokeh.models import ColumnDataSource, HoverTool
from bokeh.plotting import figure
from bokeh.sampledata.autompg import autompg_clean as df
from bokeh.transform import factor_cmap

df.cyl = df.cyl.astype(str)
df.yr = df.yr.astype(str)

group = df.groupby(by=['cyl', 'mfr'])
source = ColumnDataSource(group)

p = figure(plot_width=800, plot_height=300, title="Mean MPG by # Cylinders and Manufacturer",
          x_range=group, toolbar_location=None, tools="")

p.xgrid.grid_line_color = None
p.xaxis.axis_label = "Manufacturer grouped by # Cylinders"
p.xaxis.major_label_orientation = 1.2

index_cmap = factor_cmap('cyl_mfr', palette=['#2b83ba', '#abdda4', '#ffffbf', '#fdae61', '#d7191c'],
                        factors=sorted(df.cyl.unique()), end=1)

p.vbar(x='cyl_mfr', top='mpg_mean', width=1, source=source,
      line_color="white", fill_color=index_cmap,
      hover_line_color="darkgrey", hover_fill_color=index_cmap)

p.add_tools(HoverTool(tooltips=[("MPG", "@mpg_mean"), ("Cyl, Mfr", "@cyl_mfr")]))

show(p)

from IPython.display import IFrame

IFrame('https://demo.bokehplots.com/apps/sliders', width=900, height=500)

from IPython.core.display import Markdown

Markdown(open("README.md").read())

from IPython import __version__ as ipython_version
from pandas import __version__ as pandas_version
from bokeh import __version__ as bokeh_version

print("IPython - %s" % ipython_version)
print("Pandas - %s" % pandas_version)
print("Bokeh - %s" % bokeh_version)

"""
Explanation: cf. Bokeh Tutorial: 00 - Introduction and Setup
End of explanation
"""


from bokeh.plotting import figure, output_file, show

"""
Explanation: cf. https://bokeh.pydata.org/en/latest/docs/user_guide/quickstart.html#userguide-quickstart
End of explanation
"""


# prepare some data
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]

"""
Explanation: Basic steps to creating plots with bokeh.plotting interface are:
Prepare some data
In this case, plain python lists, but oculd also be NumPy arrays or Pandas series.
End of explanation
"""


# output to static HTML file
output_file("lines.html")

"""
Explanation: Tell Bokeh where to generate output
In this case, using output_file(), with filename "lines.html". Another option is output_notebook() for use in Jupyter notebooks.
End of explanation
"""


# create a new plot with a title and axis labels
p = figure(title="simple line example", x_axis_label='x', y_axis_label='y')

"""
Explanation: Call figure()
This creates a plot with typical default options and easy customization of title, tools, and axes labels.
End of explanation
"""


# add a line renderer with legend and line thickness
p.line(x, y, legend="Temp.", line_width=2)

"""
Explanation: Add renderers 
In this case, we use line() for our data, specifying visual customizations like colors, legends, and widths.
End of explanation
"""


# show the results
show(p)

"""
Explanation: Ask Bokeh to show() or save() the results.
These functions save plot to an HTML file and optionally display it in a browser.
End of explanation
"""


from bokeh.plotting import figure, output_file, show

# prepare some data
x = [0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]
y0 = [i**2 for i in x]
y1 = [10**i for i in x]
y2 = [10**(i**2) for i in x]

# output to static HTML file
output_file("log_lines.html")

# create new plot
p = figure(
    tools="pan,box_zoom,reset,save",
    y_axis_type="log", y_range=[0.001, 10**11], title="log axis example",
    x_axis_label='sections', y_axis_label='particles')

# add some renderers
p.line(x, x, legend="y=x")
p.circle(x, x, legend="y=x", fill_color="white", size=8)
p.line(x, y0, legend="y=x^2", line_width=3)
p.line(x, y1, legend="y=10^x", line_color="red")
p.circle(x, y1, legend="y=10^x", fill_color="red", line_color="red", size=6)
p.line(x, y2, legend="y=10^x^2", line_color="orange", line_dash="4 4")

# show the results
show(p)

from bokeh.plotting import output_notebook

"""
Explanation: Steps 3 and 4, "Add renderers", "Ask Bokeh to show() or save() the results", can be repeated to create more than 1 plot.
End of explanation
"""


output_notebook()

"""
Explanation: To view examples in a notebook, you'd only change output_file() to a call to output_notebook() instead.
End of explanation
"""


import numpy as np

from bokeh.plotting import figure, output_file, show

# prepare some data
N = 4000
x = np.random.random(size = N) * 100
y = np.random.random(size = N) * 100
radii = np.random.random(size = N) * 1.5

colors = ["#%02x%02x%02x" % (int(r), int(g), 150) for r, g in zip(50 + 2 * x, 30 + 2 * y)] # rainbox colors

print(len(colors))

# output to static HTML file (with CDN resources)
output_file("color_scatter.html", title="color_scatter.py example", mode = "cdn")

TOOLS = "crosshair,pan,wheel_zoom,box_zoom,reset,box_select,lasso_select"

"""
Explanation: Vectorized colors and sizes
This example shows how it's possible to provide sequences of data values for glyph attributes like fill_color, radius.
End of explanation
"""


# create a new plot with the tools above, and explicit ranges
p = figure(tools=TOOLS, x_range=(0, 100), y_range=(0, 100))

# add a circle renderer with vectorized colors and sizes
p.circle(x, y, radius=radii, fill_color=colors, fill_alpha=0.6, line_color=None)

# show the results
show(p)

"""
Explanation: supplying an explicit list of tool names to figure()
fetching BokehJS resources from CDN using the mode argument
setting the x_range and y_range explicitly
using NumPy arrays for supplying data
End of explanation
"""


from bokeh.layouts import gridplot
from bokeh.plotting import figure, output_file, show

# prepare some data
N = 100
x = np.linspace(0, 4*np.pi, N)
y0 = np.sin(x)
y1 = np.cos(x)
y2 = np.sin(x) + np.cos(x)

# output to static HTML file
output_file("linked_panning.html")

"""
Explanation: Linked panning and brushing
Linking together various aspects of different plots - such linkages are typically sharing some plot component between plots. 
Below is an example of linked panning (where changing the range of one plot causes others to update) by 
- sharing range objects between the plots.
End of explanation
"""


# create a new plot
s1 = figure(width=250, plot_height=250, title=None)
s1.circle(x, y0, size=10, color="navy", alpha=0.5)

# NEW: create a new plot and share both ranges (in x and y directions)
s2 = figure(width=250, height=250, x_range=s1.x_range, y_range=s1.y_range, title=None)
s2.triangle(x, y1, size=10, color="firebrick", alpha=0.5)

# NEW: create a new plot and share only one range (in x-direction)
s3 = figure(width=250, height=250, x_range=s1.x_range, title=None)
s3.square(x, y2, size=10, color="olive", alpha=0.5)

"""
Explanation: calling figure() multiple times to create multiple plots
showing new glyphs using new glyph methods triangle() and square()
End of explanation
"""


p = gridplot([[s1, s2, s3]], toolbar_location=None)

# show the results
show(p)

"""
Explanation: using gridplot() to arrange several plots in an array
hiding the toolbar by setting toolbar_location to None
setting convenience arguments color (sets both line_color and fill_color) and alpha (sets both line_alpha and fill_alpha)
End of explanation
"""


from bokeh.plotting import *
from bokeh.models import ColumnDataSource

# prepare some data
N = 300
x = np.linspace(0, 4*np.pi, N)
y0 = np.sin(x)
y1 = np.cos(x)

# output to static HTML file
output_file("linked_brushing.html")

# NEW: create a column data source for the plots to share
source = ColumnDataSource(data=dict(x=x, y0=y0, y1=y1))

TOOLS = "pan,wheel_zoom,box_zoom,reset,save,box_select,lasso_select"

# create a new plot and add a renderer
left = figure(tools=TOOLS, width=350, height=350, title=None)

left.circle('x', 'y0', source=source)

# create another new plot and add a renderer
right = figure(tools=TOOLS, width=350, height=350, title=None)
right.circle('x', 'y1', source=source)

# put the subplots in a gridplot
p = gridplot([[left, right]])

# show the results
show(p)

"""
Explanation: linked brushing - where selection on 1 plot causes a selection to update on other plots.
Below, linked brushing is by sharing a ColumnDataSource between 2 plots.
End of explanation
"""


from bokeh.sampledata.stocks import AAPL

# prepare some data
aapl = np.array(AAPL['adj_close'])
aapl_dates = np.array(AAPL['date'], dtype=np.datetime64)

window_size = 30
window = np.ones(window_size)/float(window_size)
aapl_avg = np.convolve(aapl,window, 'same')

# output to static HTML file
output_file("stocks.html", title="stocks.py example")

"""
Explanation: Datetime axes
DatetimeAxis that can change displayed ticks based on current scale of the plot. There are some inputs for which Bokeh will automatically default to DatetimeAxis, but you can always explicitly ask for one by passing the value "datetime" to the x_axis_type or y_axis_type parameters to figure().
End of explanation
"""


# create a new plot with a datetime axis type
p = figure(plot_width=800, plot_height=350, x_axis_type="datetime")

# add renderers
p.circle(aapl_dates, aapl, size=4, color='darkgrey', alpha=0.2, legend='close')
p.line(aapl_dates, aapl_avg, color='navy', legend='avg')

"""
Explanation: setting the plot_width and plot_height arguments to figure()
End of explanation
"""


# NEW: customize by setting attributes
p.title.text = "AAPL One-Month Average"
p.legend.location = "top_left"
p.grid.grid_line_alpha = 0
p.xaxis.axis_label = 'Date'
p.yaxis.axis_label = 'Price'
p.ygrid.band_fill_color = "olive"
p.ygrid.band_fill_alpha = 0.1

# show the results
show(p)

"""
Explanation: customizing plots and other objects by assigning values to their attributes
accessing guides and annotations with convenience Figure attributes: legend, grid, xgrid, ygrid, axis, xaxis, yaxis
End of explanation
"""


