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