このページではPGPLOTの利用に関するちょっとした情報を集めています。
Tcl/Tk関係のリンクを整理 (2000/8/25)
HTMLの書きまちがいを修正(< → < など) (2000/8/28)
私の所属する流体研内では、 PGPLOTを利用してグラフを描くツールを多用しています。PGPLOTはFORTRANおよびCから呼び出せる、デバイスに依存しないグラフィックス・パッケージで、特に2次元のグラフや図形、等値線図(コンター)を描く機能に優れています。出力として、X Window System, Tektronix端末, (Encupsulated) PostScript, Canon LaserShot, Compuserve GIF, HPGLなど、多くのデバイス/フォーマットに対応しているのも嬉しい。当研究室では、数値計算プログラムに組み込んでの簡単な可視化や実時間アニメーションなどに使われています。
このページではUNIX上でPGPLOTを使うことを前提とします。しかしPGPLOT自体はVMS、Windows95、WindowsNTでも利用できるそうです。
PGPLOTサブルーチン解説
PGPLOT Subroutine Descriptionsの日本語訳です。濱田 孝治 先生(九州大・総理工)と当研究室の松沢、私の3人で翻訳をぼちぼち進めています。
ミジンコでもわかるPGPLOT
私と同じ研究室所属の松沢君による、PGPLOTの使い方の解説です。等値線図
(コンター)の書き方は松沢君のページで特集される予定です(まだ無い :-)
あなたはだいたい 人目のお客様です。(1997年10月1日以降)
PGPLOTはライブラリの名称ですので、これを利用するにはプログラムから呼び出すことになるのですが、まずその前に、PGPLOTを利用したプログラムの、ツールとしての使い方の一般論を説明します。自分でプログラムを作る方法ではなく、既成のプログラムを利用したいときに必要となる事柄です。プログラムの書き方は次節以降をごらん下さい。
PGPLOT_DIRという環境変数に、PGPLOTをインストールしたディレクトリを設定して下さい。これは必須です。
次に、PGPLOT_DEVという環境変数にふだん利用するデバイスタイプを設定しておくと便利です。X Window Systemでグラフを表示させる場合は以下のように設定します。
プログラムによってはこの環境変数を設定しないと動作しないものもあります。この環境変数を利用するかどうかは、そのプログラムの構成に依存します。
PGPLOTが扱える出力先は多岐に渡ります。出力先の指定には、環境変数 PGPLOT_DEVで指定する方法、プロンプト
Graphics device/type (? to see list, default /NULL):
が表示されたときにキーボードから入力する方法、プログラムの中で指定する方法などがあります。(指定方法はプログラムによって異なります。)
代表的な出力先の指定方法は以下の通りです。なお、プロンプトに対して"?" を入力すると利用できるデバイス一覧が表示されます。
/psまたは/vpsを指定して作成したPostScriptファイルはEPSファイルになっているので、EPSファイルを取り込めるソフトウェア、たとえばLaTeXなどの文書中にそのまま取り込むことも出来ます。
注意: この節では流体研内で使われているプログラムの使い方を説明しています。ですから研究室外の方には役に立たないと思います。
流体研内でCpやキャビティ厚みを表示・印刷するために使われている UNIXプログラムは、もともとあったSunView(SunCORE)プログラムを金野が PGPLOTに移植・改造したものです。利用方法は全て共通です。
プログラム名 [ [デバイス名]/デバイスタイプ ]
Graphics device/type (? to see list, default /NULL):と質問されますので、デバイス名とデバイスタイプを入力して下さい。 たとえばX Window System上でグラフを見たい場合には/xwinと入力し ます。
Graphics device/type (? to see list, default /xwin):と質問されます。ここでただリターンを入力するとX Window System上 にグラフを表示できます。もちろん異なるデバイスを指定することも 出来ます。
プログラム名 filename.ps/vps
といった具合です。この場合はプロンプトは表示されません。 デバイス名、デバイスタイプの指定法は前の節で簡単に説明してあり ます。
流体研でよく用いられている計算プログラムがデータファイルの名前を固定しており、現在の表示プログラムはそのファイルを読んでグラフを作ります。そのために最後に計算した結果を表示することになります。 これを改造して任意のデータを表示するよう変更するのは簡単ですが、特に要望が無いようなので過去のプログラムの仕様をそのまま踏襲しています。
PGPLOTを利用したプログラムを書くのは、難しくありません。この節では私が実際に作ったプログラムの一部を引きながら、プログラムの骨組みを説明しますので参考にして下さい。それなりにきっちりしたプログラムになっていると思います。
前節で述べた、私が作って研究室内で利用されているプログラムは、もともと SunView(SunCORE)用のプログラムを移植したもので、Cで書かれています。私にとってもCの方が書きやすいという事情もあります。そのため、以下の説明ではCで書かれたプログラムを引用しています。 FORTRANで書く場合と、本質的な違いはありません。
英語に抵抗が無ければ、グラフの描き方についてもっとも参考になるのは、 PGPLOTの本家のページ内にある"Examples"です。どうぞご参照下さい。 (以下のリンクをたどって下さい。)
PGPLOT Examples
PGPLOT Graphics Subroutine Library(PGPLOTの総本山)内
このほかに、PGPLOTソースコードについて来るデモプログラム(FORTRANで書いてある)は参考になります。PGPLOTをインストールしてあるディレクトリに入っていると思いますので、見てみましょう。
PGPLOTを利用できる言語は、例えば次のようなものがあります。より詳しい情報はPGPLOT本家のページ から得られます。
以下の例では、主にC言語を使って説明していますが、これは私がCでプログラムを書いていたから、という理由です。PGPLOT自体は、もともとFORTRANのサブルーチン群です。最近は、Perlのほうが保守が簡単なのでPerlに移行しつつあります。
もっとも簡単な、一つの画面に一つの絵(図、グラフ)を描くようなプログラムをPGPLOTを用いて作る場合、プログラムの流れは以下の通り。
PGOPEN、PGCLOSはPGPLOT Ver.5.1以降で追加されたサブルーチンです。それ以前のPGPLOTでは PGBEG、 PGENDを利用します。
実際に私が使っているプログラムのメインルーチンを以下に示します。
main(int argc, char *argv[]) { char *devname = "?"; if (argc == 2) devname = argv[1]; init(); read_data(); ← データファイルを読む if(cpgopen(devname) != 1) exit(1); cpgenv(xmin, xmax, ymin, ymax, 1, -2); plot_graph(); ← グラフを描いている print_notations(); cpgclos(); return 0; }
プログラムの骨組みは簡単なので、理解していただけると思います。このプログラムではPGOPENの引数に、プログラムの引数をそのまま渡しています。プログラムの引数が無い場合には、"?"を渡しています。PGOPENが"?"を渡された場合は、
Graphics device/type (? to see list, default /NULL):
というプロンプトを出してデバイス名とデバイスタイプの入力を促します。
上記のように下準備をきちんとしてあれば、グラフを描くのは簡単です。ここではデータ列が配列x, yに入っており、データの数が N個あるとしましょう。曲線(折れ線)を描く場合と点(ドット、マーク)を打つ場合とに分けて説明します。
どちらの例でも、一つのデータ列に対してはサブルーチンを一度呼ぶだけでよく、ループを回す必要はないのでご注意下さい。データ列が3つあるとき、端的には線を3本描くときには、PGLINEを3回呼びます。
必要なら、はじめにグラフにラベルをつけます。 PGLABを使います。
PGPTで点を打ちます。
PGPT(NW, x, y, MARKTYPE)
線や点(マーク)の種類は、ここで説明するよりもPGPLOTのデモプログラム "pgdemo2"を実行するのがいちばん分かりやすい。2ページ目にマークの種類が、 4ページ目に線の太さを変えた例があります。
pgdemo2をはじめPGPLOTのデモプログラムは、PGPLOTをインストールしてあるディレクトリに入っているはずです。
地図の等高線や天気図の等圧線のように、同じ値を持つ場所を線で結んで表現した図を等値線図(コンター図、コンターマップ)と呼びます。"等高線"と呼ぶ人もいます。
私は等値線図を作った経験が数える程しか無いので、同じ研究室所属の 松沢君のページを紹介します。彼は等値線図をたくさん書く必要のある研究をしています。
ミジンコでもわかるPGPLOT
私と同じ研究室所属の松沢君による、PGPLOTの使い方の解説です。等値線図
(コンター)の書き方は松沢君のページで特集される予定です(まだ無い :-)
そうなんです、彼のページでもまだ等値線図の書き方は完成していないんです。彼にメールでも出してプレッシャーをかけてやって下さい :-)
PGPLOTでは一つの画面には一つの絵(図、グラフ)を入れるのが基本ですが、ちょっと手を入れれば複数の絵を入れることも出来ます。方法は2つ、
があります。
ここではより柔軟な、バッチ処理を利用する方法を説明します。その場合のプログラムの流れは以下のようになります。
以下は私の所属する研究室で使われている、一つの画面に、翼型とCp(圧力係数)の2つのグラフを表示するプログラムのメインルーチンです。
main(int argc, char *argv[]) { char *devname = "?"; progname = argv[0]; if (argc == 2) devname = argv[1]; read_data(); ← データファイルを読む if(cpgopen(devname) != 1) exit(1); cpgbbuf(); cpgsave(); cpgsvp(0.1, 0.9, 0.1, 0.3); plot_foil(-0.125, 0.125); ← 翼型を表示する cpgsvp(0.1, 0.9, 0.35, 0.95); plot_Cp(); ← Cp曲線を表示する cpgunsa(); cpgebuf(); cpgclos(); return 0; }
グラフの定義域、値域はサブルーチンの中で設定しています。
PGPLOTは、グラフ作成の汎用ツールとして使うのには向かないと思います。汎用のツールがほしいなら、たとえば Gnuplot などがあります。これを使うほうが、PGPLOTでいちいちグラフ作成プログラムを作るよりもずっと簡単に、そしてきれいなグラフが得られます。
PGPLOTは、次のような場合に向いていると私は考えています。
上にも述べましたが、私が作って研究室内で利用されているプログラムは、もともとSunView(SunCORE)用のプログラムを移植したものです。移植に際しては、はじめにSunCOREの基礎ルーチン(move_abs_2、line_rel_2など)をPGPLOTのサブルーチンで置き換える"エミュレーション・ライブラリ"を作成し、これを利用していました。現在のプログラムはだんだんPGPLOTのサブルーチンを直接呼び出すように改造しつつありますが、まだエミュレーションライブラリを使っているプログラムもあります。
今どきSunCOREプログラムを使っている方は少ないでしょうから、SunCOREのエミュレーションに興味のある方はほとんどいないだろうと思いますので、このページでは紹介にとどめ、内容については説明しません。興味がおありの方は金野(minnie)にメールを下さい。(…と書いてからしばらく経ちますが、一度もメールを貰ったことはありません。やっぱりSunCOREなんてもう使われていないんだねぇ…。)
グラフを作ったり、簡単なお絵書きをするには、当研究室ではPGPLOTを使う人が多いのですが、実は私は、仕事の内容によってはTcl/Tk を使ってちょっとしたツールを作って使っています。このページの本題からはちょっとずれますが、Tcl/Tkの紹介をしましょう。
なお2000年8月25日の時点での最新版はTcl/Tk 8.3.2です。
TclはTool command languageの略で、簡単で強力なスクリプト言語です。言語には多少の癖があります。Tclの作者は、Tclをライブラリとして使い、アプリケーションにTclインタプリタを組み込んで使う「組み込み言語」としての利用を期待したようですが、実際にはTclはそれだけで非常に強力なプログラミング言語なので、Tclインタプリタがそのまま使われる場合の方が多いようです。私もそのような使い方をしています。
TkはToolkitの意で、グラフィック・ユーザーインターフェイス(GUI)を構成するための道具です。X11用がオリジナルですが、現在ではWindowsやMacintosh でも利用できます。ボタン、メニュー、ダイアログなど、GUIを持つプログラムを書くために必要な道具を網羅しています。
PGPLOTとくらべて、Tcl/Tkは"GUI"と"イベント処理"に優れています。GUIについては、おそらく説明は不要と思いますので、イベント処理について簡単に説明します。
イベント処理の"イベント"とは、端的にはマウスのクリックとか、キーボードを叩いたなどの"出来事"のことです。多くのイベントは、利用者の何らかの作業に対応して発生します。"処理"とはあるイベントが発生したとき、たとえば利用者がボタンをクリックしたときに、何をするか、ということです。具体的には、Tcl/Tkのコマンド列や手続きです。
Tcl/Tkには、この"イベント"と"処理"とを簡単に結びつける機構 bindがあります。bindでは、
を指定します。具体例を見てみましょう。
bind .canvas <2> "undo .canvas" bind .canvas <B1-Motion> "move_baseline .canvas %x %y" bind . <Alt-F4> exit;
はじめの例では、.canvasというGUI部品の上でマウスボタン2を押すと、
undo
という手続きを呼ぶべし、という指示です。
2行目は、同じく.canvasというGUI部品の上で、マウスボタン1を押したまま移動すると(つまりドラッグ)、move_baseline
という手続きを呼ぶべし、という指示です。引数にマウスカーソルの位置を含んでいます。
3行目は、そのプログラムのメインウィンドウ("."で表す)がアクティブな状態で、Altキーを押しながらF4キーを押すと、プログラムを終了する、という意味です。
PGPLOTはグラフィックスライブラリで、線を引いたり色を塗ったり、グラフの作成には優れています。しかしGUIとイベント処理は、得意とはいえません。付け足し程度の機能が実装されているだけです。ですから対話的な利用には、あまり向いていないのです。これに対してTcl/Tkは、GUIとイベント処理に強いので、対話的なプログラムの作成に向いています。もともと目指すものが違うのですから、これらの違いは当然だといえます。
画像を表示しておいてその中のある部分の長さや面積を計測したいときに、 Tcl/Tkで作ったツールを使っています。(これを画像解析というのはちょっと無理があるか ^^;;)
我々は高速で目視では観測しにくい現象をよく扱うので、実験データを処理する上で、写真やビデオの画像を元に、長さや面積を測る、という作業を頻繁に行ないます。写真やテレビモニターにものさしを当てて(!)長さを測る、ということを本当にやるんです。これではあまりに原始的ですから、ワークステーションのディスプレイに画像を表示しておいて、マウスカーソルを使って計測したい線分や領域を指定できると便利です。そこで昨年末から、研究室の友人に頼まれて、画像ファイルを表示して、その中のある線分の長さを測ったり、ある領域の面積を計測したりするツールをTcl/Tkを用いて開発し、利用しています。このような対話的なプログラムの作成には、PGPLOTよりもTcl/Tkの方が簡単で強力です。「計測がずっと楽になった」と好評です。
対象となる画像は、もともと画像ファイルとして記録されるもの(たとえば高速度デジタルビデオカメラの画像)はもちろんですが、写真ならスキャナで読んで、ビデオならビデオキャプチャで読んでデジタル画像に直して扱います。結局その方が早いのです。なお、利用できる画像ファイルフォーマットは GIFとPPM/PGMで、主にGIFファイルを使っています。(See photo(n))
当研究室は流体関係の研究を行なうところで、数値計算やデータ処理のためのソフトウェアを作ることはあっても、高級なユーザーインターフェイスを必要とするようなアプリケーションを作ることはありません。Tclは必要十分な機能を持つスクリプト言語ですし、Tkは有用で高機能なツールキットですが、我々は数ある機能のうち、ごくごく一部を利用しているに過ぎません。
英語で言ったらImplementationにあたるのかな。
上で述べたツールは、ある特定の目的にのみ使うように作られたもので、汎用のものではないので、ここで紹介することはしません。実現方法は簡単で、
set fname [tk_getOpenFile -filetypes $types] if {$fname == ""} { return } # load an appropriate image image create photo orig_image -format gif -file $fname
$canvas configure -height [image height orig_image] @BACKSLASH@ -width [image width orig_image] $canvas create image 0 0 -image orig_image -anchor nw
という具合です。
上で述べた画像の表示に加えて、翼型の表示、領域の指定、台形積分や結果のファイルへの出力など、それなりに高い機能を持つツールが、コメント行も含めて400行強で書けました。
注意: 座標系には注意して下さい! マウスをクリックしたときにイベントとして得られる座標は、マウスポインタのディスプレイ上の座標であって、キャンバス(canvas)上の座標ではありません。キャンバス上の座標系に直すには canvasx, canvasy という関数を使います。(See canvas(n))
画像をディスプレイに表示し、マウスで領域を指定する方法は、精度に問題があります。どんなに頑張っても画像ファイルの解像度を越える精度は出せません。実際にはマウス操作の精度以下になります。ですから精度が必要となる場面では、安易に使うべきではありません。
それでも写真にものさしを当てて測るのでしたら、画像をディスプレイに表示して計測する方が精度が出ると思います。スキャナで写真を読む手間も考慮して、どの方法がよいかを判断して下さい。
流体研の方へ: 精度が必要となる計測を行なう場合は、デジタルカメラやデジタルビデオカメラではなく、スチル写真を撮影するべきです。そしてネガフィルムを画像解析機にかけて計測するのがベストです。
リンクはご自由に。でもメールをくれると嬉しいな。
金野 祥久 konno@researchers.jpLast modified: Mon Aug 28 10:25:41 JST 2000