"""
CIF (Crystallographic Information File) データを扱うためのクラスを提供します。
このモジュールは、CIFファイルを操作するための基底クラス tkCIFObject と、
CIFデータの内容を解析し、tkCrystalオブジェクトへ変換する機能を持つ tkCIFData クラスを提供します。
CIFファイルからの情報抽出、結晶構造の構築、およびCIFファイルへの書き出しをサポートします。
関連リンク: :doc:`tkcifobject_usage`
"""
import sys
import shlex
from pprint import pprint
from tklib.tkobject import tkObject
from tklib.tkcrystal.tkcrystalobject import tkCrystalObject
from tklib.tkcrystal.tkcrystal import tkCrystal
from tklib.tkfile import tkFile
from tklib.tkutils import SplitFilePath, BuildCreationDateStr, pint, pfloat
from tklib.tkre import DelQuote
import tklib.tkre as tkre
#=====================================
# CIF root class
#=====================================
[ドキュメント]
class tkCIFObject(tkFile):
"""
CIFファイルを扱うための基底クラスです。
tkFileを継承し、CIFファイルに関する基本的な属性(結晶名、サンプル名)を管理します。
"""
def __init__(self, path = None, mode = 'r', **args):
"""
tkCIFObjectクラスのコンストラクタ。
オブジェクトの初期化を行い、結晶名とサンプル名を空文字列で設定します。
:param path: `str`, CIFファイルのパス。デフォルトはNone。
:param mode: `str`, ファイルのオープンモード('r', 'w'など)。デフォルトは'r'。
:param **args: `dict`, その他のキーワード引数。
"""
self.__crystalname = ''
self.__samplename = ''
def __del__(self):
"""
tkCIFObjectクラスのデストラクタ。
何も行いません。
"""
pass
def __str__(self):
"""
オブジェクトの文字列表現を返します。
:returns: `str`, クラスの完全パス。
"""
return self.ClassPath()
#=====================================
# CIF data class
#=====================================
[ドキュメント]
class tkCIFData(tkCrystalObject):
"""
CIFデータの内容を解析し、操作するためのクラスです。
tkCrystalObjectを継承し、CIFデータから結晶構造情報を抽出・管理し、
tkCrystalオブジェクトへの変換やファイル出力機能を提供します。
"""
def __init__(self, **args):
"""
tkCIFDataクラスのコンストラクタ。
オブジェクトの初期化を行い、デバッグフラグ、ファイルパス、CIFデータ辞書、
入力行リストなどを設定します。
:param **args: `dict`, その他のキーワード引数。
"""
super(tkCIFData, self).__init__(**args)
self.debug = 0
self.path = None
# cif data dict
self.data = None
# cif input lines list
self.lines = None
self.__crystalname = None
self.__samplename = None
self.update(**args)
def __del__(self):
"""
tkCIFDataクラスのデストラクタ。
親クラスのデストラクタを呼び出します。
"""
super(tkCIFData, self).__del__()
def __str__(self):
"""
オブジェクトの文字列表現を返します。
:returns: `str`, クラスの完全パス。
"""
return self.ClassPath()
[ドキュメント]
def get(self, key, i = None, defval = None):
"""
CIFデータから指定されたキーの値を取得します。
キーがリストの場合は最初に見つかった値を返し、キーが整数(行番号)の場合は
入力行リストから値を返します。インデックスが指定された場合は、キーにインデックスを付加して検索します。
:param key: `str` or `list` or `int`, 取得するデータのキー、キーのリスト、または行番号。
:param i: `int` or `str` or `None`, キーに付加するインデックス。ループ内のデータ(例: `_atom_site_fract_x[0]`) を取得する際に使用。
:param defval: `any`, 値が見つからなかった場合に返すデフォルト値。
:returns: `any`, 見つかった値、またはデフォルト値。
"""
# print(f"get:i={i} key={key}")
if type(key) is list:
for j in range(len(key)):
ret = self.get(key[j], i, defval = None)
if ret is not None:
return ret
else:
return defval
if type(key) is int:
try:
return self.lines[key]
except:
return defval
if key == 'path':
return self.path
key1 = key
if i is not None and i != '':
key1 = key + f'[{i}]'
# print("key1=", key1)
# for k in self.data.keys():
# print(" {}:{}".format(k, self.data[k]))
try:
val = self.data[key1]
return val
except:
return defval
[ドキュメント]
def geterrorf(self, key, i = None, defval = None):
"""
CIFデータから指定されたキーの浮動小数点値を取得します。エラー値の括弧表記を除去します。
`get` メソッドで値を取得し、括弧で囲まれたエラー表記(例: `1.234(5)`)を
除去した後、浮動小数点数に変換して返します。変換に失敗した場合はデフォルト値を返します。
:param key: `str` or `list`, 取得するデータのキーまたはキーのリスト。
:param i: `int` or `str` or `None`, キーに付加するインデックス。
:param defval: `any`, 値が見つからなかった場合や変換に失敗した場合に返すデフォルト値。
:returns: `float` or `any`, 変換された浮動小数点数、またはデフォルト値。
"""
val = self.get(key, i, defval)
if val is None:
return defval
# print("geterrorf: {} = {}: type(val)={}".format(key, val, type(val)))
try:
val = tkre.Sub(r'\(.*\)', '', val)
except:
pass
# print(" {} = {}".format(key, val))
try:
return pfloat(val)
except:
return defval
[ドキュメント]
def getf(self, key, i = None, defval = None):
"""
CIFデータから指定されたキーの浮動小数点値を取得します。
`get` メソッドで値を取得し、浮動小数点数に変換して返します。
変換に失敗した場合はデフォルト値を返します。
:param key: `str` or `list`, 取得するデータのキーまたはキーのリスト。
:param i: `int` or `str` or `None`, キーに付加するインデックス。
:param defval: `any`, 値が見つからなかった場合や変換に失敗した場合に返すデフォルト値。
:returns: `float` or `any`, 変換された浮動小数点数、またはデフォルト値。
"""
val = self.get(key, i, defval)
try:
return pfloat(val)
except:
return defval
[ドキュメント]
def geti(self, key, i = None, defval = None):
"""
CIFデータから指定されたキーの整数値を取得します。
`get` メソッドで値を取得し、整数に変換して返します。浮動小数点数として解釈できる場合は、
その整数部分を返します。変換に失敗した場合はデフォルト値を返します。
:param key: `str` or `list`, 取得するデータのキーまたはキーのリスト。
:param i: `int` or `str` or `None`, キーに付加するインデックス。
:param defval: `any`, 値が見つからなかった場合や変換に失敗した場合に返すデフォルト値。
:returns: `int` or `any`, 変換された整数、またはデフォルト値。
"""
val = self.get(key, i, defval)
try:
return pint(val)
except:
pass
try:
return int(pfloat(val))
except:
return defval
[ドキュメント]
def CheckCIF1(self, key):
"""
指定されたCIFキーが存在し、エラー付き浮動小数点値として取得可能かチェックします。
`geterrorf` メソッドを使用してキーの値を取得し、それが `None` でないかを確認します。
値が取得できない場合はエラーメッセージを出力し、0を返します。
:param key: `str`, チェックするCIFキー。
:returns: `int`, キーが存在する場合は1、存在しない場合は0。
"""
if self.geterrorf(key) is None:
print("Error in tkcrystal.tkcif.tkCIFData.CheckCIF1: key [{}] is not found in [{}]"
.format(key, self.path))
return 0
return 1
[ドキュメント]
def CheckCIF(self):
"""
必須のCIF格子定数と原子位置データが存在するかどうかをチェックします。
`_cell_length_a`、`_cell_length_b`、`_cell_length_c`、
`_cell_angle_alpha`、`_cell_angle_beta`、`_cell_angle_gamma`、
`_atom_site_fract_x[0]`、`_atom_site_fract_y[0]`、`_atom_site_fract_z[0]`
の各キーについて `CheckCIF1` を呼び出します。
いずれか一つでも存在しない場合はプログラムを終了します。
:returns: `int`, 全ての必須キーが存在する場合は1。
"""
if self.CheckCIF1('_cell_length_a') \
and self.CheckCIF1('_cell_length_b') \
and self.CheckCIF1('_cell_length_c') \
and self.CheckCIF1('_cell_angle_alpha') \
and self.CheckCIF1('_cell_angle_beta') \
and self.CheckCIF1('_cell_angle_gamma') \
and self.CheckCIF1('_atom_site_fract_x[0]') \
and self.CheckCIF1('_atom_site_fract_y[0]') \
and self.CheckCIF1('_atom_site_fract_z[0]'):
return 1
exit()
[ドキュメント]
def LatticeParameters(self):
"""
CIFデータから格子定数を取得します。
`_cell_length_a`、`_cell_length_b`、`_cell_length_c`、
`_cell_angle_alpha`、`_cell_angle_beta`、`_cell_angle_gamma`
の値を `geterrorf` メソッドで取得し、タプルとして返します。
:returns: `tuple`, (a, b, c, alpha, beta, gamma) の順で格子定数を格納したタプル。
"""
latt = self.geterrorf('_cell_length_a'), \
self.geterrorf('_cell_length_b'), \
self.geterrorf('_cell_length_c'), \
self.geterrorf('_cell_angle_alpha'), \
self.geterrorf('_cell_angle_beta'), \
self.geterrorf('_cell_angle_gamma')
return latt
[ドキュメント]
def dataprint(self, key, i = None):
"""
指定されたCIFキーの値を標準出力に表示します。
キーがリストの場合、最初に見つかったキーの値を表示します。
値が見つからない場合はエラーメッセージを出力します。
:param key: `str` or `list`, 表示するデータのキーまたはキーのリスト。
:param i: `int` or `str` or `None`, キーに付加するインデックス。
:returns: `int`, 値が見つかり表示された場合は1、見つからなかった場合は0。
"""
if type(key) is not list:
key = [key]
for j in range(len(key)):
ret = self.get(key[j], i = i, defval = None)
if ret is not None:
print("{}: {}".format(key[j], self.get(key[j], i)))
return 1
print("Error in {}.{}: Invalid key {} for tkCIFData.data"
.format(self.ClassPath(), sys._getframe().f_code.co_name, key))
return 0
[ドキュメント]
def InsertSpaceToSPGName(self, SPGName):
"""
空間群名に適切な空白を挿入して整形します(未実装または不完全な実装)。
空間群名に特定のパターンに基づいて空白を挿入しようと試みますが、
現状では正規表現による置換が不完全であり、期待通りに動作しない可能性があります。
:param SPGName: `str`, 整形する空間群名。
:returns: `str`, 整形された空間群名。
"""
if tkre.Search(r'[RH]$', SPGName) and tkre.Search(r'\s.+\S\s+[RHS]$', SPGName):
return SPGName
elif tkre.Search(r'\s', SPGName):
return SPGName
tkre.Sub(r'(.)', r'\1', SPGName)
tkre.Sub(r'\s\s+', r' ', SPGName)
tkre.Sub(r'- ', r'-', SPGName)
tkre.Sub(r' \/ ', r'\/', SPGName)
tkre.Sub(r'([^\-])2 1', r'\{1}21', SPGName)
tkre.Sub(r'([^\-])3 1', r'\{1}31', SPGName)
tkre.Sub(r'([^\-])3 2', r'\{1}32', SPGName)
tkre.Sub(r'([^\-])4 1', r'\{1}41', SPGName)
tkre.Sub(r'([^\-])4 2', r'\{1}42', SPGName)
tkre.Sub(r'([^\-])4 3', r'\{1}43', SPGName)
tkre.Sub(r'([^\-])6 1', r'\{1}61', SPGName)
tkre.Sub(r'([^\-])6 2', r'\{1}62', SPGName)
tkre.Sub(r'([^\-])6 3', r'\{1}63', SPGName)
tkre.Sub(r'([^\-])6 4', r'\{1}64', SPGName)
tkre.Sub(r'([^\-])6 5', r'\{1}65', SPGName)
return SPGName
[ドキュメント]
def FillCIFData(self):
"""
CIFデータを用いてtkCrystalオブジェクトを部分的に初期化します(未実装)。
`CrystalName` を設定しますが、他のプロパティ(格子定数、体積、空間群)の
設定はコメントアウトされており、機能しません。
:returns: `None`
"""
crystal = tkCrystal()
crystal.SetCrystalName(self.CrystalName())
# crystal->SetLatticeParameters(self.LatticeParameters())
# self.SetContent("_cell_volume", crystal.Volume())
# SPG = self.SpaceGroup()
[ドキュメント]
def GetCrystal(self):
"""
CIFデータからtkCrystalオブジェクトを生成して返します。
CIFデータに含まれる化学名、化学式、体積、格子定数、空間群、対称操作、
原子種、原子サイトの情報を用いて、tkCrystalオブジェクトを構築し初期化します。
:returns: `tklib.tkcrystal.tkcrystal.tkCrystal`, 構築されたtkCrystalオブジェクト。
"""
cry = tkCrystal()
cifdata = self.data
cry.path = self.path
if cry.path is not None:
dir, filename, filebody, ext = SplitFilePath(cry.path)
else:
dir, filename, filebody, ext = "", "", "", ""
cry.ChemicalName = self.get('_chemical_name_systematic', defval = '')
cry.ChemicalFormula = self.get('_chemical_formula_structural', defval = '')
cry.SetVolume(self.geterrorf('_cell_volume', defval = None))
cry.ChemicalFormulaUnit = self.get('_cell_formula_units_Z', defval = None)
spg_name = self.get(
['_symmetry_space_group_name_H-M', '_space_group_name_H-M_alt'],
defval = '')
ispg = self.geti(
['_symmetry_Int_Tables_number', '_space_group_IT_number'],
defval = '')
cry.SetSpaceGroup(name = spg_name, number = ispg)
cry.SetLatticeParameters(self.LatticeParameters(), GuessLatticeSystem = 0)
if cry.ChemicalFormula != '':
cry.SetCrystalName(cry.ChemicalFormula)
cry.SetSampleName(cry.ChemicalName)
else:
cry.SetSampleName(filebody)
c = 0
while 1:
sym = self.get(
['_symmetry_equiv_pos_as_xyz', '_space_group_symop_operation_xyz'],
i = c, defval = None)
if sym:
# print("add sym:", sym, " c=", c)
cry.AddSymmetry(sym)
c += 1
else:
break
c = 0
while 1:
atomtype = self.get('_atom_type_symbol', c)
if(atomtype):
charge = self.getf('_atom_type_oxidation_number', c, defval = 0.0)
cry.AddAtomType(atomtype, charge)
c += 1
else:
break
c = 0
while 1:
label = self.get('_atom_site_label', c)
if(label):
name = self.get('_atom_site_type_symbol', c, defval = None)
m = self.geti('_atom_site_symmetry_multiplicity', c, defval = 1)
ws = self.get('_atom_site_Wyckoff_symbol', c, defval = '')
x = self.geterrorf('_atom_site_fract_x', c, defval = None)
y = self.geterrorf('_atom_site_fract_y', c, defval = None)
z = self.geterrorf('_atom_site_fract_z', c, defval = None)
occ = self.geterrorf('_atom_site_occupancy', c, defval = 1.0)
h = self.geti('_atom_site_attached_hydrogens', c, defval = 0)
# print("GetCrystal: Add atom site:", name, m, ws, x, y, z)
if name is None:
name = self.get('_atom_site_label', c, defval = None)
list = tkre.Match(r'([A-Z][a-z]?)', name)
iAtomType, AtomType = cry.AddAtomType(name)
cry.AddAtomSite(label = label, name = name, m = m, ws = ws,
pos = [x, y, z], occ = occ, hydrogen = h)
c += 1
else:
break
cry.ExpandCoordinates()
cry.CalcMetrics()
return cry
[ドキュメント]
def Print(self, PrintLines = 0):
"""
CIFデータの要約情報を標準出力に表示します。
`print` メソッドのエイリアスです。
:param PrintLines: `int`, 入力行データも表示するかどうかのフラグ (1で表示)。デフォルトは0。
:returns: `None`
"""
self.print(PrintLines = PrintLines)
[ドキュメント]
def print(self, PrintLines = 0):
"""
CIFデータの詳細情報を標準出力に表示します。
ファイルパス、化学名、化学式、単位格子情報、空間群、対称操作、原子種、
原子サイトの情報を整形して出力します。`PrintLines` が1の場合、
元の入力行も表示します。
:param PrintLines: `int`, 入力行データも表示するかどうかのフラグ (1で表示)。デフォルトは0。
:returns: `None`
"""
cifdata = self.data
print("====== tkcifobject.Print start ======")
print("path: {}".format(self.path))
self.dataprint('_chemical_name_systematic')
self.dataprint('_chemical_formula_structural')
print("\nUnit cell:")
latt = self.LatticeParameters()
print('latt: ', latt)
self.dataprint('_cell_volume')
self.dataprint('_cell_formula_units_Z')
print("\nSpace group:")
self.dataprint(['_symmetry_space_group_name_H-M', '_space_group_name_H-M_alt'])
self.dataprint(['_symmetry_Int_Tables_number', '_space_group_IT_number'])
print("\nSymmetry:")
c = 0
while 1:
idx = self.geti('_symmetry_equiv_pos_site_id', i = c, defval = c)
sym = self.get(
['_symmetry_equiv_pos_as_xyz', '_space_group_symop_operation_xyz'],
i = idx, defval = None)
# print("idx,sym=", idx, sym)
if sym:
print("{}: {}".format(idx, sym))
c += 1
else:
break
print("\nAtom Type:")
c = 0
while 1:
atomtype = self.get('_atom_type_symbol', c)
if(atomtype):
charge = self.getf('_atom_type_oxidation_number', c, defval = 0.0)
print("{}: {}".format(atomtype, charge))
c += 1
else:
break
print("\nAtom Site:")
c = 0
# for key in self.data.keys():
# print(" {}={}".format(key, self.data[key]))
while 1:
label = self.get('_atom_site_type_symbol', c, defval = None)
if label is None:
label = self.get('_atom_site_label', c, defval = None)
if label:
name = self.get('_atom_site_type_symbol', c, defval = None)
m = self.geti('_atom_site_symmetry_multiplicity', c, defval = 1)
ws = self.get('_atom_site_Wyckoff_symbol', c, defval = '')
x = self.geterrorf('_atom_site_fract_x', c, defval = None)
y = self.geterrorf('_atom_site_fract_y', c, defval = None)
z = self.geterrorf('_atom_site_fract_z', c, defval = None)
occ = self.geterrorf('_atom_site_occupancy', c, defval = 1.0)
h = self.geti('_atom_site_attached_hydrogens', c, defval = 0)
if name is None:
name = self.get('_atom_site_label', c, defval = None)
list = tkre.Match(r'([A-Z][a-z]?)', name)
try:
name = list[1]
except:
pass
if name is None or x is None or y is None or z is None:
print("Error: tkcrystal.tkcifobject.Print: name ({}) or (x, y, z) ({}, {}, {}) is None)"
.format(name, x, y, z))
exit(0)
print("#{:04d}: {:4} {:4} ({:8.4f}, {:8.4f}, {:8.4f}) occ={:8.4f} ws={} m={}"
.format(c, label, name, x, y, z, occ, ws, m))
c += 1
else:
break
if PrintLines:
print("\nInput data:")
c = 0
while 1:
ret = self.get(c)
if(ret):
print(ret.strip())
c += 1
else:
break
print("====== tkcifobject.Print end ======")
[ドキュメント]
def nSymmetryOperation(self):
"""
検出された対称操作の数を返します。
`_symmetry_equiv_pos_as_xyz` キーに対応するエントリをインデックス `i` を
増やしながら検索し、値が見つからなくなるまでカウントします。
:returns: `int`, 対称操作の数。
"""
n = 0
while 1:
val = self.get('_symmetry_equiv_pos_as_xyz', i = n, defval = None)
if val is None:
return n
n += 1
[ドキュメント]
def SymmetryOperation(self, i):
"""
指定されたインデックスの対称操作を取得します。
`_symmetry_equiv_pos_as_xyz` キーから、指定されたインデックス `i` に
対応する対称操作の文字列を取得し、引用符を除去して返します。
:param i: `int`, 取得する対称操作のインデックス。
:returns: `str` or `None`, 対称操作の文字列、または見つからない場合はNone。
"""
val = self.get('_symmetry_equiv_pos_as_xyz', i = i, defval = None)
if val is None:
return val
return DelQuote(val)
[ドキュメント]
def WriteKeyVal(self, out, key, defval = None, i = None):
"""
CIFファイルにキーと値を書き込みます。
指定されたキーの値を `get` メソッドで取得し、`out` ファイルオブジェクトに
`_key value` の形式で書き込みます。値が `None` の場合は書き込まず0を返します。
:param out: `tklib.tkfile.tkFile`, 書き込み先のファイルオブジェクト。
:param key: `str`, 書き込むCIFキー。
:param defval: `any` or `None`, 値が見つからなかった場合のデフォルト値。
:param i: `int` or `str` or `None`, キーに付加するインデックス。
:returns: `int`, 値が書き込まれた場合は1、書き込まれなかった場合は0。
"""
val = self.get(key, i = i, defval = defval)
# print("\nlines:\n")
# for key in self.data.keys():
# print(" {}: {}".format(key, self.data[key]))
# print(" key=", key, "i=", i, " val=", val)
if val is None:
return 0
out.Write("%-35s%s\n" % (key, val))
return 1
[ドキュメント]
def WriteSimpleCIFFile(self, NewFile, WritePublication = 1):
"""
現在のCIFデータの内容からシンプルなCIFファイルを生成します。
`FillCIFData` を呼び出した後、新しいCIFファイルを指定されたパスに作成し、
基本情報、単位格子、空間群、対称操作、原子種、原子サイト情報を書き込みます。
:param NewFile: `str`, 新しく作成するCIFファイルのパス。
:param WritePublication: `int`, 論文情報を書き込むかどうかのフラグ (1で書き込む)。デフォルトは1。
:returns: `int`, ファイルが正常に作成された場合は1、失敗した場合は0。
"""
self.FillCIFData()
#ファイル名を(ベース名, ディレクトリ名, 拡張子)に分解
# dirname, basename, filebody, ext = SplitFilePath(NewFile)
out = tkFile(NewFile, 'w')
if out is None:
return 0
# binmode(OUT) if(defined $strCRLF and $strCRLF =~ /unix/i);
val = self.get('_database_code_ICSD', defval = 99999)
out.Write("data_{}-ICSD\n".format(val))
out.Write("\n")
self.WriteKeyVal(out, '_audit_creation_date', None)
self.WriteKeyVal(out, '_audit_creation_method', 'python tkcifobject.py 0.1')
self.WriteKeyVal(out, '_chemical_name_systematic', 'undefined')
self.WriteKeyVal(out, '_chemical_formula_structural', 'undefined')
self.WriteKeyVal(out, '_chemical_formula_sum', 'undefined')
if WritePublication:
self.WriteKeyVal(out, '_journal_name_full', 'undefined')
out.Write("\n")
self.WriteKeyVal(out, '_cell_length_a', '')
self.WriteKeyVal(out, '_cell_length_b', '')
self.WriteKeyVal(out, '_cell_length_c', '')
self.WriteKeyVal(out, '_cell_angle_alpha', '')
self.WriteKeyVal(out, '_cell_angle_beta', '')
self.WriteKeyVal(out, '_cell_angle_gamma', '')
self.WriteKeyVal(out, '_cell_volume', None)
self.WriteKeyVal(out, '_cell_formula_units_Z', None)
out.Write("\n")
self.WriteKeyVal(out, '_symmetry_space_group_name_H', None)
self.WriteKeyVal(out, '_symmetry_Int_Tables_number', None)
self.WriteKeyVal(out, '_symmetry_cell_setting', None)
out.Write("loop_\n")
out.Write('_symmetry_equiv_pos_as_xyz\n')
nsymop = self.nSymmetryOperation()
for i in range(nsymop):
val = self.get('_symmetry_equiv_pos_as_xyz', i = i, defval = '')
val = DelQuote(val)
out.Write(" '{}'\n".format(val))
out.Write("\n")
out.Write("loop_\n")
out.Write("_atom_type_symbol\n")
out.Write("_atom_type_oxidation_number\n")
c = 0
while 1:
name = self.get('_atom_type_symbol', i = c, defval = None)
if name is None:
break
charge = self.get('_atom_type_oxidation_number', i = c, defval = 0.0)
out.Write(" %-6s%6s\n" % (name, charge))
c += 1
out.Write("\n")
out.Write("loop_\n")
out.Write("_atom_site_label\n")
out.Write("_atom_site_type_symbol\n")
out.Write("_atom_site_symmetry_multiplicity\n")
out.Write("_atom_site_Wyckoff_symbol\n")
out.Write("_atom_site_fract_x\n")
out.Write("_atom_site_fract_y\n")
out.Write("_atom_site_fract_z\n")
out.Write("_atom_site_occupancy\n")
c = 0
while 1:
label = self.get('_atom_site_label', i = c, defval = None)
type = self.get('_atom_site_type_symbol', i = c, defval = None)
if type is None:
break
m = self.get('_atom_site_symmetry_multiplicity', i = c, defval = 0.0)
ws = self.get('_atom_site_Wyckoff_symbol', i = c, defval = 0.0)
x = self.get('_atom_site_fract_x', i = c, defval = 0.0)
y = self.get('_atom_site_fract_y', i = c, defval = 0.0)
z = self.get('_atom_site_fract_z', i = c, defval = 0.0)
occ = self.get('_atom_site_occupancy', i = c, defval = 0.0)
out.Write(" %-6s %-6s %2s %s %s %s %s %s\n"
% (label, type, m, ws, x, y, z, occ))
c += 1
out.Write("\n")
out.Write("\n")
out.Write("#End of data_${dbcodeICSD}-ICSD\n")
out.Write("\n")
out.Write("\n")
out.Close()
[ドキュメント]
def CreateCIFFileFromCCrystal(self, cry, NewFile, IsChooseRandomly = 0, IsPrint = 1):
"""
tkCrystalオブジェクトの内容からCIFファイルを生成します。
指定された `tkCrystal` オブジェクトから、化学組成、格子定数、空間群、
対称操作、原子種、原子サイト情報を抽出し、新しいCIFファイルを生成して書き込みます。
:param cry: `tklib.tkcrystal.tkcrystal.tkCrystal`, 書き出す情報を含むtkCrystalオブジェクト。
:param NewFile: `str`, 新しく作成するCIFファイルのパス。
:param IsChooseRandomly: `int`, (未使用)ランダムに選択するかどうかのフラグ。デフォルトは0。
:param IsPrint: `int`, (未使用)出力時にプリントするかどうかのフラグ。デフォルトは1。
:returns: `int`, ファイルが正常に作成された場合は1、失敗した場合は0。
"""
out = tkFile(NewFile, 'w')
if out is None:
return 0
# binmode(OUT) if($strCRLF =~ /unix/i);
val = 99999;
out.Write("data_{}\n".format(val))
out.Write("\n")
out.Write("%-35s%s\n" % ("_audit_creation_date", BuildCreationDateStr()))
out.Write("%-35s'%s'\n" % ("_audit_creation_method", 'python tkcifobject.py 0.1'))
out.Write("\n")
Composition = cry.ChemicalComposition()
Composition = tkre.Sub(r'\s', '', Composition)
name = Composition
if name == '':
name = cry.CrystalName()
if name == '':
name = cry.SampleName()
if name == '':
name = 'undefined'
out.Write("%-35s'%s'\n" % ("_chemical_formula_structural", cry.ChemicalComposition()))
out.Write("%-35s'%s'\n" % ("_chemical_formula_sum", cry.SumChemicalComposition()))
latt = cry.LatticeParameters()
out.Write("\n")
out.Write("%-35s %s\n" % ("_cell_length_a", latt[0]))
out.Write("%-35s %s\n" % ("_cell_length_b", latt[1]))
out.Write("%-35s %s\n" % ("_cell_length_c", latt[2]))
out.Write("%-35s %s\n" % ("_cell_angle_alpha", latt[3]))
out.Write("%-35s %s\n" % ("_cell_angle_beta", latt[4]))
out.Write("%-35s %s\n" % ("_cell_angle_gamma", latt[5]))
out.Write("\n")
SPG = cry.SpaceGroup()
op = SPG.GetSymmetryOperationList()
out.Write("%-35s %s\n" % ("_symmetry_Int_Tables_number", SPG.iSPG()))
out.Write("\n")
out.Write("loop_\n")
out.Write("_symmetry_equiv_pos_as_xyz\n")
for i in range(len(op)):
out.Write(" {}\n".format(op[i]))
out.Write("\n")
at = cry.AtomTypeList()
out.Write("loop_\n")
out.Write("_atom_type_symbol\n")
out.Write("_atom_type_oxidation_number\n")
for i in range(len(at)):
atype = at[i].AtomTypeOnly()
charge = at[i].Charge()
out.Write(" %-2s %f\n" % (atype, charge))
out.Write("\n")
ast = cry.AtomSiteList()
out.Write("loop_\n")
out.Write("_atom_site_label\n")
out.Write("_atom_site_type_symbol\n")
out.Write("_atom_site_fract_x\n")
out.Write("_atom_site_fract_y\n")
out.Write("_atom_site_fract_z\n")
out.Write("_atom_site_occupancy\n")
for i in range(len(ast)):
label = ast[i].Label()
name = ast[i].AtomNameOnly()
pos = ast[i].Position()
occ = ast[i].Occupancy()
out.Write(" %-6s %-2s %10.6f %10.6f %10.6f %f\n" %
(label, name, pos[0], pos[1], pos[2], occ))
out.Write("\n")
out.Write("#End of data_99999-ICSD\n")
out.Close()