cfg2cif.py ダウンロード/コピー
cfg2cif.py
cfg2cif.py
1"""
2概要:
3 CFGファイルをCIFファイルに変換するスクリプトです。
4詳細説明:
5 Open-CFG形式のファイルから結晶構造情報を読み込み、CIF (Crystallographic Information File) 形式に変換して出力します。
6 このスクリプトは、格子ベクトルの読み込み、原子サイトの座標処理
7 (必要に応じて[0,1)範囲への丸め込み、指定範囲外の除外)をサポートします。
8関連リンク:
9 cfg2cif_usage
10"""
11import os
12import sys
13import shutil
14import glob
15import csv
16import numpy as np
17from numpy import exp, log, sin, cos, tan, arcsin, arccos, arctan, pi
18from scipy.interpolate import interp1d
19from pprint import pprint
20from matplotlib import pyplot as plt
21
22sys.path.append("c:/git/tkProg/tklib/python")
23sys.path.append("d:/git/tkProg/tklib/python")
24
25from tklib.tkfile import tkFile
26from tklib.tkutils import IsDir, IsFile, SplitFilePath
27from tklib.tkutils import terminate, pint, pfloat, getarg, getintarg, getfloatarg
28from tklib.tksci.tksci import Reduce01, Round
29from tklib.tksci.tkmatrix import make_matrix1, make_matrix2, make_matrix3
30from tklib.tkcrystal.tkcif import tkCIF, tkCIFData
31from tklib.tkcrystal.tkcrystal import tkCrystal
32from tklib.tkcrystal.tkatomtype import tkAtomType
33
34
35#================================
36# global parameters
37#================================
38debug = 0
39
40atomtypes = ['O', 'Zn', 'Ga', 'In']
41xlim, ylim, zlim = 1.0, 1.0, 1.0
42#xlim, ylim, zlim = 0.7, 0.7, 0.7
43
44cfgfile = 'STD0.cfg'
45ciffile = 'STD0.cif'
46
47freduce01 = 1
48
49
50#=============================
51# Treat argments
52#=============================
53def usage():
54 """
55 概要:
56 スクリプトのコマンドライン引数の利用方法を表示します。
57 詳細説明:
58 スクリプト実行時に指定可能な引数(入力CFGファイル名、座標の[0,1)範囲への削減フラグ、
59 座標の出力範囲リミット)とその意味を示します。
60 """
61 global cfgfile
62 global freduce01, xlim, ylim, zlim
63
64 print("")
65 print("Usage:")
66 print(" (i) python {} cfgfile (reduce01 xilm ylim zlim)".format(sys.argv[0]))
67 print(" reduce01: Reduce fractional coordinates to [0, 1} if reduce01 == 1")
68 print(" ex: python {} {} {} {} {} {}"
69 .format(sys.argv[0], cfgfile, freduce01, xlim, ylim, zlim))
70
71def updatevars():
72 """
73 概要:
74 コマンドライン引数を解析し、グローバル設定変数を更新します。
75 詳細説明:
76 sys.argv から引数を取得し、cfgfile, freduce01, xlim, ylim, zlim などの
77 グローバル変数を設定します。入力CFGファイル名に基づいて出力CIFファイル名も決定します。
78 引数の取得には getarg, getintarg, getfloatarg を使用します。
79 """
80 global cfgfile, ciffile
81 global freduce01, xlim, ylim, zlim
82
83 argv = sys.argv
84# if len(argv) == 1:
85# terminate(usage = usage)
86
87 cfgfile = getarg (1, cfgfile)
88 freduce01 = getintarg (2, freduce01)
89 xlim = getfloatarg(3, xlim)
90 ylim = getfloatarg(4, ylim)
91 zlim = getfloatarg(5, zlim)
92
93 header, ext = os.path.splitext(cfgfile)
94 filebody = os.path.basename(header)
95 cfgfile = filebody + '.cfg'
96 ciffile = filebody + '.cif'
97
98
99def read_cfgfile(cfgfile):
100 """
101 概要:
102 指定されたCFGファイルを読み込み、tkCrystalオブジェクトを構築します。
103 詳細説明:
104 CFGファイルからサンプル名、総原子数、格子ベクトル、各原子サイトの座標と原子種を抽出します。
105 格子ベクトルの[0]行目が2倍されている点に注意が必要です。
106 抽出された情報をもとにtkCrystalオブジェクトを初期化し、原子サイトを追加します。
107 freduce01が真の場合、原子座標は[0,1)範囲に正規化され、
108 xlim, ylim, zlimで指定された範囲外の原子は除外されます。
109 引数:
110 :param cfgfile: 読み込むCFGファイルのパス。
111 :type cfgfile: str
112 戻り値:
113 :returns: 構築されたtkCrystalオブジェクト。ファイルの読み込みに失敗した場合はNoneを返す。
114 :rtype: tkCrystal or None
115 """
116 cfg = tkFile(cfgfile, 'r')
117 if not cfg:
118 terminate("Error in read_cfgfile: Can not read [{}]".format(cfgfile), usage = usage)
119
120 line = cfg.ReadLine()
121 sample_name = cfg.ReadLine().strip()
122 print("sample name: [{}]".format(sample_name))
123
124 line = cfg.SkipTo(r"molecules\s+of\s+all")
125 ret = cfg.Search(r"(\d+)", line)
126 natoms = pint(ret[1])
127
128 line = cfg.SkipTo("Defining vectors")
129 aij = np.empty([3, 3])
130 aij[0] = cfg.ReadLine().split()
131# aij[1] = cfg.ReadLine().split()
132# aij[2] = cfg.ReadLine().split()
133 for i in range(3):
134 aij[0][i] = pfloat(aij[0][i]) * 2.0
135 aij[1] = [0.0, aij[0][0], 0.0]
136 aij[2] = [0.0, 0.0, aij[0][0]]
137
138 print("")
139 print("Lattice vectors:")
140 for i in range(3):
141 print(" {:16.12f} {:16.12f} {:16.12f}".format(*aij[i]))
142
143 ntypes = []
144 ntot = 0
145 while 1:
146 line = cfg.SkipTo(r"molecules\s+of\s+type")
147 if not line:
148 break
149
150 ret = cfg.Search(r"(\d+)", line)
151 n = pint(ret[1])
152 ntypes.append(n)
153
154 ntot += n
155 if ntot >= natoms:
156 break
157
158 print("")
159 print("natoms=", natoms)
160 print(" ntypes=", ntypes)
161
162# skip two lines after the "molecules of type" line
163 cfg.ReadLine()
164 cfg.ReadLine()
165
166 site = []
167 idx = 0
168 idxtype = 0
169 itype = 0
170 while 1:
171 line = cfg.ReadLine()
172 if not line:
173 break
174
175 ret = line.split()
176# skip blank line
177 if ret is None or len(ret) < 3:
178 continue
179
180 name = atomtypes[itype]
181 xc, yc, zc = ret
182 xc = pfloat(xc)
183 yc = pfloat(yc)
184 zc = pfloat(zc)
185 print("{:04d} {:2} #{:04d} ({:8.4f}, {:8.4f}, {:8.4f})".format(idx+1, name, idxtype+1, xc, yc, zc))
186 site.append([name, xc, yc, zc])
187
188 idx += 1
189 idxtype += 1
190 if idxtype >= ntypes[itype]:
191 itype += 1
192 idxtype = 0
193
194 cfg.Close()
195
196 print("")
197 print("Build Crystal object:")
198 cry = tkCrystal()
199 cry.SetSampleName(sample_name)
200 cry.SetCrystalName(sample_name)
201 cry.SetLatticeVectors(aij)
202 latt = cry.LatticeParameters()
203 for i in range(natoms):
204 if i % 100 == 0:
205 print("{} ".format(i))
206 x, y, z = site[i][1], site[i][2], site[i][3]
207# x, y, z = cry.CartesianToFractional(site[i][1], site[i][2], site[i][3])
208 if freduce01:
209 x, y, z = Reduce01(x), Reduce01(y), Reduce01(z)
210 if x > xlim or y > ylim or z > zlim:
211 continue
212# print("xyz {}:{}: {},{},{} => {},{},{}".format(i+1, site[i][0], site[i][1], site[i][2], site[i][3], x, y, z))
213 cry.AddAtomSite(name = site[i][0], pos = [x, y, z])
214
215 print("")
216
217 cry.ExpandCoordinates()
218
219# cry.PrintInf()
220
221 return cry
222
223
224def cfg2cif():
225 """
226 概要:
227 グローバル変数で指定されたCFGファイルを読み込み、CIFファイルに変換して保存します。
228 詳細説明:
229 read_cfgfile関数を呼び出してCFGファイルから結晶情報を取得し、tkCrystalオブジェクトを生成します。
230 その後、そのtkCrystalオブジェクトを使用してtkCIFDataオブジェクトを生成し、
231 最終的にCIFファイルとして情報をciffileに書き出します。
232 処理の最後に terminate 関数が呼ばれ、スクリプトの利用方法が表示されます。
233 """
234 global cfgfile
235
236 print("CFG file: {}".format(cfgfile))
237
238 print("")
239 print("Read [{}]".format(cfgfile))
240
241# if not tkutils.IsFile(infile):
242# terminate("Error: Invalid infile [{}]".format(infile), usage = usage)
243 cry = read_cfgfile(cfgfile)
244
245 if not cry:
246 terminate("Error: Could not get crystal object from infile [{}]".format(cfgfile), usage = usage)
247
248 print("")
249 print("==============================================")
250 print(" Crystal inf")
251 print("==============================================")
252 cry.PrintInf()
253
254 print("")
255 print("Save to [{}]".format(ciffile))
256 cif = tkCIFData()
257 cif.CreateCIFFileFromCCrystal(cry, ciffile)
258
259 terminate(usage = usage)
260
261
262def main():
263 """
264 概要:
265 スクリプトのエントリポイントです。
266 詳細説明:
267 コマンドライン引数の処理 (updatevars) と、
268 CFGからCIFへの変換処理 (cfg2cif) を順に実行します。
269 スクリプトの開始時と終了時にメッセージを出力します。
270 """
271 updatevars()
272
273 print("")
274 print("=============== Convert CFG files to CIF file ============")
275 cfg2cif()
276
277
278if __name__ == "__main__":
279 main()