glycoinfo / GlycanBuilder2

7 stars 5 forks source link

Duplicated linkage position in the branched glycan #34

Open e15d5605 opened 2 years ago

e15d5605 commented 2 years ago

GlycanBuilderで単糖が分岐した部分の結合位置を編集した際に、同じ結合位置を選択することができるため以下のような構造を描画することができる\

これは、Linkageを選択する際に親側の単糖の結合状態を考慮せずに結合可能な位置を選出しているためである\ この場合は下側の単糖が4位で結合しているため、結合位置のリストで4を選択できることは適切ではない

本来は親側の単糖が環を形成しているか他の単糖や置換基と結合をしていないかを考慮する必要がある

e15d5605 commented 2 years ago

結合位置の編集機能で表示されるリストは、単糖の構造情報を管理するresidue_typesLinkPosに定義されている\

Glc Hexose  Hex C6H12O6 -   Glc$    1   D   p   yes yes no  4   5   no  5   no  5   2,3,4,5,6   -   no  no  yes Glucose

例えば六員環のGlcの場合は2,3,4,5,6と定義されており、1~6までの結合位置を選択することができる\ 1が入っていないのはアノマー位であるため考慮していないと考えられる\ この制約はGlcNAcなどの特定の置換基が結合している単糖でも考慮されており、アノマー位の1とN-アセチル基の結合位置の2が除外されている

HexNAc  HexNAc  Hex C8H15N1O6   -   Hex$2NAc        1   ?   p   yes yes no  0   5   no  4   no  4   3,4,5,6 -   no  no  yes N-acetylhexosamine

現状ではLinkPosの情報をそのままリストに表示している状態となっているため、この情報を参照する際に前後の単糖の結合位置を抜き出すことでリストに表示されなくなると考えられる\ 考慮するのは以下の情報

  1. 親側の環の位置 1-1. 開環構造の場合はアノマー位を追加する
  2. 親側の単糖が持つ子情報 2-1. 置換基 2-2. 単糖

また、以下の図のように曖昧な結合位置を選択する場合は、上記の制約に適応するべきではないと考えられる\ image

e15d5605 commented 2 years ago

結合リストの参照はGlycanCanvasに以下のように実装されている

private ListModel createPositions(Residue parent) {
        DefaultListModel ret = new DefaultListModel();

        // collect available positions
        char[] par_pos = null;
        if (parent == null || parent.getType().getLinkagePositions().length == 0)
            par_pos = new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'N' };
        else
            par_pos = parent.getType().getLinkagePositions();

        // add elements
        ret.addElement("?");
        for (int i = 0; i < par_pos.length; i++)
            ret.addElement("" + par_pos[i]);

        return ret;
    }

add elementsとコメントされている処理の前にpar_posから選択できない結合位置を抜き出す以下の処理を実装する\

親ノードに結合している情報を抜き出す

// select unavailable linkage position from par_pos, 20211223, S.TSUCHIYA add
String par_pos_temp = String.valueOf(par_pos);
for (Linkage donorLinkage : parent.getChildrenLinkages()) {
    if (this.current_residue == donorLinkage.getChildResidue()) continue;
    for (Bond donorBond : donorLinkage.getBonds()) {
        if (donorBond.getParentPositions().length > 1) continue;
        if (donorBond.getParentPositions()[0] == '?') continue;
        char donorPos = donorBond.getParentPositions()[0];
        par_pos_temp = par_pos_temp.replace(donorPos, ' ');
    }
}

2/3/4のようなFazzyな結合情報や?のような不明確な結合情報は考慮しない

if (donorBond.getParentPositions().length > 1) continue;
if (donorBond.getParentPositions()[0] == '?') continue;

親ノードの構造を確認して抜き出す

// replace ring position
if (parent.getRingSize() == 'o') {
    par_pos_temp += parent.getType().getAnomericCarbon();
}
if (parent.getRingSize() == 'p') {
    if (parent.getAnomericCarbon() == '1') {
        par_pos_temp = par_pos_temp.replace('5', ' ');
    }
    if (parent.getAnomericCarbon() == '2') {
        par_pos_temp = par_pos_temp.replace('6', ' ');
    }
}
if (parent.getRingSize() == 'f') {
    if (parent.getAnomericCarbon() == '1') {
        par_pos_temp = par_pos_temp.replace('4', ' ');
    }
    if (parent.getAnomericCarbon() == '2') {
        par_pos_temp = par_pos_temp.replace('5', ' ');
    }
}

抜き出した結合情報から新しい結合リストを生成

