Here are the examples of the python api bokeh.models.FuncTickFormatter taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
17 Examples
3
Source : bokeh.py
with MIT License
from karlicoss
with MIT License
from karlicoss
def set_hhmm_axis(axis, *, mint: int, maxt: int, period: int=30) -> None:
from bokeh.models import FixedTicker
# FIXME infer mint/maxt
ticks = list(range(mint, maxt, period))
axis.ticker = FixedTicker(ticks=ticks)
from bokeh.models import FuncTickFormatter
axis.formatter = FuncTickFormatter(code=hhmm_formatter(unit=int))
# TODO use J for defensive js?
def hhmm_formatter(unit):
0
Source : plot_expression_va.py
with Apache License 2.0
from EPFL-LCSB
with Apache License 2.0
from EPFL-LCSB
def plot_va(filename, tag, kind, color = DEFAULT_COLOR, orient = 'horizontal'):
bp.curdoc().clear()
title = verbose_kinds[kind] + ' variability analysis for {} iJO1366 model'\
.format(tag)
data = pd.read_csv(os.path.join(outputs_folder, filename), index_col = 0)
if not data.columns[0] in ['minimum','maximum']:
data.columns = ['minimum','maximum']
data += 1e-9 # Resolution of the solver
f = lambda x: np.sqrt(x[0]*x[1])
# data['score'] = data.mean(axis=1)
data['score'] = data.apply(f, axis=1)
data.sort_values(by='score', ascending = False, inplace = True)
data['y'] = range(len(data))
data['name'] = data.index
source = ColumnDataSource(data)
xdr = DataRange1d()
ydr = DataRange1d()
_tools_to_show = 'box_zoom,pan,save,hover,reset,tap,wheel_zoom'
if orient == 'vertical':
p1 = bp.figure( title=title, x_range=xdr, y_range=ydr,
x_axis_type = 'log',
plot_width=600,
plot_height=1000,
tools=_tools_to_show,
# h_symmetry=False, v_symmetry=False,
min_border=0)
glyph = HBar(y="y", right="maximum", left="minimum", height=0.9,
fill_color=color, fill_alpha=0.5,
line_color = None)
p1.add_glyph(source, glyph)
p1.circle(x='score', y='y', fill_color=color, line_color=None,
source=source)
axis1 = p1.xaxis
axis2 = p1.yaxis
elif orient == 'horizontal':
p1 = bp.figure(title=title, x_range=ydr, y_range=xdr,
y_axis_type='log',
plot_width=1000,
plot_height=600,
tools=_tools_to_show,
# h_symmetry=False, v_symmetry=False,
min_border=0)
glyph = VBar(x="y", top="maximum", bottom="minimum", width=0.9,
fill_color=color, fill_alpha=0.5,
line_color=None)
p1.add_glyph(source, glyph)
p1.circle(y='score', x='y', fill_color=color, line_color=None,
source=source)
axis1 = p1.yaxis
axis2 = p1.xaxis
else:
raise ValueError("orient should be 'vertical' or 'horizontal'")
# Fix ticks
label_dict = {}
for i, s in enumerate(data.index):
label_dict[i] = s
axis2.formatter = FuncTickFormatter(code="""
var labels = %s;
return labels[tick];
""" % label_dict)
axis1.axis_label = '[{}]'.format(verbose_kinds[kind])
# p1.yaxis.ticker = [x for x in range(len(data))]
hover = p1.select(dict(type=HoverTool))
hover.tooltips = [(verbose_kinds[kind], "@name"),
("min", "@minimum"),
("max", "@maximum"),
]
hover.mode = 'mouse'
path = os.path.join(plots_folder, 'va_' + filename)
bp.output_file(path + '.html')
bp.show(p1)
p1.output_backend='svg'
export_svgs(p1, filename=path+'.svg')
bp.curdoc().clear()
return data
if __name__ == '__main__':
0
Source : plot_bok.py
with GNU General Public License v3.0
from ganeshjawahar
with GNU General Public License v3.0
from ganeshjawahar
def bokey_plot(dictionary_input, folder_bokey_default,mode="single", output=False, id_=None,info="",color_map_mode="continuous"):
"""
as input dictionnary of the form
- label : {x:, y: , label:[labels]}
mode allows you to specify if you want everything on one single plot or if you want distinct plots
"""
reset_output()
source = {}
i = 0
color = ["blue","#ee6666"]
assert color_map_mode in ["continuous","divergent"]
if color_map_mode=="continuous": color_map= cm.OrRd
elif color_map_mode=="divergent": color_map=cm.rainbow
if id_ is None:
id_ = str(uuid.uuid4())[0:8]
if mode == "single":
p = figure(plot_width=800, plot_height=1000,
tools=[BoxZoomTool(), ResetTool(), WheelZoomTool()],
toolbar_sticky=False, toolbar_location="right",
title='T-SNE '+info) # x_range=Range1d(-6,6),y_range=Range1d(int(min(y))-1,int(max(y))+1))
for key in dictionary_input.keys():
if mode == "distinct":
p = figure(plot_width=800, plot_height=1000,
title='T-SNE '+info) # x_range=Range1d(-6,6),y_range=Range1d(int(min(y))-1,int(max(y))+1))
source[key] = ColumnDataSource(data=dict(height=dictionary_input[key]["x"],
weight=dictionary_input[key]["y"],
names=dictionary_input[key]["label"]))
colors = ["#%02x%02x%02x" %(int(r), int(g), int(b)) for r, g, b, _ in (255)*color_map(Normalize(vmin=0,vmax=5)(dictionary_input[key]["color"]))]
colors_legend = ["#%02x%02x%02x" %(int(r), int(g), int(b)) for r, g, b, _ in (255)*color_map(Normalize(vmin=0,vmax=5)(np.sort(list(set(dictionary_input[key]["color"])))))]
color_mapper = LinearColorMapper(palette=colors_legend)
ticker = FixedTicker(ticks=[0, 1, 2, 3, 4,5])
formatter = FuncTickFormatter(code="""
function(tick) {
data = {0: '0-10', 1: '10-20', 2: '20-30', 3: '30-40', 4: '40-50',50: '50plus'}
return data[tick], " ,
}
""")
cbar = ColorBar(color_mapper=color_mapper, ticker=ticker, formatter=formatter,
major_tick_out=0, major_tick_in=0, major_label_text_align='left',
major_label_text_font_size='100pt', label_standoff=5)
p.scatter(x='weight', y='height', size=8, source=source[key], legend=key)# color=colors)
p.add_layout(cbar)
labels = LabelSet(x='weight', y='height', text='names', level='glyph',
x_offset=5, y_offset=5, source=source[key], render_mode='canvas')
p.add_layout(labels)
i += 1
if output:
output_file(folder_bokey_default+id_+"_tsne_"+key+"_"+info+"_bok.html")
print(folder_bokey_default+id_+"_tsne_"+key+"_"+info+"_bok.html")
show(p)
#if mode == "distinct":
# output_notebook()
# show(p)
if mode == "single":
output_notebook()
show(p)
0
Source : figure.py
with GNU General Public License v3.0
from happydasch
with GNU General Public License v3.0
from happydasch
def _init_figure(self):
'''
Initializes the figure
'''
ftype = self.get_type()
if ftype == FigureType.IND:
aspectratio = self._scheme.ind_aspectratio
elif ftype == FigureType.OBS:
aspectratio = self._scheme.obs_aspectratio
elif ftype == FigureType.VOL:
aspectratio = self._scheme.vol_aspectratio
elif ftype == FigureType.DATA:
aspectratio = self._scheme.data_aspectratio
else:
raise Exception(f'Unknown type "{ftype}"')
f = figure(
width=1000,
tools=Figure._tools,
x_axis_type='linear',
output_backend=self._scheme.output_backend,
aspect_ratio=aspectratio)
f.y_range.range_padding = self._scheme.y_range_padding
# remove any spacing if there is no title, so there is no spacing
# between plots
if not self._scheme.plot_title:
f.min_border_bottom = 0
f.min_border_top = 0
f.border_fill_color = convert_color(self._scheme.border_fill)
f.xaxis.axis_line_color = convert_color(self._scheme.axis_line_color)
f.yaxis.axis_line_color = convert_color(self._scheme.axis_line_color)
f.xaxis.minor_tick_line_color = convert_color(
self._scheme.tick_line_color)
f.yaxis.minor_tick_line_color = convert_color(
self._scheme.tick_line_color)
f.xaxis.major_tick_line_color = convert_color(
self._scheme.tick_line_color)
f.yaxis.major_tick_line_color = convert_color(
self._scheme.tick_line_color)
f.xaxis.major_label_text_color = convert_color(
self._scheme.axis_label_text_color)
f.yaxis.major_label_text_color = convert_color(
self._scheme.axis_label_text_color)
f.xgrid.grid_line_color = convert_color(self._scheme.grid_line_color)
f.ygrid.grid_line_color = convert_color(self._scheme.grid_line_color)
f.title.text_color = convert_color(self._scheme.plot_title_text_color)
f.left[0].formatter.use_scientific = False
f.background_fill_color = convert_color(self._scheme.background_fill)
# mechanism for proper date axis without gaps, thanks!
# https://groups.google.com/a/continuum.io/forum/#!topic/bokeh/t3HkalO4TGA
formatter_code = pkgutil.get_data(
__name__,
'templates/js/tick_formatter.js').decode()
f.xaxis.formatter = FuncTickFormatter(
args=dict(
axis=f.xaxis[0],
formatter=DatetimeTickFormatter(
microseconds=['%fus'],
milliseconds=['%3Nms', '%S.%3Ns'],
seconds=[self._scheme.axis_tickformat_seconds],
minsec=[self._scheme.axis_tickformat_minsec],
minutes=[self._scheme.axis_tickformat_minutes],
hourmin=[self._scheme.axis_tickformat_hourmin],
hours=[self._scheme.axis_tickformat_hours],
days=[self._scheme.axis_tickformat_days],
months=[self._scheme.axis_tickformat_months],
years=[self._scheme.axis_tickformat_years]),
source=self._fp.cds,
),
code=formatter_code)
hover_code = pkgutil.get_data(
__name__,
'templates/js/hover_tooltips.js').decode()
h = HoverTool(
tooltips=[
('Time',
f'@datetime{{{self._scheme.hovertool_timeformat}}}')],
mode='vline',
formatters={'@datetime': 'datetime'},)
callback = CustomJS(
args=dict(source=self.cds, hover=h), code=hover_code)
h.callback = callback
f.tools.append(h)
self._hover = h
# set figure
self.figure = f
def _figure_append_title(self, title):
0
Source : sleepiness.py
with MIT License
from karlicoss
with MIT License
from karlicoss
def plot_sleepiness_vs_exercise():
# TODO strenght exercise
from .data import cardio_dataframe as CDF
c = CDF()
c['dt'] = unlocalize(c['start_time'])
c = c.set_index('dt').sort_index()
c = c[c['error'].isna()]
# FIXME error handling
# todo for error handling, would be nice to have unused variable detection?
s = _sleepy_df()
c = c[c.index >= min(s.index)] # clip till the time we started collecting it
deltas = [timedelta(hours=h) for h in range(-200, 200)]
# we want to find out what predicts sleepiness..
# so sleepiness is y and kcal is x
ldf = lag_df(x=c['kcal'], y=s['sleepy'], deltas=deltas)
# todo maybe rolling is a somewhat misleading name?
f = rolling(x='lag', y='value', df=ldf, avgs=[]).figure
f.xaxis.formatter = FuncTickFormatter(code=hhmm_formatter(unit=ldf.index.dtype))
return f
@tab
0
Source : sleepiness.py
with MIT License
from karlicoss
with MIT License
from karlicoss
def plot_sleepiness_vs_sleep():
from .data import sleep_dataframe as DF
sdf = DF()
sdf = sdf[sdf['error'].isna()]
# todo not sure... maybe sleep start/end would be better? or just median??
sdf = sdf.set_index('date')
# sdf.index = unlocalize(sdf.index)
s = _sleepy_df()
sdf = sdf[sdf.index >= min(s.index)]
deltas = [timedelta(hours=h) for h in range(-24 * 5, 24 * 5, 4)]
# TODO need something similar to scatter matrix, but instead of scatter, covariance??
# TODO unhardcode
ress = []
for col in ['bed_time', 'coverage', 'avg_hr', 'hrv_morning', 'hrv_evening']:
ldf = lag_df(x=sdf[col], y=s['sleepy'], deltas=deltas)
# TODO wtf?? so
r = rolling(x='lag', y='value', df=ldf, avgs=[])
r.figure.title.text = f'lag plot: sleepiness vs {col}'
r.figure.xaxis.formatter = FuncTickFormatter(code=hhmm_formatter(unit=ldf.index.dtype))
ress.append(r)
# TODO maybe allow to yield plots? then just assume column layout
return column([r.layout for r in ress])
# TODO this doesn't make any sense... why lag always grows negative as the window size increases??
# also probably doesn't make sense to make window bigger than the next sleep? dunno.
0
Source : _plotting.py
with GNU Affero General Public License v3.0
from kernc
with GNU Affero General Public License v3.0
from kernc
def plot(*, results: pd.Series,
df: pd.DataFrame,
indicators: List[_Indicator],
filename='', plot_width=None,
plot_equity=True, plot_return=False, plot_pl=True,
plot_volume=True, plot_drawdown=False,
smooth_equity=False, relative_equity=True,
superimpose=True, resample=True,
reverse_indicators=True,
show_legend=True, open_browser=True):
"""
Like much of GUI code everywhere, this is a mess.
"""
# We need to reset global Bokeh state, otherwise subsequent runs of
# plot() contain some previous run's cruft data (was noticed when
# TestPlot.test_file_size() test was failing).
if not filename and not IS_JUPYTER_NOTEBOOK:
filename = _windos_safe_filename(str(results._strategy))
_bokeh_reset(filename)
COLORS = [BEAR_COLOR, BULL_COLOR]
BAR_WIDTH = .8
assert df.index.equals(results['_equity_curve'].index)
equity_data = results['_equity_curve'].copy(deep=False)
trades = results['_trades']
plot_volume = plot_volume and not df.Volume.isnull().all()
plot_equity = plot_equity and not trades.empty
plot_return = plot_return and not trades.empty
plot_pl = plot_pl and not trades.empty
is_datetime_index = isinstance(df.index, pd.DatetimeIndex)
from .lib import OHLCV_AGG
# ohlc df may contain many columns. We're only interested in, and pass on to Bokeh, these
df = df[list(OHLCV_AGG.keys())].copy(deep=False)
# Limit data to max_candles
if is_datetime_index:
df, indicators, equity_data, trades = _maybe_resample_data(
resample, df, indicators, equity_data, trades)
df.index.name = None # Provides source name @index
df['datetime'] = df.index # Save original, maybe datetime index
df = df.reset_index(drop=True)
equity_data = equity_data.reset_index(drop=True)
index = df.index
new_bokeh_figure = partial(
_figure,
x_axis_type='linear',
width=plot_width,
height=400,
tools="xpan,xwheel_zoom,box_zoom,undo,redo,reset,save",
active_drag='xpan',
active_scroll='xwheel_zoom')
pad = (index[-1] - index[0]) / 20
fig_ohlc = new_bokeh_figure(
x_range=Range1d(index[0], index[-1],
min_interval=10,
bounds=(index[0] - pad,
index[-1] + pad)) if index.size > 1 else None)
figs_above_ohlc, figs_below_ohlc = [], []
source = ColumnDataSource(df)
source.add((df.Close >= df.Open).values.astype(np.uint8).astype(str), 'inc')
trade_source = ColumnDataSource(dict(
index=trades['ExitBar'],
datetime=trades['ExitTime'],
exit_price=trades['ExitPrice'],
size=trades['Size'],
returns_positive=(trades['ReturnPct'] > 0).astype(int).astype(str),
))
inc_cmap = factor_cmap('inc', COLORS, ['0', '1'])
cmap = factor_cmap('returns_positive', COLORS, ['0', '1'])
colors_darker = [lightness(BEAR_COLOR, .35),
lightness(BULL_COLOR, .35)]
trades_cmap = factor_cmap('returns_positive', colors_darker, ['0', '1'])
if is_datetime_index:
fig_ohlc.xaxis.formatter = CustomJSTickFormatter(
args=dict(axis=fig_ohlc.xaxis[0],
formatter=DatetimeTickFormatter(days=['%d %b', '%a %d'],
months=['%m/%Y', "%b'%y"]),
source=source),
code='''
this.labels = this.labels || formatter.doFormat(ticks
.map(i => source.data.datetime[i])
.filter(t => t !== undefined));
return this.labels[index] || "";
''')
NBSP = '\N{NBSP}' * 4
ohlc_extreme_values = df[['High', 'Low']].copy(deep=False)
ohlc_tooltips = [
('x, y', NBSP.join(('$index',
'$y{0,0.0[0000]}'))),
('OHLC', NBSP.join(('@Open{0,0.0[0000]}',
'@High{0,0.0[0000]}',
'@Low{0,0.0[0000]}',
'@Close{0,0.0[0000]}'))),
('Volume', '@Volume{0,0}')]
def new_indicator_figure(**kwargs):
kwargs.setdefault('height', 90)
fig = new_bokeh_figure(x_range=fig_ohlc.x_range,
active_scroll='xwheel_zoom',
active_drag='xpan',
**kwargs)
fig.xaxis.visible = False
fig.yaxis.minor_tick_line_color = None
return fig
def set_tooltips(fig, tooltips=(), vline=True, renderers=()):
tooltips = list(tooltips)
renderers = list(renderers)
if is_datetime_index:
formatters = {'@datetime': 'datetime'}
tooltips = [("Date", "@datetime{%c}")] + tooltips
else:
formatters = {}
tooltips = [("#", "@index")] + tooltips
fig.add_tools(HoverTool(
point_policy='follow_mouse',
renderers=renderers, formatters=formatters,
tooltips=tooltips, mode='vline' if vline else 'mouse'))
def _plot_equity_section(is_return=False):
"""Equity section"""
# Max DD Dur. line
equity = equity_data['Equity'].copy()
dd_end = equity_data['DrawdownDuration'].idxmax()
if np.isnan(dd_end):
dd_start = dd_end = equity.index[0]
else:
dd_start = equity[:dd_end].idxmax()
# If DD not extending into the future, get exact point of intersection with equity
if dd_end != equity.index[-1]:
dd_end = np.interp(equity[dd_start],
(equity[dd_end - 1], equity[dd_end]),
(dd_end - 1, dd_end))
if smooth_equity:
interest_points = pd.Index([
# Beginning and end
equity.index[0], equity.index[-1],
# Peak equity and peak DD
equity.idxmax(), equity_data['DrawdownPct'].idxmax(),
# Include max dd end points. Otherwise the MaxDD line looks amiss.
dd_start, int(dd_end), min(int(dd_end + 1), equity.size - 1),
])
select = pd.Index(trades['ExitBar']).union(interest_points)
select = select.unique().dropna()
equity = equity.iloc[select].reindex(equity.index)
equity.interpolate(inplace=True)
assert equity.index.equals(equity_data.index)
if relative_equity:
equity /= equity.iloc[0]
if is_return:
equity -= equity.iloc[0]
yaxis_label = 'Return' if is_return else 'Equity'
source_key = 'eq_return' if is_return else 'equity'
source.add(equity, source_key)
fig = new_indicator_figure(
y_axis_label=yaxis_label,
**({} if plot_drawdown else dict(height=110)))
# High-watermark drawdown dents
fig.patch('index', 'equity_dd',
source=ColumnDataSource(dict(
index=np.r_[index, index[::-1]],
equity_dd=np.r_[equity, equity.cummax()[::-1]]
)),
fill_color='#ffffea', line_color='#ffcb66')
# Equity line
r = fig.line('index', source_key, source=source, line_width=1.5, line_alpha=1)
if relative_equity:
tooltip_format = f'@{source_key}{{+0,0.[000]%}}'
tick_format = '0,0.[00]%'
legend_format = '{:,.0f}%'
else:
tooltip_format = f'@{source_key}{{$ 0,0}}'
tick_format = '$ 0.0 a'
legend_format = '${:,.0f}'
set_tooltips(fig, [(yaxis_label, tooltip_format)], renderers=[r])
fig.yaxis.formatter = NumeralTickFormatter(format=tick_format)
# Peaks
argmax = equity.idxmax()
fig.scatter(argmax, equity[argmax],
legend_label='Peak ({})'.format(
legend_format.format(equity[argmax] * (100 if relative_equity else 1))),
color='cyan', size=8)
fig.scatter(index[-1], equity.values[-1],
legend_label='Final ({})'.format(
legend_format.format(equity.iloc[-1] * (100 if relative_equity else 1))),
color='blue', size=8)
if not plot_drawdown:
drawdown = equity_data['DrawdownPct']
argmax = drawdown.idxmax()
fig.scatter(argmax, equity[argmax],
legend_label='Max Drawdown (-{:.1f}%)'.format(100 * drawdown[argmax]),
color='red', size=8)
dd_timedelta_label = df['datetime'].iloc[int(round(dd_end))] - df['datetime'].iloc[dd_start]
fig.line([dd_start, dd_end], equity.iloc[dd_start],
line_color='red', line_width=2,
legend_label=f'Max Dd Dur. ({dd_timedelta_label})'
.replace(' 00:00:00', '')
.replace('(0 days ', '('))
figs_above_ohlc.append(fig)
def _plot_drawdown_section():
"""Drawdown section"""
fig = new_indicator_figure(y_axis_label="Drawdown")
drawdown = equity_data['DrawdownPct']
argmax = drawdown.idxmax()
source.add(drawdown, 'drawdown')
r = fig.line('index', 'drawdown', source=source, line_width=1.3)
fig.scatter(argmax, drawdown[argmax],
legend_label='Peak (-{:.1f}%)'.format(100 * drawdown[argmax]),
color='red', size=8)
set_tooltips(fig, [('Drawdown', '@drawdown{-0.[0]%}')], renderers=[r])
fig.yaxis.formatter = NumeralTickFormatter(format="-0.[0]%")
return fig
def _plot_pl_section():
"""Profit/Loss markers section"""
fig = new_indicator_figure(y_axis_label="Profit / Loss")
fig.add_layout(Span(location=0, dimension='width', line_color='#666666',
line_dash='dashed', line_width=1))
returns_long = np.where(trades['Size'] > 0, trades['ReturnPct'], np.nan)
returns_short = np.where(trades['Size'] < 0, trades['ReturnPct'], np.nan)
size = trades['Size'].abs()
size = np.interp(size, (size.min(), size.max()), (8, 20))
trade_source.add(returns_long, 'returns_long')
trade_source.add(returns_short, 'returns_short')
trade_source.add(size, 'marker_size')
if 'count' in trades:
trade_source.add(trades['count'], 'count')
r1 = fig.scatter('index', 'returns_long', source=trade_source, fill_color=cmap,
marker='triangle', line_color='black', size='marker_size')
r2 = fig.scatter('index', 'returns_short', source=trade_source, fill_color=cmap,
marker='inverted_triangle', line_color='black', size='marker_size')
tooltips = [("Size", "@size{0,0}")]
if 'count' in trades:
tooltips.append(("Count", "@count{0,0}"))
set_tooltips(fig, tooltips + [("P/L", "@returns_long{+0.[000]%}")],
vline=False, renderers=[r1])
set_tooltips(fig, tooltips + [("P/L", "@returns_short{+0.[000]%}")],
vline=False, renderers=[r2])
fig.yaxis.formatter = NumeralTickFormatter(format="0.[00]%")
return fig
def _plot_volume_section():
"""Volume section"""
fig = new_indicator_figure(y_axis_label="Volume")
fig.xaxis.formatter = fig_ohlc.xaxis[0].formatter
fig.xaxis.visible = True
fig_ohlc.xaxis.visible = False # Show only Volume's xaxis
r = fig.vbar('index', BAR_WIDTH, 'Volume', source=source, color=inc_cmap)
set_tooltips(fig, [('Volume', '@Volume{0.00 a}')], renderers=[r])
fig.yaxis.formatter = NumeralTickFormatter(format="0 a")
return fig
def _plot_superimposed_ohlc():
"""Superimposed, downsampled vbars"""
time_resolution = pd.DatetimeIndex(df['datetime']).resolution
resample_rule = (superimpose if isinstance(superimpose, str) else
dict(day='M',
hour='D',
minute='H',
second='T',
millisecond='S').get(time_resolution))
if not resample_rule:
warnings.warn(
f"'Can't superimpose OHLC data with rule '{resample_rule}'"
f"(index datetime resolution: '{time_resolution}'). Skipping.",
stacklevel=4)
return
df2 = (df.assign(_width=1).set_index('datetime')
.resample(resample_rule, label='left')
.agg(dict(OHLCV_AGG, _width='count')))
# Check if resampling was downsampling; error on upsampling
orig_freq = _data_period(df['datetime'])
resample_freq = _data_period(df2.index)
if resample_freq < orig_freq:
raise ValueError('Invalid value for `superimpose`: Upsampling not supported.')
if resample_freq == orig_freq:
warnings.warn('Superimposed OHLC plot matches the original plot. Skipping.',
stacklevel=4)
return
df2.index = df2['_width'].cumsum().shift(1).fillna(0)
df2.index += df2['_width'] / 2 - .5
df2['_width'] -= .1 # Candles don't touch
df2['inc'] = (df2.Close >= df2.Open).astype(int).astype(str)
df2.index.name = None
source2 = ColumnDataSource(df2)
fig_ohlc.segment('index', 'High', 'index', 'Low', source=source2, color='#bbbbbb')
colors_lighter = [lightness(BEAR_COLOR, .92),
lightness(BULL_COLOR, .92)]
fig_ohlc.vbar('index', '_width', 'Open', 'Close', source=source2, line_color=None,
fill_color=factor_cmap('inc', colors_lighter, ['0', '1']))
def _plot_ohlc():
"""Main OHLC bars"""
fig_ohlc.segment('index', 'High', 'index', 'Low', source=source, color="black")
r = fig_ohlc.vbar('index', BAR_WIDTH, 'Open', 'Close', source=source,
line_color="black", fill_color=inc_cmap)
return r
def _plot_ohlc_trades():
"""Trade entry / exit markers on OHLC plot"""
trade_source.add(trades[['EntryBar', 'ExitBar']].values.tolist(), 'position_lines_xs')
trade_source.add(trades[['EntryPrice', 'ExitPrice']].values.tolist(), 'position_lines_ys')
fig_ohlc.multi_line(xs='position_lines_xs', ys='position_lines_ys',
source=trade_source, line_color=trades_cmap,
legend_label=f'Trades ({len(trades)})',
line_width=8, line_alpha=1, line_dash='dotted')
def _plot_indicators():
"""Strategy indicators"""
def _too_many_dims(value):
assert value.ndim >= 2
if value.ndim > 2:
warnings.warn(f"Can't plot indicators with >2D ('{value.name}')",
stacklevel=5)
return True
return False
class LegendStr(str):
# The legend string is such a string that only matches
# itself if it's the exact same object. This ensures
# legend items are listed separately even when they have the
# same string contents. Otherwise, Bokeh would always consider
# equal strings as one and the same legend item.
def __eq__(self, other):
return self is other
ohlc_colors = colorgen()
indicator_figs = []
for i, value in enumerate(indicators):
value = np.atleast_2d(value)
# Use .get()! A user might have assigned a Strategy.data-evolved
# _Array without Strategy.I()
if not value._opts.get('plot') or _too_many_dims(value):
continue
is_overlay = value._opts['overlay']
is_scatter = value._opts['scatter']
if is_overlay:
fig = fig_ohlc
else:
fig = new_indicator_figure()
indicator_figs.append(fig)
tooltips = []
colors = value._opts['color']
colors = colors and cycle(_as_list(colors)) or (
cycle([next(ohlc_colors)]) if is_overlay else colorgen())
legend_label = LegendStr(value.name)
for j, arr in enumerate(value, 1):
color = next(colors)
source_name = f'{legend_label}_{i}_{j}'
if arr.dtype == bool:
arr = arr.astype(int)
source.add(arr, source_name)
tooltips.append(f'@{{{source_name}}}{{0,0.0[0000]}}')
if is_overlay:
ohlc_extreme_values[source_name] = arr
if is_scatter:
fig.scatter(
'index', source_name, source=source,
legend_label=legend_label, color=color,
line_color='black', fill_alpha=.8,
marker='circle', radius=BAR_WIDTH / 2 * 1.5)
else:
fig.line(
'index', source_name, source=source,
legend_label=legend_label, line_color=color,
line_width=1.3)
else:
if is_scatter:
r = fig.scatter(
'index', source_name, source=source,
legend_label=LegendStr(legend_label), color=color,
marker='circle', radius=BAR_WIDTH / 2 * .9)
else:
r = fig.line(
'index', source_name, source=source,
legend_label=LegendStr(legend_label), line_color=color,
line_width=1.3)
# Add dashed centerline just because
mean = float(pd.Series(arr).mean())
if not np.isnan(mean) and (abs(mean) < .1 or
round(abs(mean), 1) == .5 or
round(abs(mean), -1) in (50, 100, 200)):
fig.add_layout(Span(location=float(mean), dimension='width',
line_color='#666666', line_dash='dashed',
line_width=.5))
if is_overlay:
ohlc_tooltips.append((legend_label, NBSP.join(tooltips)))
else:
set_tooltips(fig, [(legend_label, NBSP.join(tooltips))], vline=True, renderers=[r])
# If the sole indicator line on this figure,
# have the legend only contain text without the glyph
if len(value) == 1:
fig.legend.glyph_width = 0
return indicator_figs
# Construct figure ...
if plot_equity:
_plot_equity_section()
if plot_return:
_plot_equity_section(is_return=True)
if plot_drawdown:
figs_above_ohlc.append(_plot_drawdown_section())
if plot_pl:
figs_above_ohlc.append(_plot_pl_section())
if plot_volume:
fig_volume = _plot_volume_section()
figs_below_ohlc.append(fig_volume)
if superimpose and is_datetime_index:
_plot_superimposed_ohlc()
ohlc_bars = _plot_ohlc()
_plot_ohlc_trades()
indicator_figs = _plot_indicators()
if reverse_indicators:
indicator_figs = indicator_figs[::-1]
figs_below_ohlc.extend(indicator_figs)
set_tooltips(fig_ohlc, ohlc_tooltips, vline=True, renderers=[ohlc_bars])
source.add(ohlc_extreme_values.min(1), 'ohlc_low')
source.add(ohlc_extreme_values.max(1), 'ohlc_high')
custom_js_args = dict(ohlc_range=fig_ohlc.y_range,
source=source)
if plot_volume:
custom_js_args.update(volume_range=fig_volume.y_range)
fig_ohlc.x_range.js_on_change('end', CustomJS(args=custom_js_args,
code=_AUTOSCALE_JS_CALLBACK))
plots = figs_above_ohlc + [fig_ohlc] + figs_below_ohlc
linked_crosshair = CrosshairTool(dimensions='both')
for f in plots:
if f.legend:
f.legend.visible = show_legend
f.legend.location = 'top_left'
f.legend.border_line_width = 1
f.legend.border_line_color = '#333333'
f.legend.padding = 5
f.legend.spacing = 0
f.legend.margin = 0
f.legend.label_text_font_size = '8pt'
f.legend.click_policy = "hide"
f.min_border_left = 0
f.min_border_top = 3
f.min_border_bottom = 6
f.min_border_right = 10
f.outline_line_color = '#666666'
f.add_tools(linked_crosshair)
wheelzoom_tool = next(wz for wz in f.tools if isinstance(wz, WheelZoomTool))
wheelzoom_tool.maintain_focus = False
kwargs = {}
if plot_width is None:
kwargs['sizing_mode'] = 'stretch_width'
fig = gridplot(
plots,
ncols=1,
toolbar_location='right',
toolbar_options=dict(logo=None),
merge_tools=True,
**kwargs
)
show(fig, browser=None if open_browser else 'none')
return fig
def plot_heatmaps(heatmap: pd.Series, agg: Union[Callable, str], ncols: int,
0
Source : combine.py
with MIT License
from microsoft
with MIT License
from microsoft
def combine(self, runs: List[Dict], img_save_path: str):
"""
Combine runs from several files.
:param paths: The paths to the runs to combine.
"""
output_file('combined_plots.html')
plot = figure(title="Balances & Accuracy on Hidden Test Set", )
plot.width = 800
plot.height = 800
plot.xaxis.axis_label = "Time (days)"
plot.yaxis.axis_label = "Percent"
plot.title.text_font_size = '20pt'
plot.xaxis.major_label_text_font_size = '16pt'
plot.xaxis.axis_label_text_font_size = '16pt'
plot.yaxis.major_label_text_font_size = '16pt'
plot.yaxis.axis_label_text_font_size = '16pt'
plot.xaxis[0].ticker = AdaptiveTicker(base=5 * 24 * 60 * 60)
plot.xgrid[0].ticker = AdaptiveTicker(base=24 * 60 * 60)
# JavaScript code.
plot.xaxis[0].formatter = FuncTickFormatter(code="""
return (tick / 86400).toFixed(0);
""")
plot.yaxis[0].formatter = PrintfTickFormatter(format="%0.1f%%")
# TODO Make plot wider (or maybe it's ok for the paper).
good_colors = cycle([
colors.named.green,
colors.named.lawngreen,
colors.named.darkgreen,
colors.named.limegreen,
])
bad_colors = cycle([
colors.named.red,
colors.named.darkred,
colors.named.orangered,
colors.named.indianred,
])
accuracy_colors = cycle([
colors.named.blue,
colors.named.cadetblue,
colors.named.cornflowerblue,
colors.named.darkblue,
])
baseline_accuracy_colors = cycle([
colors.named.black,
colors.named.darkgrey,
colors.named.slategrey,
colors.named.darkslategrey,
])
line_dashes = cycle([
'solid',
'dashed',
'dotted',
'dotdash',
'dashdot',
])
legend = []
for run in runs:
name = run['name']
path = run['path']
line_dash = next(line_dashes)
self._logger.info("Opening \"%s\".", path)
with open(path) as f:
data = json.load(f)
baseline_accuracy = data['baselineAccuracy']
if baseline_accuracy is not None:
self._logger.debug("Baseline accuracy: %s", baseline_accuracy)
r = plot.ray(x=[0], y=[baseline_accuracy * 100], length=0, angle=0, line_width=2,
line_dash=line_dash,
color=next(baseline_accuracy_colors))
legend.append((f"{name} accuracy when trained with all data: {baseline_accuracy * 100:0.1f}%", [r]))
agents: Dict[str, Agent] = dict()
for agent in data['agents']:
agent = Agent(**agent)
agents[agent.address] = agent
l = plot.line(x=[d['t'] for d in data['accuracies']],
y=[d['accuracy'] * 100 for d in data['accuracies']],
line_dash=line_dash,
line_width=2,
color=next(accuracy_colors),
)
legend.append((f"{name} Accuracy", [l]))
agent_balance_data = defaultdict(list)
for balance_data in data['balances']:
agent = balance_data['a']
agent_balance_data[agent].append(
(balance_data['t'], balance_data['b'] * 100 / agents[agent].start_balance))
for agent_id, balance_data in sorted(agent_balance_data.items(), key=itemgetter(0)):
agent = agents[agent_id]
if agent.good:
color = next(good_colors)
else:
color = next(bad_colors)
l = plot.line(x=list(map(itemgetter(0), balance_data)),
y=list(map(itemgetter(1), balance_data)),
line_dash=line_dash,
line_width=2,
color=color,
)
legend.append((f"{name} {agent.address} Agent Balance", [l]))
self._logger.info("Done going through runs.")
legend = Legend(items=legend, location='center_left')
plot.add_layout(legend, 'above')
plot.legend.label_text_font_size = '12pt'
self._logger.info("Saving image to: %s", img_save_path)
export_png(plot, img_save_path)
if __name__ == '__main__':
0
Source : simulate.py
with MIT License
from microsoft
with MIT License
from microsoft
def simulate(self,
agents: List[Agent],
baseline_accuracy: float = None,
init_train_data_portion: float = 0.1,
pm_test_sets: list = None,
accuracy_plot_wait_s=2E5,
train_size: int = None, test_size: int = None,
filename_indicator: str = None
):
"""
Run a simulation.
:param agents: The agents that will interact with the data.
:param baseline_accuracy: The baseline accuracy of the model.
Usually the accuracy on a hidden test set when the model is trained with all data.
:param init_train_data_portion: The portion of the data to initially use for training. Must be [0,1].
:param pm_test_sets: The test sets for the prediction market incentive mechanism.
:param accuracy_plot_wait_s: The amount of time to wait in seconds between plotting the accuracy.
:param train_size: The amount of training data to use.
:param test_size: The amount of test data to use.
:param filename_indicator: Path of the filename to create for the run.
"""
assert 0 < = init_train_data_portion < = 1
# Data to save.
save_data = dict(agents=[asdict(a) for a in agents],
baselineAccuracy=baseline_accuracy,
initTrainDataPortion=init_train_data_portion,
accuracies=[],
balances=[],
)
time_for_filenames = int(time.time())
save_path = f'saved_runs/{time_for_filenames}-{filename_indicator}-simulation_data.json'
model_save_path = f'saved_runs/{time_for_filenames}-{filename_indicator}-model.json'
plot_save_path = f'saved_runs/{time_for_filenames}-{filename_indicator}.png'
self._logger.info("Saving run info to \"%s\".", save_path)
os.makedirs(os.path.dirname(save_path), exist_ok=True)
# Set up plots.
doc: Document = curdoc()
doc.title = "DeCAI Simulation"
plot = figure(title="Balances & Accuracy on Hidden Test Set",
)
plot.width = 800
plot.height = 600
plot.xaxis.axis_label = "Time (days)"
plot.yaxis.axis_label = "Percent"
plot.title.text_font_size = '20pt'
plot.xaxis.major_label_text_font_size = '20pt'
plot.xaxis.axis_label_text_font_size = '20pt'
plot.yaxis.major_label_text_font_size = '20pt'
plot.yaxis.axis_label_text_font_size = '20pt'
plot.xaxis[0].ticker = AdaptiveTicker(base=5 * 24 * 60 * 60)
plot.xgrid[0].ticker = AdaptiveTicker(base=24 * 60 * 60)
balance_plot_sources_per_agent = dict()
good_colors = cycle([
colors.named.green,
colors.named.lawngreen,
colors.named.darkgreen,
colors.named.limegreen,
])
bad_colors = cycle([
colors.named.red,
colors.named.darkred,
])
for agent in agents:
source = ColumnDataSource(dict(t=[], b=[]))
assert agent.address not in balance_plot_sources_per_agent
balance_plot_sources_per_agent[agent.address] = source
if agent.calls_model:
color = 'blue'
line_dash = 'dashdot'
elif agent.good:
color = next(good_colors)
line_dash = 'dotted'
else:
color = next(bad_colors)
line_dash = 'dashed'
plot.line(x='t', y='b',
line_dash=line_dash,
line_width=2,
source=source,
color=color,
legend=f"{agent.address} Balance")
plot.legend.location = 'top_left'
plot.legend.label_text_font_size = '12pt'
# JavaScript code.
plot.xaxis[0].formatter = FuncTickFormatter(code="""
return (tick / 86400).toFixed(0);
""")
plot.yaxis[0].formatter = PrintfTickFormatter(format="%0.1f%%")
acc_source = ColumnDataSource(dict(t=[], a=[]))
if baseline_accuracy is not None:
plot.ray(x=[0], y=[baseline_accuracy * 100], length=0, angle=0, line_width=2,
legend=f"Accuracy when trained with all data: {baseline_accuracy * 100:0.1f}%")
plot.line(x='t', y='a',
line_dash='solid',
line_width=2,
source=acc_source,
color='black',
legend="Current Accuracy")
@gen.coroutine
def plot_cb(agent: Agent, t, b):
source = balance_plot_sources_per_agent[agent.address]
source.stream(dict(t=[t], b=[b * 100 / agent.start_balance]))
save_data['balances'].append(dict(t=t, a=agent.address, b=b))
@gen.coroutine
def plot_accuracy_cb(t, a):
acc_source.stream(dict(t=[t], a=[a * 100]))
save_data['accuracies'].append(dict(t=t, accuracy=a))
continuous_evaluation = not isinstance(self._decai.im, PredictionMarket)
def task():
(x_train, y_train), (x_test, y_test) = \
self._data_loader.load_data(train_size=train_size, test_size=test_size)
classifications = self._data_loader.classifications()
x_train, x_test, feature_index_mapping = self._feature_index_mapper.map(x_train, x_test)
x_train_len = x_train.shape[0]
init_idx = int(x_train_len * init_train_data_portion)
self._logger.info("Initializing model with %d out of %d samples.",
init_idx, x_train_len)
x_init_data, y_init_data = x_train[:init_idx], y_train[:init_idx]
x_remaining, y_remaining = x_train[init_idx:], y_train[init_idx:]
save_model = isinstance(self._decai.im, PredictionMarket) and self._decai.im.reset_model_during_reward_phase
self._decai.model.init_model(x_init_data, y_init_data, save_model)
if self._logger.isEnabledFor(logging.DEBUG):
s = self._decai.model.evaluate(x_init_data, y_init_data)
self._logger.debug("Initial training data evaluation: %s", s)
if len(x_remaining) > 0:
s = self._decai.model.evaluate(x_remaining, y_remaining)
self._logger.debug("Remaining training data evaluation: %s", s)
else:
self._logger.debug("There is no more remaining data to evaluate.")
self._logger.info("Evaluating initial model.")
accuracy = self._decai.model.log_evaluation_details(x_test, y_test)
self._logger.info("Initial test set accuracy: %0.2f%%", accuracy * 100)
t = self._time()
doc.add_next_tick_callback(
partial(plot_accuracy_cb, t=t, a=accuracy))
q = PriorityQueue()
random.shuffle(agents)
for agent in agents:
self._balances.initialize(agent.address, agent.start_balance)
q.put((self._time() + agent.get_next_wait_s(), agent))
doc.add_next_tick_callback(
partial(plot_cb, agent=agent, t=t, b=agent.start_balance))
unclaimed_data = []
next_data_index = 0
next_accuracy_plot_time = 1E4
desc = "Processing agent requests"
current_time = 0
with tqdm(desc=desc,
unit_scale=True, mininterval=2, unit=" requests",
total=len(x_remaining),
) as pbar:
while not q.empty():
# For now assume sending a transaction (editing) is free (no gas)
# since it should be relatively cheaper than the deposit required to add data.
# It may not be cheaper than calling `report`.
if next_data_index >= len(x_remaining):
if not continuous_evaluation or len(unclaimed_data) == 0:
break
current_time, agent = q.get()
update_balance_plot = False
if current_time > next_accuracy_plot_time:
self._logger.debug("Evaluating.")
next_accuracy_plot_time += accuracy_plot_wait_s
accuracy = self._decai.model.evaluate(x_test, y_test)
doc.add_next_tick_callback(
partial(plot_accuracy_cb, t=current_time, a=accuracy))
if continuous_evaluation:
self._logger.debug("Unclaimed data: %d", len(unclaimed_data))
pbar.set_description(f"{desc} ({len(unclaimed_data)} unclaimed)")
with open(save_path, 'w') as f:
json.dump(save_data, f, separators=(',', ':'))
self._decai.model.export(model_save_path, classifications,
feature_index_mapping=feature_index_mapping)
if os.path.exists(plot_save_path):
os.remove(plot_save_path)
self.save_plot_image(plot, plot_save_path)
self._time.set_time(current_time)
balance = self._balances[agent.address]
if balance > 0 and next_data_index < len(x_remaining):
# Pick data.
x, y = x_remaining[next_data_index], y_remaining[next_data_index]
if agent.calls_model:
# Only call the model if it's good.
if random.random() < accuracy:
update_balance_plot = True
self._decai.predict(Msg(agent.address, agent.pay_to_call), x)
else:
if not agent.good:
y = 1 - y
if agent.prob_mistake > 0 and random.random() < agent.prob_mistake:
y = 1 - y
# Bad agents always contribute.
# Good agents will only work if the model is doing well.
# Add a bit of chance they will contribute since 0.85 accuracy is okay.
if not agent.good or random.random() < accuracy + 0.15:
value = agent.get_next_deposit()
if value > balance:
value = balance
msg = Msg(agent.address, value)
try:
self._decai.add_data(msg, x, y)
# Don't need to plot every time. Plot less as we get more data.
update_balance_plot = next_data_index / len(x_remaining) + 0.1 < random.random()
balance = self._balances[agent.address]
if continuous_evaluation:
unclaimed_data.append((current_time, agent, x, y))
next_data_index += 1
pbar.update()
except RejectException:
# Probably failed because they didn't pay enough which is okay.
# Or if not enough time has passed since data was attempted to be added
# which is okay too because a real contract would reject this
# because the smallest unit of time we can use is 1s.
if self._logger.isEnabledFor(logging.DEBUG):
self._logger.exception("Error adding data.")
if balance > 0:
q.put((current_time + agent.get_next_wait_s(), agent))
claimed_indices = []
for i in range(len(unclaimed_data)):
added_time, adding_agent, x, classification = unclaimed_data[i]
if current_time - added_time < self._decai.im.refund_time_s:
break
if next_data_index >= len(x_remaining) \
and current_time - added_time < self._decai.im.any_address_claim_wait_time_s:
break
balance = self._balances[agent.address]
msg = Msg(agent.address, balance)
if current_time - added_time > self._decai.im.any_address_claim_wait_time_s:
# Attempt to take the entire deposit.
try:
self._decai.report(msg, x, classification, added_time, adding_agent.address)
update_balance_plot = True
except RejectException:
if self._logger.isEnabledFor(logging.DEBUG):
self._logger.exception("Error taking reward.")
elif adding_agent.address == agent.address:
try:
self._decai.refund(msg, x, classification, added_time)
update_balance_plot = True
except RejectException:
if self._logger.isEnabledFor(logging.DEBUG):
self._logger.exception("Error getting refund.")
else:
try:
self._decai.report(msg, x, classification, added_time, adding_agent.address)
update_balance_plot = True
except RejectException:
if self._logger.isEnabledFor(logging.DEBUG):
self._logger.exception("Error taking reward.")
stored_data = self._decai.data_handler.get_data(x, classification,
added_time, adding_agent.address)
if stored_data.claimable_amount < = 0:
claimed_indices.append(i)
for i in claimed_indices[::-1]:
unclaimed_data.pop(i)
if update_balance_plot:
balance = self._balances[agent.address]
doc.add_next_tick_callback(
partial(plot_cb, agent=agent, t=current_time, b=balance))
self._logger.info("Done going through data.")
if continuous_evaluation:
pbar.set_description(f"{desc} ({len(unclaimed_data)} unclaimed)")
if isinstance(self._decai.im, PredictionMarket):
self._time.add_time(agents[0].get_next_wait_s())
self._decai.im.end_market()
for i, test_set_portion in enumerate(pm_test_sets):
if i != self._decai.im.test_reveal_index:
self._decai.im.verify_next_test_set(test_set_portion)
with tqdm(desc="Processing contributions",
unit_scale=True, mininterval=2, unit=" contributions",
total=self._decai.im.get_num_contributions_in_market(),
) as pbar:
finished_first_round_of_rewards = False
while self._decai.im.remaining_bounty_rounds > 0:
self._time.add_time(agents[0].get_next_wait_s())
self._decai.im.process_contribution()
pbar.update()
if not finished_first_round_of_rewards:
accuracy = self._decai.im.prev_acc
# If we plot too often then we end up with a blob instead of a line.
if random.random() < 0.1:
doc.add_next_tick_callback(
partial(plot_accuracy_cb, t=self._time(), a=accuracy))
if self._decai.im.state == MarketPhase.REWARD_RESTART:
finished_first_round_of_rewards = True
if self._decai.im.reset_model_during_reward_phase:
# Update the accuracy after resetting all data.
accuracy = self._decai.im.prev_acc
else:
# Use the accuracy after training with all data.
pass
doc.add_next_tick_callback(
partial(plot_accuracy_cb, t=self._time(), a=accuracy))
pbar.total += self._decai.im.get_num_contributions_in_market()
self._time.add_time(self._time() * 0.001)
for agent in agents:
balance = self._balances[agent.address]
market_bal = self._decai.im._market_balances[agent.address]
self._logger.debug("\"%s\" market balance: %0.2f Balance: %0.2f",
agent.address, market_bal, balance)
doc.add_next_tick_callback(
partial(plot_cb, agent=agent, t=self._time(), b=max(balance + market_bal, 0)))
self._time.add_time(self._time() * 0.02)
for agent in agents:
msg = Msg(agent.address, 0)
# Find data submitted by them.
data = None
for key, stored_data in self._decai.data_handler:
if stored_data.sender == agent.address:
data = key[0]
break
if data is not None:
self._decai.refund(msg, np.array(data), stored_data.classification, stored_data.time)
balance = self._balances[agent.address]
doc.add_next_tick_callback(
partial(plot_cb, agent=agent, t=self._time(), b=balance))
self._logger.info("Balance for \"%s\": %.2f (%+.2f%%)",
agent.address, balance,
(balance - agent.start_balance) / agent.start_balance * 100)
else:
self._logger.warning("No data submitted by \"%s\" was found."
"\nWill not update it's balance.", agent.address)
self._logger.info("Done issuing rewards.")
accuracy = self._decai.model.log_evaluation_details(x_test, y_test)
doc.add_next_tick_callback(
partial(plot_accuracy_cb, t=current_time + 100, a=accuracy))
with open(save_path, 'w') as f:
json.dump(save_data, f, separators=(',', ':'))
self._decai.model.export(model_save_path, classifications, feature_index_mapping=feature_index_mapping)
if os.path.exists(plot_save_path):
os.remove(plot_save_path)
self.save_plot_image(plot, plot_save_path)
doc.add_root(plot)
thread = Thread(target=task)
thread.start()
0
Source : plot.py
with MIT License
from PatrikHlobil
with MIT License
from PatrikHlobil
def plot( # noqa C901
df_in,
x=None,
y=None,
kind="line",
figsize=None,
use_index=True,
title="",
legend="top_right",
logx=False,
logy=False,
xlabel=None,
ylabel=None,
xticks=None,
yticks=None,
xlim=None,
ylim=None,
fontsize_title=None,
fontsize_label=None,
fontsize_ticks=None,
fontsize_legend=None,
color=None,
colormap=None,
category=None,
histogram_type=None,
stacked=False,
weights=None,
bins=None,
normed=False,
cumulative=False,
show_average=False,
plot_data_points=False,
plot_data_points_size=5,
number_format=None,
disable_scientific_axes=None,
show_figure=True,
return_html=False,
panning=True,
zooming=True,
sizing_mode="fixed",
toolbar_location="right",
hovertool=True,
hovertool_string=None,
rangetool=False,
vertical_xlabel=False,
x_axis_location="below",
webgl=True,
reuse_plot=None, # This keyword is not used by Pandas-Bokeh, but pandas plotting API adds it for series object calls
**kwargs,
):
"""Method for creating a interactive with 'Bokeh' as plotting backend. Available
plot kinds are:
* line
* point
* scatter
* bar / barh
* hist
* area
* pie
* map
Examples
--------
>>> df.plot_bokeh.line()
>>> df.plot_bokeh.scatter(x='x',y='y')
These plotting methods can also be accessed by calling the accessor as a
method with the ``kind`` argument (except of "map" plot):
``df.plot_bokeh(kind='line')`` is equivalent to ``df.plot_bokeh.line()``
For more information about the individual plot kind implementations, have a
look at the underlying method accessors (like df.plot_bokeh.line) or visit
https://github.com/PatrikHlobil/Pandas-Bokeh.
If `sizing_mode` is not fixed (default), it will overide the set plot width or height
depending on which axis it is scaled on.
"""
# Make a local copy of the DataFrame:
df = df_in.copy()
if isinstance(df, pd.Series):
df = pd.DataFrame(df)
if kind == "map":
return mapplot(
df,
x=x,
y=y,
figsize=figsize,
title=title,
legend=legend,
xlabel=xlabel,
ylabel=ylabel,
xlim=xlim,
color=color,
colormap=colormap,
category=category,
show_figure=show_figure,
return_html=return_html,
panning=panning,
zooming=zooming,
toolbar_location=toolbar_location,
hovertool=hovertool,
hovertool_string=hovertool_string,
webgl=webgl,
**kwargs,
)
# Check plot kind input:
allowed_kinds = [
"line",
"step",
"point",
"scatter",
"bar",
"barh",
"hist",
"area",
"pie",
"map",
]
rangetool_allowed_kinds = ["line", "step"]
if kind not in allowed_kinds:
allowed_kinds = "', '".join(allowed_kinds)
raise ValueError(f"Allowed plot kinds are '{allowed_kinds}'.")
if rangetool and kind not in rangetool_allowed_kinds:
allowed_rangetool_kinds = "', '".join(rangetool_allowed_kinds)
raise ValueError(
f"For using the rangetool, the allowed plot kinds are '{allowed_rangetool_kinds}'."
)
if rangetool:
x_axis_location = "above"
# Get and check options for base figure:
figure_options = {
"title": title,
"toolbar_location": toolbar_location,
"active_scroll": "wheel_zoom",
"plot_width": 600,
"plot_height": 400,
"output_backend": "webgl",
"sizing_mode": sizing_mode,
"x_axis_location": x_axis_location,
}
# Initializing rangetool plot variable:
p_rangetool = None
if figsize is not None:
width, height = figsize
figure_options["plot_width"] = width
figure_options["plot_height"] = height
if logx:
figure_options["x_axis_type"] = "log"
if logy:
figure_options["y_axis_type"] = "log"
if xlabel is not None:
figure_options["x_axis_label"] = xlabel
if ylabel is not None:
figure_options["y_axis_label"] = ylabel
if xlim is not None:
if not isinstance(xlim, (tuple, list)):
raise ValueError(" < xlim> must be a list/tuple of form (x_min, x_max).")
elif len(xlim) != 2:
raise ValueError(" < xlim> must be a list/tuple of form (x_min, x_max).")
else:
figure_options["x_range"] = xlim
if ylim is not None:
if not isinstance(ylim, (tuple, list)):
raise ValueError(" < ylim> must be a list/tuple of form (y_min, y_max).")
elif len(ylim) != 2:
raise ValueError(" < ylim> must be a list/tuple of form (y_min, y_max).")
else:
figure_options["y_range"] = ylim
if webgl:
figure_options["output_backend"] = "webgl"
if number_format is None:
number_format = ""
else:
number_format = "{%s}" % number_format
# Check hovertool_string and define additional columns to keep in source:
additional_columns = _extract_additional_columns(df, hovertool_string)
# Set standard linewidth:
if "line_width" not in kwargs:
kwargs["line_width"] = 2
# Get x-axis Name and Values:
delete_in_y = None
if x is not None:
if issubclass(x.__class__, pd.Index) or issubclass(x.__class__, pd.Series):
if x.name is not None:
name = str(x.name)
else:
name = ""
x = x.values
elif x in df.columns:
delete_in_y = x
name = str(x)
x = df[x].values
elif isinstance(x, (tuple, list, type(np.array))):
if len(x) == len(df):
x = x
name = ""
else:
raise Exception(
"Length of provided < x> argument does not fit length of DataFrame or Series."
)
else:
raise Exception(
"Please provide for the < x> parameter either a column name of the DataFrame/Series or an array of the same length."
)
else:
if use_index:
x = df.index.values
if df.index.name is not None:
name = str(df.index.name)
else:
name = ""
else:
x = np.linspace(0, len(df) - 1, len(df))
name = ""
# Define name of axis of x-values (for horizontal plots like barh, this corresponds
# to y-axis):
if kind == "barh":
if "y_axis_label" not in figure_options:
figure_options["y_axis_label"] = name
else:
if "x_axis_label" not in figure_options:
figure_options["x_axis_label"] = name
# Check type of x-axis:
if check_type(x) == "datetime":
figure_options["x_axis_type"] = "datetime"
xaxis_type = "datetime"
if xlim is not None:
starttime, endtime = xlim
try:
starttime = pd.to_datetime(starttime)
except ParserError:
raise ValueError("Could not parse x_min input of < xlim> as datetime.")
try:
endtime = pd.to_datetime(endtime)
except ParserError:
raise ValueError("Could not parse x_max input of < xlim> as datetime.")
figure_options["x_range"] = (starttime, endtime)
elif check_type(x) == "numeric":
xaxis_type = "numerical"
else:
xaxis_type = "categorical"
if kind in ["bar", "barh", "pie"]:
xaxis_type = "categorical"
x_old = x
x_labels_dict = None
if xaxis_type == "categorical":
if check_type(x) == "datetime":
x = _times_to_string(x)
else:
x = [str(el) for el in x]
if kind != "hist":
x_labels_dict = dict(zip(range(len(x)), x))
x = list(range(len(x)))
if "x_axis_type" in figure_options:
del figure_options["x_axis_type"]
# Determine data cols to plot (only plot numeric data):
data_cols = _determine_data_columns(y, df)
# Convert y-column names into string representation:
df.rename(columns={col: str(col) for col in data_cols}, inplace=True)
data_cols = [str(col) for col in data_cols]
# Delete x column if it appears in y columns:
if delete_in_y is not None:
if delete_in_y in data_cols:
data_cols.remove(delete_in_y)
N_cols = len(data_cols)
if len(data_cols) == 0:
raise Exception(
f"The only numeric column is the column {delete_in_y} that is already used on the x-axis."
)
# Autodetect y-label if no y-label is provided by user and only one y-column exists:
if N_cols == 1:
if kind == "barh":
if "x_axis_label" not in figure_options:
figure_options["x_axis_label"] = data_cols[0]
else:
if "y_axis_label" not in figure_options:
figure_options["y_axis_label"] = data_cols[0]
# Get Name of x-axis data:
if kind == "barh":
xlabelname = (
figure_options["y_axis_label"]
if figure_options.get("y_axis_label", "") != ""
else "x"
)
else:
xlabelname = (
figure_options["x_axis_label"]
if figure_options.get("x_axis_label", "") != ""
else "x"
)
# Create Figure for plotting:
p = figure(**figure_options)
if "x_axis_type" not in figure_options:
figure_options["x_axis_type"] = None
# For categorical plots, set the xticks:
if x_labels_dict is not None:
p.xaxis.formatter = FuncTickFormatter(
code="""
var labels = %s;
return labels[tick];
"""
% x_labels_dict
)
# Define ColumnDataSource for Plot if kind != "hist":
if kind != "hist":
source = {col: df[col].values for col in data_cols}
source["__x__values"] = x
source["__x__values_original"] = x_old
for kwarg, value in kwargs.items():
if value in df.columns:
source[value] = df[value].values
for add_col in additional_columns:
source[add_col] = df[add_col].values
# Define colormap
if kind not in ["scatter", "pie"]:
colormap = get_colormap(colormap, N_cols)
if color is not None:
colormap = get_colormap([color], N_cols)
# Add Glyphs to Plot:
if kind == "line":
p, p_rangetool = lineplot(
p,
source,
data_cols,
colormap,
hovertool,
xlabelname,
figure_options["x_axis_type"],
plot_data_points,
plot_data_points_size,
hovertool_string,
number_format,
rangetool,
**kwargs,
)
if kind == "step":
p, p_rangetool = stepplot(
p,
source,
data_cols,
colormap,
hovertool,
xlabelname,
figure_options["x_axis_type"],
plot_data_points,
plot_data_points_size,
hovertool_string,
number_format,
rangetool,
**kwargs,
)
if kind == "point":
p = pointplot(
p,
source,
data_cols,
colormap,
hovertool,
hovertool_string,
xlabelname,
figure_options["x_axis_type"],
number_format,
**kwargs,
)
if kind == "scatter":
if N_cols > 2:
raise Exception(
"For scatterplots < x> and < y> values can only be a single column of the DataFrame, not a list of columns. Please specify both < x> and < y> columns for a scatterplot uniquely."
)
# Get and set y-labelname:
y_column = data_cols[0]
if "y_axis_label" not in figure_options:
p.yaxis.axis_label = y_column
# Get values for y-axis:
y = df[y_column].values
# Delete additionally created values by pandas.plotting:
for add_param in ["s", "c"]:
if add_param in kwargs:
del kwargs[add_param]
# Get values for categorical colormap:
category_values = None
if category in df.columns:
category_values = df[category].values
elif category is not None:
raise Exception(
" < category> parameter has to be either None or the name of a single column of the DataFrame"
)
scatterplot(
p,
df,
x,
x_old,
y,
category,
category_values,
colormap,
hovertool,
hovertool_string,
additional_columns,
x_axis_type=figure_options["x_axis_type"],
xlabelname=xlabelname,
ylabelname=y_column,
**kwargs,
)
if kind == "bar" or kind == "barh":
# Define data source for barplot:
data = {col: df[col].values for col in data_cols}
data["__x__values"] = x
data["__x__values_original"] = x_old
source = ColumnDataSource(data)
for kwarg, value in kwargs.items():
if value in df.columns:
source.data[value] = df[value].values
for add_col in additional_columns:
source.data[add_col] = df[add_col].values
# Create Figure (just for categorical barplots):
del figure_options["x_axis_type"]
if "y_axis_label" not in figure_options and kind == "barh":
figure_options["y_axis_label"] = xlabelname
p = figure(**figure_options)
figure_options["x_axis_type"] = None
# Set xticks:
if kind == "bar":
p.xaxis.formatter = FuncTickFormatter(
code="""
var labels = %s;
return labels[tick];
"""
% x_labels_dict
)
elif kind == "barh":
p.yaxis.formatter = FuncTickFormatter(
code="""
var labels = %s;
return labels[tick];
"""
% x_labels_dict
)
if not stacked:
if N_cols >= 3:
base_width = 0.5
else:
base_width = 0.35
width = base_width / (N_cols - 0.5)
if N_cols == 1:
shifts = [0]
else:
delta_shift = base_width / (N_cols - 1)
shifts = [-base_width / 2 + i * delta_shift for i in range(N_cols)]
for i, name, color, shift in zip(
range(N_cols), data_cols, colormap, shifts
):
if kind == "bar":
glyph = p.vbar(
x=dodge("__x__values", shift, range=p.x_range),
top=name,
width=width,
source=source,
color=color,
legend_label=" " + name,
**kwargs,
)
hovermode = "vline"
elif kind == "barh":
glyph = p.hbar(
y=dodge("__x__values", shift, range=p.y_range),
right=name,
height=width,
source=source,
color=color,
legend_label=" " + name,
**kwargs,
)
hovermode = "hline"
if hovertool:
my_hover = HoverTool(mode=hovermode, renderers=[glyph])
if hovertool_string is None:
my_hover.tooltips = [
(xlabelname, "@__x__values_original"),
(name, "@{%s}" % name),
]
else:
my_hover.tooltips = hovertool_string
p.add_tools(my_hover)
if stacked:
if kind == "bar":
glyph = p.vbar_stack(
data_cols,
x="__x__values",
width=0.8,
source=source,
color=colormap,
legend_label=data_cols,
**kwargs,
)
hovermode = "vline"
elif kind == "barh":
glyph = p.hbar_stack(
data_cols,
y="__x__values",
height=0.8,
source=source,
color=colormap,
legend_label=data_cols,
**kwargs,
)
hovermode = "hline"
if hovertool:
my_hover = HoverTool(mode=hovermode, renderers=[glyph[-1]])
if hovertool_string is None:
my_hover.tooltips = [(xlabelname, "@__x__values_original")] + [
(col, "@{%s}" % col) for col in data_cols
]
else:
my_hover.tooltips = hovertool_string
p.add_tools(my_hover)
if kind == "hist":
# Disable line_color (for borders of histogram bins) per default:
if "line_color" not in kwargs:
kwargs["line_color"] = None
elif kwargs["line_color"] is True:
del kwargs["line_color"]
if "by" in kwargs and y is None:
y = kwargs["by"]
del kwargs["by"]
# Check for stacked keyword:
if stacked and histogram_type not in [None, "stacked"]:
warnings.warn(
f" < histogram_type> was set to '{histogram_type}', but was overriden by < stacked>=True parameter."
)
histogram_type = "stacked"
elif stacked and histogram_type is None:
histogram_type = "stacked"
# Set xlabel if only one y-column is given and user does not override this via
# xlabel parameter:
if len(data_cols) == 1 and xlabel is None:
p.xaxis.axis_label = data_cols[0]
# If Histogram should be plotted, calculate bins, aggregates and
# averages:
# Autocalculate bins if bins are not specified:
if bins is None:
values = df[data_cols].values
values = values[~np.isnan(values)]
data, bins = np.histogram(values)
# Calculate bins if number of bins is given:
elif isinstance(bins, int):
if bins < 1:
raise ValueError(
" < bins> can only be an integer>0, a list or a range of numbers."
)
values = df[data_cols].values
values = values[~np.isnan(values)]
v_min, v_max = values.min(), values.max()
bins = np.linspace(v_min, v_max, bins + 1)
if not isinstance(bins, str):
bins = list(bins)
if weights is not None:
if weights not in df.columns:
raise ValueError(
"Columns '%s' for < weights> is not in provided DataFrame."
)
else:
weights = df[weights].values
aggregates = []
averages = []
for col in data_cols:
values = df[col].values
if weights is not None:
not_nan = ~(np.isnan(values) | np.isnan(weights))
values_not_nan = values[not_nan]
weights_not_nan = weights[not_nan]
if sum(not_nan) < len(not_nan):
warnings.warn(
f"There are NaN values in column '{col}' or in the < weights> column. For the histogram, these rows have been neglected.",
Warning,
)
else:
not_nan = ~np.isnan(values)
values_not_nan = values[not_nan]
weights_not_nan = None
if sum(not_nan) < len(not_nan):
warnings.warn(
f"There are NaN values in column '{col}'. For the histogram, these rows have been neglected.",
Warning,
)
average = np.average(values_not_nan, weights=weights_not_nan)
averages.append(average)
data, bins = np.histogram(
values_not_nan, bins=bins, weights=weights_not_nan
)
if normed:
data = data / np.sum(data) * normed
if cumulative:
data = np.cumsum(data)
aggregates.append(data)
p = histogram(
p,
df,
data_cols,
colormap,
aggregates,
bins,
averages,
hovertool,
hovertool_string,
additional_columns,
normed,
cumulative,
show_average,
histogram_type,
logy,
**kwargs,
)
if kind == "area":
p = areaplot(
p,
source,
data_cols,
colormap,
hovertool,
hovertool_string,
xlabelname,
figure_options["x_axis_type"],
stacked,
normed,
**kwargs,
)
if kind == "pie":
source["__x__values"] = x_old
p = pieplot(
source,
data_cols,
colormap,
hovertool,
hovertool_string,
figure_options,
xlabelname,
**kwargs,
)
# Set xticks and yticks:
if xticks is not None:
p.xaxis[0].ticker = list(xticks)
elif x_labels_dict is not None and kind != "barh":
p.xaxis.ticker = x
elif kind == "barh":
p.yaxis.ticker = x
if yticks is not None:
p.yaxis.ticker = list(yticks)
# Format datetime ticks correctly:
if figure_options["x_axis_type"] == "datetime":
p.xaxis.formatter = DatetimeTickFormatter(
milliseconds=["%H:%M:%S.%f"],
seconds=["%H:%M:%S"],
minutes=["%H:%M:%S"],
hours=["%H:%M:%S"],
days=["%d %B %Y"],
months=["%d %B %Y"],
years=["%d %B %Y"],
)
# Rotate xlabel if wanted:
if vertical_xlabel:
p.xaxis.major_label_orientation = np.pi / 2
# Set panning option:
if panning is False:
p.toolbar.active_drag = None
# Set zooming option:
if zooming is False:
p.toolbar.active_scroll = None
# Set click policy for legend:
if not stacked and kind != "pie":
p.legend.click_policy = "hide"
# Hide legend if wanted:
if not legend:
p.legend.visible = False
# Modify legend position:
else:
if legend is True:
p.legend.location = "top_right"
elif legend in [
"top_left",
"top_center",
"top_right",
"center_left",
"center",
"center_right",
"bottom_left",
"bottom_center",
"bottom_right",
]:
p.legend.location = legend
else:
raise ValueError(
"Legend can only be True/False or one of 'top_left', 'top_center', 'top_right', 'center_left', 'center', 'center_right', 'bottom_left', 'bottom_center', 'bottom_right'"
)
# Set fontsizes:
set_fontsizes_of_figure(
figure=p,
fontsize_title=fontsize_title,
fontsize_label=fontsize_label,
fontsize_ticks=fontsize_ticks,
fontsize_legend=fontsize_legend,
)
# Scientific formatting for axes:
if disable_scientific_axes is None:
pass
elif disable_scientific_axes == "x":
p.xaxis[0].formatter.use_scientific = False
elif disable_scientific_axes == "y":
p.yaxis[0].formatter.use_scientific = False
elif disable_scientific_axes in ["xy", True]:
p.xaxis[0].formatter.use_scientific = False
p.yaxis[0].formatter.use_scientific = False
else:
raise ValueError(
"""Keyword parameter < disable_scientific_axes> only accepts "xy", True, "x", "y" or None."""
)
# If rangetool is used, add it to layout:
if p_rangetool is not None:
p = column(p, p_rangetool)
# Display plot if wanted
if show_figure:
show(p)
# Return as (embeddable) HTML if wanted:
if return_html:
return embedded_html(p)
# Return plot:
return p
def _determine_data_columns(
0
Source : neural.py
with MIT License
from phurwicz
with MIT License
from phurwicz
def _setup_widgets(self):
"""
???+ note "Bokeh widgets for changing hyperparameters through user interaction."
"""
self.epochs_slider = Slider(start=1, end=50, value=1, step=1, title="# epochs")
self.loglr_slider = Slider(
title="learning rate",
start=1.0,
end=7.0,
value=self.__class__.DEFAULT_OPTIM_LOGLR,
step=0.1,
format=FuncTickFormatter(code="return Math.pow(0.1, tick).toFixed(8)"),
)
def update_lr(attr, old, new):
self._dynamic_params["optimizer"]["lr"] = 0.1**self.loglr_slider.value
self.loglr_slider.on_change("value", update_lr)
def _layout_widgets(self):
0
Source : render.py
with MIT License
from sfu-db
with MIT License
from sfu-db
def tweak_figure(fig: Figure) -> None:
"""
Set some common attributes for a figure
"""
fig.grid.grid_line_color = None
fig.axis.axis_line_color = None
fig.axis.major_tick_line_color = None
fig.axis.major_label_text_font_size = "9pt"
fig.axis.major_label_standoff = 0
fig.xaxis.major_label_orientation = np.pi / 3
# truncate axis tick values
format_js = """
if (tick.length > 15) return tick.substring(0, 13) + '...';
else return tick;
"""
fig.xaxis.formatter = FuncTickFormatter(code=format_js)
fig.yaxis.formatter = FuncTickFormatter(code=format_js)
def render_correlation_impact(
0
Source : render.py
with MIT License
from sfu-db
with MIT License
from sfu-db
def box_viz(
df: pd.DataFrame,
x: str,
plot_width: int,
plot_height: int,
box: Box,
y: Optional[str] = None,
ttl_grps: Optional[int] = None,
) -> Panel:
"""
Render a box plot visualization
"""
# pylint: disable=too-many-arguments,too-many-locals,too-many-statements
if y and ttl_grps:
width = 0.7
grp_cnt_stats = {f"{x}_ttl": ttl_grps, f"{x}_shw": len(df)}
title = _make_title(grp_cnt_stats, x, y) if ttl_grps else f"{y} by {x}"
elif y:
width, title = 0.93, f"{y} by {x}"
endpts = [grp.left for grp in df["grp"]] + [df["grp"][len(df) - 1].right]
df["grp"] = df["grp"].astype(str)
else:
width, title = 0.7, f"{x}"
df["x0"], df["x1"] = df.index + 0.2, df.index + 0.8
fig = figure(
plot_width=plot_width,
plot_height=plot_height,
title=title,
toolbar_location=None,
x_range=df["grp"],
)
low = fig.segment(x0="x0", y0="lw", x1="x1", y1="lw", line_color="black", source=df)
ltail = fig.segment(x0="grp", y0="lw", x1="grp", y1="q1", line_color="black", source=df)
lbox = fig.vbar(
x="grp",
width=width,
top="q2",
bottom="q1",
fill_color=box.color,
line_color="black",
source=df,
)
ubox = fig.vbar(
x="grp",
width=width,
top="q3",
bottom="q2",
fill_color=box.color,
line_color="black",
source=df,
)
utail = fig.segment(x0="grp", y0="uw", x1="grp", y1="q3", line_color="black", source=df)
upw = fig.segment(x0="x0", y0="uw", x1="x1", y1="uw", line_color="black", source=df)
df.loc[df["otlrs"].isna(), "otlrs"] = pd.Series(
[[]] * df["otlrs"].isna().sum(), dtype=np.float64
).values
otlrs = [otl for otls in df["otlrs"] for otl in otls]
if otlrs:
gps = [grp for grp, ols in zip(df["grp"], df["otlrs"]) for _ in range(len(ols))]
circ = fig.circle(
x=gps,
y=otlrs,
size=3,
line_color="black",
color="black",
fill_alpha=0.6,
)
fig.add_tools(
HoverTool(
renderers=[circ],
tooltips=[("Outlier", "@y")],
)
)
tooltips = [
("Upper Whisker", "@uw"),
("Upper Quartile", "@q3"),
("Median", "@q2"),
("Lower Quartile", "@q1"),
("Lower Whisker", "@lw"),
]
if y:
lbl = f"{x}" if ttl_grps else "Bin"
tooltips.insert(0, (lbl, "@grp"))
fig.add_tools(
HoverTool(
renderers=[upw, utail, ubox, lbox, ltail, low],
tooltips=tooltips,
)
)
tweak_figure(fig, "box")
if y is None:
fig.xaxis.major_tick_line_color = None
fig.xaxis.major_label_text_font_size = "0pt"
fig.xaxis.axis_label = x if y is not None else None
fig.yaxis.axis_label = x if y is None else y
minw = min(otlrs) if otlrs else np.nan
maxw = max(otlrs) if otlrs else np.nan
_format_axis(fig, min(df["lw"].min(), minw), max(df["uw"].max(), maxw), "y")
if y and not ttl_grps: # format categorical axis tick values
# start by rounding to the length of the largest possible number
round_to = -len(str(max([abs(int(ept)) for ept in endpts])))
ticks = np.round(endpts, round_to)
nticks = len(df) // 5 + 1
show_ticks = [ticks[i] for i in range(len(ticks)) if i % nticks == 0]
while len(set(show_ticks)) != len(show_ticks): # round until show ticks unique
round_to += 1
ticks = np.round(endpts, round_to)
show_ticks = [ticks[i] for i in range(len(ticks)) if i % nticks == 0]
# format the ticks
ticks = [int(tick) if tick.is_integer() else tick for tick in ticks]
ticks = _format_ticks(ticks)
fig.xaxis.ticker = list(range(len(df) + 1))
fig.xaxis.formatter = FuncTickFormatter( # overide bokeh ticks
args={"vals": ticks, "mod": nticks},
code="""
if (index % mod == 0) return vals[index];
return "";
""",
)
tweak_figure(fig, "boxnum")
fig.xaxis.major_label_text_font_size = "10pt"
return Panel(child=row(fig), title="Box Plot")
def latlong_viz(
0
Source : render.py
with MIT License
from sfu-db
with MIT License
from sfu-db
def box_viz_dt(
df: pd.DataFrame,
outx: List[str],
outy: List[float],
x: str,
plot_width: int,
plot_height: int,
y: Optional[str] = None,
grp_cnt_stats: Optional[Dict[str, int]] = None,
timeunit: Optional[str] = None,
) -> Panel:
"""
Render a box plot visualization
"""
# pylint: disable=too-many-arguments,too-many-locals,too-many-statements
if y:
width = 0.7 if grp_cnt_stats else 0.93
title = _make_title(grp_cnt_stats, x, y) if grp_cnt_stats else f"{y} by {x}"
else:
width = 0.7
title = f"{x}"
if len(df) > 10:
plot_width = 39 * len(df)
fig = figure(
tools="",
x_range=list(df["grp"]),
toolbar_location=None,
title=title,
plot_width=plot_width,
plot_height=plot_height,
)
utail = fig.segment(x0="grp", y0="uw", x1="grp", y1="q3", line_color="black", source=df)
ltail = fig.segment(x0="grp", y0="lw", x1="grp", y1="q1", line_color="black", source=df)
ubox = fig.vbar(
x="grp",
width=width,
top="q3",
bottom="q2",
fill_color=CATEGORY20[0],
line_color="black",
source=df,
)
lbox = fig.vbar(
x="grp",
width=width,
top="q2",
bottom="q1",
fill_color=CATEGORY20[0],
line_color="black",
source=df,
)
loww = fig.segment(x0="x0", y0="lw", x1="x1", y1="lw", line_color="black", source=df)
upw = fig.segment(x0="x0", y0="uw", x1="x1", y1="uw", line_color="black", source=df)
if outx:
circ = fig.circle( # pylint: disable=too-many-function-args
outx, outy, size=3, line_color="black", color=CATEGORY20[6], fill_alpha=0.6
)
fig.add_tools(
HoverTool(
renderers=[circ],
tooltips=[("Outlier", "@y")],
)
)
tooltips = [
("Upper Whisker", "@uw"),
("Upper Quartile", "@q3"),
("Median", "@q2"),
("Lower Quartile", "@q1"),
("Lower Whisker", "@lw"),
]
if grp_cnt_stats is None and y is not None:
lbl = timeunit if timeunit else "Bin"
tooltips.insert(0, (lbl, "@grp"))
fig.add_tools(
HoverTool(
renderers=[upw, utail, ubox, lbox, ltail, loww],
tooltips=tooltips,
point_policy="follow_mouse",
)
)
tweak_figure(fig, "box")
if y is None:
fig.xaxis.major_tick_line_color = None
fig.xaxis.major_label_text_font_size = "0pt"
fig.xaxis.axis_label = x if y is not None else None
fig.yaxis.axis_label = x if y is None else y
minw = min(outy) if outy else np.nan
maxw = max(outy) if outy else np.nan
_format_axis(fig, min(df["lw"].min(), minw), max(df["uw"].max(), maxw), "y")
if not grp_cnt_stats and y and not timeunit: # format categorical axis tick values
endpts = list(df["lb"]) + [df.iloc[len(df) - 1]["ub"]]
# start by rounding to the length of the largest possible number
round_to = -len(str(max([abs(int(ept)) for ept in endpts])))
ticks = np.round(endpts, round_to)
nticks = len(df) // 5 + 1
show_ticks = [ticks[i] for i in range(len(ticks)) if i % nticks == 0]
while len(set(show_ticks)) != len(show_ticks): # round until show ticks unique
round_to += 1
ticks = np.round(endpts, round_to)
show_ticks = [ticks[i] for i in range(len(ticks)) if i % nticks == 0]
# format the ticks
ticks = [int(tick) if tick.is_integer() else tick for tick in ticks]
ticks = _format_ticks(ticks)
fig.xaxis.ticker = list(range(len(df) + 1))
fig.xaxis.formatter = FuncTickFormatter( # overide bokeh ticks
args={"vals": ticks, "mod": nticks},
code="""
if (index % mod == 0) return vals[index];
return "";
""",
)
tweak_figure(fig, "boxnum")
fig.xaxis.major_label_text_font_size = "10pt"
if timeunit == "Week of":
fig.xaxis.axis_label = x + ", the week of"
return Panel(child=row(fig), title="Box Plot")
def line_viz(
0
Source : render.py
with MIT License
from sfu-db
with MIT License
from sfu-db
def heatmap_viz(
df: pd.DataFrame,
x: str,
y: str,
grp_cnt_stats: Dict[str, int],
plot_width: int,
plot_height: int,
) -> Panel:
"""
Render a heatmap
"""
# pylint: disable=too-many-arguments
title = _make_title(grp_cnt_stats, x, y)
source = ColumnDataSource(data=df)
palette = RDBU[(len(RDBU) // 2 - 1) :]
mapper = LinearColorMapper(palette=palette, low=df["cnt"].min() - 0.01, high=df["cnt"].max())
if grp_cnt_stats[f"{x}_shw"] > 60:
plot_width = 16 * grp_cnt_stats[f"{x}_shw"]
if grp_cnt_stats[f"{y}_shw"] > 10:
plot_height = 70 + 18 * grp_cnt_stats[f"{y}_shw"]
fig = figure(
x_range=sorted(list(set(df[x]))),
y_range=sorted(list(set(df[y]))),
toolbar_location=None,
tools=[],
x_axis_location="below",
title=title,
plot_width=plot_width,
plot_height=plot_height,
)
renderer = fig.rect(
x=x,
y=y,
width=1,
height=1,
source=source,
line_color=None,
fill_color=transform("cnt", mapper),
)
color_bar = ColorBar(
color_mapper=mapper,
location=(0, 0),
ticker=BasicTicker(desired_num_ticks=7),
formatter=PrintfTickFormatter(format="%d"),
)
fig.add_tools(
HoverTool(
tooltips=[
(x, f"@{{{x}}}"),
(y, f"@{{{y}}}"),
("Count", "@cnt"),
],
mode="mouse",
renderers=[renderer],
)
)
fig.add_layout(color_bar, "right")
tweak_figure(fig, "heatmap")
fig.yaxis.formatter = FuncTickFormatter(
code="""
if (tick.length > 15) return tick.substring(0, 14) + '...';
else return tick;
"""
)
return Panel(child=fig, title="Heat Map")
def dt_line_viz(
0
Source : utils.py
with MIT License
from sfu-db
with MIT License
from sfu-db
def tweak_figure(
fig: Figure,
ptype: Optional[str] = None,
show_yticks: bool = False,
max_lbl_len: int = 15,
) -> None:
"""
Set some common attributes for a figure
"""
fig.axis.major_label_text_font_size = "9pt"
fig.title.text_font_size = "10pt"
fig.axis.minor_tick_line_color = "white"
if ptype in ["pie", "qq", "heatmap"]:
fig.ygrid.grid_line_color = None
if ptype in ["bar", "pie", "hist", "kde", "qq", "heatmap", "line"]:
fig.xgrid.grid_line_color = None
if ptype in ["bar", "hist", "line"] and not show_yticks:
fig.ygrid.grid_line_color = None
fig.yaxis.major_label_text_font_size = "0pt"
fig.yaxis.major_tick_line_color = None
if ptype in ["bar", "nested", "stacked", "heatmap", "box"]:
fig.xaxis.major_label_orientation = np.pi / 3
fig.xaxis.formatter = FuncTickFormatter(
code="""
if (tick.length > %d) return tick.substring(0, %d-2) + '...';
else return tick;
"""
% (max_lbl_len, max_lbl_len)
)
if ptype in ["nested", "stacked", "box"]:
fig.xgrid.grid_line_color = None
if ptype in ["nested", "stacked"]:
fig.y_range.start = 0
fig.x_range.range_padding = 0.03
if ptype in ["line", "boxnum"]:
fig.min_border_right = 20
fig.xaxis.major_label_standoff = 7
fig.xaxis.major_label_orientation = 0
fig.xaxis.major_tick_line_color = None
def _format_ticks(ticks: List[float]) -> List[str]:
0
Source : widgets.py
with MIT License
from smartyal
with MIT License
from smartyal
def __init_figure(self):
"""
initialize the time series widget, plot the lines, create controls like buttons and menues
also hook the callbacks
"""
self.hoverCounter = 0
self.newHover = None
self.hoverTool = None # forget the old hovers
self.showBackgrounds = False
self.showThresholds = False
self.showMotifs = False
self.showScores = False
self.buttonWidth = 70
#layoutControls = []# this will later be applied to layout() function
settings = self.server.get_settings()
mirror = self.server.get_mirror()
if "width" in settings:
self.width = settings["width"]
if "height" in settings:
self.height = settings["height"]
"""
#set the theme
if settings["theme"] == "dark":
self.curdoc().theme = Theme(json=themes.darkTheme)
self.lineColors = themes.darkLineColors
self.plot.xaxis.major_label_text_color = themes.darkTickColor
else:
self.curdoc().theme = Theme(json=themes.whiteTheme)
self.lineColors = themes.whiteLineColors
self.plot.xaxis.major_label_text_color = themes.whiteTickColor
"""
#self.cssClasses = {"button":"button_21","groupButton":"group_button_21","multiSelect":"multi_select_21"}
#self.cssClasses = {"button": "button_21_sm", "groupButton": "group_button_21_sm", "multiSelect": "multi_select_21_sm"}
#self.layoutSettings = {"controlPosition":"bottom"} #support right and bottom, the location of the buttons and tools
#initial values
try:
self.rangeStart = date2secs(settings["startTime"])*1000
self.rangeEnd = date2secs(settings["endTime"])*1000
except:
self.rangeStart = None
self.rangeEnd = None
self.logger.error("range start, end error, use default full")
#create figure
"""
the creation of the figure was reworked as this is a work around for a well known bug (in 1.04), see here
https://github.com/bokeh/bokeh/issues/7497
it's a bokeh problem with internal sync problems of frontend and backend, so what we do now is:
1) use toolbar_location = None to avoid auto-creation of toolbar
2) create tools by hand
3) assign them to the figure with add_tools()
4) create a toolbar and add it to the layout by hand
"""
if self.server.get_mirror()["panOnlyX"][".properties"]["value"]==True:
self.wheelZoomTool = WheelZoomTool(dimensions="width")
self.panTool = PanTool(dimensions="width")
else:
self.wheelZoomTool = WheelZoomTool()#dimensions="width")
self.panTool = PanTool()#dimensions="width")
tools = [self.wheelZoomTool, self.panTool]
"""
self.wheelZoomTool = WheelZoomTool()
self.wheelZoomToolX = WheelZoomTool(dimensions = "width")
self.panTool = PanTool()
tools = [self.wheelZoomTool,self.wheelZoomToolX,self.panTool]
"""
if settings["hasAnnotation"] == True:
self.boxSelectTool = BoxSelectTool(dimensions="width")
tools.append(self.boxSelectTool)
elif settings["hasThreshold"] == True:
self.boxSelectTool = BoxSelectTool(dimensions="height")
tools.append(self.boxSelectTool)
tools.append(ResetTool())
self.freeZoomTool = BoxZoomTool()
tools.append(self.freeZoomTool)
if "yAxisType" in mirror and mirror ["yAxisType"][".properties"]["value"]=="log":
yAxisType = "log"
else:
yAxisType = "linear"
if "xAxisType" in mirror and mirror ["xAxisType"][".properties"]["value"]=="number":
if yAxisType == "log":
fig = figure(toolbar_location=None, plot_height=self.height,
plot_width=self.width,
sizing_mode="scale_width",
x_range=(0,1),y_axis_type=yAxisType)
else:
fig = figure(toolbar_location=None, plot_height=self.height,
plot_width=self.width,
sizing_mode="scale_width",
x_range=(0,1),y_axis_type=yAxisType,y_range=Range1d())
else:
if yAxisType == "log":
fig = figure(toolbar_location=None, plot_height=self.height,
plot_width=self.width,
sizing_mode="scale_width",
x_axis_type='datetime',x_range=(0,1),y_axis_type=yAxisType)
else:
fig = figure(toolbar_location=None, plot_height=self.height,
plot_width=self.width,
sizing_mode="scale_width",
x_axis_type='datetime',x_range=(0,1),y_axis_type=yAxisType,y_range=Range1d())
self.plot = fig
# set the theme
if settings["theme"] == "dark":
self.curdoc().theme = Theme(json=themes.darkTheme)
self.lineColors = themes.darkLineColors
self.plot.xaxis.major_label_text_color = themes.darkTickColor
self.plot.yaxis.major_label_text_color = themes.darkTickColor
else:
self.curdoc().theme = Theme(json=themes.whiteTheme)
self.lineColors = themes.whiteLineColors
self.plot.xaxis.major_label_text_color = themes.whiteTickColor
self.plot.yaxis.major_label_text_color = themes.whiteTickColor
#b1 = date2secs(datetime.datetime(2015,2,13,3,tzinfo=pytz.UTC))*1000
#b2 = date2secs(datetime.datetime(2015,2,13,4,tzinfo=pytz.UTC))*1000
#wid = 20*60*1000 # 20 min
#self.boxData = ColumnDataSource({'x': [b1,b2], 'y':[0,0],'width': [5, 5],'height':[300,300],"alpha":[1,1,0.2]})
#self.boxRect = self.plot.rect(x="x", y="y", width="width", height="height",source=self.boxData)
#self.boxRect = self.plot.rect('x', 'y', 'width', 'height', source=self.boxData,width_units="screen")#, height_units="screen")#, height_units="screen")
self.boxModifierTool=BoxEditTool( renderers=[],num_objects=0,empty_value=0.1)#,dimensions="width")
self.box_modifier_init()
#self.box_modifier_show()
# possible attribures to boxedittool:
# custom_icon, custom_tooltip, dimensions, empty_value, js_event_callbacks, js_property_callbacks, name, num_objects, renderers, subscribed_events
#self.plot.add_layout(self.boxRect)
#self.boxModifierRect.data_source.on_change("selected",self.box_cb)
#self.boxRect.data_source.on_change("active", self.box_cb_2)
tools.append(self.boxModifierTool)
for tool in tools:
fig.add_tools(tool) # must assign them to the layout to have the actual use hooked
toolBarBox = ToolbarBox() #we need the strange creation of the tools to avoid the toolbar to disappear after
# reload of widget, then drawing an annotations (bokeh bug?)
toolBarBox.toolbar = Toolbar(tools=tools,active_inspect=None,active_scroll=self.wheelZoomTool,active_drag = None)
#active_inspect = [crosshair],
# active_drag = # here you can assign the defaults
# active_scroll = # wheel_zoom sometimes is not working if it is set here
# active_tap
toolBarBox.toolbar_location = "right"
toolBarBox.toolbar.logo = None # no bokeh logo
self.tools = toolBarBox
self.toolBarBox = toolBarBox
if "xAxisType" in mirror and mirror["xAxisType"][".properties"]["value"]=="number":
if "xAxisUnit" in mirror:
self.plot.xaxis.formatter = FuncTickFormatter(code = """
let x=tick.toString();
return x + " %s";
"""%mirror['xAxisUnit']['.properties']['value'])
else:
#no formatter
pass
else:
self.plot.xaxis.formatter = FuncTickFormatter(code = """
let local = moment(tick).tz('%s');
let datestring = local.format();
return datestring.slice(0,-6);
"""%settings["timeZone"])
self.plot.xaxis.ticker = DatetimeTicker(desired_num_ticks=5)# give more room for the date time string (default was 6)
self.plot.xgrid.ticker = self.plot.xaxis.ticker
self.build_second_y_axis()
self.show_hide_scroll_label() #it must be created at startup and then visible=True/False, the later add_layout did not work
self.refresh_plot()
#hook in the callback of the figure
self.plot.x_range.on_change('start', self.range_cb)
self.plot.x_range.on_change('end', self.range_cb)
self.plot.on_event(events.Pan, self.event_cb)
self.plot.on_event(events.PanStart, self.event_cb)
self.plot.on_event(events.PanEnd, self.event_cb)
self.plot.on_event(events.LODEnd, self.event_cb)
self.plot.on_event(events.Reset, self.event_cb)
self.plot.on_event(events.SelectionGeometry, self.event_cb)
self.plot.on_event(events.Tap,self.event_cb)
#self.plot.on_event(events.MouseWheel, self.mouse_cb)
#make the controls
layoutControls =[]
#Annotation drop down
if 0: #no drop down for now
labels=[]
if settings["hasAnnotation"] == True:
labels = settings["tags"]
labels.append("-erase-")
if settings["hasThreshold"] == True:
labels.extend(["threshold","-erase threshold-"])
if labels:
menu = [(label,label) for label in labels]
self.annotationDropDown = Dropdown(label="Annotate: "+str(labels[0]), menu=menu,width=self.buttonWidth,css_classes = ['dropdown_21'])
self.currentAnnotationTag = labels[0]
self.annotationDropDown.on_change('value', self.annotation_drop_down_on_change_cb)
#self.annotation_drop_down_on_change_cb() #call it to set the box select tool right and the label
layoutControls.append(self.annotationDropDown)
"""
currently disabled
# show Buttons
# initially everything is disabled
# check background, threshold, annotation, streaming
self.showGroupLabels = []
self.showGroupLabelsDisplay=[]
if self.server.get_settings()["hasAnnotation"] == True:
self.showGroupLabels.append("Annotation")
self.showGroupLabelsDisplay.append("Anno")
if self.server.get_settings()["background"]["hasBackground"]:
self.showGroupLabels.append("Background")
self.showGroupLabelsDisplay.append("Back")
self.showBackgrounds = False # initially off
if self.server.get_settings()["hasThreshold"] == True:
self.showGroupLabels.append("Threshold")
self.showGroupLabelsDisplay.append("Thre")
self.showThresholds = False # initially off
if self.server.get_settings()["hasStreaming"] == True:
self.showGroupLabels.append("Streaming")
self.showGroupLabelsDisplay.append("Stream")
self.streamingMode = False # initially off
self.showGroup = CheckboxButtonGroup(labels=self.showGroupLabelsDisplay)
self.showGroup.on_change("active",self.show_group_on_click_cb)
layoutControls.append(row(self.showGroup))
"""
#make the custom buttons
buttonControls = []
self.customButtonsInstances = []
if "buttons" in settings:
self.logger.debug("create user buttons")
#create the buttons
for entry in settings["buttons"]:
button = Button(label=entry["name"],width=self.buttonWidth)#,css_classes=['button_21'])
instance = self.ButtonCb(self,entry["targets"])
button.on_click(instance.cb)
buttonControls.append(button)
self.customButtonsInstances.append(instance)
#make the debug button
if "hasReloadButton" in self.server.get_settings():
if self.server.get_settings()["hasReloadButton"] == True:
#we must create a reload button
button = Button(label="reload",width=self.buttonWidth)#, css_classes=['button_21'])
button.on_click(self.reset_all)
buttonControls.append(button)
if 0: # turn this helper button on to put some debug code
self.debugButton= Button(label="debug")
self.debugButton.on_click(self.debug_button_cb)
self.debugButton2 = Button(label="debug2")
self.debugButton2.on_click(self.debug_button_2_cb)
buttonControls.append(self.debugButton)
buttonControls.append(self.debugButton2)
layoutControls.extend(buttonControls)
#build the layout
self.layout = layout([row(children=[self.plot, self.tools], sizing_mode="fixed")], row(layoutControls, width=int(self.width*0.6),sizing_mode="scale_width"))
#self.layout = layout([row(children=[self.plot, self.tools], sizing_mode="fixed")])
if self.server.get_settings()["hasAnnotation"] == True:
self.init_annotations() # we create all annotations that we have into self.annotations
if "hasEvents" in self.server.get_settings() and self.server.get_settings()["hasEvents"] == True:
self.init_events()
def init_additional_elements(self):