保存交互式 Matplotlib 图形

2025-02-28 08:23:00
admin
原创
64
摘要:问题描述:有没有办法保存 Matplotlib 图形,以便可以重新打开并恢复典型的交互?(像 MATLAB 中的 .fig 格式?)我发现自己要多次运行相同的脚本来生成这些交互式图形。或者我向同事发送多个静态 PNG 文件来展示情节的不同方面。我宁愿发送图形对象并让他们自己与之交互。解决方案 1:我刚刚发现了...

问题描述:

有没有办法保存 Matplotlib 图形,以便可以重新打开并恢复典型的交互?(像 MATLAB 中的 .fig 格式?)

我发现自己要多次运行相同的脚本来生成这些交互式图形。或者我向同事发送多个静态 PNG 文件来展示情节的不同方面。我宁愿发送图形对象并让他们自己与之交互。


解决方案 1:

我刚刚发现了如何做到这一点。@pelson 提到的“实验性 pickle 支持”效果很好。

尝试一下:

# Plot something
import matplotlib.pyplot as plt
fig,ax = plt.subplots()
ax.plot([1,2,3],[10,-10,30])

完成交互式调整后,将图形对象保存为二进制文件:

import pickle
pickle.dump(fig, open('FigureObject.fig.pickle', 'wb')) # This is for Python 3 - py2 may need `file` instead of `open`

稍后,打开图形,调整应该被保存,并且应该存在 GUI 交互性:

import pickle
figx = pickle.load(open('FigureObject.fig.pickle', 'rb'))

figx.show() # Show the figure, edit it, etc.!

您甚至可以从图中提取数据:

data = figx.axes[0].lines[0].get_data()

(它适用于线条、pcolor 和 imshow - pcolormesh 使用一些技巧来重建扁平数据。)

我从使用 Pickle 保存 Matplotlib 图形中获得了很好的提示。

解决方案 2:

Matplotlib 自 1.2 版起允许您对图形进行 pickle。正如发行说明所述,这是一项实验性功能,不支持在一个 matplotlib 版本中保存图形并在另一个版本中打开。从不受信任的来源恢复 pickle 通常也是不安全的。

对于共享/稍后编辑图表(这需要首先进行大量数据处理,并且可能需要在几个月后进行调整,例如在科学出版物的同行评审期间),我仍然建议以下工作流程:(1)在生成图表之前使用数据处理脚本将处理后的数据(进入您的图表)保存到文件中,以及(2)使用单独的图表生成脚本(根据需要进行调整)来重新创建图表。这样,对于每个图表,您都可以快速运行脚本并重新生成它(并使用新数据快速复制您的图表设置)。也就是说,pickle 图表可能方便短期/交互式/探索性数据分析。

如果您使用的是尚未支持的旧版本,我建议(a)将数据处理与生成图形分开(使用唯一名称保存数据)并编写图形生成脚本(加载已保存数据的指定文件)并根据需要进行编辑或(b)另存为 PDF / SVG / PostScript格式并在一些花哨的图形编辑器(如Adob​​e Illustrator(或Inkscape ))中进行编辑。

解决方案 3:

为什么不直接发送 Python 脚本?MATLAB 的 .fig 文件要求收件人有 MATLAB 才能显示它们,因此这相当于发送需要 Matplotlib 才能显示的 Python 脚本。

或者(免责声明:我还没有尝试过),你可以尝试腌制这个数字:

import pickle
output = open('interactive figure.pickle', 'wb')
pickle.dump(gcf(), output)
output.close()

解决方案 4:

好问题。以下是文档文本pylab.save

pylab 不再提供保存函数,但旧的 pylab 函数仍可用作 matplotlib.mlab.save(您仍可以在 pylab 中将其称为“mlab.save”)。但是,对于纯文本文件,我们建议使用 numpy.savetxt。对于保存 numpy 数组,我们建议使用 numpy.save 及其类似函数 numpy.load,它们在 pylab 中可用作 np.save 和 np.load。

解决方案 5:

我想到了一个相对简单(但略显不寻常)的方法来保存我的 matplotlib 图表。它的工作原理如下:

import libscript

import matplotlib.pyplot as plt
import numpy as np

t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2*np.pi*t)

#<plot>
plt.plot(t, s)
plt.xlabel('time (s)')
plt.ylabel('voltage (mV)')
plt.title('About as simple as it gets, folks')
plt.grid(True)
plt.show()
#</plot>

save_plot(fileName='plot_01.py',obj=sys.argv[0],sel='plot',ctx=libscript.get_ctx(ctx_global=globals(),ctx_local=locals()))

函数save_plot定义如下(简单版本以理解逻辑):

def save_plot(fileName='',obj=None,sel='',ctx={}):
    """
    Save of matplolib plot to a stand alone python script containing all the data and configuration instructions to regenerate the interactive matplotlib figure.

    Parameters
    ----------
    fileName : [string] Path of the python script file to be created.
    obj : [object] Function or python object containing the lines of code to create and configure the plot to be saved.
    sel : [string] Name of the tag enclosing the lines of code to create and configure the plot to be saved.
    ctx : [dict] Dictionary containing the execution context. Values for variables not defined in the lines of code for the plot will be fetched from the context.

    Returns
    -------
    Return ``'done'`` once the plot has been saved to a python script file. This file contains all the input data and configuration to re-create the original interactive matplotlib figure.
    """
    import os
    import libscript

    N_indent=4

    src=libscript.get_src(obj=obj,sel=sel)
    src=libscript.prepend_ctx(src=src,ctx=ctx,debug=False)
    src='
