In [1]:
# from Mastering matplotlib Chapter 5 (slightly modified - moved all to notebook by removing ./lib/topo.py)
# note use of backend

import collections
import matplotlib as mpl                                                                                                                  
import numpy as np                                                                                                                        
from scipy import interpolate 
from matplotlib import pyplot as plt

plt.switch_backend('nbAgg')
                                                                                                                                          
                                                                                                                                          
snow = "#eeeeee"                                                                                                                          
mountains = "#aa8052"                                                                                                                     
hills = "#ccb688"                                                                                                                         
highlands = "#608350"                                                                                                                     
midlands = "#506d48"                                                                                                                      
lowlands = "#405644"                                                                                                                      
shallowsea = "#66a4c7"                                                                                                                    
sea = "#3681a5"                                                                                                                           
deepsea = "#39547c"                                                                                                                       
land_colors = [snow, mountains, hills,                                                                                                    
               highlands, midlands, lowlands,                                                                                             
               shallowsea, sea, deepsea]                                                                                                  
land_colors.reverse()                                                                                                                     
land_cmap = mpl.colors.LinearSegmentedColormap.from_list(                                                                                 
                "land", land_colors, N=16)                                                                                                
                                                                                                                                          
                                                                                                                                          
def make_land_map(xrange, yrange, seed):                                                                                                  
    (xmin, xmax) = xrange                                                                                                                 
    (ymin, ymax) = yrange                                                                                                                 
    np.random.seed(seed)                                                                                                                  
    x, y, z = np.random.random((3, 10))                                                                                                   
    # Interpolate these onto a regular grid                                                                                               
    xi, yi = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]                                                                                     
    interpolation = interpolate.Rbf(x, y, z, function="linear")                                                                           
    zi = 3200 * interpolation(xi, yi) + 1000                                                                                              
    coords = collections.OrderedDict([("x", xi), ("y", yi), ("z", zi)])                                                                   
    (dy, dx) = np.gradient(-zi.T)                                                                                                         
    gradient = collections.OrderedDict([("dy", dy), ("dx", dx)])                                                                          
    return (coords, gradient)  

class TopoFlowMap:
             def __init__(self, xrange=None, yrange=None, seed=1):
                 self.xrange = xrange or (0,1)
                 self.yrange = yrange or (0,1)
                 self.seed = seed
                 (self.figure, self.axes) = plt.subplots(
                    figsize=(12,8))
                 self.axes.set_aspect(1)
                 self.colorbar = None
                 self.update()

             def get_ranges(self, xrange, yrange):
                 if xrange:
                     self.xrange = xrange
                 if yrange:
                     self.yrange = yrange
                 return (xrange, yrange)

             def get_colorbar_axes(self):
                 colorbar_axes = None
                 if self.colorbar:
                     colorbar_axes = self.colorbar.ax
                     colorbar_axes.clear()
                 return colorbar_axes

             def get_filled_contours(self, coords):
                 return self.axes.contourf(
                    cmap=land_cmap, *coords.values())

             def update_contour_lines(self, filled_contours):
                 contours = self.axes.contour(
                    filled_contours, colors="black", linewidths=2)
                 self.axes.clabel(
                    contours, fmt="%d", colors="#330000")

             def update_water_flow(self, coords, gradient):
                 self.axes.streamplot(
                     coords.get("x")[:,0],
                     coords.get("y")[0,:],
                     gradient.get("dx"),
                     gradient.get("dy"),
                     color="0.6",
                     density=1,
                     arrowsize=2)

             def update_labels(self):
                 self.colorbar.set_label("Altitude (m)")
                 self.axes.set_title(
                    "Water Flow across Land Gradients", fontsize=20)
                 self.axes.set_xlabel("$x$ (km)")
                 self.axes.set_ylabel("$y$ (km)")

             def update(self, xrange=None, yrange=None):
                 (xrange, yrange) = self.get_ranges(xrange, yrange)
                 (coords, grad) = make_land_map(
                    self.xrange, self.yrange, self.seed)
                 self.axes.clear()
                 colorbar_axes = self.get_colorbar_axes()
                 filled_contours = self.get_filled_contours(coords)
                 self.update_contour_lines(filled_contours)
                 self.update_water_flow(coords, grad)
                 self.colorbar = self.figure.colorbar(
                    filled_contours, cax=colorbar_axes)
                 self.update_labels()
                    
class TopoFlowMapManager:
         def __init__(self, xrange=None, yrange=None, seed=1):
             self.map = TopoFlowMap(xrange, yrange, seed)
             _ = self.map.figure.canvas.mpl_connect(
                 'button_release_event',
                 self.handle_pan_zoom_release)

         def start(self):
             plt.show()

         def handle_pan_zoom_release(self, event):
             if event.canvas.toolbar.mode != "pan/zoom":
                 return
             self.map.update(event.inaxes.get_xlim(),
                             event.inaxes.get_ylim())
             event.canvas.draw()

In [2]:
tfmm = TopoFlowMapManager(xrange=(0,1.5), yrange=(0,1.5), seed=1732)
tfmm.start()



In [ ]: