magattacaのブログ

日付以外誤報

pymolをimportしようとする話の続きの話

PyMOLのjupyter notebookからのimportに失敗したことについて記事を書いたところ、早速twitterで解決方法を教えていただきました。 @kira_kira_worldさん、@Ag_smith先生ありがとうございました!

解決策に入る前に・・・pythonのバージョンについて

先の記事を書いた時点では気づいていなかったのですがどうもpythonのバージョンに原因があったようです。

私の環境はmacOS High Sierra

  • Homebrew > pyenv > Anaconda(複数の仮想環境)

みたいな感じになっています。(たぶん)

で、全体(pyenv global)はPython 3.70となっています。 この状態でhomebrewからPyMOLをインストールしたためか、importしようとしたPyMOLは以下のディレクトリ 「/usr/local/Cellar/pymol/2.3.0/libexec/lib/python3.7/site-packages」 を呼びに行っていました(先の記事でpathを通した所)。
如何にもpython3.7に紐づいていそうな場所です。

また、別の話として、色々とソフトウェアをインストールするためにAnacondaで複数の仮想環境を作成し、 jupyter notebookのカーネルに追加、切り替えつつ使おうとしています。どうやらここに問題がありそうでした。

先の記事で使用した仮想環境(カーネル)のpythonのバージョンを確認したところPython 3.6.10となっていました。 そこで別のPython 3.70の仮想環境に切り替えたところ、エラーは出ずにimport pymolすることができました。(pathを通す必要はありました)

おそらくPythonのバージョンをきちんと合わせておけば問題なく使用できるのではないでしょうか? また確認不足で誤情報を垂れ流してしまった。。。すみません。

解決策1)シンボリックリンクの作成

ではでは、教えていただいた方法をご紹介したいと思います!
まずは@Ag_smith先生に教えていただいた方法です。

先の記事では怪しげなファイル「_cmd.cpython-37m-darwin.so」をコピペして「_cmd.so」に名前を変えるという荒技を行いました。 これだと思わぬ不具合を起こす可能性があるということで、こういう場合はシンボリックリンクを作成すれば良いそうです。

シンボリックリンクUNIX系のOS(MacLinuxで、Windowsショートカットに相当するものだそうです。*1*2

つまり「_cmd.cpython-37m-darwin.so」のシンボリックリンクとして「_cmd.so」を作成しておけば、 import pymolシンボリックリンクを中継として本体のファイルに辿りつくことができる、ということのようです。

作成方法は簡単で、ターミナルで以下を実行すればOKです。

# シンボリックリンクを作成したいファイルが入っているディレクトリに移動
cd /usr/local/Cellar/pymol/2.3.0/libexec/lib/python3.7/site-packages/pymol

# 「ln -s 本体のファイル リンクの名前」でシンボリックリンクを作成
ln -s _cmd.cpython-37m-darwin.so _cmd.so

できました!

f:id:magattaca:20200321225101p:plain

だそうです。「種類:エイリアス」となっていますがエイリアスシンボリックリンクは微妙に機能が違うらしい・・・。 このあとjupyter notebookで(エラーの出ていたpython 3.6の仮想環境でも)import pymolできることを確認しました。

スマート!

解決策2)インストール方法を変える(Anaconda CloudのSchrödinger社のチャンネルを利用)

さて、もう一つの解決方法は@kira_kira_worldさんに教えていただいたもので、 condaでSchrödinger社のチャンネルからPyMOLをインストールするというものです。

1行でOK!

conda install -c schrodinger pymol

ですが注意点があります。こちらはSchrödinger社が配布しているものだということです。

Wikipediaによると、 もともとPyMOLはWarren L. DeLano氏により開発されたオープンソースのソフトウェアで、 現在はSchrödinger社によって商品化されているとのことです。 ですので、上記の方法で入手可能なPyMOLはライセンスに注意が必要そうです。

私はライセンス等に詳しくなく判断ができないので、以下手に入る情報を共有させていただきます。(←コンプライアンスを意識した発言)

まずはSchrödinger社のPyMOLのページ
2020年03月20日現在、こちらではPyMOL 2.3のダウンロードが可能です(Python 3.7を含むそう)。 WindowsmacOSLinuxそれぞれのインストーラ、および上記のAnaconda Channelを利用する方法が提供されています。 また、ライセンスの購入方法についてもリンクがあります。

さらにスクロールしていくとOpen-Source Philosophyの文字が・・・
Schrödinger社が商用として維持、開発しているものの、元々のDelano氏の意向を引き続き大枠をオープンソースプロジェクトとしているようです。 したがってほとんどのソースコードGitHub上で公開されています。ページのリンクはこちら

Homebrew経由でインストールを行った際にも、ソースコードは上記のGithubから取得しているようです。 @Ag_smith先生の記事に記載されていて、 GitHubのHomebrewのFomulraでも取得先URLを確認できます。

では、Schrödinger社コンパイル済みのものをインストールした場合どうなるのでしょうか?試してみます。

テストのための仮想環境を作成し、condaで取得します。ちなみにAnaconda CloudのPyMolページはこちら

# pythonのバージョンを指定して仮想環境pymoltestを作成
conda create -n pymoltest python=3.7

# 仮想環境をactivate
conda activate pymoltest

# PyMOLをインストール
conda install -c schrodinger pymol

# PyMOLを起動
pymol

無事PyMOLのウインドウが立ち上がりました!

