1

There are a number of questions on SO about creating "thumbnail" plots with matplotlib (i.e. smaller versions of a larger plot, where the thumbnail plot is overlaid onto the original).

However, I cannot find a way to do this with GridSpec plots. I understand that this is because axes from a GridSpec cannot be transformed (i.e. resized and translated).

Here is a complete script which reproduces the problem:

import matplotlib
from matplotlib import gridspec, pyplot
from matplotlib.backends.backend_pdf import PdfPages

def add_inset_to_axis(figure, axis, rect):
    left, bottom, width, height = rect
    def transform(coord):
        return figure.transFigure.inverted().transform(
            axis.transAxes.transform(coord))
    fig_left, fig_bottom = transform((left, bottom))
    fig_width, fig_height = transform([width, height]) - transform([0, 0])
    return figure.add_axes([fig_left, fig_bottom, fig_width, fig_height])

def main():
    pdf = PdfPages('example.pdf')
    fig = pyplot.figure()
    n_rows, n_cols = 2, 2
    x_range = (-100, 100)
    outer_grid = gridspec.GridSpec(n_rows, n_cols)
    index, row, col = 0, 0, 0
    while index < n_rows * n_cols:
        data = [x for x in xrange(*x_range)]
        grid_cell = outer_grid[row, col]
        axis = pyplot.subplot(grid_cell)
        axis.plot(range(*x_range), data)
        inset = add_inset_to_axis(fig, grid_cell, (0.675, 0.82, 0.3, 0.15))
        inset.plot(range(0, 10), data[0:10])
        col += 1
        if col == 2:
            col = 0
            row += 1
        index = row * 2 + col
    pdf.savefig(fig)
    pdf.close()

if __name__ == '__main__':
    print('Using matplotlib version %s' % matplotlib.__version__)
    main()

Output:

Using matplotlib version 1.5.1
Traceback (most recent call last):
  File "stackoverflow_inset.py", line 38, in <module>
    main()
  File "stackoverflow_inset.py", line 26, in main
    inset = add_inset_to_axis(fig, grid_cell, (0.675, 0.82, 0.3, 0.15))
  File "stackoverflow_inset.py", line 10, in add_inset_to_axis
    fig_left, fig_bottom = transform((left, bottom))
  File "stackoverflow_inset.py", line 9, in transform
    axis.transAxes.transform(coord))
AttributeError: 'SubplotSpec' object has no attribute 'transAxes'

Is there a way around this?

Community
  • 1
  • 1
snim2
  • 4,004
  • 27
  • 44
  • Can you cite some of the "number of questions... "? I guess it would help others to understand what you are trying to achieve. Can you also go into detail about your requirement to use `GridSpec`? From the code it seems that it can easily replaced by `figure.subplots`. – ImportanceOfBeingErnest Dec 06 '16 at 14:10
  • Also.. what happens if you call `add_inset_to_axis(fig, axis, (0.675, 0.82, 0.3, 0.15))` with `axis` instead of `grid_cell`? At least from the way the function is written, it appears that that would be the intended way of calling it. – ImportanceOfBeingErnest Dec 06 '16 at 14:13
  • Well, it turns out that you are correct about using `axis` instead of `grid_cell`, that does work, many thanks. In the code this is based on the relevant function doesn't have access to the actual axis, which I guess is why I didn't spot this earlier. If you write that out as an answer rather than a comment I can give you the credit for it. – snim2 Dec 06 '16 at 14:20

1 Answers1

1

From the function definition add_inset_to_axis(figure, axis, rect) it seems that the second argument is actually meant to be a matplotlib.axes instance.

So instead of giving grid_cell as an argument, one should probably use axis

inset = add_inset_to_axis(fig, axis, (0.675, 0.82, 0.3, 0.15))
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712