In [1]:
from bqplot import *

import numpy as np

ColorScale

The colors for the ColorScale can be defined one of two ways:

  • Manually, by setting the scale's colors attribute to a list of css colors. They can be either:
    • html colors (link) 'white'
    • hex '#000000'
    • rgb 'rgb(0, 0, 0)'.
col_sc = ColorScale(colors=['yellow', 'red'])
  • Using one of bqplot's color-schemes. As of now we support all the colorbrewer schemes (link), as well as the matplotlib schemes 'viridis', 'magma', 'inferno' and 'plasma'.
    col_sc = ColorScale(scheme=['viridis'])
    

The color scale then linearly interpolates between its colors.

ColorAxis

A ColorAxis, like other Axis types, takes a color scale as input. It can then be displayed in a Figure.

ax_col = ColorAxis(scale=col_sc)

In [2]:
size = 100
np.random.seed(0)
x_data = range(size)
y_data = np.cumsum(np.random.randn(size) * 100.0)

def create_figure(color_scale, color_data):

    scales = {'x': LinearScale(), 'y': LinearScale(), 'color': color_scale}
    scatter = Scatter(x=x_data, y=y_data, color=color_data,
                      scales=scales, 
                      stroke='black')
    ax_y = Axis(label='Price', scale=scales['y'], 
                orientation='vertical', side='left')
    ax_x = Axis(label='Day', scale=scales['x'], num_ticks=10, label_location='end')
    ax_c = ColorAxis(scale=color_scale, label='Returns', orientation='vertical', side='right')
    ax_y = Axis(scale=scales['y'], 
                orientation='vertical', side='left')
    ax_x = Axis(scale=scales['x'], num_ticks=10, label_location='end')
    ax_c = ColorAxis(scale=color_scale, orientation='vertical', side='right')

    m_chart = dict(top=50, bottom=70, left=50, right=100)

    return Figure(axes=[ax_x, ax_y, ax_c], title='Up and Down',
                  marks=[scatter], fig_margin=m_chart,)

col_sc = ColorScale()
create_figure(col_sc, y_data)


Attributes

ColorScales share attributes with the other Scale types:

  • Their domain can be manually constrained with the min and max attributes
  • They can be inversed by setting the reverse attribute to True

In [3]:
col_sc.min = 0

In [4]:
col_sc.reverse = True

Mid

In addition they also have a mid attribute, a value that will be mapped to the middle color. This is especially suited to diverging color schemes.


In [5]:
col_sc.min = None
col_sc.mid = 0

DateColorScale

The DateColorScale is a color scale for dates. It works in every way like the regular ColorScale, except that its min, mid and max attributes — if defined — must be date elements (datetime, numpy or pandas).


In [6]:
import pandas as pd

date_col_sc = DateColorScale()
dates = pd.date_range(start='01-01-2007', periods=size)
create_figure(date_col_sc, dates)



In [7]:
date_col_sc.min = pd.datetime(2007,2,28)


---------------------------------------------------------------------------
TraitError                                Traceback (most recent call last)
<ipython-input-7-a139b5e3506c> in <module>()
----> 1 date_col_sc.min = pd.datetime(2007,2,28)

~/.local/lib/python3.5/site-packages/traitlets/traitlets.py in __set__(self, obj, value)
    583             raise TraitError('The "%s" trait is read-only.' % self.name)
    584         else:
--> 585             self.set(obj, value)
    586 
    587     def _validate(self, obj, value):

~/.local/lib/python3.5/site-packages/traitlets/traitlets.py in set(self, obj, value)
    557 
    558     def set(self, obj, value):
--> 559         new_value = self._validate(obj, value)
    560         try:
    561             old_value = obj._trait_values[self.name]

~/.local/lib/python3.5/site-packages/traitlets/traitlets.py in _validate(self, obj, value)
    589             return value
    590         if hasattr(self, 'validate'):
--> 591             value = self.validate(obj, value)
    592         if obj._cross_validation_lock is False:
    593             value = self._cross_validate(obj, value)

~/.local/lib/python3.5/site-packages/traitlets/traitlets.py in validate(self, obj, value)
   1974             value = float(value)
   1975         if not isinstance(value, float):
-> 1976             self.error(obj, value)
   1977         return _validate_bounds(self, obj, value)
   1978 

~/.local/lib/python3.5/site-packages/traitlets/traitlets.py in error(self, obj, value)
    623             e = "The '%s' trait must be %s, but a value of %r was specified." \
    624                 % (self.name, self.info(), repr_type(value))