f:id:magattaca:20200321225337p:plain

ただしHomebrew経由のインストールとは明確な違いが!

同時にActivationのウィンドウが立ち上がります。
「オフィシャル版なのでライセンスを持っているならactivationしてくださいね」ということのようです。 ライセンスがない場合、評価版として30日間使用することができるようです(skip activation)。

評価期間がすぎると「ウィンドウにNo License Fileの表示がされ使えなくなる機能がある」、とのことですが もうすでにNo License Fileの文字が見えますし、30日すぎるとどうなるのかはまだわかりません。

ちなみに学生であればライセンスは無料で取得することができるそうです。が、私はとうに学生ではなくなってしまったのでとりあえずskip activationで先に進めたいと思います。

さて、こちらのPyMOLがjupyter notebookでimportできるか検証したいと思います。 まず準備としてcondaの仮想環境をjupyter notebookに認識させます。

# 以下ターミナルで実行
# jupyter notebookのカーネルに仮想環境を追加
python -m ipykernel install --user --name pymoltest

# 一旦、仮想環境を抜けます
conda deactivate

また、インストールしたPyMOLの場所を確認するため、PyMOLのコマンド枠で以下を打ち込みます。

import sys
print(sys.path)

今回、それっぽいpathは「'/Users/XXXXX/.pyenv/versions/anaconda3-5.3.1/envs/pymoltest/lib/python3.7/site-packages'」でした(XXXXXは実際にはユーザーアカウント名ですが恥ずかしいので隠しています)。 condaの仮想環境pymoltestの中に入っていることがわかりやすいですね。

準備できたのでjupyter notebookを起動、新しいnotebookを作成してChange kernelでkernelをpymoltestに切り替えます。

f:id:magattaca:20200321225534p:plain

前回同様、pathを通してpymolをimportしてみます。

import sys
sys.path.append('/Users/XXXXX/.pyenv/versions/anaconda3-5.3.1/envs/pymoltest/lib/python3.7/site-packages') # XXXXXは実際にはユーザーアカウント名

import pymol

# importしたpymolのpathを確認
print(pymol.__path__)

無事importすることができました!! PATHも指定したものとなっていました!

ちなみにpython 3.6の仮想環境のkernelで上記を実行したところ、前回記事同様に「モジュールpymol._cmdが見つからない」というエラーがでてimportできませんでした。 やはりバージョンの確認が大事そうですね。

何はともあれconda経由でもPyMolのインストールとCUIの利用が可能であることが確認できました!

目的は達成できたので、とりあえずオープンソース版での利用することとして仮想環境ごと削除しておきます。

# 以下ターミナルで実行
# jupyter notebookのカーネルからアンインストールしておく
jupyter kernelspec uninstall pymoltest

# condaの仮想環境を削除
conda remove -n pymoltest --all

ターミナルを一度落としてから再度立ち上げpymolを実行することでオープンソース版のPyMOLが立ち上がることを確認できました。

_cmdはどこからきたのか?

さて、jupyter notebookからPyMOLをimportする際の不具合は

  • Pythonのversion違いである可能性がある

こと、解決策として

があることまでわかりました。

で、今回importエラーとなった「pymol._cmd」とは何者か?もう少し調べてみたいと思います。

Github Open-Source PyMOL上でオープンソースソースコードを確認してみましたが、 ディレクトmodules/pymolの中にcmd.pyはあるものの_cmdに相当するものはありませんでした。

ビルド(?)する際に作成されたのかな?ということでsetup.pyの中身を確認したところ以下のコードに行き当たりました。

from distutils.core import setup, Extension
# ~ 中略 ~
ext_modules += [
    Extension("pymol._cmd",
              get_sources(pymol_src_dirs),
              include_dirs = inc_dirs,
              libraries = libs,
              library_dirs = lib_dirs,
              define_macros = def_macros,
              extra_link_args = ext_link_args,
              extra_compile_args = ext_comp_args,
              extra_objects = ext_objects,
    ),
# ~以下略~

distutilsPythonのモジュール配布のためのユーティリティで *3Extensionは「C/C++拡張モジュールをセットアップスクリプトで表すために使われ」るそうです*4

Extensionの説明と引数(argument)の内容からソースコードからビルドに伴って作成されたC/C++関連のファイルということがなんとなくぼんやりとわかりました。 これを踏まえて「_cmd.cpython-37m-darwin.so」というファイル名を再度眺めてみます。

前回邪魔なのではと削除してしまった「cpython-37m-darwin」の部分ですが、こちらはCythonでコンパイルする際に追加される接尾辞(suffix)のようです*5。 CythonはPythonの「処理速度が遅い」という問題を解決するためにC/C++に変換するもの(????)で*6、 また、darwinmacOSMac OS X)のベースとなっているオープンソースオペレーティングシステムDarwinのことのようです*7

なんとなくですがMacpython 3.7でC/C++関連のコンパイルを行うことで作成されたファイルという感じでしょうか?(・・・浅い理解)

python 3.7に紐づいているからpython 3.6の仮想環境ではうまく動かなかったのかもしれませんね!(平然と誤情報を垂れ流すよ!!)

まとめ

以上、前回に引き続きPyMOLのCUIを利用するための方法についてでした。 適当な記事を書くとすぐに解決策が教えていただけるのでオープンソースのコミュニティに感謝感謝です。ありがとうございました!!

今回も適当調べで誤情報多そうなのでご指摘いただければ幸いです。ではでは!