gnuplot を使いこなす - 情報処理IIレジュメ(2021-6)

1. はじめに

データ処理を行うには Excel は便利ですが、グラフを描くために色々とマウスで作業が必要であり面倒です。 マウスで設定作業をするのは、初心者が手探りでグラフを作成できるという意味ではいいですが、慣れても作業効率が上がらないところに問題があります。 今回は、すでに第二学年の情報処理で使ってきた gnuplot について、もう少し効率的な使い方を解説します。

2. gnuplot を使ってみる

自分のマシンの画面が異なると混乱するという意見があったので、macOS 版、Windows 版を併記して表示することにします。 以下、左側が macOS、右側が Windows となります。 macOS はデフォルトで qt ターミナル、Windows は wxt ターミナルです。 Windows も qt ターミナルを利用できるのですが、複雑なグラフに難があるとのことで wxt にしています(macOS や Linux は qt で問題ありません)。

2.1 起動

macOS はターミナルで gnuplotとタイプします。 Windows 版は GUI アプリとなっています。 ただし、特にメニューなどを使わない場合には、PowerShell から gnuplot とタイプすることで macOS と同様に CUI 版の gnuplot が立ち上がります。 今後、2年生の時のように、この画面に直接入力することは、あまりないので GUI のメリットはあまりないと思います。

f:id:hkob:20200521214231p:plainf:id:hkob:20200521214250p:plain
起動画面

2.2 正弦波を書いてみる

先ほどの画面に plot sin(x) とタイプしてみます。 この結果、-10\leq x\leq 10までのグラフが描画されているのがわかります。

f:id:hkob:20200521214957p:plainf:id:hkob:20200521214736p:plain
sin(x)のグラフ

ここで、1[Hz]の正弦波を書いてみます。plot sin(2*pi*x)とすると画面に少し変な波形が表示されました。

f:id:hkob:20200521215259p:plainf:id:hkob:20200521215240p:plain
1[Hz]の正弦波(不具合あり)

理由はshow samplesとすると判明します。 見るとわかるようにグラフの点数が100点と少ないことがわかります(以下、gnuplot>のプロンプト部分は省略します)。

show samples

    sampling rate is 100, 100

そこで、samples の値をもう少し増やして、再描画してみると正しく正弦波になっていました。

set samples 512
replot

f:id:hkob:20200521215809p:plainf:id:hkob:20200521215842p:plain
1[Hz]の正弦波(不具合解消)

ここでx軸の範囲を-1から1までに変更してみます。 plot の後ろに範囲を指定することで、x 軸の範囲を設定できます。

plot [-1:1] sin(2*pi*x)

f:id:hkob:20200521220220p:plainf:id:hkob:20200521220238p:plain
x軸を-1から1までに限定

図の中に x 軸(y=0の線)が書かれていないので、さらにコマンドを追加してみます。

set xzeroaxis
replot

f:id:hkob:20200521220643p:plainf:id:hkob:20200521220704p:plain
x軸の描画

同様に y 軸(x=0の線)もコマンドで追加してみます。

set yzeroaxis
replot

f:id:hkob:20200521221015p:plainf:id:hkob:20200521221054p:plain
y軸も追加

あまり使うことはないと思いますがグリッドも書いてみます。

set grid
replot

f:id:hkob:20200521221234p:plainf:id:hkob:20200521221248p:plain
グリッドも追加

各軸のラベルも追加してみましょう。

set xlabel "Time t[s]"
set ylabel "Voltage v[V]"
replot

f:id:hkob:20200521221431p:plainf:id:hkob:20200521221448p:plain
軸ラベルの追加

2.3 特殊関数を使ってみる

切り捨ての関数 floor(x) を描画してみます。小数点以下が切り捨てられるので、階段型の波形になっています。

plot [-5:5] floor(x)

f:id:hkob:20200521221817p:plainf:id:hkob:20200521221832p:plain
切り捨て関数 floor(x)

