Visualization

  • Matplotlib
  • Seaborn
  • ggplot
  • plotly
  • Bokeh + ipywidgets
  • Inline network displays
  • GUI programming example with wxPython
  • ipywidgets + networkx

TODO:

  • Vispy
$ conda install ipywidgets wxpython networkx seaborn matplotlib
$ jupyter nbextension enable --py widgetsnbextension --sys-prefix
$ conda install -c bokeh bokeh

Standard plots with Matplotlib: line, scatter, chart, contour, heatmap

Control every detail of your graphics programmatically.

Have a look at more examples: http://matplotlib.org/gallery.html


In [2]:
#ipython magic command
%matplotlib inline

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

matplotlib.rcParams.update({'font.size': 18, 'font.family': 'arial'})

x = np.linspace(0.1, 10, 100)
y1 = np.sin(x)
y2 = np.sin(1/x)
#y2 = np.exp(x)

fig, ax = plt.subplots(figsize=(13,4))

#axes[0].plot(x, y1, x, y2)
ax.plot(x, y1, label="y = sin(x)")
ax.plot(x, y2, label=r"$sin(\frac{1}{x})$", color="#05cd90", lw=2, ls='dotted', marker='o', markersize=4)
ax.set_xlabel('time')
ax.set_ylabel('harmonics')
ax.set_ylim([- 1.5, 1.5])
#ax.set_yscale("log")
ax.set_title("Line plots")
ax.legend(loc=2)
yticks = [0, 1]
plt.annotate('wow!', xy=(8, 1), xytext=(7, -1), arrowprops=dict(facecolor='black', shrink=0.05))
ax.set_yticks(yticks)
ax.set_yticklabels([r"rest $\alpha$", r"disturbed $\delta$"], fontsize=18)

#fig.savefig("filename.png")
#fig.savefig("filename.png", dpi=100)
plt.show()


/home/sergiu/programs/miniconda3/envs/pycourse/lib/python3.5/site-packages/matplotlib/font_manager.py:1297: UserWarning: findfont: Font family ['arial'] not found. Falling back to DejaVu Sans
  (prop.get_family(), self.defaultFamily[fontext]))

In [4]:
%matplotlib inline

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

fig, axes = plt.subplots(2, 2, figsize=(10,8))
matplotlib.rcParams.update({'font.size': 10, 'font.family': 'arial'})
x = 10*np.random.random(100)
y = 10*np.random.random(100)
def f(x,y): return np.sin(x)**2+np.sin(y)**2

axes[0][0].scatter(x, y, c=f(x,y), cmap=plt.cm.Blues)
axes[0][0].set_title("scatter plot")

x1 = np.linspace(-10,10,100)
y1 = np.zeros(100)+5.0
axes[0][1].bar(x1, f(x1,y1), align="center", width=0.5, alpha=0.5)
axes[0][1].set_title("bar plot")


x = np.linspace(-10,10,100)
y = np.linspace(-10,10,100)

X,Y = np.meshgrid(x, y)
Z = f(X,Y)
axes[1][0].pcolor(x, y, Z, cmap=plt.cm.Blues, vmin=np.abs(Z).min(), vmax=np.abs(Z).max())
#axes[1][1].pcolor(x, y, Z, cmap=plt.cm.RdBu, vmin=np.abs(Z).min(), vmax=np.abs(Z).max())
axes[1][0].set_title("colour map (heatmap)")

axes[1][1].contour(Z.T, cmap=plt.cm.Blues, vmin=np.abs(Z).min(), vmax=np.abs(Z).max(), extent=[-10, 10, -10, 10])
axes[1][1].set_title("contour plot")


Out[4]:
<matplotlib.text.Text at 0x7f2d4b7ac5c0>
/home/sergiun/programs/anaconda3/envs/py35/lib/python3.5/site-packages/matplotlib/font_manager.py:1288: UserWarning: findfont: Font family ['arial'] not found. Falling back to Bitstream Vera Sans
  (prop.get_family(), self.defaultFamily[fontext]))

Seaborn

