先日、ある方と「BashからMatlabを呼び出せないだろうか」という話をしていました。もし、これができたら、シェルスクリプトから、Matlabを呼び出せるので、シェルとMatlabを完全に連携できるわけです。
結論としては、以下でできました。
- Short answer
Matlabのスクリプト名を sample_code.m とすると、以下でできます。
$ matlab -nodesktop -nosplash -r 'sample_code; exit'
コツは2つです。
- スクリプト名ではなく、コマンドとして指示するため、.mは外す
- Matlabから抜けるために exit を追加する
まず、Matlabに様々なオプションがありますが、それについて知りたいと思いました。
ふと、matlabというコマンドはシェルスクリプトではないのか?と思い、ファイルの中身を見てみたら、案の定、シェルスクリプトでした。その中に説明がありました。以下で見られます。
$ matlab -h Usage: matlab [-h|-help] | [-n | -e] [v=variant] [-c licensefile] [-display Xdisplay | -nodisplay] [--noFigureWindows] [-nosplash] [-debug] [-softwareopengl | -nosoftwareopengl] [-desktop | -nodesktop | -nojvm] [-r MATLAB_command] [-logfile log] [-singleCompThread] [-jdb [port]] [-Ddebugger [options]] [-nouserjavapath]
シェルからMatlabのスクリプトを実行するには、以下を行いたいと思います。
- Matlabの起動画面を抑制する
- コマンドをそのまま走らせる
- できるだけ、ターミナル上で完結させる。といっても、SPMなどのバッチも走らせることを考えて、グラフィックを出すこともできるようにする
以下、試行錯誤の結果です。
- サンプルコードの準備
今、簡単なコードとして、y=sin(x)のグラフを描いて、png形式で保存するというものを準備します。これだと、グラフィックを使いますので確認にいいと思いました。
x=[0:0.01:10]; y=sin(x); plot(x,y); saveas(gcf,'sin.png')
これはヘルプを見たら簡単にわかりました。
$ matlab -nosplash
これで起動画面を抑制できました。
これもあっさりわかりました。
$ matlab -r MATLAB_command
で走らせることができます。早速、
$ matlab -nosplash -r sample_code.m
としたところ、Matlabは無事に起動したのですが、
変数 "sample_code" またはクラス "sample_code.m" は未定義です。
とエラーになりました。
理由を考えてみて、ふと思いました。
MATLAB_command ということは、.mをとったらいいのではないか?
sample_code.m はスクリプトファイルですが、
sample_code はコマンドになるわけですから…。
もう一度やってみます。
$ matlab -nosplash -r sample_code
そうしたところ、無事にスクリプトが走り、そしてsin.pngが保存されました。本質的ではありませんが、一応、保存されたpngファイルを示します。
ただ、これだとMatlabが終わりません。
終わりたいと思いましたので、exitもつけてみました。引数としてまとめるためにシングルくオーテーションでくくります。
$ matlab -nosplash -r 'sample_code; exit'
そうすると、期待通りにMatlabが走り、スクリプトが実行された後、終了し、シェルに戻りました。
これまでの流れで、実質やりたいことは達成できたのですが、Matlabが端末上で走った方がかっこいいので、最後にそこをやります。
Matlabのヘルプを見ると、以下の3つのオプションが気になりました。
-nodisplay Do not display any X commands. The MATLAB desktop will not be started. However, unless -nojvm is also provided the Java virtual machine will be started. -nodesktop Do not start the MATLAB desktop. Use the current terminal for commands. The Java virtual machine will be started. -nojvm Shut off all Java support by not starting the Java virtual machine. In particular the MATLAB desktop will not be started.
-nodisplay と -nodesktop という似たようなオプションがあり、それはどっちも -nojvm が関係しているようです。
まず、 -nojvm を入れてみます。
$ matlab -nosplash -nojvm -r 'sample_code; exit'
そうすると、以下のエラーとなりました。
エラー: plot この機能は -nojvm 起動オプションでサポートされなくなりました。 詳細は、『MATLAB リリース ノート』の "Changes to -nojvm Startup option" を参照してください。ご利用のシステムのブラウザーにリリース ノートを表示するには、web('http://www.mathworks.com/help/matlab/ release-notes.html#btsurqv-6','-browser') を実行してください。 エラー: sample_code (line 3) plot(x,y);
どうも -nojvm を設定すると、グラフィックを表示できないようです。
なので、これは設定しないことにします。
次に -nodisplayを試してみます。
$ matlab -nosplash -nodisplay -r 'sample_code; exit'
そうすると、今回はエラーは起こりませんでしたが、グラフィックも表示されずに終了となりました。ただ、確認すると、sin.pngは生成されています。
これから、 -nodisplay は、「グラフィックは有効ではあるけれども、画面には表示しない」オプションということがわかりました。
最後に、 -nodesktop を試してみます。
$ matlab -nosplash -nodesktop -r 'sample_code; exit'
そうすると、期待通りに、グラフィックも表示され、その後、exitコマンドも打っていますので、自動で終了し、シェルに戻ってきました。
これから、 -nodesktop は、「Matlabデスクトップアプリを起動しないが、(Java Virtual Machineは動作しているので、)グラフィックなどは適宜呼び出すことができるオプション」と言えるかと思います。
ということで、matlab の後に、引数として
-nosplash -nodesktop -r ‘スクリプト; exit’
でシェルからMatlabのスクリプトを実行できることが確認できました。
bash からmファイルを呼び出せれば、今までその場しのぎでMatlab で書き捨てていた処理(いわゆるad hoc処理)も含めて解析パイプラインに取り込めそうです。
それに臨床データをcsvファイルなどで定型のテキストファイルをMatlabに取り込むことでデザインマトリクスやデザインコントラスの生成もパイプライン化できそうです。
さらにbash だけでは実現が難しかった数学的処理、統計的処理結果を分岐条件に使った柔軟な解析パイプラインを構築できそうです。
いつも有用な情報をありがとうございます。
下地先生
コメントどうもありがとうございます。
先生とのディスカッションがあるおかげですので、私も感謝しています。
今後ともどうぞよろしくお願いいたします。