Subsections

4 C言語からgnuplotを操作する

4.1 パイプラインとは

gnuplotをC言語のプログラムから制御するには,パイプを使うのが最も簡単である.C言語の プログラムで,パイプを開いて,それをgnuplotに接続するのである.接続方法を説明す る前に,UNIXのパイプと言う機能を簡単に説明しておく.

UNIXのコマンドの大部分は,標準入力(キーボード)からデータを受け取り,標準出力(ディ スプレイ) に処理した結果を出力するようになっている.例えば,


	ls -l

などである.このように,コマンドをフィルターと呼ぶ.

複数のコマンドを使って,処理したいデータがある場合,UNIXではコマンドを接続するこ とができる.標準出力から出てくるデータを次のコマンドの標準入力に渡すのである.例 えば,


	ls -l | sort -n +4

のようにするのである.最初のコマンドで,カレントディレクトリーのファイルとディレ クトリーの情報を調べ,次のコマンドでファイル容量の順に並べている.

このようにコマンドを連結する機能をパイプラインという.そして,連結する | を パイプという.あたかも,パイプにデータが流れているかのようである.もちろん,2個 以上のコマンドの連結が可能である.このようにパイプを使ってコマンドをつなぐことに より,UNIXではかなり複雑な動作も簡単に記述できる.

4.2 パイプを使う方法

パイプを使うことにより,C言語のプログラムを通してgnuplotを制御することができる. パイプを通してC言語のプログラムから,gnuplotにコマンドを流して,プログラマーの思 い通りに動作させることが可能である.これを実現するためには, の操作が必要である.

パイプを開くためには,ファイルポインターをつかう.そのためファイルポインターを格 納すの変数を用意しなくてはならない.パイプの先もファイルとして扱われるのである.


FILE *hoge;

次にgnuplotを立ち上げて,そこにパイプを接続する必要がある.パイプの情報のファイ ルポインターで示される.


hoge = popen("gnuplot -persist","w");
popen()関数がパイプを開く命令である.これで,gnuplot が立ち上がり,パイプを 通して,コマンドを送ることができる.オプションのpersistで,gnuplotが終了し てもグラフが残るようにしている.そうしないと,コンピューターの動作は高速なので, gunplotは一瞬にして終了し,グラフが消えてしまい,ほとんど動作内容が分からなく なる.

パイプを通して,gnuplotにコマンドを送るのはfprintf()関数を使う.


fprintf(hoge, "plot sin(x)\n");
このfprintfを使って,gnuplotにいくらでもコマンドを送ることができる.あたか も,C言語の向こう側でgnuplotが立ち上がって,それから命令を送っているかのように動 作する.このようなことができるのが,コマンドを打ち込むCharacter-based User Interface(CUI)の良いところである.

すべての動作が終了したならば,パイプを閉じなくてはならない.これは,ファイルの操 作と全く同じである.


pclose(hoge);

4.3 プログラム例

4.3.1 グラフ作成

先に示した方法で,C言語からgnuplotを制御して,三角関数のグラフを作成するプログラ ムをリスト1に示す.
   1 #include <stdio.h>
   2 
   3 int main(void){
   4   FILE *hoge;
   5 
   6   hoge = popen("gnuplot -persist","w");
   7   fprintf(hoge, "plot sin(x)\n");
   8 
   9   pclose(hoge);
  10 
  11   return 0;
  12 }

4.3.2 データファイルとグラフ作成

複雑な数値計算を行う場合,データを作成してから,それをグラフ化することがしばしば ある.次に,インパルスのデータを作成した後,グラフ化する例をリスト2に示す.
   1 #include <stdio.h>
   2 
   3 int main(void){
   4   FILE *data, *gp;
   5   int i, imax=20;
   6   double x=-5.0, dx, y;
   7   char *data_file;
   8 
   9   /*------ データファイル作成 ---------- */
  10   
  11   data_file="out.dat";
  12   data = fopen(data_file,"w");
  13 
  14   dx=10.0/imax;
  15 
  16   for(i=0; i<=imax; i++){
  17     if(x<-1){
  18       y=-1.0;
  19     }else{
  20       y=1.0;
  21     }
  22 
  23     fprintf(data,"%f\t%f\n", x, y);
  24     x+=dx;
  25   }
  26 
  27   fclose(data);
  28 
  29   /*------ グラフの作成 ---------- */
  30   
  31   gp = popen("gnuplot -persist","w");
  32   fprintf(gp, "set xrange [-5:5]\n");
  33   fprintf(gp, "set yrange [-1.5:1.5]\n");
  34   fprintf(gp, "set pointsize 2\n");
  35   fprintf(gp, "plot \"%s\" using 1:2 with linespoints 1 4 \n", data_file);
  36   pclose(gp);
  37 
  38   return 0;
  39 }