Matplotlib was the first big library for visualization in Python, but after its creator tragically died more and more users migrated to Seaborn. Seaborn offers a much easier entry point to the detriment of high customization. But, it looks great! Here is a violin plot example. Check other examples in the galery.


In [2]:
import seaborn as sns
sns.set(style="whitegrid", palette="pastel", color_codes=True)

# Load the example tips dataset
tips = sns.load_dataset("tips")

# Draw a nested violinplot and split the violins for easier comparison
sns.violinplot(x="day", y="total_bill", hue="sex", data=tips, split=True,
               inner="quart", palette={"Male": "b", "Female": "y"})
sns.despine(left=True)


Web publishing with plotly and Bokeh

Bokeh is using D3, one of the most complex and performant web visualization libraries. This makes it easy to add web interaction, and also makes very nice publication quality graphics.

jupyter nbextension enable --py widgetsnbextension --sys-prefix


In [1]:
from ipywidgets import interact
import numpy as np

from bokeh.io import push_notebook, show, output_notebook
from bokeh.plotting import figure
output_notebook()


Loading BokehJS ...

In [2]:
x = np.linspace(0, 2*np.pi, 2000)
y = np.sin(x)

p = figure(title="simple line example", plot_height=300, plot_width=600, y_range=(-5,5))
r = p.line(x, y, color="#2222aa", line_width=3)

In [3]:
def update(f, w=1, A=1, phi=0):
    if   f == "sin": func = np.sin
    elif f == "cos": func = np.cos
    elif f == "tan": func = np.tan
    r.data_source.data['y'] = A * func(w * x + phi)
    push_notebook()

In [4]:
show(p, notebook_handle=True)


Out[4]:

<Bokeh Notebook handle for In[4]>


In [5]:
from IPython.display import display
from ipywidgets import *
interact(update, f=["sin", "cos", "tan"], w=(0,100), A=(1,5), phi=(0, 20, 0.1))


Out[5]:
<function __main__.update(f, w=1, A=1, phi=0)>

In [6]:
from IPython.display import display
from ipywidgets import *
w = IntSlider()
display(w)



In [7]:
def f(x):
    return x
interact(f, x=10);


Network layout and display


In [11]:
%matplotlib inline
import networkx as nx
#net = nx.erdos_renyi_graph(100,0.12)
net = nx.barabasi_albert_graph(100, 1)
nx.write_gml(net,"mynetwork.gml")

import matplotlib.pyplot as plt
#nx.draw(net)
nx.draw(net,pos=nx.spring_layout(net, scale = 5000, iterations = 10))
#nx.draw_random(net)
#nx.draw_circular(net)
#nx.draw_spectral(net, dim = 500, scale = 20)

#plt.show()

## Generate a picture and load it with IPython
#plt.savefig("test.png")

#from IPython.display import Image
#Image(filename='test.png')

#from IPython.core.display import HTML 
#HTML('<img src="files/test.png" width=100 height=20/>')



In [10]:
import pandas as pd
nodes = pd.DataFrame([['ipcy', 'IPython-Cytoscape.js', 50, 'green', 'square'], 
                      ['cy', 'Cytoscape.js', 50, 'blue', 'circle'],
                      ['ip', 'IPython', 50, 'red', 'hexagon']],                      
                     columns=['id', 'name', 'weight', 'color', 'shape'])
edges = pd.DataFrame([['ipcy', 'ip', 20, 'gray' ], 
                      ['ipcy', 'cy', 20, 'gray']], 
                     columns=['source', 'target', 'strength', 'color'])
%load_ext cyto
network = cyto.Network(nodes, edges)
network
#network.save_state()

#nw2 = cyto.Network(nodes, edges, layout='grid')
#nw2


---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-10-c0f304cec768> in <module>
      8                       ['ipcy', 'cy', 20, 'gray']], 
      9                      columns=['source', 'target', 'strength', 'color'])
---> 10 get_ipython().run_line_magic('load_ext', 'cyto')
     11 network = cyto.Network(nodes, edges)
     12 network

/media/sergiu/lappie/programs/miniconda3/envs/pycourse/lib/python3.7/site-packages/IPython/core/interactiveshell.py in run_line_magic(self, magic_name, line, _stack_depth)
   2305                 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
   2306             with self.builtin_trap:
