島根県産業技術センター の東です。
前回の記事では、組み込み機器向けRubyフレームワーク「Alone」が、なぜ現代においてもCGIという「不変のプロトコル」にこだわり、安定性を担保しているかをお話ししました。
今回は、データ収集アプライアンスを開発する場合、Web UIで必ずといっていいほど求められる「データの可視化(グラフ化)」に焦点をあてます。Aloneに標準で付属している軽量グラフ描画ライブラリ 「AlGraph」の設計思想と、特に現場で重宝する「対数グラフ」の実装についてご紹介します。
Abstract
Aloneに標準で付属する軽量グラフ描画ライブラリ「AlGraph」を紹介します。 サーバーサイドでPure Rubyにより劣化のないSVGを出力することで、外部ライブラリを一切排除しつつ、レポートや論文などの文書・スライドにそのままコピー&ペーストして再利用できる極めて高品位なグラフ表示を、シンプルな構成で実現します。
はじめに
データ収集アプライアンス(データロガーや監視用ゲートウェイなど)を開発する際、取得した時系列データをWeb画面上でグラフ表示したいケースは多々あります。
ウェブブラウザにCanvas機能が実装された頃から、クライアントサイド(JavaScript)でグラフを描画することができるようになりました。しかし、そこから「グラフ画像をレポートや論文、発表スライドに貼り付けたい」となったとき、クライアントサイド描画では画面から画像として出力・保存する追加の実装コストが発生したり、保存時にビットマップ画像(PNGなど)に変換されることで印刷や拡大時にぼやけて画質が劣化したりするという実務上の問題に直面します。
AlGraphは、これに対するAloneなりの明快な回答として、「サーバーサイドでPure RubyによりSVG(XML)を直接出力する」 というアプローチを採用しています。これにより、美しく劣化しないグラフデータを極めてシンプルに生成・再利用することが可能です。
AlGraphがサポートするグラフ表現
実務で求められるデータの種類や可視化の目的に応じて、AlGraphは標準で以下のグラフ描画に対応しています。外部ライブラリを一切追加することなく、用途に応じたファイルを require するだけで使い分けることができます。
- 折れ線グラフ / 棒グラフ (require 'al_graph')
- 基本となるクラス AlGraph を用いて、時系列変化やカテゴリごとの比較を直感的に描画します。
- 円グラフ (require 'al_graph_pie')
- 内訳やシェアの可視化に適した、組み込みWebでのステータス割合表示などに役立つ表現です。
- 散布図 (require 'al_graph_scatter')
- 2変数の相関関係をプロットするのに最適です。
- 対数グラフ(片対数・両対数)
- 軸オブジェクトに
.logarithmic()メソッドを実行すると対数軸になります。 - 測定データのレンジが広い計測用途に必須のグラフです。
- 軸オブジェクトに
開発の背景:なぜサーバーサイドSVG(ベクター)生成なのか?
Web画面上のグラフを業務レポート、学術論文、あるいはプレゼン用のスライド(PowerPoint等)に転載したいというニーズは、研究開発や生産現場において非常に強力です。
しかし、多くのモダンなJSグラフライブラリ(Chart.jsなど)はHTML5の Canvas を使ってグラフを描画します。Canvasは本質的に「ビットマップ」であるため、以下の課題が生じます。
- 画質の劣化: ブラウザ上で綺麗に見えていても、拡大してWordやPowerPointに貼り付けた際に文字や線がぼやけてしまう。
- 保存の手間: ブラウザ上で描画されたCanvasをファイルとして保存するには、別途JSでエクスポート用の処理(Data URLへの変換やダウンロード処理)を実装しなければならない。
これに対し、AlGraphが採用する SVG (Scalable Vector Graphics) は「XMLテキストによるベクターデータ」です。SVGをサーバー側(Ruby)でテキストとして出力し、それをHTMLに埋め込むアプローチには、他にはない圧倒的なメリットがあります。
「ベクターデータなので、どれだけ拡大・縮小しても、他ツールにコピー&ペーストしても、線や文字が一切劣化しない」
ブラウザに表示されたSVGコードをそのままコピーする、あるいはSVG画像としてダウンロードすれば、IllustratorやOfficeドキュメント(Word、PowerPointなど)に劣化ゼロのベクター画像としてそのまま取り込むことができます。印刷品質が求められるレポートや学術論文への引用に、これほど最適な形式はありません。
しかもサーバー側(組み込み機器側)には、画像処理用の重いCライブラリ(GDやImageMagickなど)も、日本語フォントファイルも一切不要。Pure Rubyの文字列処理だけでこの最高品質のグラフデータを出力できるのが、AlGraphの最大の強みです。
技術的特徴:AlGraphがもたらす「再利用性」と「確実さ」
1. 外部Gem・外部ライブラリへの依存ゼロ
Aloneの基本思想と同様、AlGraphも外部のGemに依存しません。標準ライブラリとAlGraphのコードさえあれば動作するため、インターネットに接続できない閉じた開発・製造環境でも、ソースを配置するだけで確実に動かすことができます。
2. シンプルな記述と柔軟な出力
折れ線グラフや棒グラフを描画する場合、使い方は直感的です。
require 'al_graph'
ydata1 = [ 5, 3, 6, 3, 2, 5, 6 ]
graph = AlGraph.new # オブジェクトの生成
graph.add_data_line(ydata1) # データのセット
# CGIとして標準出力に直接SVG(XML)を書き出す場合
graph.draw
# あるいは、変数にバッファリングしてHTMLテンプレートに埋め込む場合
# svg_code = graph.draw__buffer
出力は draw による直接出力と、draw_buffer による文字列バッファ取得の双方に対応しており、Aloneのコントローラ・ビュー構造の中に綺麗に収まります。
3. 優秀なオートスケール機能 - 「適当なデータ」でも「それなりの見栄え」に
グラフを描画する際に意外と実装が面倒なのが、データに応じた「軸の最大値・最小値や、目盛り間隔(スケール)の計算」です。
AlGraphは軸のオートスケールロジックが非常に優秀に作られており、与えられた入力データのレンジを判別し、美しく読みやすい目盛り間隔を自律的に割り出してくれます。
開発者が事前に最大値を探すループ処理を書いたり、表示用の余白(マージン)を計算したりする必要はありません。センサーから上がってきた生の配列データを適当に放り投げるだけで、自動的に「それなりに整った、見栄えの良いグラフ」として破綻なく表示してくれます。この手軽さは、プロトタイプ開発時や急ぎの可視化要件において大きな威力を発揮します。1
トレードオフ:クライアントサイド(JS) vs サーバーサイド(AlGraph)
可視化のアプローチについて、再利用性と運用の観点からメリット・デメリットを整理します。
| 評価軸 | クライアントサイド(Chart.js等) | サーバーサイド(AlGraph) | 組み込み・研究開発での評価 |
|---|---|---|---|
| 描画の実体 | 主にCanvas(ビットマップ) | SVG(ベクターデータ) | 解像度非依存のメリット。 拡大・縮小でも線や文字が一切ぼやけない。 |
| レポート・論文への転載 | 画像としての保存・抽出にJSの実装コストがかかる | HTML内のSVGをそのままコピー・保存可能 | 極めて実用的。 OfficeやLaTeXにベクター形式のまま直接貼り付け可能。 |
| 依存関係とデプロイ(保守性) | 外部JSの読み込み、資産管理が必要 | Rubyコード(ファイルを置くだけ) | 運用の手間を最小化。 ネットワーク隔離環境での設置や、超長期の保守管理に最適。 |
| 動的な操作性 | 非常に高い(アニメーション, ホバー等) | 低い(基本は静止画、リンク埋め込みは可) | インタラクティブ性重視ならJS。 ただし印刷や文書引用が前提なら、静的SVGで必要十分。 |
組み込み・計測エンジニアに刺さる「対数グラフ(ログスケール)」への対応
センサーデータの可視化において、値の範囲が数桁〜数十桁に及ぶケース(音響データ、振動、通信の電波強度、暗電流の推移など)では、通常の直線軸(リニアスケール)では微小な変化が潰れてしまい、役に立ちません。そこで必要になるのが対数グラフ(ログスケール)です。
AlGraphは、この対数グラフの描画を強力にサポートしており、作成した美しい対数グラフをそのまま劣化なしでレポートに移植できます。
1. 基本的な片対数グラフ
Y軸を対数軸にするには、軸オブジェクトに対して .logarithmic() を呼び出すだけです。
graph = AlGraph.new
graph.y_axis.logarithmic() # Y軸を対数スケールに設定
graph.add_data_line([ 0.1, 1, 10, 100 ])
graph.draw
これだけで、デフォルトでは10倍(10の階乗)ごとの目盛りが自動計算され、広大なレンジのデータを1つのグラフに綺麗に収めることができます。
2. 実務で助かる「異常値(0・マイナス・nil)の自動排除」
対数( $\log_{10}(x)$ )の数学的な定義(真数条件 $x > 0$)の制約により、0 以下の値や計算不能なデータ(nil)が入力されるとエラーになってしまいます。実際の運用では、センサーの瞬断やノイズによって nil や 0 がデータに混入することは日常茶飯事です。
AlGraphでは、データ内に 0、マイナス値、nil が含まれていた場合、ライブラリ側が自動的にそれを「異常値」として描画対象から排除(無視)してくれます。開発者が事前に配列をループで回してバリデーションをかける泥臭い前処理コードを書く必要はありません。
3. 目盛り間隔のカスタマイズ
自動計算される目盛りだけでなく、実業務の仕様に合わせて [1, 2, 5] といった任意のインクリメントを指定することも可能です。
# 1, 2, 5 単位での目盛り間隔を指定
graph.y_axis.interval = [1, 2, 5]
4. Y2軸(右側軸)の対数化
メインのY軸(左側)は通常の直線軸で物理量を表示し、第2Y軸(右側)を対数軸にして別の指標を重ね合わせる、といった高度なレイアウトも1行で設定できます。
# 右側の第2Y軸のみを対数スケールにする
graph.y2_axis.logarithmic()
5. 両対数グラフへの応用
X軸・Y軸の双方が対数となる「両対数グラフ」が必要な場合は、AlGraphXY クラスを使用することで、双方の軸に .logarithmic() を適用可能です。
# 両対数グラフの構築
graph = AlGraphXY.new
graph.x_axis.logarithmic()
graph.y_axis.logarithmic()
まとめ:システムをすべて「自分の制御下」に置き続けるということ
前回の記事でも強調しましたが、組み込み機器のWeb UI開発において最優先されるべきは、流行りのリッチな画面遷移ではなく、「何年経っても、どんな環境でも、確実に、同じように動き続けること」です。
そして、そのシステムから生み出される「計測データ」や「グラフ」が、劣化のないベクターデータ(SVG)としていつでも簡単にレポートや論文へと再利用できるという価値は、現場のエンジニアや研究者にとってこの上ない実用性をもたらします。
- 拡大・縮小しても劣化せず、他ツールへコピペ可能な高品質SVG
- 依存Gemなし、外部Cライブラリ不要(Pure Ruby)
- 0やnilを自動排除してくれるタフな設計
- 組み込み・計測に必須な対数軸を標準サポート
- 適当なデータ入力でも綺麗なスケールを描き出す優秀なオートスケール
「フルスタックの重厚なWebフレームワークを載せるリソースはない。それでも、綺麗で正確なグラフ画面をサクッと実装したい。なおかつ、生成したデータを美しいドキュメントとして再利用したい。」
そんな現場の極めて切実かつ実用的な要件に対して、AlGraphは今もなお、最高に「ちょうどいい」選択肢であり続けています。
参考リンク
-
もちろん、オートスケールを止めてプログラムから指定することも出来ます。 ↩


