📈

dash-cytoscapeで可視化する重みをつけた最短経路問題を書く

2020/12/01に公開

この記事で作りたいもの

環境

  • Google Coraboratory
    • Python 3.6.9
      • dash 1.17.0
      • dash-cytoscape 0.2.0
      • jupyter-dash 0.3.1
      • pandas 1.1.4

手順

1. 必要ライブラリのインストール

今回のメインとなるdashとdash-cytoscape、Webフレームワークでもあるdashを、JupyterのようなNotebook StyleのGoogle Coraboratoryでも、インラインで扱うことが可能なjupyter-dashをインストールします

pip install dash jupyter-dash dash-cytoscape

注意:jupyter-dashは、dashに比べて内部エラーの原因究明があまりできません。思い当たったら、生dashで試してみてください

2. JupyterDashの初期化

本来、dashにはlayoutやcallbackなどの機能があります。今回使用するのはlayoutだけですが、これらを設定するためにも、まずは本体の定義・初期化が必要です。

app = JupyterDash()

3. グラフの定義

グラフ(ツリーグラフやDAG)は、ライブラリによって様々な記述方法があります(隣接行列表現など)が、今回dash-cytoscapeで使用する形式はオブジェクト形式で割と独自系です。
2 ~ 7行目でノードの定義。8行目以降で、ノードとノードを繋ぐ線(エッジ)の定義をしています。weightは、そのエッジの重みと言って、作業量などを考慮して最短経路問題など解く際に使用されます。

elements = [
    {'data': {'id': 'A'}},
    {'data': {'id': 'B'}},
    {'data': {'id': 'C'}},
    {'data': {'id': 'D'}},
    {'data': {'id': 'E'}},
    {'data': {'id': 'F'}},
    {'data': {'id': 'AC', 'weight': 5, 'source': 'A', 'target': 'C'}},
    {'data': {'id': 'AB', 'weight': 3, 'source': 'A', 'target': 'B'}},
    {'data': {'id': 'BD', 'weight': 1, 'source': 'B', 'target': 'D'}},
    {'data': {'id': 'BE', 'weight': 2, 'source': 'B', 'target': 'E'}},
    {'data': {'id': 'CD', 'weight': 7, 'source': 'C', 'target': 'D'}},
    {'data': {'id': 'CE', 'weight': 2, 'source': 'C', 'target': 'E'}},
    {'data': {'id': 'DF', 'weight': 4, 'source': 'D', 'target': 'F'}},
    {'data': {'id': 'EF', 'weight': 5, 'source': 'E', 'target': 'F'}}
]

4. 可視化

JupyterDash(dash)を使ってグラフの可視化をします。今回は参考文献1にもある、dash-cytoscape公式のusage-pie-style.pyを参考にさせていただきました。

過不足

  • エッジの重み(今回は値に加えて、矢印の太さで表現したい)の表現が足りない
  • ノードの円グラフいらない
    いろいろ削除すると下記のような記述となります。
    'selector': 'edge'の中の'label': 'data(weight)'と'width': 'data(weight)'でエッジのラベルと太さ調整を可能にしています
app.layout = html.Div([
    cyto.Cytoscape(
        id='cytoscape',
        elements=elements,
        layout={
            'name': 'circle',
            'padding': 10
        },
        stylesheet=[{
            'selector': 'node',
            'style': {
                'width': '60px',
                'height': '60px',
                'content': 'data(id)',
                }
        }, {
            'selector': 'edge',
            'style': {
                'curve-style': 'bezier',
                'label': 'data(weight)',
                'width': 'data(weight)',
                'target-arrow-shape': 'triangle',
                'opacity': 0.5
            }
        }],
        style={
            'width': '100%',
            'height': '100%',
            'position': 'absolute',
            'left': 0,
            'top': 0
        }
    )
])

起動

インラインで起動しましょう

app.run_server(mode="inline")

付録・参考文献

  1. dash-cytoscape/usage-pie-style.py at master · plotly/dash-cytoscape
  2. 今回作成したColab Notebook
  3. 2のGithub Link
  4. dash-cytoscape/Cytoscape.py at master · plotly/dash-cytoscape
  5. jupyter-dash/getting_started.py at master · plotly/jupyter-dash

まとめ

dash-cytoscapeのexampleなどを眺めてもエッジの太さが変えられる例はありませんでしたが、文字列の中にしこむdata関数にキーを入れるという手法は、元々exampleでちらほら記述されていたので、比較的簡単な突破口と言えます。zenn初投稿の2020/12/1ですが、これから毎日更新していければと思います。

Discussion