ファイルを保存するたびに plot を反映させる Julia Tips

3 min read読了の目安(約2700字

本日は

Julia のグラフ描画にてよく使われる Plots.jl を触ることが多いと思います.その練習の過程で

yourfile.jl
using Plots
function main()
    plot(... # ここを試行錯誤する)
end

というコードを書いて

REPL
julia> include("yourfile.jl")
julia> main()

を手動で何回も呼び出すことがあると思います.include したり main() を呼び出したりと...ちょっとめんどくさいですね.

Revise.jl を使うと includet("yourfile.jl") のようにして includet (t がついていることに注意)を用いると yourfile.jl を更新した際にそのファイルの中で定義した関数定義や変数の値が反映されるようになります.

REPL
# REPL の上で
julia> using Revise
julia> includet("yourfile.jl") # dosomething 関数の定義が記述されているとする
julia> dosomething() # うーん何出力がおかしい
julia> edit("yourfile.jl") # ファイルを編集
julia> dosomething() # ちょっとマシになった
julia> edit("yourfile.jl") # もう一度編集
julia> dosomething() # お?いい感じになったかも
... # この作業を繰り返す

これでもいいのですが dosomething() を呼び出す手間がまだあります.

  • 幸い Pluto.jl はコードのある部分が変更されればその変更箇所に伴って値が変わって欲しいセルを更新する機能があってその上で練習することもできます.
  • 一方で使い慣れているエディタを使ってファイルを編集したい人もいるでしょう.今回はそういう場合の需要に応えたTipsを紹介します.

FileWathing を使う

Remark.jl という Literate.jl + Remark.js を組み合わせるマークダウンからスライド作成するパッケージからヒントを得ました.

https://github.com/piever/Remark.jl/blob/master/examples/markdown/make.jl

監視ファイルの作成

FileWatching.watch_file("yourfile.jl") とすることで yourfile.jl が編集されたかを監視することができます.

watcher.jl という対象とするファイルを監視するスクリプトを作ります.

watcher.jl
# watching
using FileWatching

while true
    @info "Rebuilt"
    include("yourfile.jl")
    try 
        display(main()) 
    catch 
        @warn "Something went wrong"
    end
    FileWatching.watch_file("yourfile.jl")
end
  • ここで display(main())yourfile.jl で定義されている main 関数の戻り値を display させたい意図があります.

試行錯誤するためのファイルを作成

  • 皆さんが試行錯誤するファイルが yourfile.jl だとします.そしてその中に main という関数があって main は,例えば,下記のソースコードのように Plots.jl で作られたオブジェクトを返すことにしましょう.
yourfile.jl
using Plots

function main()
    plot(tan) # この部分をいっぱい編集したい
end

最初は三角関数の \tan\theta を描画させてますが \sin\theta, \cos\theta のような他の関数も描画したいわけです.

やってみましょう

作業する手順は下記の通りです. まずはターミナルを開いて

$ julia watching.jl

とします. [ Info: Rebuilt というメッセージが出たらひとまずOKです.

tan 関数のグラフが出てきます.
そして今度は yourfile.jl の中身を plot(tan) から plot(sin) としてみましょう. 保存すると watching.jl のなかで FileWatching.watch_file("app.jl") の行で停止していたロジックがもう一回りして display(main()) を実行します. 実行するともちろん sin の関数が描画されると期待できます.実際に下記のように結果が更新されます.

ちなみに plot(cos, sin, 0, 2pi, aspect_ratio=:equal) とすると 0 から 2\pi までの範囲で動くパラメータ t に対する x=cos(t), y=sin(t) の軌跡,つまり,円周が描画されます.

これでファイルを編集するだけでそれに対応する変更を自動的に反映できるようになりました.