简体   繁体   English

Jupyter Notebook:在上一行中输出图像

[英]Jupyter Notebook: Output image in previous line

I want to plot some image side by side in my jupyter notebook. 我想在我的Jupyter笔记本中并排绘制一些图像。 So it can save some space for display. 这样可以节省一些显示空间。 For example 例如

在此处输入图片说明

This is done through 这是通过完成

fig = plt.figure(figsize=(14,3))
ax1 = fig.add_subplot(1,3,1,projection = '3d')
ax2 = fig.add_subplot(1,3,2)
ax3 = fig.add_subplot(1,3,3)

And this makes them in one .png file. 这使它们成为一个.png文件。 However, later on in writing the paper, I may only want part of the image. 但是,稍后在撰写论文时,我可能只需要一部分图像。 For example, the 2nd or the 3rd in previous plot. 例如,上图中的第二或第三。 And this requires me to crop the image manually . 这需要我手动裁剪图像

One way I can think of, is to make each subplot seperately, but display them in same line. 我可以想到的一种方法是分别制作每个子图,但将它们显示在同一行中。 In Python/Jupyter Notebook, the string output can achieve this by adding a comma at the end of previous line: 在Python / Jupyter Notebook中,字符串输出可以通过在上一行的末尾添加逗号来实现:

print 5, 
print 6
# returns 5, 6
# instead of 
# 5 
# 6

I'm wondering if there is anything similar in Jupyter Nobebook, that can do something like 我想知道Jupyter Nobebook中是否有类似的东西可以做类似的事情

plot fig1,
plot fig2
# Out put [fig1],[fig2]
# instead of 
# fig1 
# fig2

Output fig1, fig2 in the same line, but in seperate .png file? 在同一行中输出fig1,fig2,但在单独的.png文件中?

use the following align_figures() : 使用以下align_figures()

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)

Here is a test: 这是一个测试:

fig1, ax1 = pl.subplots(figsize=(4, 3))
fig2, ax2 = pl.subplots(figsize=(4, 3))
fig3, ax3 = pl.subplots(figsize=(4, 3))
align_figures()

The code assumes that the output format is PNG image. 该代码假定输出格式为PNG图像。

first let me recommend you use a colormap other than the jet colormap for the reasons detailed in A better colormap for matplotlib . 首先,我建议您使用除喷射色图以外的其他色图,其原因在“ matplotlib的更好色图”详细说明。

As to what you want to do you can achieve this with a modified code from: https://stackoverflow.com/a/26432947/835607 至于您想做什么,可以使用以下代码中的修改代码来实现: https : //stackoverflow.com/a/26432947/835607

I've extended that function to handle the zaxis of 3d plots as well as the colorbars you are using. 我已经扩展了该功能,以处理3d绘图的z轴以及所使用的颜色条。

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.transforms import Bbox
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.ticker import LinearLocator, FormatStrFormatter

def full_extent(ax, xpad=0.0, ypad=0.0, cbar=None):
    """Modified from https://stackoverflow.com/a/26432947/835607

    Get the full extent of an axes, including axes labels, tick labels, and
    titles.
    You may need to pad the x or y dimension in order to not get slightly chopped off labels

    For text objects, we need to draw the figure first, otherwise the extents
    are undefined. These draws can be eliminated by calling plt.show() prior 
    to calling this function."""

    ax.figure.canvas.draw()
    items = ax.get_xticklabels() + ax.get_yticklabels() 
    items += [ax, ax.title, ax.xaxis.label, ax.yaxis.label]
    if '3D' in str(type(ax)):  
        items += ax.get_zticklabels() +[ax.zaxis.label]
    if cbar:
        items+=cbar.ax.get_yticklabels()
        bbox = Bbox.union([cbar.ax.get_window_extent()]+[item.get_window_extent() for item in items])
    else:
         bbox = Bbox.union([item.get_window_extent() for item in items])
    return bbox.expanded(1.0 + xpad, 1.0 + ypad)

Now for an example I plot 3 subplots and save them all to separate files. 现在以一个示例为例,绘制3个子图并将它们全部保存到单独的文件中。 Note that the full_extent function has cbar, xpad, and ypad as arguments. 请注意,full_extent函数将cbar, xpad,ypad作为参数。 For the plots that have colorbars make sure to pass the colorbar axes object to the function. 对于具有颜色条的图,请确保将颜色条轴对象传递给函数。 You may also need to play around with the padding to get the best results. 您可能还需要玩弄填充以获得最佳效果。

# Make an example plot with 3 subplots...
fig = plt.figure(figsize=(9,4))

#3D Plot
ax1 = fig.add_subplot(1,3,1,projection='3d')
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
surf = ax1.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='viridis',
                       linewidth=0, antialiased=False)
ax1.set_zlim(-1.01, 1.01)
ax1.zaxis.set_major_locator(LinearLocator(10))
ax1.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

# This plot has a colorbar that we'll need to pass to extent
ax2 = fig.add_subplot(1,3,2)
data = np.clip(np.random.randn(250, 250), -1, 1)
cax = ax2.imshow(data, interpolation='nearest', cmap='viridis')
ax2.set_title('Gaussian noise')
cbar = fig.colorbar(cax)
ax2.set_xlabel('asdf')
ax2.set_ylabel('Some Cool Data')


#3rd plot for fun
ax3 = fig.add_subplot(1,3,3)
ax3.plot([1,4,5,7,7],[3,5,7,8,3],'ko--')
ax3.set_ylabel('adsf')
ax3.set_title('a title')


plt.tight_layout() #no overlapping labels
plt.show()  #show in notebook also give text an extent
fig.savefig('full_figure.png') #just in case

# Save just the portion _inside_ the boundaries of each axis
extent1 = full_extent(ax1).transformed(fig.dpi_scale_trans.inverted())
fig.savefig('ax1_figure.png', bbox_inches=extent1)

extent2 = full_extent(ax2,.05,.1,cbar).transformed(fig.dpi_scale_trans.inverted())
fig.savefig('ax2_figure.png', bbox_inches=extent2)

extent3 = full_extent(ax3).transformed(fig.dpi_scale_trans.inverted())
fig.savefig('ax3_figure.png', bbox_inches=extent3)

This plots the three plots on one line as you wanted and creates cropped output images such as this one: 这将根据需要在一条线上绘制三个图,并创建裁剪后的输出图像,如下图所示:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM