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

Fhkl.py をダウンロード

Fhkl.py
Fhkl.py
  1"""
  2X線回折に関連する原子散乱因子、異常散乱因子、結晶構造因子の計算および表示を行うスクリプト。
  3
  4このスクリプトは、指定された原子の原子散乱因子 (ASF) や異常散乱因子スペクトルのプロット、
  5またはCIFファイルから読み込んだ結晶の構造因子 (Fhkl) の計算と表示、
  6さらには結晶構造情報の表示を行います。
  7モードはコマンドライン引数またはスクリプト内のグローバル変数で制御されます。
  8
  9関連リンク:
 10:doc:`Fhkl_usage`
 11"""
 12import os
 13import sys
 14import shutil
 15import glob
 16import csv
 17from itertools import product
 18import numpy as np
 19from numpy import exp, log, sin, cos, tan, arcsin, arccos, arctan, pi
 20from scipy.interpolate import interp1d
 21from pprint import pprint
 22from matplotlib import pyplot as plt
 23
 24
 25from tklib.tkfile import tkFile
 26from tklib.tkutils import IsDir, IsFile
 27from tklib.tkutils import terminate, pint, pfloat, getarg, getintarg, getfloatarg
 28from tklib.tkcrystal.tkcif import tkCIF
 29from tklib.tkcrystal.tkcrystal import tkCrystal
 30from tklib.tkcrystal.tkatomtype import tkAtomType
 31
 32
 33#================================
 34# global parameters
 35#================================
 36debug = 0
 37
 38# mode: 'asf', 'anom', 'F', 'inf'
 39#    asf : atomic form factor for target_atom
 40#    anom: anomalous scattering factor for target_atom
 41#    F   : crystal structure factor for the CIF specified by ciffile
 42#    inf : show crystal structure information for the CIF specified by ciffile
 43mode = 'asf'
 44#mode = 'anom'
 45#mode = 'F'
 46#mode = 'inf'
 47
 48# X-ray
 49target_atom = 'Ni'
 50xray_source = 'CuKa1'
 51
 52wavelength = {
 53      'MoKa1': 0.070926 # nm
 54    , 'MoKa2': 0.071354
 55    , 'MoKa' : 0.071069
 56    , 'CuKa1': 0.15405
 57    , 'CuKa2': 0.15443
 58    , 'CuKa' : 0.15418
 59    , 'CuKb1': 0.13810
 60    , 'CuKb2': 0.13922
 61    , 'CuKb' : 0.13847
 62    }
 63
 64# CIF file configuration
 65ciffile = 'test.cif'
 66
 67single = 1
 68findvalidstructure = 1
 69
 70# scattering vector (s = sin Q / lambda) plot range
 71smin =  0.0
 72smax = 20.0
 73ns   = 31
 74
 75# s value to plot asf(s)
 76s_value = 0.1
 77
 78# Wavelength plot range for  anomolous scattering factor
 79WLmin = None
 80WLmax = None
 81
 82# wavelength to calculate atomic form factor and anomolous scattering factor
 83wl_value = None
 84
 85# Miller index to calculate Fhkl
 86hkl = [5, 1, 3]
 87#hkl = [-9, -1, 2]
 88
 89# graph configuration
 90figuresize = (8, 4)
 91scale  = 'linear'
 92#scale  = 'log'
 93
 94
 95#=============================
 96# Treat argments
 97#=============================
 98def usage():
 99    """
100    スクリプトの利用方法とコマンドライン引数の例を表示します。
101
102    各モード (`asf`, `anom`, `F`, `inf`) の使用例と、それに続く引数のフォーマットを標準出力に表示します。
103    """
104    global mode
105    global ciffile
106    global target_atom, xray_source
107    global smin, smax, ns
108    global hkl
109    global scale
110
111    print("")
112    print("Usage:")
113    print("  (Ia)  python {} asf (target_atom xray_source smin smax ns s_value plot_scale".format(sys.argv[0]))
114    print("      plot atomic form factor function for target_atom")
115    print("      ex: python {} {} {} {} {} {} {} {} {}"
116                    .format(sys.argv[0], 'asf', target_atom, xray_source, smin, smax, ns, s_value, scale))
117    print("  (Ib)  python {} anom (target_atom wl_min wl_max wl_value wl scale)".format(sys.argv[0]))
118    print("      plot anomalous scattering factor spectrum for target_atom")
119    print("      ex: python {} {} {} {} {} {} {}"
120                    .format(sys.argv[0], 'anom', target_atom, WLmin, WLmax, wl_value, scale))
121    print("  (IIa) python {} F CIF_file (xray_source h k l)".format(sys.argv[0]))
122    print("      calculate crystal structure factor for the CIF specified by ciffile")
123    print("          plot_scale: 'linear', 'log'")
124    print("     ex: python {} {} {} {} {} {}"
125                .format(sys.argv[0], ciffile, xray_source, hkl[0], hkl[1], hkl[2]))
126    print("  (IIb) python {} inf CIF_file".format(sys.argv[0]))
127    print("      show crystal structure information for the CIF specified by ciffile")
128    print("     ex: python {} {}".format(sys.argv[0], ciffile))
129
130def updatevars():
131    """
132    コマンドライン引数に基づいてグローバル変数を更新します。
133
134    `sys.argv` から引数を解析し、`mode`, `ciffile`, `target_atom`, `xray_source`,
135    `smin`, `smax`, `ns`, `s_value`, `WLmin`, `WLmax`, `wl_value`, `hkl`, `scale`
136    などのグローバル変数の値を上書きします。
137    無効なモードが指定された場合はエラーメッセージを表示し、終了します。
138    """
139    global mode
140    global ciffile
141    global target_atom, xray_source
142    global smin, smax, ns, s_value
143    global WLmin, WLmax, wl_value
144    global scale
145
146    argv = sys.argv
147#    if len(argv) == 1:
148#        terminate(usage = usage)
149
150    mode        = getarg(1, mode)   
151    if mode == 'asf':
152        target_atom = getarg     (2, target_atom)
153        xray_source = getarg     (3, xray_source)
154        smin        = getfloatarg(4, smin)
155        smax        = getfloatarg(5, smax)
156        ns          = getintarg  (6, ns)
157        s_value     = getfloatarg(7, s_value)
158        scale       = getarg     (8, scale)
159    elif mode == 'anom':
160        target_atom = getarg     (2, target_atom)
161        WLmin       = getfloatarg(3, WLmin)
162        WLmax       = getfloatarg(4, WLmax)
163        wl_value    = getfloatarg(5, wl_value)
164        scale       = getarg     (6, scale)
165    elif mode == 'F':
166        ciffile     = getarg     (2, ciffile)
167        xray_source = getarg     (3, xray_source)
168        hkl[0]      = getintarg  (4, hkl[0])
169        hkl[1]      = getintarg  (5, hkl[1])
170        hkl[2]      = getintarg  (6, hkl[2])
171    elif mode == 'inf':
172        ciffile = getarg(2, ciffile)
173    else:
174        terminate("Error: Invalide mode [{}]".format(mode), usage = usage)
175
176def cal_Fhkl(cry: tkCrystal, xray_source: str | float) -> list[dict]:
177    """
178    指定された結晶構造とX線源に基づいて、ミラー指数範囲内の結晶構造因子を計算します。
179
180    hmin から hmax、kmin から kmax、lmin から lmax の範囲で全てのミラー指数について
181    回折角、散乱ベクトル、2θ角、原子散乱因子、そして結晶構造因子 Fhkl を計算します。
182    計算結果は2θ角でソートされて返されます。
183
184    :param cry: tkCrystal 結晶構造情報を持つtkCrystalオブジェクト。
185    :param xray_source: str | float X線源の名前(例: 'CuKa1')または波長(nm)。
186    :returns: list[dict] 各ミラー指数に対する回折情報と結晶構造因子を含む辞書のリスト。
187                         各辞書は'hkl' (tuple), 'dhkl' (float), 'Q2' (float), 'Fhkl' (complex) のキーを持ちます。
188    """
189    hmin, hmax = -4, 4
190    kmin, kmax = -4, 4
191    lmin, lmax = -4, 4
192    
193    print("X-ray source:", xray_source)
194    wl = pfloat(xray_source, defval = None)
195    if wl is None or wl == 0.0:
196        wl = wavelength[xray_source]
197    else:
198        xray_source = wl
199    print("  wavelength: {} nm".format(wl))
200
201    AtomTypes = cry.AtomTypeList()
202    AtomSites = cry.ExpandedAtomSiteList()
203
204    inf = []
205    print("")
206    print("Crystal structure factors:")
207    for h, k, l in product(range(hmin, hmax+1), range(kmin, kmax+1), range(lmin, lmax+1)):
208        dhkl, sB, Q2 = cry.DiffractionAngle(wl * 10.0, h, k, l)    # angstrom in crystal object
209        if dhkl is None or Q2 is None: continue
210
211#        print("Diffraction for ({} {} {})".format(*hkl))
212#        print("  d({} {} {}) = {:10.6g} A".format(*hkl, dhkl))
213#        print("  s_B  = {:10.6g} nm^-1".format(sB))
214#        print("  2Q_B = {:10.6g} rad = {:10.6g} deg".format(Q2, Q2 * 180.0 / pi))
215#        print("  Atomic form factors at s_B:")
216        for i in range(len(AtomTypes)):
217            atom = AtomTypes[i]
218            atomname  = atom.AtomTypeOnly()
219            asf = atom.asf(sB) 
220#            print("    {:2}: asf(sB) = {:10.6g}".format(atomname, asf))
221
222        Fhkl = cry.Fhkl(sB, h, k, l)
223        inf.append({
224            'hkl' : (h, k, l),
225            'dhkl': dhkl,
226            'Q2'  : Q2 * 180.0 / pi,
227            'Fhkl': Fhkl,
228            })
229
230    sorted_inf = sorted(inf, key=lambda x: x['Q2'])
231    return sorted_inf
232
233def cal_Fhkl_single(cry: tkCrystal, hkl: list[int], xray_source: str | float) -> None:
234    """
235    指定されたミラー指数とX線源について、結晶構造因子を計算しプロットします。
236
237    特定のミラー指数 `hkl` に対して回折角、散乱ベクトル、2θ角、そして結晶構造因子 `Fhkl` を計算します。
238    また、指定された散乱ベクトル範囲で各原子種の原子散乱因子を計算し、グラフとして表示します。
239    計算された `Fhkl` の値も標準出力に出力されます。
240
241    :param cry: tkCrystal 結晶構造情報を持つtkCrystalオブジェクト。
242    :param hkl: list[int] 計算対象のミラー指数 `[h, k, l]`。
243    :param xray_source: str | float X線源の名前(例: 'CuKa1')または波長(nm)。
244    :returns: None 計算結果を標準出力に表示し、原子散乱因子のグラフをプロットしてユーザーの入力を待ちます。
245    """
246    print("X-ray source:", xray_source)
247    wl = pfloat(xray_source, defval = None)
248    if wl is None or wl == 0.0:
249        wl = wavelength[xray_source]
250    else:
251        xray_source = wl
252    print("  wavelength: {} nm".format(wl))
253    print("h k l = {} {} {}".format(hkl[0], hkl[1], hkl[2]))
254
255    AtomTypes = cry.AtomTypeList()
256    AtomSites = cry.ExpandedAtomSiteList()
257
258    print("")
259    dhkl, sB, Q2 = cry.DiffractionAngle(wl * 10.0, *hkl)    # angstrom in crystal object
260    print("Diffraction for ({} {} {})".format(*hkl))
261    print("  d({} {} {}) = {:10.6g} A".format(*hkl, dhkl))
262    print("  s_B  = {:10.6g} nm^-1".format(sB))
263    print("  2Q_B = {:10.6g} rad = {:10.6g} deg".format(Q2, Q2 * 180.0 / pi))
264    print("  Atomic form factors at s_B:")
265    for i in range(len(AtomTypes)):
266        atom = AtomTypes[i]
267        atomname  = atom.AtomTypeOnly()
268        asf = atom.asf(sB) 
269        print("    {:2}: asf(sB) = {:10.6g}".format(atomname, asf))
270
271    Fhkl = cry.Fhkl(sB, *hkl)
272    print("  F({} {} {}) = {:10.6g}".format(*hkl, Fhkl))
273
274    print("")
275    print("Plot atomic form factor:")
276    sstep = (smax - smin) / (ns - 1)
277    print("  plot range: s = sin(Q) / wl = {} to {} at {} nm^-1 step, {} points".format(smin, smax, sstep, ns))
278
279    xs = [smin + i * sstep for i in range(ns)]
280    yfs = []
281    yfsB = []
282    for i in range(len(AtomTypes)):
283        at = AtomTypes[i]
284        yfsB.append(at.asf(sB))
285        print("")
286        print("{:8}\t{:12}".format("s=sin(Q)/wl (nm^-1)", "f(s)"))
287        _fs = []
288        for i in range(ns):
289            s = xs[i]
290            fs = at.asf(s)
291            _fs.append(fs)
292            print("{:8.4f}\t{:12.6g}".format(s, fs))
293        yfs.append(_fs)
294
295    print("")
296    print("Plot")
297
298#=============================
299# Plot graphs
300#=============================
301    fig = plt.figure(figsize = figuresize)
302
303    ax1 = fig.add_subplot(1, 2, 1)
304
305    for i in range(len(AtomTypes)):
306        at = AtomTypes[i]
307        name = at.AtomType()
308        ax1.plot(xs, np.array(yfs[i]).real,  label = name, linewidth = 0.5)
309        ax1.plot(sB, yfsB[i].real, linestyle = 'none', marker = 'o')
310    ax1.set_xlim([smin, smax])
311    ylim = ax1.get_ylim()
312    ax1.set_ylim([0.0, ylim[1]])
313    ax1.set_xlabel("s = sin $ \Theta  / \lambda$ (nm$^{-1}$)")
314    ax1.set_ylabel("real part of $f(s)$")
315    ax1.set_title('atomic form factor')
316    ax1.legend()
317    if scale == 'log':
318        ax1.set_yscale('log')
319    plt.tight_layout()
320
321    plt.pause(0.1)
322
323    print("")
324    print("Press ENTER to exit>>", end = '')
325    input()
326    
327    terminate(usage = usage)
328
329def exec_Fhkl() -> None:
330    """
331    CIFファイルから結晶構造を読み込み、指定されたミラー指数に対する結晶構造因子を計算し表示します。
332
333    グローバル変数 `ciffile`, `xray_source`, `hkl` を使用して、CIFファイルを解析し、
334    結晶構造情報を取得します。その後、`cal_Fhkl_single` 関数を呼び出して
335    結晶構造因子を計算し、結果を標準出力に表示し、原子散乱因子のグラフをプロットします。
336    """
337    global xray_source
338    
339    print("X-ray source:", xray_source)
340    wl = pfloat(xray_source, defval = None)
341    if wl is None or wl == 0.0:
342        wl = wavelength[xray_source]
343    else:
344        xray_source = wl
345    print("  wavelength: {} nm".format(wl))
346
347    print("CIF file: {}".format(ciffile))
348    print("single: {}".format(single))
349    print("findvalidstructure: {}".format(findvalidstructure))
350
351    print("")
352    print("Read [{}]".format(ciffile))
353
354#    if not tkutils.IsFile(ciffile):
355#        terminate("Error: Invalid ciffile [{}]".format(ciffile), usage = usage)
356    cif = tkCIF()
357    cif.debug = debug
358    
359    cifdata = cif.ReadCIF(ciffile, find_valid_structure = findvalidstructure)
360    cif.Close()
361
362    if not cifdata:
363        terminate("Error: Could not get cifdat from ciffile [{}]".format(ciffile), usage = usage)
364
365    cry = cifdata.GetCrystal()
366#    cry.PrintInf()
367
368    print("")
369    print("Crystal structure:")
370    a, b, c, alpha, beta, gamm = cry.LatticeParameters()
371    print("cell: {} {} {} A   {} {} {}".format(a, b, c, alpha, beta, gamm))
372
373    print("")
374    print("Atom types:")
375    AtomTypes = cry.AtomTypeList()
376    for i in range(len(AtomTypes)):
377        t = AtomTypes[i]
378        typea = t.AtomType()
379        typeo = t.AtomTypeOnly()
380        charge = t.Charge()
381        AN     = t.AtomicNumber()
382        M      = t.AtomicMass()
383        print("  %3d: %4s (%2s) charge=%8.4f  [Z=%3d  M=%6.4f]" % (i, typea, typeo, charge, AN, M))
384        asfparams = t.ReadASFParameters(XraySource = wl)
385        print("     asf parameters: ", asfparams[0:10])
386        print("                     ", asfparams[10:])
387
388    print("")
389    print("Expanded atom sites:")
390    AtomSites = cry.ExpandedAtomSiteList()
391    for atom in AtomSites:
392        label     = atom.Label()
393        atomname  = atom.AtomName()
394        atomname0 = atom.AtomNameOnly()
395        charge    = atom.Charge()
396        pos       = atom.Position()
397        occ       = atom.Occupancy()
398        id        = atom.IdAsymmetricAtomSite()
399        iAtomType = atom.iAtomType()
400        atomtype  = atom.AtomType()
401        m         = atom.Multiplicity()
402        print("  %3d: (iAtomType=%d) %5s: %4s charge=%6.3f (%6.3f, %6.3f, %6.3f) occ=%8.4f  m=%d" 
403                % (id, iAtomType, label, atomname, charge, pos[0], pos[1], pos[2], occ, m))
404
405    cal_Fhkl_single(cry, hkl, xray_source = 'CuKa1')
406
407
408def anom() -> None:
409    """
410    指定された原子の異常散乱因子スペクトルを計算し、グラフとして表示します。
411
412    グローバル変数 `target_atom`, `WLmin`, `WLmax`, `wl_value`, `scale` を使用します。
413    `tkAtomType` オブジェクトから異常散乱因子のデータを読み込み、
414    指定された波長範囲でスペクトルをプロットします。
415    特定の波長 `wl_value` における異常散乱因子の値も表示します。
416    """
417    global target_atom
418    global WLmin, WLmax
419    
420    at = tkAtomType(target_atom)
421    typea  = at.AtomType()
422    typeo  = at.AtomTypeOnly()
423    charge = at.Charge()
424    Z      = at.AtomicNumber()
425    M      = at.AtomicMass()
426    print("Target atom:", target_atom)
427    print("  %4s (%2s) charge=%8.4f  [Z=%3d  M=%6.4f]" % (typea, typeo, charge, Z, M))
428
429    print("")
430    print("Anomalous scattering factor")
431    print("citation: http://skuld.bmsc.washington.edu/scatter/")
432
433    xE, xwl, yf1, yf2, dbpath = at.ReadAnomalousScatteringFactor()
434    print("DB path: ", dbpath)
435    if WLmin is None:
436        WLmin = 0.0
437    if WLmax is None:
438        WLmax = max(xwl)
439    print("  plot range: wavelength = {} to {} nm".format(WLmin, WLmax))
440
441    print("{:8}\t{:12}\t{:12}\t{:12}".format("E (eV)", "wl (nm)", "f1", "f2"))
442    idx0 = None
443    idx1 = None
444    for i in range(len(xE)):
445        if xwl[i] > WLmin:
446            idx0 = i
447        if xwl[i] < WLmax and idx1 is None:
448            idx1 = i
449        print("{:8.4f}\t{:12.6g}\t{:12.6g}\t{:12.6g}".format(xE[i], xwl[i], yf1[i], yf2[i]))
450
451    print("")
452    print("  plot index range: {} - {}".format(idx1, idx0))
453    xE   = xE[idx1:idx0]
454    xwl  = xwl[idx1:idx0]
455    yf1  = yf1[idx1:idx0]
456    yf2  = yf2[idx1:idx0]
457    
458    print("")
459    f1, f2 = at.AnomalousScatteringFactor(wl_value)
460    print("anormalous scattering factor at wl = {:8.4g} nm = {:10.6g} + j{:10.6g}".format(wl_value, f1, f2))
461    print("")
462    print("Plot")
463
464#=============================
465# Plot graphs
466#=============================
467    fig = plt.figure(figsize = figuresize)
468
469    ax1 = fig.add_subplot(1, 2, 1)
470    ax2 = fig.add_subplot(1, 2, 2)
471
472    ax1.plot(xwl, yf1, label = target_atom, color = 'black', linewidth = 0.5)
473    if wl_value is not None:
474        ax1.plot([wl_value], [f1], linestyle = 'none', marker = 'o') #, markersize = 0.5)
475    ax2.plot(xwl, yf2, label = target_atom, color = 'black', linewidth = 0.5)
476    if wl_value is not None:
477        ax2.plot([wl_value], [f2], linestyle = 'none', marker = 'o') #, markersize = 0.5)
478
479    ax1.set_xlim([WLmin, WLmax])
480    ax1.set_ylim([min(yf1), max(yf1) * 1.1])
481    ax1.set_xlabel("Wavelength (nm)")
482    ax1.set_ylabel("f'")
483    ax1.set_title('real part of anomalous scattering factor')
484    ax2.set_xlim([WLmin, WLmax])
485    ax2.set_ylim([0.0, max(yf2) * 1.1])
486    ax2.set_xlabel("Wavelength (nm)")
487    ax2.set_ylabel("f''")
488    ax2.set_title('imaginary part of anomalous scattering factor')
489    ax1.legend()
490    ax2.legend()
491    if scale == 'log':
492        ax1.set_yscale('log')
493        ax2.set_yscale('log')
494
495    plt.tight_layout()
496
497    plt.pause(0.1)
498
499    print("")
500    print("Press ENTER to exit>>", end = '')
501    input()
502    
503    terminate(usage = usage)
504
505def asf() -> None:
506    """
507    指定された原子の原子散乱因子(Atomic Scattering Factor, ASF)を計算し、グラフとして表示します。
508
509    グローバル変数 `target_atom`, `xray_source`, `smin`, `smax`, `ns`, `s_value`, `scale` を使用します。
510    `tkAtomType` オブジェクトから原子散乱因子のデータを読み込み、
511    指定された散乱ベクトル `s` の範囲で ASF を計算し、プロットします。
512    特定の `s_value` における ASF の値も表示します。
513    """
514    global target_atom
515    global xray_source, wavelength
516    global smin, smax, ns
517
518    print("X-ray source:", xray_source)
519    wl = pfloat(xray_source)
520    if wl is None or wl == 0.0:
521        wl = wavelength[xray_source]
522    else:
523        xray_source = wl
524    print("  wavelength: {} nm".format(wl))
525
526    print("")
527    print("Atomic form factor:")
528    sstep = (smax - smin) / (ns - 1)
529    print("  plot range: s = sin(Q) / wl = {} to {} at {} nm^-1 step, {} points".format(smin, smax, sstep, ns))
530
531    at = tkAtomType(target_atom)
532    typea  = at.AtomType()
533    typeo  = at.AtomTypeOnly()
534    charge = at.Charge()
535    Z      = at.AtomicNumber()
536    M      = at.AtomicMass()
537    print("Target atom:", target_atom)
538    print("  %4s (%2s) charge=%8.4f  [Z=%3d  M=%6.4f]" % (typea, typeo, charge, Z, M))
539    asf_params = at.ReadASFParameters(target_atom)
540    print("  ASF parameters:", asf_params)
541    print("  asf(s) at s={:8.4g} = {:10.6g}".format(s_value, at.asf(s_value)))
542
543    print("")
544    print("Calculate atomic form factor function f(s)")
545    xs  = []
546    yfs = []
547    print("{:8}\t{:12}".format("s=sin(Q)/wl (nm^-1)", "f(s)"))
548    for i in range(ns):
549        s = smin + i * sstep
550        fs = at.asf(s)
551        xs.append(s)
552        yfs.append(fs)
553        print("{:8.4f}\t{:12.6g}".format(s, fs))
554
555    print("")
556    print("Plot")
557
558#=============================
559# Plot graphs
560#=============================
561    fig = plt.figure(figsize = figuresize)
562
563    ax1 = fig.add_subplot(1, 2, 1)
564
565    ax1.plot(xs, yfs,  label = target_atom, color = 'black', linewidth = 0.5)
566    ax1.plot([s_value], [at.asf(s_value)], linestyle = 'none', marker = 'o')
567    ax1.set_xlim([smin, smax])
568    ax1.set_ylim([0.0, max(yfs) * 1.1])
569    ax1.set_xlabel("s = sin $\Theta / \lambda$ (nm$^{-1}$)")
570    ax1.set_ylabel("$f(s)$")
571    ax1.set_title('atomic form factor')
572    ax1.legend()
573    if scale == 'log':
574        ax1.set_yscale('log')
575    plt.tight_layout()
576
577    plt.pause(0.1)
578
579    print("")
580    print("Press ENTER to exit>>", end = '')
581    input()
582    
583    terminate(usage = usage)
584
585def inf() -> None:
586    """
587    指定されたCIFファイルから結晶構造情報を読み込み、その詳細を標準出力に表示します。
588
589    グローバル変数 `ciffile`, `single`, `findvalidstructure` を使用します。
590    CIFファイルを読み込み、`tkCIF` オブジェクトと `tkCrystal` オブジェクトが提供する
591    `Print()` および `PrintInf()` メソッドを呼び出して、
592    読み込まれた結晶構造に関する詳細情報(格子パラメータ、原子の種類、原子サイトなど)を出力します。
593    """
594    global target_atom
595    global xray_source, wavelength
596    global smin, smax, ns
597
598    print("CIF file: {}".format(ciffile))
599    print("single: {}".format(single))
600    print("findvalidstructure: {}".format(findvalidstructure))
601
602    print("")
603    print("Read [{}]".format(ciffile))
604
605#    if not tkutils.IsFile(ciffile):
606#        terminate("Error: Invalid ciffile [{}]".format(ciffile), usage = usage)
607    cif = tkCIF()
608    cif.debug = debug
609    
610    cifdata = cif.ReadCIF(ciffile, find_valid_structure = findvalidstructure)
611    cif.Close()
612
613    if not cifdata:
614        terminate("Error: Could not get cifdat from ciffile [{}]".format(ciffile), usage = usage)
615
616    print("")
617    print("==============================================")
618    print("    CIF inf")
619    print("==============================================")
620    cifdata.Print()
621    cry = cifdata.GetCrystal()
622    print("")
623    print("==============================================")
624    print("    Crystal inf")
625    print("==============================================")
626    cry.PrintInf()
627    print("")
628            
629#    d = cry.Density()
630#    ad = cry.AtomDensity()
631
632    terminate(usage = usage)
633
634
635def main() -> None:
636    """
637    スクリプトのメインエントリポイント。コマンドライン引数に基づいて処理モードを選択し実行します。
638
639    `updatevars()` を呼び出してコマンドライン引数を解析し、
640    グローバル変数 `mode` に応じて `asf()`, `anom()`, `exec_Fhkl()`, `inf()` の
641    いずれかの関数を実行します。
642    無効なモードが指定された場合はエラーメッセージを表示し、終了します。
643    """
644    global mode
645    global xray_source, wavelength
646    
647    updatevars()
648
649    print("")
650    print("=============== Atom informat, form factor, crystal structure factor ============")
651    print("")
652    print("mode: ", mode)
653
654    if mode == 'asf':
655        asf()
656    elif mode == 'anom':
657        anom()
658    elif mode == 'F':
659        exec_Fhkl()
660    elif mode == 'inf':
661        inf()
662    else:
663        terminate("Error: Invalide mode [{}]".format(mode), usage = usage)
664
665
666if __name__ == "__main__":
667    main()