if (!par_pos_temp.equals(String.valueOf(par_pos))) {
    par_pos_temp = par_pos_temp.replaceAll(" ", "");
    par_pos = par_pos_temp.toCharArray();
    Arrays.sort(par_pos);
}
e15d5605 commented 2 years ago

簡単な動作確認

上記の実装により結合位置は以下のように変化する

例えばマンノースの6位側の単糖の結合位置を?, 2, 4, 6から選択することが可能となる\ 他の単糖と結合している3と親側の単糖の環の位置である1, 5はリストに表示されない

親ノードを開環構造にした場合は1, 5が追加される(変更前の親ノードがピラノースの場合)

別の単糖との結合が3/6のようにFazzyな場合は、選択可能な結合位置として選出される

e15d5605 commented 2 years ago

置換基を含む単糖の結合位置

繰り返しや環状構造を含む結合位置

createPositionsとは別の方法で結合位置のリストを生成しているようだ\ どこで結合位置のリストを生成しているのかを調べる必要がある

繰り返し構造の結合情報編集に関しては、編集メニューの選択時に都度ドロップダウンリストを生成するのではなく\ 単糖同士の結合時の情報を流用しているようだ\ 繰り返しの終点位置の単糖がGlcの場合、候補となる結合位置は?, 2, 3, 4, 6と表示される

終点位置の単糖をNeu5Acに変更しても、候補となる結合位置は変更前のGlcの情報のままになっていた

GlycanCanvasのupdateToolbarPropertiesという関数で結合情報や環のサイズなどの構造情報を編集するメニューを更新している\ ここではキャンバスで選択されたノートが単糖(または置換基)と繰り返し構造のエンドブラケットで処理を分岐している\ 前者の場合はcreatePositionsを参照して選択可能な結合位置のリストを更新している\ 一方で後者の場合は、それぞれの項目に対してデフォルト値を割り当てるのみでリストの更新などは行っていない\

選択されたノードがエンドブラケットだった場合に、以下の処理を行っているため結合位置のリストを更新する処理を追加した\

if(current != null && current.isEndRepetition()) {
    field_linkage_position.setEnabled(true);
    field_anomeric_carbon.setSelectedItem("1");

    // update linkage item, 20211224, S.TSUCHIYA add
    Linkage parent_link = current.getParentLinkage();
    if (parent_link != null) {
        field_linkage_position.setListModel(createPositions(parent_link.getParentResidue()));
        field_linkage_position.setSelectedValues(toStrings(parent_link.glycosidicBond().getParentPositions()));
    }
}

createPositionsでエンドブラケットの直前の単糖を確認し、利用可能な結合位置を生成する\ これにより、単糖が置き換えられた場合でも単糖に即した結合位置がリストに反映される

field_linkage_position.setListModel(createPositions(parent_link.getParentResidue()));

現在選択されている結合位置がリストのデフォルト値として反映される

field_linkage_position.setSelectedValues(toStrings(parent_link.glycosidicBond().getParentPositions()));

フラグメントの含む構造の結合位置

yamadaissaku commented 2 years ago

@e15d5605 別の単糖との結合が3/6のようにFazzyな場合は、選択可能な結合位置として選出される について、例えば、?を”3”と選択した場合、下の”3/6”は、”6”しかありえなくなりますが、この辺りは検討可能かわかりますか? もし検討するのであれば、描画された構造に矛盾がないかのチェック機能を追加するようなことになるかと思います。もし、既にあれば一番いいのですが・・・

e15d5605 commented 2 years ago

@yamadaissaku ?3と選択した例を添付します\ 図で示されているように分岐の上側が3、下側が3/6と表示されています

下側の分岐を選択して結合情報を編集するメニューを展開すると、選択ができない結合位置は除かれるようになったため\ 結果的に結合位置が最適化された状態になります\ 最適化はされていますが、ユーザーが下側の分岐を選択しない限りは矛盾した表示が維持されてしまいます\

分岐した単糖の結合位置の重複が許されることから、描画しようとしている糖鎖が適切かを検証する機能は実装されていないと思われます\ Render処理の前後でGlycanのNormalizerやValidationを実行する関数もみたことはありません

もし、描画された糖鎖構造のチェック機能を実装する場合、Render周りの処理で結合位置が適切かの検証→最適化(または例外判定)が必要と考えられます\ どの程度の規模を想定してチェック機能を開発するか、が一番大きな問題になりそうです\ ここでいう規模というのは描画だけに止めるのか、テキストへの変換も想定してチェックするのかなどです

e15d5605 commented 2 years ago

20220210所見 単一の結合情報を選択した場合の重複を避けるようにしたが、Fuzzyな結合位置に関しては今後検討する\ 本課題は、部分的に解決されただけの状態であるため、Closeせずに残しておく