'.join([' '*N_indent+line for line in src.split('
')])

    if(os.path.isfile(fileName)): os.remove(fileName)
    with open(fileName,'w') as f:
        f.write('import sys
')
        f.write('sys.dont_write_bytecode=True
')
        f.write('def main():
')
        f.write(src+'
')

        f.write('if(__name__=="__main__"):
')
        f.write(' '*N_indent+'main()
')

return 'done'

save_plot或者像这样定义函数(更好的版本使用 zip 压缩来生成更轻的图形文件):

def save_plot(fileName='',obj=None,sel='',ctx={}):

    import os
    import json
    import zlib
    import base64
    import libscript

    N_indent=4
    level=9#0 to 9, default: 6
    src=libscript.get_src(obj=obj,sel=sel)
    obj=libscript.load_obj(src=src,ctx=ctx,debug=False)
    bin=base64.b64encode(zlib.compress(json.dumps(obj),level))

    if(os.path.isfile(fileName)): os.remove(fileName)
    with open(fileName,'w') as f:
        f.write('import sys
')
        f.write('sys.dont_write_bytecode=True
')
        f.write('def main():
')
        f.write(' '*N_indent+'import base64
')
        f.write(' '*N_indent+'import zlib
')
        f.write(' '*N_indent+'import json
')
        f.write(' '*N_indent+'import libscript
')
        f.write(' '*N_indent+'bin="'+str(bin)+'"
')
        f.write(' '*N_indent+'obj=json.loads(zlib.decompress(base64.b64decode(bin)))
')
        f.write(' '*N_indent+'libscript.exec_obj(obj=obj,tempfile=False)
')

        f.write('if(__name__=="__main__"):
')
        f.write(' '*N_indent+'main()
')

return 'done'

libscript这利用了我自己的模块,它主要依赖于模块inspectast。如果有人感兴趣,我可以尝试在 Github 上分享它(首先需要进行一些清理,然后我开始使用 Github)。

save_plot此函数和模块背后的想法libscript是获取创建图形的 Python 指令(使用 module inspect),分析它们(使用 module ast)以提取它所依赖的所有变量、函数和模块,从执行上下文中提取它们并将它们序列化为 Python 指令(变量的代码将类似于t=[0.0,2.0,0.01]... ,模块的代码将类似于import matplotlib.pyplot as plt... )添加到图形指令的前面。生成的 Python 指令将保存为 Python 脚本,其执行将重建原始 matplotlib 图形。

你可以想象,这对大多数(如果不是全部)matplotlib 图形都很有效。

解决方案 6:

如果您希望将 Python 图保存为交互式图形,以便修改并与其他人共享(如 MATLAB .fig 文件),那么您可以尝试使用以下代码。这里z_data.values只是一个 numpy ndarray,因此您可以使用相同的代码来绘制和保存自己的数据。那么就不需要使用 pandas 了。

任何人(无论是否使用 Python)都可以打开此处生成的文件并以交互方式进行修改,只需单击它并在 Chrome/Firefox/Edge 等浏览器中打开即可。

import plotly.graph_objects as go
import pandas as pd

z_data=pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv')

fig = go.Figure(data=[go.Surface(z=z_data.values)])

fig.update_layout(title='Mt Bruno Elevation', autosize=False,
                  width=500, height=500,
                  margin=dict(l=65, r=50, b=65, t=90))

fig.show()
fig.write_html("testfile.html")
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2974  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1836  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与管理过程中扮演着至关重要的角色。然而,在实际运行中,资源冲突是经常会遇到的难题。资源冲突可能导致项目进度延迟、成本增加以及产品质量下降等一系列问题,严重影响企业的效益与竞争力。因此,如何有效应对PLM系统中的资源冲突,成为众多企业关注的焦点。接下来,我们将详细探讨5...
plm项目管理系统   47  
  敏捷项目管理与产品生命周期管理(PLM)的融合,正成为企业在复杂多变的市场环境中提升研发效率、增强竞争力的关键举措。随着技术的飞速发展和市场需求的快速更迭,传统的研发流程面临着诸多挑战,而将敏捷项目管理理念融入PLM,有望在2025年实现研发流程的深度优化,为企业创造更大的价值。理解敏捷项目管理与PLM的核心概念敏捷项...
plm项目   47  
  模块化设计在现代产品开发中扮演着至关重要的角色,它能够提升产品开发效率、降低成本、增强产品的可维护性与可扩展性。而产品生命周期管理(PLM)系统作为整合产品全生命周期信息的关键平台,对模块化设计有着强大的支持能力。随着技术的不断发展,到 2025 年,PLM 系统在支持模块化设计方面将有一系列令人瞩目的技术实践。数字化...
plm软件   48  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用