さて、Cytoscape関係の4本目です。 1〜3本目はこちら↓
- ネットワーク可視化ツール「Cytoscape」に雑に入門して手っ取り早く使う話
- ネットワーク可視化ツール「Cytoscape」を自動操作して楽する話—PowerShellでCyREST-APIを叩く—
- ネットワーク可視化ツール「Cytoscape」で描いた大きな図を印刷する話—CyREST+ImageMagic+Acrobat Reader=∞—
2本目の記事で、CytoscapeのAPIを Powershellで叩く話を書きましたが、セキュリティ設定なんかの関係で、たとえば他の人に使ってもらいたい時には不便です。
あと、GUIが欲しいって時、PowershellでもGUIを作ることはできるようですが、そもそもPowershell自体使い慣れていないので、少し敷居が高いです。
そこで、面倒な環境構築が不要で、プラットフォームも気にせず使えるhtmlとjavascriptを使って、簡単にCytoscapeの拡張GUIを作る方法を思いついたので、ここで紹介します。
javascriptからCyREST APIを叩く方法
さて、javascriptからHTTPリクエストを送るには、XMLHttpRequest
という関数を使います。
この関数を使えば、クロスドメインで非同期通信ができるので、今回のようにローカルで開いたhtml ファイルから、Webサーバー上のCyREST-APIを叩くような使い方もできます。
さらに、CytoscapeからはJson形式の返事がくるので、Javascriptならそのままオプジェクトとして扱えます。楽ちんです。
さっそく試してみる
例として、サンプルセッションの「Yeast Perturbation.cys」を使って、「選択中のエッジのEdgeBetweenness
の合計値をリアルタイムで表示する」というGUIを作ってみましょう。
非同期通信なので、1秒間隔でポーリングして、「ほぼリアルタイム」を目指します(Cytoscapeがツラそうだったら、もう少し頻度を下げます)。
ソースコード
解説はコードのコメントに書いてみました。 タイトルの通り、ひとつのhtmlファイルにまとめてあるので、テキストエディタに張り付け、UTF-8のhtmlとして保存すれば動くはずです。
お作法とかエラー処理とかは特に気にせず、とりあえず動くレベル。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> #result { font-size: 25pt; } </style> </head> <body> <div id="result">ここに結果が入ります。</div> <script> // 計算結果を表示する用のdivを取得 const result = document.getElementById("result"); // たまにメモリー解放してあげないと暴走するので、メモリ解放するコマンドを用意 const free_unused_memory = () => { const xhr = new XMLHttpRequest(); xhr.open('GET', 'http://localhost:1234/v1/gc'); xhr.send(null); } // とりあえずHTTPリクエストのとこ全部囲む const update = () => { // APIのリクエストボディを、Json文字列として用意する(書き方はCytoscapeのヘルプを参照) const request_body = JSON.stringify({ "columnList": "EdgeBetweenness", "edgeList": "selected", "network": "current" }); // xhrを使う準備 const xhr = new XMLHttpRequest(); // Edgeのアトリビュートを取得するAPI xhr.open('POST', 'http://localhost:1234/v1/commands/edge/get attribute'); // リクエストはJson形式で送る xhr.setRequestHeader('Content-Type', 'application/json'); // 返事はJson形式で解釈する xhr.responseType = 'json'; // HTTPリクエストに返事が来たときの処理 xhr.onload = () => { // 返事の中身を取り出して const response_body = xhr.response.data; // reduce関数でEdgeBetweennessを積算してtoFixedで小数点1桁表示 // 0を足しているのはnull値対策 const total_Betweenness = (response_body.reduce((acc, x) => acc + x.EdgeBetweenness, 0) + 0).toFixed(1); // テンプレートリテラルで結果のhtml文字列を作る const html = `選択中のEdgeは${response_body.length}本です。<br> EdgeBetweennessの合計は${total_Betweenness}です。`; // 結果をhtmlに書き込む result.innerHTML = html; } // HTTPリクエストを送信 xhr.send(request_body); // 10回毎にメモリ開放 if (update_count > 10) { free_unused_memory(); update_count = 0; } else { update_count++ } } // メモリ解放するタイミング用のカウンタ let update_count = 0; // 最初の1回はすぐに実行 update(); // あとは1秒間隔でアップデート setInterval(update, 1000); </script> </body> </html>
動いた!
htmlファイルをブラウザで開いてから、Cytoscapeでエッジを選択すると、すぐに集計結果が反映されます。
1秒間隔でも十分なレスポンスです、呼び出し頻度的にも特に問題は無さそう。
おまけ:ネイティブプラグイン風に表示する
CytoscapeにはWebブラウザが内蔵されているので、そこでhtmlファイルを開いて、あたかも本体に組み込まれた機能のような見た目にしてみましょう。
手で開くなら「Tools」→「Cytoscape Browser」で、file://
を付けたフルパスを入れ、「Open in results panel?」にチェックを入れます。
それか、APIからの操作で開く場合はこう。
POST http://localhost:1234/v1/commands/cybrowser/show { "id": "適当なID", "title": "タブに表示したいタイトル", "url": "file://htmlファイルのフルパス" }
するとこうなります、ちゃんとCytoscapeのウィンドウ内で動くので、まるでネイティブなプラグインのようです。
まとめ
今回は文字列を作って表示しただけですが、データさえ取れてしまえば、あとはもうjavascriptでやりたい放題です。
集計結果をテーブル表示したり、chart.jsのような可視化ライブラリを使ってグラフを描いたりと、夢が広がりますね!
それじゃ、今日はここまで。