0

I have a function that returns a matplotlib.image.AxesImage object and I would like to plot two of these objects side by side in the same figure. I tried something like this:

fig, (ax1, ax2) = plt.subplots(ncols=2)
ax1 = function_that_returns_AxesImage(some_arguments)  # tried to reassign ax1
ax2 = function_that_returns_AxesImage(other_arguments) # tried to reassign ax2

However, that just produces a figure with two empty subplots and the two plots I want are plotted in a column, and not side by side (see current plots output here). My problem is that I have to use the function_that_returns_axes, and I don't know how to put the returned plots into subplots. Alternatively, if I could just display two figures side by side in Jupyter, that could work too.

Jack Hong
  • 3
  • 4
  • I think we need more information about `function_that_returns_axes`. It seems it does actually take into account some part of the code, otherwise it would not plot to the same existing figure. Where does this function come from? Did you write it yourself? Can you give a link to it? – ImportanceOfBeingErnest May 26 '17 at 23:29
  • @ImportanceOfBeingErnest Sure, I am working with the galpy library [https://github.com/jobovy/galpy.git](https://github.com/jobovy/galpy.git). The particular function is the plot function found in galpy/galpy/potential_src/Potential.py. Thanks for your help! – Jack Hong May 28 '17 at 19:43
  • Does my answer from below work for you or not? If so I wouldn't need to look deep into the galpy code. – ImportanceOfBeingErnest May 28 '17 at 19:44
  • I'm not sure why, but I'm getting this error. **AttributeError: 'AxesImage' object has no attribute 'set_position'**. I've tried some other methods and it looks like set_cmap and set_colorbar both work, but set_title and set_position give the AttributeError. – Jack Hong May 28 '17 at 19:55
  • Ok, sorry, i was mislead by the `function_that_returns_axes` because it does apparently not return an axes but an image (I know you wrote that in the beginning of the code but because the method was called differently, I did not notice). So I updated my answer with a method for the image. – ImportanceOfBeingErnest May 28 '17 at 20:22
  • Ah yes, sorry I messed up the function names. I got confused between Axes and AxesImage as well. Thanks for all your help! – Jack Hong May 28 '17 at 20:39

2 Answers2

0

If you can't pass ax1, ax2 to function_that_returns_axes, then you can use following code:

def align_figures():
    import matplotlib
    from matplotlib._pylab_helpers import Gcf
    from IPython.display import display_html
    import base64
    from ipykernel.pylab.backend_inline import show

    images = []
    for figure_manager in Gcf.get_all_fig_managers():
        fig = figure_manager.canvas.figure
        png = get_ipython().display_formatter.format(fig)[0]['image/png']
        src = base64.encodebytes(png).decode()
        images.append('<img style="margin:0" align="left" src="data:image/png;base64,{}"/>'.format(src))

    html = "<div>{}</div>".format("".join(images))
    show._draw_called = False
    matplotlib.pyplot.close('all')
    display_html(html, raw=True)

For detail: Jupyter Notebook: Output image in previous line

HYRY
  • 94,853
  • 25
  • 187
  • 187
0

A solution will of course depend on what exactly function_that_returns_axes does to the figure. But as it seems, it takes into account an existing figure and returns the axes it has plotted to.

One could then take this axes and change its position such that it lives on a user defined grid. The grid would be created via matplotlib.gridspec.

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

fig = plt.figure()

def function_that_returns_axes(l="A"):
    ax = fig.add_subplot(111, label=l)
    ax.plot(np.random.rand(5))
    return ax

ax1 = function_that_returns_axes("A")
ax2 = function_that_returns_axes("B")

gs = gridspec.GridSpec(1,2)
ax1.set_position(gs[0].get_position(fig))
ax1.set_subplotspec(gs[0]) 

ax2.set_position(gs[1].get_position(fig))
ax2.set_subplotspec(gs[1])   

plt.show()

enter image description here

As can be seen both axes are next to each other, although they have initially been created on top of each other by the function_that_returns_axes.

If the function does not return an axes, but an image, the solution would be as follows:

def function_that_returns_image(l="A"):
    ax = fig.add_subplot(111, label=l)
    im = ax.imshow(np.random.rand(5,5))
    return im

im1 = function_that_returns_image("A")  
im2 = function_that_returns_image("B")

ax1 = im1.axes
ax2 = im2.axes

# the rest being the same as above...

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712