I am trying to get a line plot via Bokeh in Python. I am new to Bokeh and I am trying to apply hover tool tips over the plot. The x-axis of the plot has Timestamp values which are converted into epoch string. I've reviewed some same problems here and tried to use the workaround for my case but it doesn't seem to work. On the plot it gives ??? where the time should show up.
Any suggestions for my code?
Timestamp is in format 2016-12-29 02:49:12
Also can someone tell how do I format x-axis ticks to show up vertically ?
p = figure(width=1100,height=300,tools='resize,pan,wheel_zoom,box_zoom,reset,previewsave,hover',logo=None)
p.title.text = "Time Series for Price in Euros"
p.grid.grid_line_alpha = 0
p.xaxis.axis_label = "Day"
p.yaxis.axis_label = "Euros"
p.ygrid.band_fill_color = "olive"
p.ygrid.band_fill_alpha = 0.1
p.circle(df['DateTime'],df['EuP'], size=4, legend='close',
color='darkgrey', alpha=0.2)
p.xaxis.formatter = DatetimeTickFormatter(formats=dict(
hours=["%d %B %Y"],
days=["%d %B %Y"],
months=["%d %B %Y"],
years=["%d %B %Y"],
))
source = ColumnDataSource(data=dict(time=[x.strftime("%Y-%m-%d %H:%M:%S")for x in df['DateTime']]))
hover = p.select(dict(type=HoverTool))
hover.tooltips = {"time":'#time', "y":"$y"}
hover.mode = 'mouse'
p.line(df['DateTime'],df['EuP'],legend='Price',color='navy',alpha=0.7)
Since this answer was originally posted, new work has gone into Bokeh to make things simpler. A datetime field can be formatted as a datetime directly by the hover tool, by specifying a formatter, e.g.:
HoverTool(tooltips=[('date', '#DateTime{%F}')],
formatters={'#DateTime': 'datetime'})
It is no longer necessary to pre-format date fields in the data source as below. For more information see Formatting Tooltip Fields
OLD ANSWER:
The problem with your tooltip is you created a source with the string representation of the dates, but the p.line() call is unaware of it. So you have to pass in a columndatasource that has the tooltip, the x and y values.
Here is a working variant of your code:
from bokeh.plotting import figure, show
from bokeh.models.formatters import DatetimeTickFormatter
from bokeh.models import ColumnDataSource
from bokeh.models.tools import HoverTool
import pandas as pd
import numpy as np
data = {
'DateTime' : pd.Series(
['2016-12-29 02:49:12',
'2016-12-30 02:49:12',
'2016-12-31 02:49:12'],
dtype='datetime64[ns]'),
'EuP' : [20,40,15]
}
df = pd.DataFrame(data)
df['tooltip'] = [x.strftime("%Y-%m-%d %H:%M:%S") for x in df['DateTime']]
p = figure(width=1100,height=300,tools='resize,pan,wheel_zoom,box_zoom,reset,previewsave,hover',logo=None)
p.title.text = "Time Series for Price in Euros"
p.grid.grid_line_alpha = 0
p.xaxis.axis_label = "Day"
p.yaxis.axis_label = "Euros"
p.ygrid.band_fill_color = "olive"
p.ygrid.band_fill_alpha = 0.1
p.circle(df['DateTime'],df['EuP'], size=4, legend='close',
color='darkgrey', alpha=0.2)
p.xaxis.formatter = DatetimeTickFormatter(formats=dict(
hours=["%d %B %Y"],
days=["%d %B %Y"],
months=["%d %B %Y"],
years=["%d %B %Y"],
))
hover = p.select(dict(type=HoverTool))
tips = [('when','#tooltip'), ('y','$y')]
hover.tooltips = tips
hover.mode = 'mouse'
p.line(x='DateTime', y='EuP', source=ColumnDataSource(df),
legend='Price',color='navy',alpha=0.7)
show(p)
Also note there is an open issue about the lack of formatting options in the bokeh tooltip. There might be an easier way to not have to format the datestrings as a separate column:
https://github.com/bokeh/bokeh/issues/1239
Also can someone tell how do I format x-axis ticks to show up vertically ?
They look fine to me, sorry I cannot help on that one.
Hope this helps!
PS it would be better next time if you posted a working script with import statements, and a mocked up dataframe to make it possible to test. It took some time to sort it all out. But I am learning Bokeh so that is fine :)
Sorry for not commenting, I don't have enough reputation for that.
The accepted answer by #Alex doesn't work for me (Bokeh 2.0.1), because it is lacking a simple #-sign in the formatter. The working code is this:
HoverTool(tooltips=[('date', '#DateTime{%F}')],
formatters={'#DateTime': 'datetime'})
I have created a wrapper for ScatterPlot in bokeh.
class Visualization():
WIDTH = 1000
TOOLS = "pan,wheel_zoom,box_zoom,reset,save"
class ScatterChart(Visualization):
def __init__(self, data, spec:Dict):
self.data = data
self.x_column = spec["x_axis"]
self.y_column = spec["y_axis"]
self.series_ = spec["series_column"]
self.xlabel = spec['xlabel']
self.ylabel = spec['ylabel']
self.title = spec['title']
def prepare_data(self):
# Get Axis Type
self.xtype = 'datetime' if self.data.dtypes[self.x_column].type is np.datetime64 else 'linear'
self.ytype = 'datetime' if self.data.dtypes[self.x_column].type is np.datetime64 else 'linear'
return self.data
def render(self):
df_ = self.prepare_data()
format_= {}
tool_tip=[]
# For axis
for col in [self.x_column, self.y_column , self.series_]:
if self.data.dtypes[col].type is np.datetime64:
format_['#' + str(col) ] = "datetime" # formatter
tool_tip.append(tuple([str(col) , '#' + str(col) + '{%F}'])) # tool-tip
else:
format_['#' + str(col) ] = "numeral" #
tool_tip.append(tuple([str(col) , '#' + str(col)]))
# print(format_)
# print(tool_tip)
# Add Hover parameters
hover = HoverTool(tooltips= tool_tip
, formatters=format_ )
p=figure(
width = super().WIDTH,
height = 500,
x_axis_label = self.xlabel,
x_axis_type=self.xtype,
y_axis_label = self.ylabel,
y_axis_type=self.ytype,
title = self.title,
tools = super().TOOLS
)
# Get Only Top 10 groups/series to display
for value, color in zip(islice(self.data.groupby(by=[self.series_]
)[self.series_].count().sort_values(ascending=False).rename('cnt').reset_index()[self.series_].tolist(), 10), Category10[10]):
p.scatter(
x=self.x_column,
y=self.y_column,
source=df_.loc[(df_[self.series_]==value)],
color=color,
legend_group=self.series_
)
p.add_tools(hover)
p.toolbar.logo = None
p.legend.location = "top_left"
p.legend.click_policy="hide"
return p
# end of ScatterChart
This is how I initialize this
from visualization import ScatterChart
sc = ScatterChart(
df,
{'x_axis' :'ts',
'y_axis': 'Discus',
'series_column': 'Competition',
'xlabel':'Discus',
'ylabel':'Javeline',
'title':'Discus Vs Javeline'
})
d = sc.render()
show(d)
Related
I am new to Bokeh I am trying to replicate the line plots shown in https://www.worldometers.info/coronavirus/ using Bokeh.Here is my full code
from datetime import datetime, timedelta, date
import requests
import json
from bokeh.plotting import output_notebook, figure, show
from bokeh.models import ColumnDataSource, HoverTool, Title
def DateFormatter(x):
s = '01222020'
global given_date
given_date = datetime(month=int(s[:2]), day=int(s[2:4]), year=int(s[4:]))
given_date += timedelta(days=x)
final = str(given_date.strftime('%m{}%d{}%y').format('/','/'))
if int(final[0:2])<10 and int(final[3:5])<10:
final = final[1:]
final = final[0 : 2 : ] + final[3 : :]
elif int(final[0:2])<10:
final = final[1:]
elif int(final[3:5])<10:
final = final[0 : 2 : ] + "/" + final[4 : :]
return final
def DateFormatterForPlot(x):
s_plot = '01222020'
global given_date_plot
given_date_plot = datetime(month=int(s_plot[:2]), day=int(s_plot[2:4]), year=int(s_plot[4:]))
given_date_plot += timedelta(days=x-1)
final_plot1 = str(given_date_plot.strftime('%b %d'))
if int(final_plot1[4:6])<10:
final_plot1 = final_plot1[0 : 4 : ] + final_plot1[5 : :]
return final_plot1
finallist=[]
l2 = []
plot_list = []
country = "India"
chart_type = "cases"
base_site = f'https://disease.sh/v3/covid-19/historical/{country}?lastdays=all'
r = requests.get(base_site)
if r.status_code == 200:
packages_json = r.json()
today_date = str(date.today().strftime('%m{}%d{}%y').format('/','/'))
if int(today_date[0:2])<10 and int(today_date[3:5])<10:
today_date = today_date[1:]
today_date = today_date[0 : 2 : ] + today_date[3 : :]
elif int(today_date[0:2])<10:
today_date = today_date[1:]
elif int(today_date[3:5])<10:
today_date = today_date[0 : 2 : ] + "/" + today_date[4 : :]
for i in range(1,1000):
current_date = DateFormatter(i)
if current_date==today_date:
f_date = datetime(2020, 1, 22)
delta = given_date - f_date
break;
for i in range(delta.days):#Day 157 is 26th June
try:
a = DateFormatter(i)
packages_str = json.dumps(packages_json['timeline'][chart_type][a], indent=2)
finallist.append(int(packages_str))
except KeyError:
pass
count = 0
for i in finallist:
count = count + 1
for i in range(1,count+1):
l2.append(i)
for i in l2:
plot_list.append(DateFormatterForPlot(i))
else:
print("Not a valid country")
source = ColumnDataSource(data=dict(y=finallist, x=l2, desc=plot_list))
TOOLTIPS = """
<style>
.bk-tooltip>div:not(:first-child) {display:none;}
</style>
<b>X: </b> #desc <br>
<b>Y: </b> #y{0,0}
"""
plot = figure(background_fill_color='#fafafa', x_axis_label='Days', y_axis_label='Coronavirus {}'.format(chart_type.capitalize()), plot_width=1200, plot_height=400, toolbar_location=None)
plot.line('x', 'y', source=source, legend = 'Number of {}'.format(chart_type.capitalize()), line_width=2, color='gray')
cr = plot.circle('x', 'y', size=10, source=source, fill_color="grey", hover_fill_color="gainsboro", fill_alpha=0.1, line_color=None, hover_line_color="white", hover_fill_alpha=1)
plot.add_tools(HoverTool(tooltips=TOOLTIPS, renderers=[cr]))
plot.add_layout(Title(text="Coronavirus {} Example Graph".format(chart_type.capitalize()), align="center"), "above")
plot.legend.location = 'top_left'
plot.left[0].formatter.use_scientific = False #Used to disable scientific notation on y-axis
The problem that is arising here is that more than one circle glyphs are being shown when cursor is hovered on the area of the plot where the density of circle glyphs are high.
I think there is a CustomJS callback for Hovertool to allow only one circle glyph to be shown on hovering mouse over it but I am not able to implement it.
Output of the snippet can be seen here http://geetanshjindal.pythonanywhere.com/charts/
I am using the latest bokeh version 2.1.1 and python version 3.6
I think you have three options and all have to do with de-densifying your plot:
Reduce the size of the circle glyphs so that they don't overlap. size=5 seems to work OK for your plot width.
Increase plot width so that the circle glyphs are more spaced out. Of course, this will add a scroll bar so might not be the best user experience.
Don't remove the Bokeh toolbar and encourage the user to interact with the plot - zooming in to see all circle glyphs.
The approach of selectively showing tooltips using CSS is interesting, but it hides the decision-making ("show the tooltip only for the first circle of the overlapping two") from the user, potentially causing confusion.
One alternative approach would be to remove the tooltips altogether and add annotations in key places instead (passing a million of cases?), as well as putting a table with all dates and values as a side panel for reference.
For annotations, you can use a combination of a Label and Bezier curve models:
from bokeh.models import Label, Bezier
test_label = Label(x=50, y=550000, x_units='data', y_units='data',
text='Custom description of the datapoint', render_mode='css',
border_line_color='white', border_line_alpha=1.0,
border_line_width=3, background_fill_color='white',
background_fill_alpha=1.0)
# play around with control point values for best effect
curve_source = ColumnDataSource(dict(
x0=[150],
y0=[395048],
x1=[130],
y1=[600000],
cx0=[150],
cy0=[500000],
cx1=[150],
cy1=[600000]
)
)
test_curve = Bezier(
x0="x0", y0="y0", x1="x1", y1="y1",
cx0="cx0", cy0="cy0", cx1="cx1", cy1="cy1",
line_color="green", line_width=1)
plot.add_glyph(curve_source, test_curve)
plot.add_layout(test_label)
I've got a program that displays stock market info for a google. I can adjust it with a DateRangeSlider to increase the dates that we're looking at. I also have a hovertool set on the chart to display the various aspects of the data for each respective day.
The issue I'm having is on callback. Instead of the hover data being refreshed with each call, it retains memory of previous calls and just stacks the previous hover info on top of the new.
Here's my code for running in Jupyter:
from pandas_datareader import data
from pandas import Timedelta
from datetime import datetime, date
from bokeh.plotting import figure, show
from bokeh.layouts import column, row
from bokeh.models import ColumnDataSource, HoverTool, NumeralTickFormatter, DatetimeTickFormatter, TextInput, DateRangeSlider
from bokeh.io import output_notebook, curdoc
output_notebook()
def inc_dec(c, o):
"""Determines if the financial day with and Increase or Decrease"""
if c > o:
return "Increase"
elif c == 0:
return "Equal"
else:
return "Decrease"
def get_sources(start = date(2016, 3, 1), end = date(2016, 3, 10), company = "GOOG"):
"""Gets all my dataframes for each glyph below"""
#Gather data for df's
df = data.DataReader(company, data_source="yahoo", start=start, end=end)
df["Status"] = [inc_dec(c, o) for c, o in zip(df.Close, df.Open)]
df["Mid"] = (df.Open + df.Close) / 2
df["Height"] = abs(df.Open - df.Close)
df["Width"] = 12*60*60*1000
df["Segment, Left"] = df.index - Timedelta(hours=2)
df["Segment, Right"] = df.index + Timedelta(hours=2)
#my df is complete. Split them
inc_df = df[df.Status == "Increase"]
dec_df = df[df.Status == "Decrease"]
#inc_s = ColumnDataSource(inc_df)
#dec_s = ColumnDataSource(dec_df)
#tot_s = ColumnDataSource(df)
#Dictionary of dataframes, Increasing, Decreasing, and Total
dfs = {"I": inc_df, "D": dec_df, "T": df}
return dfs
def fin(doc):
"""Initialize the graphs and make an application"""
#Get df's and convert to CDS
dfs = get_sources()
inc_s = ColumnDataSource(dfs["I"])
dec_s = ColumnDataSource(dfs["D"])
tot_s = ColumnDataSource(dfs["T"])
hover = HoverTool(names=["inc","dec"],
tooltips = [("Date", "#Date{%m/%d/%Y}"),
("High", "#High{$0.00}"),
("Low","#Low{$0.00}"),
("Open","#Open{$0.00}"),
("Close","#Close{$0.00}"),
("Volume", "#Volume{0,0}")],
formatters = {"#Date" : "datetime"})
#Formatting the plot, p
p = figure(x_axis_type="datetime", width=1000, height=300, sizing_mode="scale_width", tools="crosshair,pan,wheel_zoom,box_zoom,reset")
#p.title.text = "{}: Finacial Data".format(company) #Change this with company later
p.title.text = "GOOG: Financial Data"
p.title.align = "center"
p.xaxis.axis_label="Date"
p.yaxis.axis_label="Price"
p.yaxis.formatter = NumeralTickFormatter(format="$0,0.00")
p.grid.grid_line_alpha = 0.3
#Add glyphs
p.segment(x0='Date', y0='High', x1='Date', y1='Low', source=tot_s) #vertical
p.segment(x0='Segment, Left', y0='High', x1='Segment, Right', y1='High', source=tot_s) #high
p.segment(x0='Segment, Left', y0='Low', x1='Segment, Right', y1='Low', source=tot_s) #low
p.rect(x="Date", y="Mid", width="Width", height="Height", name="inc",
fill_color="#00FFFF", line_color="black", source=inc_s)
p.rect(x="Date", y="Mid", width="Width", height="Height", name="dec",
fill_color="#B22222", line_color="black", source=dec_s)
p.add_tools(hover)
#the callbacks
def cb_date(attr, new, old):
"""Callback for the DateRangeSlider"""
if not isinstance(new[0], int):
return None
else:
#Get new dates, pass them to get_sources to get df's, add new CDS's
start = date.fromtimestamp(new[0]/1000)
end = date.fromtimestamp(new[1]/1000)
dfs = get_sources(start=start, end=end)
inc_s.stream(dfs["I"])
dec_s.stream(dfs["D"])
tot_s.stream(dfs["T"])
#def cb_com(attr, new, old):
#Changes the company name, do later
#add widgets
slider = DateRangeSlider(start=date(2016, 1, 1),
end=date(2016, 5, 1),
value=(date(2016, 3, 1), date(2016, 3, 10)),
step=1,
title="Change Dates:")
slider.on_change('value', cb_date)
doc.add_root(column(slider,p))
show(fin)
Let me know what how I can go forward with this. I'm pretty lost.
I cannot run your code without some test data, but it seems to me that the issue is with the calls to the stream function. Streaming data does not remove the old data, even if the X coordinate is the same (data sources don't know and don't care about coordinates). If you want to replace the data for some particular date, you should use patch. If you want to replace the whole data, you should just assign the new value to the data attribute of a data source.
I'm creating a nested categorical bar chart with bokeh and pandas. I tested the exampled included in Bokeh docs (shown below)
from bokeh.io import show, output_file
from bokeh.plotting import figure
from bokeh.palettes import Spectral5
from bokeh.sampledata.autompg import autompg_clean as df
from bokeh.transform import factor_cmap
output_file("bar_pandas_groupby_nested.html")
df.cyl = df.cyl.astype(str)
df.yr = df.yr.astype(str)
group = df.groupby(by=['cyl', 'mfr'])
index_cmap = factor_cmap('cyl_mfr', palette=Spectral5, factors=sorted(df.cyl.unique()), end=1)
p = figure(plot_width=800, plot_height=300, title="Mean MPG by # Cylinders and Manufacturer",
x_range=group, toolbar_location=None, tooltips=[("MPG", "#mpg_mean"), ("Cyl, Mfr", "#cyl_mfr")])
p.vbar(x='cyl_mfr', top='mpg_mean', width=1, source=group,
line_color="white", fill_color=index_cmap, )
p.y_range.start = 0
p.x_range.range_padding = 0.05
p.xgrid.grid_line_color = None
p.xaxis.axis_label = "Manufacturer grouped by # Cylinders"
p.xaxis.major_label_orientation = 1.2
p.outline_line_color = None
show(p)
I'm trying to apply this with my out set of data. However, we i run the script i get the error
Js error
This is my code:
def test(data):
output_file("bar_pandas_groupby_nested.html")
print(df.head())
data.prueba = data.prueba.astype(str)
data.inst_nombre_institucion = data.inst_nombre_institucion.astype(str)
group = data.groupby(by=['prueba', 'inst_nombre_institucion'])
index_cmap = factor_cmap('prueba_inst_nombre_institucion', palette=Spectral5, factors=sorted(data.prueba.unique()), end=1)
p = figure(plot_width=800, plot_height=300, title="Mean",
x_range=group, toolbar_location=None, tooltips=[("MPG", "#media_mod_ingles_mean"), ("prueba, institucion", "#prueba_inst_nombre_institucion")])
p.vbar(x='prueba_inst_nombre_institucion', top='media_mod_ingles_mean', width=1, source=group,
line_color="white", fill_color=index_cmap, )
p.y_range.start = 0
p.x_range.range_padding = 0.05
p.xgrid.grid_line_color = None
p.xaxis.axis_label = "Mean"
p.xaxis.major_label_orientation = 1.2
p.outline_line_color = None
show(p)
return True
And my data looks like this:
data.head()
Why do i get this error?
Thanks for your time!
UPDATE:
data.csv and script can be downloaded here
The issue is that your labels are way, way too long to fit inside a 300px high plot when they are oriented vertical-ish. If I change the orientation to
p.xaxis.major_label_orientation = 0.2
Then the plot can render, but you can also see the problem:
Alternatively, if I make the labels actually nearly vertical (~pi/2), and make the plot height be 800px, everything is visible:
But I would say that still is fairly hard to interpret/read. I would suggest trying to find shorter strings to use for your categories.
I using bokeh patchs plot for my energy datas. It successfully worked the default timeseries. But if I select different two dates then it merges two date ranges block
Example:
date-range : 29/07/2018 - 31/07/2018 with hours
Successfull working example of result is here
dates : 30/07/2018 and 06/08/2018 with hours
Wrongly working example of result is here
So I tried this post but it's not change anything.
And code blocks :
df = generateRtpDataFrame(data_list,frekans)
df=df.round(2)
def stacked(df):
df=df[df.columns[::-1]]
df_top = df.cumsum(axis=1)
df_bottom = df_top.shift(axis=1).fillna({'total': 0})[::-1]
df_stack = pd.concat([df_bottom, df_top], ignore_index=False)
df_stack=df_stack.drop("total", axis=1)
return df_stack
areas = stacked(df)
colors = d3['Category20b'][areas.shape[1]]
x2 = np.hstack((df.index[::-1], df.index))
msg = "Example Plot"
caption = Title(text=msg, align='left', text_font_size='10pt')
tooltips=[
("index", "$index"),
]
p = figure(sizing_mode = 'scale_width',tooltips=tooltips,x_axis_type='datetime')
p.add_layout(caption, 'above')
p.grid.minor_grid_line_color = '#eeeeee'
p.xaxis.formatter=DatetimeTickFormatter(
minutes=["%M"],
hours=["%H:%M"],
days=["%d/%m/%Y"],
months=["%m/%Y"],
years=["%Y"],
)
p.xaxis.major_label_overrides = {
i: date.strftime('%Y-%m-%d %H:%M') for i, date in enumerate(pd.to_datetime(df.index))
}
p.patches(xs=[x2]*areas.shape[1],ys= [areas[c].values for c in areas], color=colors, alpha=0.8,line_color=None)
I am learning Bokeh, I am trying to plot a data from a panda data frame in a candlestick chart. Then hover over the candle to see the data. In the following code i see only red candles( open > close) working for hovering and not the one where (open < close) >not sure what is the problem.
Please let me know what is the issue with this.
from math import pi
import pandas as pd
from bokeh.models.formatters import TickFormatter, String, List
from bokeh.plotting import figure, show, output_file
from bokeh.sampledata.stocks import MSFT
from bokeh.models import ColumnDataSource, HoverTool
# create a custom model for a new tick formatter
class DateGapTickFormatter(TickFormatter):
''' A custom TickFormatter useful for skipping dates
Axis labels are taken from an array of date strings
(e.g. ['Sep 01', 'Sep 02', ...]) passed to the ``date_labels``
property.
'''
date_labels = List(String, help="""
An array of date strings to map integer date indices to.
""")
__implementation__ = """
import {Model} from "model"
import * as p from "core/properties"
export class DateGapTickFormatter extends Model
type: 'DateGapTickFormatter'
doFormat: (ticks) ->
date_labels = #date_labels
return (date_labels[tick] ? "" for tick in ticks)
#define {
date_labels: [ p.Any ]
}
"""
df = pd.DataFrame(MSFT)[:100]
# xaxis date labels used in the custom TickFormatter
date_labels = [date.strftime('%b %d') for date in pd.to_datetime(df["date"])]
inc = df.close > df.open
dec = df.open > df.close
w = 0.5
TOOLS = "pan,hover,wheel_zoom,box_zoom,reset,save"
p = figure(tools=TOOLS, plot_width=1000, title="MSFT Candlestick with Custom X-Axis")
hover = p.select(dict(type=HoverTool))
hover.mode ="mouse"
#hover.names = ['vbar1','vbar2']
hover.tooltips=[
( 'Date', '#date' ),
( 'Close','#close{0.2f}' ),
# ( 'Open', '#open{0.2f}'),
# ( 'High','#High{%0.2f}'),
# ( 'Low', '#Low{%0.2f}'),
# ( 'Delta', '#Delta{0.2f}' ),
# ( 'volume', '#Volume' )
]
mysource1 = ColumnDataSource(df[inc])
mysource2 = ColumnDataSource(df[dec])
p.xaxis.major_label_orientation = pi/4
p.grid[0].ticker.desired_num_ticks = 6
# use the custom TickFormatter. You must always define date_labels
p.xaxis.formatter = DateGapTickFormatter(date_labels=date_labels)
# x coordinates must be integers. If, for example, df.index are
# datetimes, you should replace them with a integer sequence
p.segment(df.index, df.high, df.index, df.low, color="black")
p.vbar(df.index[inc], w, df.open[inc], df.close[inc], fill_color="#D5E1DD", line_color="black",source=mysource1)
p.vbar(df.index[dec], w, df.open[dec], df.close[dec], fill_color="#F2583E", line_color="black",source=mysource2)
output_file("custom_datetime_axis.html", title="custom_datetime_axis.py example")
show(p) # open a browser