gnuplot は自作の関数を作ることができます。 ここでは f(x) という関数を作成し、そのグラフを描画してみます。 この f(x) はどんな関数なのかは各自で考えてください(グラフの外形から理解できると思います)。

f(x) = x - floor(x)
plot [-5:5] f(x)

f:id:hkob:20200521222435p:plainf:id:hkob:20200521222452p:plain
自作関数 f(x)

もう一つの自作関数 g(x) を作ってみる。今回の関数は条件判断が含まれています。 こちらも何ができているのかは各自で考えてください。 また、高さを自動のままにするとグラフの外径が見えにくくなるので、手動でy方向の範囲も設定している。

g(x) = floor(x) % 2 == 0 ? 1 : 0
plot [-5:5] [-0.5:1.5] g(x)

f:id:hkob:20200521222827p:plainf:id:hkob:20200521222840p:plain
自作関数 g(x)

最後に複数のグラフの描画を実行してみます。 今回は三年生で学ぶ三相交流波形を描いてみます。 三相交流とは120度ずつずらした三本の正弦波交流です。

plot [-1:1] sin(2*pi*x), sin(2*pi*x+2*pi/3), sin(2*pi*x+4*pi/3)

f:id:hkob:20200521223413p:plainf:id:hkob:20200521223437p:plain
三相交流(キーなし)

デフォルトではキーの部分に記載した関数がそのまま表示されます。 かなり見にくいので、v_a, v_b, v_cのようにタイトルをつけます。 LaTeX と同じで_を使うことで下付文字を記載することが可能です。

plot [-1:1] sin(2*pi*x) t "v_a", sin(2*pi*x+2*pi/3) t "v_b", sin(2*pi*x+4*pi/3) t "v_c"

f:id:hkob:20200521224116p:plainf:id:hkob:20200521224148p:plain
波形にタイトルを付ける

3. スクリプトを使って自動化する

これまでの作業を毎回打つのは面倒なので、これを一つのスクリプトにしてみます。 その結果、次回以降はそれを複製して修正すればよいことになります。 ただし、Windows と macOS でやり方が大きく異なるので、個別に説明します。 ここでは、先ほどの3つの正弦波を表示するスクリプトで説明します。

3.1 macOS の場合の自動化

macOS の場合、シェルスクリプト(普段使っているシェルコマンドの流れをまとめて記述したもの)の中に gnuplot の呼び出しまでを含めます。 gnuplot のスクリプトはヒアドキュメントという機能を使って、シェルスクリプト内に記載します。 以下、手順を箇条書きで説明します。

  • すでに作成しているフォルダに移動して vscode で開きます。 フォルダ名は自分のものに読み替えてください。 ターミナル(iTerm2など) を開いて以下のコマンドを実行してください。
cd ~/Documents/gnuplotTest
code .
  • vscode のターミナルを開き、空のシェルスクリプト threeSins.sh を作り、スクリプト実行権限を付けます。ファイルは vscode で作ってもいいです。
touch threeSins.sh
chmod +x threeSins.sh
  • このスクリプトを watch して自動実行するように chokidar を設定する。ファイル名は最初の数文字を書けばあとはタブキー で補完できる。
chokidar threeSins.sh -c ./threeSins.sh
Watching "threeSins.sh" ..
  • これでターミナルの作業は終了となります。 vscode で以下のスクリプトを記載してください。 ここで、スクリプトを簡単に説明します。
    • FNAME には $0 で示されるスクリプト自身のファイル名から「.sh」を取り除いた文字列が入ります。
    • PDF はこの名前に .pdf をつけた名前が入ります。今回の場合は、threeSins.pdf という名前になります。
    • gnuplot の後ろに書かれた <<EOF はヒアドキュメントと呼ばれる機能です。次の行から EOF までの行が gnuplot への入力となります。
    • gnuplot 内では、PDF ターミナルを設定し、そのファイル名を先ほど設定した $PDF 変数に設定します。ここでは先ほど描いた3本の sin(x) が描画されます。
    • gnuplot の描画が終わると、macOS の open コマンドで作成された pdf ファイルが表示されます。
