cfg2cif.py ダウンロード/コピー

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()