LoginSignup
0
0

More than 5 years have passed since last update.

p6-Chart-Gnuplotを作った話

Last updated at Posted at 2017-12-11

こんにちは、11日目の投稿になります。

Advent of Codeばっかり解いててもつまらないので、今日は私の作ったp6-Chart-Gnuplotをどういう感じで作っていったのか紹介しようと思います。

1. モチベーション

去年のアドベントカレンダーでも紹介記事があったように、Perl6のグラフ描画ライブラリにはSVG::Plotがありました。
しかし、matplotlibやgnuplotなどの高機能な描画ライブラリと比較すると、どうしても力不足な印象が否めなせんでした。
そこで、Perl6初の本格的な描画ライブラリとして、gnuplotのバインダを作ることにしました。

2. コードリーディング

描画ライブラリというものを全く作ったことがありませんでした。
いろいろ着手していく前に、ほかの競合ライブラリのコードリーディングをやって知見を貯めていくところから始めました。

具体的には、まず開発規模が近そうなのでperl, goのgnuplotのライブラリを読みました。
そして、これだけ使われてればさすがにいい感じのテストが書いてあるだろうと思ってmatplotlibを読みました。

Chart-Gnuplot

大先輩であるPerl 5のライブラリです。
プロダクトが出来上がるとPerlと確実に比較されるので読むことにしました。

  • このライブラリは下記のような特徴があるようでした:
    • 細かな描画オプションはChart::Gnuplot::DataSetに格納する
    • thawに描画オプションを読み取る操作をやらせる
    • 実行のためのスクリプトはファイルにいったん保存する: https://metacpan.org/source/KWMAK/Chart-Gnuplot-0.23/lib/Chart/Gnuplot.pm#L236
    • executeでシステムコールによってgnuplotコマンドを実行する
    • あらかじめファイル保存されたスクリプトとテスト時に生成保存されたスクリプトのdiffを取ることでテストしている

go-gnuplot

規模が小さいので手が付けやすそうでした

glot

goのライブラリで特に人気があるようなので読むことにしました。

  • このライブラリは下記のような特徴があるようでした:
    • ところどころAPIは違うかもしれないが、おそらくgo-gnuplotがベースになっていてアプローチがかなり近い
    • エラー処理だけはテストされている

matplotlib

単体テストを一体どのようにおこなっているのか。この一点にだけ関心があったので読みました。

結論から言うと、maptlotlibで行われている単体テストは仕様化テストです。コードをそこまでしっかりと読まなくても下記ページに説明がありました:
https://matplotlib.org/devel/testing.html

具体的には下記の手順になっているようです:
1) 今後テストに使用したい描画オプションを指定してmatplotlibによりsvg画像を生成する(※pngはファイルが大きいので結局svgしか使わない)
2) ベースとなるイメージを保存するためのフォルダにそのsvg画像をコピーする
3) 1)で指定した描画オプションと同様のオプションを指定して画像を生成し、2)のフォルダ内の対応する画像とのdiffを取る

3. フレームワーク

コードリーディングした結果を参考にして、どういう枠組みで解くべきか決めました:

  • 基本的にgo-gnuplotのアプローチを採用する
    • i.e. 専用のインタフェースがある場合はそれで、そうじゃない場合はベタに命令文を指定してもらう
  • ファイル書き込みはダサいのでやらない
  • テストはChart-Gnuplot(Perl)の方式でおこなう。ただしファイル書き込みは行わないので、変数に命令文を保存して、想定した命令文と一定しているかどうかをチェックするようにする

4. 実装

フレームワークがだいたい定まったのでいよいよ実装です。
はまったポイントをいくつか紹介しようと思います

Procでgnuplotを呼び出すとハングする

  • Proc::Asyncに切り替えて乗り切りました

Proc::Asyncを使うと副作用があってテストが書けない

プロット対象のデータをファイル書き込みしたくない

nohidden3d などのオプションがPerl6の否定の書き方と一貫性がない

  • FalseOnlyというFalseしか格納できないsubsetを作りました
  • FalseOnly :$hidden3d というようにすることでnohidden3dをPerl6っぽい感じで指定することができるようにしました

replotが効かない・・・?

ほかにもいろいろありました。
特に、自分のgnuplotへの理解の浅さがコードに露呈するのが怖かったので、何のスキルが伸びるでもなく、毎日のようにgnuplotの公式ドキュメントを読む日々はつらかったです。

5. テスト

  • 生成された命令文が想定したものと一致するかどうかをテストしました。
  • 画像自体のテストはしていません。(それはgnuplotがやるべきだと思います)

6. リリース後

某NASAの人がスター付けてくれました。:muscle:
一方APIがダメダメだというコメントがirclogに残されていたので微妙な気分です。

ぜひPRお待ちしております :bow:

以上11日目の投稿でした。

0
0
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
0
0