magattacaのブログ

日付以外誤報

TeachOpenCADD トピック11(イントロ)〜オンラインAPI/サービスを使った構造に基づくCADD〜

こちらはTeachOpenCADDの試訳です。TeachOpenCADD GitHubレポジトリトークトリアル11をもととしておりCC BY 4.0のライセンスに従っています。

トークトリアル11は論文発表時のTeachOpenCADDには含まれておらず新しく追加されたものです。
4つのノートブックに分かれており、ここではその一つ目を訳出します。
トークトリアル11で取り上げられているWebサーバー、サービスには既に停止しているものもあり、そのまま使えるものではなくなってしまっていますが、基本的な考え方や手法を知る上では役にたつかもしれません。

~~ 追記 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以下のページに翻訳したノートブックを保存しています。よろしければご利用ください。

github.com

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

以下、訳。

トークトリアル 11 (イントロ)

オンラインAPI/サービスを使った構造に基づくCADD

Developed at AG Volkamer, Charité

Dr. Jaime Rodríguez-Guerra, Dominique Sydow

このトークトリアルの目的

Webサービスは、ユーザーのインストールの煩わしさを避けられるので、ソフトウェア利用の上で便利な方法です。Web UIは、通常ワークフローの自動化の可能性を犠牲にして、簡単に利用できるようにします。幸運にも、アクセスを自動化するためのAPI(アプリケーションプログラミングインターフェース / Application Programming Interface)を提供するWebサービスの数は増えています。コンピューター支援医薬品デザインの分野における例としては次のようなものがあります:

  • ChEMBL
  • RCSB PDB
  • KLIFS
  • Proteins.plus
  • SwissDock

以下のノートブックでは、医薬品デザインの文脈において、オンラインWebサービスPythonからプラグラム的に使う方法を学びます。最終的な目標は、(ほとんど)すべてのローカル環境での実行なしに、もっぱらWebサービスのみに依るパイプライン全体を構築することです!

: 簡単のため、このトークトリアルの実践編はイントロダクションと以下の追加の3つのノートブックに分けていてます。

  • 11a. キナーゼ阻害剤の候補をKLIFとPubChemで検索
  • 11b. 11aで取得した候補化合物をターゲットタンパク質に対してドッキング
  • 11c. 結果を評価し既知のデータと比較

学習の目標

理論

Pythonを使ってWebサービスにプログラムでアクセスする方法の種類:

  • プログラムのAPI
    • HTTPベースのRESTful API
    • どのようなAPIに対してもクライアントを生成する
  • ドキュメントの構文解析(Document parsing)
  • ブラウザのリモートコントロール

理論

プログラムによるアクセスの種類

プログラムのAPI

現代のWebサービスは、特にデータベースの場合、データへのアクセスのために標準化された方法を提供することができます。通常、これはサイトの特定のURLにアクセスし、機械が読むことができる形式の結果を要求することができることを意味します。

例えば、UniProt はタンパク質に関するあらゆる種類の情報のためのデータベースです。もし(癌に関与している)Srcのような特定のタンパク質を探しているのであれば、セクションごとにコンテンツがよく組織化されたこの美しいWebページにたどり着くでしょう。ですが、もしURLに.fastを追加したならば、タンパク質の配列をFASTA形式で取得することができます。

https://www.uniprot.org/uniprot/P12931 -> https://www.uniprot.org/uniprot/P12931.fasta
---

>sp|P12931|SRC_HUMAN Proto-oncogene tyrosine-protein kinase Src OS=Homo sapiens OX=9606 GN=SRC PE=1 SV=3
MGSNKSKPKDASQRRRSLEPAENVHGAGGGAFPASQTPSKPASADGHRGPSAAFAPAAAE
PKLFGGFNSSDTVTSPQRAGPLAGGVTTFVALYDYESRTETDLSFKKGERLQIVNNTEGD
WWLAHSLSTGQTGYIPSNYVAPSDSIQAEEWYFGKITRRESERLLLNAENPRGTFLVRES
ETTKGAYCLSVSDFDNAKGLNVKHYKIRKLDSGGFYITSRTQFNSLQQLVAYYSKHADGL
CHRLTTVCPTSKPQTQGLAKDAWEIPRESLRLEVKLGQGCFGEVWMGTWNGTTRVAIKTL
KPGTMSPEAFLQEAQVMKKLRHEKLVQLYAVVSEEPIYIVTEYMSKGSLLDFLKGETGKY
LRLPQLVDMAAQIASGMAYVERMNYVHRDLRAANILVGENLVCKVADFGLARLIEDNEYT
ARQGAKFPIKWTAPEAALYGRFTIKSDVWSFGILLTELTTKGRVPYPGMVNREVLDQVER
GYRMPCPPECPESLHDLMCQCWRKEPEERPTFEYLQAFLEDYFTSTEPQYQPGENL

これは特定のURLスキームを介して、プログラムによりWebサービスにアクセスすることを提供する方法です。ですが、各Webサービスは各々独自の仕組みを提案しており、開発者はケースバイケースでスクリプトを実装せざるを得ません。

幸運にも、この種のプログラムによるアクセスを提供する標準化された方法がいくつかあります:

このトークトリアルでは、RESTとSOAP APIだけを扱います。

HTTPベースのRESTful API

この種のプログラムアクセス/規定は、プログラムによるアクセスを要求するクライアント(スクリプト、ライブラリ、プログラム)に対して特定のエントリーポイントを定義します。api.webservice.comといったようなものです。バージョン管理することができるので、サービス提供者はすでに存在している実装を中断せずにスキームを更新することができます(api.webservice.com/v2 をデプロイした時でさえでも、まだapi.webservice.com/v1が機能し続けます)

この種のAPIには通常、プラットフォームで利用可能なアクションを全て解説したうまくまとめられたドキュメンテーションがあります。例えば、GitHub REST API for listing repositoriesをみてください。各引数とオプションが、利用例とともにどのようにドキュメント化されているか、見てみることができるでしょう。

唯一の難しい点は、必要なURLを正しい方法で構築することです:

https://api.github.com/users/volkamerlab/repos

訳注(2020/05)
ノートブックではここにURLの戻り値が書かれていますが、冗長で内容とは関係しないので省略します。GitHubのノートブックを確認してください。
訳注ここまで

これはたまたまJSONフォーマットの辞書でした!jsonライブラリを使って構文解析Pythonの辞書に変換することが簡単にできます。さらに良いことには、それをする必要すらありません。requestsを使うことで、以下の操作が3行でできます。

import requests

response = requests.get("https://api.github.com/users/volkamerlab/repos")
response.raise_for_status()  # この行はエラーが生じる可能性をチェックします。
result = response.json()
result

訳注(2020/05)
ノートブックではrequestsで得た結果が出力されていますが、冗長なので省略します。先にURLを使った場合と同じ結果が得られることが確認されています。
訳注ここまで

URLをf文字列(f-string)でパラメーター化すれば、どのユーザーのレポジトリでもリストするように関数を書くことができます。

def repos(username):
    response = requests.get(f"https://api.github.com/users/{username}/repos")
    response.raise_for_status()
    return response.json()

repos("volkamerlab")

訳注(2020/05)
ノートブックではここに関数の出力が書かれていますが省略します。
訳注ここまで

APIのクライアントを生成

便利だと思いましたか?まだ終わりではありません!

REAT APIスキーマはプログラムによりSwagger/OpenAPI definitionsと呼ばれるドキュメントで表現することができます。これによりSwagger/OpenAPIスキーマを実装するREST APIPythonクライアントを動的に生成することができます。 これはGitHubのための実例です

もちろん、Pythonで行うためのライブラリもあります。

  • bravado
  • agithub

Bravadoを使う場合、

# 以下でImportErrorが出た場合はこれを実行してください
!pip install bravado
from bravado.client import SwaggerClient
GITHUB_SWAGGER = "https://api.apis.guru/v2/specs/github.com/v3/swagger.json"
client = SwaggerClient.from_url(GITHUB_SWAGGER)
client

# SwaggerClient(https://api.github.com/)

これで、メソッドとして全てのAPIアクションがあるかclientオブジェクトを調べて遊ぶことができます。ケーススタディとしてKLIFSを実例として取り上げます。

ヒント: clientについてこのNotebook上で調べるにはclient?を使ってください。

訳注(2020/05)
KLIFSの実例はトークトリアル11パートAを参照してください。
訳注ここまで

SOAP(Simple Object Access Protovol)のような他の標準的な方法も非常に似た原理で動作します。必要なことはクライアント生成ライブラリによって処理される定義ファイルを提供することだけです。SOAPの場合、定義ファイルは.wsdl(Web Services Description Language)のフォーマットとなっています。最も人気のあるライブラリの一つはsudsです(現在、suds-communityとしてインストール可能です)。

# sudsのインストールが必要であればこのセルを"code"に変換してください
!pip install suds-community
import suds.client
wsdl = 'http://www.swissdock.ch/soap/wsdl'
client = suds.client.Client(wsdl)
# Sudsは("?でアクセスできる) __docstring__ を持ちませんが、__str__() メソッドに多くのことが記載されています。
# 言い換えれば、ドキュメンテーションを入手するにはオブジェクトを"print"しなければなりません。
print(client)

訳注(2020/05)
残念ながら現在swisdockのサーバーは機能しておらずHTTP Error 502: Proxy Errorというエラーが表示されます。
訳注ここまで

ドキュメント構文解析

時折運悪く、Webサービスが、機械可読なドキュメントを生成する標準化されたAPIを提供していない場合があるでしょう。代わりに、必要な情報を得るために、通常のWebページを使って、HTMLコードを構文解析しなければなりません。これはウェブスクレイピング((web)scraping)と呼ばれており、通常、 価値のあるデータを含む正しいHTMLタグとIDを見つけることを含みます(サイドバーやトップメニュー、フッター、広告 etc.といったものを無視します)。

スクレイピングでは、基本的に2つのことを行います。

  1. requestsを使ってWebページにアクセスしHTMLコンテンツを取得します。
  2. BeautifulSoupあるいはrequests-htmlで、HTML文字列を構文解析します。

このWikipediaの記事のタンパク質を構成する(proteinogenic)アミノ酸のテーブルを構文解析して見ましょう!

import requests
from bs4 import BeautifulSoup
import pandas as pd

r = requests.get("https://en.wikipedia.org/wiki/Proteinogenic_amino_acid")
r.raise_for_status()

# ここで正しいステップを推測するためには、手動でHTMLコードを調べる必要があります。
# ヒント: HTMLの定義にたどり着くにはWebページ上で右クリック+検証(inspect content)を使ってください ;)
html = BeautifulSoup(r.text)
header = html.find('span', id="General_chemical_properties")
table = header.find_all_next()[4]
table_body = table.find('tbody')

data = []
for row in table_body.find_all('tr'):
    cells = row.find_all('td')
    if cells:
        data.append([])
    for cell in cells:
        cell_content = cell.text.strip()
        try:  # 可能であればfloatに変換します
            cell_content = float(cell_content)
        except ValueError:
            pass
        data[-1].append(cell_content)
pd.DataFrame.from_records(data)
0 1 2 3 4 5
0 A Ala 89.09404 6.01 2.35 9.87
1 C Cys 121.15404 5.05 1.92 10.7
2 D Asp 133.10384 2.85 1.99 9.9
3 E Glu 147.13074 3.15 2.1 9.47
4 F Phe 165.19184 5.49 2.2 9.31
5 G Gly 75.06714 6.06 2.35 9.78
6 H His 155.15634 7.6 1.8 9.33
7 I Ile 131.17464 6.05 2.32 9.76
8 K Lys 146.18934 9.6 2.16 9.06
9 L Leu 131.17464 6.01 2.33 9.74
10 M Met 149.20784 5.74 2.13 9.28
11 N Asn 132.11904 5.41 2.14 8.72
12 O Pyl 255.31000 ? ? ?
13 P Pro 115.13194 6.3 1.95 10.64
14 Q Gln 146.14594 5.65 2.17 9.13
15 R Arg 174.20274 10.76 1.82 8.99
16 S Ser 105.09344 5.68 2.19 9.21
17 T Thr 119.12034 5.6 2.09 9.1
18 U Sec 168.05300 5.47 1.91 10
19 V Val 117.14784 6 2.39 9.74
20 W Trp 204.22844 5.89 2.46 9.41
21 Y Tyr 181.19124 5.64 2.2 9.21

ブラウザのリモートコントロールBrowser remote control

数年前のトレンドではJavaScriptを使って動的にHTMLドキュメントを生成するサーバーを構築することがあちこちで行われていました(Wikipediaのように)。言い換えれば、HTMLはサーバに組み込まれクラアント(あなたのブラウザ)に送られます。

しかし、最近のトレンドではアプリケーション全体をJavaScriptフレームワークで全部構築することに向かっています。つまり、HTMLのコンテンツがクライアント上で動的に生成されます。伝統的な構文解析は機能せず、JavaScriptフレームワークをホストする代替のHTMLコードをダウンロードするだけです。これを回避するには、HTMLはクライアント側のJavaScriptエンジンで翻訳されなければなりません。

現在のノートブックではこれは取扱いませんが、興味があれば次のプロジェクトをチェックしてください。


ディスカッション

このイントロダクション理論編では、PythonインタープリターからオンラインのWebサービスにプログラムでアクセスする様々な方法を見てきました。これらのテクニックを活用することで、Jupyter Notebook上で自動化されたパイプラインを構築することができるようになります。このトークトリアルの続きのパートを読んでCADDへの適用例を見てください。

クイズ

  • Webサイトの特定の箇所をスクレイピングするために正確なHTMLタグとIDをみつけるためにはどうすれば良いでしょうか?自動化できるでしょうか?
  • プログラムによるAPI、あるいは手動で作成したスクレイピングのどちらが良いですか?

訳以上

追記

今回も訳出、用語の選択に誤りがあるかもしれません。ご指摘いただければ幸いです。

トークトリアル11はちょっと私のようなプログラミングができないものには辛いです。何をやっているかよくわかりません。HTMLのタグなどWebスクレイピングについても勉強しないといけなさそうです・・・

とりあえずこれまでの訳を置いておくレポジトリを作成しました。

github.com