kukkuのメモ帳

勉強したこと,思ったこと,あったことをつらつら書いていきます

まとめてグラフを描画するPythonスクリプトplotlogを作った

以前の記事で「テスト駆動開発」を読んだ記事を書きました。

kukku2123.hatenablog.com

実際に使ってみようと思い、前から作ろうと思っていた(というよりは以前作っていたけど色々拡張したいと思っていた)グラフ描画スクリプトを作りました。 この記事では、前半に作ったスクリプトの説明を、後半にTDDを使ってみた感想を書きたいと思います。

plotlogとは

概要

csv形式等で保存されたログファイルから、yamlファイルに記述した設定に従ってグラフを出力するスクリプトです。 単一のログファイルからはもちろん、ログファイル名を日時で管理している場合は、オプションを指定することで簡単に描画対象ログファイルを複数指定できます。 また、subplotにも対応しています。 大量に同一フォーマットのログファイルを持ち、同じ見た目のグラフを複数作成したい場合に便利なスクリプトです。

リポジトリ

Githubで公開しています。

github.com

動作環境,インストール

Python3.6.3で動作確認しました。 3.4以上なら動くんじゃないかと思いますが確認していません。

PyPIに登録してみたので、pipを使ってインストール出来ます。

pip3 install plotlog

ローカルでビルドする場合は

git clone https://github.com/s-naoya/plotlog.git
cd plotlog
python3 setup.py install

で出来ると思います。

次のパッケージに依存しています。

  • matplotlib(グラフ描画)
  • pandas(ログファイル読み込み、読み込みデータ整形)
  • PyYAML(設定ファイル読み込み)

使い方

まず、次のコマンドでカレントディレクトリにuser.ymlが生成されます。

plotlog --copy

生成されたuser.ymlを編集して作成したいグラフなどを指定します。 最初に生成されたuser.ymlの内容は毎回読み込まれるので、指定したい内容が最初のuser.ymlと同じ場合、その項目を削除しても大丈夫です。 変更された設定項目のみ上書きされます。

設定が終了したら、グラフを描画します。

plotlog

と指定すると、まだ描画されていないログファイル(=graph_save_dir内に、対応するフォルダがないログファイル)について、user.ymlの設定に従ってグラフを描画し、ファイルを保存します。

例えば2018年1月1日以降のグラフを描画したい場合は

plotlog --after 180101000000

2018年1月3日14時00分30秒と2018年1月3日14時10分25秒のグラフをuser-1.ymlに従って描画したい場合は

plotlog --select 180103140030 180103141025 --setting user-1.yml

みたいな感じです。何も指定しなかったら--newとした時と同じ動作をします。

graph_save_dir内のフォルダ構成は下のようになります。

graph_save_dir/
    日付/
        日時/
            グラフファイル
        日時/
            グラフファイル
    日付/
        日時/
            グラフファイル
    other/
        日時以外のログファイル名/
            グラフファイル

正しくフォルダ分けするためにはlog_date_typeの適切な設定が必要です。 ログファイルの方はput_log_dir内にそのまま入れれば大丈夫です。

描画オプションは--slice--noshiftの二つを用意しています。

--slice BEGIN ENDでは、X軸の値の始めと終わりを指定すると、その部分のみ切り出されたグラフが描画されます。 設定ファイルのxlimでも同じことが出来ますが、これを使うと--sliceを使わなかったグラフと別ファイルとして保存されます。 BEGINENDの値を変えるとさらに別ファイルとして保存されます。

--noshiftは、グラフの描画始めのシフトをしない、というオプションです。 plotlogでは、グラフの描画始めを指定した列(shift_trig_col)の値が指定した値の範囲(shift_trig_val)を超えた時を0とする、という機能がデフォルトでついています。

つまり、これ(--noshift付き)が f:id:kukku2123:20180128123508p:plain trigグラフをトリガーとした場合、こうなります。 f:id:kukku2123:20180128123625p:plain

とはいっても、shift_trig_colのデフォルトは0、つまり殆どの場合グラフのX軸となる列なので作動することはありません。 使いたい場合のみ設定を記述してください。

今後の予定

グラフ種類の追加

現在折れ線グラフ(matplotlib で言うplot)しか対応していません。 棒グラフや散布図なども指定できるようにする予定です。

設定項目の整理

ちょっと無駄があるかなと思うので、少しいじる予定です。 ここまで出来たら正式版として更新します。

フットプリント描画機能の追加

フットプリントの描画機能を作成する予定です。 この場合のフットプリントとは足跡、並びに足の支持領域を指します。 私が行っているヒューマノイドロボットの研究に使用します。 つまりはただの自分用機能です。 使わない人のほうが多いと思うので、独自機能実装の例として見てくれると嬉しいです。

TDDでやってみた感想

良かった点

やはりテストが通ったまま実装に取り掛かれるのは非常に安心感がありました。 他人への引き継ぎ、仕様変更等に強いと感じました。

悪かった点

ロジックに関わる部分には強いですが、描画に関わる部分に対するテストの書き方がわかりませんでした。 plotlog で言うところの PlotGraph クラスです。 これらのテストが通ればちゃんと描画されてるはず、というのをテストに書けばいいんでしょうか。 出たグラフを目で確認した方が確実だと判断したので、ここに関してはほとんどテストを書きませんでした。

反省

私は今までテストを書いたことがなく(すいません……)、テストの書き方に全く慣れないままやったのが悪かったのか、実装スピードがかなり低下してしまいました。

単純な実力不足で重複を放置したままの箇所も……

まだまだ勉強が足りないですね。

まとめ

グラフ描画スクリプトとしては中々便利なものが出来たんじゃないでしょうか。 ロジック部分に関してはTDDの強力な面を体感できました。

ただプログラムとしては「きれいなコード」とは言い切れないものになってしまったので、これから慣れていこうと思います。

コメント、指摘等ありましたら是非どうぞ。