16 06 2013 chemoinformatics Python Tweet
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" } }