-> 2307                 result = fn(*args, **kwargs)
   2308             return result
   2309 

</media/sergiu/lappie/programs/miniconda3/envs/pycourse/lib/python3.7/site-packages/decorator.py:decorator-gen-64> in load_ext(self, module_str)

/media/sergiu/lappie/programs/miniconda3/envs/pycourse/lib/python3.7/site-packages/IPython/core/magic.py in <lambda>(f, *a, **k)
    185     # but it's overkill for just that one bit of state.
    186     def magic_deco(arg):
--> 187         call = lambda f, *a, **k: f(*a, **k)
    188 
    189         if callable(arg):

/media/sergiu/lappie/programs/miniconda3/envs/pycourse/lib/python3.7/site-packages/IPython/core/magics/extension.py in load_ext(self, module_str)
     31         if not module_str:
     32             raise UsageError('Missing module name.')
---> 33         res = self.shell.extension_manager.load_extension(module_str)
     34 
     35         if res == 'already loaded':

/media/sergiu/lappie/programs/miniconda3/envs/pycourse/lib/python3.7/site-packages/IPython/core/extensions.py in load_extension(self, module_str)
     78             if module_str not in sys.modules:
     79                 with prepended_to_syspath(self.ipython_extension_dir):
---> 80                     mod = import_module(module_str)
     81                     if mod.__file__.startswith(self.ipython_extension_dir):
     82                         print(("Loading extensions from {dir} is deprecated. "

/media/sergiu/lappie/programs/miniconda3/envs/pycourse/lib/python3.7/importlib/__init__.py in import_module(name, package)
    125                 break
    126             level += 1
--> 127     return _bootstrap._gcd_import(name[level:], package, level)
    128 
    129 

/media/sergiu/lappie/programs/miniconda3/envs/pycourse/lib/python3.7/importlib/_bootstrap.py in _gcd_import(name, package, level)

/media/sergiu/lappie/programs/miniconda3/envs/pycourse/lib/python3.7/importlib/_bootstrap.py in _find_and_load(name, import_)

/media/sergiu/lappie/programs/miniconda3/envs/pycourse/lib/python3.7/importlib/_bootstrap.py in _find_and_load_unlocked(name, import_)

ModuleNotFoundError: No module named 'cyto'

Basic GUI programming with wxPython


In [8]:
%gui wx

"""
A Simple wx example to test IPython's event loop integration.

To run this do:

In [5]: %gui wx  # or start IPython with '--gui wx'

In [6]: %run gui-wx.py

Ref: Modified from wxPython source code wxPython/samples/simple/simple.py
"""


import wx


class MyFrame(wx.Frame):
    """
    This is MyFrame.  It just shows a few controls on a wxPanel,
    and has a simple menu.
    """
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, -1, title,
                          pos=(150, 150), size=(350, 200))

        # Create the menubar
        menuBar = wx.MenuBar()

        # and a menu
        menu = wx.Menu()

        # add an item to the menu, using \tKeyName automatically
        # creates an accelerator, the third param is some help text
        # that will show up in the statusbar
        menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample")

        # bind the menu event to an event handler
        self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT)

        # and put the menu on the menubar
        menuBar.Append(menu, "&File")
        self.SetMenuBar(menuBar)

        self.CreateStatusBar()

        # Now create the Panel to put the other controls on.
        panel = wx.Panel(self)

        # and a few controls
        text = wx.StaticText(panel, -1, "Hello World!")
        text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
        text.SetSize(text.GetBestSize())
        btn = wx.Button(panel, -1, "Close")
        funbtn = wx.Button(panel, -1, "Just for fun...")

        # bind the button events to handlers
        self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, btn)
        self.Bind(wx.EVT_BUTTON, self.OnFunButton, funbtn)

        # Use a sizer to layout the controls, stacked vertically and with
        # a 10 pixel border around each
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(text, 0, wx.ALL, 10)
        sizer.Add(btn, 0, wx.ALL, 10)
        sizer.Add(funbtn, 0, wx.ALL, 10)
        panel.SetSizer(sizer)
        panel.Layout()


    def OnTimeToClose(self, evt):
        """Event handler for the button click."""
        print("See ya later!")
        self.Close()

    def OnFunButton(self, evt):
        """Event handler for the button click."""
        print("Having fun yet?")