#!/bin/sh

# ここからは固定
FNAME=${0%.sh}
PDF=${FNAME}.pdf

gnuplot <<EOF
set term pdf color font 'Helvetica,14'
set output '$PDF'

# ここからは自分で変更する部分
set samples 500
set xzeroaxis
set yzeroaxis
set grid
set xlabel 'Time t[s]'
set ylabel 'Voltage v[V]'
plot [-1:1] sin(2*pi*x) t 'v_a', sin(2*pi*x+2*pi/3) t 'v_b', sin(2*pi*x+4*pi/3) t 'v_c'

# ここからは固定
quit
EOF
open $PDF
  • 上記のファイルを保存した瞬間に chokidar がファイル更新を認識し、自動的にグラフが出力されます。
    f:id:hkob:20200522094830p:plain
    自動出力されたグラフ
  • ファイルを書き換えて、グラフが更新されることを確認してください。
  • 別のグラフを書きたければ、このファイルを別名で保存し、gnuplot の中身だけを書き換えればよい。先ほど説明したようにファイル名はシェルスクリプト自体の名前で自動設定されるので、gnuplot 以外の部分は全くいじる必要はない。

3.2 Windows の場合の自動化

Windows の Adobe Reader は PDF ファイルを開いている時に、そのファイルを別のプログラムで変更することができません。このため、昨年度までは Adobe Reader を終了させる処理を追加していました。今年度は SumatraPDF というファイルをロックしないビューワを使うことで、この問題を回避します。

また、Windows の場合にはヒアドキュメントの仕組みが使いにくいです。 そのため、gnuplot のスクリプトの中から、外部コマンドを実行することにしています。

  • すでに作成しているフォルダを code で開きます。
  • threeSins.gp というファイルを新規で作成します。
  • ターミナルを開きます。
  • このスクリプトを watch して自動実行するように chokidar を設定します。二箇所ファイル名を書く場所がありますが、PowerShell では最初の数文字を入れれば、あとはタブキー で補完できます。ここで、-c のオプションであるコマンドを""で括ることを忘れないでください。
chokidar .\threeSins.gp -c "gnuplot .\threeSins.gp"
  • これでターミナルの作業は終了です。
  • vscode で以下のスクリプトを記載します。ここで、スクリプトを簡単に説明します。
    • name には PDF のファイル名を記載します。
    • gnuplot のデフォルトでは、漢字コードが WIndows 標準の Shift JIS になっています。ただし、vscode のデフォルトは UTF-8 なので、エディタでファイルを開くたびにエンコードを変更する必要しなければなりません。この作業は非常に面倒なので、gnuplot の方を UTF-8 で動作するように変更しています。「set encoding utf8」はそのコマンドです。これで何も気にせずに日本語などを書くことができます。ただし、このコマンドを実行して初めて漢字コードが設定されるので、このコマンドの前に日本語のコメントを書くことはできません(昨年度かなり多くの学生がハマっていました)。
    • あとは gnuplot のコードとなります。gnuplot 内では、PDF ターミナルを設定し、そのファイル名を先ほど設定した $PDF 変数に設定します。ここでは先ほど描いた3本の sin(x) が描画されます。
    • gnuplot の描画が終わると、set output で書き込みを中止します(ファイル名を変更することで書き込みが確定します)。その後、system コマンドで pdf を実行します。Windows の場合にはファイル名に関連したアプリを選ぶように言われるので、SumatraPDF を選んでください。すでに PDF のデフォルトを Adobe Reader に設定してしまっている人は、SumatraPDF に変更しておいてください。
set encoding utf8
# 文字コードをUTF-8 に設定します。このコマンドの前に日本語を書かないでください。

# ここの名前は自分で設定します
name = "threeSins.pdf"

# PDF reader として、どうしても Adobe Reader を使う場合にはコメントを外してください。
# SumatraPDF を使う場合は必要ありません
# system("taskkill /im AcroRd32.exe")
# system("timeout 1")

