You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1793 lines
72 KiB

# 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"""
=====
Marks
=====
.. currentmodule:: bqplot.marks
.. autosummary::
:toctree: _generate/
Mark
Lines
FlexLine
Scatter
Hist
Bars
Graph
GridHeatMap
HeatMap
Label
OHLC
Pie
Map
"""
import os
import json
from warnings import warn
import ipywidgets as widgets
from ipywidgets import (Widget, DOMWidget, CallbackDispatcher,
Color, widget_serialization)
from traitlets import (Int, Unicode, List, Enum, Dict, Bool, Float,
Instance, TraitError, validate)
from traittypes import Array
from numpy import histogram
import numpy as np
from .scales import Scale, OrdinalScale, LinearScale
from .traits import (Date, array_serialization,
array_squeeze, array_dimension_bounds, array_supported_kinds)
from ._version import __frontend_version__
from .colorschemes import CATEGORY10
def register_mark(key=None):
"""Returns a decorator registering a mark class in the mark type registry.
If no key is provided, the class name is used as a key. A key is provided
for each core bqplot mark so that the frontend can use
this key regardless of the kernel language.
"""
def wrap(mark):
name = key if key is not None else mark.__module__ + mark.__name__
Mark.mark_types[name] = mark
return mark
return wrap
# Shape constraint for array-types
def shape(*dimensions):
def validator(trait, value):
err_msg_tmpl = 'Expected an array of shape {} ' + \
'but got an array of shape {}'
if value.shape != dimensions:
raise TraitError(err_msg_tmpl.format(dimensions, value.shape))
else:
return value
return validator
class Mark(Widget):
"""The base mark class.
Traitlet mark attributes may be decorated with metadata.
**Data Attribute Decoration**
Data attributes are decorated with the following values:
scaled: bool
Indicates whether the considered attribute is a data attribute which
must be associated with a scale in order to be taken into account.
rtype: string
Range type of the associated scale.
atype: string
Key in bqplot's axis registry of the recommended axis type to represent
this scale. When not specified, the default is 'bqplot.Axis'.
Attributes
----------
display_name: string
Holds a user-friendly name for the trait attribute.
mark_types: dict (class-level attribute)
A registry of existing mark types.
scales: Dict of scales (default: {})
A dictionary of scales holding scales for each data attribute.
- If a mark holds a scaled attribute named 'x', the scales dictionary
must have a corresponding scale for the key 'x'.
- The scale's range type should be equal to the scaled attribute's
range type (rtype).
scales_metadata: Dict (default: {})
A dictionary of dictionaries holding metadata on the way scales are
used by the mark. For example, a linear scale may be used to count
pixels horizontally or vertically. The content of this dictionary
may change dynamically. It is an instance-level attribute.
preserve_domain: dict (default: {})
Indicates if this mark affects the domain(s) of the specified scale(s).
The keys of this dictionary are the same as the ones of the "scales"
attribute, and values are boolean. If a key is missing, it is
considered as False.
display_legend: bool (default: False)
Display toggle for the mark legend in the general figure legend
labels: list of unicode strings (default: [])
Labels of the items of the mark. This attribute has different meanings
depending on the type of mark.
apply_clip: bool (default: True)
Indicates whether the items that are beyond the limits of the chart
should be clipped.
visible: bool (default: True)
Visibility toggle for the mark.
selected_style: dict (default: {})
CSS style to be applied to selected items in the mark.
unselected_style: dict (default: {})
CSS style to be applied to items that are not selected in the mark,
when a selection exists.
selected: list of integers or None (default: None)
Indices of the selected items in the mark.
tooltip: DOMWidget or None (default: None)
Widget to be displayed as tooltip when elements of the scatter are
hovered on
tooltip_style: Dictionary (default: {'opacity': 0.9})
Styles to be applied to the tooltip widget
enable_hover: Bool (default: True)
Boolean attribute to control the hover interaction for the scatter. If
this is false, the on_hover custom mssg is not sent back to the python
side
interactions: Dictionary (default: {'hover': 'tooltip'})
Dictionary listing the different interactions for each mark. The key is
the event which triggers the interaction and the value is the kind of
interactions. Keys and values can only take strings from separate enums
for each mark.
tooltip_location : {'mouse', 'center'} (default: 'mouse')
Enum specifying the location of the tooltip. 'mouse' places the tooltip
at the location of the mouse when the tooltip is activated and 'center'
places the tooltip at the center of the figure. If tooltip is linked to
a click event, 'mouse' places the tooltip at the location of the click
that triggered the tooltip to be visible.
"""
mark_types = {}
scales = Dict(trait=Instance(Scale)).tag(sync=True, **widget_serialization)
scales_metadata = Dict().tag(sync=True)
preserve_domain = Dict().tag(sync=True)
display_legend = Bool().tag(sync=True, display_name='Display legend')
labels = List(trait=Unicode()).tag(sync=True, display_name='Labels')
apply_clip = Bool(True).tag(sync=True)
visible = Bool(True).tag(sync=True)
selected_style = Dict().tag(sync=True)
unselected_style = Dict().tag(sync=True)
selected = Array(None, allow_none=True).tag(sync=True, **array_serialization)
enable_hover = Bool(True).tag(sync=True)
tooltip = Instance(DOMWidget, allow_none=True, default_value=None)\
.tag(sync=True, **widget_serialization)
tooltip_style = Dict({'opacity': 0.9}).tag(sync=True)
interactions = Dict({'hover': 'tooltip'}).tag(sync=True)
tooltip_location = Enum(['mouse', 'center'], default_value='mouse')\
.tag(sync=True)
_model_name = Unicode('MarkModel').tag(sync=True)
_model_module = Unicode('bqplot').tag(sync=True)
_view_module = Unicode('bqplot').tag(sync=True)
_view_module_version = Unicode(__frontend_version__).tag(sync=True)
_model_module_version = Unicode(__frontend_version__).tag(sync=True)
_ipython_display_ = None
def _get_dimension_scales(self, dimension, preserve_domain=False):
"""
Return the list of scales corresponding to a given dimension.
The preserve_domain optional argument specifies whether one should
filter out the scales for which preserve_domain is set to True.
"""
if preserve_domain:
return [
self.scales[k] for k in self.scales if (
k in self.scales_metadata and
self.scales_metadata[k].get('dimension') == dimension and
not self.preserve_domain.get(k)
)
]
else:
return [
self.scales[k] for k in self.scales if (
k in self.scales_metadata and
self.scales_metadata[k].get('dimension') == dimension
)
]
@validate('scales')
def _validate_scales(self, proposal):
"""
Validates the `scales` based on the mark's scaled attributes metadata.
First checks for missing scale and then for 'rtype' compatibility.
"""
# Validate scales' 'rtype' versus data attribute 'rtype' decoration
# At this stage it is already validated that all values in self.scales
# are instances of Scale.
scales = proposal.value
for name in self.trait_names(scaled=True):
trait = self.traits()[name]
if name not in scales:
# Check for missing scale
if not trait.allow_none:
raise TraitError("Missing scale for data attribute %s." %
name)
else:
# Check scale range type compatibility
if scales[name].rtype != trait.get_metadata('rtype'):
raise TraitError("Range type mismatch for scale %s." %
name)
return scales
def __init__(self, **kwargs):
super(Mark, self).__init__(**kwargs)
self._hover_handlers = CallbackDispatcher()
self._click_handlers = CallbackDispatcher()
self._legend_click_handlers = CallbackDispatcher()
self._legend_hover_handlers = CallbackDispatcher()
self._element_click_handlers = CallbackDispatcher()
self._bg_click_handlers = CallbackDispatcher()
self.on_msg(self._handle_custom_msgs)
def on_hover(self, callback, remove=False):
self._hover_handlers.register_callback(callback, remove=remove)
def on_click(self, callback, remove=False):
self._click_handlers.register_callback(callback, remove=remove)
def on_legend_click(self, callback, remove=False):
self._legend_click_handlers.register_callback(callback, remove=remove)
def on_legend_hover(self, callback, remove=False):
self._legend_hover_handlers.register_callback(callback, remove=remove)
def on_element_click(self, callback, remove=False):
self._element_click_handlers.register_callback(callback, remove=remove)
def on_background_click(self, callback, remove=False):
self._bg_click_handlers.register_callback(callback, remove=remove)
def _handle_custom_msgs(self, _, content, buffers=None):
if content.get('event', '') == 'hover':
self._hover_handlers(self, content)
if content.get('event', '') == 'click':
self._click_handlers(self, content)
elif content.get('event', '') == 'legend_click':
self._legend_click_handlers(self, content)
elif content.get('event', '') == 'legend_hover':
self._legend_hover_handlers(self, content)
elif content.get('event', '') == 'element_click':
self._element_click_handlers(self, content)
elif content.get('event', '') == 'background_click':
self._bg_click_handlers(self, content)
@register_mark('bqplot.Lines')
class Lines(Mark):
"""Lines mark.
In the case of the Lines mark, scales for 'x' and 'y' MUST be provided.
Attributes
----------
icon: string (class-level attribute)
Font-awesome icon for the respective mark
name: string (class-level attribute)
User-friendly name of the mark
colors: list of colors (default: CATEGORY10)
List of colors of the Lines. If the list is shorter than the number
of lines, the colors are reused.
close_path: bool (default: False)
Whether to close the paths or not.
fill: {'none', 'bottom', 'top', 'inside', 'between'}
Fill in the area defined by the curves
fill_colors: list of colors (default: [])
Fill colors for the areas. Defaults to stroke-colors when no
color provided
opacities: list of floats (default: [])
Opacity for the lines and patches. Defaults to 1 when the list is too
short, or the element of the list is set to None.
fill_opacities: list of floats (default: [])
Opacity for the areas. Defaults to 1 when the list is too
short, or the element of the list is set to None.
stroke_width: float (default: 2)
Stroke width of the Lines
labels_visibility: {'none', 'label'}
Visibility of the curve labels
curves_subset: list of integers or None (default: [])
If set to None, all the lines are displayed. Otherwise, only the items
in the list will have full opacity, while others will be faded.
line_style: {'solid', 'dashed', 'dotted', 'dash_dotted'}
Line style.
interpolation: {'linear', 'basis', 'cardinal', 'monotone'}
Interpolation scheme used for interpolation between the data points
provided. Please refer to the svg interpolate documentation for details
about the different interpolation schemes.
marker: {'circle', 'cross', 'diamond', 'square', 'triangle-down', 'triangle-up', 'arrow', 'rectangle', 'ellipse'}
Marker shape
marker_size: nonnegative int (default: 64)
Default marker size in pixels
Data Attributes
x: numpy.ndarray (default: [])
abscissas of the data points (1d or 2d array)
y: numpy.ndarray (default: [])
ordinates of the data points (1d or 2d array)
color: numpy.ndarray (default: None)
colors of the different lines based on data. If it is [], then the
colors from the colors attribute are used. Each line has a single color
and if the size of colors is less than the number of lines, the
remaining lines are given the default colors.
Notes
-----
The fields which can be passed to the default tooltip are:
name: label of the line
index: index of the line being hovered on
color: data attribute for the color of the line
The following are the events which can trigger interactions:
click: left click of the mouse
hover: mouse-over an element
The following are the interactions which can be linked to the above events:
tooltip: display tooltip
"""
# Mark decoration
icon = 'fa-line-chart'
name = 'Lines'
# Scaled attributes
x = Array([]).tag(sync=True, scaled=True,
rtype='Number', atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 2), array_supported_kinds())
y = Array([]).tag(sync=True, scaled=True,
rtype='Number', atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 2), array_supported_kinds())
color = Array(None, allow_none=True).tag(sync=True,
scaled=True,
rtype='Color',
atype='bqplot.ColorAxis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
# Other attributes
scales_metadata = Dict({
'x': {'orientation': 'horizontal', 'dimension': 'x'},
'y': {'orientation': 'vertical', 'dimension': 'y'},
'color': {'dimension': 'color'}
}).tag(sync=True)
colors = List(trait=Color(default_value=None, allow_none=True),
default_value=CATEGORY10)\
.tag(sync=True, display_name='Colors')
fill_colors = List(trait=Color(default_value=None, allow_none=True))\
.tag(sync=True, display_name='Fill colors')
stroke_width = Float(2.0).tag(sync=True, display_name='Stroke width')
labels_visibility = Enum(['none', 'label'], default_value='none')\
.tag(sync=True, display_name='Labels visibility')
curves_subset = List().tag(sync=True)
line_style = Enum(['solid', 'dashed', 'dotted', 'dash_dotted'],
default_value='solid')\
.tag(sync=True, display_name='Line style')
interpolation = Enum(['linear', 'basis', 'basis-open',
'basis-closed', 'bundle',
'cardinal', 'cardinal-open',
'cardinal-closed', 'monotone', 'step-before',
'step-after'],
default_value='linear')\
.tag(sync=True, display_name='Interpolation')
close_path = Bool().tag(sync=True, display_name='Close path')
fill = Enum(['none', 'bottom', 'top', 'inside', 'between'],
default_value='none')\
.tag(sync=True, display_name='Fill')
marker = Enum(['circle', 'cross', 'diamond', 'square', 'triangle-down',
'triangle-up', 'arrow', 'rectangle', 'ellipse'],
default_value=None, allow_none=True)\
.tag(sync=True, display_name='Marker')
marker_size = Int(64).tag(sync=True, display_name='Default size')
opacities = List().tag(sync=True, display_name='Opacity')
fill_opacities = List().tag(sync=True, display_name='Fill Opacity')
_view_name = Unicode('Lines').tag(sync=True)
_model_name = Unicode('LinesModel').tag(sync=True)
@register_mark('bqplot.FlexLine')
class FlexLine(Mark):
"""Flexible Lines mark.
In the case of the FlexLines mark, scales for 'x' and 'y' MUST be provided.
Scales for the color and width data attributes are optional. In the case
where another data attribute than 'x' or 'y' is provided but the
corresponding scale is missing, the data attribute is ignored.
Attributes
----------
name: string (class-level attributes)
user-friendly name of the mark
colors: list of colors (default: CATEGORY10)
List of colors for the Lines
stroke_width: float (default: 1.5)
Default stroke width of the Lines
Data Attributes
x: numpy.ndarray (default: [])
abscissas of the data points (1d array)
y: numpy.ndarray (default: [])
ordinates of the data points (1d array)
color: numpy.ndarray or None (default: None)
Array controlling the color of the data points
width: numpy.ndarray or None (default: None)
Array controlling the widths of the Lines.
"""
# Mark decoration
icon = 'fa-line-chart'
name = 'Flexible lines'
# Scaled attributes
x = Array([]).tag(sync=True, scaled=True, rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
y = Array([]).tag(sync=True, scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
color = Array(None, allow_none=True)\
.tag(sync=True, scaled=True, rtype='Color',
atype='bqplot.ColorAxis',
**array_serialization).valid(array_squeeze)
width = Array(None, allow_none=True)\
.tag(sync=True, scaled=True, rtype='Number',
**array_serialization).valid(array_squeeze)
# Other attributes
scales_metadata = Dict({
'x': {'orientation': 'horizontal', 'dimension': 'x'},
'y': {'orientation': 'vertical', 'dimension': 'y'},
'color': {'dimension': 'color'}
}).tag(sync=True)
stroke_width = Float(1.5).tag(sync=True, display_name='Stroke width')
colors = List(trait=Color(default_value=None, allow_none=True),
default_value=CATEGORY10).tag(sync=True)
_view_name = Unicode('FlexLine').tag(sync=True)
_model_name = Unicode('FlexLineModel').tag(sync=True)
class _ScatterBase(Mark):
"""
Base Mark for Label and Scatter
"""
# Scaled attributes
x = Array([], allow_none=True).tag(sync=True, scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_dimension_bounds(1, 1))
y = Array([], allow_none=True).tag(sync=True, scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_dimension_bounds(1, 1))
color = Array(None, allow_none=True).tag(sync=True,
scaled=True,
rtype='Color',
atype='bqplot.ColorAxis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
opacity = Array(None, allow_none=True).tag(sync=True,
scaled=True,
rtype='Number',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
size = Array(None, allow_none=True).tag(sync=True, scaled=True,
rtype='Number',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
rotation = Array(None, allow_none=True).tag(sync=True, scaled=True,
rtype='Number',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
# Other attributes
scales_metadata = Dict({
'x': {'orientation': 'horizontal', 'dimension': 'x'},
'y': {'orientation': 'vertical', 'dimension': 'y'},
'color': {'dimension': 'color'},
'size': {'dimension': 'size'},
'opacity': {'dimension': 'opacity'},
'rotation': {'dimension': 'rotation'}
}).tag(sync=True)
default_opacities = Array([1.0])\
.tag(sync=True, display_name='Opacities', **array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
hovered_style = Dict().tag(sync=True)
unhovered_style = Dict().tag(sync=True)
hovered_point = Int(None, allow_none=True).tag(sync=True)
enable_move = Bool().tag(sync=True)
enable_delete = Bool().tag(sync=True)
restrict_x = Bool().tag(sync=True)
restrict_y = Bool().tag(sync=True)
update_on_move = Bool().tag(sync=True)
def __init__(self, **kwargs):
self._drag_start_handlers = CallbackDispatcher()
self._drag_handlers = CallbackDispatcher()
self._drag_end_handlers = CallbackDispatcher()
super(_ScatterBase, self).__init__(**kwargs)
def on_drag_start(self, callback, remove=False):
self._drag_start_handlers.register_callback(callback, remove=remove)
def on_drag(self, callback, remove=False):
self._drag_handlers.register_callback(callback, remove=remove)
def on_drag_end(self, callback, remove=False):
self._drag_end_handlers.register_callback(callback, remove=remove)
def _handle_custom_msgs(self, _, content, buffers=None):
event = content.get('event', '')
if event == 'drag_start':
self._drag_start_handlers(self, content)
elif event == 'drag':
self._drag_handlers(self, content)
elif event == 'drag_end':
self._drag_end_handlers(self, content)
super(_ScatterBase, self)._handle_custom_msgs(self, content)
@register_mark('bqplot.Scatter')
class Scatter(_ScatterBase):
"""Scatter mark.
In the case of the Scatter mark, scales for 'x' and 'y' MUST be provided.
The scales of other data attributes are optional. In the case where another
data attribute than 'x' or 'y' is provided but the corresponding scale is
missing, the data attribute is ignored.
Attributes
----------
icon: string (class-level attribute)
Font-awesome icon for that mark
name: string (class-level attribute)
User-friendly name of the mark
marker: {'circle', 'cross', 'diamond', 'square', 'triangle-down', 'triangle-up', 'arrow', 'rectangle', 'ellipse'}
Marker shape
colors: list of colors (default: ['steelblue'])
List of colors of the markers. If the list is shorter than the number
of points, the colors are reused.
default_colors: Deprecated
Same as `colors`, deprecated as of version 0.8.4
fill: Bool (default: True)
Whether to fill the markers or not
stroke: Color or None (default: None)
Stroke color of the marker
stroke_width: Float (default: 1.5)
Stroke width of the marker
default_opacities: list of floats (default: [1.0])
Default opacities of the markers. If the list is shorter than
the number
of points, the opacities are reused.
default_skew: float (default: 0.5)
Default skew of the marker.
This number is validated to be between 0 and 1.
default_size: nonnegative int (default: 64)
Default marker size in pixel.
If size data is provided with a scale, default_size stands for the
maximal marker size (i.e. the maximum value for the 'size' scale range)
drag_size: nonnegative float (default: 5.)
Ratio of the size of the dragged scatter size to the default
scatter size.
names: numpy.ndarray (default: None)
Labels for the points of the chart
display_names: bool (default: True)
Controls whether names are displayed for points in the scatter
enable_move: bool (default: False)
Controls whether points can be moved by dragging. Refer to restrict_x,
restrict_y for more options.
restrict_x: bool (default: False)
Restricts movement of the point to only along the x axis. This is valid
only when enable_move is set to True. If both restrict_x and restrict_y
are set to True, the point cannot be moved.
restrict_y: bool (default: False)
Restricts movement of the point to only along the y axis. This is valid
only when enable_move is set to True. If both restrict_x and restrict_y
are set to True, the point cannot be moved.
Data Attributes
x: numpy.ndarray (default: [])
abscissas of the data points (1d array)
y: numpy.ndarray (default: [])
ordinates of the data points (1d array)
color: numpy.ndarray or None (default: None)
color of the data points (1d array). Defaults to default_color when not
provided or when a value is NaN
opacity: numpy.ndarray or None (default: None)
opacity of the data points (1d array). Defaults to default_opacity when
not provided or when a value is NaN
size: numpy.ndarray or None (default: None)
size of the data points. Defaults to default_size when not provided or
when a value is NaN
skew: numpy.ndarray or None (default: None)
skewness of the markers representing the data points. Defaults to
default_skew when not provided or when a value is NaN
rotation: numpy.ndarray or None (default: None)
orientation of the markers representing the data points.
The rotation scale's range is [0, 180]
Defaults to 0 when not provided or when a value is NaN.
Notes
-----
The fields which can be passed to the default tooltip are:
All the data attributes
index: index of the marker being hovered on
The following are the events which can trigger interactions:
click: left click of the mouse
hover: mouse-over an element
The following are the interactions which can be linked to the above events:
tooltip: display tooltip
add: add new points to the scatter (can only linked to click)
"""
# Mark decoration
icon = 'fa-cloud'
name = 'Scatter'
# Scaled attribtes
skew = Array(None, allow_none=True).tag(sync=True, scaled=True,
rtype='Number',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
# Other attributes
marker = Enum(['circle', 'cross', 'diamond', 'square', 'triangle-down',
'triangle-up', 'arrow', 'rectangle', 'ellipse'],
default_value='circle').tag(sync=True, display_name='Marker')
colors = List(trait=Color(default_value=None, allow_none=True),
default_value=['steelblue'])\
.tag(sync=True, display_name='Colors')
scales_metadata = Dict({
'x': {'orientation': 'horizontal', 'dimension': 'x'},
'y': {'orientation': 'vertical', 'dimension': 'y'},
'color': {'dimension': 'color'},
'size': {'dimension': 'size'},
'opacity': {'dimension': 'opacity'},
'rotation': {'dimension': 'rotation'},
'skew': {'dimension': 'skew'}
}).tag(sync=True)
@property
def default_colors(self):
return self.colors
@default_colors.setter
def default_colors(self, value):
warn("default_colors is deprecated, use colors instead.",
DeprecationWarning)
self.colors = value
stroke = Color(None, allow_none=True).tag(sync=True,
display_name='Stroke color')
stroke_width = Float(1.5).tag(sync=True, display_name='Stroke width')
default_skew = Float(0.5, min=0, max=1).tag(sync=True)
default_size = Int(64).tag(sync=True, display_name='Default size')
names = Array(None, allow_none=True)\
.tag(sync=True, **array_serialization).valid(array_squeeze)
display_names = Bool(True).tag(sync=True, display_name='Display names')
fill = Bool(True).tag(sync=True)
drag_color = Color(None, allow_none=True).tag(sync=True)
drag_size = Float(5.).tag(sync=True)
names_unique = Bool(True).tag(sync=True)
_view_name = Unicode('Scatter').tag(sync=True)
_model_name = Unicode('ScatterModel').tag(sync=True)
@register_mark('bqplot.ScatterGL')
class ScatterGL(Scatter):
_view_name = Unicode('ScatterGL').tag(sync=True)
_model_name = Unicode('ScatterGLModel').tag(sync=True)
@register_mark('bqplot.Label')
class Label(_ScatterBase):
"""Label mark.
Attributes
----------
x_offset: int (default: 0)
horizontal offset in pixels from the stated x location
y_offset: int (default: 0)
vertical offset in pixels from the stated y location
text: string (default: '')
text to be displayed
default_size: string (default: '14px')
font size in px, em or ex
font_weight: {'bold', 'normal', 'bolder'}
font weight of the caption
drag_size: nonnegative float (default: 1.)
Ratio of the size of the dragged label font size to the default
label font size.
align: {'start', 'middle', 'end'}
alignment of the text with respect to the provided location
enable_move: Bool (default: False)
Enable the label to be moved by dragging. Refer to restrict_x,
restrict_y for more options.
restrict_x: bool (default: False)
Restricts movement of the label to only along the x axis. This is valid
only when enable_move is set to True. If both restrict_x and restrict_y
are set to True, the label cannot be moved.
restrict_y: bool (default: False)
Restricts movement of the label to only along the y axis. This is valid
only when enable_move is set to True. If both restrict_x and restrict_y
are set to True, the label cannot be moved.
Data Attributes
x: numpy.ndarray (default: [])
horizontal position of the labels, in data coordinates or in
figure coordinates
y: numpy.ndarray (default: [])
vertical position of the labels, in data coordinates or in
figure coordinates
color: numpy.ndarray or None (default: None)
label colors
size: numpy.ndarray or None (default: None)
label sizes
rotation: numpy.ndarray or None (default: None)
label rotations
opacity: numpy.ndarray or None (default: None)
label opacities
"""
# Mark decoration
icon = 'fa-font'
name = 'Labels'
# Other attributes
x_offset = Int(0).tag(sync=True)
y_offset = Int(0).tag(sync=True)
colors = List(trait=Color(default_value=None,
allow_none=True),
default_value=CATEGORY10)\
.tag(sync=True, display_name='Colors')
rotate_angle = Float(0.0).tag(sync=True)
text = Array(None, allow_none=True)\
.tag(sync=True, **array_serialization).valid(array_squeeze)
default_size = Float(16.).tag(sync=True)
drag_size = Float(1.).tag(sync=True)
font_unit = Enum(['px', 'em', 'pt', '%'],
default_value='px').tag(sync=True)
font_weight = Enum(['bold', 'normal', 'bolder'],
default_value='bold').tag(sync=True)
align = Enum(['start', 'middle', 'end'],
default_value='start').tag(sync=True)
_view_name = Unicode('Label').tag(sync=True)
_model_name = Unicode('LabelModel').tag(sync=True)
@register_mark('bqplot.Hist')
class Hist(Mark):
"""Histogram mark.
In the case of the Hist mark, scales for 'sample' and 'count' MUST be
provided.
Attributes
----------
icon: string (class-level attribute)
font-awesome icon for that mark
name: string (class-level attribute)
user-friendly name of the mark
bins: nonnegative int (default: 10)
number of bins in the histogram
normalized: bool (default: False)
Boolean attribute to return normalized values which
sum to 1 or direct counts for the `count` attribute. The scale of
`count` attribute is determined by the value of this flag.
colors: list of colors (default: ['steelblue'])
List of colors of the Histogram. If the list is shorter than the number
of bins, the colors are reused.
stroke: Color or None (default: None)
Stroke color of the histogram
opacities: list of floats (default: [])
Opacity for the bins of the histogram. Defaults to 1 when the list
is too short, or the element of the list is set to None.
midpoints: list (default: [])
midpoints of the bins of the histogram. It is a read-only attribute.
Data Attributes
sample: numpy.ndarray (default: [])
sample of which the histogram must be computed.
count: numpy.ndarray (read-only)
number of sample points per bin. It is a read-only attribute.
Notes
-----
The fields which can be passed to the default tooltip are:
midpoint: mid-point of the bin related to the rectangle hovered on
count: number of elements in the bin hovered on
bin_start: start point of the bin
bin-end: end point of the bin
index: index of the bin
"""
# Mark decoration
icon = 'fa-signal'
name = 'Histogram'
# Scaled attributes
sample = Array([]).tag(sync=True, display_name='Sample',
scaled=True, rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
count = Array([], read_only=True).tag(sync=True,
display_name='Count',
scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze)
normalized = Bool().tag(sync=True)
# Other attributes
scales_metadata = Dict({
'sample': {'orientation': 'horizontal', 'dimension': 'x'},
'count': {'orientation': 'vertical', 'dimension': 'y'}
}).tag(sync=True)
bins = Int(10).tag(sync=True, display_name='Number of bins')
midpoints = List(read_only=True).tag(sync=True, display_name='Mid points')
# midpoints is a read-only attribute that is set when the mark is drawn
colors = List(trait=Color(default_value=None, allow_none=True),
default_value=['steelblue'])\
.tag(sync=True, display_name='Colors')
stroke = Color(None, allow_none=True).tag(sync=True)
opacities = List(trait=Float(1.0, min=0, max=1, allow_none=True))\
.tag(sync=True, display_name='Opacities')
_view_name = Unicode('Hist').tag(sync=True)
_model_name = Unicode('HistModel').tag(sync=True)
@register_mark('bqplot.Boxplot')
class Boxplot(Mark):
"""Boxplot marks.
Attributes
----------
stroke: Color or None
stroke color of the marker
color: Color
fill color of the box
opacities: list of floats (default: [])
Opacities for the markers of the boxplot. Defaults to 1 when the
list is too short, or the element of the list is set to None.
outlier-color: color
color for the outlier
box_width: int (default: None)
width of the box in pixels. The minimum value is 5.
If set to None, box_with is auto calculated
auto_detect_outliers: bool (default: True)
Flag to toggle outlier auto-detection
Data Attributes
x: numpy.ndarray (default: [])
abscissas of the data points (1d array)
y: numpy.ndarray (default: [[]])
Sample data points (2d array)
"""
# Mark decoration
icon = 'fa-birthday-cake'
name = 'Boxplot chart'
# Scaled attributes
x = Array([]).tag(sync=True, scaled=True, rtype='Number',
atype='bqplot.Axis', **array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
# Second dimension must contain OHLC data, otherwise the behavior
# is undefined.
y = Array([[]]).tag(sync=True, scaled=True, rtype='Number',
atype='bqplot.Axis', **array_serialization)\
.valid(array_dimension_bounds(1, 2), array_supported_kinds())
# Other attributes
scales_metadata = Dict({
'x': {'orientation': 'horizontal', 'dimension': 'x'},
'y': {'orientation': 'vertical', 'dimension': 'y'}
}).tag(sync=True)
stroke = Color(None, allow_none=True)\
.tag(sync=True, display_name='Stroke color')
box_fill_color = Color('steelblue', sync=True,
display_name='Fill color for the box')
outlier_fill_color = Color('gray').tag(sync=True,
display_name='Outlier fill color')
opacities = List(trait=Float(1.0, min=0, max=1, allow_none=True))\
.tag(sync=True, display_name='Opacities')
box_width = Int(None, min=5, allow_none=True).tag(sync=True, display_name='Box Width')
auto_detect_outliers = Bool(True).tag(sync=True, display_name='Auto-detect Outliers')
_view_name = Unicode('Boxplot').tag(sync=True)
_model_name = Unicode('BoxplotModel').tag(sync=True)
@register_mark('bqplot.Bars')
class Bars(Mark):
"""Bar mark.
In the case of the Bars mark, scales for 'x' and 'y' MUST be provided.
The scales of other data attributes are optional. In the case where another
data attribute than 'x' or 'y' is provided but the corresponding scale is
missing, the data attribute is ignored.
Attributes
----------
icon: string (class-level attribute)
font-awesome icon for that mark
name: string (class-level attribute)
user-friendly name of the mark
color_mode: {'auto', 'group', 'element'}
enum attribute to specify if color should be the same for all bars with
the same x or for all bars which belong to the same array in Y
'group' means for every x all bars have same color.
'element' means for every dimension of y, all bars have same color.
'auto' picks 'group' and 'element' for 1-d and 2-d values of
Y respectively.
type: {'stacked', 'grouped'}
whether 2-dimensional bar charts should appear grouped or stacked.
colors: list of colors (default: ['steelblue'])
list of colors for the bars.
orientation: {'horizontal', 'vertical'}
Specifies whether the bar chart is drawn horizontally or vertically.
If a horizontal bar chart is drawn, the x data is drawn vertically.
padding: float (default: 0.05)
Attribute to control the spacing between the bars value is specified
as a percentage of the width of the bar
fill: Bool (default: True)
Whether to fill the bars or not
stroke: Color or None (default: None)
Stroke color for the bars
stroke_width: Float (default: 0.)
Stroke width of the bars
opacities: list of floats (default: [])
Opacities for the bars. Defaults to 1 when the list is too
short, or the element of the list is set to None.
base: float (default: 0.0)
reference value from which the bars are drawn. defaults to 0.0
align: {'center', 'left', 'right'}
alignment of bars with respect to the tick value
label_display: bool (default: False)
whether or not to display bar data labels
label_display_format: string (default: .2f)
format for displaying values.
label_font_style: dict
CSS style for the text of each cell
label_display_vertical_offset: float
vertical offset value for the label display
label_display_horizontal_offset: float
horizontal offset value for the label display
Data Attributes
x: numpy.ndarray (default: [])
abscissas of the data points (1d array)
y: numpy.ndarray (default: [])
ordinates of the values for the data points
color: numpy.ndarray or None (default: None)
color of the data points (1d array). Defaults to default_color when not
provided or when a value is NaN
Notes
-----
The fields which can be passed to the default tooltip are:
All the data attributes
index: index of the bar being hovered on
sub_index: if data is two dimensional, this is the minor index
"""
# Mark decoration
icon = 'fa-bar-chart'
name = 'Bar chart'
# Scaled attributes
x = Array([]).tag(sync=True, scaled=True, rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
y = Array([]).tag(sync=True, scaled=True, rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_dimension_bounds(1, 2), array_supported_kinds())
color = Array(None, allow_none=True)\
.tag(sync=True, scaled=True, rtype='Color',
atype='bqplot.ColorAxis', **array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
# Bar text labels attributes -- add default values.
# Add bool for displaying a label or not. Add d3 formatting in docstring
label_display = Bool(default_value=False).tag(sync=True)
label_display_format = Unicode(default_value=".2f",
allow_none=False).tag(sync=True)
label_font_style = Dict().tag(sync=True)
label_display_vertical_offset = Float(default_value=0.0,
allow_none=False).tag(sync=True)
label_display_horizontal_offset = Float(default_value=0.0,
allow_none=False).tag(sync=True)
# Other attributes
scales_metadata = Dict({
'x': {'orientation': 'horizontal', 'dimension': 'x'},
'y': {'orientation': 'vertical', 'dimension': 'y'},
'color': {'dimension': 'color'}
}).tag(sync=True)
color_mode = Enum(['auto', 'group', 'element'], default_value='auto')\
.tag(sync=True)
type = Enum(['stacked', 'grouped'], default_value='stacked')\
.tag(sync=True, display_name='Type')
colors = List(trait=Color(default_value=None,
allow_none=True),
default_value=['steelblue'])\
.tag(sync=True, display_name='Colors')
padding = Float(0.05).tag(sync=True)
fill = Bool(True).tag(sync=True)
stroke = Color(None, allow_none=True).tag(sync=True)
stroke_width = Float(1.).tag(sync=True, display_name='Stroke width')
base = Float().tag(sync=True)
opacities = List(trait=Float(1.0, min=0, max=1, allow_none=True))\
.tag(sync=True, display_name='Opacities')
align = Enum(['center', 'left', 'right'], default_value='center')\
.tag(sync=True)
orientation = Enum(['vertical', 'horizontal'], default_value='vertical')\
.tag(sync=True)
@validate('orientation')
def _validate_orientation(self, proposal):
value = proposal['value']
x_orient = "horizontal" if value == "vertical" else "vertical"
self.scales_metadata = {'x': {'orientation': x_orient,
'dimension': 'x'},
'y': {'orientation': value, 'dimension': 'y'}}
return value
_view_name = Unicode('Bars').tag(sync=True)
_model_name = Unicode('BarsModel').tag(sync=True)
@register_mark('bqplot.Bins')
class Bins(Bars):
"""Backend histogram mark.
A `Bars` instance that bins sample data.
It is very similar in purpose to the `Hist` mark, the difference being that
the binning is done in the backend (python), which avoids large amounts of
data being shipped back and forth to the frontend. It should therefore be
preferred for large data.
The binning method is the numpy `histogram` method.
The following documentation is in part taken from the numpy documentation.
Attributes
----------
icon: string (class-level attribute)
font-awesome icon for that mark
name: string (class-level attribute)
user-friendly name of the mark
bins: nonnegative int (default: 10)
or {'auto', 'fd', 'doane', 'scott', 'rice', 'sturges', 'sqrt'}
If `bins` is an int, it defines the number of equal-width
bins in the given range (10, by default).
If `bins` is a string (method name), `histogram` will use
the method chosen to calculate the optimal bin width and
consequently the number of bins (see `Notes` for more detail on
the estimators) from the data that falls within the requested
range.
density : bool (default: `False`)
If `False`, the height of each bin is the number of samples in it.
If `True`, the height of each bin is the value of the
probability *density* function at the bin, normalized such that
the *integral* over the range is 1. Note that the sum of the
histogram values will not be equal to 1 unless bins of unity
width are chosen; it is not a probability *mass* function.
min : float (default: None)
The lower range of the bins. If not provided, lower range
is simply `x.min()`.
max : float (default: None)
The upper range of the bins. If not provided, lower range
is simply `x.max()`.
Data Attributes
sample: numpy.ndarray (default: [])
sample of which the histogram must be computed.
Notes
-----
The fields which can be passed to the default tooltip are:
All the `Bars` data attributes (`x`, `y`, `color`)
index: index of the bin
"""
# Mark decoration
icon = 'fa-signal'
name = 'Backend Histogram'
# Scaled Attributes
sample = Array([]).tag(
sync=False, display_name='Sample', rtype='Number',
atype='bqplot.Axis', **array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
# Binning options
min = Float(None, allow_none=True).tag(sync=True)
max = Float(None, allow_none=True).tag(sync=True)
density = Bool().tag(sync=True)
bins = (Int(10) | List() | Enum(['auto', 'fd', 'doane',
'scott', 'rice', 'sturges', 'sqrt']))\
.tag(sync=True, display_name='Number of bins')
def __init__(self, **kwargs):
'''
Sets listeners on the data and the binning parameters.
Adjusts `Bars` defaults to suit a histogram better.
'''
self.observe(self.bin_data,
names=['sample', 'bins', 'density', 'min', 'max'])
# One unique color by default
kwargs.setdefault('colors', [CATEGORY10[0]])
# No spacing between bars
kwargs.setdefault('padding', 0.)
super(Bins, self).__init__(**kwargs)
def bin_data(self, *args):
'''
Performs the binning of `sample` data, and draws the corresponding bars
'''
# Get range
_min = self.sample.min() if self.min is None else self.min
_max = self.sample.max() if self.max is None else self.max
_range = (min(_min, _max), max(_min, _max))
# Bin the samples
counts, bin_edges = histogram(self.sample, bins=self.bins,
range=_range, density=self.density)
midpoints = (bin_edges[:-1] + bin_edges[1:]) / 2
# Redraw the underlying Bars
with self.hold_sync():
self.x, self.y = midpoints, counts
@register_mark('bqplot.OHLC')
class OHLC(Mark):
"""Open/High/Low/Close marks.
Attributes
----------
icon: string (class-level attribute)
font-awesome icon for that mark
name: string (class-level attribute)
user-friendly name of the mark
marker: {'candle', 'bar'}
marker type
stroke: color (default: None)
stroke color of the marker
stroke_width: float (default: 1.0)
stroke width of the marker
colors: List of colors (default: ['limegreen', 'red'])
fill colors for the markers (up/down)
opacities: list of floats (default: [])
Opacities for the markers of the OHLC mark. Defaults to 1 when
the list is too short, or the element of the list is set to None.
format: string (default: 'ohlc')
description of y data being passed
supports all permutations of the strings 'ohlc', 'oc', and 'hl'
Data Attributes
x: numpy.ndarray
abscissas of the data points (1d array)
y: numpy.ndarrays
Open/High/Low/Close ordinates of the data points (2d array)
Notes
-----
The fields which can be passed to the default tooltip are:
x: the x value associated with the bar/candle
open: open value for the bar/candle
high: high value for the bar/candle
low: low value for the bar/candle
close: close value for the bar/candle
index: index of the bar/candle being hovered on
"""
# Mark decoration
icon = 'fa-birthday-cake'
name = 'OHLC chart'
# Scaled attributes
x = Array([]).tag(sync=True, scaled=True,
rtype='Number', atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
y = Array([[]]).tag(sync=True, scaled=True,
rtype='Number', atype='bqplot.Axis',
**array_serialization)\
.valid(array_dimension_bounds(1, 2))
# Other attributes
scales_metadata = Dict({
'x': {'orientation': 'horizontal', 'dimension': 'x'},
'y': {'orientation': 'vertical', 'dimension': 'y'}
}).tag(sync=True)
marker = Enum(['candle', 'bar'], default_value='candle',
display_name='Marker').tag(sync=True)
stroke = Color(None, display_name='Stroke color', allow_none=True)\
.tag(sync=True)
stroke_width = Float(1.0).tag(sync=True, display_name='Stroke Width')
colors = List(trait=Color(default_value=None, allow_none=True),
default_value=['green', 'red'])\
.tag(sync=True, display_name='Colors')
opacities = List(trait=Float(1.0, min=0, max=1, allow_none=True))\
.tag(sync=True, display_name='Opacities')
format = Unicode('ohlc').tag(sync=True, display_name='Format')
_view_name = Unicode('OHLC').tag(sync=True)
_model_name = Unicode('OHLCModel').tag(sync=True)
@register_mark('bqplot.Pie')
class Pie(Mark):
"""Piechart mark.
Attributes
----------
colors: list of colors (default: CATEGORY10)
list of colors for the slices.
stroke: color (default: 'white')
stroke color for the marker
opacities: list of floats (default: [])
Opacities for the slices of the Pie mark. Defaults to 1 when the list
is too short, or the element of the list is set to None.
sort: bool (default: False)
sort the pie slices by descending sizes
x: Float (default: 0.5) or Date
horizontal position of the pie center, in data coordinates or in figure
coordinates
y: Float (default: 0.5)
vertical y position of the pie center, in data coordinates or in figure
coordinates
radius: Float
radius of the pie, in pixels
inner_radius: Float
inner radius of the pie, in pixels
start_angle: Float (default: 0.0)
start angle of the pie (from top), in degrees
end_angle: Float (default: 360.0)
end angle of the pie (from top), in degrees
display_labels: {'none', 'inside', 'outside'} (default: 'inside')
label display options
display_values: bool (default: False)
if True show values along with labels
values_format: string (default: '.2f')
format for displaying values
label_color: Color or None (default: None)
color of the labels
font_size: string (default: '14px')
label font size in px, em or ex
font_weight: {'bold', 'normal', 'bolder'} (default: 'normal')
label font weight
Data Attributes
sizes: numpy.ndarray (default: [])
proportions of the pie slices
color: numpy.ndarray or None (default: None)
color of the data points. Defaults to colors when not provided.
Notes
-----
The fields which can be passed to the default tooltip are:
: the x value associated with the bar/candle
open: open value for the bar/candle
high: high value for the bar/candle
low: low value for the bar/candle
close: close value for the bar/candle
index: index of the bar/candle being hovered on
"""
# Mark decoration
icon = 'fa-pie-chart'
name = 'Pie chart'
# Scaled attributes
sizes = Array([]).tag(sync=True, rtype='Number', **array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
color = Array(None, allow_none=True).tag(sync=True,
scaled=True,
rtype='Color',
atype='bqplot.ColorAxis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
# Other attributes
x = (Float(0.5) | Date() | Unicode()).tag(sync=True)
y = (Float(0.5) | Date() | Unicode()).tag(sync=True)
scales_metadata = Dict({'color': {'dimension': 'color'}}).tag(sync=True)
sort = Bool().tag(sync=True)
colors = List(trait=Color(default_value=None, allow_none=True),
default_value=CATEGORY10).tag(sync=True,
display_name='Colors')
stroke = Color(None, allow_none=True).tag(sync=True)
opacities = List(trait=Float(1.0, min=0, max=1, allow_none=True))\
.tag(sync=True, display_name='Opacities')
radius = Float(180.0, min=0.0, max=float('inf')).tag(sync=True)
inner_radius = Float(0.1, min=0.0, max=float('inf')).tag(sync=True)
start_angle = Float().tag(sync=True)
end_angle = Float(360.0).tag(sync=True)
display_labels = Enum(['none', 'inside', 'outside'],
default_value='inside').tag(sync=True)
display_values = Bool(False).tag(sync=True)
values_format = Unicode(default_value='.1f').tag(sync=True)
label_color = Color(None, allow_none=True).tag(sync=True)
font_size = Unicode(default_value='12px').tag(sync=True)
font_weight = Enum(['bold', 'normal', 'bolder'],
default_value='normal').tag(sync=True)
_view_name = Unicode('Pie').tag(sync=True)
_model_name = Unicode('PieModel').tag(sync=True)
def topo_load(name):
with open(os.path.join(os.path.split(os.path.realpath(__file__))[0],
name)) as data_file:
data = json.load(data_file)
return data
@register_mark('bqplot.Map')
class Map(Mark):
"""Map mark.
Attributes
----------
colors: Dict (default: {})
default colors for items of the map when no color data is passed.
The dictionary should be indexed by the id of the element and have
the corresponding colors as values. The key `default_color`
controls the items for which no color is specified.
selected_styles: Dict (default: {'selected_fill': 'Red',
'selected_stroke': None, 'selected_stroke_width': 2.0})
Dictionary containing the styles for selected subunits
hovered_styles: Dict (default: {'hovered_fill': 'Orange',
'hovered_stroke': None, 'hovered_stroke_width': 2.0})
Dictionary containing the styles for hovered subunits
hover_highlight: bool (default: True)
boolean to control if the map should be aware of which country is being
hovered on.
map_data: dict (default: topo_load("map_data/WorldMap.json"))
a topojson-formatted dictionary with the objects to map under the key
'subunits'.
Data Attributes
color: Dict or None (default: None)
dictionary containing the data associated with every country for the
color scale
"""
# Mark decoration
icon = 'fa-globe'
name = 'Map'
# Scaled attributes
color = Dict(allow_none=True).tag(sync=True, scaled=True, rtype='Color',
atype='bqplot.ColorAxis')
# Other attributes
scales_metadata = Dict({'color': {'dimension': 'color'}}).tag(sync=True)
hover_highlight = Bool(True).tag(sync=True)
hovered_styles = Dict({
'hovered_fill': 'Orange',
'hovered_stroke': None,
'hovered_stroke_width': 2.0}, allow_none=True).tag(sync=True)
stroke_color = Color(default_value=None, allow_none=True).tag(sync=True)
colors = Dict().tag(sync=True, display_name='Colors')
scales_metadata = Dict({'color': {'dimension': 'color'},
'projection': {'dimension': 'geo'}}).tag(sync=True)
selected_styles = Dict({
'selected_fill': 'Red',
'selected_stroke': None,
'selected_stroke_width': 2.0
}).tag(sync=True)
map_data = Dict(topo_load('map_data/WorldMap.json')).tag(sync=True)
_view_name = Unicode('Map').tag(sync=True)
_model_name = Unicode('MapModel').tag(sync=True)
@register_mark('bqplot.GridHeatMap')
class GridHeatMap(Mark):
"""GridHeatMap mark.
Alignment: The tiles can be aligned so that the data matches either the
start, the end or the midpoints of the tiles. This is controlled by the
align attribute.
Suppose the data passed is a m-by-n matrix. If the scale for the rows is
Ordinal, then alignment is by default the mid points. For a non-ordinal
scale, the data cannot be aligned to the mid points of the rectangles.
If it is not ordinal, then two cases arise. If the number of rows passed
is m, then align attribute can be used. If the number of rows passed
is m+1, then the data are the boundaries of the m rectangles.
If rows and columns are not passed, and scales for them are also
not passed, then ordinal scales are generated for the rows and columns.
Attributes
----------
row_align: Enum(['start', 'end'])
This is only valid if the number of entries in `row` exactly match the
number of rows in `color` and the `row_scale` is not `OrdinalScale`.
`start` aligns the row values passed to be aligned with the start
of the tiles and `end` aligns the row values to the end of the tiles.
column_align: Enum(['start', end'])
This is only valid if the number of entries in `column` exactly
match the number of columns in `color` and the `column_scale` is
not `OrdinalScale`. `start` aligns the column values passed to
be aligned with the start of the tiles and `end` aligns the
column values to the end of the tiles.
anchor_style: dict (default: {})
Controls the style for the element which serves as the anchor during
selection.
display_format: string (default: None)
format for displaying values. If None, then values are not displayed
font_style: dict
CSS style for the text of each cell
Data Attributes
color: numpy.ndarray or None (default: None)
color of the data points (2d array). The number of elements in
this array correspond to the number of cells created in the heatmap.
row: numpy.ndarray or None (default: None)
labels for the rows of the `color` array passed. The length of
this can be no more than 1 away from the number of rows in `color`.
This is a scaled attribute and can be used to affect the height of the
cells as the entries of `row` can indicate the start or the end points
of the cells. Refer to the property `row_align`.
If this property is None, then a uniformly spaced grid is generated in
the row direction.
column: numpy.ndarray or None (default: None)
labels for the columns of the `color` array passed. The length of
this can be no more than 1 away from the number of columns in `color`
This is a scaled attribute and can be used to affect the width of the
cells as the entries of `column` can indicate the start or the
end points of the cells. Refer to the property `column_align`.
If this property is None, then a uniformly spaced grid is generated in
the column direction.
"""
# Scaled attributes
row = Array(None, allow_none=True).tag(sync=True, scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
column = Array(None, allow_none=True).tag(sync=True, scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
color = Array(None, allow_none=True).tag(sync=True, scaled=True,
rtype='Color',
atype='bqplot.ColorAxis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 2))
# Other attributes
scales_metadata = Dict({
'row': {'orientation': 'vertical', 'dimension': 'y'},
'column': {'orientation': 'horizontal', 'dimension': 'x'},
'color': {'dimension': 'color'}
}).tag(sync=True)
row_align = Enum(['start', 'end'], default_value='start').tag(sync=True)
column_align = Enum(['start', 'end'], default_value='start').tag(sync=True)
null_color = Color('black', allow_none=True).tag(sync=True)
stroke = Color('black', allow_none=True).tag(sync=True)
opacity = Float(1.0, min=0.2, max=1).tag(sync=True, display_name='Opacity')
anchor_style = Dict().tag(sync=True)
display_format = Unicode(default_value=None, allow_none=True)\
.tag(sync=True)
font_style = Dict().tag(sync=True)
def __init__(self, **kwargs):
# Adding scales in case they are not passed too.
scales = kwargs.pop('scales', {})
if(scales.get('row', None) is None):
row_scale = OrdinalScale(reverse=True)
scales['row'] = row_scale
if(scales.get('column', None) is None):
column_scale = OrdinalScale()
scales['column'] = column_scale
kwargs['scales'] = scales
super(GridHeatMap, self).__init__(**kwargs)
@validate('row')
def _validate_row(self, proposal):
row = proposal.value
if row is None:
return row
color = np.asarray(self.color)
n_rows = color.shape[0]
if len(row) != n_rows and len(row) != n_rows + 1 and len(row) != n_rows - 1:
raise TraitError('row must be an array of size color.shape[0]')
return row
@validate('column')
def _validate_column(self, proposal):
column = proposal.value
if column is None:
return column
color = np.asarray(self.color)
n_columns = color.shape[1]
if len(column) != n_columns and len(column) != n_columns + 1 and len(column) != n_columns - 1:
raise TraitError('column must be an array of size color.shape[1]')
return column
_view_name = Unicode('GridHeatMap').tag(sync=True)
_model_name = Unicode('GridHeatMapModel').tag(sync=True)
@register_mark('bqplot.HeatMap')
class HeatMap(Mark):
"""HeatMap mark.
Attributes
----------
Data Attributes
color: numpy.ndarray or None (default: None)
color of the data points (2d array).
x: numpy.ndarray or None (default: None)
labels for the columns of the `color` array passed. The length of
this has to be the number of columns in `color`.
This is a scaled attribute.
y: numpy.ndarray or None (default: None)
labels for the rows of the `color` array passed. The length of this has
to be the number of rows in `color`.
This is a scaled attribute.
"""
# Scaled attributes
x = Array(None, allow_none=True).tag(sync=True, scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
y = Array(None, allow_none=True).tag(sync=True, scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
color = Array(None, allow_none=True).tag(sync=True, scaled=True,
rtype='Color',
atype='bqplot.ColorAxis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(2, 2))
# Other attributes
scales_metadata = Dict({
'x': {'orientation': 'horizontal', 'dimension': 'x'},
'y': {'orientation': 'vertical', 'dimension': 'y'},
'color': {'dimension': 'color'}
}).tag(sync=True)
null_color = Color('black', allow_none=True).tag(sync=True)
def __init__(self, **kwargs):
data = kwargs['color']
kwargs.setdefault('x', range(data.shape[1]))
kwargs.setdefault('y', range(data.shape[0]))
scales = kwargs.pop('scales', {})
# Adding default x and y data if they are not passed.
# Adding scales in case they are not passed too.
if(scales.get('x', None) is None):
x_scale = LinearScale()
scales['x'] = x_scale
if(scales.get('y', None) is None):
y_scale = LinearScale()
scales['y'] = y_scale
kwargs['scales'] = scales
super(HeatMap, self).__init__(**kwargs)
_view_name = Unicode('HeatMap').tag(sync=True)
_model_name = Unicode('HeatMapModel').tag(sync=True)
@register_mark('bqplot.Graph')
class Graph(Mark):
"""Graph with nodes and links.
Attributes
----------
node_data: List
list of node attributes for the graph
link_matrix: numpy.ndarray of shape(len(nodes), len(nodes))
link data passed as 2d matrix
link_data: List
list of link attributes for the graph
charge: int (default: -300)
charge of force layout. Will be ignored when x and y data attributes
are set
link_distance: float (default: 100)
link distance in pixels between nodes. Will be ignored when x and y
data attributes are set
link_type: {'arc', 'line', 'slant_line'} (default: 'arc')
Enum representing link type
directed: bool (default: True)
directed or undirected graph
highlight_links: bool (default: True)
highlights incoming and outgoing links when hovered on a node
colors: list (default: CATEGORY10)
list of node colors
Data Attributes
x: numpy.ndarray (default: [])
abscissas of the node data points (1d array)
y: numpy.ndarray (default: [])
ordinates of the node data points (1d array)
color: numpy.ndarray or None (default: None)
color of the node data points (1d array).
link_color: numpy.ndarray of shape(len(nodes), len(nodes))
link data passed as 2d matrix
"""
charge = Int(-600).tag(sync=True)
link_distance = Float(100).tag(sync=True)
node_data = List().tag(sync=True)
link_data = List().tag(sync=True)
link_matrix = Array([]).tag(sync=True, rtype='Number',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 2))
link_type = Enum(['arc', 'line', 'slant_line'],
default_value='arc').tag(sync=True)
directed = Bool(True).tag(sync=True)
colors = List(trait=Color(default_value=None, allow_none=True),
default_value=CATEGORY10).tag(sync=True,
display_name='Colors')
interactions = Dict({'hover': 'tooltip', 'click': 'select'}).tag(sync=True)
highlight_links = Bool(True).tag(sync=True)
# Scaled attributes
x = Array([], allow_none=True).tag(sync=True,
scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_dimension_bounds(1, 1))
y = Array([], allow_none=True).tag(sync=True,
scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_dimension_bounds(1, 1))
color = Array(None, allow_none=True).tag(sync=True,
scaled=True,
rtype='Color',
atype='bqplot.ColorAxis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 1))
link_color = Array([]).tag(sync=True, rtype='Color',
atype='bqplot.ColorAxis',
**array_serialization)\
.valid(array_squeeze, array_dimension_bounds(1, 2))
hovered_style = Dict().tag(sync=True)
unhovered_style = Dict().tag(sync=True)
hovered_point = Int(None, allow_none=True).tag(sync=True)
# Other attributes
scales_metadata = Dict({
'x': {'orientation': 'horizontal', 'dimension': 'x'},
'y': {'orientation': 'vertical', 'dimension': 'y'},
'color': {'dimension': 'color'},
'link_color': {'dimension': 'link_color'}
}).tag(sync=True)
_model_name = Unicode('GraphModel').tag(sync=True)
_view_name = Unicode('Graph').tag(sync=True)
@register_mark('bqplot.Image')
class Image(Mark):
"""Image mark, based on the ipywidgets image
If no scales are passed, uses the parent Figure scales.
Attributes
----------
image: Instance of ipywidgets.Image
Image to be displayed
Data Attributes
x: tuple (default: (0, 1))
abscissas of the left and right-hand side of the image
in the format (x0, x1)
y: tuple (default: (0, 1))
ordinates of the bottom and top side of the image
in the format (y0, y1)
"""
_view_name = Unicode('Image').tag(sync=True)
_model_name = Unicode('ImageModel').tag(sync=True)
image = Instance(widgets.Image).tag(sync=True, **widget_serialization)
x = Array(default_value=(0, 1)).tag(sync=True, scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, shape(2))
y = Array(default_value=(0, 1)).tag(sync=True, scaled=True,
rtype='Number',
atype='bqplot.Axis',
**array_serialization)\
.valid(array_squeeze, shape(2))
scales_metadata = Dict({
'x': {'orientation': 'horizontal', 'dimension': 'x'},
'y': {'orientation': 'vertical', 'dimension': 'y'},
}).tag(sync=True)