rowan について
rowanは、分子構造を扱う研究者や開発者向けのクラウド量子化学計算用Python SDKです。ジョブの実行と保存を担い、量子化学ソフトをローカルに導入せずにエネルギー、構造、電子物性を取得できます。
主な機能
- 01DFT・半経験的計算
- 02構造最適化と配座探索
- 03ねじれエネルギースキャン
- 04単一点分子物性計算
- 05一括ジョブ送信と結果取得
活用シーン
- 01候補分子の構造最適化
- 02エネルギーによる配座順位付け
- 03ねじれエネルギー曲線の比較
- 04電荷とHOMO/LUMO準位の計算
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jaechang-hits/ sciagent-skills --skill rowanインストール後、Claude Code で/rowanを入力して読み込まれたか確認します。
詳細
rowan
概要
Rowan は、DFT および半経験的計算を Python SDK(rowan)を通じて利用できる、クラウド量子化学プラットフォームです。Python スクリプトや Jupyter ノートブックから計算(構造最適化、配座生成、ねじれ角スキャン、単一点エネルギー計算)を送信し、Gaussian、ORCA、Psi4 のインストールを管理することなく、結果(エネルギー、構造、部分電荷、フロンティア軌道エネルギー)を取得できます。Rowan がジョブのキューイング、実行、保存を処理します。学術研究や探索的な利用向けに無料プランが用意されています。
使用する場面
- 小分子の構造最適化:DFT を使用して、医薬品候補、フラグメント、ビルディングブロックの正確な平衡構造を取得します。
- エネルギー順位付けによる配座生成:複数の配座を生成して最適化し、ドッキングや物性予測に適した最低エネルギー配座を特定します。
- ねじれ角ポテンシャルスキャン:回転可能な結合に沿ったエネルギープロファイルをマッピングし、配座の選好を把握します。
- 量子化学的な物性計算:双極子モーメント、部分電荷(Mulliken、ESP)、HOMO/LUMO エネルギー、静電ポテンシャル面を計算します。
- ドッキング前のエネルギー最小化:構造ベースのドッキングツール(DiffDock、AutoDock Vina)に入力する前に、リガンド構造を調整します。
- 異性体の安定性比較:互変異性体、立体異性体、構造異性体の相対エネルギーを計算します。
- 大規模な配座スクリーニング(1000 分子超)には、RDKit の ETKDGv3 + MMFF を使用してください(力場レベルで、クラウド費用はかかりません)。
- タンパク質規模の量子化学/分子力学(QM/MM)には、ORCA + CP2K などの専用パッケージが必要です。
前提条件
- Python パッケージ:
rowan(公式 Python SDK) - アカウント:https://rowan.chem.ucla.edu/(学術向け)または https://rowanquantum.com/ の無料アカウント
- API キー:アカウント作成後、環境変数
ROWAN_API_KEYを設定します - データ要件:SMILES 文字列または XYZ 座標ブロック形式の分子構造
pip install rowan
# Set API key (add to .bashrc or .env)
export ROWAN_API_KEY="your_api_key_here"
クイックスタート
import rowan
# Authenticate (uses ROWAN_API_KEY environment variable automatically)
client = rowan.RowanClient()
# Run geometry optimization of aspirin at GFN2-xTB level
job = client.compute(
smiles="CC(=O)Oc1ccccc1C(=O)O",
method="gfn2-xtb",
tasks=["optimize"],
)
print(f"Job ID: {job.id}, Status: {job.status}")
# Wait for completion and retrieve energy
result = client.wait(job.id)
print(f"Energy: {result.energy:.6f} Hartree")
print(f"Optimized geometry atoms: {len(result.geometry.atoms)}")
コア API
モジュール 1:クライアントの初期化と認証
import rowan
import os
# Option 1: automatic (reads ROWAN_API_KEY env variable)
client = rowan.RowanClient()
# Option 2: explicit key
client = rowan.RowanClient(api_key=os.environ["ROWAN_API_KEY"])
print(f"Authenticated as: {client.user.email}")
print(f"Organization: {client.user.organization}")
モジュール 2:構造最適化
分子構造を最も近い局所極小へ最適化します。
import rowan
client = rowan.RowanClient()
# GFN2-xTB semiempirical (fast, good for conformer screening)
job_xtb = client.compute(
smiles="CCc1ccc(cc1)NC(=O)C", # paracetamol
method="gfn2-xtb",
tasks=["optimize"],
)
result_xtb = client.wait(job_xtb.id)
print(f"xTB optimized energy: {result_xtb.energy:.6f} Hartree")
print(f"Geometry: {len(result_xtb.geometry.atoms)} atoms")
# DFT optimization: B3LYP/6-31G* (accurate, slower)
job_dft = client.compute(
smiles="CCc1ccc(cc1)NC(=O)C",
method="b3lyp",
basis_set="6-31g*",
tasks=["optimize"],
solvent="water", # implicit solvent (SMD model)
)
result_dft = client.wait(job_dft.id)
print(f"B3LYP/6-31G* energy (water): {result_dft.energy:.6f} Hartree")
print(f"Dipole moment: {result_dft.dipole_moment:.3f} Debye")
モジュール 3:配座生成
複数の 3D 配座を生成し、エネルギーで順位付けします。
import rowan
import pandas as pd
client = rowan.RowanClient()
# Generate and optimize 10 conformers at GFN2-xTB level
job = client.compute(
smiles="CC(C)CC1=CC=C(C=C1)C(C)C(=O)O", # ibuprofen
method="gfn2-xtb",
tasks=["conformers"],
n_conformers=10,
)
result = client.wait(job.id)
# Rank conformers by relative energy
conformers = result.conformers
df = pd.DataFrame([
{"conformer_id": i,
"energy_hartree": c.energy,
"rel_energy_kcal": (c.energy - min(c2.energy for c2 in conformers)) * 627.509}
for i, c in enumerate(conformers)
]).sort_values("rel_energy_kcal")
print(df.to_string(index=False))
print(f"\nLowest energy conformer ID: {df.iloc[0]['conformer_id']}")
モジュール 4:ねじれ角スキャン
二面角の関数としてエネルギーをマッピングします。
import rowan
import numpy as np
import matplotlib.pyplot as plt
client = rowan.RowanClient()
# Scan the C-C=C-C dihedral of butene
job = client.compute(
smiles="CC=CC", # but-2-ene
method="gfn2-xtb",
tasks=["torsion_scan"],
torsion_atoms=[0, 1, 2, 3], # atom indices defining dihedral
n_scan_points=36, # 36 points = 10-degree steps
)
result = client.wait(job.id)
angles = [point.angle for point in result.torsion_scan]
energies = [point.energy for point in result.torsion_scan]
rel_e = [(e - min(energies)) * 627.509 for e in energies] # convert to kcal/mol
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(angles, rel_e, "o-", color="steelblue")
ax.set_xlabel("Dihedral angle (degrees)")
ax.set_ylabel("Relative energy (kcal/mol)")
ax.set_title("Torsional potential: but-2-ene C-C=C-C dihedral")
plt.tight_layout()
plt.savefig("torsion_scan.png", dpi=150)
print("Torsion scan saved -> torsion_scan.png")
モジュール 5:単一点物性
固定された構造における電子物性(HOMO/LUMO、部分電荷、ESP)を計算します。
import rowan
client = rowan.RowanClient()
# Single-point DFT: get frontier orbital energies and partial charges
job = client.compute(
smiles="c1ccccc1N", # aniline
method="b3lyp",
basis_set="6-311+g**",
tasks=["single_point", "partial_charges", "orbitals"],
)
result = client.wait(job.id)
print(f"HOMO energy: {result.homo_energy:.4f} eV")
print(f"LUMO energy: {result.lumo_energy:.4f} eV")
print(f"HOMO-LUMO gap: {result.lumo_energy - result.homo_energy:.4f} eV")
print(f"Dipole moment: {result.dipole_moment:.3f} Debye")
# Partial charges (Mulliken)
for i, (atom, charge) in enumerate(zip(result.geometry.atoms, result.partial_charges)):
print(f" Atom {i} ({atom.symbol}): {charge:+.4f} e")
モジュール 6:バッチジョブの送信
複数の分子を並行して送信します。
import rowan
import pandas as pd
from concurrent.futures import ThreadPoolExecutor, as_completed
client = rowan.RowanClient()
smiles_list = [
("aspirin", "CC(=O)Oc1ccccc1C(=O)O"),
("caffeine", "Cn1cnc2c1c(=O)n(c(=O)n2C)C"),
("paracetamol", "CC(=O)Nc1ccc(O)cc1"),
("ibuprofen", "CC(C)Cc1ccc(cc1)C(C)C(=O)O"),
]
def submit_and_wait(name, smiles):
job = client.compute(smiles=smiles, method="gfn2-xtb", tasks=["optimize"])
result = client.wait(job.id)
return {"name": name, "smiles": smiles, "energy": result.energy}
results = []
with ThreadPoolExecutor(max_workers=4) as executor:
futures = {executor.submit(submit_and_wait, n, s): n for n, s in smiles_list}
for future in as_completed(futures):
results.append(future.result())
df = pd.DataFrame(results)
df.to_csv("batch_energies.csv", index=False)
print(df)
主なパラメーター
| パラメーター | モジュール | デフォルト | 範囲/オプション | 効果 |
|---|---|---|---|---|
method | compute | 必須 | "gfn2-xtb", "b3lyp", "wb97x-d", "mp2" | QC メソッド。xTB は最速、DFT は高精度、MP2 は電子相関の計算に使用します |
basis_set | compute (DFT) | メソッドに依存 | "6-31g*", "6-311+g**", "def2-svp", "def2-tzvp" | 基底関数系。大きいほど高精度ですが、計算は遅くなります |
tasks | compute | 必須 | ["optimize"], ["single_point"], ["conformers"], ["torsion_scan"] | 実行する計算 |
n_conformers | conformers task | 10 | 1–100 | 生成して最適化する配座の数 |
n_scan_points | torsion_scan | 36 | 12–72 | 二面角スキャンの点数(360/n がステップ幅になります) |
solvent | compute | None | "water", "dmso", "methanol", etc. | 暗黙的な SMD 溶媒和モデル |
torsion_atoms | torsion_scan | 必須 | 4 つの原子インデックスのリスト | スキャンする二面角を定義します |
ベストプラクティス
-
スクリーニングにはGFN2-xTBを、最終的な特性評価にはDFTを使用します:xTBはDFTより100〜1000倍高速で、配座ランキングや構造探索には十分です。正確なエネルギー、HOMO/LUMOギャップ、公開可能な結果を得るには、B3LYPまたはwB97X-Dに切り替えてください。
-
物性を計算する前に、必ず構造を最適化します:緩和されていない構造(SMILESからの3D埋め込みなど)を使ったシングルポイント計算では、信頼性の低いエネルギーや電子物性が得られます。最初に
tasks=["optimize"]を実行してください。 -
生物学的に重要な分子には
solventを設定します:気相のエネルギーは、帯電分子や極性の高い分子では、溶液相のエネルギーと大きく異なることがあります。水溶液条件下で評価する創薬候補には、solvent="water"を使用してください。 -
長時間のDFT計算ではジョブのステータスを確認します:長時間実行するバッチワークフローで処理がブロックされないよう、タイムアウトを指定して
client.wait()を使用するか、client.get_job(job_id).statusでポーリングしてください。 -
最適化した構造は再利用できるようXYZ形式でエクスポートします:同じ構造に対して異なる物性計算が必要な場合に、高コストなDFTジョブを再実行せずに済むよう、最適化した構造を保存してください。
with open("optimized.xyz", "w") as f: f.write(result.geometry.to_xyz())
一般的なワークフロー
ワークフロー1:配座探索と物性計算
目的:創薬候補の最低エネルギー配座を見つけ、その電子物性を計算します。
import rowan
import pandas as pd
client = rowan.RowanClient()
smiles = "CC(C)Cc1ccc(cc1)C(C)C(=O)O" # ibuprofen
# Step 1: Generate and rank conformers at fast xTB level
conf_job = client.compute(
smiles=smiles, method="gfn2-xtb", tasks=["conformers"], n_conformers=20
)
conf_result = client.wait(conf_job.id)
lowest_conf = min(conf_result.conformers, key=lambda c: c.energy)
print(f"Lowest conformer energy: {lowest_conf.energy:.6f} Hartree")
# Step 2: Refine with DFT and compute properties
dft_job = client.compute(
xyz=lowest_conf.to_xyz(), # use optimized xTB geometry as DFT start
method="b3lyp",
basis_set="6-31g*",
tasks=["optimize", "partial_charges", "orbitals"],
solvent="water",
)
dft_result = client.wait(dft_job.id)
print(f"B3LYP/6-31G* energy (water): {dft_result.energy:.6f} Hartree")
print(f"HOMO-LUMO gap: {dft_result.lumo_energy - dft_result.homo_energy:.4f} eV")
print(f"Dipole moment: {dft_result.dipole_moment:.3f} Debye")
ワークフロー2:互変異性体の相対安定性
目的:2つの互変異性体のエネルギーを比較し、水中でどちらがより安定かを判断します。
import rowan
client = rowan.RowanClient()
tautomers = {
"keto": "CC(=O)CC(=O)C", # acetylacetone keto form
"enol": "CC(=O)C=C(O)C", # acetylacetone enol form
}
energies = {}
for name, smiles in tautomers.items():
job = client.compute(
smiles=smiles,
method="b3lyp",
basis_set="6-311+g**",
tasks=["optimize"],
solvent="water",
)
result = client.wait(job.id)
energies[name] = result.energy
print(f"{name}: {result.energy:.6f} Hartree")
delta_e_hartree = energies["enol"] - energies["keto"]
delta_e_kcal = delta_e_hartree * 627.509
print(f"\nDelta E (enol - keto): {delta_e_kcal:.2f} kcal/mol")
print(f"More stable form: {'enol' if delta_e_kcal < 0 else 'keto'}")
予想される出力
result.energy— Hartree単位の全電子エネルギーresult.geometry— 最適化された3D構造(原子と座標)result.dipole_moment— Debye単位のスカラー双極子モーメントresult.homo_energy、result.lumo_energy— eV単位のフロンティア軌道エネルギーresult.partial_charges— 元素電荷単位で表した、各原子の電荷のリストresult.conformers— 個別のエネルギーを持つ配座オブジェクトのリストresult.torsion_scan— (角度、エネルギー)のスキャン点のリスト
よく使うレシピ
レシピ:高速シングルポイントエネルギー計算
使用する場面:1回の呼び出しで2つの配座または反応中間体の相対エネルギーを比較します。
import rowan
client = rowan.Client()
smiles_list = ["CC(=O)O", "C(=O)(O)C"] # Acetic acid, two representations
jobs = []
for smi in smiles_list:
job = client.compute(
molecule=rowan.Molecule.from_smiles(smi),
theory_level="gfn2-xtb",
task="single_point",
)
jobs.append(job)
# Collect energies
for smi, job in zip(smiles_list, jobs):
result = client.wait(job)
print(f"{smi}: energy = {result.energy:.6f} Hartree")
レシピ:実行中のジョブのステータス確認
使用する場面:処理をブロックせずに、時間のかかる最適化や配座探索を監視します。
import rowan, time
client = rowan.Client()
job = client.compute(
molecule=rowan.Molecule.from_smiles("c1ccccc1"),
theory_level="gfn2-xtb",
task="optimize",
)
print(f"Job ID: {job.id}")
# Poll every 10 seconds (non-blocking)
for _ in range(30):
status = client.status(job)
print(f"Status: {status}")
if status in ("completed", "failed"):
break
time.sleep(10)
result = client.get(job)
print(f"Final energy: {result.energy:.6f} Hartree")
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
AuthenticationError | APIキーが設定されていないか、期限切れです | ROWAN_API_KEY環境変数を設定し、rowanquantum.comでキーを再生成してください |
ジョブがqueued状態のままになる | 無料プランのサーバー負荷が高い | 待機するか、有料プランにアップグレードしてください。無料プランではピーク時にキューに入ることがあります |
SCF not convergedエラー | DFTの自己無撞着場計算が収束しませんでした | より小さい基底関数系を試してください。まずmethod="gfn2-xtb"を使用して、より良い初期構造を取得してください |
ValueError: invalid SMILES | SMILES文字列の形式が正しくありません | 送信前に、RDKitのChem.MolFromSmiles(smiles)で検証してください |
| 最適化後のエネルギーが高い | 構造が局所極小にとどまっています | tasks=["conformers"]で複数の配座を生成し、最もエネルギーの低いものを選択してください |
result.homo_energyがない | 軌道計算が要求されていません | tasksリストに"orbitals"を追加してください |
参考資料
- Rowanのドキュメント — SDKとAPIの公式リファレンス
- Rowan Python SDK(GitHub) — ソースコードと例
- GFN2-xTB論文:Bannwarth et al.(2019)、J. Chem. Theory Comput. — Rowanで使用されているxTB半経験的方法
- B3LYP汎関数の参考文献:Becke(1993)、J. Chem. Phys. — DFTの基礎となる方法