SVGファイルの利用
Ipython Notebook内にMatplotlibで描画されるグラフは、標準ではpngと呼ばれる、ビットマップイメージです。 この形式はブラウザ上に表示するには適していますが、そのままの設定で印刷物にすると解像度が十分ではありません。
plt.savefig()というコマンドで実行時に高解像度の画像ファイルに変換する事は可能で、 恐らく、それが一般的な使用方法として想定されているものと思います。 しかし、この方法だと画像保存のために演算を初めからしなおして、必要な箇所にplt.savefig()を追加していく必要があります。 計算時間が掛かる場合など、このようなやり方を避けたい場合もあると思います。
その解決方法には2つあると思います。 一つ目は、初めから高解像度のpngファイルにするという方法です。 これは、ipython notebook用のmatplotlibの設定を変える必要があります。
そのために、今回はipython notebookをpylabの引数無しで起動しています。
Matplotlibの設定を変えるには、pylabの実行前に以下のようなコマンドを実行する必要があります。
%config InlineBackend.rc = {'font.size': 20, 'figure.figsize': (12.0, 8.0),'figure.facecolor': 'white', 'savefig.dpi': 72, 'figure.subplot.bottom': 0.125, 'figure.edgecolor': 'white'}
%pylab inline
x=np.linspace(0,2*np.pi)
plt.plot(x,np.sin(x))
plt.figure()
plt.plot(x,np.cos(x))
デフォルトの設定(私の場合にはC:.ipythondefaultnotebook_config.py)の値と比べて、'font.size'と 'figure.figsize'を大きくしました。 ところが、こうすると線が細すぎます。 つまり、このようなやり方だと折角Matplotlibにおいて、グラフを綺麗に見せるために設定されている様々な初期設定を、色々と変えなければならなくなる可能性があります。
また、ブラウザで見る際には見た目が大きすぎます。
2つ目の方法は画像形式をSVGに変える事で、これが本命です。
%config InlineBackend.rc = {'font.size': 10, 'figure.figsize': (6.0, 4.0),'figure.facecolor': 'white', 'savefig.dpi': 72, 'figure.subplot.bottom': 0.125, 'figure.edgecolor': 'white'}
まずは設定を戻しておきます。
%config InlineBackend.figure_format = 'svg'
%pylab inline
x=np.linspace(0,2*np.pi)
plt.plot(x,np.sin(x))
plt.figure()
plt.plot(x,np.cos(x))
この方法だと、ブラウザ上で大きく表示されていませんが、全体の表示を拡大(「ctrl」+「+」)すると解像度が高い事が分かります。 ベクターグラフィックなので、当然ですが。
この埋め込まれたSVGファイルを取り出す方法として二つの方法を紹介します。
一つはInternetExplorer(IE)を用いる方法です。 ノートブックファイル(".ipynb")やnbconvertで作成したhtmlファイルをIEで開き、SVGファイルの上でマウスを右クリックすれば、svgファイルで保存することが出来ます。 その際、pngファイルやbitmapファイルでも保存できますが、高い解像度の画像にはなりませんでした。 一つのノートブックから数個のグラフを保存するにはこの方法が良いでしょう。
二つ目は、nbconvertを用いる方法です。nbconvertでrst(reStructured Text)というファイル形式にすると、画像ファイルは別フォルダに保存されます。
!ipython nbconvert --to rst SVG2PNG
その際、画像ファイルのファイル名には自動的に番号が振られますので、どのファイルがどのグラフに対応しているのかがすぐには分かりません。
!dir SVG2PNG_files\*.SVG
似たようなグラフがある場合には出来上がった".rst"という拡張子のファイルをエディタで開いてみて下さい。 rstはipython notebookで採用されているmarkdownと似たような軽量マークアップ言語なので、エディタでみればノートブックとの対応は完全につくはずです。
nbconvertはmarkdownにも変換できるとされているのですが、なぜか私が変換すると、画像ファイルへのリンクが出来ませんでした。 まだバグがあるのだと思います。 markdownへの変換が出来れば、IpythonNotebookに貼り付ける事で対応がより分かりやすくなるのですが。。
SVGからPNGへの変換
さて、出来上がったSVGファイルを高解像度のPNGファイルにしたいという方も多いと思います。 SVGというのは国際標準に基づいた形式なのですが、現実には対応ソフトが少ないのです。 PNGへの変換ソフトとして、Inkscapeを紹介します。 これはWindowsでも簡単に動作するオープンソースのソフトです。 このソフトはSVGのファイルを作成、編集するのが本来の目的なのですが、ファイル変換ソフトとしても使えます。
InkscapeはPythonのソフトではないのですが、コマンドラインからGUI無しでファイル変換を実行できます。 そこでsubprocessというpythonモジュールを用いて、ipython notebook上から実行してみましょう。
まずは、変換するファイルの入ったフォルダを指定します。
def get_directory():
import Tkinter
import tkFileDialog
import tkMessageBox
root=Tkinter.Tk()
root.withdraw()
tkMessageBox.showinfo('showinfo','ディレクトリ名を取得します。')
dirname=tkFileDialog.askdirectory()
return dirname
image_folder=get_directory()
print image_folder
フォルダ内のsvgファイル名を取得します。
import glob
import os.path
filenames = glob.glob(image_folder+'/*.svg')
filenames_without_ext=[]
for filename in filenames:
#print file
root, ext = os.path.splitext(filename)
#print root
filenames_without_ext.append(root)
for filename in filenames_without_ext:
print filename
Inkscapeをsubprocessで動かして、SVGファイルをPNGファイルに変換します。この段階で解像度を選択できます。
import subprocess
for file in filenames_without_ext:
args= '"c:\Program Files\Inkscape\Inkscape.com" -z -e ' +file+'.png '+ '-w 1024 '+file+'.svg '
#上の-w 1024の数字で横幅のピクセル数が決まる。
#-h 600 などと縦のピクセル数で指定することも可能。
p=subprocess.Popen(args,stdout=subprocess.PIPE)
for i in p.stdout.read().split('\n'):
print i
if p.wait()==0:
print u"変換成功!"
変換結果を表示します。
from IPython.core.display import Image, display
for file in filenames_without_ext:
filename=file+'.png'
print filename
display(Image(filename=filename,width=512))
#そのまま表示すると大きすぎるので縮小して表示する。なぜか、nbconvert後のhtmlでは元に戻ってしまうので、貼り直しました。
まとめ
SVG形式は殆どのブラウザが対応しています。また、グラフによってはファイルサイズを小さくできます。 ですから、デフォルトでSVGになるように、初期設定ファイル(ipython_notebook_config.py)を変更しておいても良いと思います。 デメリットはブラウザ上で画像だけを拡大するというのが出来なくなる程度でしょう。 また、今回は自分自身の中でnbconvertや変換を行いましたが、この作業は別のノートブック上で行った方が実際には混乱が少ないと思います。
最後のPNGの表示が大きすぎたので、nbconvert後で貼り直しました。
返信削除