class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, "Simple wxPython App")
        self.SetTopWindow(frame)

        print("Print statements go to this stdout window by default.")

        frame.Show(True)
        return True

app = None
app = wx.GetApp()
if app is None:
    app = MyApp(redirect=False, clearSigInt=False)
else:
    frame = MyFrame(None, "Simple wxPython App")
    app.SetTopWindow(frame)
    print("Print statements go to this stdout window by default.")
    frame.Show(True)

try:
    from IPython.lib.inputhook import enable_wx
    enable_wx(app)
except ImportError:
    print("error")
    app.MainLoop()


Print statements go to this stdout window by default.
error
/media/sergiu/lappie/programs/miniconda3/envs/pycourse/lib/python3.7/site-packages/ipykernel_launcher.py:103: DeprecationWarning: `IPython.lib.inputhook` is deprecated since IPython 5.0 and will be removed in future versions.

ipywidgets


In [9]:
from ipywidgets import widgets

In [10]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

def plot(amplitude, color):
    fig, ax = plt.subplots(figsize=(4, 3),
                           subplot_kw={'axisbelow':True})
    ax.grid(color='w', linewidth=2, linestyle='solid')
    x = np.linspace(0, 10, 1000)
    ax.plot(x, amplitude * np.sin(x), color=color,
            lw=5, alpha=0.4)
    ax.set_xlim(0, 10)
    ax.set_ylim(-1.1, 1.1)
    return fig

from ipywidgets import interact, FloatSlider, RadioButtons

interact(plot,
         amplitude=FloatSlider(min=0.1, max=1.0, step=0.1),
         color=RadioButtons(options=['blue', 'green', 'red']))


Out[10]:
<function __main__.plot(amplitude, color)>

In [12]:
from ipywidgets import *
IntSlider()



In [11]:
widgets.Select(
    description='OS:',
    options=['Linux', 'Windows', 'OSX'],
)



In [13]:
import ipywidgets as widgets
from IPython.display import display
name = widgets.Text(description='Name:', padding=4)
#name.layout.padding = 4
color = widgets.Dropdown(description='Color:', options=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])
#color.layout.padding = 4
page1 = widgets.Box(children=[name, color])
#page1.layout.padding = 4

age = widgets.IntSlider(description='Age:', min=0, max=120, value=50)
#age.layout.padding = 4
gender = widgets.RadioButtons(description='Gender:', options=['male', 'female'])
#gender.layout.padding = 4
page2 = widgets.Box(children=[age, gender])
#page2.layout.padding = 4

tabs = widgets.Tab(children=[page1, page2])
display(tabs)

tabs.set_title(0, 'Name')
tabs.set_title(1, 'Details')



In [14]:
from ipywidgets import interact
%matplotlib inline
import matplotlib.pyplot as plt
import networkx as nx
# wrap a few graph generation functions so they have the same signature

def random_lobster(n, m, k, p):
    return nx.random_lobster(n, p, p / m)

def powerlaw_cluster(n, m, k, p):
    return nx.powerlaw_cluster_graph(n, m, p)

def erdos_renyi(n, m, k, p):
    return nx.erdos_renyi_graph(n, p)

def newman_watts_strogatz(n, m, k, p):
    return nx.newman_watts_strogatz_graph(n, k, p)

def plot_random_graph(n, m, k, p, generator):
    g = generator(n, m, k, p)
    nx.draw(g)
    plt.show()

interact(plot_random_graph, n=(2,30), m=(1,10), k=(1,10), p=(0.0, 1.0, 0.001),
        generator={'lobster': random_lobster,
                   'power law': powerlaw_cluster,
                   'Newman-Watts-Strogatz': newman_watts_strogatz,
                   u'Erdős-Rényi': erdos_renyi,
                   });



In [ ]: