可視化#

数値はどれだけかを教え、絵はどこで・なぜかを教えます。本章は 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

5

1 軌道(0 始まり絶対値)

範囲文字列

"10:20"

両端含む範囲

フロンティアトークン

"HOMO", "LUMO+2"

占有から解決

フロンティア範囲

"HOMO-3:LUMO+3"

ギャップ周辺の窓

混在リスト

["HOMO-1", "HOMO", 5]

任意の組み合わせ

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

  1. m.orbitals は HOMO を番号 4(占有 2.0)、LUMO を番号 5(占有 0.0)と示します。view3d の呼び出しを 2 つ 書きなさい:HOMO だけのものと、HOMO−1 から LUMO+1 までのギャラリー。

  2. 同僚に、Python なしでブラウザで開けるインタラクティブな 3 次元軌道を渡したいです。どのメソッドがそれを作り、 ファイルがオフラインで動くのはなぜですか。

  3. ノートブックが ImportError: qc.view 3D rendering needs py3Dmol を出しました。1 行の対処は何で、2 次元の plot_* がそれなしでも動くのはなぜですか。

次はログと出力の章で、実行が出力するものの読み取り・再生・保存を扱います。その後、大規模な 分子物性スイートに到達します。その実空間場こそ view3d が描くものです。