[2021/11/16追記]Cytoscape3.9.0ではPDF出力の挙動が改善されていて、この記事の手間を掛けなくても、綺麗にエクスポートできるようになりました、ハッピー!
さて、またCytoscapeネタを1発。
これまでのあらすじ
一見操作が難しそうで取っ付き辛いCytoscapeでしたが、使い方の流れをつかんでしまえば意外と簡単に使えて、膨大なデータも思うがままに可視化できるようになりました。
続いて、REST-APIを使うことで操作を自動化して、手間をかけずにバンバン最新のネットワーク図を出せるようになりました、ってとこまでがこれまでの話。
そうして事件は起きました。
ことの発端
職場のひと「画面で見てもわかんないからさ、紙でちょうだいよ」
ぼく「……はい?」
うん、データの可用性よりも紙の温もりが重要な場面ってありますよね。
てなわけで、試行錯誤を重ねた末、Cytoscapeで作った巨大なネットワークビューを、なんとかきれいに印刷する手法を編み出したので、今日はそのノウハウを紹介しようと思います。
- これまでのあらすじ
- ことの発端
- やりたいこと
- そもそもどう印刷するのが良いのか?
- 使うツール
- やってみよう!
- CyREST-APIでPNG画像を書き出す
- ImageMagicで余白をトリミング
- ImageMagicでPNGをPDFに変換
- Acrobat Readerで分割印刷
- どうなったか
やりたいこと
要件をまとめるとこんな感じです。
- Cytoscapeで描いた大きなネットワーク図がある
- ここでいう「大きい」は、1000ノードくらいの規模です
- ラベル文字が見えるサイズで印刷したい、するとA0サイズくらいになる
- そんなでかいプリンター持ってないので、A3用紙8分割で印刷したい
- ゆくゆくは自動化できるように、GUI無しでできるとなお良し
そもそもどう印刷するのが良いのか?
基本的には、Cytoscapeから画像として書き出して、それを印刷するのが良さそうな感じです。
Cytoscapeから画像を書き出す方法はいくつかあって、それぞれなかなかクセが強めです。
PNG・JPEG
- ラスターデータなので解像度に限界がある
- ファイルサイズがちょっと大きい
- 拡大率が画面表示に依存する(後述します)
SVG
- ベクターデータなので解像度関係なく綺麗
- システムの時計が日本語設定だとタイムスタンプが文字化けして、書き出したそのままでは開けない
- テキストエディターとかでSJIS→UTF-8に変換すれば開ける
- 分割印刷するにはPDFにするしかない?
- こっちもベクターなので綺麗
- A4縦っぽいサイズ固定なので、横長のネットワーク図を出すとすごくイマイチな感じになる
- 分割印刷すると長い線が崩れる、致命的
Cytoscapeから直接印刷
- 細かい設定ができない
- たぶんPDF出力してデフォルト設定で印刷するのと同じ?
Postscript
- 扱いが面倒そうなので使いません
試行錯誤のあれこれを書くのは難儀なので、その辺は端折るとして、これらを弄り倒して導き出した、Cytoscape印刷のベストプラクティス(暫定)がこちら!
- ネットワーク図を高解像度のPNG画像として書き出す
- ImageMagicで余白をトリム&リサイズ
- ImageMagicでPDFに変換
- Acrobat Readerのポスター印刷で分割印刷
使うツール
今回使うツールはこちら
Cytoscape
- https://cytoscape.org/
- 言わずもがなですが、描いたネットワーク図をCyrestAPI経由でPNG画像として吐いてもらいます
ImageMagic
- https://imagemagick.org/
- Cytoscapeが吐く画像の加工とPDF変換に使います
Adobe Acrobat Reader DC
- https://get.adobe.com/jp/reader/
- 巨大なネットワーク図を簡単に分割印刷するために使います
やってみよう!
とりあえず、サンプルデータとして用意されている「Yeast Perturbation.cys」を使って試してみましょう。
CyREST-APIでPNG画像を書き出す
ネットワークIDを確認
まずは、書き出し対象のネットワークのIDが必要です。
表示中のネットワークのIDをAPIから確認するには
POST http://localhost:1234/v1/commands/network/get content-type: application/json {}
そうするとこんなレスポンスが帰ってきます。
{ "data": { "shared name": "MyNetwork", "name": "MyNetwork", "SUID": 52, "__Annotations": [], "selected": true }, "errors": [] }
"SUID"ってのがIDですね。
あ、ちなみにREST-APIの動作確認には、Visual Studio Codeの拡張機能「REST Client」が便利です。
PNG画像の取得
さて、ここは超簡単です。
確認したIDは「52」だったので、これをURLに突っ込んで
http://localhost:1234/v1/networks/52/views/first.png
ブラウザで開けばpngに変換されたネットワーク図が表示されます。 ね、簡単!
しかしこれ、すごく粗いなぁ…
拡大率を取得して等倍書き出し
デフォルトの状態だと、表示中の解像度を基準にするようなので、大きいグラフを書き出すとかなり粗くなってしまいます。
等倍で書き出すためには、現状の拡大率をもとに書き出しサイズを決めてやる必要があります。
ちなみに書き出しサイズは画像の高さで指定するので、必要なのは現状の高さと拡大率です。
APIにこんなリクエストを送ると
POST http://localhost:1234/v1/commands/network/get properties content-type: application/json { "network": "current", "propertyList": "height,Scale Factor" }
こんな返事を返してくれます。
{ "data": [ { "SUID": 52, "visualProperties": [ { "visualProperty": "NETWORK_HEIGHT", "value": 478.0 }, { "visualProperty": "NETWORK_SCALE_FACTOR", "value": 0.11344625974084283 } ] } ], "errors": [] }
そしたら高さに拡大率の逆数をかけて、整数にしておきましょう。
というわけで、本来のサイズは高さ=4213pxのようですね。
これをさっきのURLに突っ込んであげれば
http://localhost:1234/v1/networks/52/views/first.png?h=4213
こんどは文字までバッチリ読めますね!
ImageMagicで余白をトリミング
さて、ネットワーク図を高解像度のPNG画像として取り出すことができましたが、表示中の余白も含まれているのでムダに横幅の大きい画像になってしまいました。
このままだと印刷時に1/3くらいは白紙を出すことになってしまうので、うまくトリミングしたい。
そこで使いたいのが”画像加工界のスイスアーミーナイフ”と呼ばれるImageMagicです。
インストール方法とか詳しい使い方とかは各所で紹介されているので、ここでは必要なところだけ紹介します。
magick convert -trim +repage -resize "14300x14300>" "http://localhost:1234/v1/networks/52/views/first.png?h=4213" "C:\temp\network.png"
さて、いくつかオプションがついているのでそれぞれ簡単に説明します。
-trim
- これをつけるだけで、余白を自動認識してトリミングしてくれます。
+repage
- キャンバスサイズをトリム後サイズに合わせてくれます。付けときましょう。
-resize
- 僕の環境では辺長が14300pxを超えるとうまくPDFにできなかったので、リサイズオプションも付けてみました。
- ">"を付けると、指定サイズを超えたときだけ、収まるようにリサイズしてくれます。
その結果がこちら、わかりやすいように黒枠で囲ってみました。
うまくトリミングされていますね。
ImageMagicでPNGをPDFに変換
あとはそのままPDFに変換するだけですね。
出力ファイル名で拡張子を指定すれば、勝手に判定して変換してくれます。すごい!
magick convert "C:\temp\network.png" "C:\temp\network_output.pdf"
Acrobat Readerで分割印刷
PDFの分割印刷は、いろいろやり方があると思いますが、ここではAcrobat Reader DCの「ポスター印刷」機能を使ってみます。
変換したPDFを開いて
印刷メニューの「ページサイズ処理」で「ポスター」を選択しましょう。
プレビューを見ながら、倍率などを適宜指定して印刷すれば完成です!
どうなったか
ぼく「印刷できました!」
職場の人「うーん、大きすぎてよくわかんないよ」
ぼく「……はい?」
※この記事の登場人物は架空のものです。