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