# ここからは固定
set term pdf color font ',10'
set output name

# ここからは自分で変更する部分
set samples 500
set xzeroaxis
set yzeroaxis 
set grid
set xlabel 'Time t[s]'
set ylabel 'Voltage v[V]'
plot [-1:1] sin(2*pi*x) t 'v_a', sin(2*pi*x+2*pi/3) t 'v_b', sin(2*pi*x+4*pi/3) t 'v_c'

# ここから下も固定部分
set output
system(name) 
quit

gnuplot でスクリプトにエラーがある場合は chokidar の画面内で確認することができます。一昨年度までは、gp ファイルをダブルクリックしていましたが、この場合にはエラーが出ていても何も表示されないので、サポートが大変でした。

4. 線種・点種の確認

先ほどの chokidar はどちらの環境でも ctrl-c で止めることができます。

次に線種・点種の確認をする画面を表示してみます。どちらの環境でも先ほど作ったファイルをコピーします。macOS の場合はこちら。

cp threeSins.sh test.sh

Windows の場合にはこちら。

copy threeSins.gp test.gp

macOS の場合には、以下のように修正します(中身をtest に書き換えるだけです)。

#!/bin/sh

# ここからは固定
FNAME=${0%.sh}
PDF=${FNAME}.pdf

gnuplot <<EOF
set term pdf color font 'Helvetica,14'
set output '$PDF'

# ここからは自分で変更する部分
test

# ここからは固定
quit
EOF
open $PDF

Windows の場合にも同様に修正をします。こちらは一番上の name の書き換えを忘れないでください。

set encoding utf8
# 文字コードをUTF-8 に設定します。このコマンドの前に日本語を書かないでください。

# ここの名前は自分で設定します
name = "test.pdf"

# PDF reader として、どうしても Adobe Reader を使う場合にはコメントを外してください。
# SumatraPDF を使う場合は必要ありません
# system("taskkill /im AcroRd32.exe")
# system("timeout 1")

# ここからは固定
set term pdf color font ',10'
set output name

# ここからは自分で変更する部分
test

# ここから下も固定部分
set output
system(name) 
quit

それぞれの環境で作成された PDF を示します。 これを基に今回の課題を実行してください。

f:id:hkob:20200522141104p:plainf:id:hkob:20200522141123p:plain
test の結果

5. 課題

5.1 課題1: 線種・点種を変更したグラフ

test.pdf の出力を参考に先ほどのグラフの線種・点種などを変更したグラフを作成し提出してください。 描画の種類については(詳しくは help plot の後に style で確認できる)は w styleの形で書きます。基本的に省略形が用意されているので、フルスペルで書く必要はありません。

  • w l: 線で記述 (with lines の省略形)
  • w p: 点で記述 (with points の省略形)
  • w lp: 線と点を両方記述 (with linespoints の省略形)

また、線の種類や点の種類も同様に記述します。以下のものも、区別できれば頭文字だけで Okです。

  • lt 数字: (線種の指定: linetype の略)
  • lw 数字: (線の太さの指定: linewidth の略)
  • lc 数字: (線の色の指定: linecolor の略)
  • pt 数字: (点種の指定: pointtype の略)
  • ps 数字: (点のサイズの指定: pointsize の略)

提出するもの

  • gp (Windows) または sh (macOS)
  • 作成した pdf ファイル

5.2 課題2: 実験データの出力

実験レポートのスタイルファイル内に、実際のデータを使った実験データの出力のやり方が書いてあります。 データファイルを用意して、Windows、macOS のそれぞれにおいて、gp または sh を作成し、近似曲線まで含めたグラフを作成してください。スクリプトの中身は template.tex に書かれているので、それを今回のスクリプトに埋め込めばいいだけです。

提出するもの

  • gp (Windows) または sh (macOS)
  • 作成した pdf ファイル

hkob.hatenablog.com