Julia で時系列データをリアルタイム(お気持ち程度)に描画する


はじめに

実験やデモをしたい時,取得した信号をその場で可視化したいニーズがあると思います.
例えば Arduino IDE のシリアルプロッタなど,いい感じの描画ソフトウェアが既にあります.
今回は csv ファイルで保存した時系列データを描画したかったので,簡単なスクリプトを作りました.

タイトルに「お気持ち程度」と断りを入れたのは,
「デッドタイムを超えないことを保証する」リアルタイム性は全く考慮していないためです.

でも,こういう用途のスクリプトを調べようとすると,結局「リアルタイム 描画」で検索しますよね

出来たもの

試した環境

Mac book 上の Ubuntu 20.04 (Virtual Box) + Julia 1.41

こだわったところ

  • プロット点が一定数を超えても描画し続ける
  • プロット点の移動に合わせて x 軸(時刻)も動く

描画スクリプト

  • 適宜必要なパッケージを Pkg.add() してください.
  • 利用環境で qt5 のインストールが必要です.
SignalPlot.jl

using Plots
using CSV

gr(show = true)

function main()

    # graph setting
    Title = "time-series data"
    Label = "random data"
    XLabel = "time (s)"
    YLabel = "number"
    # sampling time
    dt = 0.1
    # graph width(number of plotting point)
    width = 100
    # declear x, y
    x = dt:dt:dt*width
    y = zeros(width,1)
    x_offset = 0

    for i in 1:500
        data = CSV.read("tmp.csv",header=false)
        datalen = length(data.Column1)
        if datalen <= width
            y[1:datalen] = data.Column1
        else
            y = data.Column1[end-(width-1):end]
            x_offset = dt*(datalen-width)
        end
        display(plot(x + x_offset*ones(width,1),y,title = Title,label = Label,xlabel=XLabel,ylabel=YLabel))
    end
end

おまけ:デモに用いた乱数生成スクリプト

上記描画スクリプトの実行前にバッググラウンド実行してください.
100 以下の整数がサンプリング周期 0.1 秒ごとに csv ファイルに保存されます.

GenerateSignal.sh

#! /bin/bash
FILE=tmp.csv

if [ -e $FILE ]; then
    rm $FILE
fi

while true
do
    echo $(($(od -vAn -N1 -tu < /dev/urandom) % 101 )) >> $FILE
    sleep 0.1s
done

おわりに

  • 仮想マシン上でも描画速度は良好で満足しています.
  • csv ファイルで時系列データを保存できる機器,アプリケーションに大体適用できそうです.
  • 描画処理を無限ループにしても良いですが,強制終了できないためお勧めしません.
  • 大規模データを扱いたい or より高速に描画したい場合は, 時系列データをバイナリファイルとして扱うと良いかと思います.

参考