プログラミング/julia/グラフの書き方 のバックアップ差分(No.9)

更新


  • 追加された行はこの色です。
  • 削除された行はこの色です。
[[プログラミング/julia]]

* 目次 [#feeedfdd]

#contents

* Plots を使う [#m6aac946]

関数グラフの描画には [[Plots>http://docs.juliaplots.org/latest/]] というライブラリを使う。

これは様々なグラフ描画ライブラリを julia から同一の API で使えるようにするためのラッパーライブラリ。

実際の描画を行う Backend の描画ライブラリとして何を選ぶかによって、描画速度や仕上がりなどが大きく変わってくる。

** インストール [#k3a82351]

バックエンドのライブラリがないと描画できないので、とりあえず GR も入れておく。

 LANG:julia
 Pkg.add("Plots")
 Pkg.add("GR")
 
 # github の最新版を使うには次のようにする
 Pkg.checkout("Plots")

** バックエンドライブラリ [#we87f61f]

実際の描画を行うバックエンドライブラリはいろいろある。

http://docs.juliaplots.org/latest/backends/

例えばバックエンドライブラリとして GR を使うには次のようにする。

 LANG:julia
 using Plots    // Plots ライブラリの関数を取り込む
 Plots.gr()     // Plots のバックエンドとして GR を使うことにする
 gr()           // using してあるので、こう書いても同じことになる
 
 plot()         // GR を使ったグラフが出力される

たぶん、2018春時点で有名なのは GR, Plotly, PyPlot の3つ。

PGFPlots や GLVisualize もまずまず?

各ライブラリの対応表はこちら:~
http://docs.juliaplots.org/latest/supported/

それぞれの特徴を独断と偏見でまとめると:

- GR : Plots.gr()
-- 出力が svg になるので、印刷したときキレイ
-- 点がたくさんあるとブラウザが固まる
-- 普段使いにはこれがベスト?
-- 3D 表示の一部で x, y パラメータ指定の仕様が他と異なる? surface や wireframe
-- 3D 表示の一部に OpenGL を使うため物理ディスプレイなしでは使いづらい? → juliabox でも動かない~
~
- Plotly : Plots.plotly()
-- マウスでグラフの表示範囲などを調整可能
-- 特に3D表示をぐりぐり動かせるのは圧巻
-- 出力が svg になるので、印刷してもキレイ
-- 点がたくさんあるとブラウザが固まる
-- Gists 上などでは javascript が許可されないためまるっきり表示されない
-- jupyter notebook のリロードでもエラーになり画像が表示されない(場合がある?)
-- 試行錯誤中は良いのだが、最終版としてはつらい~
~
- PyPlot : Plots.pyplot()
-- 出力が png になるため、データ点の多いグラフでも Web ブラウザに負担がかからない
-- ただ印刷などすると dpi 不足で画像が粗くなりがち
-- インストール時に PyCall の設定が必要(下記参照)
-- 一番安定している気がする
-- GR が不得意とする 3D 表示や点数の多いグラフではこれがいい~
~
- PGFPlots : Plots.pgfplots()
-- 出力が svg になるので、印刷してもキレイ
-- 点がたくさんあるとブラウザが固まる
-- 3D は対応していないものが多い
-- 出力がキレイ(なのか?)~
~
- GLVisualize : Plots.glvisualize()
-- OpenGL を使うので高速(?)
-- 対応する機能が多い(?)
-- ディスプレイドライバが OpenGL に対応していなければならない
-- 物理ディスプレイのない環境で動かすのは大変そう(まだ動かせてない)

** 表示例 [#fb42c0f4]

それぞれの表示はこんな感じ。~
- PyPlot は一番問題が少ないが、出力は png なので拡大すると粗い
- GD は Surface プロットができない
- Plotly はグラフを複数並べると円グラフや3Dグラフの表示がおかしくなる
-- 単体なら問題ない
- PGFPlots は Surface, Pie, WireFrame, HeatMap プロットができない

共通コードはこちら:

 LANG:julia
 using Plots
 
 data1d=rand(10)
 data1d2=rand(10)
 data1d3=rand(10)
 data2d=[rand()/5 + exp(-(x^2+y^2)/100) for x in -10:10, y in -10:10]
 data1dp=0:2pi/10:2pi;
 
 function example(no3d=false,forpgf=false)
     plot(
         plot(data1d),
         plot(data1d,xscale=:log10,yscale=:log10),
         plot(data1d,seriestype=:steppre),
         plot(data1d,seriestype=:step),
         plot(data1d,seriestype=:scatter),
         plot(data1d,seriestype=:bar),
         forpgf ? plot() : plot(data1d,seriestype=:pie),
         plot(data2d,seriestype=:contour,legend=:none),
         plot(data2d,seriestype=:contour,fill=true,legend=:none),
         no3d ? plot() : plot(data2d,seriestype=:surface,legend=:none),
         forpgf ? plot() : plot(data2d,seriestype=:wireframe),
         forpgf ? plot() : plot(data2d,seriestype=:heatmap,legend=:none),
         plot(data1dp,data1d,proj=:polar),
         plot(data1d,data1d2,data1d2,seriestype=:scatter3d),
         plot(data1d,data1d2,data1d2),
         plot([0,1,0,-1],[-1,0,1,0],seriestype=:shape),
         layout=(4,4),size=(800,800),legend=:none
     )
 end

*** PyPlot [#w98b3df9]

&ref(test-julia-pyplot.png,,50%);

*** GR [#td670520]

&ref(test-julia-gr.png,,50%);

*** Plotly [#md3b9bb9]

&ref(test-julia-plotly.png,,50%);

あまりにひどいので、表示のおかしなものをすべて取り去ったところこうなった。

&ref(test-julia-plotly2.png,,50%);

ここでおかしかったものも、単体で表示する分にはまともに表示される。

対数スケールの軸がキレイに表示されているのは Plotly だけだった。
*** PGFPlots [#ad69e624]

&ref(test-julia-pgfplots.png,,50%);

*** svg vs png [#ob14598b]

GR のグラフは拡大してもキレイ

&ref(test-julia-plots-gr.png,border);

PyPlot のグラフは拡大するとぼやける

&ref(test-julia-plots-pyplot.png,border);

*** Plotly のグラフはインタラクティブに編集できるが・・・ [#dd1ca975]

ぐりぐり動く。

&attachref(test-julia-plots-plotly.gif,border,50%);

&attachref(test-julia-plots-plotly2.gif,border);

でも、ブラウザ上でリロードするだけで、

>COLOR(RED){Javascript error adding output!}
>COLOR(RED){ReferenceError: Plotly is not defined}
>COLOR(RED){See your browser Javascript console for more details.}

などというエラーが出てグラフが表示されなくなってしまう。

Gist 上でも無理。

#gist(osamutake/88c0d0676fe659df23769d2bdbcc21b6);

nbviewer でもダメだった。

http://nbviewer.jupyter.org/gist/osamutake/88c0d0676fe659df23769d2bdbcc21b6

*** gist から nbviewer への飛び方 [#j586e609]

ちょっとオフトピだけど・・・

gist 上で .ipynb を見たとき、右上に θ マークが表示されている場合があり、
そこにカーソルを合わせると nbviewer へのリンクが出るのだけれど、

&ref(gist-to-nbviewer.png,border,50%);

これをクリックしてもうまく nbviewer に繋がらない。

本来なら

http://nbviewer.jupyter.org/gist/osamutake/da4856f49e025e4646214a0ce690ba06

へ飛ぶべきが、

http://nbviewer.jupyter.org/github/osamutake/da4856f49e025e4646214a0ce690ba06/blob/9c7f6f6d2adc84c7dc78fa9874b22aa05b7d10cc/test-julia-plots.ipynb

へ飛んでしまう。

たぶん、github に入れた .ipynb ファイルからだとうまく行くんだと思う。

github の文字を gist に直し、/blob/ 以下を削除すれば良いのだけれど、
もっと簡単には http://nbviewer.jupyter.org/ に gist の URL を入れることで本来のページに飛べる。

* バックエンドライブラリのインストール [#t3742bc9]

結構いろいろ大変。~
先人達の足跡を探すのに非常に時間がかかる。。。
** GR のインストール [#b191daad]

 LANG:console
 $ julia
 julia> Pkg.add("GR")

これだけでOK

** GLVisualize のインストール [#vf93d43a]

Web ブラウザから jupyter 経由で使えるようにインストールしたかったのですが、現時点ではできてません。

 LANG:console
 $ julia
 julia> Pkg.add("GLVisualize ")
  ...
   -- Could NOT find Vulkan (missing:  VULKAN_LIBRARY VULKAN_INCLUDE_DIR) 
   -- Using X11 for window creation
   ...
   CMake Error at CMakeLists.txt:222 (message):
    The RandR library and headers were not found
 julia>^D

OpenGL が必要らしい。

 LANG:console
 $ sudo apt-get install libgl1-mesa-dev
  パッケージリストを読み込んでいます... 完了
  依存関係ツリーを作成しています
  状態情報を読み取っています... 完了
  以下のパッケージが自動でインストールされましたが、もう必要とされていません:
    libdmx-dev libdmx1 libfontconfig1-dev libfontenc-dev libfreetype6-dev libfs-dev libfs6 libice-dev
    libmirclient-dev libmircommon-dev libmircookie-dev libmircookie2 libmircore-dev libpciaccess-dev
    libpixman-1-dev libprotobuf-dev libprotobuf9v5 libsm-dev libxaw7-dev libxcomposite-dev libxcursor-dev
    libxfont-dev libxfont1-dev libxfont2 libxft-dev libxi-dev libxinerama-dev libxkbcommon-dev
    libxkbfile-dev libxmu-dev libxmu-headers libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev
    libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86dga-dev
    mir-client-platform-mesa-dev x11proto-bigreqs-dev x11proto-composite-dev x11proto-dmx-dev
    x11proto-dri3-dev x11proto-fonts-dev x11proto-present-dev x11proto-randr-dev x11proto-record-dev
    x11proto-render-dev x11proto-resource-dev x11proto-scrnsaver-dev x11proto-video-dev
    x11proto-xcmisc-dev x11proto-xf86bigfont-dev x11proto-xf86dga-dev x11proto-xf86dri-dev
    x11proto-xinerama-dev xserver-xorg-dev
  これを削除するには 'sudo apt autoremove' を利用してください。
  以下の追加パッケージがインストールされます:
    libdrm-amdgpu1 libdrm-common libdrm-dev libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libdrm2
    libgl1-mesa-glx libglapi-mesa mesa-common-dev
  以下のパッケージが新たにインストールされます:
    libdrm-common
  以下のパッケージはアップグレードされます:
    libdrm-amdgpu1 libdrm-dev libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libdrm2 libgl1-mesa-dev
    libgl1-mesa-glx libglapi-mesa mesa-common-dev
  アップグレード: 10 個、新規インストール: 1 個、削除: 0 個、保留: 26 個。
  1,062 kB のアーカイブを取得する必要があります。
  この操作後に追加で 616 kB のディスク容量が消費されます。
 $ julia
 julia> Pkg.build("GLVisualize ")

として試したところ、

 X11: The DISPLAY environment variable is missing

と言うエラーが出た。

ディスプレイドライバの OpenGL 機能を使ってレンダリングするので、
Web サーバー経由の jupyter からは使えないのかもしれない?

https://github.com/JuliaGL/GLVisualize.jl/issues/146

VirtualGL を使えばできるのかもしれないけれど、ちょっと追い切れなかった。

** Plotly のインストール [#add06469]

juliabox ならそのまま使えるのだけれど、
以下は自分で建てた jupyter サーバーにインストールする場合の話。

https://qiita.com/deaikei/items/b71c1ca2c4c2a2c37526 を見ながら。

julia 上で
 LANG: julia
 Pkg.add("Plotly")

とする前に、python の plotly モジュールを入れておかないとダメ。

 LANG:console
 $ python3 -m pip install plotly
 $ julia
 julia> Pkg.add("Plotly")

こうするのが正解。


** PyPlot のインストール [#k1b8dc14]

juliabox ならそのまま使えるのだけれど、
以下は自分で建てた jupyter サーバーにインストールする場合の話。

正しい手順はこちら > [[#e720f643]]

*** 試行錯誤 [#oc9732d3]

matplotlib を使うので、

 LANG:console
 $ sudo python3 -m pip install matplotlib

とすれば、python から使うのは簡単だった。

#gist(13f0268cafbb92bd1b270503b1c738a5);

julia から使うには、単に Pkg.add("PyPlot") しただけだと、

 InitError: Failed to import required Python module matplotlib.
 
 For automated matplotlib installation, try configuring PyCall to use the Conda.jl package's Python "Miniconda" distribution within Julia. Relaunch Julia and run:
     ENV["PYTHON"]=""
     Pkg.build("PyCall")
 before trying again.
 
 The pyimport exception was: PyError (ccall(@pysym(:PyImport_ImportModule), PyPtr, (Cstring,), name)
 
 The Python package matplotlib could not be found by pyimport. Usually this means
 that you did not install matplotlib in the Python version being used by PyCall.
 
 PyCall is currently configured to use the Python version at:
 
 python
 
 and you should use whatever mechanism you usually use (apt-get, pip, conda,
 etcetera) to install the Python package containing the matplotlib module.
 
 One alternative is to re-configure PyCall to use a different Python
 version on your system: set ENV["PYTHON"] to the path/name of the python
 executable you want to use, run Pkg.build("PyCall"), and re-launch Julia.
 
 Another alternative is to configure PyCall to use a Julia-specific Python
 distribution via the Conda.jl package (which installs a private Anaconda
 Python distribution), which has the advantage that packages can be installed
 and kept up-to-date via Julia.  As explained in the PyCall documentation,
 set ENV["PYTHON"]="", run Pkg.build("PyCall"), and re-launch Julia. Then,
 To install the matplotlib module, you can use `pyimport_conda("matplotlib", PKG)`,
 where PKG is the Anaconda package the contains the module matplotlib,
 or alternatively you can use the Conda package directly (via
 `using Conda` followed by `Conda.add` etcetera).
 
 ) <type 'exceptions.ImportError'>
 ImportError('No module named matplotlib',)
 
 
 during initialization of module PyPlot
 
 Stacktrace:
  [1] pyimport_conda(::String, ::String, ::String) at /home/osamu/.julia/v0.6/PyCall/src/PyCall.jl:609
  [2] __init__() at /home/osamu/.julia/v0.6/PyPlot/src/init.jl:175
  [3] _include_from_serialized(::String) at ./loading.jl:157
  [4] _require_from_serialized(::Int64, ::Symbol, ::String, ::Bool) at ./loading.jl:200
  [5] _require_search_from_serialized(::Int64, ::Symbol, ::String, ::Bool) at ./loading.jl:236
  [6] _require(::Symbol) at ./loading.jl:441
  [7] require(::Symbol) at ./loading.jl:405
  [8] include_string(::String, ::String) at ./loading.jl:522

と言われ、PyCall を build する必要があった。

@gif を使ってアニメーションをしようとしたところ、

 could not spawn `ffmpeg -v 0 -i /tmp/tmpsIoz72/%06d.png -vf palettegen=stats_mode=diff -y /tmp/tmpsIoz72/palette.bmp`: no such file or directory (ENOENT)

と言われた

 LANG:console
 $ sudo apt-get install ffmpeg

*** 正しい手順 [#e720f643]

 LANG:console
 $ sudo python3 -m pip install matplotlib
 $ julia
 julia> Pkg.add("PyPlot")
 julia> ENV["PYTHON"]=""
 julia> Pkg.build("PyCall")

ENV["PYTHON"]="" はシステムの python を使うためのおまじないっぽい?

** PGFPlots のインストール [#a20734e0]

GR, Plotly, PyPlot は juliabox でもそのまま使えるのだけれど、
PGFPlots は juliabox では使えないため、使いたければ自分で建てた 
jupyter サーバーにインストールするしかない。

正しい手順はこちら > [[#beed29ca]]

*** 試行錯誤 [#t5bf2924]

jupyter の上から Pkg.add("PGFPlots") としたところ、途中で

 Installing dependency libmagickwand-6.q16-2 via `sudo apt-get install libmagickwand-6.q16-2`:
 
 sudo: 端末 (tty) が存在せず、パスワードを尋ねる (askpass) プログラムが指定されていません
 =============================[ ERROR: ImageMagick ]=============================
 
 LoadError: failed process: Process(`sudo apt-get install libmagickwand-6.q16-2`, ProcessExited(1)) [1]
 while loading /home/osamu/.julia/v0.6/ImageMagick/deps/build.jl, in expression starting on line 122

というエラーが出た。
そこでコンソールからやってみたら、

 LANG:console
 $ julia
 julia> Pkg.build("PGFPlots")
  INFO: Building SpecialFunctions
  INFO: Building FFTW
  INFO: Building ImageMagick
  Installing dependency libmagickwand-6.q16-2 via `sudo apt-get install libmagickwand-6.q16-2`:
  [sudo] osamu のパスワード:
  パッケージリストを読み込んでいます... 完了
  依存関係ツリーを作成しています
  状態情報を読み取っています... 完了
  以下の追加パッケージがインストールされます:
    ghostscript gsfonts imagemagick-common libcupsfilters1 libcupsimage2 libgs9 libgs9-common libijs-0.35 libjbig2dec0 liblqr-1-0 libmagickcore-6.q16-2 libpaper-utils libpaper1
    poppler-data
  提案パッケージ:
    ghostscript-x hpijs fonts-droid texlive-lang-cjk libmagickcore-6.q16-2-extra poppler-utils fonts-arphic-ukai fonts-arphic-uming fonts-nanum
  以下のパッケージが新たにインストールされます:
  ghostscript gsfonts imagemagick-common libcupsfilters1 libcupsimage2 libgs9 libgs9-common   libijs-0.35 libjbig2dec0 liblqr-1-0 libmagickcore-6.q16-2 libmagickwand-6.q16-2
    libpaper-utils libpaper1 poppler-data
  アップグレード: 0 個、新規インストール: 15 個、削除: 0 個、保留: 20 個。
  12.1 MB のアーカイブを取得する必要があります。
  この操作後に追加で 48.1 MB のディスク容量が消費されます。
  続行しますか? [Y/n] 中断しました。
  ===============================================================================[ ERROR: ImageMagick ]===============================================================================
  
  LoadError: failed process: Process(`sudo apt-get install libmagickwand-6.q16-2`, ProcessExited(1)) [1]
  while loading /home/osamu/.julia/v0.6/ImageMagick/deps/build.jl, in expression starting on line 122
  
  ====================================================================================================================================================================================
  INFO: Building CodecZlib
  
  ==================================================================================[ BUILD ERRORS ]==================================================================================
  
  WARNING: ImageMagick had build errors.
  
   - packages with build errors remain installed in /home/osamu/.julia/v0.6
   - build the package(s) and all dependencies with `Pkg.build("ImageMagick")`
   - build a single package by running its `deps/build.jl` script
  
  ====================================================================================================================================================================================

となって、やはりエラー。おしい。

 LANG:console
 $ sudo apt-get install libmagickwand-6.q16-2
 $ julia
 julia> Pkg.build("PGFPlots")

で入った。

でも、plot を呼ぶと

 Error saving as SVG
 
 could not spawn `lualatex --enable-write18 --output-directory=. tikzpicture`: no such file or directory (ENOENT)

とのエラー。texlive-luatex を入れれば良いのかと思ったのだけれど、

 LANG:console
 $ sudo apt-get install texlive-luatex
 $ lua^T
  lua2dox_filter   luajittex        luaotfload-tool  luatex

で、lualatex というコマンドは入らなかった?

http://mickey-happygolucky.hatenablog.com/entry/2016/03/01/234228 を見て、

 LANG:console
 $ sudo apt-get install texlive-lang-cjk lmodern texlive-xetex
 $ which lualatex
  /usr/bin/lualatex

これでエラーメッセージが変わって、

 Error saving as SVG
 
 could not spawn `pdf2svg tikzpicture.pdf tikzpicture.svg`: no such file or directory (ENOENT)

そこで、

 LANG:console
 $ sudo apt-get install pdf2svg

これで正しく動作するようになった。

*** 正しい手順 [#beed29ca]

 LANG:console
 $ sudo apt-get install libmagickwand-6.q16-2 texlive-luatex texlive-lang-cjk lmodern texlive-xetex pdf2svg
 $ julia
 julia> Pkg.add("PGFPlots")

こうかな。

* Plots.plot に関数を与えるだけでグラフを書ける [#a6b4f0f6]

あまり用例を見ないのだけれど、直接関数を与えてグラフが書ける。とても便利。

&ref(plot-function1.png);

&ref(plot-function2.png);

ただ今のところ、グラフがカクカクになってしまったときにサンプリング点数を増やす方法が分からなくて困ってる。
* @manipulate でインタラクティブにパラメータを変えられる [#a67f1d22]

Interact モジュールと widget/extension を使う。

実際には、あらかじめパラメータを変えたグラフをすべて用意しておき、
入力値に従って切り替えて表示しているっぽい。

&ref(プログラミング/julia/インストール/jupyter-interact.gif,border,50%);

* このあたりを見る? [#v8a20489]

Plots/GR: グラフ package のおすすめ~
http://www.cas.cmc.osaka-u.ac.jp/~paoon/misc/julia/post/trouble-plots-package/

JupyterでJuliaを動かして回帰分析をやってみる。~
https://qiita.com/kenmatsu4/items/b77ecec75418cbaa2212

jupyter notebookで触れるプロットを描く~
http://ksknw.hatenablog.com/entry/2016/08/04/233103

Julia言語と Plots + GR で複素関数のgifアニメーションを作る~
http://optie.hatenablog.com/entry/2018/03/29/210619

GR - examples~
http://docs.juliaplots.org/latest/examples/gr/

PlotThemes~
https://github.com/JuliaPlots/PlotThemes.jl


PGFPlots.ipynb~
http://nbviewer.jupyter.org/github/sisl/PGFPlots.jl/blob/master/doc/PGFPlots.ipynb
* コメント・質問 [#xbcaa13f]

#article_kcaptcha


Counter: 39740 (from 2010/06/03), today: 1, yesterday: 0