DNAやタンパク質の立体構造をRubyで表示すっゾ - GR.rbの場合

## はじめに

タンパク質の立体構造をRubyで表示するということは古来から人類の夢であり、以前よりいろいろな試みが行われてきました。

* [タンパク質の立体構造を A-Frame で](https://qiita.com/scivola/items/16889866458ebb701fde)
* [タンパク質の立体構造をSketchUpでモデル化 その1](https://qiita.com/yoho/items/1e15bbd4e3a7c4c7ff69)

この記事では、私がメンテナンスしているグラフ描出ツール[GR.rb](https://github.com/red-data-tools/GR.rb)を利用してタンパク質などの立体構造を表示する方法を説明します。

* [Rubyでグラフを描画するツール GR.rb の紹介](https://qiita.com/kojix2/items/456259f40d5563005cd1)

## GR.rb で xyz ファイルを表示しよう

![video.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/fa1873b5-0c4c-b616-b9bf-70521571b5c9.gif)

GR.rb でDNAの立体構造が記述されている xyz ファイルを表示するスクリプトを動かしたところ。

### xyzファイルを入手する

最初に`xyz` 形式のファイルを保存します。ブラウザからダウンロードしたい方は[こちら](https://raw.githubusercontent.com/red-data-tools/GR.rb/master/examples/assets/dna.xyz)

```
wget https://raw.githubusercontent.com/red-data-tools/GR.rb/master/examples/assets/dna.xyz
```

### Rubyスクリプトを作る

次にRubyスクリプトを作成します。ここでは仮に `mol.rb` としましょう。

ライブラリを読み込みます。

```ruby:mol.rb
require 'gr'
require 'gr3'
require 'numo/narray'
require 'optparse'
```

今回は割と真面目にコマンドラインオプションつけてみました。

```ruby
# コマンドラインオプション
options = { radius: 1.0, size: 500 }
OptionParser.new do |opt|
  opt.on('-o', '--output PATH', String) { |v| options[:save_path] = v }
  opt.on('-r', '--radius VALUE', Float) { |v| options[:radius] = v }
  opt.on('-s', '--size VALUE', Integer) { |v| options[:size] = v }
  opt.on('-t', '--title TITLE', String) { |v| options[:title] = v }
  opt.parse!(ARGV)
  options[:title] ||= ARGV[0]
end
```

ファイルを読み込みます。ここで残念なお知らせがあって、Rubyではよくあることなのですが、`xyz` のパーサーは見つかりませんでした。なので自分でファイルからデータを読み込みます。しかし、もともとのファイルの形式が単純なので超簡単です。
原子の表示用の色や、サイズはGR3モジュールに定数にデフォルトの値が保存されているので、それを使いましょう。

```ruby
# ファイルの読み込み
data = readlines
nrows = data.shift.to_i
puts data.shift
data = data.take(nrows)
data.map! { |row| row.split(/\s+/) }

positions = data.map { |row| row[1..3].map(&:to_f) }
atoms     = data.map { |row| row[0] }.map { |a| GR3::ATOM_NUMBERS[a.upcase] }
colors    = atoms.map { |a| GR3::ATOM_COLORS[a] }
radii     = atoms.map { |a| GR3::ATOM_RADII[a] * options[:radius] }
```

実際に表示する部分です。ここは、GR.jlのサンプルを参考に書きました。

```ruby
GR.initgr
GR.setviewport(0, 1, 0, 1)

# ビデオファイル保存
GR.beginprint(options[:save_path]) if options[:save_path]

360.times do |i|
  GR.clearws
  GR3.clear
  GR3.drawmolecule(positions, colors, radii, nil, nil, nil, 2, true, i, 45)
  GR3.drawimage(0, 1, 0, 1, options[:size], options[:size], GR3::DRAWABLE_GKS)
  GR.settextcolorind(0)
  GR.settextalign(GR::TEXT_HALIGN_CENTER, GR::TEXT_VALIGN_TOP)
  GR.text(0.5, 1, options[:title])
  GR.updatews
end

# ファイル保存おわり
GR.endprint if options[:save_path]

GR3.terminate
```

以上です。
スクリプト全体はこちらの[gist](https://gist.github.com/kojix2/3152bed11ea9ff546328538d0cbdddba)になります。

## 実行する

そのまま半径が少し小さい気がするので、`-r 2` として半径を2倍にしてみます。

```sh
ruby mol.rb -r2 dna.xyz
```

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/ac0be1a3-2944-533e-ad8d-d49c1625d58f.gif)

こんな画面が出てくれれば成功です!

## ヘモグロビンの立体構造を表示してみよう

他の分子も表示してみましょう。ここでは有名なタンパク質としてヘモグロビンの構造を表示してみます。

酸素が結合していいない時のヘモグロビンの構造を記述したファイルを日本蛋白質構造データバンク（PDBj: Protein Data Bank Japan）からダウンロードします。

* https://pdbj.org/mine/resources/2hhb

ここでは `pdb2hhb.ent` というPDBファイル形式のファイルをダウンロードします。
これを[Open Babel](https://openbabel.org/wiki/Main_Page)というツールを利用して、`xyz` 形式のファイルに変換します。

```sh
# Open Babelのインストール
sudo apt install openbabel
```

pdb2hhb.ent を xyz ファイルに変換する。

```
obabel pdb2hhb.ent -O hb.xyz
```

そして `mol.rb` で表示します。

```
ruby mol.rb hb.xyz -s 1000 -o hemoglobin.mp4 -t hemoglobin
```

GIFアニメに変換する過程でカクカクしてしまっていますが、実際にはもう少し綺麗な動画が保存されます。
`-s` オプションを上げれば動画はきれいになります。

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/58501f49-c42b-b192-f038-ae56e6ab7d8d.gif)

一方で `-s` を小さくすると、それはそれでドット絵のような味のある動画になります。DNAの例でやるとこんな感じです。

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/dd6bbb70-bc11-7b14-dff5-3737665c928c.gif)

往年のゲームのワンシーンみたいです。すみません。とくに学術的な意味はありませんね…。

## 最後に

さて、Rubyでも実は分子の構造を表示する方法はあるよ〜

という話をしました。「なぜRuby？」という疑問があるかも知れませんが、それについては深く考えないことにしましょう。

最後になりますが、私、こうやって喜んで立体構造のデータを表示していますけど、私、特に分子の構造に詳しいわけではなく完全なる素人です。xyz形式や、PDFファイル形式についても今回はじめて知りました。

なので、もし間違っているところをみつけたら**遠慮なくコメント欄に指摘してください**。よろしくおねがいします。

この記事は以上です