Google API で数式とグラフを書く(TEX + Google Chart API + Google Visualization API)
ウェブページで数式を利用する(TEX表記)
ウェブページで数式を用いた情報発信を行おうとするとき、いつも問題になるのが式の取り扱いについてです。
HTMLでは複雑な数式を表現することができないため、gifなど図としてHTMLに埋め込むことが一般的に行われます。
その際に問題となるのが「どのようにして図を作るのか」ということです。
自分はこれまで「Equation Magic」というソフトを利用しています。
このソフトの利点は、「TEX表記」で式を出力でき、かつコピーアンドペーストでベクトルデータとして扱える点です。
Illustratorなどのベクトルデータを扱えるソフトと組み合わせることで、数式のあるプレゼン資料などを簡単に作成することができます。
WEBページで利用する場合も、Equation Magicでgifに出力できるので問題は無いのですが、手間がかかることが唯一の欠点でした。
本稿で紹介するのは、HTMLソースに直接TEX表記で式を書くことで、google API が図にしてくれるという google が提供するサービスです。
ブラウザの拡張機能やインストールなどは一切必要ありません。HTMLのimgタグのsrcの特定の箇所にTEX表記で式を書くだけです。
つまり、式の gif 化が一切要らなくなるということです。
上の式が google API を利用したものです。図そのものは google のサーバ上で動的に作られ、それをユーザのブラウザにダウンロードしているという流れです。つまり、ネットに接続されていないローカル環境では、図をダウンロード使えません。 唯一の欠点は、URLの中にTEX表記を埋め込むため、URLエンコーディングが必要となる点です。 下のサンプルでは、PHPを利用してURLエンコーディングを行なっています。
<img src="http://chart.apis.google.com/chart?cht=tx&chs=1x0&chf=bg,s,FFFFFF00&chco=000000&chl= <?php print urlencode(" \bar{H}_{n+2}(x) = \sqrt{\frac{2}{n+2}} x \bar{H}_{n+1}(x) \sqrt{\frac{n+1}{n+2}} \bar{H}_n(x) "); ?> " alt=""/>
javascript などでも実現できると思います。 毎回サンプルのような HTML は書きたくないので、次のようにPHPの関数を定義します。
<?php function WriteEquation( $tex ){ $str = trim($tex); $str = str_replace("\r", "\\r", $str); $str = str_replace("\t", "\\t", $str); $str = str_replace("\n", "\\n", $str); $str = urlencode($str); print " <img src=\"http://chart.apis.google.com/chart?cht=tx&chs=1x0&chf=bg,s,FFFFFF00&chco=000000&chl= " . $str . "\" alt=\"$tex\"/>"; } ?>
そして、式を埋め込みたいところに
<?php WriteEquation(" \bar{H}_n(x) \equiv = \frac{1}{\sqrt{2^nn!\,\sqrt{\pi}}}\, H_n(x) \,e^{-\frac{x^2}{2}} ") ?>
と、TEX表記で式を書くだけです。これで手間が軽減されました。
【参考】
・Google Chart APIを使って数式を埋め込む - Hello, world! - s21g
ウェブページでグラフを利用する(javascript)
グラフも式と同様、科学系の情報発信を行う際には欠かせない要素です。 自分はこれまで、gnuplot で描画した後に gif で出力し、HTML で利用するという手順でした。 本稿で紹介するのは、上の式と同様に google API を利用して、javascriptで動的にグラフを描画することのできるサービスです。
上の図は規格化したエルミート多項式を動的に描画しました。 グラフの上にマウスポインタを持って行くと、座標が表示されるといった具合です。 各座標 x に対して漸化式をjavascriptを用いて計算して、その結果を描画しています。 つまり、数値計算と描画を同時に行える点が魅力的です。
<script type="text/javascript" src="http://www.google.com/jsapi"></script> <script type="text/javascript"> google.load("visualization", "1", {packages:["corechart"]}); google.setOnLoadCallback(drawVisualization); function NormalizedHermite (n, x ) { var y0, y1, y2; y0 = Math.sqrt(1.0/Math.sqrt(Math.PI)) * Math.exp(-Math.pow(x,2)/2.0); if( n==0 ) return (y0); y1 = Math.sqrt(2.0/Math.sqrt(Math.PI)) * Math.exp(-Math.pow(x,2)/2.0) * x; if( n==1 ) return (y1); for(var m = 2; m<=n; m++ ){ y2 = Math.sqrt(2.0/m) * x * y1 - Math.sqrt((m-1)/m) * y0; y0 = y1; y1 = y2; } return (y2); } function round(n, x) { return( Math.round(x*Math.pow(10, n))/Math.pow(10, n)); } var keta = 3; function drawVisualization() { var data = new google.visualization.DataTable(); data.addColumn('number', 'X'); data.addColumn('number', 'n=0'); data.addColumn('number', 'n=1'); data.addColumn('number', 'n=2'); data.addColumn('number', 'n=3'); data.addColumn('number', 'n=4'); data.addColumn('number', 'n=5'); data.addColumn('number', 'n=6'); data.addColumn('number', 'n=7'); data.addColumn('number', 'n=8'); data.addColumn('number', 'n=9'); data.addColumn('number', 'n=10'); var x; var y; var n_max = 500; var x_max = 20.0; data.addRows(n_max+2); for (var n =0; n<=n_max ; n++){ x = -x_max/2.0 + x_max * n /n_max; data.addRow([round(keta, x), round(keta, NormalizedHermite(0,x)), round(keta, NormalizedHermite(1,x)+1), round(keta, NormalizedHermite(2,x)+2), round(keta, NormalizedHermite(3,x)+3), round(keta, NormalizedHermite(4,x)+4), round(keta, NormalizedHermite(5,x)+5), round(keta, NormalizedHermite(6,x)+6), round(keta, NormalizedHermite(7,x)+7), round(keta, NormalizedHermite(8,x)+8), round(keta, NormalizedHermite(9,x)+9), round(keta, NormalizedHermite(10,x)+10)]); } var chart = new google.visualization.ScatterChart( document.getElementById('drow2')); chart.draw(data, {title: '規格化エルミート多項式', width: 600, height: 700, pointSize: 1, vAxis: {title: "Y", minValue: 0, maxValue: 10, titleTextStyle: {color: "black"}}, hAxis: {title: "X", minValue: 0, maxValue: 10, titleTextStyle: {color: "black"}}} ); } </script>
上のサンプルは、google APIの内「Scatter Chart」と呼ばれる散布図を利用しています。 このAPIの欠点は、今のところ科学用のグラフではないことです。 特に横軸や縦軸のメモリの付け方などの自由度が低く、思い通りのグラフに仕上がらない点です。 (例えば、x軸のメモリの刻み幅を変えられないなど) もし、gunuplot 並に指定できればかなり有用なツールとなるでしょう。
【参考】
・Visualization: Scatter Chart - Google Chart Tools - Google Code