前言
遺伝子IDの変換にはDAVIDがよく使われるが、同じNational Cancer Institute Advanced Biomedical Computing Centerが運営しているサイトにbioDBnetというのがある。bioDBnetはAPIを提供している1。APIにはJSON版とSOAP版があるが、JSON GETはURLのQuery Stringに引数を指定せねばならず2、大規模処理には不安がある。SOAPはPOSTなのでこの心配はない。故にSOAP版が推奨される。
実装
さてSOAPであるが、RubyにはSavonというライブラリが存在する。これを使うと当該処理は以下のように実装できる3。
require 'savon'
kwargs = {
#:endpoint => 'https://biodbnet.abcc.ncifcrf.gov/webServices/biodbnetSoapServer.php',
:wsdl => 'https://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet.wsdl',
}
# kwargs[:log] = true
# kwargs[:proxy] = "http://localhost:8888"; kwargs[:ssl_verify_mode] = :none # for mitmproxy
client=Savon.client(kwargs)
puts client.call(:db2db,message:{db2db_params:{input:'Ensembl Gene ID',outputs:'Gene Symbol,RefSeq mRNA Accession,RefSeq ncRNA Accession',input_values:'ENSG00000110693'}}).body[:db2db_response][:return]
- 変数はdb2dbParamにくるむ必要がある(Hashのルートにinputとか書いても無視される)
WSDLでもそうなっているからそうなんだろうけど、ドキュメントにはComplex type db2dbParams
としか書かれていないのでかなり厳しい。WSDLというものがどういうものなのかも理解していないし(通常であれば理解はしていなくても使えるよなぁ)。
- messages内の変数はsnakecaseに変換する必要がある
https://github.com/savonrb/savon/blob/v2.12.1/lib/savon/builder.rb#L163 にsnakecase変換処理がある。これが意味するのは、WSDLに記載のパラメータ名はsnakecaseに変換しなければならないということである。
WSDLにはこのような記載があるので、
<xsd:complexType name="db2dbParams">
<xsd:all>
<xsd:element name="input" type="xsd:string"/>
<xsd:element name="taxonId" type="xsd:string"/>
<xsd:element name="inputValues" type="xsd:string"/>
<xsd:element name="outputs" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
Savonのmessage引数は{db2db_params:{input:"INPUT",taxon_id:"TAXONID",input_values:"INPUTVALUES",outputs:"OUTPUTS"}}
となる。db2dbParams
のままだと 単に無視される。
このことについては Savonのドキュメントに記載がない ので確実にはまりうる。
Charles使ってなかったら死んでた。
終わりに
Python版は公式クライアント(DAVID / bioDBnet)があるのですが、例しかないので使い方がわからなかった、この使い方を把握するのに1年ほどかかってしまった笑(GUI使えば良い話ではあるんだけど、まあ、GUIだと再現性がないってことです…)
-
DAVIDもAPIを提供しているが、使い勝手はbioDBnetとあまり変わらない上に、登録が必要4なので、(ID変換とかでなく)遺伝子クラスタリング等解析処理のバッチ処理が必要でないなら特段使う理由はないかと… ↩
-
GET自体はContent-Lengthヘッダ(リクエストボディ)を受け付けるが、bioDBnet APIの実装はこれを読むようになっていないようだ、しかもPOSTもだめ(Charlesやらtelnet -z sslやらで確認) ↩
-
ちょろっと書いておきますが、DAVIDの認証は、
cookies = client.call(:authenticate,message:{'args0'=>'EMAIL'}).http.cookies
として以降のリクエストではcookies:cookies
引数を渡せばよいです ↩ -
ネメシスの見過ぎだ ↩