2月 2009のアーカイブ
Ubiquityを使って英単語を調べる
FireFoxのプラグインでUbiquityというのがあります。他のWebサイトの機能をコマンドとして登録して使用できる、User MashUpを可能にするFirefox上の環境です。将来的にはFirefoxのURLバーに実装されるかも知れません(URLをWebのドキュメントがある場所であると考えるのではなく、Web上のリソースに対するリクエストような考えると割と自然な進歩?)。
ブラウザの新境地? Ubiquityが変える衝撃のブラウザ体験 (1/2):
http://www.itmedia.co.jp/enterprise/articles/0808/31/news003.html
まあ、そういうわけでどういうものかちょっと気になって見てみて、最近APIが公開されたiknowという英語学習SNSの単語検索を呼び出すコマンドを作成してみました。
コード
CmdUtils.CreateCommand({
name: "iknow_search",
icon: "http://example.com/example.png",
homepage: "http://example.com/",
author: { name: "xxxx", email: "xxxxx@gmail.com"},
license: "GPL",
description: "search words or pharase in iknow",
help: "iknow",
takes: {"input": noun_arb_text},
preview: function( pblock, input ) {
var baseUrl = "http://api.iknow.co.jp/items/matching/${word}.${format}";
var tempUrl = {"word":input.text,"format":"json"}
var params = {include_sentences:"true"};
pblock.innerHTML = "";
jQuery.getJSON(CmdUtils.renderTemplate(baseUrl,tempUrl),params,function(resp){
jQuery.each(resp,function(i){
pblock.innerHTML += this.responses[0].text + "<br/>";
pblock.innerHTML += this.sentences[0].text + "<br/>";
pblock.innerHTML += this.sentences[0].translations[0].text + "<br/>";
});
});
},
execute: function(input) {
var baseUrl ="http://www.iknow.co.jp/items/search?keyword=${QUERY}";
var tempUrl = {"QUERY":input.text};
var urlString = CmdUtils.renderTemplate(baseUrl, tempUrl);
Utils.openUrlInBrowser(urlString);
}
});
Ubiquityコマンドの作成
Ubiquityコマンド作成の情報は、現状下記のリンクかソースを見るしかないくらい少なく、しかも上記のコマンドはまだプレビューで訳を表示しEnterキーでiKnowのサイトで該当のアイテム検索結果を表示するのみですが、行数の割には用を足しているかと思います。Ubiquity導入後、Command Editorを使用して上記のコードを貼付ければ使用できます。
Labs/Ubiquity/Ubiquity 0.1 Author Tutorial
https://wiki.mozilla.org/Labs/Ubiquity/Ubiquity_0.1_Author_Tutorial
上のチュートリアルに載っている事ですが簡単に作り方を説明したいと思います。
CmdUtils.CreateCommand({
name: "hello-world",
execute: function() {
displayMessage( "Hello, World!" );
}
})
ubiquityコマンドは、cmd_<コマンド名>というfunctionがあればそれを参照するのですが、普通はCmdUtils.CreateCommand()というユーティリティ関数を使用して作成します。上記のコードはその最も単純な例です。
CreateCommandに渡すオブジェクトのnameとexecuteというプロパティに、それぞれコマンド名の文字列と実行する関数を指定します。execute(コマンドの実行)はUbiquityのコンソールにコマンド名を入力しEnterを押した時点で実行されます。displayMessage()を実行すると、MacならGrowl,WindowsならUbiquityのコマンドの下に引数に与えた文字列が表示されます。
CmdUtilsにはコマンド作成以外にも、ユーザーがブラウザで選択中の箇所にテキストやHTMLを挿入(setSelection),IPから位置情報を取得(getGeoLocation),文字列のテンプレート処理(renderTemplate)などコマンド作成を楽にする関数が用意されており、これまたドキュメントは少ないのですが、ソースはこちらで見る事ができます。
プレビューの表示
Ubiquityではユーザーの入力に応じて出力されるプレビューウインドウがあり、こちらはCreateCommandに渡すオブジェクトのpreviewプロパティに、HTML文字列か関数を指定する事で実現できます。下記は冒頭のコマンドでのpreview部分です。
preview: function( pblock, input ) { var baseUrl = "http://api.iknow.co.jp/items/matching/${word}.${format}"; var tempUrl = {"word":input.text,"format":"json"} var params = {include_sentences:"true"}; pblock.innerHTML = ""; jQuery.getJSON(CmdUtils.renderTemplate(baseUrl,tempUrl),params,function(resp){ jQuery.each(resp,function(i){ pblock.innerHTML += this.responses[0].text + "<br/>"; pblock.innerHTML += this.sentences[0].text + "<br/>"; pblock.innerHTML += this.sentences[0].translations[0].text + "<br/>"; }); }); },.....
previewは第一引数にpreviewエリアに表示するDOM要素を、第二引数にユーザーから渡されるコマンドの引数をとっています。コマンドの引数はtakeプロパティで、どのnoun_typeで取得するか指定できます。
takes: {"input": noun_arb_text},
引数データの扱い
noun_typeは引数の制約や、コマンドの補完機能(例えば日付データが入力されたら、日付データを引数にとるコマンドをUbiquityがサジェストする)に使用され、下記のようなnoun_typeがあります。また、CmdUtilsを使用してカスタムのnoun_typeを作成する事ができます。
- noun_type_arb_text
- noun_type_date
- noun_type_language
- noun_type_people
- noun_type_place
- noun_type_tab
noun_typeのソースは下記で確認する事ができます
nountypes.js
一方、コマンドの引数としてpreviewやexecute(の第二引数)に渡されるオブジェクトは、下記のようなプロパティを持ちます。
- inputObject.text // 文字列
- inputObject.html //タグを含む整形されたHTML
- inputObject.data // 文字列以外のnoun_typeのデータ
- inputObject.summary // 長い文字列の要約版
iknow-searchのpreviewで行っているのは、コマンドの引数から(テンプレート機能を使用して)URL文字列を組み立て、JSONでリクエストを取得、preview用のDOMに結果を反映するという一連の処理ですが、uqibuityではjQueryが使用できるため簡単に実装できます。
また同様に、コマンド入力後Enterを押した時に実行されるexecuteでは、Utils.openUrlInBrowser()を使用してブラウザで該当のURL(検索結果ページ)を開くようになっています。
まだまだ発展途上(というかできたばかり)のコンセプトですが、Webの機能をお手軽にコマンドにできるのはこれから重宝しそうです。
追記:Ubiquity のアップデートに合わせて、コードも少し書き換えました
Processingでグラフ
前から少し気になっていたProcessingという言語について、ちょうど本屋におもしろそうなオライリー本が出ていたので買ってみました。
ビジュアライジング・データ ―Processingによる情報視覚化手法
簡単な例としてグラフの作成があったので、自分でも日本の人口統計を使ってグラフを書いてみました。

