分子を描画するのに必要な原子座標のフォーマットは,そのソースによって異なり,どんな書式でもすんなり読めるわけではない.典型的な例は以下に示すような空白区切りである.一見問題はないように見えるが,実際はスペースが1個であったり,2個であったりする.今回,分子座標データをファイルから読み込む必要にせまられ,大いに勉強になったので,以下に纏めてみた次第である.目標は,[元素名(文字),x 座標(実数),y 座標(実数),z 座標(実数)] の(小)リストを含む(大)リストの簡単変換である.
C -2.1434 3.2205 -0.7607
C -3.3430 2.9171 0.2166
C -1.1232 2.9776 0.4164
C -2.3227 2.6737 1.3934
C -1.0470 1.4497 0.0353
H -0.2715 3.6101 0.6480
C -2.2466 1.1461 1.0121
H -2.4239 3.0636 2.4018
C -3.2668 1.3891 -0.1651
H -4.2555 3.5010 0.2884
H -2.2876 0.3210 1.7167
C -2.0673 1.6928 -1.1420
H -4.1189 0.7571 -0.3963
H -0.1345 0.8657 -0.0369
H -2.1025 4.0451 -1.4660
H -1.9661 1.3028 -2.1504
#-----------------------------ファイルの読み込み
axyz,new_axyz = [], []
for line in open('cubane-1.txt').readlines():
#for line in open('sk_81b.txt').readlines():
data = line[:-1].split(' ') # ’ 'はスペース1個を意味する
axyz.append(data) #リストの中にリストを作成
print(data)
#n=len(axyz)
#print('原子数',n);print()
#print(axyz)
=========== RESTART: /Users/KH/pythonPRG/cubane_f_read_nospace.py ===========
['', 'C', '', '-2.1434', '', '3.2205', '-0.7607'] ⬅ 2個以上のスペースは文字データとみなされる. 以下同じ.
['C', '', '-3.3430', '2.9171', '', '', '0.2166']
['', 'C', '', '-1.1232', '', '', '2.9776', '', '0.4164']
['C', '', '-2.3227', '', '', '2.6737', '', '', '1.3934']
['C', '', '-1.0470', '1.4497', '', '0.0353']
['', 'H', '', '', '-0.2715', '', '3.6101', '', '0.6480']
['C', '', '-2.2466', '', '1.1461', '', '1.0121']
['H', '', '', '', '-2.4239', '', '3.0636', '', '2.4018']
['C', '', '-3.2668', '', '1.3891', '-0.1651']
['H', '', '-4.2555', '', '', '', '3.5010', '', '0.2884']
['', 'H', '', '', '-2.2876', '', '', '', '0.3210', '', '1.7167']
['C', '', '-2.0673', '', '1.6928', '-1.1420']
['H', '', '-4.1189', '', '', '', '0.7571', '', '-0.3963']
['', 'H', '', '-0.1345', '', '0.8657', '-0.0369']
['H', '', '', '-2.1025', '', '4.0451', '', '-1.4660']
['H', '', '-1.9661', '', '1.3028', '', '', '-2.1504']
>>>
# coding: utf-8
#-----------------------------ファイルの読み込み
axyz,new_axyz = [], []
for line in open('cubane-1.txt').readlines():
data = line[:-1].split() # 括弧内は無文字
axyz.append(data) # リストの中にリストを作成
print(data)
#n=len(axyz)
#print('原子数',n);print()
#print(axyz)
['C', '-2.1434', '3.2205', '-0.7607'] ⬅ 空白が除去されているが, すべて文字データ
['C', '-3.3430', '2.9171', '0.2166']
['C', '-1.1232', '2.9776', '0.4164']
['C', '-2.3227', '2.6737', '1.3934']
['C', '-1.0470', '1.4497', '0.0353']
['H', '-0.2715', '3.6101', '0.6480']
['C', '-2.2466', '1.1461', '1.0121']
['H', '-2.4239', '3.0636', '2.4018']
['C', '-3.2668', '1.3891', '-0.1651']
['H', '-4.2555', '3.5010', '0.2884']
['H', '-2.2876', '0.3210', '1.7167']
['C', '-2.0673', '1.6928', '-1.1420']
['H', '-4.1189', '0.7571', '-0.3963']
['H', '-0.1345', '0.8657', '-0.0369']
['H', '-2.1025', '4.0451', '-1.4660']
['H', '-1.9661', '1.3028', '-2.1504']
>>>
元素記号は文字,座標は数値に変換する必要があるため,定義関数を用いて処理した.
# coding: utf-8
#-----------------------------ファイルの読み込み
#from tkinter import *
axyz,new_axyz = [], []
for line in open('cubane-1.txt').readlines():
# data = line[:-1].split(' ') #スペース区切り
data = line[:-1].split() #スペース区切りなし
print(data)
axyz.append(data) #リストの中にリストを作成
n=len(axyz)
print('原子数',n);print()
#-----------------------------定義関数
def change_to_float_if_possible(s): #変換可能の要素は実数変換
try:
return float(s)
except Exception:
return s
#-----------------------------座標のみ定義関数(例外処理)を利用して実数化
new_axyz = [[change_to_float_if_possible(e) for e in l] for l in axyz]
print(new_axyz)
=========== RESTART: /Users/KH/pythonPRG/cubane_space_exception.py ===========
['C', '-2.1434', '3.2205', '-0.7607'] ⬅ ファイル読込段階で, 不要なスペースは除去されているが, すべて文字. 座標のみ実数化が必要.
['C', '-3.3430', '2.9171', '0.2166']
['C', '-1.1232', '2.9776', '0.4164']
['C', '-2.3227', '2.6737', '1.3934']
['C', '-1.0470', '1.4497', '0.0353']
['H', '-0.2715', '3.6101', '0.6480']
['C', '-2.2466', '1.1461', '1.0121']
['H', '-2.4239', '3.0636', '2.4018']
['C', '-3.2668', '1.3891', '-0.1651']
['H', '-4.2555', '3.5010', '0.2884']
['H', '-2.2876', '0.3210', '1.7167']
['C', '-2.0673', '1.6928', '-1.1420']
['H', '-4.1189', '0.7571', '-0.3963']
['H', '-0.1345', '0.8657', '-0.0369']
['H', '-2.1025', '4.0451', '-1.4660']
['H', '-1.9661', '1.3028', '-2.1504']
原子数 16
定義関数処理により実数化されている
[['C', -2.1434, 3.2205, -0.7607], ['C', -3.343, 2.9171, 0.2166], ['C', -1.1232, 2.9776, 0.4164], ['C', -2.3227, 2.6737, 1.3934], ['C', -1.047, 1.4497, 0.0353], ['H', -0.2715, 3.6101, 0.648], ['C', -2.2466, 1.1461, 1.0121], ['H', -2.4239, 3.0636, 2.4018], ['C', -3.2668, 1.3891, -0.1651], ['H', -4.2555, 3.501, 0.2884], ['H', -2.2876, 0.321, 1.7167], ['C', -2.0673, 1.6928, -1.142], ['H', -4.1189, 0.7571, -0.3963], ['H', -0.1345, 0.8657, -0.0369], ['H', -2.1025, 4.0451, -1.466], ['H', -1.9661, 1.3028, -2.1504]]
>>>
-----------------------------ファイルの読み込み
#from tkinter import *
axyz,new_axyz,data = [], [], []
for line in open('cubane-1.txt').readlines():
dat = line[:-1].split() # スペース区切り
print(dat,end='')
data =[dat[0],float(dat[1]),float(dat[2]),float(dat[3])] # リスト内の座標のみを float 関数で実数化
print(' ---→',data,' ← 部分実数化')
axyz.append(data) # リストの中にリストを作成
n=len(axyz)
print('原子数',n);print()
print(axyz)
=========== RESTART: /Users/KH/pythonPRG/cubane_space_exception.py ===========
['C', '-2.1434', '3.2205', '-0.7607'] ---→ ['C', -2.1434, 3.2205, -0.7607] ← 部分実数化
['C', '-3.3430', '2.9171', '0.2166'] ---→ ['C', -3.343, 2.9171, 0.2166] ← 部分実数化
['C', '-1.1232', '2.9776', '0.4164'] ---→ ['C', -1.1232, 2.9776, 0.4164] ← 部分実数化
['C', '-2.3227', '2.6737', '1.3934'] ---→ ['C', -2.3227, 2.6737, 1.3934] ← 部分実数化
['C', '-1.0470', '1.4497', '0.0353'] ---→ ['C', -1.047, 1.4497, 0.0353] ← 部分実数化
['H', '-0.2715', '3.6101', '0.6480'] ---→ ['H', -0.2715, 3.6101, 0.648] ← 部分実数化
['C', '-2.2466', '1.1461', '1.0121'] ---→ ['C', -2.2466, 1.1461, 1.0121] ← 部分実数化
['H', '-2.4239', '3.0636', '2.4018'] ---→ ['H', -2.4239, 3.0636, 2.4018] ← 部分実数化
['C', '-3.2668', '1.3891', '-0.1651'] ---→ ['C', -3.2668, 1.3891, -0.1651] ← 部分実数化
['H', '-4.2555', '3.5010', '0.2884'] ---→ ['H', -4.2555, 3.501, 0.2884] ← 部分実数化
['H', '-2.2876', '0.3210', '1.7167'] ---→ ['H', -2.2876, 0.321, 1.7167] ← 部分実数化
['C', '-2.0673', '1.6928', '-1.1420'] ---→ ['C', -2.0673, 1.6928, -1.142] ← 部分実数化
['H', '-4.1189', '0.7571', '-0.3963'] ---→ ['H', -4.1189, 0.7571, -0.3963] ← 部分実数化
['H', '-0.1345', '0.8657', '-0.0369'] ---→ ['H', -0.1345, 0.8657, -0.0369] ← 部分実数化
['H', '-2.1025', '4.0451', '-1.4660'] ---→ ['H', -2.1025, 4.0451, -1.466] ← 部分実数化
['H', '-1.9661', '1.3028', '-2.1504'] ---→ ['H', -1.9661, 1.3028, -2.1504] ← 部分実数化
原子数 16
[['C', -2.1434, 3.2205, -0.7607], ['C', -3.343, 2.9171, 0.2166], ['C', -1.1232, 2.9776, 0.4164], ['C', -2.3227, 2.6737, 1.3934], ['C', -1.047, 1.4497, 0.0353], ['H', -0.2715, 3.6101, 0.648], ['C', -2.2466, 1.1461, 1.0121], ['H', -2.4239, 3.0636, 2.4018], ['C', -3.2668, 1.3891, -0.1651], ['H', -4.2555, 3.501, 0.2884], ['H', -2.2876, 0.321, 1.7167], ['C', -2.0673, 1.6928, -1.142], ['H', -4.1189, 0.7571, -0.3963], ['H', -0.1345, 0.8657, -0.0369], ['H', -2.1025, 4.0451, -1.466], ['H', -1.9661, 1.3028, -2.1504]]
>>>
空白削除, 数値データの実数化を1行で実行
入力データ
C , -2.1434, 3.2205, -0.7607
C, -3.3430, 2.9171, 0.2166
C , -1.1232, 2.9776, 0.4164
C, -2.3227, 2.6737, 1.3934
C , -1.0470, 1.4497, 0.0353
H , -0.2715, 3.6101, 0.6480
C, -2.2466, 1.1461, 1.0121
H , -2.4239, 3.0636, 2.4018
C, -3.2668, 1.3891, -0.1651
H, -4.2555, 3.5010, 0.2884
H, -2.2876, 0.3210, 1.7167
C, -2.0673, 1.6928, -1.1420
H, -4.1189, 0.7571, -0.3963
H , -0.1345, 0.8657, -0.0369
H, -2.1025, 4.0451, -1.4660
H , -1.9661, 1.3028, -2.1504
# coding: utf-8
#-----------------------------ファイルの読み込み
axyz,new_axyz = [], []
for line in open('cubane-1_comma.txt').readlines():
#for line in open('sk_81b.txt').readlines():
d = line[:-1].split(',') # カンマ区切り
dat =[d[0].strip(), float(d[1]), float(d[2]), float(d[3])] # ⬅ ⬅ ⬅ ⬅ ⬅ ⬅ 追加処理, 説明は前項と同じ
print(dat)
axyz.append(dat) # リストの中にリストを作成
n=len(axyz)
print('原子数',n);print()
print(axyz)
======== RESTART: /Users/KH/pythonPRG/cubane_f_read_comma_separate.py ========
['C', -2.1434, 3.2205, -0.7607]
['C', -3.343, 2.9171, 0.2166]
['C', -1.1232, 2.9776, 0.4164]
['C', -2.3227, 2.6737, 1.3934]
['C', -1.047, 1.4497, 0.0353]
['H', -0.2715, 3.6101, 0.648]
['C', -2.2466, 1.1461, 1.0121]
['H', -2.4239, 3.0636, 2.4018]
['C', -3.2668, 1.3891, -0.1651]
['H', -4.2555, 3.501, 0.2884]
['H', -2.2876, 0.321, 1.7167]
['C', -2.0673, 1.6928, -1.142]
['H', -4.1189, 0.7571, -0.3963]
['H', -0.1345, 0.8657, -0.0369]
['H', -2.1025, 4.0451, -1.466]
['H', -1.9661, 1.3028, -2.1504]
原子数 16
[['C', -2.1434, 3.2205, -0.7607], ['C', -3.343, 2.9171, 0.2166], ['C', -1.1232, 2.9776, 0.4164], ['C', -2.3227, 2.6737, 1.3934], ['C', -1.047, 1.4497, 0.0353], ['H', -0.2715, 3.6101, 0.648], ['C', -2.2466, 1.1461, 1.0121], ['H', -2.4239, 3.0636, 2.4018], ['C', -3.2668, 1.3891, -0.1651], ['H', -4.2555, 3.501, 0.2884], ['H', -2.2876, 0.321, 1.7167], ['C', -2.0673, 1.6928, -1.142], ['H', -4.1189, 0.7571, -0.3963], ['H', -0.1345, 0.8657, -0.0369], ['H', -2.1025, 4.0451, -1.466], ['H', -1.9661, 1.3028, -2.1504]]
>>>
--------------------
今回紹介したスペース区切りのデータの処理法はタブ区切りデータの場合も適応可能である.
ファイル読込, 整形がシンプルになると, 分子描画プログラム全体がすっきりとなった. X線回折データや分子計算データの任意の書式ファイルからのデータ抽出, 整形が楽になった.
なお, "C , -2.1434(3), 3.2205(4), -0.7607(3)" のような標準偏差値が付いているデータの場合はAWK言語で処理するとうまくいく. 「超便利なAwk言語 必要な部分だけを切り出す」 を参考にしてほしい.