GNUPlotを使ってリアルタイムでグラフを描いてみよう
実行ファイルを作成し,シミュレーションなどの数値をテキストファイルに書き込み,Excelで読み込んでグラフを
描くことはできる.しかし,例えば,パラメータの数値を変化させて違いを知りたいときは,これらの一連の作業が
煩わしいと感じるため,シミュレーションの結果を見ながらパラメータを調整する場合,現在の状態を含めて,でき
ればリアルタイムにグラフィカルに確認できる手段が欲しくなる.
古のシステムであれば,簡単なコマンドをソースファイルに記述して,画面に直接グラフを描くこともでき,シミュ
レーションの過程や結果を簡単に確認することもできたが,今はそこまで簡単でもなくなっている.
本日扱うテクニックは,皆さんが卒業論文などでシミュレーション,データ解析を行う上でも利用できる実用的なもの
なので,ぜひマスターしよう.
実験した直後にすぐ解析,条件を変えてシミュレーションをすることで,より多くの知見を得ることができるはずである.
グラフィックについて
画面のある座標から別の座標まで線分を引くことを考えてみよう.
現状のシステムは,Windowsであれ,Mac(Linux)であれ,デスクトップに直に線分を描くことはせず,あるウィンドウが
立ち上がって,そのウインドウの枠内の座標に対して線分を描いている.
ウィンドウをマウスで動かせば,ウィンドウ内の線分も同様に動くことが確認できる.
コーディングして線分を描くように記述をして作った実行ファイルがグラフィックボードを直接コントロールして線分を
描いているのではないことを知っておいて欲しい.
では,実際には何をしているかと言うと,実行ファイルはOSに働き掛け,OS内のライブラリを呼び出してCPUからバスを
介し,グラフィックボード内のGPUに働きかけて描画を行っているのである.
実行ファイルとOSの間にAPI(Application Programming
Interface)の関係があって,実行ファイルはアーキテクチャ内の
動作をコントロールしなくても,OSにコマンドを送るだけで動作する.
先の動作については,ある大きさのウインドウを開く,ウィンドウ内の座標において線を描画する,というタスクが実行
されていると考えればよい.
従って,C/C++言語そのものにグラフィックを描く機能は備わっていないこと※を留意しておこう.
※C/C++言語は,OSそのものを作ることもできることからAPIを作ることもでき,あるいはAPIをまとめたミドルウェア
(プログラム間の通信など司る)を作ることもでき,ハードウェアを動作させるドライバを作ることもできるので,厳密
にはC/C++言語にグラフィックを描くことができないというのは間違いであるが,説明の関係上,上記のように記した.
すなわち,コーデイング上は,APIを呼び出すためのコマンドとなる記述をしていることとなる.
従って,このコマンドを示す関数を持ったヘッダファイルやライブラリを適宜インクルード,リンクすればグラフィックを
使うことができるのである.初めに説明した古のシステムであれば,関数1行で描けたものが今は簡単でなくなったと考え
ればよい.
しかも,このヘッダファイルやライブラリが難物で,OS,開発環境(プログラミング言語を扱うソフトウェア群),OpenGL
(グラフィックライブラリ)などのバージョンなどによる仕様変化により,意図しない描画になるような不具合も発生する
のである.
そこで,グラフィックを扱うための手法についていくつか紹介しよう.
アイディア1:描画に長けたソフトウェアを利用する
そこで,確実にグラフィックを扱うには,確実に描画できるソフトウェアにデータを送るということを考えればよく,これ
までの授業で扱ったのは,テキストファイルに書き出し,手動でExcelに読み込みグラフを描いていたが,これを自動化する
ものである.
GNUPlotというソフトウェアがあり,これにデータを送り込むのも一策であるが,将来的にこれが無くなる,容易に使えな
なる可能性もないわけではなく,また,仕様が変わる可能性もある.また,大変美しい描画をするため,若干時間がかかる
のも手軽な運用にはやや向かないとも言われている.(簡単なグラフなら全く問題ない)
http://www.gnuplot.info/
商用ソフトウェアにMATLAB,よく似た無料のscilabがあり,MATLABとscilabには違いがあるため,これらの差を埋め合わせる
MAT@scilabというツールもある.
https://jp.mathworks.com/products/matlab.html
https://www.scilab.org/
https://www.vector.co.jp/download/file/data/edu/fh691392.html
これらに対して,自作のプログラムのデータを送り込む方法もある.授業では扱わないが関心のある学生はぜひ試してほしい.
(GNUPlotは扱う.)
Excelで生成されるグラフは,そのままでは科学技術に関する資料にすることは難しく,かなり体裁を整えなければならない
ので,Excelで数値データをまとめ,上記に挙げたようなソフトウェアに読み込ませるのも有効であると考えられる.
アイディア2:描画に長けた言語のライブラリを使う
本授業の3回目でpythonを利用した.現在pythonは裾野の広いユーザに支えられ,多くのライブラリが実装できる.その中に,
グラフの描画に適したライブラリmatplotlibがあり,これを利用する.(さらに綺麗にしたければseabornというライブラリも
あるので試してみよう.)
アイディア1と異なるのは,C/C++の開発環境でコーディングを行うが,コンパイルの際,pythonのインタープリターを呼び
出して描画する機能を組み込む点である.
さらに加えると,pythonのコマンドを呼び出すためのヘッダ,ライブラリを自作するか,ネットで流通しているもので著作権の
問題のないもの※を利用するかを考える必要がある.
※ソフトウェア開発の世界ではオープンであることを良しとする文化もある.プログラマ相互が技術を享受し提供する関係である.
しかしながら,著作権について細かく見ていくと,著作権を主張しない,自由に使ってよいが著作権は放棄しない,改変しないで
欲しい,個人利用のみ自由,費用は発生しないが一報して欲しい,費用が発生する(初期費用のみ,期間あり)など様々なものが
ある.readme.txt(昔はreadme.docもあったが初期のwordが拡張子を被せてしまった)などをよく読んで利用するのが作法である.
アイディア3:正攻法
C/C++で描画のためのヘッダやライブラリを作るというのももちろん有効である.敷居は高いが一旦作ればしばらく使うことが
できる.あるいは開発環境として,Visual Studio(C/C++/C#)やC/C++
Builderを用い,例えばWindows用のAPIや.NET
Framework
(CLI:共通言語基盤)などOSに依存するライブラリを内蔵しているものを用いることもできるが,有償である.
およそ14万円,17万円であり,個人で使うには少々覚悟が必要なものでもある.もちろんOSのマイナーバージョンが上がれば,
これに関するライブラリを使えるようなサポートがあるため,商用ソフトウェアの開発には必須のツールでもある.
しかしながら,ごく最近は,商用利用をしない,作成したソフトウェアn配布法に気を付ければ無料のものが続々と使えるように
なってきている.
12/10実施の手順
本授業では簡単なアイディア1に則って,進めていく.
今までは,FILEポインタを利用して,テキストファイルを開き,fprintf()関数で数値とカンマやタブ,改行で計算した解をテキ
ストファイルに書き込み,CSVやTSVファイルを作り,エクセルに書き込んでいた.
エクセルのグラフは,何も設定しないと科学技術の分野のグラフとしては大味であり,また,必要な情報も伝えきれない.かなり
手を入れないと[らしい]グラフにはならないことを是非知っておいて欲しい.そこで,グラフを簡単に作ってみることにする.
パイプについて
GNUPlotはコマンドラインで操作するタイプのソフトウェアである.ということは,コマンドラインとは文字列であるから,コマ
ンドライン上に文字列を出力すれば,コマンドライン上で動作するソフトウェアを起動できるのである.
ここでメイン関数と関数の関係を考える.メイン関数から関数名を呼び出し,引数を介して関数に変数を送り,その値を関数内で
処理し,returnを記述すれば,その値を結果として関数から取得することができる.
この関係が,コマンドラインと作成した実行ファイルの間にも成り立っている.これまでは,コマンドラインで,実行ファイル名を
打ち込むことで作成した実行ファイルが動作するというものであった.
これに対し,実行ファイル名の後に,先の関数の引数と同様に引数を置けば,実行ファイルに数値や文字列を送り込むことが可能
である.同様に,メイン関数内にpopenという関数を記述すれば,コマンドラインに文字列を送り込むことができるので,コマンド
ラインで起動できるソフトウェアを動亜させることが可能である.このようなテクニックをパイプと呼んでいる.
1.GNUPlotを用意する.
以下のサイトから,自身のPCの環境(Win?,Mac?,Ver?)に合わせたものを探してダウンロードする.必ずしも最新を探す必要な無く,
安定版,Stable,Bugfixedなどのキーワードで探せばよい.エンドユーザーとして利用するのであれば,テスト版,α版,β版を
選ぶ必要は無く,むしろ何らかの不具合があると思っておくべきである.
http://www.gnuplot.info/
ダウンロードしたらインストールしましょう.GNUPlotは特段操作をしなくても自動的にインストールできるはずである.
Macの場合は幾分手続きが変わるので注意が必要.
A, ターミナルを開いておきましょう.(コマンドラインを打ち込むため)
B. パッケージマネージャHomebrewなどをインストールする.
https://brew.sh/index_ja
無くてもよい場合もあるが,不具合が出にくいようである.指示通りでインストールできる.
C.GNUPlotを用意する.
以下のサイトから,自身のPCの環境(Win?,Mac?,Ver?)に合わせたものを探してダウンロードする.
http://www.gnuplot.info/
D. パッケージマネージャ越しにインストールする.
ターミナルなどから,
brew install gnuplot
のようにタイプしてインストールする.パッケージマネージャがほどよく環境設定をしてくれるはずである.
以上で準備ができた.
C言語でプログラム開発
パイプを使うための設定,コマンドをはじめに説明する.
宣言
#include <stdio.h> | /*標準入出力のためのヘッダ*/ |
考慮すべきはほぼ上記のことのみである.fprintf関数にコマンドラインに書くべき文字列を配置する.もちろん変数の値を置く
こともでき,以下のようにすれば,順次プロットすることが可能である.
Main関数
FILE *gp; | /*コマンドラインとアクセスするためのファイルポインタ*/ |
gp = popen("gnuplot", "w"); | /*パイプを用いてコマンドラインにGNUPlot起動のコマンドを送る.パイプによりコマンドラインとのやりとりの道が開いた状態にしている.*/ |
fprintf(gp, "plot '-' with linespoints\n"); | /* GNUPlot起動後のコマンドを逐次記述する*/ |
pclose(gp); | /*パイプのためのポインタを閉じる*/ |
考慮すべきはほぼ上記のことのみである.fprintf関数にコマンドラインに書くべき文字列を配置する.もちろん変数の値を置く
こともでき,以下のようにすれば,順次プロットすることが可能である.
fprintf(gp, "%f %f\n", 変数, 変数); |
練習課題
プログラムからGnuplotを呼び出して正弦波を描く
#include <math.h> #include <stdio.h> int main(void){ FILE *gp; |
特段難しいことはやっていないので,ひとまず試そう.
同じ要領で,課題を取り組めばグラフを作成することができる.
なお,各軸の範囲の指定をすることも可能である.省略可であるが,グラフの形式が気になるのであれば試してもよい.
GNUPlotは横軸がX軸,縦軸がY軸と決まっている.
fprintf(gp, "set xrange [0:10]\n");
fprintf(gp, "set yrange [0:1]\n"); |
[0:1]内を適宜調整してみて欲しい.もちろん負の値も設定できる.