Three.jsチュートリアルで見て楽しむタンパク質

# 初めに

**Three.js**を触ってみたので、ついでにタンパク質を可視化するWebアプリを作ってみました。

>three.jsは、ウェブブラウザ上でリアルタイムレンダリングによる3次元コンピュータグラフィックスを描画する、クロスブラウザ対応の軽量なJavaScriptライブラリ及びアプリケーションプログラミングインタフェースである。

- **Webアプリ : [「Protein GL」](http://takemoto08.bio.kyutech.ac.jp/~hirano/Protein_GL/)**
（学生時代の研究室サーバに立てているので動かなくなってるかも）

左上のフォームに見たいタンパク質のPDBID(デフォルトで３種用意)を入力してください。

下例：**ヘモグロビン(1ABW)の立体構造(α炭素)**
![output1.gif](https://qiita-image-store.s3.amazonaws.com/0/247972/93cd522a-5a89-e491-18ee-143ace6847d4.gif)

タンパク質は以下のように、アミノ酸から成る１本の鎖が折りたたまれてできています。
このアミノ酸を鎖の端から順に色付けすることで、タンパク質がどのように折りたたまれているのかをある程度可視化することができます。

![protein.gif](https://qiita-image-store.s3.amazonaws.com/0/247972/e3d946f7-f5b7-c6bf-b125-286f6cfb02b6.gif)

# Three.jsチュートリアル ー 球・線を描く
Three.jsを使うところだけ簡単に紹介します。

初めに、htmlのbodyでcanvasの指定とThree.jsを読み込みを行います。

```html
<body>
　　　　<!-- 描画画面の設置 -->
　　　　<canvas id="myCanvas"></canvas>

　　　　<!-- Three.jsを読み込む -->
　　　　<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"></script>

　　　　<!-- 以下に描画コードを書く -->
</body>
```

次に、Three.jsの**描画コード**を書きます。

```html
<script>
    window.addEventListener('DOMContentLoaded', init);

    function init() {
        var theCanvas = document.getElementById('myCanvas');

        var windowInnerWidth = window.innerWidth;
        theCanvas.setAttribute('width', windowInnerWidth);
        const width = windowInnerWidth;

        var windowInnerHeight = window.innerHeight;
        theCanvas.setAttribute('height', windowInnerHeight);
        const height = windowInnerHeight;

        // レンダラーを作成
        const renderer = new THREE.WebGLRenderer({
            canvas: document.querySelector('#myCanvas')
        });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(width, height);

        // シーンを作成
        const scene = new THREE.Scene();

        // カメラを作成
        const camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
        camera.position.set(0, 0, 1000);

        // # 球を作成
        var balls = new THREE.Group();  // ball0 と ball1をまとめる親

        // 1つ目の子供球
        const geometry0 = new THREE.SphereGeometry(100);
        const material0 = new THREE.MeshStandardMaterial({ color: 0x0000FF });
        const ball0 = new THREE.Mesh(geometry0, material0);
        ball0.position.set(77, 71, 31); // ex. 原子座標(x,y,z)
        balls.add(ball0);

        // 2つ目の子供球
        const geometry1 = new THREE.SphereGeometry(50);
        const material1 = new THREE.MeshStandardMaterial({ color: 0x0000FF });
        const ball1 = new THREE.Mesh(geometry1, material1);
        ball1.position.set(-77, -71, -31);
        balls.add(ball1);

        scene.add(balls);

        // # 線を作成
        var geometry = new THREE.Geometry();

        // 球１から球２まで線を引く
        geometry.vertices.push(new THREE.Vector3(77, 71, 31)); // 球１の座標
        geometry.vertices.push(new THREE.Vector3(-77, -71, -31)); // 球２の座標

        //線オブジェクトの生成	
        var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0xFFFFFF }));

        scene.add(line);

        // 平行光源
        const light = new THREE.DirectionalLight(0xFFFFFF);
        light.intensity = 5; // 光の強さを倍に
        light.position.set(1, 1, 1);
        // シーンに追加
        scene.add(light);

        // 初回実行
        tick();

        function tick() {
            requestAnimationFrame(tick);

            // 球を回転させる
            balls.rotation.x += 0.01;
            balls.rotation.y += 0.01;

            // 線を回転させる
            line.rotation.x += 0.01;
            line.rotation.y += 0.01;

            // 色変更
            balls["children"][0]["material"]["color"]["r"] = 1; // 1つ目の子供球
            balls["children"][0]["material"]["color"]["g"] = 0;
            balls["children"][0]["material"]["color"]["b"] = 0;

            // レンダリング
            renderer.render(scene, camera);
        }
    }

</script>
```

すると、以下のように表示されます。

![output2.gif](https://qiita-image-store.s3.amazonaws.com/0/247972/07a22e44-1877-c1e2-9a46-90c39ff57ba1.gif)

作ったWebアプリはほぼこれをベースにしています。

Webアプリのフローは以下の通りです。

1. フロントのフォームでPDBID(タンパク質ID)を受け取る
2. サーバーで受け取ったPDBIDより、タンパク質の立体構造データを[「PDB(タンパク質のデータベース)」](https://www.rcsb.org/)よりダウンロード
3. サーバーで、ダウンロードした立体構造データからアミノ酸の３次元座標を抽出
4. flaskでhtmlをレンダリング(座標の位置に球を設置)

以上、Three.jsチュートリアルとWebアプリ紹介でした。