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

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