2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

bashとawkとgnuplotでCUIグラフ作成

Last updated at Posted at 2020-08-10

データを標準出力からそのままグラフ化したい

シェル芸に長けた仕事の仕方をしてる人は往々にしてそういう状況に巡り合いますよね?
私はあります。特に環境が整っていない組込系の仕事をしていると。
(それ以外の人は素直にmatplotlib/seabornでもしてください)

なので、標準入力からデータを受け取ってgnuplotからグラフ化までを行うbash(awk)を作りました。

環境

gnuplot 5.4 patchlevel 0
GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.0)
GNU bash, バージョン 4.4.12(3)-release (x86_64-unknown-cygwin)

グラフ表示するウィンドウはx11を指定していますが、環境によって適当に変更してもらえれば良いと思っています。

使い方

とりあえず表示

$ seq 10 | awk '{print $1,$1**2}'
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100
$ seq 10 | awk '{print $1,$1**2}' | gplt

01.png

optionを使う

一応使えるoptionはhelpで表示されるようにしていますが、メモ書き程度なので、なんとなく使ってみてoption内容を理解するようにしてください。
基本的にはoption指定の後ろに数字なりテキストなりを入れて、どんどん設定入力していくようなイメージになります。

$ gplt --help
[x|y|y2]range,[x|y|y2]r  -X  X  : range setting
[x|y|y2]label,[x|y|y2]l  X      : label text setting
[x|y|y2]tics,[x|y|y2]t  X       : scale setting
[x|y|y2]format,[x|y|y2]f  X     : axis decimal digit num. e.g. X=2->1.00
title,t  X                      : graph title
key,k  X                        : w lp key X. legend label
axis                            : , u X:X axis. y2axis
font  X                         : font size ratio(default 14)
out                             : png file output
file  X                         : png file name
size  X                         : png iamge pix size ratio(default:640,480)


pngファイルに出力する

$ seq 10 | gplt out
$ ls
001.png

fileでファイル名を指定しなければ001.pngからの連番で作成されていきます。
scriptと絡めて使うと便利です。

X軸のレンジを指定する

$ seq 10 | gplt xrange 0 5

02.png

複数データを表示し、第二軸に設定する

$ seq 10 | awk '{print $1,$1*2,$1^2}' | gplt , u 1:3 axis

03.png

よく使うのはこのあたりです。
最終的なoutputとしてグラフデータを使う場合はlabel/key/title設定とか整形したりします。

$ seq 20 | awk '{print $1,$1*2,$1^2,$1/2}' | gplt w lp pt 5 k data1 , u 1:3 axis k y2axis yr 0 50 y2r 0 500 , u 1:4 w p pt 7 ps 4 k data3 xl xaxis yl yaxis t test_graph

04.png

コード

内容のほとんど(引数のoption解析)がawkなのでawkでシンタックスハイライトしています。

長いので折りたたみ
gplt
#!/bin/bash
# gnuplot 4.0 upper
# awk gawk 4.0 upper

###############
### setting ###
###############
### X window font size (8,10{11},12{13},14,17,18{20},24{25})
terminal_font_size=14

### default graph size
def_height=640
def_width=480

### deault graph size ratio
graph_size=1.1

### default graph terminal on gnuplot 5.0 over
def_terminal="x11"


# gnuplot version check
gnuplot_ver=`gnuplot -V | awk '{print int($2)}'`
# gnuplot_ver=4  # ver4.0debug 
if [ $gnuplot_ver -lt 5 ]; then
    # 5未満なら組込PC上(Xwindow無し)の使用
    gnuplot4_flag=1
    terminal="png"
    gnuplotcmd="gnuplot"
else
    # 5以上ならローカルPCでXwindow前提の使用
    gnuplot4_flag=0
    terminal=$def_terminal
    gnuplotcmd="gnuplot -p"
fi

# for png font size setting
if [ $terminal = "png" ]; then
    term_font_set="giant"
else
    term_font_set="font\",$terminal_font_size\""
fi

filename='tmp_01.dat'
optionfile='tmp_02.gp'
waferfile='tmp_03.dat'
displayfile='tmp_04.png'
xlinefile='tmp_05.dat'
ylinefile='tmp_06.dat'