4.3.3 setコマンドを使った例

もう少し複雑な,setコマンドを駆使した例をリスト3に示す.
   1 #include <stdio.h>
   2 #include <math.h>
   3 void mk_triangle_data(char *a, double x1, double x2, int n);
   4 void mk_graph(char *f, char *xlb, double x1, double x2,
   5 	      char *ylb, double y1, double y2);
   6 
   7 /*==========================================================*/
   8 /*   main function                                          */
   9 /*==========================================================*/
  10 int main(void){
  11 
  12   double pi = 4*atan(1);
  13   
  14   mk_triangle_data("out.txt", -2*pi, 2*pi, 1000);
  15   mk_graph("out.txt", "x", -2*pi, 2*pi, "y", -3, 3);
  16   
  17   return 0;
  18 }
  19 
  20 /*==========================================================*/
  21 /*   make a data file                                       */
  22 /*==========================================================*/
  23 void mk_triangle_data(char *a, double x1, double x2, int n){
  24   double x, dx;
  25   double y1, y2, y3;
  26   int i;
  27   FILE *out;
  28   
  29   dx = (x2-x1)/n;
  30   
  31   out = fopen(a, "w");
  32   
  33   for(i=0; i<=n; i++){
  34     x = x1+dx*i;
  35     y1 = sin(x);
  36     y2 = cos(x);
  37     y3 = tan(x);
  38     
  39     fprintf(out, "%e\t%e\t%e\t%e\n", x, y1, y2, y3);
  40   }
  41   
  42   fclose(out);
  43 }
  44 
  45 /*==========================================================*/
  46 /*   make a graph                                           */
  47 /*==========================================================*/
  48 void mk_graph(char *f, char *xlb, double x1, double x2,
  49 	      char *ylb, double y1, double y2)
  50 {
  51   
  52   FILE *gp;
  53   
  54   gp = popen("gnuplot -persist","w");
  55   
  56   fprintf(gp, "reset\n");
  57 
  58   /* -------  set x grid ---------*/
  59 
  60   fprintf(gp, "set grid\n");
  61   
  62   /* -------  set x axis ---------*/
  63   
  64   fprintf(gp, "set xtics 1\n");
  65   fprintf(gp, "set mxtics 10\n");
  66   fprintf(gp, "set xlabel \"%s\"\n", xlb);
  67   fprintf(gp, "set nologscale x\n");
  68   fprintf(gp, "set xrange[%e:%e]\n", x1, x2);
  69   
  70   /* -------  set y axis ---------*/
  71   
  72   fprintf(gp, "set ytics 1\n");
  73   fprintf(gp, "set mytics 10\n");
  74   fprintf(gp, "set ylabel \"%s\"\n", ylb);
  75   fprintf(gp, "set nologscale y\n");
  76   fprintf(gp, "set yrange[%e:%e]\n", y1, y2);
  77   
  78         /* -------  plat graphs ---------*/
  79 
  80   fprintf(gp, "set terminal x11\n");
  81   
  82   fprintf(gp, "plot \"%s\" using 1:2 with line,\
  83                     \"%s\" using 1:3 with line,\
  84                     \"%s\" using 1:4 with line\n", f, f, f);
  85   
  86   fprintf(gp, "set terminal emf\n");
  87   fprintf(gp, "set output \"tri.emf\"\n");
  88 
  89   fprintf(gp, "replot\n");
  90   
  91   pclose(gp);
  92 }



ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
2006-02-13


no counter