Hi matplotlib developers,

I was answering a question on the -users list and came across a
gridspec __getitem__ bug which causes an infinite loop if the
user tries to iterate over it, because getitem never did a
sanity-check when given an integer key.

  from matplotlib import gridspec
  gs = gridspec.GridSpec(1,2)
  gs[100] # no error is given, a SubplotSpec is returned 
  [x for x in gs] # causes infinite loop before applying patch

  # after applying the patch - which is just lines 171-172 in the
  # traceback below
  In [9]: gs[100]
  ----------------------------------------------------------
  IndexError               Traceback (most recent call last)
  
  ./matplotlib/<ipython console> in <module>()
  
  ./matplotlib/gridspec.pyc
  in __getitem__(self, key)
      170            key += total
      171        if key >= total or key < 0:
  --> 172            raise IndexError("index out of range")
      173        num1, num2 = key, None
      174 
  
  IndexError: index out of range
  
  In [10]: [x for x in gs]
  Out[10]: 
  
  [<matplotlib.gridspec.SubplotSpec object at 0x9b7edcc>,
   <matplotlib.gridspec.SubplotSpec object at 0x9b8834c>]


I'm also including a patch for the gridspec docs which create a
grid-of-grids using gridspec in a colorful manner. Note that
there, I explicitly create indexes in the right range, like so:

  outer_grid = GridSpec(4, 4)
  for i in xrange(16):
    inner_grid = GridSpecFromSubplotSpec(3, 3, subplot_spec=outer_grid[i])
    for j in xrange(9):
      ax = plt.Subplot(f, inner_grid[j])
      ...

because before applying the getitem patch described above, one
*can't* currently iterate over the spec itself like this:

  outer_grid = GridSpec(4, 4)
  for cell in outer_grid:
    inner_grid = GridSpecFromSubplotSpec(3, 3, subplot_spec=cell)
    for subcell in inner_grid:
      ax = plt.Subplot(f, subcell)
      ...

The doc patch also fixes the currently broken .. _gridspec-guide:
anchor name which can be seen peeking out at the top of:
http://matplotlib.sourceforge.net/users/gridspec.html

because there was previously a misplaced leading \ on line 1 of
doc/users/gridspec.rst

best,
-- 
Paul Ivanov
314 address only used for lists,  off-list direct email at:
http://pirsquared.org | GPG/PGP key id: 0x0F3E28F7 
Index: doc/users/plotting/examples/demo_gridspec06.py
===================================================================
--- doc/users/plotting/examples/demo_gridspec06.py	(revision 0)
+++ doc/users/plotting/examples/demo_gridspec06.py	(revision 0)
@@ -0,0 +1,41 @@
+import matplotlib.pyplot as plt
+import matplotlib.gridspec as gridspec
+import numpy as np
+from itertools import product
+
+def squiggle_xy(a, b, c, d, i=np.arange(0.0, 2*np.pi, 0.05)):
+    return np.sin(i*a)*np.cos(i*b), np.sin(i*c)*np.cos(i*d)
+
+f = plt.figure(figsize=(8, 8))
+
+# gridspec inside gridspec
+outer_grid = gridspec.GridSpec(4, 4, wspace=0.0, hspace=0.0)
+
+for i in xrange(16):
+    inner_grid = gridspec.GridSpecFromSubplotSpec(3, 3,
+            subplot_spec=outer_grid[i], wspace=0.0, hspace=0.0)
+    a, b = int(i/4)+1,i%4+1
+    for j, (c, d) in enumerate(product(range(1, 4), repeat=2)):
+        ax = plt.Subplot(f, inner_grid[j])
+        ax.plot(*squiggle_xy(a, b, c, d))
+        ax.set_xticks([])
+        ax.set_yticks([])
+        f.add_subplot(ax)
+
+all_axes = f.get_axes()
+
+#show only the outside spines
+for ax in all_axes:
+    for sp in ax.spines.values():
+        sp.set_visible(False)
+    if ax.is_first_row():
+        ax.spines['top'].set_visible(True)
+    if ax.is_last_row():
+        ax.spines['bottom'].set_visible(True)
+    if ax.is_first_col():
+        ax.spines['left'].set_visible(True)
+    if ax.is_last_col():
+        ax.spines['right'].set_visible(True)
+
+plt.show()
+
Index: doc/users/gridspec.rst
===================================================================
--- doc/users/gridspec.rst	(revision 8885)
+++ doc/users/gridspec.rst	(working copy)
@@ -1,4 +1,4 @@
-\.. _gridspec-guide:
+.. _gridspec-guide:
 
 
 ************************************************
@@ -129,6 +129,16 @@
 .. plot:: users/plotting/examples/demo_gridspec04.py
 
 
+A Complex Nested GridSpec using SubplotSpec
+===========================================
+
+Here's a more sophisticated example of nested gridspec where we put
+a box around each cell of the outer 4x4 grid, by hiding appropriate 
+spines in each of the inner 3x3 grids. ::
+
+.. plot:: users/plotting/examples/demo_gridspec06.py
+
+
 GridSpec with Varying Cell Sizes
 ================================
 
Index: lib/matplotlib/gridspec.py
===================================================================
--- lib/matplotlib/gridspec.py	(revision 8885)
+++ lib/matplotlib/gridspec.py	(working copy)
@@ -167,6 +167,8 @@
             else:
                 if key < 0:
                     key += total
+                if key >= total or key < 0:
+                    raise IndexError("index out of range")
                 num1, num2 = key, None
 
 

Attachment: signature.asc
Description: Digital signature

------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to