可視化#
数値はどれだけかを教え、絵はどこで・なぜかを教えます。本章は SCF の密度と軌道を、確認できる画像 — 軌道や
実空間場の 3 次元等値面、2 次元プロット、収束曲線 — に変えます。すべてノートブックの中から、qc.view 層を
通じて行えます。
Tip
可視化に必要な追加パッケージ 3 次元ビューアは py3Dmol、静止画エクスポートは kaleido、2 次元プロットは matplotlib を使います。 必要なものをプロジェクト venv に入れます:
uv add py3dmol kaleido --project "$UV_PROJECT" # 3D ビューア + 静止 PNG エクスポート
(matplotlib は通常、基盤の科学スタックに含まれます。)各ビューアの入口はメソッド(mychk.view3d(...))と
関数(qc.view3d(mychk, ...))の両方で存在します。
軌道テーブル#
何かを描く前に、軌道を一覧して何を要求するか把握します。mychk.orbitals はピッキング用テーブル — 番号・
占有・エネルギー — をフロンティア軌道を印つきで表示し、ノートブックでは HTML テーブルとして描画します:
import qc
water = "O 0 0 0.117; H 0 0.757 -0.469; H 0 -0.757 -0.469"
m = qc.chk.new(atom=water, ao="cc-pvdz", unit="angstrom").scf(ref="r").run()
m.orbitals
# idx occ E(Eh) label
# --- ---- ----------- -----
# 3 2.0 -0.56656
# 4 2.0 -0.49314 HOMO
# 5 0.0 0.18604 LUMO
# 6 0.0 0.25618
番号は 0 始まりの絶対値(PySCF と同じ慣習)で、人に優しい経路はビューアも受け付ける HOMO/LUMO±n トークン
です。水/cc-pVDZ では HOMO が番号 4、LUMO が番号 5 です。
3 次元等値面:view3d#
等値面は、スカラー場がある固定値(isovalue)を取る面です — 雲のような量を 3 次元で「見る」直感的な方法です。
view3d はそれをインラインで描画し、セルの最後の式が表示します:
m.view3d("density") # 電子密度の等値面
m.view3d(orbital="HOMO") # 符号つき 2 ローブ軌道(正 赤、負 青)
m.view3d(orbitals="HOMO-2:LUMO+2") # 小さな複数図のギャラリー
m.view3d("elf", isovalue=0.8) # 選んだ等値での実空間場
スカラー場#
view3d(field) は qc-prop の実空間ファミリ全体を受け付けます — density, spin, laplacian, rdg,
iri, elf, lol, nci, igm, esp, mo, alie, deformation — それぞれ妥当な既定等値を持ちます。
描画は isovalue=, color=, style=("stick"/"sphere"/"line"), width=/height=, background=、
グリッドは spacing=/margin=(bohr)で調整します。これらの場は分子物性スイートの視覚版
です — そこで数値として計算するのと同じ ELF・NCI・ESP です。
軌道の選択#
軌道は符号つき 2 ローブ等値面として描画されます。orbital=(1 つ)または orbitals=(複数 → ギャラリー)で
選び、以下を自由に混ぜられます:
形式 |
例 |
意味 |
|---|---|---|
int |
|
1 軌道(0 始まり絶対値) |
範囲文字列 |
|
両端含む範囲 |
フロンティアトークン |
|
占有から解決 |
フロンティア範囲 |
|
ギャップ周辺の窓 |
混在リスト |
|
任意の組み合わせ |
spin="alpha"(既定)または "beta" で UHF/ROHF のチャネルを選びます。
キューブデータ:mo_cube#
絵の背後の数値が欲しいとき — Gaussian キューブをエクスポートしたり別ツールに渡したり — mo_cube はキューブ
データを構築・キャッシュし、各軌道のエネルギー・占有・キューブテキストを持つハンドルを返します:
handles = m.mo_cube("HOMO-1:LUMO+1")
[(h.orbital, round(h.energy, 3), h.occ) for h in handles]
# [(3, -0.567, 2.0), (4, -0.493, 2.0), (5, 0.186, 0.0), (6, 0.256, 0.0)]
キューブは MO 係数のハッシュをキーにセッション中メモ化されます — 軌道を変える SCF を再実行すると、古い
キューブは自動的に無効化されます(m.mo_cache / m.mo_cache.clear())。
2 次元プロット#
すべてが 3 次元向きとは限りません。3 つの matplotlib 図が一般的な平面図をカバーします:
m.plot_convergence() # SCF 収束:E, |ΔE|, RMS 勾配 をサイクルに対して
m.plot_nci() # 2 次元 NCI プロット:縮約密度勾配 s 対 sign(λ₂)ρ
m.plot_field_plane("density", ...) # 切断面上のスカラー場
plot_convergence() は SCF の最速の健全性チェック(しきい値への滑らかな下降);plot_nci() は標準的な非共有
結合相互作用の診断(低密度でのスパイクが水素結合・ファンデルワールス接触・立体反発を示す)です。各々 matplotlib
の Figure を返します。
エクスポートと共有#
3 次元ビューは自己完結の HTML ファイルに書き出せます(3Dmol.js ライブラリが埋め込まれるので、オフラインでも VSCode webview でも開けます):
m.view3d(orbital="HOMO").to_html("homo.html") # 単体 HTML
m.view3d(orbital="HOMO").to_html("homo.html", self_contained=False) # 小さく、3Dmol.js を CDN から読む
kaleido を入れると、matplotlib/plotly の図を通常どおり静止 PNG として保存できます(fig.savefig(...) /
plotly write_image)。
総合例:フロンティア軌道を見る#
import qc
water = "O 0 0 0.117; H 0 0.757 -0.469; H 0 -0.757 -0.469"
m = qc.chk.new(atom=water, ao="cc-pvdz", unit="angstrom").scf(ref="r").run()
m.orbitals # HOMO/LUMO を探す(番号 4 と 5)
m.view3d(orbitals="HOMO-1:LUMO+1") # フロンティア軌道のギャラリー
m.view3d("density").to_html("water_density.html") # 密度等値面を保存
練習 8
m.orbitalsは HOMO を番号 4(占有 2.0)、LUMO を番号 5(占有 0.0)と示します。view3dの呼び出しを 2 つ 書きなさい:HOMO だけのものと、HOMO−1 から LUMO+1 までのギャラリー。同僚に、Python なしでブラウザで開けるインタラクティブな 3 次元軌道を渡したいです。どのメソッドがそれを作り、 ファイルがオフラインで動くのはなぜですか。
ノートブックが
ImportError: qc.view 3D rendering needs py3Dmolを出しました。1 行の対処は何で、2 次元のplot_*がそれなしでも動くのはなぜですか。
解答 練習 8
m.view3d(orbital="HOMO")とm.view3d(orbitals="HOMO-1:LUMO+1")(範囲文字列がギャラリーを生む)。m.view3d(orbital="HOMO").to_html("homo.html")— 既定のself_contained=Trueで 3Dmol.js を ファイルに埋め込むので、どのブラウザでもオフラインで描画します。uv add py3dmol --project "$UV_PROJECT"(その後カーネル再起動)。2 次元プロットは別依存の matplotlib を 使うので、py3Dmol の欠如に影響されません。
次はログと出力の章で、実行が出力するものの読み取り・再生・保存を扱います。その後、大規模な
分子物性スイートに到達します。その実空間場こそ view3d が描くものです。