Python による RDKit 練習ノート
「RDKitドキュメンテーション非公式日本語版」の「Python で RDKit を始めよう」というページを教材として勉強しています.
「Python で RDKit を始めよう」はインタラクティブモード(対話モード)の解説ですが,スクリプトモードに改変しています.
スクリプトを作成するに際し,RDKit API リファレンスを参照して,メソッドのキーワード引数を理解することを目指します.
RDKit はクラス,メソッド,メソッドの引数が多くて憶えきれないけれども,API リファレンスが読めれば何とかなる,かも,というわけです.
インフォメーション
オンラインドキュメント
RDKit: Open-Source Cheminformatics Software は "Usefl Links" からなる簡素なページです.そこで見つかる下記ドキュメントで勉強しました.
- Japanese translation of the documentation:リンク先のページタイトルは「RDKitドキュメンテーション非公式日本語版サイト」
- Python で RDKit を始めよう:「RDKitドキュメンテーション非公式日本語版サイト」内のページ.「始めよう」と略します
- The RDKit Documentation — The RDKit 2025.09.1 documentation:"Document" と略します
- Python API Reference — The RDKit 2023.09.4 documentation:Document 内のページ."API Reference" と略します
関連パッケージのインストール
このページは Debian ”trixie” 上で作成しています.使用している主な Debian パッケージを示します.
| パッケージ名(バージョン) | 注 |
| python3(3.13.5) | インストール済みだったのですがバージョンを記しておきます |
| python3-rdkit | Debian パッケージのページには,Collection of cheminformatics and machine-learning software と書いてあります |
| libboost-numpy1.83.0(1.83.0) | python3-rdkit のインストール時に依存性によりインストールされました |
| rdkit-data(202503.1) | python3-rdkit のインストール時に依存性によりインストールされました |
| rdkit-doc(202503.1) | 念の為にインストールしておきました./usr/share/doc/rdkit/html/ 以下にインストールされます.RDKit のコピーのようです |
目次(ページ内リンク)
最初の例
サンプルコード 1
「始めよう」の冒頭部分から抜粋・改変して単純なサンプルコードを作成してみました.
このコードは,ベンゼンの骨格を SMILES 形式の文字列から作成し,MDL MOL 形式で出力します.
「始めよう」には,「基本的な分子を取り扱う機能の多くは rdkit.Chem モジュールに含まれています」と書いてあります.サンプルコード 1 でも rdkit.Chem モジュールのメソッドを使っています.
from rdkit import Chem
tmp_mol = Chem.MolFromSmiles(SMILES='c1ccccc1') #rdkit.Chem.rdchem.Mol オブジェクトを生成.キーワード引数で引数を与えている
tmp_str = Chem.MolToMolBlock(mol=tmp_mol) #MDL MOL 形式の文字列を生成.キーワード引数で引数を与えている
print(tmp_str)
Python のメソッドの引数には,位置引数とキーワード引数があります.このページの最後のセクション補遺 メソッドのキーワード引数と位置引数で勉強しています.
Chem.MolFromSmiles() メソッド
SMILES 形式の文字列から rdkit.Chem.rdchem.Mol オブジェクトを生成するメソッドです.
API Reference では,rdkit.Chem.rdmolfiles module 内に Chem.MolFromSmiles() が見つかります.
2 つの書式が記されています.これらの関係は執筆時点では解りません.
- rdkit.Chem.rdmolfiles.MolFromSmiles((AtomPairsParameters)SMILES, (SmilesParserParams)params) → Mol : #これはメソッドセクションのタイトル
- MolFromSmiles( (AtomPairsParameters)SMILES [, (bool)sanitize=True [, (dict)replacements={}]]) -> Mol : #これはセクションの途中にある,引数を明示した書式
ここでは,引数を明示した書式に注目します.引数が (SmilesParserParams)params である書式は後回しにします.
第二引数以降にはデフォルト引数が設定されているので省略可能です.
後者のメソッドを引数リスト [] に注目して箇条書きにしてみます.
- MolFromSmiles(
- (AtomPairsParameters)SMILES #SMILES 形式の文字列
- [, (bool)sanitize=True #真理値型.Molecular Sanitization を見るとデータ構造を矛盾のないものに調整するかということ
- [, (dict)replacements={}]] #辞書型
- -> Mol :
サンプルコード 1 では,第一引数 (AtomPairsParameters)SMILES の部分に 'c1ccccc1' を充てて SMILES='c1ccccc1' としています.
第二引数と第三引数は省略しているので,デフォルト引数が充てられます.
メソッドの戻り値は,"→ Mol" で示されています.Mol オブジェクトの作成に失敗した場合は,None を返すとのことです.
この Mol クラスに関するページは,API Reference では rdkit.Chem.rdchem.Mol に記されています.
Mol クラスには,分子,原子,結合の状態を取得したり,分子を編集したりするメソッドが見つかります.
Chem.MolToMolBlock() メソッド
API Reference では,Chem.MolToMolBlock() です.API リファレンスには 2 種類の書式が記されています.
- rdkit.Chem.rdmolfiles.MolToMolBlock((Mol)mol, (MolWriterParams)params[, (int)confId=-1]) → str : #これはメソッドセクションのタイトル
- MolToMolBlock( (Mol)mol [, (bool)includeStereo=True [, (int)confId=-1 [, (bool)kekulize=True [, (bool)forceV3000=False]]]]) -> str : #これは引数を明示した書式
上と同様に,引数を明示した書式に注目して,引数を箇条書きにしてみると,
- MolToMolBlock((Mol)mol
- [, (bool)includeStereo=True #出力に立体化学情報を含めるか
- [, (int)confId=-1 #出力するコンフォメーション.デフォルト引数は -1
- [, (bool)kekulize=True #分子をケクレ化するか
- [, (bool)forceV3000=False]]]]) #V3000 形式で出力するか.これは高分子用の形式.原子数が 999 以上だと自動的に実行される
- → str :
サンプルコード 1 では,第一引数 (Mol)mol の部分にコード内で作成した tmp_mol を充てて mol=tmp_mol としています.
第二引数以降はデフォルト引数が与えられているので,省略しています.
戻り値は"→ str" すなわち,文字列です.もう少し詳しく言うと,MDL MOL 形式で分子が表現された文字列です.
実行
サンプルコード 1 を sample1.py という名前で保存し,そのディレクトリで,
~$ python3 sample1.py
としたら,下の内容が表示されました.
(1 行目には分子名を記す)
RDKit 2D
(3 行めはコメント行)
6 6 0 0 0 0 0 0 0 0999 V2000
1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
0.7500 -1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.7500 -1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.7500 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
0.7500 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 2 0
2 3 1 0
3 4 2 0
4 5 1 0
5 6 2 0
6 1 1 0
M END
引数の構造をもう少し
Chem.MolFromSmiles() メソッドを再掲すると,
- rdkit.Chem.rdmolfiles.MolFromSmiles((AtomPairsParameters)SMILES, (SmilesParserParams)params) → Mol : #これはメソッドセクションのタイトル
- MolFromSmiles( (AtomPairsParameters)SMILES [, (bool)sanitize=True [, (dict)replacements={}]]) -> Mol : #これは引数を明示した書式
サンプルコード1では,後者の,引数を明示した書式に注目してコードを書いています.この書式では,第二引数以降は [] で括られており,リスト構造であると判ります.
前者の,メソッドセクションのタイトルの書式では,このリストに該当する箇所を (SmilesParserParams)param と書いています.
理解を進めるために,この '(SmilesParserParams)parms' について調べてみます.
API リファレンス class rdkit.Chem.rdmolfiles.SmilesParserParams((object)arg1) を見るとクラスと判ります.説明には,"Parameters controlling SMILES Parsing" とあります.ちなみに,C++ のAPI リファレンスを見ると構造体でした.
どうやら,SMILES 形式から rdkit.Chem.rdchem.Mol を構築するためのパラメータを格納しておくクラスオブジェクトのようです.
サンプルコード 2
サンプルコード 2 では,params の attribute のデフォルト値を出力したり,代入したりするコードを書いてみました.
from rdkit import Chem
# まず,prm オブジェクトを作成
prm = Chem.SmilesParserParams()
# prm のデフォルト値を出力
print("prm のデフォルト値")
print(prm.allowCXSMILES, prm.debugParse, prm.parseName, prm.removeHs, prm.sanitize, prm.strictCXSMILES)
# 代入可能なことを,デフォルト値を代入して確認(いったん値を出力させ,その出力を記述した)
prm.allowCXSMILES = True
prm.debugParse = False
prm.parseName = True
prm.removeHs = True
prm.sanitize = True
prm.strictCXSMILES = True
# prm の変更後の値を出力(実際は変更していませんが)
print("prm の変更後の値")
print(prm.allowCXSMILES, prm.debugParse, prm.parseName, prm.removeHs, prm.sanitize, prm.strictCXSMILES)
# 上で書き換えた prm を第二引数にして分子を構築
mol0 = Chem.MolFromSmiles(SMILES='c1ccccc1', params=prm)
tmp_str = Chem.MolToMolBlock(mol=mol0)
#print(tmp_str) # 出力はサンプルコード1と同じなのでコメントアウト
MolFromSmiles() メソッドの第二引数 params について
第二引数の SmilesParserParams の attribute を箇条書きにすると,
- property allowCXSMILES:controls whether or not the CXSMILES extensions are parsed
- property debugParse:controls the amount of debugging information produced
- property parseName:controls whether or not the molecule name is also parsed
- property removeHs:controls whether or not Hs are removed before the molecule is returned
- property sanitize:controls whether or not the molecule is sanitized before being returned
- property strictCXSMILES:controls whether or not problems in CXSMILES parsing causes molecule parsing to fail
さらに API Reference をページ内検索すると,以下のセクションへのリンクを見つけることができます.
- CXSMILES/CXSMARTS extensions:SMILES/SMARTS の ChemAxon 拡張
- Reading molecule names:RDKit Mol オブジェクトの Name の構文解析拡張
- Molecular Sanitization:RDKit Mol オブジェクトのデータ構造を矛盾のないものに調整する
実行
サンプルコード 2 を sample2.py という名前で保存し,そのディレクトリで,
~$ python3 sample2.py
としたら,下の内容が表示されました.
デフォルト値以外の引数でどのように動作が変わるのか,調べる準備が整いました.
prm のデフォルト値 True 0 True True True True prm の変更後の値 True 0 True True True True
引数を設定してみる
サンプルコード 1 を少し変えて,引数を与える例を書いてみました.
サンプルコード 3
from rdkit import Chem
tmp_mol = Chem.MolFromSmiles(SMILES='Xc1cYccc1', sanitize=True, replacements={'X':'F', 'Y':'n'}) #SMILE 形式の原子を辞書 replacement にしたがって置換
tmp_str = Chem.MolToMolBlock(tmp_mol, forceV3000=True) #V3000 形式で出力.他の引数は省略している
print(tmp_str)
rplacement を使うには,置換されるべき原子を SMILES 引数のなかに書いておき,辞書型引数である replacement で置換すべき原子を与えます.
この例では 'X' が 'F' に,'Y' が 'N'(SMILES 形式では芳香環の窒素は小文字の 'n')に置き換わります.
V3000 形式で出力するには,forceV3000=True とします.
実行
サンプルコード 3 を sample3.py という名前で保存し,そのディレクトリで,
~$ python3 sample3.py
としたら,下の内容が表示されました.うまく行ったようです.
(1 行目には分子名を記す)
RDKit 2D
(3 行めはコメント行)
0 0 0 0 0 0 0 0 0 0999 V3000
M V30 BEGIN CTAB
M V30 COUNTS 7 7 0 0 0
M V30 BEGIN ATOM
M V30 1 F 3.000000 0.000000 0.000000 0
M V30 2 C 1.500000 0.000000 0.000000 0
M V30 3 C 0.750000 -1.299038 0.000000 0
M V30 4 N -0.750000 -1.299038 0.000000 0
M V30 5 C -1.500000 0.000000 0.000000 0
M V30 6 C -0.750000 1.299038 0.000000 0
M V30 7 C 0.750000 1.299038 0.000000 0
M V30 END ATOM
M V30 BEGIN BOND
M V30 1 1 1 2
M V30 2 2 2 3
M V30 3 1 3 4
M V30 4 2 4 5
M V30 5 1 5 6
M V30 6 2 6 7
M V30 7 1 7 2
M V30 END BOND
M V30 END CTAB
M END
ファイルを開く
「始めよう」の冒頭で,MDL MOL 形式のファイルを開くメソッドが紹介されています.そのまま引用すると,
m = Chem.MolFromMolFile('data/input.mol')
このメソッドを API Reference で探すと,次の項目が見つかります.
rdkit.Chem.rdmolfiles.MolFromMolFile((str)molFileName[, (bool)sanitize=True[, (bool)removeHs=True[, (bool)strictParsing=True]]]) → Mol :
このメソッドは,名前が示すように MDL MOL 形式のファイルを読み込んで,rdkit.Chem.rdchem.Mol 返します.
引数リスト [] に注目して引数を箇条書きにすると下のようになります.第二引数以降は省略可能で,デフォルト引数はすべて True です.
- MolFromMolFile((str)molFileName
- [, (bool)sanitize=True
- [, (bool)removeHs=True
- [, (bool)strictParsing=True]]])
- → Mol :
分子ファイル
このメソッドはファイルを開くメソッドなので,カレントディレクトリに MDL MOL 形式の mol0.mol ファイルを作成しておきます.すなわち,
(1 行目には分子名を記す)
RDKit 3D
(3 行めはコメント行)
2 1 0 0 0 0 0 0 0 0999 V2000
-0.6290 -0.4450 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
0.6290 0.4450 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
M END
サンプルコード 4
mol0.mol を読み取るサンプルコードを作成しました.
下のコードは,カレントディレクトリにあるmol0.mol を読み込んで,その内容を端末に出力します.
from rdkit import Chem
tmp_mol = Chem.MolFromMolFile(molFileName='./mol0.mol') #rdkit.Chem.rdchem.Mol を生成
tmp_str = Chem.MolToMolBlock(mol=tmp_mol) #MDL MOL 形式の文字列を生成
print(tmp_str)
実行
サンプルコード 4 を sample4.py という名前で,カレントディレクトリに保存したものとします.
そのディレクトリで,
~$ python3 sample4.py
としたら,mol0.mol の内容が端末に表示されました.1 行めの内容は表示されましたが,3 行めの内容は表示されませんでした.
(1 行目には分子名を記す)
RDKit 3D
2 1 0 0 0 0 0 0 0 0999 V2000
-0.6290 -0.4450 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
0.6290 0.4450 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
M END
ファイルに保存
サンプルコード 5
「始めよう」の冒頭部分から,ファイル出力している文をピックアップして,サンプルコードにまとめました.
from rdkit import Chem
#SMILES 形式から rdkit.Chem.rdchem.Mol オブジェクトを生成.サンプルコード 1 と同じ方法
methane = Chem.MolFromSmiles(SMILES='C')
ethane = Chem.MolFromSmiles(SMILES='CC')
mol_list = [methane, ethane] #methane と ethane からなるリスト
#MOL MOL 形式で methane をファイル出力.ファイル名は methane.mol.
print(Chem.MolToMolBlock(methane), file=open('methane.mol', 'w'))
#SDF 形式で mol_list をファイル出力.ファイル名は mol_list.sdf.
write = Chem.SDWriter('mol_list.sdf')
for m in mol_list:
write.write(m)
#SMILES 形式で mol_list をファイル出力.ファイル名は mol_list.sdf.
write = Chem.SmilesWriter('mol_list.sml')
for m in mol_list:
write.write(m)
これまでに API Reference を読む練習をしたので,API Reference へのリンクを作成すれば充分かと思います.
MolToMolBlock() はメソッド,SDWriter と SmilesWriter はクラスです.
- rdkit.Chem.rdmolfiles.MolToMolBlock((Mol)mol[, (bool)includeStereo=True[, (int)confId=-1[, (bool)kekulize=True[, (bool)forceV3000=False]]]]) → str :
- class rdkit.Chem.rdmolfiles.SDWriter((AtomPairsParameters)arg1, (AtomPairsParameters)arg2)
- class rdkit.Chem.rdmolfiles.SmilesWriter((AtomPairsParameters)arg1, (AtomPairsParameters)fileObj[, (str)delimiter=' '[, (str)nameHeader='Name'[, (bool)includeHeader=True[, (bool)isomericSmiles=True[, (bool)kekuleSmiles=False]]]]])
実行
サンプルコード 5 を sample5.py という名前で保存し,そのディレクトリで,
~$ python3 sample5.py
としたら,methane.mol,mol_list.sdf,および mol_list.sml というファイルが生成しました.それぞれの内容を記します.
methane.mol
(ここは空行)
RDKit 2D
(ここは空行)
1 0 0 0 0 0 0 0 0 0999 V2000
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
M END
mol_list.sdf
(ここは空行)
RDKit 2D
(ここは空行)
1 0 0 0 0 0 0 0 0 0999 V2000
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
M END
$$$$
(ここは空行)
RDKit 2D
(ここは空行)
2 1 0 0 0 0 0 0 0 0999 V2000
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1.2990 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
M END
$$$$
mol_list.sml
SMILES Name C 0 CC 1
補遺 メソッドのキーワード引数と位置引数
Python のメソッドには位置引数とキーワード引数があります.Python の習熟を意図して,この場を利用して復習しました.
Python における実引数
3.14.0 Documentation の用語集を見ると,Python の引数には 2 種類あります.キーワード引数と位置引数です.注釈を付けつつ引用します.
キーワード引数: メソッド呼び出しの際に引数の前に識別子がついたものや, ** に続けた辞書の中の値として渡された引数.
このページで作成したコードのキーワード引数は「引数の前に識別子がついたもの」ということでした.
例えば,次の complex() の呼び出しでは, 3 と 5 がキーワード引数です:
- complex(real=3, imag=5)
- complex(**{'real': 3, 'imag': 5})
位置引数: キーワード引数以外の引数.
位置引数は引数リストの先頭に書くことができ,また * に続けた iterable の要素として渡すことができます.
例えば,次の例では 3 と 5 は両方共位置引数です:
- complex(3, 5)
- complex(*(3, 5))
引数の書式
もう少し具体的な説明が,Python チュートリアルにあります.4.9. 関数定義についてもう少し.
いくつか文言を引用します.
- キーワード引数は位置引数の後でなければならない
- キーワード引数は全て,メソッドで受け付けられる引数のいずれかに対応していなければならない
- キーワード引数の順序は重要ではない
- いかなる引数も値を複数回は受け取れない
例えば,サンプルコード 3 で書いた
Chem.MolToMolBlock(tmp_mol, forceV3000=True)
は,位置引数とキーワード引数を組み合わせた書式でした.
サンプルコード
これらを踏まえて練習をしたときのコードを載せておきます.
最初に関数を定義し,その跡でいろいろな書式で呼び出しています.
def tmp_func(num:int=123, string:str='qwerty'):
if type(num) != (int):
print("num 型エラー")
return
if type(string) != (str):
print("string 型エラー")
return
print(type(num), type(string))
print(num, string)
# キーワード引数を使うと,引数の順番を入れ替えてもエラーにならないし,任意の引数を省略できる
print("Case 0:キーワード引数")
tmp_func(num=456, string="Hello")
print('\n',"Case 1:キーワード引数")
tmp_func(string="Hello", num=456)
print('\n',"Case 2:キーワード引数")
tmp_func(string="Hello")
print('\n',"Case 3:キーワード引数")
tmp_func(num=456)
print('\n',"Case 4:位置引数")
tmp_func(456, "Hello")
print('\n',"Case 5:位置引数")
tmp_func(456)
# キーワード引数と位置引数の混在
print('\n',"Case 6:キーワード引数と位置引数の混在")
tmp_func(456, string="Hello")
# これはエラーになる.ので,コメントアウトしている
#print('\n',"Case 7:キーワード引数と位置引数の混在")
#tmp_func(string="Hello", 456)
# 位置引数の型エラー
# def tmp_func() メソッドの if 文をコメントアウトするとエラーにならず,端末に出力される
# もちろん,引数で何らかの処理をするとエラーになる可能性が高い
print('\n',"Case 8:位置引数")
tmp_func("Hello", 456)