[python] 대화 형 Matplotlib 그림 저장

다시 열 수 있고 일반적인 상호 작용을 복원 할 수 있도록 Matplotlib 그림을 저장하는 방법이 있습니까? (MATLAB의 .fig 형식과 비슷합니까?)

이러한 대화 형 그림을 생성하기 위해 동일한 스크립트를 여러 번 실행하고 있습니다. 또는 동료들에게 여러 개의 정적 PNG 파일을 보내 플롯의 다양한 측면을 보여줍니다. 차라리 피겨 객체를 보내고 그들 스스로 상호 작용하게하고 싶습니다.



답변

이것은 훌륭한 기능이지만 AFAIK는 Matplotlib에서 구현되지 않으며 수치가 저장되는 방식으로 인해 직접 구현하기 어려울 수 있습니다.

(a) 그림 생성 (고유 한 이름으로 데이터 저장)에서 데이터 처리를 분리하고 그림 생성 스크립트 (저장된 데이터의 지정된 파일로드)를 작성하고 적합하다고 생각되는대로 편집하거나 (b ) PDF / SVG / PostScript 형식으로 저장하고 Adobe Illustrator (또는 Inkscape ) 와 같은 멋진 그림 편집기에서 편집 합니다.

편집 게시물 Fall 2012 : 다른 사람들이 아래에서 지적했듯이 (허용되는 답변으로 여기에 언급했지만) 버전 1.2 이후 Matplotlib를 사용하면 수치를 피클 할 수 있습니다. 는 AS 릴리스 노트 상태 , 그것은 실험적인 기능이며 다른 하나 개하기 matplotlib 버전과 구멍에 그림을 저장하는 지원하지 않습니다. 신뢰할 수없는 소스에서 피클을 복원하는 것도 일반적으로 안전하지 않습니다.

플롯을 공유 / 나중에 편집하려면 (먼저 중요한 데이터 처리가 필요하고 몇 달 후에 과학 간행물에 대한 동료 검토 중에 수정해야 할 수 있음) 플롯을 생성하기 전에 (1)의 워크 플로를 사용하는 것이 좋습니다. 처리 된 데이터 (플롯으로 이동)를 파일에 저장하고 (2) 별도의 플롯 생성 스크립트 (필요에 따라 조정)를 사용하여 플롯을 다시 만듭니다. 이렇게하면 각 플롯에 대해 스크립트를 빠르게 실행하고 다시 생성 할 수 있습니다 (새 데이터로 플롯 설정을 빠르게 복사). 즉, 수치를 산세하는 것은 단기 / 대화 형 / 탐색 데이터 분석에 편리 할 수 ​​있습니다.


답변

이 작업을 수행하는 방법을 방금 찾았습니다. @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는 평면화 된 데이터를 재구성하는 몇 가지 트릭과 함께 작동합니다 .)

Pickle을 사용하여 Matplotlib Figures 저장 에서 훌륭한 팁을 얻었습니다 .


답변

Matplotlib 1.2부터 실험적인 피클 지원이 제공됩니다. 그것을 시도하고 그것이 당신의 경우에 잘 작동하는지 확인하십시오. 문제가있는 경우 Matplotlib 메일 링리스트 또는 github.com/matplotlib/matplotlib 에서 문제를 열어 알려주십시오 .


답변

왜 파이썬 스크립트를 보내지 않습니까? MATLAB의 .fig 파일은 수신자에게 MATLAB이이를 표시하도록 요구하므로 표시하는 데 Matplotlib가 필요한 Python 스크립트를 보내는 것과 거의 같습니다.

또는 (면책 조항 : 아직 시도하지 않았습니다) 그림을 피클 링 할 수 있습니다.

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


답변

좋은 질문. 다음은의 문서 텍스트입니다 pylab.save.

이전 pylab 함수는 여전히 matplotlib.mlab.save로 사용할 수 있지만 pylab은 더 이상 저장 기능을 제공하지 않습니다 (pylab에서 “mlab.save”로 계속 참조 할 수 있음). 그러나 일반 텍스트 파일의 경우 numpy.savetxt를 권장합니다. numpy 배열을 저장하려면 numpy.save 및 pylab에서 np.save 및 np.load로 사용할 수있는 아날로그 numpy.load를 권장합니다.


답변

나는 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 압축을 사용하는 더 나은 버전) :

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대부분의 모듈에 의존하는, 내 자신의 inspectast. 관심이 있으면 Github에서 공유해 볼 수 있습니다 (먼저 정리가 필요하고 Github를 시작하려면 제가 필요합니다).

save_plot함수와 libscript모듈의 이면에있는 아이디어 는 Figure를 생성 (module 사용 inspect)하고 분석 (module 사용 ast)하여 모든 변수, 함수 및 모듈 가져 오기를 추출하고 실행 컨텍스트에서이를 추출하고 직렬화 하는 Python 명령어를 가져 오는 것입니다. 파이썬 명령어 (변수에 대한 코드는 t=[0.0,2.0,0.01]…와 같고 모듈에 대한 코드는 …와 같음 import matplotlib.pyplot as plt)로 그림 명령어 앞에 추가됩니다. 결과 python 명령어는 실행이 원래 matplotlib 그림을 다시 빌드하는 python 스크립트로 저장됩니다.

상상할 수 있듯이 이것은 대부분의 (전부는 아니지만) matplotlib 그림에서 잘 작동합니다.


답변