# Copyright 2015 Bloomberg Finance L.P.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
r"""
|
|
|
|
======
|
|
Pyplot
|
|
======
|
|
|
|
.. currentmodule:: bqplot.pyplot
|
|
|
|
.. autosummary::
|
|
:toctree: _generate/
|
|
|
|
figure
|
|
show
|
|
axes
|
|
|
|
plot
|
|
scatter
|
|
hist
|
|
bar
|
|
ohlc
|
|
geo
|
|
|
|
clear
|
|
close
|
|
current_figure
|
|
|
|
scales
|
|
xlim
|
|
ylim
|
|
|
|
axes
|
|
xlabel
|
|
ylabel
|
|
|
|
"""
|
|
import sys
|
|
from collections import OrderedDict
|
|
from IPython.display import display
|
|
from ipywidgets import VBox
|
|
from ipywidgets import Image as ipyImage
|
|
from numpy import arange, issubdtype, array, column_stack, shape
|
|
from .figure import Figure
|
|
from .scales import Scale, LinearScale, Mercator
|
|
from .axes import Axis
|
|
from .marks import (Lines, Scatter, ScatterGL, Hist, Bars, OHLC, Pie, Map, Image,
|
|
Label, HeatMap, GridHeatMap, topo_load, Boxplot, Bins)
|
|
from .toolbar import Toolbar
|
|
from .interacts import (BrushIntervalSelector, FastIntervalSelector,
|
|
BrushSelector, IndexSelector, MultiSelector,
|
|
LassoSelector)
|
|
from traitlets.utils.sentinel import Sentinel
|
|
import functools
|
|
|
|
SCATTER_SIZE_LIMIT = 10*1000 # above this limit, ScatterGL will be used by default
|
|
|
|
Keep = Sentinel('Keep', 'bqplot.pyplot', '''
|
|
Used in bqplot.pyplot to specify that the same scale should be used for
|
|
a certain dimension.
|
|
''')
|
|
# `_context` object contains the global information for pyplot.
|
|
# `figure`: refers to the current figure to which marks will be added.
|
|
# `scales`: The current set of scales which will be used for drawing a mark. if
|
|
# the scale for an attribute is not present, it is created based on the range
|
|
# type.
|
|
# `scale_registry`: This is a dictionary where the keys are the context
|
|
# names and the values are the set of scales which were used on the last plot
|
|
# in that context. This is useful when switching context.
|
|
# `last_mark`: refers to the last mark that has been plotted.
|
|
# `current_key`: The key for the current context figure. If there is no key,
|
|
# then the value is `None`.
|
|
_context = {
|
|
'figure': None,
|
|
'figure_registry': {},
|
|
'scales': {},
|
|
'scale_registry': {},
|
|
'last_mark': None,
|
|
'current_key': None
|
|
}
|
|
|
|
LINE_STYLE_CODES = OrderedDict([(':', 'dotted'), ('-.', 'dash_dotted'),
|
|
('--', 'dashed'), ('-', 'solid')])
|
|
|
|
COLOR_CODES = {'b': 'blue', 'g': 'green', 'r': 'red', 'c': 'cyan',
|
|
'm': 'magenta', 'y': 'yellow', 'k': 'black'}
|
|
|
|
MARKER_CODES = {'o': 'circle', 'v': 'triangle-down', '^': 'triangle-up',
|
|
's': 'square', 'd': 'diamond', '+': 'cross'}
|
|
|
|
|
|
PY2 = sys.version_info[0] == 2
|
|
|
|
if PY2:
|
|
string_types = basestring,
|
|
else:
|
|
string_types = str,
|
|
|
|
|
|
def hashable(data, v):
|
|
"""Determine whether `v` can be hashed."""
|
|
try:
|
|
data[v]
|
|
except (TypeError, KeyError, IndexError):
|
|
return False
|
|
return True
|
|
|
|
|
|
def show(key=None, display_toolbar=True):
|
|
"""Shows the current context figure in the output area.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
key : hashable, optional
|
|
Any variable that can be used as a key for a dictionary.
|
|
display_toolbar: bool (default: True)
|
|
If True, a toolbar for different mouse interaction is displayed with
|
|
the figure.
|
|
|
|
Raises
|
|
------
|
|
|
|
KeyError
|
|
When no context figure is associated with the provided key.
|
|
|
|
Examples
|
|
--------
|
|
|
|
>>> import numpy as np
|
|
>>> import pyplot as plt
|
|
>>> n = 100
|
|
>>> x = np.arange(n)
|
|
>>> y = np.cumsum(np.random.randn(n))
|
|
>>> plt.plot(x,y)
|
|
>>> plt.show()
|
|
|
|
"""
|
|
if key is None:
|
|
figure = current_figure()
|
|
else:
|
|
figure = _context['figure_registry'][key]
|
|
if display_toolbar:
|
|
if not hasattr(figure, 'pyplot'):
|
|
figure.pyplot = Toolbar(figure=figure)
|
|
figure.pyplot_vbox = VBox([figure, figure.pyplot])
|
|
display(figure.pyplot_vbox)
|
|
else:
|
|
display(figure)
|
|
|
|
|
|
def figure(key=None, fig=None, **kwargs):
|
|
"""Creates figures and switches between figures.
|
|
|
|
If a ``bqplot.Figure`` object is provided via the fig optional argument,
|
|
this figure becomes the current context figure.
|
|
|
|
Otherwise:
|
|
|
|
- If no key is provided, a new empty context figure is created.
|
|
- If a key is provided for which a context already exists, the
|
|
corresponding context becomes current.
|
|
- If a key is provided and no corresponding context exists, a new context
|
|
is reated for that key and becomes current.
|
|
|
|
Besides, optional arguments allow to set or modify Attributes
|
|
of the selected context figure.
|
|
|
|
Parameters
|
|
----------
|
|
key: hashable, optional
|
|
Any variable that can be used as a key for a dictionary
|
|
fig: Figure, optional
|
|
A bqplot Figure
|
|
|
|
"""
|
|
scales_arg = kwargs.pop('scales', {})
|
|
_context['current_key'] = key
|
|
if fig is not None: # fig provided
|
|
_context['figure'] = fig
|
|
if key is not None:
|
|
_context['figure_registry'][key] = fig
|
|
for arg in kwargs:
|
|
setattr(_context['figure'], arg, kwargs[arg])
|
|
else: # no fig provided
|
|
if key is None: # no key provided
|
|
_context['figure'] = Figure(**kwargs)
|
|
else: # a key is provided
|
|
if key not in _context['figure_registry']:
|
|
if 'title' not in kwargs:
|
|
kwargs['title'] = 'Figure' + ' ' + str(key)
|
|
_context['figure_registry'][key] = Figure(**kwargs)
|
|
_context['figure'] = _context['figure_registry'][key]
|
|
for arg in kwargs:
|
|
setattr(_context['figure'], arg, kwargs[arg])
|
|
scales(key, scales=scales_arg)
|
|
# Set the axis reference dictionary. This dictionary contains the mapping
|
|
# from the possible dimensions in the figure to the list of scales with
|
|
# respect to which axes have been drawn for this figure.
|
|
# Used to automatically generate axis.
|
|
if(getattr(_context['figure'], 'axis_registry', None) is None):
|
|
setattr(_context['figure'], 'axis_registry', {})
|
|
return _context['figure']
|
|
|
|
|
|
def close(key):
|
|
"""Closes and unregister the context figure corresponding to the key.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
key: hashable
|
|
Any variable that can be used as a key for a dictionary
|
|
|
|
"""
|
|
figure_registry = _context['figure_registry']
|
|
if key not in figure_registry:
|
|
return
|
|
if _context['figure'] == figure_registry[key]:
|
|
figure()
|
|
fig = figure_registry[key]
|
|
if hasattr(fig, 'pyplot'):
|
|
fig.pyplot.close()
|
|
fig.pyplot_vbox.close()
|
|
fig.close()
|
|
del figure_registry[key]
|
|
del _context['scale_registry'][key]
|
|
|
|
|
|
def _process_data(*kwarg_names):
|
|
"""Helper function to handle data keyword argument
|
|
"""
|
|
def _data_decorator(func):
|
|
@functools.wraps(func)
|
|
def _mark_with_data(*args, **kwargs):
|
|
data = kwargs.pop('data', None)
|
|
if data is None:
|
|
return func(*args, **kwargs)
|
|
else:
|
|
data_args = [data[i] if hashable(data, i) else i for i in args]
|
|
data_kwargs = {
|
|
kw: data[kwargs[kw]] if hashable(data, kwargs[kw]) else kwargs[kw] for kw in set(kwarg_names).intersection(list(kwargs.keys()))
|
|
}
|
|
try:
|
|
# if any of the plots want to use the index_data, they can
|
|
# use it by referring to this attribute.
|
|
data_kwargs['index_data'] = data.index
|
|
except AttributeError as e:
|
|
pass
|
|
kwargs_update = kwargs.copy()
|
|
kwargs_update.update(data_kwargs)
|
|
return func(*data_args, **kwargs_update)
|
|
|
|
return _mark_with_data
|
|
return _data_decorator
|
|
|
|
|
|
def scales(key=None, scales={}):
|
|
"""Creates and switches between context scales.
|
|
|
|
If no key is provided, a new blank context is created.
|
|
|
|
If a key is provided for which a context already exists, the existing
|
|
context is set as the current context.
|
|
|
|
If a key is provided and no corresponding context exists, a new context is
|
|
created for that key and set as the current context.
|
|
|
|
Parameters
|
|
----------
|
|
key: hashable, optional
|
|
Any variable that can be used as a key for a dictionary
|
|
scales: dictionary
|
|
Dictionary of scales to be used in the new context
|
|
|
|
Example
|
|
-------
|
|
|
|
>>> scales(scales={
|
|
>>> 'x': Keep,
|
|
>>> 'color': ColorScale(min=0, max=1)
|
|
>>> })
|
|
|
|
This creates a new scales context, where the 'x' scale is kept from the
|
|
previous context, the 'color' scale is an instance of ColorScale
|
|
provided by the user. Other scales, potentially needed such as the 'y'
|
|
scale in the case of a line chart will be created on the fly when
|
|
needed.
|
|
|
|
Notes
|
|
-----
|
|
Every call to the function figure triggers a call to scales.
|
|
|
|
The `scales` parameter is ignored if the `key` argument is not Keep and
|
|
context scales already exist for that key.
|
|
"""
|
|
old_ctxt = _context['scales']
|
|
if key is None: # No key provided
|
|
_context['scales'] = {_get_attribute_dimension(k): scales[k] if scales[k] is not Keep
|
|
else old_ctxt[_get_attribute_dimension(k)] for k in scales}
|
|
else: # A key is provided
|
|
if key not in _context['scale_registry']:
|
|
_context['scale_registry'][key] = {
|
|
_get_attribute_dimension(k): scales[k]
|
|
if scales[k] is not Keep
|
|
else old_ctxt[_get_attribute_dimension(k)]
|
|
for k in scales
|
|
}
|
|
_context['scales'] = _context['scale_registry'][key]
|
|
|
|
|
|
def xlim(min, max):
|
|
"""Set the domain bounds of the current 'x' scale.
|
|
"""
|
|
return set_lim(min, max, 'x')
|
|
|
|
|
|
def ylim(min, max):
|
|
"""Set the domain bounds of the current 'y' scale.
|
|
"""
|
|
return set_lim(min, max, 'y')
|
|
|
|
|
|
def set_lim(min, max, name):
|
|
"""Set the domain bounds of the scale associated with the provided key.
|
|
|
|
Parameters
|
|
----------
|
|
name: hashable
|
|
Any variable that can be used as a key for a dictionary
|
|
|
|
Raises
|
|
------
|
|
KeyError
|
|
When no context figure is associated with the provided key.
|
|
|
|
"""
|
|
scale = _context['scales'][_get_attribute_dimension(name)]
|
|
scale.min = min
|
|
scale.max = max
|
|
return scale
|
|
|
|
|
|
def axes(mark=None, options={}, **kwargs):
|
|
"""Draws axes corresponding to the scales of a given mark.
|
|
|
|
It also returns a dictionary of drawn axes. If the mark is not provided,
|
|
the last drawn mark is used.
|
|
|
|
Parameters
|
|
----------
|
|
mark: Mark or None (default: None)
|
|
The mark to inspect to create axes. If None, the last mark drawn is
|
|
used instead.
|
|
options: dict (default: {})
|
|
Options for the axes to be created. If a scale labeled 'x' is required
|
|
for that mark, options['x'] contains optional keyword arguments for the
|
|
constructor of the corresponding axis type.
|
|
"""
|
|
if mark is None:
|
|
mark = _context['last_mark']
|
|
if mark is None:
|
|
return {}
|
|
fig = kwargs.get('figure', current_figure())
|
|
scales = mark.scales
|
|
fig_axes = [axis for axis in fig.axes]
|
|
axes = {}
|
|
for name in scales:
|
|
if name not in mark.class_trait_names(scaled=True):
|
|
# The scale is not needed.
|
|
continue
|
|
scale_metadata = mark.scales_metadata.get(name, {})
|
|
dimension = scale_metadata.get('dimension', scales[name])
|
|
axis_args = dict(scale_metadata,
|
|
**(options.get(name, {})))
|
|
|
|
axis = _fetch_axis(fig, dimension, scales[name])
|
|
if axis is not None:
|
|
# For this figure, an axis exists for the scale in the given
|
|
# dimension. Apply the properties and return back the object.
|
|
_apply_properties(axis, options.get(name, {}))
|
|
axes[name] = axis
|
|
continue
|
|
|
|
# An axis must be created. We fetch the type from the registry
|
|
# the key being provided in the scaled attribute decoration
|
|
key = mark.class_traits()[name].get_metadata('atype')
|
|
if(key is not None):
|
|
axis_type = Axis.axis_types[key]
|
|
axis = axis_type(scale=scales[name], **axis_args)
|
|
axes[name] = axis
|
|
fig_axes.append(axis)
|
|
# Update the axis registry of the figure once the axis is added
|
|
_update_fig_axis_registry(fig, dimension, scales[name], axis)
|
|
fig.axes = fig_axes
|
|
return axes
|
|
|
|
|
|
def _set_label(label, mark, dim, **kwargs):
|
|
"""Helper function to set labels for an axis
|
|
"""
|
|
if mark is None:
|
|
mark = _context['last_mark']
|
|
if mark is None:
|
|
return {}
|
|
fig = kwargs.get('figure', current_figure())
|
|
scales = mark.scales
|
|
scale_metadata = mark.scales_metadata.get(dim, {})
|
|
scale = scales.get(dim, None)
|
|
if scale is None:
|
|
return
|
|
dimension = scale_metadata.get('dimension', scales[dim])
|
|
axis = _fetch_axis(fig, dimension, scales[dim])
|
|
|
|
if axis is not None:
|
|
_apply_properties(axis, {'label': label})
|
|
|
|
|
|
def xlabel(label=None, mark=None, **kwargs):
|
|
"""Sets the value of label for an axis whose associated scale has the
|
|
dimension `x`.
|
|
|
|
Parameters
|
|
----------
|
|
label: Unicode or None (default: None)
|
|
The label for x axis
|
|
"""
|
|
_set_label(label, mark, 'x', **kwargs)
|
|
|
|
|
|
def ylabel(label=None, mark=None, **kwargs):
|
|
"""Sets the value of label for an axis whose associated scale has the
|
|
dimension `y`.
|
|
|
|
Parameters
|
|
----------
|
|
label: Unicode or None (default: None)
|
|
The label for y axis
|
|
"""
|
|
_set_label(label, mark, 'y', **kwargs)
|
|
|
|
|
|
def grids(fig=None, value='solid'):
|
|
"""Sets the value of the grid_lines for the axis to the passed value.
|
|
The default value is `solid`.
|
|
|
|
Parameters
|
|
----------
|
|
fig: Figure or None(default: None)
|
|
The figure for which the axes should be edited. If the value is None,
|
|
the current figure is used.
|
|
value: {'none', 'solid', 'dashed'}
|
|
The display of the grid_lines
|
|
"""
|
|
|
|
if fig is None:
|
|
fig = current_figure()
|
|
for a in fig.axes:
|
|
a.grid_lines = value
|
|
|
|
|
|
def title(label, style=None):
|
|
"""Sets the title for the current figure.
|
|
|
|
Parameters
|
|
----------
|
|
label : str
|
|
The new title for the current figure.
|
|
style: dict
|
|
The CSS style to be applied to the figure title
|
|
"""
|
|
fig = current_figure()
|
|
fig.title = label
|
|
if style is not None:
|
|
fig.title_style = style
|
|
|
|
|
|
def legend():
|
|
"""Places legend in the current figure."""
|
|
for m in current_figure().marks:
|
|
m.display_legend = True
|
|
|
|
|
|
def hline(level, **kwargs):
|
|
"""Draws a horizontal line at the given level.
|
|
|
|
Parameters
|
|
----------
|
|
level: float
|
|
The level at which to draw the horizontal line.
|
|
preserve_domain: boolean (default: False)
|
|
If true, the line does not affect the domain of the 'y' scale.
|
|
"""
|
|
kwargs.setdefault('colors', ['dodgerblue'])
|
|
kwargs.setdefault('stroke_width', 1)
|
|
scales = kwargs.pop('scales', {})
|
|
fig = kwargs.get('figure', current_figure())
|
|
scales['x'] = fig.scale_x
|
|
|
|
level = array(level)
|
|
if len(level.shape) == 0:
|
|
x = [0, 1]
|
|
y = [level, level]
|
|
else:
|
|
x = [0, 1]
|
|
y = column_stack([level, level])
|
|
return plot(x, y, scales=scales, preserve_domain={
|
|
'x': True,
|
|
'y': kwargs.get('preserve_domain', False)
|
|
}, axes=False, update_context=False, **kwargs)
|
|
|
|
|
|
def vline(level, **kwargs):
|
|
"""Draws a vertical line at the given level.
|
|
|
|
Parameters
|
|
----------
|
|
level: float
|
|
The level at which to draw the vertical line.
|
|
preserve_domain: boolean (default: False)
|
|
If true, the line does not affect the domain of the 'x' scale.
|
|
"""
|
|
kwargs.setdefault('colors', ['dodgerblue'])
|
|
kwargs.setdefault('stroke_width', 1)
|
|
scales = kwargs.pop('scales', {})
|
|
fig = kwargs.get('figure', current_figure())
|
|
scales['y'] = fig.scale_y
|
|
|
|
level = array(level)
|
|
if len(level.shape) == 0:
|
|
x = [level, level]
|
|
y = [0, 1]
|
|
else:
|
|
x = column_stack([level, level])
|
|
# TODO: repeating [0, 1] should not be required once we allow for
|
|
# 2-D x and 1-D y
|
|
y = [[0, 1]] * len(level)
|
|
return plot(x, y, scales=scales, preserve_domain={
|
|
'x': kwargs.get('preserve_domain', False),
|
|
'y': True
|
|
}, axes=False, update_context=False, **kwargs)
|
|
|
|
|
|
def _process_cmap(cmap):
|
|
'''
|
|
Returns a kwarg dict suitable for a ColorScale
|
|
'''
|
|
option = {}
|
|
if isinstance(cmap, str):
|
|
option['scheme'] = cmap
|
|
elif isinstance(cmap, list):
|
|
option['colors'] = cmap
|
|
else:
|
|
raise ValueError('''`cmap` must be a string (name of a color scheme)
|
|
or a list of colors, but a value of {} was given
|
|
'''.format(cmap))
|
|
return option
|
|
|
|
|
|
def set_cmap(cmap):
|
|
'''
|
|
Set the color map of the current 'color' scale.
|
|
'''
|
|
scale = _context['scales']['color']
|
|
for k, v in _process_cmap(cmap).items():
|
|
setattr(scale, k, v)
|
|
return scale
|
|
|
|
|
|
def _draw_mark(mark_type, options={}, axes_options={}, **kwargs):
|
|
"""Draw the mark of specified mark type.
|
|
|
|
Parameters
|
|
----------
|
|
mark_type: type
|
|
The type of mark to be drawn
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
figure: Figure or None
|
|
The figure to which the mark is to be added.
|
|
If the value is None, the current figure is used.
|
|
cmap: list or string
|
|
List of css colors, or name of bqplot color scheme
|
|
"""
|
|
fig = kwargs.pop('figure', current_figure())
|
|
scales = kwargs.pop('scales', {})
|
|
update_context = kwargs.pop('update_context', True)
|
|
|
|
# Set the color map of the color scale
|
|
cmap = kwargs.pop('cmap', None)
|
|
if cmap is not None:
|
|
# Add the colors or scheme to the color scale options
|
|
options['color'] = dict(options.get('color', {}),
|
|
**_process_cmap(cmap))
|
|
|
|
# Going through the list of data attributes
|
|
for name in mark_type.class_trait_names(scaled=True):
|
|
dimension = _get_attribute_dimension(name, mark_type)
|
|
# TODO: the following should also happen if name in kwargs and
|
|
# scales[name] is incompatible.
|
|
if name not in kwargs:
|
|
# The scaled attribute is not being passed to the mark. So no need
|
|
# create a scale for this.
|
|
continue
|
|
elif name in scales:
|
|
if update_context:
|
|
_context['scales'][dimension] = scales[name]
|
|
# Scale has to be fetched from the context or created as it has not
|
|
# been passed.
|
|
elif dimension not in _context['scales']:
|
|
# Creating a scale for the dimension if a matching scale is not
|
|
# present in _context['scales']
|
|
traitlet = mark_type.class_traits()[name]
|
|
rtype = traitlet.get_metadata('rtype')
|
|
dtype = traitlet.validate(None, kwargs[name]).dtype
|
|
# Fetching the first matching scale for the rtype and dtype of the
|
|
# scaled attributes of the mark.
|
|
compat_scale_types = [
|
|
Scale.scale_types[key]
|
|
for key in Scale.scale_types
|
|
if Scale.scale_types[key].rtype == rtype and
|
|
issubdtype(dtype, Scale.scale_types[key].dtype)
|
|
]
|
|
sorted_scales = sorted(compat_scale_types,
|
|
key=lambda x: x.precedence)
|
|
scales[name] = sorted_scales[-1](**options.get(name, {}))
|
|
# Adding the scale to the context scales
|
|
if update_context:
|
|
_context['scales'][dimension] = scales[name]
|
|
else:
|
|
scales[name] = _context['scales'][dimension]
|
|
|
|
mark = mark_type(scales=scales, **kwargs)
|
|
_context['last_mark'] = mark
|
|
fig.marks = [m for m in fig.marks] + [mark]
|
|
if kwargs.get('axes', True):
|
|
axes(mark, options=axes_options)
|
|
return mark
|
|
|
|
|
|
def _infer_x_for_line(y):
|
|
"""
|
|
Infers the x for a line if no x is provided.
|
|
"""
|
|
array_shape = shape(y)
|
|
|
|
if len(array_shape) == 0:
|
|
return []
|
|
if len(array_shape) == 1:
|
|
return arange(array_shape[0])
|
|
if len(array_shape) > 1:
|
|
return arange(array_shape[1])
|
|
|
|
|
|
@_process_data('color')
|
|
def plot(*args, **kwargs):
|
|
"""Draw lines in the current context figure.
|
|
|
|
Signature: `plot(x, y, **kwargs)` or `plot(y, **kwargs)`, depending of the
|
|
length of the list of positional arguments. In the case where the `x` array
|
|
is not provided.
|
|
|
|
Parameters
|
|
----------
|
|
x: numpy.ndarray or list, 1d or 2d (optional)
|
|
The x-coordinates of the plotted line. When not provided, the function
|
|
defaults to `numpy.arange(len(y))`
|
|
x can be 1-dimensional or 2-dimensional.
|
|
y: numpy.ndarray or list, 1d or 2d
|
|
The y-coordinates of the plotted line. If argument `x` is 2-dimensional
|
|
it must also be 2-dimensional.
|
|
marker_str: string
|
|
string representing line_style, marker and color.
|
|
For e.g. 'g--o', 'sr' etc
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
figure: Figure or None
|
|
The figure to which the line is to be added.
|
|
If the value is None, the current figure is used.
|
|
"""
|
|
marker_str = None
|
|
if len(args) == 1:
|
|
kwargs['y'] = args[0]
|
|
if kwargs.get('index_data', None) is not None:
|
|
kwargs['x'] = kwargs['index_data']
|
|
else:
|
|
kwargs['x'] = _infer_x_for_line(args[0])
|
|
elif len(args) == 2:
|
|
if type(args[1]) == str:
|
|
kwargs['y'] = args[0]
|
|
kwargs['x'] = _infer_x_for_line(args[0])
|
|
marker_str = args[1].strip()
|
|
else:
|
|
kwargs['x'] = args[0]
|
|
kwargs['y'] = args[1]
|
|
elif len(args) == 3:
|
|
kwargs['x'] = args[0]
|
|
kwargs['y'] = args[1]
|
|
if type(args[2]) == str:
|
|
marker_str = args[2].strip()
|
|
|
|
if marker_str:
|
|
line_style, color, marker = _get_line_styles(marker_str)
|
|
|
|
# only marker specified => draw scatter
|
|
if marker and not line_style:
|
|
kwargs['marker'] = marker
|
|
if color:
|
|
kwargs['colors'] = [color]
|
|
return _draw_mark(Scatter, **kwargs)
|
|
else: # draw lines in all other cases
|
|
kwargs['line_style'] = line_style or 'solid'
|
|
|
|
if marker:
|
|
kwargs['marker'] = marker
|
|
if color:
|
|
kwargs['colors'] = [color]
|
|
return _draw_mark(Lines, **kwargs)
|
|
else:
|
|
return _draw_mark(Lines, **kwargs)
|
|
|
|
|
|
def imshow(image, format, **kwargs):
|
|
"""Draw an image in the current context figure.
|
|
Parameters
|
|
----------
|
|
image: image data
|
|
Image data, depending on the passed format, can be one of:
|
|
- an instance of an ipywidgets Image
|
|
- a file name
|
|
- a raw byte string
|
|
format: {'widget', 'filename', ...}
|
|
Type of the input argument.
|
|
If not 'widget' or 'filename', must be a format supported by
|
|
the ipywidgets Image.
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
if format == 'widget':
|
|
ipyimage = image
|
|
elif format == 'filename':
|
|
with open(image, 'rb') as f:
|
|
data = f.read()
|
|
ipyimage = ipyImage(value=data)
|
|
else:
|
|
ipyimage = ipyImage(value=image, format=format)
|
|
kwargs['image'] = ipyimage
|
|
|
|
kwargs.setdefault('x', [0., 1.])
|
|
kwargs.setdefault('y', [0., 1.])
|
|
|
|
return _draw_mark(Image, **kwargs)
|
|
|
|
|
|
def ohlc(*args, **kwargs):
|
|
"""Draw OHLC bars or candle bars in the current context figure.
|
|
|
|
Signature: `ohlc(x, y, **kwargs)` or `ohlc(y, **kwargs)`, depending of the
|
|
length of the list of positional arguments. In the case where the `x` array
|
|
is not provided
|
|
|
|
Parameters
|
|
----------
|
|
x: numpy.ndarray or list, 1d (optional)
|
|
The x-coordinates of the plotted line. When not provided, the function
|
|
defaults to `numpy.arange(len(y))`.
|
|
y: numpy.ndarray or list, 2d
|
|
The ohlc (open/high/low/close) information. A two dimensional array. y
|
|
must have the shape (n, 4).
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
if len(args) == 2:
|
|
kwargs['x'] = args[0]
|
|
kwargs['y'] = args[1]
|
|
elif len(args) == 1:
|
|
kwargs['y'] = args[0]
|
|
length = len(args[0])
|
|
kwargs['x'] = arange(length)
|
|
return _draw_mark(OHLC, **kwargs)
|
|
|
|
|
|
@_process_data('color', 'opacity', 'size', 'skew', 'rotation')
|
|
def scatter(x, y, use_gl=None, **kwargs):
|
|
"""Draw a scatter in the current context figure.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
x: numpy.ndarray, 1d
|
|
The x-coordinates of the data points.
|
|
y: numpy.ndarray, 1d
|
|
The y-coordinates of the data points.
|
|
use_gl: If true, will use the ScatterGL mark (pixelized but faster), if false a normal
|
|
Scatter mark is used. If None, a choised is made automatically depending on the length
|
|
of x.
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
kwargs['x'] = x
|
|
kwargs['y'] = y
|
|
if use_gl is None:
|
|
mark_class = ScatterGL if len(x) >= SCATTER_SIZE_LIMIT else Scatter
|
|
else:
|
|
mark_class = ScatterGL if use_gl else Scatter
|
|
return _draw_mark(mark_class, **kwargs)
|
|
|
|
|
|
@_process_data()
|
|
def hist(sample, options={}, **kwargs):
|
|
"""Draw a histogram in the current context figure.
|
|
|
|
Parameters
|
|
----------
|
|
sample: numpy.ndarray, 1d
|
|
The sample for which the histogram must be generated.
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'counts'
|
|
is required for that mark, options['counts'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'counts' is
|
|
required for that mark, axes_options['counts'] contains optional
|
|
keyword arguments for the constructor of the corresponding axis type.
|
|
"""
|
|
kwargs['sample'] = sample
|
|
scales = kwargs.pop('scales', {})
|
|
if 'count' not in scales:
|
|
dimension = _get_attribute_dimension('count', Hist)
|
|
if dimension in _context['scales']:
|
|
scales['count'] = _context['scales'][dimension]
|
|
else:
|
|
scales['count'] = LinearScale(**options.get('count', {}))
|
|
_context['scales'][dimension] = scales['count']
|
|
kwargs['scales'] = scales
|
|
return _draw_mark(Hist, options=options, **kwargs)
|
|
|
|
|
|
@_process_data()
|
|
def bin(sample, options={}, **kwargs):
|
|
"""Draw a histogram in the current context figure.
|
|
Parameters
|
|
----------
|
|
sample: numpy.ndarray, 1d
|
|
The sample for which the histogram must be generated.
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x'
|
|
is required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is
|
|
required for that mark, axes_options['x'] contains optional
|
|
keyword arguments for the constructor of the corresponding axis type.
|
|
"""
|
|
kwargs['sample'] = sample
|
|
scales = kwargs.pop('scales', {})
|
|
for xy in ['x', 'y']:
|
|
if xy not in scales:
|
|
dimension = _get_attribute_dimension(xy, Bars)
|
|
if dimension in _context['scales']:
|
|
scales[xy] = _context['scales'][dimension]
|
|
else:
|
|
scales[xy] = LinearScale(**options.get(xy, {}))
|
|
_context['scales'][dimension] = scales[xy]
|
|
kwargs['scales'] = scales
|
|
return _draw_mark(Bins, options=options, **kwargs)
|
|
|
|
|
|
@_process_data('color')
|
|
def bar(x, y, **kwargs):
|
|
"""Draws a bar chart in the current context figure.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
x: numpy.ndarray, 1d
|
|
The x-coordinates of the data points.
|
|
y: numpy.ndarray, 1d
|
|
The y-coordinates of the data pints.
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
kwargs['x'] = x
|
|
kwargs['y'] = y
|
|
return _draw_mark(Bars, **kwargs)
|
|
|
|
|
|
@_process_data()
|
|
def boxplot(x, y, **kwargs):
|
|
"""Draws a boxplot in the current context figure.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
x: numpy.ndarray, 1d
|
|
The x-coordinates of the data points.
|
|
y: numpy.ndarray, 2d
|
|
The data from which the boxes are to be created. Each row of the data
|
|
corresponds to one box drawn in the plot.
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
kwargs['x'] = x
|
|
kwargs['y'] = y
|
|
return _draw_mark(Boxplot, **kwargs)
|
|
|
|
|
|
@_process_data('color')
|
|
def barh(*args, **kwargs):
|
|
"""Draws a horizontal bar chart in the current context figure.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
x: numpy.ndarray, 1d
|
|
The domain of the data points.
|
|
y: numpy.ndarray, 1d
|
|
The range of the data pints.
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
kwargs['orientation'] = "horizontal"
|
|
return bar(*args, **kwargs)
|
|
|
|
|
|
@_process_data('color')
|
|
def pie(sizes, **kwargs):
|
|
"""Draws a Pie in the current context figure.
|
|
|
|
Parameters
|
|
----------
|
|
sizes: numpy.ndarray, 1d
|
|
The proportions to be represented by the Pie.
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
kwargs['sizes'] = sizes
|
|
return _draw_mark(Pie, **kwargs)
|
|
|
|
|
|
def label(text, **kwargs):
|
|
"""Draws a Label in the current context figure.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
text: string
|
|
The label to be displayed.
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
kwargs['text'] = text
|
|
return _draw_mark(Label, **kwargs)
|
|
|
|
|
|
def geo(map_data, **kwargs):
|
|
"""Draw a map in the current context figure.
|
|
|
|
Parameters
|
|
----------
|
|
map_data: string or bqplot.map (default: WorldMap)
|
|
Name of the map or json file required for the map data.
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
scales = kwargs.pop('scales', _context['scales'])
|
|
options = kwargs.get('options', {})
|
|
if 'projection' not in scales:
|
|
scales['projection'] = Mercator(**options.get('projection', {}))
|
|
kwargs['scales'] = scales
|
|
if isinstance(map_data, string_types):
|
|
kwargs['map_data'] = topo_load('map_data/' + map_data + '.json')
|
|
else:
|
|
kwargs['map_data'] = map_data
|
|
return _draw_mark(Map, **kwargs)
|
|
|
|
|
|
def heatmap(color, **kwargs):
|
|
"""Draw a heatmap in the current context figure.
|
|
|
|
Parameters
|
|
----------
|
|
color: numpy.ndarray, 2d
|
|
Matrix of color of the data points
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
kwargs['color'] = color
|
|
return _draw_mark(HeatMap, **kwargs)
|
|
|
|
|
|
def gridheatmap(color, **kwargs):
|
|
"""Draw a GridHeatMap in the current context figure.
|
|
|
|
Parameters
|
|
----------
|
|
color: numpy.ndarray, 2d
|
|
Matrix of color of the data points
|
|
options: dict (default: {})
|
|
Options for the scales to be created. If a scale labeled 'x' is
|
|
required for that mark, options['x'] contains optional keyword
|
|
arguments for the constructor of the corresponding scale type.
|
|
axes_options: dict (default: {})
|
|
Options for the axes to be created. If an axis labeled 'x' is required
|
|
for that mark, axes_options['x'] contains optional keyword arguments
|
|
for the constructor of the corresponding axis type.
|
|
"""
|
|
kwargs['color'] = color
|
|
return _draw_mark(GridHeatMap, **kwargs)
|
|
|
|
|
|
def _add_interaction(int_type, **kwargs):
|
|
"""Add the interaction for the specified type.
|
|
|
|
If a figure is passed using the key-word argument `figure` it is used. Else
|
|
the context figure is used.
|
|
If a list of marks are passed using the key-word argument `marks` it
|
|
is used. Else the latest mark that is passed is used as the only mark
|
|
associated with the selector.
|
|
|
|
Parameters
|
|
----------
|
|
int_type: type
|
|
The type of interaction to be added.
|
|
"""
|
|
|
|
fig = kwargs.pop('figure', current_figure())
|
|
marks = kwargs.pop('marks', [_context['last_mark']])
|
|
|
|
for name, traitlet in int_type.class_traits().items():
|
|
dimension = traitlet.get_metadata('dimension')
|
|
if dimension is not None:
|
|
# only scales have this attribute in interactions
|
|
kwargs[name] = _get_context_scale(dimension)
|
|
kwargs['marks'] = marks
|
|
interaction = int_type(**kwargs)
|
|
if fig.interaction is not None:
|
|
fig.interaction.close()
|
|
fig.interaction = interaction
|
|
return interaction
|
|
|
|
|
|
def _get_context_scale(dimension):
|
|
"""Return the scale instance in the current context for a given dimension.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
dimension: string
|
|
The dimension along which the current context scale is to be fetched.
|
|
"""
|
|
return _context['scales'][dimension]
|
|
|
|
|
|
def _create_selector(int_type, func, trait, **kwargs):
|
|
"""Create a selector of the specified type.
|
|
|
|
Also attaches the function `func` as an `on_trait_change` listener
|
|
for the trait `trait` of the selector.
|
|
|
|
This is an internal function which should not be called by the user.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
int_type: type
|
|
The type of selector to be added.
|
|
func: function
|
|
The call back function. It should take atleast two arguments. The name
|
|
of the trait and the value of the trait are passed as arguments.
|
|
trait: string
|
|
The name of the Selector trait whose change triggers the
|
|
call back function `func`.
|
|
"""
|
|
interaction = _add_interaction(int_type, **kwargs)
|
|
if func is not None:
|
|
interaction.on_trait_change(func, trait)
|
|
return interaction
|
|
|
|
|
|
def brush_int_selector(func=None, trait='selected', **kwargs):
|
|
"""Create a `BrushIntervalSelector` interaction for the `figure`.
|
|
|
|
Also attaches the function `func` as an event listener for the
|
|
specified trait.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
func: function
|
|
The call back function. It should take atleast two arguments. The name
|
|
of the trait and the value of the trait are passed as arguments.
|
|
trait: string
|
|
The name of the BrushIntervalSelector trait whose change triggers the
|
|
call back function `func`.
|
|
"""
|
|
return _create_selector(BrushIntervalSelector, func, trait, **kwargs)
|
|
|
|
|
|
def int_selector(func=None, trait='selected', **kwargs):
|
|
"""Creates a `FastIntervalSelector` interaction for the `figure`.
|
|
|
|
Also attaches the function `func` as an event listener for the
|
|
trait `trait`.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
func: function
|
|
The call back function. It should take atleast two arguments. The name
|
|
of the trait and the value of the trait are passed as arguments.
|
|
trait: string
|
|
The name of the IntervalSelector trait whose change triggers the
|
|
call back function `func`.
|
|
"""
|
|
return _create_selector(FastIntervalSelector, func, trait, **kwargs)
|
|
|
|
|
|
def index_selector(func=None, trait='selected', **kwargs):
|
|
"""Creates an `IndexSelector` interaction for the `figure`.
|
|
|
|
Also attaches the function `func` as an event listener for the
|
|
trait `trait`.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
func: function
|
|
The call back function. It should take atleast two arguments. The name
|
|
of the trait and the value of the trait are passed as arguments.
|
|
trait: string
|
|
The name of the IndexSelector trait whose change triggers the
|
|
call back function `func`.
|
|
"""
|
|
return _create_selector(IndexSelector, func, trait, **kwargs)
|
|
|
|
|
|
def brush_selector(func=None, trait='selected', **kwargs):
|
|
"""Creates a `BrushSelector` interaction for the `figure`.
|
|
|
|
Also attaches the function `func` as an event listener for the
|
|
trait `trait`.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
func: function
|
|
The call back function. It should take atleast two arguments. The name
|
|
of the trait and the value of the trait are passed as arguments.
|
|
trait: string
|
|
The name of the BrushSelector trait whose change triggers the
|
|
call back function `func`.
|
|
"""
|
|
return _create_selector(BrushSelector, func, trait, **kwargs)
|
|
|
|
|
|
def multi_selector(func=None, trait='selected', **kwargs):
|
|
"""Creates a `MultiSelector` interaction for the `figure`.
|
|
|
|
Also attaches the function `func` as an event listener for the
|
|
trait `trait`.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
func: function
|
|
The call back function. It should take atleast two arguments. The name
|
|
of the trait and the value of the trait are passed as arguments.
|
|
trait: string
|
|
The name of the MultiSelector trait whose change triggers the
|
|
call back function `func`.
|
|
"""
|
|
return _create_selector(MultiSelector, func, trait, **kwargs)
|
|
|
|
|
|
def lasso_selector(func=None, trait='selected', **kwargs):
|
|
"""Creates a `LassoSelector` interaction for the `figure`.
|
|
|
|
Also attaches the function `func` as an event listener for the
|
|
specified trait.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
func: function
|
|
The call back function. It should take atleast two arguments. The name
|
|
of the trait and the value of the trait are passed as arguments.
|
|
trait: string
|
|
The name of the LassoSelector trait whose change triggers the
|
|
call back function `func`.
|
|
"""
|
|
return _create_selector(LassoSelector, func, trait, **kwargs)
|
|
|
|
|
|
def clear():
|
|
"""Clears the current context figure of all marks axes and grid lines."""
|
|
fig = _context['figure']
|
|
if fig is not None:
|
|
fig.marks = []
|
|
fig.axes = []
|
|
setattr(fig, 'axis_registry', {})
|
|
_context['scales'] = {}
|
|
key = _context['current_key']
|
|
if key is not None:
|
|
_context['scale_registry'][key] = {}
|
|
|
|
|
|
def current_figure():
|
|
"""Returns the current context figure."""
|
|
if _context['figure'] is None:
|
|
figure()
|
|
return _context['figure']
|
|
|
|
# FOR DEBUG ONLY
|
|
|
|
|
|
def get_context():
|
|
"""Used for debug only. Return a copy of the current global
|
|
context dictionary."""
|
|
return {k: v for k, v in _context.items()}
|
|
|
|
|
|
def set_context(context):
|
|
"""Sets the current global context dictionary. All the attributes to be set
|
|
should be set. Otherwise, it will result in unpredictable behavior."""
|
|
global _context
|
|
_context = {k: v for k, v in context.items()}
|
|
|
|
|
|
def _fetch_axis(fig, dimension, scale):
|
|
# Internal utility function.
|
|
# Given a figure instance `fig`, the dimension of the scaled attribute and
|
|
# the instance of a scale, returns the axis if an axis is present for that
|
|
# combination. Else returns `None`
|
|
axis_registry = getattr(fig, 'axis_registry', {})
|
|
dimension_data = axis_registry.get(dimension, [])
|
|
dimension_scales = [dim['scale'] for dim in dimension_data]
|
|
dimension_axes = [dim['axis'] for dim in dimension_data]
|
|
try:
|
|
return dimension_axes[dimension_scales.index(scale)]
|
|
except (ValueError, IndexError):
|
|
return None
|
|
|
|
|
|
def _update_fig_axis_registry(fig, dimension, scale, axis):
|
|
axis_registry = fig.axis_registry
|
|
dimension_scales = axis_registry.get(dimension, [])
|
|
dimension_scales.append({'scale': scale, 'axis': axis})
|
|
axis_registry[dimension] = dimension_scales
|
|
setattr(fig, 'axis_registry', axis_registry)
|
|
|
|
|
|
def _get_attribute_dimension(trait_name, mark_type=None):
|
|
"""Returns the dimension for the name of the trait for the specified mark.
|
|
|
|
If `mark_type` is `None`, then the `trait_name` is returned
|
|
as is.
|
|
Returns `None` if the `trait_name` is not valid for `mark_type`.
|
|
"""
|
|
if(mark_type is None):
|
|
return trait_name
|
|
scale_metadata = mark_type.class_traits()['scales_metadata']\
|
|
.default_args[0]
|
|
return scale_metadata.get(trait_name, {}).get('dimension', None)
|
|
|
|
|
|
def _apply_properties(widget, properties={}):
|
|
"""Applies the specified properties to the widget.
|
|
|
|
`properties` is a dictionary with key value pairs corresponding
|
|
to the properties to be applied to the widget.
|
|
"""
|
|
with widget.hold_sync():
|
|
for key, value in properties.items():
|
|
setattr(widget, key, value)
|
|
|
|
|
|
def _get_line_styles(marker_str):
|
|
"""Return line style, color and marker type from specified marker string.
|
|
|
|
For example, if ``marker_str`` is 'g-o' then the method returns
|
|
``('solid', 'green', 'circle')``.
|
|
"""
|
|
def _extract_marker_value(marker_str, code_dict):
|
|
"""Extracts the marker value from a given marker string.
|
|
|
|
Looks up the `code_dict` and returns the corresponding marker for a
|
|
specific code.
|
|
|
|
For example if `marker_str` is 'g-o' then the method extracts
|
|
- 'green' if the code_dict is color_codes,
|
|
- 'circle' if the code_dict is marker_codes etc.
|
|
"""
|
|
val = None
|
|
for code in code_dict:
|
|
if code in marker_str:
|
|
val = code_dict[code]
|
|
break
|
|
return val
|
|
|
|
return [_extract_marker_value(marker_str, code_dict) for
|
|
code_dict in [LINE_STYLE_CODES, COLOR_CODES, MARKER_CODES]]
|