mpld3#

Links: notebook, html, PDF, python, slides, GitHub

mpld3 is taking matplotlib graphs and converts them into javascript. the support was stopped in Summer 2017. This notebook should be failing at some point is not checked anymore on regular basis.

documentation source installation tutorial gallery

from jyquickhelper import add_notebook_menu
add_notebook_menu()

example#

%matplotlib inline
import matplotlib.pyplot as plt
import mpld3
import numpy
x = [float(_) for _ in numpy.random.normal(size=N)]
type(x[0])
float
fig, ax = plt.subplots()
N = 100
ax.plot(numpy.random.normal(size=N), numpy.random.normal(size=N), 'o', alpha=0.3)
ax.set_title("Scatter Plot", size=20)
labels = ['point {0}'.format(i + 1) for i in range(N)]
mpld3.display(fig)

mpld3.display(fig) displays the graph. You can use mpld3.enable_notebook() to avoid that but matplotlib will not be available. scatter produces the following error TypeError: Object of type 'ndarray' is not JSON serializable. The github repository tells that it is no longer supported so I won’t insist on fixing the errors.

Same graph with a plugin#

import pandas
fig, ax = plt.subplots()
N = 100
mplplot = ax.plot(numpy.random.normal(size=N), numpy.random.normal(size=N), 'o', markersize=12, alpha=0.3)
ax.set_title("Scatter Plot", size=20)

# addition
labels = ['point {0}'.format(i + 1) for i in range(N)]
tooltip = mpld3.plugins.LineLabelTooltip(mplplot[0])
# fails
# mpld3.plugins.connect(fig, tooltip)


mpld3.display(fig)

Other plugin#

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from mpld3 import plugins

# Define some CSS to control our custom labels
css = """
table
{
  border-collapse: collapse;
}
th
{
  color: #ffffff;
  background-color: #000000;
}
td
{
  background-color: #cccccc;
}
table, th, td
{
  font-family:Arial, Helvetica, sans-serif;
  border: 1px solid black;
  text-align: right;
}
"""

fig, ax = plt.subplots()
ax.grid(True, alpha=0.3)

N = 50
df = pd.DataFrame(index=range(N))
df['x'] = np.random.randn(N)
df['y'] = np.random.randn(N)
df['z'] = np.random.randn(N)

labels = []
for i in range(N):
    label = df.iloc[[i], :].T
    label.columns = ['Row {0}'.format(i)]
    # .to_html() is unicode; so make leading 'u' go away with str()
    labels.append(str(label.to_html()))

points = ax.plot(df.x, df.y, 'o', color='b',
                 mec='k', ms=15, mew=1, alpha=.6)

ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('HTML tooltips', size=20)

tooltip = plugins.PointHTMLTooltip(points[0], labels,
                                   voffset=10, hoffset=10, css=css)
plugins.connect(fig, tooltip)

mpld3.display(fig)
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris

import mpld3
from mpld3 import plugins, utils


data = load_iris()
X = data.data
y = data.target

# dither the data for clearer plotting
X += 0.1 * np.random.random(X.shape)

fig, ax = plt.subplots(4, 4, sharex="col", sharey="row", figsize=(8, 8))
fig.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.95,
                    hspace=0.1, wspace=0.1)

for i in range(4):
    for j in range(4):
        points = ax[3 - i, j].plot(X[:, j], X[:, i], 'o', alpha=0.6)

# remove tick labels
for axi in ax.flat:
    for axis in [axi.xaxis, axi.yaxis]:
        axis.set_major_formatter(plt.NullFormatter())

# fails
# plugins.connect(fig, plugins.LinkedBrush(points))

mpld3.display(fig)

Javascript plugin#

import jinja2
import json
import numpy as np
import matplotlib.pyplot as plt

import mpld3
from mpld3 import plugins, utils


class HighlightLines(plugins.PluginBase):
    """A plugin to highlight lines on hover"""

    JAVASCRIPT = """
    mpld3.register_plugin("linehighlight", LineHighlightPlugin);
    LineHighlightPlugin.prototype = Object.create(mpld3.Plugin.prototype);
    LineHighlightPlugin.prototype.constructor = LineHighlightPlugin;
    LineHighlightPlugin.prototype.requiredProps = ["line_ids"];
    LineHighlightPlugin.prototype.defaultProps = {alpha_bg:0.3, alpha_fg:1.0}
    function LineHighlightPlugin(fig, props){
        mpld3.Plugin.call(this, fig, props);
    };

    LineHighlightPlugin.prototype.draw = function(){
      for(var i=0; i<this.props.line_ids.length; i++){
         var obj = mpld3.get_element(this.props.line_ids[i], this.fig),
             alpha_fg = this.props.alpha_fg;
             alpha_bg = this.props.alpha_bg;
         obj.elements()
             .on("mouseover", function(d, i){
                            d3.select(this).transition().duration(50)
                              .style("stroke-opacity", alpha_fg); })
             .on("mouseout", function(d, i){
                            d3.select(this).transition().duration(200)
                              .style("stroke-opacity", alpha_bg); });
      }
    };
    """

    def __init__(self, lines):
        self.lines = lines
        self.dict_ = {"type": "linehighlight",
                      "line_ids": [utils.get_id(line) for line in lines],
                      "alpha_bg": lines[0].get_alpha(),
                      "alpha_fg": 1.0}


N_paths = 50
N_steps = 100

x = np.linspace(0, 10, 100)
y = 0.1 * (np.random.random((N_paths, N_steps)) - 0.5)
y = y.cumsum(1)

fig, ax = plt.subplots(subplot_kw={'xticks': [], 'yticks': []})
lines = ax.plot(x, y.T, color='blue', lw=4, alpha=0.1)
plugins.connect(fig, HighlightLines(lines))

mpld3.display(fig)