データ構造と構造検知

libbuilcule で実装している分子を表現するデータ構造を,簡略化して紹介します.
libbuilcule では,系全体を表現するための Unit クラス内に,Atom クラス,Amino_Acid クラス,Molecule クラスの組み合わせからなるデータ構造を構築しています.

現バージョンの libbuilcule は Builcule の非 GUI 部分をライブラリにしただけなので,拡張性に乏しい等々,不都合が出ています.
次期バージョンでは,継承関係を中心に大幅変更する予定です.

目次(ページ内リンク)


Atom クラス:原子を表現するためのデータ構造です.まず考えねばならないのは,編集に大きく係る共有結合の処理でしょうか
Amino_Acid クラス:アミノ酸なのですが,水素付加,水素除去,シークエンス,変異などの編集に係る情報も格納します
Molecule クラス:分子を表現するためのデータ構造です.分子単位の操作が可能になります
Unit クラス:系全体を表現するためのデータ構造です
ペプチドの検知:共有結合情報からどうやって検知しているか,セクションを儲けました

Atom クラス

分子ファイルに記述されたデータ

分子情報を記したファイルには,一般に 1 行に 1 原子の情報が記述されています.
このことから,原子を表現するデータ構造を作成すれば,ファイルの情報を処理しやすそうです.

一例として,下に XYZ 形式で記述したメタンを示します.
1 行に元素とカルテシアン座標(XYZ 座標)が記述されています.

5
This file was creatwd with Builcule.
C         -0.00000        0.00000       -0.00000
H          1.07000        0.00000       -0.00000
H         -0.35667        0.00000        1.00881
H         -0.35667       -0.87365       -0.50440
H         -0.35667        0.87365       -0.50440

Atom クラスの概略

仮に XYZ 形式のファイルを処理するとするなら,元素と座標がファイルの各 1 行から読み取れます.
座標から,2 原子間の距離を測定し,標準的な共有結合距離と比較すれば検知できます(距離の実測例:タンパク質における共有結合の検知

libbuilcule では,これらの情報を格納する Atom クラスを定義しています.
下はクラス宣言の一部です.

#include <Eigen/Dense>
#include <memory>
#include <vector>

class Atom {
 private:
  int SerialNum;  //原子ごとにユニークな番号を与える
  int Element;  //原子番号(ここには記さないが,元素記号も保持している)
  Eigen::Vector3d XYZ;  //座標を線形代数ライブラリである Eigen のオブジェクトとしている
  std::vector<std::shared_ptr<Atom>> Bond;  //共有結合の相手を格納する可変長配列
 public:
  Atom(const std::string *symbol, double x, double y, double z);  //コンストラクタ
  void push_bond(const std::shared_ptr<Atom> &pair) { Bond.push_back(pair); }  //共有結合の形成
};

Amino_Acid クラス

共有結合が検知できたら,後述するペプチドの検知で紹介しているアルゴリズムで,アミノ酸残基やペプチドが検知できます.
libbuilcule では,アミノ酸残基を表すデータ構造として Amino_Acid クラスを定義しています.
下はクラス宣言の一部です.
メンバ変数のみ抜書しました.これらのメンバ変数を操作(== アミノ酸を編集)するメンバ関数は省略しました.

アミノ酸残基を構成する原子は,Atom クラスへの共有ポインタをベクトル型配列に格納したオブジェクトとなっています.
水素付加,水素除去に対応するため,4 種類に分割しています.

PDB 形式での表示記号(CA とか CB とか)をキーとし,原子への共有ポインタを返す連想配列連想配列を作成しています.
アミノ酸の編集用です.

シークエンス用に,配列上前後のアミノ酸へのポインタを保持するオブジェクトも宣言しました.

class Amino_Acid {
 private:
  char Code;  //アミノ酸 1 文字コード

  //アミノ酸を構成する原子
  std::vector<std::shared_ptr<Atom>> Main;  //主鎖の非水素原子
  std::vector<std::shared_ptr<Atom>> MainH;  //主鎖の水素原子
  std::vector<std::shared_ptr<Atom>> Side;  //側鎖の非水素原子
  std::vector<std::shared_ptr<Atom>> SideH;  //側鎖の水素原子

  //表示記号をキーとして,原子への共有ポインタを返す連想配列
  std::map<AA_Atom, std::shared_ptr<Atom>> MapMain;  //キーは表示記号
  std::map<AA_Atom, std::shared_ptr<Atom>> MapSide;  //同上

  //シークエンス用
  const Amino_Acid *BeforeAA;  //N-末側のアミノ酸へのポインタ
  const Amino_Acid *NextAA;  //C-末側のアミノ酸へのポインタ
};

Molecule クラス

libbuilcule では,分子を格納する Molecule クラスを定義しています.
下にクラス言言の一部を示します.

class Molecule {
 private:
  std::vector<std::shared_ptr<Atom>> MolAtom;  //分子を構成する原子
  std::vector<std::vector<Amino_Acid>> PeptVect;  //その分子で検知されたペプチド
};

原子の結合情報をたどれば全原子を捕獲できます.
Molecule クラスでは,Atom クラスのオブジェクト への共有ポインタをベクトル型配列に格納して,分子を表現するオブジェクト MolAtom としています.

Molecule クラス内ではまた,ペプチドを検知しています.
Amino_Acid クラスを構築し,シークエンス用のポインタに従ってベクトル型配列に格納すればペプチドとなります.
1 分子内に複数のペプチドが検知される場合があるので,ペプチドを表現するオブジェクト PeptVect は二次元配列です.

このクラスを使えば,分子ごと回転や削除といった編集が可能になります.
また,ペプチドの削除等,ペプチドを対象とする編集も可能になります.


Unit クラス

ファイルの情報からは,次の手順で Unit クラスを作成します.

  1. ファイルから読み取れた原子の情報は,std::shared_ptr<Atom> としてベクトル型配列 AtomVect に格納します
  2. その際必要に応じて,原子間距離から共有結合情報を作成し,Atom::Bond にプッシュします
  3. AtomVect から共有結合情報に基づいて分子を検知し,Molecule クラスのオブジェクトを作成し,MolVect にプッシュします
  4. MolVect の要素(分子)ごとにアミノ酸を検知し Amino_Acid クラスの一時オブジェクトを作成します
  5. Amino_Acid クラスのシークエンス用のポインタに従って,Amino_Acid オブジェクトを Molecule::VeptVect にプッシュすればペプチドとなります
class Unit {
 private:
  std::vector<Atom> AtomVect;  //ファイルから読み取れた全原子
  std::vector<Mol> MolVect;  //検知された分子
};

libbuilcule では,原子(を表現するデータ構造への共有ポインタ)をベクトル型配列に格納しています.
現バージョンでは,原子を管理するために 2 つの方法を使っています.
一つは,共有ポインタを利用する方法です.
もう一つは,原子ごとにユニークなシリアル番号を与え,ベクトル型配列をシリアル番号で関節参照する方法です.
殺ってみたら,どちらの方法にも一長一短があるように思えました.例えば,


ペプチドの検知

ペプチドを構成する原子の略号(一部)

図は,ペプチドの構造式と原子の表示記号の一部を示すものです.上が非末端,下が C-末です.
この記号を使って libbuilcule でペプチドを検知する考え方を簡略化して紹介します.

カルボニル炭素(C)候補

まず,共有結合が 3 個の炭素原子のうち,

であるものを探します.このなかに C が含まれます.
前者が C-末以外の候補,後者が C-末の候補です.

α-炭素(CA)候補

C 候補に結合した炭素は CA 候補です.
CA 候補に共有結合した原子を数え上げます.

が結合しているので,この条件に合わないものは,候補から外します.

アミノ窒素(N)候補

CA 候補に結合した炭素は N 候補です.
N 候補に共有結合した原子を数え上げます.

ペプチド結合

CB,CA,N の検知が終了した時点で,N-CA-CB-N まで検知できているので,あとはそれらを数珠つなぎしていきます.

側鎖

CA を捜査した時点で Gly は確定済みです.すなわち,Gly の CA には窒素と炭素が 1 個ずつ結合しているだけです.
他のアミノ酸には窒素が 1 個と炭素が 2 個結合しています.その炭素の片方が CB ということになります.
CB を走査すると,Ala,Cys,Ser,Thr,および Val の候補をピックアップできます.
水素を無視して記すと,

このような作業を繰り返して,側鎖を確定しています.