Population growth in Japan
-
FloatTable data;
-
PFont plotFont;
-
float plotX1,plotY1;
-
float plotX2,plotY2;
-
float labelX,labelY;
-
float dataAreaWidth;
-
float dataAreaHeight;
-
final float dataOffsetY = 30;
-
float volumnInterval = 10000;
-
float dataCeil;
-
int []years;
-
int yearMin;
-
int yearMax;
-
int yearInterval;
-
float dataMin;
-
float dataMax;
-
void setup(){
-
plotFont = createFont(“SansSerif”,20);
-
textFont(plotFont);
- //load csv file
-
data = new FloatTable(“ppl1920-1990-grs-t.csv”);
-
years = int(data.getRowNames());
-
yearMin = years[0];
-
yearMax = years[years.length -1];
-
yearInterval = 10;
-
dataMin = data.getColumnMin(0);
-
dataMax = data.getColumnMax(0);
-
println(ceil(dataMax/volumnInterval));
-
dataCeil = ceil(dataMax/volumnInterval) * volumnInterval;
-
size(600,400);
-
smooth();
-
plotX1 = 160;
-
plotY1 = 80;
-
plotX2 = width - plotX1/2;
-
plotY2 = height - plotY1;
-
labelX = plotX1 -110;
-
labelY = plotY2 +40;
-
dataAreaWidth = plotX2 - plotX1;
-
dataAreaHeight = plotY2- plotY1;
-
}
-
-
void draw(){
-
background(022); // (1)background color
-
fill(044);
-
rectMode(CORNERS);
-
noStroke();
-
rect(plotX1,plotY1,plotX2,plotY2);
-
strokeWeight(0.4);
-
stroke(254);
-
drawDataArea();
-
stroke(112);
-
strokeWeight(0.1);
-
drawLabels();
-
}
-
void drawLabels(){
-
drawTitleLabel();
-
drawAxisLabels();
-
drawYearLabels();
-
drawYearGrid();
-
drawVolumnLabels();
-
}
-
-
void drawTitleLabel( ) {
-
fill(112);
-
textSize(15);
-
textAlign(CENTER,CENTER);
-
text(“Population growth in Japan\n 1920 to 2000″,(plotX1+plotX2)/2,plotY1 - 40);
-
}
-
-
void drawAxisLabels( ) {
-
fill(112);
-
textSize(13);
-
textLeading(15);
-
textAlign(CENTER, CENTER);
-
text(“Total \npopulation\n(Thousand)”, labelX, (plotY1+plotY2)/2);
-
textAlign(CENTER);
-
text(“Year”, (plotX1+plotX2)/2, labelY);
-
}
-
void drawYearLabels(){
-
fill(112);
-
textSize(12);
-
textAlign(LEFT);
-
int rowCount = data.getRowCount();
-
for(int i=0;i < rowCount;i++){
-
if(years[i] % yearInterval ==0){
-
String yearText = data.getRowName(i);
-
float x = map(int(yearText),yearMin,yearMax,plotX1,plotX2);
-
text(yearText,x,plotY2+12);
-
}
-
}
-
}
-
void drawYearGrid(){
-
int rowCount = data.getRowCount();
-
for(int i=0;i < rowCount;i++){
-
if(years[i] % yearInterval ==0){
-
float x = float(data.getRowName(i));
-
x = map(x,yearMin,yearMax,plotX1,plotX2);
-
line(x,plotY2,x,plotY1);
-
}
-
}
-
}
-
void drawVolumnLabels(){
-
fill(112);
-
textSize(10);
-
textAlign(RIGHT);
-
float x = plotX1;
-
float y;
-
for(float v = floor(dataMin/volumnInterval)*volumnInterval;v <= dataCeil;v+= volumnInterval){
-
y = map(v,floor(dataMin/volumnInterval)*volumnInterval,dataCeil,plotY2,plotY1);
-
line(x-10,y,x,y);
-
//println(v);
-
text(floor(v),x-20,y+4);
-
}
-
}
-
void drawDataArea(){
-
beginShape();
-
int rowCount = data.getRowCount();
-
for(int i=0;i < rowCount;i++){
-
float value = data.getFloat(i,0);
-
float x = map(years[i],yearMin,yearMax,plotX1,plotX2);
-
float y = map(value,floor(dataMin/volumnInterval)*volumnInterval,dataCeil,plotY2,plotY1);
-
vertex(x,y);
-
}
-
endShape();
-
}
-
void keyPressed( ) {
-
saveFrame(“japan_pl_##.png”);
-
}
processing実行後に何かキーを押すと、連番で”japan_pl_01.png”という画像が保存されます。FloatTableというクラスは本のサンプルコードに含まれているものですが、http://benfry.com/writing/archives/3 からダウンロードできます。人口のCSVは統計局からダウンロードしたものをタブ区切りのcsvにしてます。
こんな感じで
-
Year Total
-
1920 55963
-
1921 56666
-
1922 57390
-
1923 58119
-
1924 58876
-
1925 59737
-
1926 60740.9
-
1927 61659.3
-
1928 62595.3
-
1929 63460.6
-
1930 64450
-
1931 65457
-
1932 66434
-
1933 67432
-
1934 68309
-
1935 69254
-
1936 70114
-
1937 70630
-
1938 71013
-
1939 71380
-
1940 71933
-
1941 71933
-
1942 71933
-
1943 71933
-
1944 73064
-
1945 71998
-
1946 73114
-
1947 78101
-
1948 80002
-
1949 81773
-
1950 83200
-
1951 84573
-
1952 85852
-
1953 87033
-
1954 88293
-
1955 89276
-
1956 90259
-
1957 91088
-
1958 92010
-
1959 92973
-
1960 93419
-
1961 94285
-
1962 95178
-
1963 96156
-
1964 97186
-
1965 98275
-
1966 99054
-
1967 100243
-
1968 101408
-
1969 102648
-
1970 103720
-
1971 105014
-
1972 107332
-
1973 108710
-
1974 110049
-
1975 111940
-
1976 110089
-
1977 114154
-
1978 115174
-
1979 116133
-
1980 117060
-
1981 117884
-
1982 118693
-
1983 119483
-
1984 120235
-
1985 121049
-
1986 121672
-
1987 122264
-
1988 122783
-
1989 123255
-
1990 123611
-
1991 124043
-
1992 124452
-
1993 124764
-
1994 125034
-
1995 125570
-
1996 125864
-
1997 126166
-
1998 126486
-
1999 126686
-
2000 126926
Processingを一言で説明しようとすると、Javaの描写機能を使用しやすいインタフェースで提供する言語環境(なのかな?)でしょうが、なんでProcessingに興味をもっていたかというと、これを使用した作品(っていうのがいいですね)に興味深いというか斬新なものが多かったからな訳です。
MusicBox: a truly powerful visualization of your music library:http://www.crunchgear.com/2008/12/15/musicbox-a-truly-powerful-visualization-of-your-music-library/
音楽のライブラリを可視化するソフト。ファイルのメタデータ(作者やジャンルなど)のみではなく、実際の音声データをスキャンしてマッピングする。
Aligning humans and mammals:http://benfry.com/infoseed/
人間とほ乳類の遺伝子配列をならべて描写した画像
Base26:http://toxi.co.uk/p5/base26/
英語の言葉同士の慣例性を表現した図。
仕事ではほとんどCRUDなWEBアプリケーションしか見ないのですが、こういうデータの重要性もさることながらどう見せるかでどれだけ印象や理解度が変わるかという事を考えるとおもしろい。色々遊んでみようと思います。


