HTML ＋ Javascript ＋ cyREST-API でデスクトップ版Cytoscape用の拡張GUIを手軽に作る方法

日頃からQiitaにはお世話になっているので、ブログに書いた内容のうち、過去の自分が欲しかった情報（動かすのに必要な部分）を要約してご紹介します。

元のブログ記事はこちらです。
[ネットワーク可視化ツール「Cytoscape」の拡張GUIを、htmlファイル1つでお手軽に作る話](https://www.creativity-ape.com/entry/2020/01/21/070000)

Cytoscape自体の使い方についても書いているので、よかったら参考にしてみてください。
[ネットワーク可視化ツール「Cytoscape」に雑に入門して手っ取り早く使う話](https://www.creativity-ape.com/entry/2019/02/16/080000)

## 概要

HTML＋Javascriptから、XMLHttpRequest（xhr）を使ってCyREST APIを叩く方法です。
デスクトップ版のCytoscapeに、お手軽に外付けのGUIを生やすことができます。

![](https://cdn-ak.f.st-hatena.com/images/fotolife/a/at_you_key/20200120/20200120234556.png)

例として、サンプルセッションの「Yeast Perturbation.cys」を使って、「選択中のエッジの`EdgeBetweenness`の合計値をリアルタイムで表示する」GUIをつくってみました。

右のウィンドウがそれです。

![](https://cdn-ak.f.st-hatena.com/images/fotolife/a/at_you_key/20200120/20200120202613.gif)


Cytoscapeで上記サンプルセッションを開いたうえで、下のソースコードをUTF-8のHTMLとして保存して、IE以外のブラウザで開いてください。

Shift＋ドラッグでエッジを複数選択すると、ほぼリアルタイムで集計値が表示されます。

## ソースコード

ソースコードの説明は、コード内のコメントを参照ください。

HTMLもJavascriptもCytoscapeも専門外なので、品質は保証できませんが、狙い通り動くことは確認済みです。

```html:cy.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>
```

## おまけ
- リクエストJsonの`"columnList"`の値は、カンマ区切りで複数アトリビュートを指定することもできます。
- この例では結果を文字列として表示しただけですが、集計データをChart.jsなどでリアルタイムにグラフ化するような使い方もできると思います。
- [ブログ](https://www.creativity-ape.com/entry/2020/01/21/070000)には、このHTMLをCytoscapeのウィンドウ内で開く方法も書いてあるので、よかったら覗いてみてください。