Here are the examples of the python api bokeh.transform.factor_cmap taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
11 Examples
3
View Source File : test_transform.py
License : MIT License
Project Creator : rthorst
License : MIT License
Project Creator : rthorst
def test_basic(self):
t = bt.factor_cmap("foo", ["red", "green"], ["foo", "bar"], start=1, end=2, nan_color="pink")
assert isinstance(t, dict)
assert set(t) == {"field", "transform"}
assert t['field'] == "foo"
assert isinstance(t['transform'], CategoricalColorMapper)
assert t['transform'].palette == ["red", "green"]
assert t['transform'].factors == ["foo", "bar"]
assert t['transform'].start == 1
assert t['transform'].end == 2
assert t['transform'].nan_color == "pink"
def test_defaults(self):
3
View Source File : test_transform.py
License : MIT License
Project Creator : rthorst
License : MIT License
Project Creator : rthorst
def test_defaults(self):
t = bt.factor_cmap("foo", ["red", "green"], ["foo", "bar"])
assert isinstance(t, dict)
assert set(t) == {"field", "transform"}
assert t['field'] == "foo"
assert isinstance(t['transform'], CategoricalColorMapper)
assert t['transform'].palette == ["red", "green"]
assert t['transform'].factors == ["foo", "bar"]
assert t['transform'].start == 0
assert t['transform'].end is None
assert t['transform'].nan_color == "gray"
class Test_factor_hatch(object):
0
View Source File : html_reporting.py
License : Apache License 2.0
Project Creator : allegroai
License : Apache License 2.0
Project Creator : allegroai
def report_html_periodic_table(logger, iteration=0):
# type: (Logger, int) -> ()
"""
reporting interactive (html) of periodic table to debug samples section
:param logger: The task.logger to use for sending the plots
:param iteration: The iteration number of the current reports
"""
output_file("periodic.html")
periods = ["I", "II", "III", "IV", "V", "VI", "VII"]
groups = [str(x) for x in range(1, 19)]
autompg_clean = elements.copy()
autompg_clean["atomic mass"] = autompg_clean["atomic mass"].astype(str)
autompg_clean["group"] = autompg_clean["group"].astype(str)
autompg_clean["period"] = [periods[x - 1] for x in autompg_clean.period]
autompg_clean = autompg_clean[autompg_clean.group != "-"]
autompg_clean = autompg_clean[autompg_clean.symbol != "Lr"]
autompg_clean = autompg_clean[autompg_clean.symbol != "Lu"]
cmap = {
"alkali metal": "#a6cee3",
"alkaline earth metal": "#1f78b4",
"metal": "#d93b43",
"halogen": "#999d9a",
"metalloid": "#e08d49",
"noble gas": "#eaeaea",
"nonmetal": "#f1d4Af",
"transition metal": "#599d7A",
}
source = ColumnDataSource(autompg_clean)
p = figure(
plot_width=900,
plot_height=500,
title="Periodic Table (omitting LA and AC Series)",
x_range=groups,
y_range=list(reversed(periods)),
toolbar_location=None,
tools="hover",
)
p.rect(
"group",
"period",
0.95,
0.95,
source=source,
fill_alpha=0.6,
legend_label="metal",
color=factor_cmap(
"metal", palette=list(cmap.values()), factors=list(cmap.keys())
),
)
text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
x = dodge("group", -0.4, range=p.x_range)
r = p.text(x=x, y="period", text="symbol", **text_props)
r.glyph.text_font_style = "bold"
r = p.text(
x=x, y=dodge("period", 0.3, range=p.y_range), text="atomic number", **text_props
)
r.glyph.text_font_size = "8pt"
r = p.text(
x=x, y=dodge("period", -0.35, range=p.y_range), text="name", **text_props
)
r.glyph.text_font_size = "5pt"
r = p.text(
x=x, y=dodge("period", -0.2, range=p.y_range), text="atomic mass", **text_props
)
r.glyph.text_font_size = "5pt"
p.text(
x=["3", "3"],
y=["VI", "VII"],
text=["LA", "AC"],
text_align="center",
text_baseline="middle",
)
p.hover.tooltips = [
("Name", "@name"),
("Atomic number", "@{atomic number}"),
("Atomic mass", "@{atomic mass}"),
("Type", "@metal"),
("CPK color", "$color[hex, swatch]:CPK"),
("Electronic configuration", "@{electronic configuration}"),
]
p.outline_line_color = None
p.grid.grid_line_color = None
p.axis.axis_line_color = None
p.axis.major_tick_line_color = None
p.axis.major_label_standoff = 0
p.legend.orientation = "horizontal"
p.legend.location = "top_center"
save(p)
logger.report_media("html", "periodic_html", iteration=iteration, local_path="periodic.html")
def report_html_groupby(logger, iteration=0):
0
View Source File : html_reporting.py
License : Apache License 2.0
Project Creator : allegroai
License : Apache License 2.0
Project Creator : allegroai
def report_html_groupby(logger, iteration=0):
# type: (Logger, int) -> ()
"""
reporting bokeh groupby (html) to debug samples section
:param logger: The task.logger to use for sending the plots
:param iteration: The iteration number of the current reports
"""
output_file("bar_pandas_groupby_nested.html")
bokeh_df.cyl = bokeh_df.cyl.astype(str)
bokeh_df.yr = bokeh_df.yr.astype(str)
group = bokeh_df.groupby(by=["cyl", "mfr"])
index_cmap = factor_cmap(
"cyl_mfr", palette=Spectral5, factors=sorted(bokeh_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
save(p)
logger.report_media(
"html",
"pandas_groupby_nested_html",
iteration=iteration,
local_path="bar_pandas_groupby_nested.html",
)
def report_html_graph(logger, iteration=0):
0
View Source File : container.py
License : BSD 3-Clause "New" or "Revised" License
Project Creator : griquelme
License : BSD 3-Clause "New" or "Revised" License
Project Creator : griquelme
def pca_scores(self, x_pc: int = 1, y_pc: int = 2, hue: str = _sample_class,
ignore_classes: Optional[List[str]] = None,
show_order: bool = False, scaling: Optional[str] = None,
normalization: Optional[str] = None, draw: bool = True,
fig_params: Optional[dict] = None,
scatter_params: Optional[dict] = None
) -> bokeh.plotting.Figure:
"""
plots PCA scores
Parameters
----------
x_pc: int
Principal component number to plot along X axis.
y_pc: int
Principal component number to plot along Y axis.
hue: {"class", "type", "batch"}
How to color samples. "class" color points according to sample
class, "type" color points according to the sample type
assigned in the mapping and "batch" uses batch information. Samples
classes without a mapping are not shown in the plot
ignore_classes : list[str], optional
classes in the data to ignore to build the PCA model.
show_order: bool
add a label with the run order.
scaling: {`autoscaling`, `rescaling`, `pareto`}, optional
scaling method.
normalization: {`sum`, `max`, `euclidean`}, optional
normalization method
draw: bool
If True calls bokeh.plotting.show on fig.
fig_params: dict, optional
Optional parameters to pass to bokeh figure
scatter_params: dict, optional
Optional parameters to pass to bokeh scatter plot.
Returns
-------
bokeh.plotting.Figure.
"""
default_fig_params = {"aspect_ratio": 1}
if fig_params is None:
fig_params = default_fig_params
else:
default_fig_params.update(fig_params)
fig_params = default_fig_params
default_scatter_params = {"size": 6}
if scatter_params is None:
scatter_params = default_scatter_params
else:
default_scatter_params.update(scatter_params)
scatter_params = default_scatter_params
tooltips = [(_sample_class, "@{}".format(_sample_class)),
(_sample_order, "@{}".format(_sample_order)),
(_sample_batch, "@{}".format(_sample_batch)),
(_sample_id, "@{}".format(_sample_id))]
fig = bokeh.plotting.figure(tooltips=tooltips, **fig_params)
x_name = "PC" + str(x_pc)
y_name = "PC" + str(y_pc)
n_comps = max(x_pc, y_pc)
score, _, variance, total_var = \
self._data_container.metrics.pca(n_components=n_comps,
ignore_classes=ignore_classes,
normalization=normalization,
scaling=scaling)
score = score.join(self._data_container.sample_metadata)
if hue == _sample_type:
rev_map = _reverse_mapping(self._data_container.mapping)
score[_sample_type] = (score[_sample_class]
.apply(lambda x: rev_map.get(x)))
score = score[~pd.isna(score[_sample_type])]
elif hue == _sample_batch:
score[_sample_batch] = score[_sample_batch].astype(str)
# setup the colors
unique_values = score[hue].unique().astype(str)
score = ColumnDataSource(score)
cmap = Category10[10]
palette = cmap * (int(unique_values.size / len(cmap)) + 1)
palette = palette[:unique_values.size]
# TODO: Category10_3 should be in a parameter file
fig.scatter(source=score, x=x_name, y=y_name,
color=factor_cmap(hue, palette, unique_values),
legend_group=hue, **scatter_params)
# figure appearance
x_label = x_name + " ({:.1f} %)"
x_label = x_label.format(variance[x_pc - 1] * 100 / total_var)
y_label = y_name + " ({:.1f} %)"
y_label = y_label.format(variance[y_pc - 1] * 100 / total_var)
fig.xaxis.axis_label = x_label
fig.yaxis.axis_label = y_label
fig.yaxis.axis_label_text_font_style = "bold"
fig.xaxis.axis_label_text_font_style = "bold"
if show_order:
labels = LabelSet(x=x_name, y=y_name, text=_sample_order,
level="glyph", x_offset=3, y_offset=3,
source=score, render_mode="canvas",
text_font_size="8pt")
fig.add_layout(labels)
if draw:
bokeh.plotting.show(fig)
return fig
def pca_loadings(self, x_pc=1, y_pc=2, scaling: Optional[str] = None,
0
View Source File : container.py
License : BSD 3-Clause "New" or "Revised" License
Project Creator : griquelme
License : BSD 3-Clause "New" or "Revised" License
Project Creator : griquelme
def feature(self, ft: str, hue: str = _sample_class,
ignore_classes: Optional[List[str]] = None,
draw: bool = True,
fig_params: Optional[dict] = None,
scatter_params: Optional[dict] = None) -> bokeh.plotting.Figure:
"""
plots a feature intensity as a function of the run order.
Parameters
----------
ft: str
Feature to plot. Index of feature in `feature_metadata`
hue: {"class", "type"}
ignore_classes : list[str], optional
exclude samples from the listed classes in the plot
draw: bool
If True calls bokeh.plotting.show on figure.
fig_params: dict
key-value parameters to pass to bokeh figure
scatter_params: dict
key-value parameters to pass to bokeh circle
Returns
-------
bokeh.plotting.Figure
"""
default_fig_params = {"aspect_ratio": 1.5}
if fig_params is None:
fig_params = default_fig_params
else:
default_fig_params.update(fig_params)
fig_params = default_fig_params
if scatter_params is None:
scatter_params = dict()
if ignore_classes is None:
ignore_classes = list()
source = (self._data_container.sample_metadata
.join(self._data_container.data_matrix[ft]))
ignore_samples = source[_sample_class].isin(ignore_classes)
source = source[~ignore_samples]
if hue == _sample_type:
rev_map = _reverse_mapping(self._data_container.mapping)
source[_sample_type] = (source[_sample_class]
.apply(lambda x: rev_map.get(x)))
source = source[~source[_sample_type].isna()]
elif hue == _sample_batch:
source[_sample_batch] = source[_sample_batch].astype(str)
# setup the colors
unique_values = source[hue].unique().astype(str)
cmap = Category10[10]
palette = cmap * (int(unique_values.size / len(cmap)) + 1)
palette = palette[:unique_values.size]
source = ColumnDataSource(source)
tooltips = [(_sample_class, "@{}".format(_sample_class)),
(_sample_order, "@{}".format(_sample_order)),
(_sample_batch, "@{}".format(_sample_batch)),
(_sample_id, "@{}".format(_sample_id))]
fig = bokeh.plotting.figure(tooltips=tooltips, **fig_params)
cmap_factor = factor_cmap(hue, palette, unique_values)
fig.scatter(source=source, x=_sample_order, y=ft, color=cmap_factor,
legend_group=hue, **scatter_params)
fig.xaxis.axis_label = "Run order"
fig.yaxis.axis_label = "{} intensity [au]".format(ft)
fig.yaxis.axis_label_text_font_style = "bold"
fig.yaxis.formatter.precision = 2
fig.xaxis.formatter.precision = 2
fig.xaxis.axis_label_text_font_style = "bold"
if draw:
bokeh.plotting.show(fig)
return fig
class SeabornPlotMethods(object): # pragma: no cover
0
View Source File : plotting.py
License : Apache License 2.0
Project Creator : hms-dbmi
License : Apache License 2.0
Project Creator : hms-dbmi
def plot_hail_file_metadata(t_path: str) -> Optional[Union[Grid, Tabs, bokeh.plotting.Figure]]:
"""
Takes path to hail Table or MatrixTable (gs://bucket/path/hail.mt), outputs Grid or Tabs, respectively
Or if an unordered Table is provided, a Figure with file sizes is output
If metadata file or rows directory is missing, returns None
"""
panel_size = 600
subpanel_size = 150
files = hl.hadoop_ls(t_path)
rows_file = [x['path'] for x in files if x['path'].endswith('rows')]
entries_file = [x['path'] for x in files if x['path'].endswith('entries')]
# cols_file = [x['path'] for x in files if x['path'].endswith('cols')]
success_file = [x['modification_time'] for x in files if x['path'].endswith('SUCCESS')]
data_type = 'Table'
metadata_file = [x['path'] for x in files if x['path'].endswith('metadata.json.gz')]
if not metadata_file:
warnings.warn('No metadata file found. Exiting...')
return None
with hl.hadoop_open(metadata_file[0], 'rb') as f:
overall_meta = json.loads(f.read())
rows_per_partition = overall_meta['components']['partition_counts']['counts']
if not rows_file:
warnings.warn('No rows directory found. Exiting...')
return None
rows_files = hl.hadoop_ls(rows_file[0])
if entries_file:
data_type = 'MatrixTable'
rows_file = [x['path'] for x in rows_files if x['path'].endswith('rows')]
rows_files = hl.hadoop_ls(rows_file[0])
row_partition_bounds, row_file_sizes = get_rows_data(rows_files)
total_file_size, row_file_sizes, row_scale = scale_file_sizes(row_file_sizes)
if not row_partition_bounds:
warnings.warn('Table is not partitioned. Only plotting file sizes')
row_file_sizes_hist, row_file_sizes_edges = np.histogram(row_file_sizes, bins=50)
p_file_size = figure(plot_width=panel_size, plot_height=panel_size)
p_file_size.quad(right=row_file_sizes_hist, left=0, bottom=row_file_sizes_edges[:-1],
top=row_file_sizes_edges[1:], fill_color="#036564", line_color="#033649")
p_file_size.yaxis.axis_label = f'File size ({row_scale}B)'
return p_file_size
all_data = {
'partition_widths': [-1 if x[0] != x[2] else x[3] - x[1] for x in row_partition_bounds],
'partition_bounds': [f'{x[0]}:{x[1]}-{x[2]}:{x[3]}' for x in row_partition_bounds],
'spans_chromosome': ['Spans chromosomes' if x[0] != x[2] else 'Within chromosome' for x in row_partition_bounds],
'row_file_sizes': row_file_sizes,
'row_file_sizes_human': [f'{x:.1f} {row_scale}B' for x in row_file_sizes],
'rows_per_partition': rows_per_partition,
'index': list(range(len(rows_per_partition)))
}
if entries_file:
entries_rows_files = hl.hadoop_ls(entries_file[0])
entries_rows_file = [x['path'] for x in entries_rows_files if x['path'].endswith('rows')]
if entries_rows_file:
entries_files = hl.hadoop_ls(entries_rows_file[0])
entry_partition_bounds, entry_file_sizes = get_rows_data(entries_files)
total_entry_file_size, entry_file_sizes, entry_scale = scale_file_sizes(entry_file_sizes)
all_data['entry_file_sizes'] = entry_file_sizes
all_data['entry_file_sizes_human'] = [f'{x:.1f} {entry_scale}B' for x in row_file_sizes]
title = f'{data_type}: {t_path}'
msg = f"Rows: {sum(all_data['rows_per_partition']):,} < br/>Partitions: {len(all_data['rows_per_partition']):,} < br/>Size: {total_file_size} < br/>"
if success_file[0]:
msg += success_file[0]
source = ColumnDataSource(pd.DataFrame(all_data))
p = figure(tools=TOOLS, plot_width=panel_size, plot_height=panel_size)
p.title.text = title
p.xaxis.axis_label = 'Number of rows'
p.yaxis.axis_label = f'File size ({row_scale}B)'
color_map = factor_cmap('spans_chromosome', palette=Spectral8,
factors=list(set(all_data['spans_chromosome'])))
p.scatter('rows_per_partition', 'row_file_sizes', color=color_map, legend='spans_chromosome', source=source)
p.legend.location = 'bottom_right'
p.select_one(HoverTool).tooltips = [(x, f'@{x}') for x in
('rows_per_partition', 'row_file_sizes_human', 'partition_bounds', 'index')]
p_stats = Div(text=msg)
p_rows_per_partition = figure(x_range=p.x_range, plot_width=panel_size, plot_height=subpanel_size)
p_file_size = figure(y_range=p.y_range, plot_width=subpanel_size, plot_height=panel_size)
rows_per_partition_hist, rows_per_partition_edges = np.histogram(all_data['rows_per_partition'], bins=50)
p_rows_per_partition.quad(top=rows_per_partition_hist, bottom=0, left=rows_per_partition_edges[:-1],
right=rows_per_partition_edges[1:],
fill_color="#036564", line_color="#033649")
row_file_sizes_hist, row_file_sizes_edges = np.histogram(all_data['row_file_sizes'], bins=50)
p_file_size.quad(right=row_file_sizes_hist, left=0, bottom=row_file_sizes_edges[:-1],
top=row_file_sizes_edges[1:], fill_color="#036564", line_color="#033649")
rows_grid = gridplot([[p_rows_per_partition, p_stats], [p, p_file_size]])
if 'entry_file_sizes' in all_data:
title = f'Statistics for {data_type}: {t_path}'
msg = f"Rows: {sum(all_data['rows_per_partition']):,} < br/>Partitions: {len(all_data['rows_per_partition']):,} < br/>Size: {total_entry_file_size} < br/>"
if success_file[0]:
msg += success_file[0]
source = ColumnDataSource(pd.DataFrame(all_data))
panel_size = 600
subpanel_size = 150
p = figure(tools=TOOLS, plot_width=panel_size, plot_height=panel_size)
p.title.text = title
p.xaxis.axis_label = 'Number of rows'
p.yaxis.axis_label = f'File size ({entry_scale}B)'
color_map = factor_cmap('spans_chromosome', palette=Spectral8, factors=list(set(all_data['spans_chromosome'])))
p.scatter('rows_per_partition', 'entry_file_sizes', color=color_map, legend='spans_chromosome', source=source)
p.legend.location = 'bottom_right'
p.select_one(HoverTool).tooltips = [(x, f'@{x}') for x in ('rows_per_partition', 'entry_file_sizes_human', 'partition_bounds', 'index')]
p_stats = Div(text=msg)
p_rows_per_partition = figure(x_range=p.x_range, plot_width=panel_size, plot_height=subpanel_size)
p_rows_per_partition.quad(top=rows_per_partition_hist, bottom=0, left=rows_per_partition_edges[:-1],
right=rows_per_partition_edges[1:],
fill_color="#036564", line_color="#033649")
p_file_size = figure(y_range=p.y_range, plot_width=subpanel_size, plot_height=panel_size)
row_file_sizes_hist, row_file_sizes_edges = np.histogram(all_data['entry_file_sizes'], bins=50)
p_file_size.quad(right=row_file_sizes_hist, left=0, bottom=row_file_sizes_edges[:-1],
top=row_file_sizes_edges[1:], fill_color="#036564", line_color="#033649")
entries_grid = gridplot([[p_rows_per_partition, p_stats], [p, p_file_size]])
return Tabs(tabs=[Panel(child=entries_grid, title='Entries'), Panel(child=rows_grid, title='Rows')])
else:
return rows_grid
def scale_file_sizes(file_sizes):
0
View Source File : _plotting.py
License : GNU Affero General Public License v3.0
Project Creator : kernc
License : GNU Affero General Public License v3.0
Project Creator : 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
View Source File : plot_apple_watch_data.py
License : Apache License 2.0
Project Creator : openPfizer
License : Apache License 2.0
Project Creator : openPfizer
def plot_heart_rate_variability(apple_watch):
"""
Generate swarm-like plots of heart rate variability measures for multiple days
:param apple_watch: data frame of heart rate variability data
:return: None
"""
logger.info('Loading and Plotting Heart Rate Variability Data')
df = apple_watch.load_heart_rate_variability_data()
df = df[(df['start_timestamp'] > START_DATE) & (df['start_timestamp'] < END_DATE)]
df['date'] = list(map(lambda d: d.strftime('%m/%d/%y'), df['start_timestamp']))
df['time'] = list(map(lambda d: d.strftime('%H:%M:%S'), df['start_timestamp']))
dates = list(df['date'].unique())
# remove instantaneous data, bokeh doesn't not like dictionary format
del df['instantaneous_bpm']
source = ColumnDataSource(df)
plot = figure(
width=800,
height=600,
x_range=dates,
x_axis_label='Date',
y_axis_label='Time Between Heart Beats (ms)',
title='Apple Watch Heart Rate Variability (SDNN)',
tools='pan, wheel_zoom, box_zoom, reset, hover',
toolbar_location='above',
sizing_mode='scale_both')
# add color map for dates
dates_cmap = factor_cmap('date', palette=Category20_20, factors=dates)
plot.circle(x='date', y='heart_rate_variability', source=source, size=12, fill_color=dates_cmap)
plot.xaxis.axis_label_text_font_size = "14pt"
plot.xaxis.major_label_text_font_size = "12pt"
plot.yaxis.axis_label_text_font_size = "14pt"
plot.yaxis.major_label_text_font_size = "12pt"
plot.title.text_font_size = '16pt'
# configure hover tool
plot.select_one(HoverTool).tooltips = [
('date', '@date'),
('time', '@time'),
('time interval', '@heart_rate_variability')
]
if SHOW_PLOTS:
show(plot, browser='chrome')
save_plot(plot, 'heart_rate_variability')
# clear output mode for next plot
reset_output()
# save dataframe
df.to_csv('apple_watch_data/heart_rate_variability.csv', index=False)
def plot_resting_heart_rate(apple_watch):
0
View Source File : bokeh_figures.py
License : MIT License
Project Creator : SolarArbiter
License : MIT License
Project Creator : SolarArbiter
def bar(cds, metric):
"""
Create a bar graph comparing a single metric across forecasts.
Parameters
----------
cds : bokeh.models.ColumnDataSource
Metric cds created by :py:func:`solarforecastarbiter.reports.figures.construct_metrics_cds`
metric: str
The metric to plot. This value should be found in cds['metric'].
Returns
-------
data_table : bokeh.widgets.DataTable
""" # NOQA
x_range = np.unique(cds.data['abbrev'])
palette = cycle(PALETTE)
palette = [next(palette) for _ in x_range]
metric_name = datamodel.ALLOWED_METRICS[metric]
view = CDSView(source=cds, filters=[
GroupFilter(column_name='metric', group=metric),
GroupFilter(column_name='category', group='total')
])
# TODO: add units to title
fig = figure(x_range=x_range, width=800, height=200, title=metric_name,
name=f'{metric}_total_bar', toolbar_location='above',
tools='pan,xwheel_zoom,box_zoom,reset,save')
fig.vbar(x='abbrev', top='value', width=0.8,
source=cds, view=view,
line_color='white',
fill_color=factor_cmap('abbrev', palette, factors=x_range))
fig.xgrid.grid_line_color = None
tooltips = [
('Forecast', '@name'),
(metric_name, '@value'),
]
hover = HoverTool(tooltips=tooltips, mode='vline')
# more accurate would be if any single name is longer than each
# name's allotted space. For example, never need to rotate labels
# if forecasts are named A, B, C, D... but quickly need to rotate
# if they have long names.
if len(x_range) > 6:
# pi/4 looks a lot better, but first tick label flows off chart
# and I can't figure out how to add padding in bokeh
fig.xaxis.major_label_orientation = np.pi / 2
fig.width = 800
# add more height to figure so that the names can go somewhere.
fig.height = 400
fig.add_tools(hover)
return fig
def calc_y_start_end(y_min, y_max, pad_factor=1.03):
0
View Source File : plot.py
License : Apache License 2.0
Project Creator : spotify
License : Apache License 2.0
Project Creator : spotify
def _get_color_and_order(self,
data_frame,
color_column,
color_order,
categorical_columns=None):
"""
Returns:
colors: List of hex colors or factor_cmap.
color_order: List of values for each color.
"""
if color_column is None:
colors = [self._chart.style.color_palette.next_color()]
color_order = [None]
else:
# Determine color order or verify integrity of specified order.
if color_order is None:
color_order = sorted(data_frame[color_column].unique())
else:
# Check that all color factors are present in the color order.
if not set(data_frame[color_column].unique()).issubset(
set(color_order)):
raise ValueError("""Color order must include
all unique factors of variable `%s`.""" %
color_column)
next_colors = self._chart.style.color_palette.next_colors(
color_order)
if categorical_columns is None: # Numeric data
colors = next_colors
else:
# # Color column must be in the categorical_columns
# try:
# color_index = categorical_columns.index(color_column)
# color_label = 'factors'
# except ValueError:
# color_label = 'color_column'
# color_index = 0
# raise ValueError(
# '''`color_column` must be present
# in the `categorical_columns`'''
# )
color_label = 'color_column'
color_index = 0
color_order = [str(factor) for factor in color_order]
colors = bokeh.transform.factor_cmap(
color_label,
palette=next_colors,
factors=color_order,
start=color_index,
end=color_index + 1,
)
return colors, color_order
@staticmethod