--> 625         raise TraitError(e)
    626 
    627     def get_metadata(self, key, default=None):

TraitError: The 'min' trait of a DateColorScale instance must be a float, but a value of datetime.datetime(2007, 2, 28, 0, 0) <class 'datetime.datetime'> was specified.

Color Schemes

Use the following widgets to browse through the available color schemes


In [8]:
from bqplot.market_map import MarketMap

from ipywidgets import IntSlider, SelectionSlider, Dropdown
from ipywidgets import VBox, HBox, Layout
from traitlets import link

Diverging schemes


In [9]:
div_schemes = [
    'Spectral',
    'RdYlGn',
    'RdBu',
    'PiYG',
    'PRGn',
    'RdYlBu',
    'BrBG',
    'RdGy',
    'PuOr',
]

In [10]:
def scheme_inspector(fig, schemes, title=''):
    '''
    Takes a Figure and a list of schemes and returns the Figure along with
    sliders to go through the different schemes.
    
    Supposes that the 
    '''
    
    # Get the color scale
    col_sc = fig.marks[0].scales['color']
    
    # Create the widgets to select the colorscheme
    scheme_slider = SelectionSlider(description='',
                                    options=schemes)
    scheme_dd = Dropdown(description='Scheme',
                         options=schemes)
    link((scheme_dd, 'value'), (scheme_slider, 'value'))

    def update_scheme(*args):
        col_sc.scheme = scheme_slider.value
        # ax_c.label = scheme_slider.value

    scheme_slider.observe(update_scheme, 'value')
    scheme_dd.observe(update_scheme, 'value')
    
    update_scheme()

    return VBox([HBox([scheme_dd, scheme_slider]), fig])

scheme_inspector(create_figure(ColorScale(), y_data), div_schemes)


Non-diverging schemes


In [11]:
lin_schemes = [
    'OrRd',
    'PuBu',
    'BuPu',
    'Oranges',
    'BuGn',
    'YlOrBr',
    'YlGn',
    'Reds',
    'RdPu',
    'Greens',
    'YlGnBu',
    'Purples',
    'GnBu',
    'Greys',
    'YlOrRd',
    'PuRd',
    'Blues',
    'PuBuGn',
    'viridis',
    'plasma',
    'inferno',
    'magma'
]

In [12]:
scheme_inspector(create_figure(ColorScale(), y_data), lin_schemes,
                 title='Non-diverging schemes')


OrdinalColorScale

The OrdinalColorScale is a color scale for categorical data, i.e. data that does not have an intrinsic order.

The scale colors may be specified by the user, or chosen from a set scheme. As of now, the supported color schemes are the colorbrewer categorical schemes, listed here along with their maximum number of colors.


In [13]:
ord_schemes = {
    'Set2': 8,
    'Accent': 8,
    'Set1': 9,
    'Set3': 12,
    'Dark2': 8,
    'Paired': 12,
    'Pastel2': 8,
    'Pastel1': 9,
}

In [14]:
def partition(array, n_groups):
    n_elements = len(array)
    if n_groups > n_elements:
        return np.arange(n_elements)
    n_per_group = n_elements // n_groups + (n_elements % n_groups > 0)
    return np.tile(range(1, n_groups+1), n_per_group)[:n_elements]

In [15]:
# Define the control widgets
n_groups_slider = IntSlider(description='n colors', min=3)
scheme_slider = SelectionSlider(options=ord_schemes)
scheme_dd = Dropdown(description='Scheme',
                     options=ord_schemes)
link((scheme_dd, 'label'), (scheme_slider, 'label'))
    
def update_scheme(*args):
    col_sc.scheme = scheme_slider.label
    ax_c.label = scheme_slider.label
    n_groups_slider.max = scheme_slider.value

def update_categories(*args):
    groups = partition(names, n_groups_slider.value)
    market_map.color = groups
    market_map.groups = groups

n_groups_slider.observe(update_categories, 'value')
scheme_slider.observe(update_scheme, 'value')

# Define the bqplot marketmap
names = range(100)

col_sc = OrdinalColorScale()
ax_c = ColorAxis(scale=col_sc)

market_map = MarketMap(names=names,
                       display_text=['' for _ in names],
                       scales={'color': col_sc}, axes=[ax_c],
                       layout=Layout(min_width='800px', min_height='600px'))
update_scheme()
update_categories()

VBox([HBox([scheme_dd, scheme_slider, n_groups_slider]), market_map])



In [ ]:


In [ ]:


In [ ]: