Flaskとpychembldbを使えばChEMBLウェブサービスみたいなのは簡単に作れるよと、朝の30分くらいを使ってちょっとやってみた。
pychembldbはSQLAlchemyのラッパーなので、Flaskのほうではルーティングを設定して、ハンドラ関数用意すればいいだけ。特にFlaskはJSON化する関数が用意されているのでJSONで返すのはラク。
@app.route("/chemblws/compounds/<chembl_id>")
def compound_by_ChEMBLID(chembl_id):
compound = chembldb.query(Molecule).filter_by(chembl_id=chembl_id).one()
result = {...}
return jsonify(result)
という感じでDictionaryを用意してxmlかjsonに変換して返せばいいので、とりあえずChEMBLIDを与えると対応する化合物情報を返すAPIを実装してExamplesに用意してみた。
自前でサービスを用意することのメリットは
- 外部に情報が流れない
- レスポンスが速い
- 沢山投げても怒られない
ということの他に
- 自分たちの用途に合わせて 拡張できる
- データベースのスキーマをきちんと理解できる
という部分もあるかなと思います。例えばChEMBLウェブサービスにはジャーナルのdoiから構造リストを返すというAPIは存在しないけど、project毎にジャーナルをまとめていたりするときにはそういうAPIが用意されていると便利かもしれませんよね?
最初、ウェブサービスが返す情報は固定なのかなと思い、決め打ちで用意したのだけど、CHEMBL1とCHEMBL2で返ってくるjsonのキーが違うので、valueが存在するのものをすべて返しているのかな。
もう少しちゃんと出来たらきちんとテストを書こう。
CHEMBL1
{
"compound": {
"acdLogd": 7.67,
"acdLogp": 7.67,
"alogp": 3.63,
"chemblId": "CHEMBL1",
"knownDrug": "No",
"medChemFriendly": "Yes",
"molecularFormula": "C32H32O8",
"molecularWeight": 544.59,
"numRo5Violations": 1,
"passesRuleOfThree": "No",
"rotatableBonds": 2,
"smiles": "COc1ccc2[C@@H]3[C@H](COc2c1)C(C)(C)OC4=C3C(=O)C(=O)C5=C4OC(C)(C)[C@@H]6COc7cc(OC)ccc7[C@H]56",
"stdInChiKey": "GHBOEFUAGSHXPO-XZOTUCIWSA-N"
}
}
CHEMBL2
{
"compound": {
"acdBasicPka": 6.52,
"acdLogd": 2.09,
"acdLogp": 2.14,
"alogp": 2.11,
"chemblId": "CHEMBL2",
"knownDrug": "Yes",
"medChemFriendly": "Yes",
"molecularFormula": "C19H21N5O4",
"molecularWeight": 383.4,
"numRo5Violations": 0,
"passesRuleOfThree": "No",
"preferredCompoundName": "PRAZOSIN",
"rotatableBonds": 4,
"smiles": "COc1cc2nc(nc(N)c2cc1OC)N3CCN(CC3)C(=O)c4occc4",
"species": "NEUTRAL",
"stdInChiKey": "IENZQIKPVFGBNW-UHFFFAOYSA-N",
"synonyms": "CP-12299,Minipress,Minizide,PRAZOSIN,Prazosin"
}
}