title: Zoomed inset in matplotlib without re-plotting data
body: <p>I'm working on some matplotlib plots and need to have a zoomed inset. This is possible with the <code>zoomed_inset_axes</code> from the <code>axes_grid1</code> toolkit. See the example <a href="http://matplotlib.org/1.3.1/mpl_toolkits/axes_grid/users/overview.html" rel="noreferrer" title="here">here</a>:</p>
  
  <pre><code>import matplotlib.pyplot as plt
  
  from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes
  from mpl_toolkits.axes_grid1.inset_locator import mark_inset
  
  import numpy as np
  
  def get_demo_image():
      from matplotlib.cbook import get_sample_data
      import numpy as np
      f = get_sample_data("axes_grid/bivariate_normal.npy", asfileobj=False)
      z = np.load(f)
      # z is a numpy array of 15x15
      return z, (-3,4,-4,3)
  
  fig, ax = plt.subplots(figsize=[5,4])
  
  # prepare the demo image
  Z, extent = get_demo_image()
  Z2 = np.zeros([150, 150], dtype="d")
  ny, nx = Z.shape
  Z2[30:30+ny, 30:30+nx] = Z
  
  # extent = [-3, 4, -4, 3]
  ax.imshow(Z2, extent=extent, interpolation="nearest",
            origin="lower")
  
  axins = zoomed_inset_axes(ax, 6, loc=1) # zoom = 6
  axins.imshow(Z2, extent=extent, interpolation="nearest",
               origin="lower")
  
  # sub region of the original image
  x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9
  axins.set_xlim(x1, x2)
  axins.set_ylim(y1, y2)
  
  plt.xticks(visible=False)
  plt.yticks(visible=False)
  
  # draw a bbox of the region of the inset axes in the parent axes and
  # connecting lines between the bbox and the inset axes area
  mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.5")
  
  plt.draw()
  plt.show()
  </code></pre>
  
  <p>This will give the desired result:</p>
  
  <p><a href="https://i.stack.imgur.com/fnsp5.png" rel="noreferrer"><img src="https://i.stack.imgur.com/fnsp5.png" alt="Result"></a><a href="http://matplotlib.org/1.3.1/_images/inset_locator_demo21.png" rel="noreferrer">http://matplotlib.org/1.3.1/_images/inset_locator_demo21.png</a></p>
  
  <p>But as you can see in the code, the data has to be plotted twice - once for the main axis (<code>ax.imshow...</code>) and once for the inset axis (<code>axins.imshow...</code>). </p>
  
  <h3>My question is:</h3>
  
  <p>Is there a way to add a zoomed inset <strong>after</strong> the main plot is completed, <strong>without</strong> the need to plot everything again on the new axis?</p>
  
  <p>Please note: I am not looking for a solution which wraps the plot call with a function and let the function plot <code>ax</code> and <code>axins</code> (see example below), but (if this exists) a native solution that makes use of the existing data in <code>ax</code>. Anybody knows if such a solution exists?</p>
  
  <p>This is the wrapper-solution:</p>
  
  <pre><code>def plot_with_zoom(*args, **kwargs):
      ax.imshow(*args, **kwargs)
      axins.imshow(*args, **kwargs)
  </code></pre>
  
  <p>It works, but it feels a bit like a hack, since why should I need to plot all data again if I just want to zoom into a region of my existing plot.</p>
  
  <hr>
  
  <p>Some additional clarification after the answer by ed-smith:</p>
  
  <p>The example above is of course only the minimal example. There could be many different sets of data in the plot (and with <em>sets of data</em> I mean things plotted via <code>imshow</code> or <code>plot</code> etc). Imagine for example a scatter plot with 10 arrays of points, all plotted vs. common x. </p>
  
  <p>As I wrote above, the most direct way to do that is just have a wrapper to plot the data in all instances. But what I'm looking for is a way (if it exists) to start with the final <code>ax</code> object (not the individual plotting commands) and somehow create the zoomed inset.</p>