Juliaで綺麗なプロットを作る：Makie.jlのインストールと使い方

Juliaで何かをプロットする時に何かいいものがないかと探していました。
そして、Makie.jlを発見しました。
https://github.com/JuliaPlots/Makie.jl
マニュアルは
http://makie.juliaplots.org/stable/index.html
にあります。

これを使うと非常に綺麗なプロットを作ることができます。特に、３次元プロットが綺麗です。
Julia 1.0.0でインストールする際に少し詰まった部分があったので、そこを解消する方法を記します。

# インストール
Makie.jlのインストールをするには、AbstractPlotting.jlとGLMakie.jlが必要らしいので、]を押してパッケージモードにしてから

```
add AbstractPlotting#master Makie#master GLMakie#master
```
として、三つをインストールします。
もしMakieだけをインストールしてしまうと、

```
../assets/icons: No such file or directory
```
みたいなエラーが出ます。このエラーが出てしまっている時は、GLMakieが入っていないようです。
参考URL:
https://github.com/JuliaPlots/Makie.jl/issues/261

さらに、作った図を保存する際に、チュートリアル通りにやろうとするとエラーが出ます。これは、```FileIO```が必要なためで、
]を押してパッケージモードで

```
add FileIO
```
として入れてください。そして、```using FileIO```をすると```save```でファイルが保存できるようになります。

# グラフの例（マニュアルにあるグラフ）
まずはじめに、マニュアルにあるグラフをプロットしてみましょう。

## 立体
立体のグラフの例を示します。

```julia
using Makie
using FileIO
v1 = volume(rand(32, 32, 32), algorithm = :mip)
save("volume.png", v1)
```
とすると、
![volume.png](https://qiita-image-store.s3.amazonaws.com/0/246113/beb4f22b-df7a-fcbd-359b-edb8d8b7c070.png)
が作れます。

##表面プロット
表面プロット（いわゆる色付きの3Dグラフ）は、

```julia
using Makie
using FileIO

using Makie

N = 51
x = range(-2, stop = 2, length = N)
y = x
z = (-x .* exp.(-x .^ 2 .- (y') .^ 2)) .* 4

scene = wireframe(x, y, z)
xm, ym, zm = minimum(scene.limits[])
scene = surface!(scene, x, y, z .+ 0.05)
contour!(scene, x, y, z, levels = 15, linewidth = 2, transformation = (:xy, zm))
save("surface.png",scene)
```
となります。ここで、保存する際には`scene`を指定しています。

![surface.png](https://qiita-image-store.s3.amazonaws.com/0/246113/ba1b1948-d812-3182-8617-f767965938ac.png)



## 等値面の3Dプロット
等値面は

```julia
using Makie
using LinearAlgebra
using FileIO

function test(x, y, z)
    xy = [x, y, z]
    ((xy') * Matrix(I, 3, 3) * xy) / 20
end
x = range(-2pi, stop = 2pi, length = 100)
scene = Scene()
c = contour!(scene, x, x, x, test, levels = 6, alpha = 0.3)[end]
xm, ym, zm = minimum(scene.limits[])
 # c[4] == fourth argument of the above plotting command
contour!(scene, x, x, map(v-> v[1, :, :], c[4]), transformation = (:xy, zm), linewidth = 10)
heatmap!(scene, x, x, map(v-> v[:, 1, :], c[4]), transformation = (:xz, ym))
contour!(scene, x, x, map(v-> v[:, :, 1], c[4]), fillrange = true, transformation = (:yz, xm))
save("v2.png", c)
```
で描くことができて、出来上がるグラフは
![v2.png](https://qiita-image-store.s3.amazonaws.com/0/246113/b1593c66-e046-9408-b863-28b2e5ff7c19.png)
となります。この立体はJuliaを起動してから実行するとグルグルマウスで回せます(Macで確認)。

##球の上の矢印

```julia

using Makie
using FileIO

using LinearAlgebra

n = 20
f   = (x,y,z) -> x*exp(cos(y)*z)
∇f  = (x,y,z) -> Point3f0(exp(cos(y)*z), -sin(y)*z*x*exp(cos(y)*z), x*cos(y)*exp(cos(y)*z))
∇ˢf = (x,y,z) -> ∇f(x,y,z) - Point3f0(x,y,z)*dot(Point3f0(x,y,z), ∇f(x,y,z))

θ = [0;(0.5:n-0.5)/n;1]
φ = [(0:2n-2)*2/(2n-1);2]
x = [cospi(φ)*sinpi(θ) for θ in θ, φ in φ]
y = [sinpi(φ)*sinpi(θ) for θ in θ, φ in φ]
z = [cospi(θ) for θ in θ, φ in φ]

pts = vec(Point3f0.(x, y, z))
∇ˢF = vec(∇ˢf.(x, y, z)) .* 0.1f0
scene = surface(x, y, z)
arrows!(
    pts, ∇ˢF,
    arrowsize = 0.03, linecolor = (:white, 0.6), linewidth = 3
)
save("sp.png",scene)
```
となります。
図は、

![sp.png](https://qiita-image-store.s3.amazonaws.com/0/246113/bb78b89e-68ed-972b-1896-c14e630da14b.png)
となります。

##棒グラフ
棒グラフは

```julia
using Makie
using FileIO

scene = barplot(rand(10), color = rand(10))
save("bar.png",scene)
```

とすればよくて、
![bar.png](https://qiita-image-store.s3.amazonaws.com/0/246113/3943b8bd-1ef6-1daf-28c1-613fd69eef87.png)
が得られます。

##その他
そのほかにも様々なグラフが
http://makie.juliaplots.org/stable/functions-overview.html
にあります。


# グラフの例
ここからは、自分で作ってみたものをお見せします。

##等値面一つだけ
等値面のうち、一つだけプロットしたい時は、

```julia
using Makie
using FileIO

using LinearAlgebra

function test(x, y, z)
    return cos(x)+cos(y)+cos(z)
end
x = range(-π, stop = π, length = 100)
scene = Scene()
contour!(scene, x, x, x, test, levels = [0], alpha = 0.3)
save("tb.png",scene)
```
とします。ここで、```levels=[0]```は値が0の等値面を描く、ということになっています。
得られた図は

![tb.png](https://qiita-image-store.s3.amazonaws.com/0/246113/b7d6f4cc-8232-5567-7be5-23af07bc2b4e.png)
です。

## 濃度分布
3D中の濃度分布をプロットしてみます。
コードは

```julia

using Makie
using FileIO
N=32
x = range(-10, stop = 10, length = 100)
function vor(x,y,z)
    shift = cos(z)  
    shift2 = sin(z) 
    r = sqrt((x-shift)^2+(y-shift2)^2)  
    return 1-tanh(r)    
end
v2 = volume(x,x,x,vor, algorithm = :mip)
save("vortex.png", v2)
```
です。
これを実行すると、

![vortex.png](https://qiita-image-store.s3.amazonaws.com/0/246113/758760ab-283d-aaa9-913c-ef379b63e44a.png)
とグルグルしたものが可視化されます。