1050 words
5 minutes
【計算化学】ブログ記事の遷移状態構造の虚振動のアニメーション生成pythonスクリプト
最終更新:2025-12-15
過去の記事の抜粋である。ブログ記事の遷移状態構造の虚振動のアニメーション生成を手元で行うのに便利なスクリプトを置いておく。
python 3.ⅹとASE, numpyさえあれば動くはずである。
以下、遷移状態構造。
migratory_insertion_Rh_AsCF3_3_2_C2H4_ts_final_1.xyz
36
OptimizedStructure
Rh 0.958151914527 0.092523108800 -0.496769592729
H 1.501231121468 0.233108056765 1.040216302151
C 0.803480069587 0.104833433532 -2.416926942935
O 0.758192356809 0.122464408665 -3.548518032566
C 2.957005795567 -0.071699319221 0.623941487154
C 3.057874755464 -0.445802496509 -0.729739370779
H 3.022748919493 -0.848155772730 1.377973175995
H 3.343837828960 0.888100430758 0.943161677199
H 3.157582137572 -1.494776133770 -0.974477842407
H 3.516335870909 0.242389745586 -1.426046401644
As -0.313784781338 2.017271125955 0.004136565475
As -0.356475336740 -1.870936669561 0.017863940241
C -0.422505248928 2.661070244596 1.889689280198
C 0.114783787530 3.769208436270 -0.859021574324
C -2.269670013406 1.986906003723 -0.414933185319
C -1.201087816673 -2.163146686806 1.804168903202
C -1.941297149575 -2.344805908135 -1.103865962241
C 0.590904845605 -3.629162849501 -0.096200561111
F 0.721718877363 3.295304871851 2.189296157545
F -1.434674440222 3.497707979413 2.120392993993
F -0.549064186420 1.618346939271 2.715745543089
F 1.439811460481 3.959175262177 -0.830109288397
F -0.464149686809 4.829257365032 -0.294327436700
F -0.269539766699 3.714827497028 -2.143395154607
F -2.857245270090 3.181479027595 -0.466811224298
F -2.441792355518 1.388126816966 -1.602141526104
F -2.889919911077 1.250495486638 0.516776489532
F -2.995969850986 -1.629128176519 -0.692401633655
F -1.684258200831 -2.011037052301 -2.376195287556
F -2.275270870868 -3.635492673751 -1.078865165524
F -0.233874685999 -2.442850228712 2.693110590351
F -1.805493042457 -1.034568429608 2.190787492883
F -2.100283123568 -3.147087897264 1.845131722467
F 1.789684893939 -3.500540661486 0.498686217354
F 0.805876262244 -3.921718800742 -1.388218246484
F -0.032865159314 -4.661686484001 0.467885890551以下に虚振動を可視化するスクリプトを示す。遷移状態構造をxyzファイルに保存し、以下のスクリプトをコピーして同じディレクトリ内で実行すると虚振動のアニメーションが見られるxyzファイルが出力される。ほかのブログ記事の内容に対しても、このスクリプトのLOG_TEXTの改変および対応する遷移状態構造を保存すればアニメーションを生成可能である。
import numpy as np
from ase.io import read, write
# ---------------------------------------------------------
# 1. ブログの「Normal Mode」セクションをここにコピペします
# ---------------------------------------------------------
LOG_TEXT = """
Mode 0 1 2
Freq [cm^-1] -909.3347 12.0385 20.0676
Reduced mass [au] 1.1783 12.0872 16.8805
Force const [Dyne/A] -0.5740 0.0010 0.0040
Char temp [K] 0.0000 17.3207 28.8727
Normal mode x y z x y z x y z
Rh 0.00293 -0.00230 -0.00896 -0.00926 0.00045 -0.02268 -0.00019 -0.00091 -0.00418
H 0.87899 0.05212 -0.11058 0.02243 0.00304 -0.03452 0.01531 0.00033 -0.00932
C 0.01400 0.01538 0.01514 -0.04773 0.00352 -0.02005 -0.01983 -0.00649 -0.00226
O -0.00096 -0.00249 0.00893 -0.06969 0.00654 -0.01910 -0.03206 -0.01067 -0.00184
C -0.06931 0.02242 0.05233 0.01506 -0.00373 -0.06656 0.00955 -0.00410 -0.02215
C -0.05206 -0.00050 -0.02231 -0.01787 -0.01605 -0.06534 -0.00271 -0.00187 -0.02381
H 0.13267 -0.01656 0.00744 0.02788 0.00246 -0.06133 0.01516 -0.00563 -0.02421
H 0.13983 -0.04034 0.01118 0.02615 -0.00262 -0.08352 0.01449 -0.00548 -0.02397
H 0.06118 -0.00128 0.03012 -0.02993 -0.01877 -0.05877 -0.00560 -0.00151 -0.02640
H 0.05826 -0.01582 0.03660 -0.02992 -0.02492 -0.08204 -0.00815 -0.00101 -0.02653
As -0.00179 -0.00155 0.00138 0.00204 0.00071 0.00173 0.00333 0.00115 -0.00346
As -0.00089 0.00009 0.00183 0.00015 -0.00006 0.00261 0.00085 0.00164 0.00883
C -0.00298 0.00417 -0.00256 0.00309 -0.02263 0.00984 -0.03789 -0.01174 -0.00128
C 0.00115 -0.00142 -0.00063 0.01341 0.01062 0.02732 0.02421 0.00861 0.02223
C 0.00029 0.00168 0.00034 0.00329 0.01577 -0.00479 0.01253 0.00225 -0.04520
C -0.00306 -0.00517 -0.00363 -0.01986 0.01732 -0.00375 0.02780 -0.00554 0.02013
C 0.00066 0.00029 0.00027 0.01713 -0.02674 -0.00965 -0.01831 0.00844 0.03276
C -0.00097 0.00115 -0.00059 0.01475 0.00549 0.03854 -0.00214 0.00161 -0.01713
F 0.00099 0.00001 0.00045 0.00202 -0.02379 0.01617 -0.04936 -0.00400 0.02553
F -0.00114 0.00148 0.00298 0.00146 -0.02752 0.02063 -0.04969 -0.02141 -0.01701
F 0.00083 -0.00036 -0.00101 0.00627 -0.03257 -0.00242 -0.04584 -0.01754 -0.01019
F 0.00044 -0.00049 0.00030 0.01440 0.00306 0.03299 0.02323 0.01025 0.06157
F 0.00035 -0.00125 -0.00005 0.01783 0.00559 0.04140 0.00661 0.00343 0.01393
F 0.00000 -0.00017 0.00011 0.01595 0.03126 0.02574 0.06100 0.01808 0.01085
F -0.00151 0.00063 -0.00030 0.00982 0.01959 0.00934 0.01379 0.00208 -0.06044
F 0.00022 0.00019 -0.00004 0.00440 0.03274 -0.01358 0.03718 -0.00057 -0.04754
F 0.00065 0.00044 0.00003 -0.00388 0.00630 -0.01725 -0.00708 0.00406 -0.05658
F 0.00008 -0.00023 -0.00001 0.01082 -0.01846 -0.03972 -0.01179 0.00481 0.05563
F 0.00004 0.00020 -0.00014 0.03410 -0.05411 -0.01346 -0.04066 0.01679 0.03051
F -0.00017 0.00013 0.00001 0.01793 -0.02642 0.01362 -0.01692 0.00796 0.03050
F 0.00037 0.00023 -0.00035 -0.02824 0.04209 0.01293 0.04311 0.00825 0.00791
F 0.00035 -0.00085 -0.00026 -0.03815 0.01612 -0.02901 0.01890 -0.01201 0.02517
F -0.00317 -0.00247 0.00348 -0.00916 0.00762 -0.00040 0.04047 -0.01646 0.03456
F 0.00008 0.00024 0.00021 0.00744 0.02352 0.04966 0.00822 -0.00233 -0.03706
F 0.00034 -0.00010 -0.00003 0.03126 -0.01172 0.04512 -0.02456 0.00945 -0.02267
F 0.00024 -0.00018 0.00014 0.01688 0.00872 0.04670 0.00754 -0.00164 -0.01257
"""
# ---------------------------------------------------------
def parse_mode0_vectors(text):
"""ログテキストからMode 0 (虚振動) のベクトルを抽出する"""
vectors = []
for line in text.strip().split('\n'):
parts = line.split()
# 数が少なすぎる、または "Mode" で始まる行はヘッダーなのでスキップ
if len(parts) < 4 or parts[0] == "Mode":
continue
try:
# 2, 3, 4列目(index 1, 2, 3)が数値に変換できればベクトルとみなす
# Mode 0 (x, y, z)
vec = [float(parts[1]), float(parts[2]), float(parts[3])]
vectors.append(vec)
except ValueError:
# ヘッダー行(Freq, Massなど)はここで弾かれるので無視してOK
continue
return np.array(vectors)
def generate_animation(structure_file, vectors, output_file="imaginary_mode.xyz", frames=20, amp=1.5):
"""構造とベクトルからアニメーションXYZを生成"""
atoms = read(structure_file)
initial_pos = atoms.get_positions()
if len(initial_pos) != len(vectors):
print(f"Error: 原子数({len(initial_pos)})とベクトルの行数({len(vectors)})が一致しません。")
print("ヒント: LOG_TEXTのコピペ範囲が正しいか、または不要な行が含まれていないか確認してください。")
return
images = []
for i in range(frames):
phase = 2 * np.pi * i / frames
# sin波で振動させる
new_atoms = atoms.copy()
new_atoms.set_positions(initial_pos + vectors * np.sin(phase) * amp)
images.append(new_atoms)
write(output_file, images)
print(f"Animation saved to: {output_file}")
if __name__ == "__main__":
# 構造ファイル名を指定してください
xyz_filename = "migratory_insertion_Rh_AsCF3_3_2_C2H4_ts_final_1.xyz"
# パース実行
mode0_vectors = parse_mode0_vectors(LOG_TEXT)
# アニメーション生成
generate_animation(xyz_filename, mode0_vectors, amp=2.0)【計算化学】ブログ記事の遷移状態構造の虚振動のアニメーション生成pythonスクリプト
https://ss0832.github.io/posts/20251215_imaginary_freq_animation/