回答:
これはすばらしい機能ですが、私の知る限り、Matplotlibには実装されておらず、数値の格納方法が原因で、実装が難しい場合があります。
(a)データの処理を図の生成(データを一意の名前で保存)とは別に処理し、図の生成スクリプトを作成(保存されたデータの指定されたファイルをロード)して、必要に応じて編集するか、または(b )PDF / SVG / PostScript形式で保存し、Adobe Illustrator(またはInkscape)などの豪華な図エディタで編集します。
2012年秋の編集後:他の人が下で指摘したように(これは受け入れられる回答であるため、ここで言及します)、バージョン1.2以降のMatplotlibでは数値をピクルすることができました。リリースノート状態、それは実験的な機能であり、他の1つのmatplotlibのバージョンおよび開口部の図を保存することはできません。また、信頼できないソースからピクルスを復元することは、一般的に安全ではありません。
プロットを共有/後で編集する場合(最初に重要なデータ処理が必要であり、数か月後に科学出版物の査読中に言う必要があるかもしれません)、私はまだ(1)のワークフローにプロットを生成する前にデータ処理スクリプトを用意することをお勧めします(プロットに入る)処理されたデータをファイルに保存し、(2)プロットを再作成するための(必要に応じて調整する)独立したプロット生成スクリプトを用意します。このように、プロットごとに、スクリプトをすばやく実行して再生成できます(そして、新しいデータでプロット設定をすばやくコピーできます)。とはいえ、図を酸洗いすることは、短期/インタラクティブ/探索的データ分析に便利かもしれません。
pickle
MPLフィギュアで動作するようになったので、これを実行すると、Matlabの「.fig」フィギュアファイルのように、適切に機能するように見えます。それを行う方法の例については、以下の私の答え(今のところ?)を参照してください。
私はこれを行う方法を見つけました。@pelsonが言及した「実験的なピクルスのサポート」は非常にうまく機能します。
これを試して:
# Plot something
import matplotlib.pyplot as plt
fig,ax = plt.subplots()
ax.plot([1,2,3],[10,-10,30])
インタラクティブな調整後、Figureオブジェクトをバイナリファイルとして保存します。
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は、いくつかのトリックを使用して、平坦化されたデータを再構築します。)
私はピクルスを使用してMatplotlibのフィギュアを保存することから素晴らしいヒントを得ました。
pickle
ドキュメントには、オブジェクトがピクルス化(保存)されたときと同じように環境をセットアップする必要があると記載されていると思いましたがimport matplotlib.pyplot as plt
、ピクルル化解除(ロード)するときに必要がないことがわかりました-ピクルス化されたファイルにインポートステートメントを保存します。
with open('FigureObject.fig.pickle', 'rb') as file: figx = pickle.load(file)
figx.show()
呼び出す必要がありますplt.show()
。
Matplotlib 1.2の時点で、実験的なピクルのサポートが追加されました。それを試してみて、それがあなたのケースにうまくいくかどうか見てください。問題がある場合は、Matplotlibメーリングリストまたはgithub.com/matplotlib/matplotlibで問題を開いてお知らせください。
PicklingError: Can't pickle <type '_macosx.GraphicsContext'>: it's not found as _macosx.GraphicsContext
。
PicklingError
はplt.show()
、ピクルスを行う前に呼び出す場合にのみ発生します。だからちょうどplt.show()
後に置きpickle.dump()
ます。
fig.show()
問題に見えません-おそらくそのバグは修正されました。show()
問題なく前後に漬けることができます。
なぜPythonスクリプトを送信しないのですか?MATLABの.figファイルは、受信者がMATLABにそれらを表示するように要求するため、Matplotlibの表示を必要とするPythonスクリプトを送信するのとほぼ同じです。
代わりに(免責事項:私はまだこれを試していません)、図を酸洗いすることもできます:
import pickle
output = open('interactive figure.pickle', 'wb')
pickle.dump(gcf(), output)
output.close()
MyPlot.fig.pickle
ファイルを保存したりすることができます。後で必要に応じて、プロットの表示を調整することができます。これは、Matlabの.fig
ファイルの優れた点でもあります。イチジクのサイズ/アスペクト比を変更する必要がある場合に特に役立ちます(プレゼンテーション/論文に挿入するため)。
良い質問。これは、次のドキュメントテキストですpylab.save
。
pylabは保存機能を提供しなくなりましたが、古いpylab関数は引き続きmatplotlib.mlab.saveとして使用できます(pylabでは「mlab.save」として引き続き参照できます)。ただし、プレーンテキストファイルの場合は、numpy.savetxtをお勧めします。numpy配列を保存するには、numpy.saveとそのアナログnumpy.loadをお勧めします。これらはpylabでnp.saveおよびnp.loadとして利用できます。
pylab.save
です。実際、ドキュメントのテキストから、それを使用すべきではないようです。
私は、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='\n'.join([' '*N_indent+line for line in src.split('\n')])
if(os.path.isfile(fileName)): os.remove(fileName)
with open(fileName,'w') as f:
f.write('import sys\n')
f.write('sys.dont_write_bytecode=True\n')
f.write('def main():\n')
f.write(src+'\n')
f.write('if(__name__=="__main__"):\n')
f.write(' '*N_indent+'main()\n')
return 'done'
または、次のsave_plot
ような関数を定義します(zip圧縮を使用して軽量のFigureファイルを生成するより良いバージョン):
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\n')
f.write('sys.dont_write_bytecode=True\n')
f.write('def main():\n')
f.write(' '*N_indent+'import base64\n')
f.write(' '*N_indent+'import zlib\n')
f.write(' '*N_indent+'import json\n')
f.write(' '*N_indent+'import libscript\n')
f.write(' '*N_indent+'bin="'+str(bin)+'"\n')
f.write(' '*N_indent+'obj=json.loads(zlib.decompress(base64.b64decode(bin)))\n')
f.write(' '*N_indent+'libscript.exec_obj(obj=obj,tempfile=False)\n')
f.write('if(__name__=="__main__"):\n')
f.write(' '*N_indent+'main()\n')
return 'done'
これはlibscript
、自分のモジュールを使用します。これは主にモジュールinspect
とに依存していますast
。関心が表明されている場合は、Githubで共有してみることができます(最初にクリーンアップが必要で、Githubを使い始めるには私が必要です)。
このsave_plot
関数とlibscript
モジュールの背後にある考え方は、図を作成するPython命令を取得し(moduleを使用inspect
)、それらを分析(moduleを使用ast
)して、それが依存するすべての変数、関数、およびモジュールを抽出し、実行コンテキストからこれらを抽出してシリアル化することですPythonの命令(変数のコードはt=[0.0,2.0,0.01]
...であり、モジュールのコードはimport matplotlib.pyplot as plt
...である)が図の命令の前に追加されているため。結果のpython命令は、実行によって元のmatplotlibフィギュアが再構築されるpythonスクリプトとして保存されます。
ご想像のとおり、これは(すべてではないにしても)ほとんどのmatplotlibの数値に適しています。