if [ $# -eq 0 ]; then

sed 's/,/ /g' | awk 'substr($1,1,1)!~/#|%/' > $filename

$gnuplotcmd <<EOF
set term $terminal size $def_height*$graph_size,$def_width*$graph_size $term_font_set
set out '$displayfile'
set nokey
set grid
plot '$filename' w lp pt 6
EOF

else

# help disp
if [ $1 = "--help" ] || [ $1 = "--h" ] || [ $1 = "-h" ] || [ $1 = "-help" ] || [ $1 = "help" ]; then
    echo "####################"
    echo "### graph option ###"
    echo "####################"
    echo "[x|y|y2|cb][range|r] (min) (max)    : range setting. e.g. xr 0 5 -> 0to5"
    echo "                     {abs (absmax)} : range abs setting. e.g. xr abs 100 -> -100to100"
    echo "[x|y|y2|cb][label|l]  X             : label text setting. e.g. xl \"test\""
    echo "[x|y|y2|cb][tics|t]  X              : scale setting. e.g. xt 2->2 4 6..."
    echo "[x|y|y2|cb][format|f]  X            : axis decimal digit num. e.g. xf 2->1.00"
    echo "[title|t]  X                        : graph title. If no file name is set and the file is to be output, the title will be used as the file name."
    echo "[key|k]  X                          : w lp key X. legend label"
    echo "[keypos|kp] [left|l][right|r]"
    echo "            [top|t][bottom|b]       : legend label position e.g. kp r b"
    echo "axis                                : using y2axis e.g. , u X:X axis"
    echo "log [x|y|y2|cb]                     : axis logscale"
    echo "font [(3)|(giant|g|2)|(large|l|1)|(medium|m|0)|"
    echo "      (small|s|-1)|(tiny|t|-2)|(-3)]: font size e.g. font l. e.g. font 2"
    echo "size  X                             : png iamge pix size ratio(default:640,480)"
    echo "all {no \"keystr\"}                   : col all data plot. X is key title number. XX is key title str."
    echo "    {[h|s][s|split]}                : vsplit arranges charts vertically. hsplit arrange charts horizon."
    echo "[x|y]line X                         : line plot"
    echo "wafer [2|4|6|8|12]                  : wafer circle [inch]"
    echo "bar {rot} {label}                   : bar graph. rot is xtics dir rot. label is data label."
    echo "bubble {scale X} {refoff}           : bubble chart. scale is ref chart scale size."
    echo "map {gray|viridis}                  : color map graph u 1:2:3."
    echo ""
    echo "#####################"
    echo "### output option ###"
    echo "#####################"
    echo "out                                 : png file output"
    echo "file  X                             : png file name"
    echo "svg                                 : for markdown"
    echo "sixel|term|terminal                 : terminal display"
    echo ""
    echo "####################"
    echo "### other option ###"
    echo "####################"
    echo "fit {poly X} {txt|text|dat}         : poly fitting. degree X.  txt is fitting log output \"fit.log\""
    echo "    {gauss {height} {peak} {sigm} {base}}"
    echo "                                    : gauss fitting. "
    echo "headder                             : "
    exit;
fi

sed 's/,/ /g' | awk 'substr($1,1,1)!~/#|%/' > $filename

# record number get
nf=`awk 'NR>1{print NF;exit}' $filename`

echo $@ |\
awk '\
    function adb(s, n1, n2, n3, n4, n5){return out = sprintf(s, n1, n2, n3, n4, n5) out}
    function ad(s, n1, n2, n3, n4, n5){return out = out sprintf(s, n1, n2, n3, n4, n5)}
    function adop(s, n1, n2, n3){return w = w sprintf(s, n1, n2, n3)}
    function number_judge(x){return x~/^[-+]*[0-9]+\.*[0-9]*$/}
    function natural_no_judge(x){return x~/^[+]*[1-9]+[0-9]*$/}
    function range_set(s,  min_tmp, max_tmp){
        min_tmp = max_tmp = ""
        if($(i+1)=="abs" && number_judge($(i+2)) && $(i+2)>0){
            # arg1 abs -> range
            min_tmp = -$(i+2)
            max_tmp = $(i+2)
        }else{
            if(number_judge($(i+1))){
                min_tmp = $(i+1)
                next_flag++
            }
            if(number_judge($(i+2))){
                max_tmp = $(i+2)
                next_flag++
            }
        }
        gsub("range", "", s)
        gsub("r", "", s)
        ad("set %srange [%s:%s];", s, min_tmp, max_tmp)
    }
    function tics_set(s){
        gsub("tics", "", s);
        gsub("t", "", s)
        ad("set %stics %s;", s, $(i+1))
    }
    function label_set(s){
        gsub("label", "", s)
        gsub("l", "", s)
        ad("set %slabel \"%s\"", s, $(i+1));
        if(!gnuplot4_flag)ad(" noenhanced")
        ad(";")
    }
    function format_set(s){
        gsub("format", "", s)
        gsub("f", "", s)
        return format[s] = $(i+1)
    }
    function maxminget(  rc, rcr, k, n, i){
        if(maxminget_flag)return
        i = 0
        while(getline rc < filename > 0){
            n = split(rc, rcr);
            if(!maxminget_flag)for(k=1; k<=nf; k++)mint[k] = maxt[k] = rcr[k]
            i++
            for(k=1; k<=nf; k++){
                data[i, k] = rcr[k];
                if(rcr[k]>maxt[k])maxt[k]=rcr[k]
                if(rcr[k]<mint[k])mint[k]=rcr[k]
            }
            maxminget_flag++
        }
        nr = maxminget_flag
        close(filename)
    }
    function wafer_setting(){
        if(out!~/xrange/ && out!~/yrange/)ad("set size square;")
        if(out!~/xrange/)ad("set xrange [-%d*1.1:%d*1.1];", wafer_size, wafer_size)
        if(out!~/yrange/)ad("set yrange [-%d*1.1:%d*1.1];", wafer_size, wafer_size)
        if(out!~/xlabel/)ad("set xlabel \"x[mm]\";")
        if(out!~/ylabel/)ad("set ylabel \"y[mm]\";")
        ad("wafer_size=%s;", wafer_size)
    }
    BEGIN{
        axis_list["x"]++
        axis_list["y"]++
        axis_list["y2"]++
        axis_list["cb"]++
        # TICS_LIST
        tics_list["t"]++
        tics_list["tics"]++
        for(i in axis_list)for(k in tics_list)TICS_LIST[i k]++
        # RANGE_LIST
        range_list["r"]++
        range_list["range"]++
        for(i in axis_list)for(k in range_list)RANGE_LIST[i k]++
        # LABEL_LIST
        label_list["l"]++
        label_list["label"]++
        for(i in axis_list)for(k in label_list)LABEL_LIST[i k]++
        # FORMAT_LIST
        fromat_list["f"]++
        fromat_list["format"]++
        for(i in axis_list)for(k in fromat_list)FORMAT_LIST[i k]++
    }
    {
        fname = "001"
        font_size = 1
        wafer_size = 150
        def_scale = 10
        ad("set nokey;")
        ad("set ytics nomirror;")
        for(i=1; i<=NF; i++){
            if(next_flag && next_flag--)continue
            if($i == "title" || $i == "t"){
                ad("set title \"%s\"",$(i+1));
                if(!gnuplot4_flag)ad(" noenhanced")
                ad(";")
                title_str = $(i+1)
                next_flag++
                continue
            }
            if($i == "file"){
                fname = $(i+1)
                fname_flag++
                next_flag++
                continue
            }
            if($i == "size" && number_judge($(i+1))){
                graph_size *= $(i+1)
                next_flag++
                continue
            }
            if($i in TICS_LIST){
                tics_set($i)
                next_flag++
                continue
            }
            if($i in RANGE_LIST){
                range_set($i)
                continue
            }
            if($i in LABEL_LIST){
                label_set($i)
                next_flag++
                continue
            }
            if($i == "keypos" || $i == "kp"){
                gsub("set nokey;", "", out);
                trans_dir["r"] = trans_dir["right"] = "right"
                trans_dir["l"] = trans_dir["left"] = "left"
                trans_dir["t"] = trans_dir["top"] = "top"
                trans_dir["b"] = trans_dir["bottom"] = "bottom"
                i1 = $(i+1)
                i2 = $(i+2)
                if(i1 in trans_dir){
                    i1 = trans_dir[i1]
                    next_flag++
                    ad("set key %s", i1)
                    if(i2 in trans_dir){
                        i2 = trans_dir[i2]
                        ad(" %s", i2)
                        next_flag++
                    }
                    ad(";")
                }else if(i1 == "off"){
                    ad("unset key;")
                    next_flag++
                }
                continue
            }
            if($i == "key" || $i == "k"){
                gsub("set nokey;", "", out);
                adop(" title \"%s\" ", $(i+1))
                next_flag++
                continue
            }
            if($i == "font"){
                font_size = $(i+1)
                if(terminal != "png" &&
                   term_font_set = font_size == 3  ? "font\",24\"" :
                                   font_size == -3 ? "font\",8\"" : "" &&
                    ++next_flag)continue
                font_size_list["giant"] = font_size_list["g"] = font_size_list[2] = "giant"
                font_size_list["large"] = font_size_list["l"] = font_size_list[1] = "large"
                font_size_list["medium"] = font_size_list["m"] = font_size_list[0] = "medium"
                font_size_list["small"] = font_size_list["s"] = font_size_list[-1] = "small"
                font_size_list["tiny"] = font_size_list["t"] = font_size_list[-2] = "tiny"
                font_size in font_size_list &&
                (term_font_set = font_size_list[font_size]) &&
                terminal != "png" &&
                term_font_set = term_font_set == "giant" ? "font\",18\"" :
                                term_font_set == "large" ? "font\",17\"" :
                                term_font_set == "medium" ? "font\",14\"" :
                                term_font_set == "small" ? "font\",12\"" :
                                term_font_set == "tiny" ? "font\",10\"" : term_font_set;
            }
            if($i in FORMAT_LIST && format_set($i) && ++next_flag)continue
            if($i == ","){
                gsub("set nokey;", "", out);
                N = split(w, T)
                t_flag = w_flag = 0;
                for(k=N; k>=1; k--){
                    if(T[k] == "title")t_flag++
                    if(T[k] == "w")w_flag++
                    if(T[k] == ",")break
                }
                keyn++
                if(!t_flag)adop(" title \"%d\" ", keyn);
                if(!w_flag)adop(" w lp pt 6 ")
                adop(" , \"\" ");
                continue
            }
            if($i == "axis" && adop(" axis x1y2 "))continue
            if($i == "log" && $(i+1) in axis_list && ad("set logscale %s;", $(i+1)))continue
            if($i == "u" && adop(" u %s ", $(i+1)) && ++next_flag)continue
            if($i == "w"){
                i1 = $(i+1)
                if     (i1 == "lp")adop(" w lp pt 6 ");
                else if(i1 == "p") adop(" w p pt 5 ");
                else if(i1 == "l") adop(" w l ");
                continue
            }
            if($i == "pt"){
                N = split(w, T)
                flag = 0
                for(k=N; k>1; k--){
                    if(T[k] == "pt" && natural_no_judge($(i+1)) && (T[k+1] = $(i+1)) && ++flag)break
                    if(T[k] == ",")break
                }
                if(flag){
                    w = ""
                    for(k=1; k<=N; k++)adop(sprintf(" %s",T[k]));
                }
                continue
            }
            if($i == "ps" || $i == "lt" || $i == "lw"){
                N = split(w, T)
                flag = 0
                for(k=N; k>1; k--){
                    if((T[k] == "p" || T[k] == "lp" || T[k] == "l") && ++flag)break
                    if(T[k] == ",")break
                }
                if(flag)adop(" %s %d ", $i, natural_no_judge($(i+1)) ? $(i+1) : 1)
                continue
            }
            # if gnuplot version > 5.0
            if(($i == "hasen" || $i == "hasenn" || $i == "dot") && !gnuplot4_flag){
                N = split(w,T);
                flag = 0
                for(k=N; k>1; k--){
                    if((T[k] == "lp" || T[k] == "l") && ++flag)break
                    if(T[k] == ",")break
                }
                if(!flag)adop(" w lp pt 6 ")
                adop(" dt \"-\" ")
                continue
            }
            if($i == "out" && ++out_flag)continue
            if($i == "all"){
                all_flag++
                gsub("set nokey;", "", out);
                k = i+1
                while(k < NF){
                    if(!natural_no_judge($k))break
                    set_all_key_t[$k] = $(k+1)
                    k+=2
                }
                continue
            }
            if(all_flag){
                if(($i == "vsplit" || $i == "vs") && !hsplit_flag && ++vsplit_flag)continue
                if(($i == "hsplit" || $i == "hs") && !vsplit_flag && ++hsplit_flag)continue
            }
            # 複数列あってもいいかもしれないが一応allじゃないときに有効にする
            if($i == "fit" && !all_flag && nf >= 2){
                fit_flag++
                # とりあえず20個くらいパラメータを初期化 ⇒ gauss以外はいらないかも?
                for(k=1; k<=20; k++)ad("p%d=1;", k);
                if($(i+1) == "gauss"){ # 一次元gauss
                    # 1:Height, 2:PeakPos, 3:Sigm, 4:Base ←収束しないこともあるのでこれらのparam_initは個別指定可能とする.初期値はある程度求めたあげた方が良いな…
                    for(k=1; k<=4; k++){
                        if(!number_judge($(i+k+1)))continue
                        ad("p%d=%s;", k, $(i+k+1))
                        next_flag++
                    }
                    ad("f(x) = p1 * exp(-((x - p2) / p3)**2) + p4;")
                    ad("fit f(x) \"%s\" via p1, p2, p3, p4;", filename)
                    fx = "ttt*exp(-((x - ttt) / ttt)^2) + ttt"
                    param_no = 4
                    next_flag++
                }else if($(i+1) == "gauss2" && nf >= 3){ # 二次元gauss 表示は重ねるんじゃなくてsplitだな
                    # 1:Height, 2:PeakPos1, 3:Sigm1, 4:PeakPos2, 5:Sigm2, 6:Base
                    for(k=1; k<=6; k++){
                        if(!number_judge($(i+k+1)))continue
                        ad("p%d=%s;", k, $(i+k+1))
                        next_flag++
                    }
                    ad("f(x) = p1 * exp(-((x - p2) / p3)**2 - ((y - p4) / p5)**2) + p6;")
                    ad("fit f(x) \"%s\" via p1, p2, p3, p4, p5, p6;", filename)
                    fx = "ttt*exp(-((x - ttt) / ttt)^2 - ((y - ttt) / ttt)^2) + ttt"
                    param_no = 6
                    next_flag++
                }else if($(i+1) == "poly" && natural_no_judge($(i+2))){  # 多項式一変数
                    param_no = $(i+2) + 1
                    st1 = "f(x) = "
                    st2 = "fit f(x) \"%s\" via "
                    for(k=1; k<=param_no; k++){
                        st1 = st1 sprintf("p%d*x**%d", k, param_no-k)
                        st2 = st2 sprintf("p%d", k)
                        fx = fx sprintf("tttx^%d", param_no-k)
                        if(k != param_no){
                            fx = fx " + "
                            st1 = st1 " + "
                            st2 = st2 ", "
                        }
                    }
                    st1 = st1 ";"
                    st2 = st2 ";"
                    ad(st1)
                    ad(st2, filename)
                    next_flag+=2
                }else if($(i+1) == "poly2" && nf >= 3 && natural_no_judge($(i+2))){ # 多項式二変数 ⇒ これもアルゴ化したい
                    if($(i+2) == 2){ # 二次
                        ad("f(x) = p1*x**2 + p2*x*y + p3*y**2 + p4*x + p5*y + p6;")
                        ad("fit f(x) \"%s\" via p1, p2, p3, p4, p5, p6;", filename)
                        fx = "tttx^2 + tttxy + ttty^2 + tttx + ttty + ttt"
                        param_no = 6
                        next_flag+=2
                    }else{          # 一次(平面)
                        ad("f(x) = p1*x + p2*y + p3;")
                        ad("fit f(x) \"%s\" via p1, p2, p3;", filename)
                        fx = "tttx + ttty + ttt"
                        param_no = 3
                        next_flag++
                    }
                }else{
                    # 引数何もない時は一次fit固定
                    ad("f(x) = p1*x + p2;")
                    ad("fit f(x) \"%s\" via p1, p2;", filename)
                    fx = "tttx + ttt"
                    param_no = 2
                }
                # fitting parameterをグラフ上に表示する. 4.0はsprintfが使えないので5.0以上限定
                # 適当に4個ずつくらいで改行を入れてみる? ⇒ 改行文字が上手く入れられないからlabelを追加していくしかなさそう
                if(!gnuplot4_flag && param_no){
                    st = "set label %d right at graph 0.95,0.05 sprintf(\"f(x) = %s\"" 
                    for(k=1; k<=param_no; k++){
                        st = st sprintf(", p%d", k)
                    }
                    st = st ");"
                    ad(st, ++label_cnt, fx)
                    gsub("ttt", "%g", out)
                }
                continue
            }
            # fit result text output
            # ファイルの有無でfit.logを残すか残さないかshで判断する
            if(fit_flag && ($i == "txt" || $i == "text" || $i == "dat"))print 1 > "fit_log_get"
            if($i == "svg" && ++svg_flag)continue;
            if(($i == "sixel" || $i == "term" || $i == "terminal") && ++sixel_flag)continue;
            if($i == "map" && ++cmap_flag)continue;
            if(cmap_flag){
                if     ($i == "gray")   gray_color_flag++
                else if($i == "viridis")viridis_color_flag++
            }
            if($i == "xline"){
                maxminget()
                printf"%s ",$(i+1) > xlinefile
                for(k=1; k<=nf; k++)printf"%s ", maxt[k] > xlinefile
                printf"\n%s ",$(i+1) > xlinefile
                for(k=1; k<=nf; k++)printf"%s ", mint[k] > xlinefile
                printf"\n\n" > xlinefile
                next_flag++
                xline_flag++
                continue
            }
            if($i == "bubble" && ++bubble_flag)continue
            if(bubble_flag){
                if($i == "scale" && number_judge($(i+1)) && scale = $(i+1) && ++next_flag)continue;
                if($i == "refoff" && ++refoff_flag)continue
            }
            if($i == "yline"){
                maxminget()
                printf"%s %s\n%s %s\n\n", nf==1?0:mint[1], $(i+1), nf==1?nr:maxt[1], $(i+1) > ylinefile
                next_flag++
                yline_flag++
                continue
            }
            # inch
            if($i == "wafer" && natural_no_judge($i+1)){
                wafer_size = $(i+1)
                if(!(wafer_size%2) && wafer_size<=12 && wafer_size>=2)wafer_flag++
                if(!wafer_flag)continue
                wafer_size *= 25.4 / 2
                wafer_plot_point = 1000
                pi = atan2(0, -0)
                for(j=1; j<=wafer_plot_point; j++){
                    p = j * 2 * pi / wafer_plot_point;
                    print wafer_size*cos(p), wafer_size*sin(p), j/wafer_plot_point > waferfile
                }
                continue;
            }
            if($i == "bar" && nf > 1){
                maxminget();
                bar_flag++;
                continue;
            }
            if(bar_flag){
                if($i == "rot")  rot_flag++;
                if($i == "label")label_flag++;
            }
            if($i == "hedder"){
                hedder_flag++
                maxminget()
                # 一行目はヘッダーとして読み込むので#でコメントアウト化
                cmd = sprintf("sed -i -e \"1 s/^/#/g\" %s", filename);
                system(cmd)
                close(cmd)
                for(k=1; k<=nf; k++)hedder_list[k] = data[1, k]
                for(r=2; r<=nr; r++)for(k=1; k<=nf; k++)data[r-1, k] = data[r, k]
                nr--
                continue
            }
        }

        for(i in format)adb("set format %s \"%%.%df\";", i, format[i])

        # terminal type
        adb("set grid;")
        set_width = int(def_width * graph_size)
        set_hight = int(def_height * graph_size)
        if(out_flag){
            # title & fname flag check
            if(!fname_flag && title_str)fname = title_str
            # exist file check
            exst = fname ".png"
            if(getline < exst > 0){
                close(exst);
                exst = sprintf("%s_t.png", fname)
                if(fname~/^[0-9]+$/){
                    while(getline < (exst = sprintf("%03d.png", ++fname)) > 0)close(exst)
                    close(exst)
                }
            }
            close(exst)
            adb("set out \"%s\";", exst)
            adb("set term png size %s, %s %s;", set_hight, set_width, term_font_set)
        }else if(svg_flag){
            adb("set term svg font \", %d\";", set_font)
        }else if(sixel_flag){
            adb("set term sixel size %s, %s font \", %d\";",set_hight, set_width, set_font)
        }else{
            adb("set out \"%s\";", displayfile)
            adb("set term %s size %s, %s %s %s;", terminal, set_hight, set_width, term_font_set, gnuplot4_flag?"":"noenhanced")
        }

        if(w!~/ w /){
            if(cmap_flag)adop(" w p pt 5 ps 1 ");
            else         adop(" w lp pt 6 ");
        }else{
            S = w;
            nw = gsub(" w ", "", S);
            S = w;
            nc = gsub(" , ", "", S);
            if(nw < nc + 1)adop(" w lp pt 6 ")
        }
        if(w~/axis/){
            ad("set y2tics;")
        }
        if(w~/,/){
            N = split(w, T)
            flag = 0;
            for(k=N; k>=1; k--){
                if(T[k] == "title" && ++flag)break
                if(T[k] == ",")break
            }
            if(!flag)adop(" title \"%d\" ", ++keyn);
        }

        # graph type select
        if(cmap_flag){
            ad("set palette defined ")
            if     (gray_color_flag)   ad("( 0 \"#000000\", 1 \"#252525\", 2 \"#525252\", 3 \"#737373\", 4 \"#969696\", 5 \"#BDBDBD\", 6 \"#D9D9D9\", 7 \"#F0F0F0\", 8 \"#FFFFFF\");")
            else if(viridis_color_flag)ad("( 0 \"#440154\", 1 \"#472c7a\", 2 \"#3b518b\", 3 \"#2c718e\", 4 \"#21908d\", 5 \"#27ad81\", 6 \"#5cc863\", 7 \"#aadc32\", 8 \"#fde725\");")
            else                       ad("( 0 \"#000090\", 1 \"#000fff\", 2 \"#0090ff\", 3 \"#0fffee\", 4 \"#90ff70\", 5 \"#ffee00\", 6 \"#ff7000\", 7 \"#ee0000\", 8 \"#7f0000\");")
            ad("set view map;")
            if(wafer_flag){
                wafer_setting()
                # どうせカラーはnmであることが多いのでdefaultはそうする
                if(out!~/cblabel/)ad("set cblabel [nm];")
            }
            ad("splot \"%s\" u 1:2:3 %s palette", filename, w)
            if(wafer_flag)ad(", \"%s\" w l lt -1 lw 2;", waferfile)
            ad(";")
        }else if(bubble_flag){
            # ここでdefaultのスケールを設定
            if(scale == "")scale = def_scale
            tmp_scale = scale
            scalestr = scale
            scale = 15 / scale
            ad("set multiplot;")
            # ver4.0はcirclesに対応していないので、psで対応するため、レンジを固定する
            if(wafer_flag || gnuplot4_flag){
                wafer_setting()
                ad("ref_pos=%s;", wafer_size*0.93)
                if(!refoff_flag && !gnuplot4_flag){
                    ad("ref_scale=%s;", 15)
                    ad("scalestr=\"%s\";", scalestr)
                    ad("plot \"%s\" u (1>0?ref_pos:0):(1>0?ref_pos:0):(1>0?ref_scale:0) every 1 w circles lc \"gray\" fs solid border -1, \"\" u (1>0?ref_pos:0):(1>0?ref_pos:0):(1>0?scalestr:0) every 1 w labels offset 0,0;", filename)
                }
                ad("set parametric;")
                ad("plot [0:2*pi] wafer_size*cos(t),wafer_size*sin(t) w l lt -1 lw 2;")
            }else{
                # 横縦軸のレンジを固定する
                maxminget();
                ad("set xrange [%s:%s];", mint[1]-(maxt[1]-mint[1])/10, maxt[1]+(maxt[1]-mint[1])/10);
                ad("set yrange [%s:%s];", mint[2]-(maxt[2]-mint[2])/10, maxt[2]+(maxt[2]-mint[2])/10);
            }
            # gnuplot ver4 correspondesce
            # 別にこっちに統一してもいいけど5.0verも残しておく
            if(gnuplot4_flag){
                maxminget();
                # gnuplotバージョンによって〇のポイントタイプが異なる。6が中抜き円、Ver4.0は7が中抜き円
                circle_type = 7
                scale /= 4
                # refの表示
                ad("set label %d \"%s\" center at first ref_pos,ref_pos;", ++label_cnt, scalestr)
                scale_plot = scale * tmp_scale
                ad("b=%s;", scale_plot<0 ? -scale_plot : scale_plot);
                ad("plot \"%s\" u (1>0?ref_pos:0):(1>0?ref_pos:0) every ::1::1 w lp pt %d ps b*2 lt %d lw 2 notitle;", filename, circle_type, scale_plot<0?1:2)
                for(i=1; i<=nr; i++){
                    ad("set label %d \"%s\" center at first %s,%s;", ++label_cnt, data[i,3], data[i,1], data[i,2])
                    scale_plot = data[i,3] * scale
                    ad("i=%d;", i-1);
                    ad("b=%s;", scale_plot<0 ? -scale_plot : scale_plot);
                    ad("plot \"%s\" u 1:2 every ::i::i w lp pt %d ps b*2 lt %d lw 2 notitle;", filename, circle_type, scale_plot<0?1:2) # ここで正負の色決めてます
                }
            }else{
                ad("plot \"%s\" u 1:2:($3<0?-$3*%f:0) w circles lc 4 fs solid border -1, \"\" u 1:2:3 w labels offset 0,0;", filename, scale)
                ad("plot \"%s\" u 1:2:($3>0?$3*%f:0) w circles lc \"light-blue\" fs solid border -1, \"\" u 1:2:3 w labels offset 0,0;", filename, scale)
            }
            ad("unset multiplot;")
        }else if(bar_flag){
            # ver4.0はxlabelに行数しか指定できない(xtic()が使えない) set xformat ""してから個別にラベルを配置するか…
            # なので横軸が1列目のデータではなく行数になる…⇒ 1列目を文字列変換すればなんとかなるか?
            ad("set style fill solid border;")
            ad("set boxwidth 0.925;")
            if(out!~/yrange/){
                maxall = maxt[2]
                if(all_flag)for(k=2; k<=nf; k++)if(maxt[k] > maxall)maxall = maxt[k]
                ad("set yrange [:%s];", maxall*1.1)
            }
            if(rot_flag)ad("set xtics rotate by -90;")

            if(all_flag){
                if(label_flag && gnuplot4_flag){
                    maxminget();
                    axis_cnt = 0
                    for(i=1; i<=nr; i++){
                        for(k=2; k<=nf; k++){
                            ad("set label %d \"%s\" center at first %s,%s;", ++label_cnt, data[i,k], axis_cnt++, data[i,k]+maxall*0.02)
                        }
                        axis_cnt++
                    }
                }
                ad("plot \"%s\" u ($0*%d):2", filename, nf)
                if(nf == 3 && !gnuplot4_flag)ad(":xtic(1)")
                ad(" t")
                ad(" \"%s\"", set_all_key_t[1]?set_all_key_t[1]:1)
                ad(" w boxes lw 1 lt 3")
                if(label_flag && !gnuplot4_flag)ad(", \"\" u ($0*%d):2:2 t \"\" w labels offset 0, 1", nf)
                for(i=2; i<nf; i++){
                    ad(", \"\" u ($0*%d+%d):%d", nf, i-1, i+1)
                    if(i == int(nf/2) && !gnuplot4_flag)ad(":xtic(1)")
                    ad(" t")
                    ad(" \"%s\"", set_all_key_t[i]?set_all_key_t[i]:i)
                    ad(" w boxes lw 1 lt %d", i+3)
                    if(label_flag && !gnuplot4_flag)ad(", \"\" u ($0*%d+%d):%d:%d t \"\" w labels offset 0, 1", nf, i-1, i+1, i+1)
                }
            }else{
                if(label_flag && gnuplot4_flag){
                    maxminget();
                    for(i=1; i<=nr; i++)ad("set label %d \"%s\" center at first %s,%s;", ++label_cnt, data[i,2], i-1, data[i,2]+maxt[2]*0.02)
                }
                ad("plot \"%s\" u 0:2", filename)
                if(!gnuplot4_flag)ad(":xtic(1)")
                ad(" w boxes lw 1 lt 3")
                if(label_flag && !gnuplot4_flag)ad(", \"\" u 0:2:2 w labels offset 0, 1")
            }
            if(yline_flag)ad(", \"%s\" u ($1-1):2 t \"\" w l lt -1 lw 3", ylinefile)
            ad(";")
        }else if(all_flag){
            if(vsplit_flag){
                # ad("set multiplot layout %d,1;", nf-1)  # ver4.0ではlayoutは存在しない ⇒ 存在する場合はそのまま使えば?
                ad("set multiplot;")
                ad("set format x \"\";")
                # ver4.0ではscreenは使えないのでベタ書きで設定する。
                # ad("set lmargin screen 0.1;")
                ad("set lmargin 10;") # 左だけ軸の数字がちゃんと入るようにこれくらい空ける
                # ad("set rmargin screen 0.9;") # y2軸使用しない場合は設定不要なはず
                graph_no = nf - 1
                ratio_set = (gnuplot4_flag?1.1:1.15) / graph_size # 係数は経験則
                all_size = 30
                for(i=1; i<nf; i++){
                    # ad("set tmargin screen %s;", 0.95-0.90/(nf-1)*(i-1))
                    # ad("set bmargin screen %s;", 0.95-0.90/(nf-1)*i+0.025)
                    ad("set tmargin %s;", (2.5 + all_size / graph_no * (i-1)) / ratio_set)  # 係数は経験則
                    ad("set bmargin %s;", (3 + all_size - all_size / graph_no * i) / ratio_set)
                    if(i == nf - 1){
                        ad("set format x \"ttt\";")
                        gsub("ttt", "%g", out);
                    }
                    ad("plot \"%s\" u 1:%d t \"%s\" %s", filename, i+1, hedder_list[i+1]?hedder_list[i+1]:set_all_key_t[i]?set_all_key_t[i]:i, w)
                    if(xline_flag)ad(", \"%s\" u 1:%d t \"\" w l lt -1 lw 3", xlinefile, i+2)
                    ad(";")
                }
            }else if(hsplit_flag){
                ad("set multiplot;")
                graph_no = nf - 1
                ratio_set = (gnuplot4_flag?1.1:1) / graph_size
                all_size = 77
                for(i=1; i<nf; i++){
                    # if(i>1)ad("set format y \"\";")
                    ad("set lmargin %s;", (5 + all_size / graph_no * (i-1)) / ratio_set)
                    ad("set rmargin %s;", (5 + all_size - all_size / graph_no * i) / ratio_set)
                    ad("plot \"%s\" u 1:%d t \"%s\" %s", filename, i+1, hedder_list[i+1]?hedder_list[i+1]:set_all_key_t[i]?set_all_key_t[i]:i, w)
                    if(yline_flag)ad(", \"%s\" u ($1-1):2 t \"\" w l lt -1 lw 3", ylinefile)
                    ad(";")
                }
            }else{
                ad("plot \"%s\" u 1:2 t", filename)
                ad(" \"%s\"", hedder_list[1]?hedder_list[1]:set_all_key_t[1]?set_all_key_t[1]:1)
                ad(" %s", w)
                if(xline_flag)ad(", \"%s\" u 1:3 t \"\" w l lt -1 lw 3", xlinefile)
                for(i=2; i<nf; i++){
                    ad(", \"%s\" u 1:%d t", filename, i+1)
                    ad(" \"%s\"", hedder_list[i]?hedder_list[i]:set_all_key_t[i]?set_all_key_t[i]:i)
                    ad(" %s", w)
                    if(xline_flag)ad(", \"%s\" u 1:%d t \"\" w l lt -1 lw 3", xlinefile, i+2)
                    if(yline_flag)ad(", \"%s\" t \"\" w l lt -1 lw 3", ylinefile)
                }
                ad(";")
            }
        }else{
            if(wafer_flag){
                wafer_setting()
                ad("set parametric;")
                ad("set multiplot;")
                ad("plot [0:2*pi] wafer_size*cos(t),wafer_size*sin(t) w l lt -1 lw 2;")
            }
            ad("plot \"%s\" %s", filename, w)
            if(fit_flag)ad(", f(x) w l")
            if(xline_flag){
                flag = 0
                for(i=1; i<=nf; i++){
                    if(!index(out, sprintf(":%d", i)))continue
                    ad(", \"%s\" u 1:%d t \"\" w l lt -1 lw 3", xlinefile, i+1)
                    flag++
                }
                if(!flag){
                    ad(", \"%s\"", xlinefile)
                    if(nf != 1)ad(" u 1:3")
                    ad(" t \"\" w l lt -1 lw 3")
                }
            }
            if(yline_flag)ad(", \"%s\" t \"\" w l lt -1 lw 3", ylinefile)
            ad(";")
        }
    }
    END{
        print out > optfile;
    }' optfile=$optionfile filename=$filename nf=$nf waferfile=$waferfile\
       terminal=$terminal displayfile=$displayfile xlinefile=$xlinefile\
       ylinefile=$ylinefile term_font_set=$term_font_set gnuplot4_flag=$gnuplot4_flag\
       graph_size=$graph_size def_height=$def_height def_width=$def_width

$gnuplotcmd <<EOF
load '$optionfile'
EOF

if [ $gnuplot4_flag -eq 0 ] && [ `echo $@ grep out | wc -l` -gt 0 ] && [ `whereis mogrify | awk 'NF>1' | wc -l` -gt 0 ]; then
    # mogrify -fuzz 10% -trim +repage $out_file
    mogrify -trim +repage $out_file
fi

fi

# png出力する場合にimagemagickで表示するようにする
if [ -f $displayfile ]; then
    if [ $terminal = "png" ] && [ `whereis display | awk 'NF>1' | wc -l` -gt 0 ]; then
        display $displayfile
    fi
    rm $displayfile
fi

# temp file delete
if [ -f $filename ]; then   rm $filename; fi
if [ -f $optionfile ]; then rm $optionfile; fi
if [ -f $waferfile ]; then  rm $waferfile; fi
if [ -f $xlinefile ]; then  rm $xlinefile; fi
if [ -f $ylinefile ]; then  rm $ylinefile; fi
if [ -f fit_log_get ]; then
    rm fit_log_get
elif [ -f fit.log ]; then
    rm fit.log
fi

おわりに

gnuplotとawkしかないような環境でログデータ分析を行う場合に、これひとつつっこんでおけば分析が捗るような気がします。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?