Skip to content

Commit

Permalink
Version 2.3.0
Browse files Browse the repository at this point in the history
Merged pull request for non-integer hkl option on SF and electron form factors.
Thanks Prestipino!
Added menu with various options to GUI.
Updated docs and examples.
  • Loading branch information
DanPorter committed May 8, 2023
1 parent d644152 commit 3ee9349
Show file tree
Hide file tree
Showing 40 changed files with 1,534 additions and 311 deletions.
196 changes: 196 additions & 0 deletions Dans_Diffraction/Structures/NaCoO2_stripe_supercell.cif

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions Dans_Diffraction/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
Diamond
2017
Version 2.2.3
Last updated: 14/01/23
Version 2.3.0
Last updated: 08/05/23
Version History:
02/03/18 1.0 Version History started.
Expand Down Expand Up @@ -66,6 +66,7 @@
23/07/22 2.2.1 Fixed error in MultiCrystal.Scatter
06/01/23 2.2.2 Removed redundent references to np.float
14/01/23 2.2.3 Corrected background error in xtl.Scatter.powder
08/05/23 2.3.0 Merged pull request for non-integer hkl option on SF and electron form factors. Thanks Prestipino!
-----------------------------------------------------------------------------
Copyright 2023 Diamond Light Source Ltd.
Expand Down Expand Up @@ -119,8 +120,8 @@
from .classes_fdmnes import Fdmnes, FdmnesAnalysis


__version__ = '2.2.3'
__date__ = '14/01/23'
__version__ = '2.3.0'
__date__ = '08/05/23'


# Build
Expand Down Expand Up @@ -155,6 +156,10 @@ def module_info():
return out


def doc_str():
return __doc__


# tkGUI Activation
def start_gui(xtl=None):
"""Start GUI window (requires tkinter)"""
Expand Down
5 changes: 4 additions & 1 deletion Dans_Diffraction/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
By Dan Porter, PhD
Diamond
2017
2023
"""
if __name__ == '__main__':

Expand All @@ -32,6 +32,9 @@
if 'cif' in arg.lower():
xtl = dif.Crystal(arg)
print(xtl.info())
elif arg in dif.structure_list.list:
xtl = getattr(dif.structure_list, arg)()
print(xtl.info())
elif 'gui' in arg.lower():
xtl.start_gui()

4 changes: 2 additions & 2 deletions Dans_Diffraction/classes_crystal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1826,11 +1826,11 @@ def print_symmetric_coordinate_operations(self, UVW, remove_identical=True):
unique_uvw, uniqueidx, matchidx = fg.unique_vector(sym_uvw, tol=0.01)

out += ' (%1.3g, %1.3g, %1.3g)\n' % (u, v, w)
out += ' n u v w Symmetry Magnetic Symmetry\n'
out += ' n u v w Symmetry Magnetic Symmetry\n'
if remove_identical:
# Only display distict positions
for n in range(len(unique_uvw)):
out += '%3d %7.4f %7.4f %7.4f %20s %20s\n' % (
out += '%3d %7.4f %7.4f %7.4f %30s %20s\n' % (
uniqueidx[n], unique_uvw[n, 0], unique_uvw[n, 1], unique_uvw[n, 2],
self.symmetry_operations[uniqueidx[n]], self.symmetry_operations_magnetic[uniqueidx[n]])
else:
Expand Down
39 changes: 26 additions & 13 deletions Dans_Diffraction/classes_scattering.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
Diamond
2017
Version 2.1.1
Last updated: 14/01/23
Version 2.2.0
Last updated: 06/05/23
Version History:
10/09/17 0.1 Program created
Expand All @@ -31,6 +31,7 @@
08/02/22 2.0.3 Corrected error in powder of wrong tth values. Thanks Mirko!
14/03/22 2.1.0 powder() updated for new inputs and outputs for pVoight and custom peak shapes. Thanks yevgenyr!
14/01/23 2.1.1 Corrected background error in xtl.Scatter.powder
06/05/23 2.0.0 Merged pull request for non-integer hkl option on SF and electron form factors. Thanks Prestipino!
@author: DGPorter
"""
Expand All @@ -45,7 +46,7 @@
from . import multiple_scattering as ms
# from . import tensor_scattering as ts # Removed V1.7

__version__ = '2.1.1'
__version__ = '2.2.0'
__scattering_types__ = {'xray': ['xray', 'x', 'x-ray', 'thomson', 'charge'],
'neutron': ['neutron', 'n', 'nuclear'],
'xray magnetic': ['xray magnetic', 'magnetic xray', 'spin xray', 'xray spin'],
Expand Down Expand Up @@ -356,6 +357,7 @@ def structure_factor(self, hkl=None, scattering_type=None, int_hkl=True, **kwarg
:param hkl: array[n,3] : reflection indexes (h, k, l)
:param scattering_type: str : one of ['xray','neutron','xray magnetic','neutron magnetic','xray resonant']
:param int_hkl: Bool : when True, hkl values are converted to integer.
:param kwargs: additional options to pass to scattering function
:return: complex array[n] : structure factors
"""
Expand All @@ -365,9 +367,9 @@ def structure_factor(self, hkl=None, scattering_type=None, int_hkl=True, **kwarg
if scattering_type is None:
scattering_type = self._scattering_type
if int_hkl:
hkl = np.asarray(np.rint(hkl), dtype=np.float).reshape([-1, 3])
hkl = np.asarray(np.rint(hkl), dtype=float).reshape([-1, 3])
else:
hkl = np.asarray(hkl, dtype=np.float).reshape([-1, 3])
hkl = np.asarray(hkl, dtype=float).reshape([-1, 3])
uvw, atom_type, label, occ, uiso, mxmymz = self.xtl.Structure.get()

q = self.xtl.Cell.calculateQ(hkl)
Expand Down Expand Up @@ -424,14 +426,14 @@ def structure_factor(self, hkl=None, scattering_type=None, int_hkl=True, **kwarg
# Scattering factors
if scattering_type in fs.SCATTERING_TYPES['neutron']:
ff = fc.atom_properties(atom_type, 'Coh_b')
elif scattering_type in fs.SCATTERING_TYPES['electron']:
ff = fc.electron_scattering_factor(atom_type, qmag)
elif scattering_type in fs.SCATTERING_TYPES['xray fast']:
ff = fc.atom_properties(atom_type, 'Z')
elif scattering_type in fs.SCATTERING_TYPES['xray dispersion']:
ff = fc.xray_scattering_factor_resonant(atom_type, qmag, enval)
elif self._use_waaskirf_scattering_factor:
ff = fc.xray_scattering_factor_WaasKirf(atom_type, qmag)
elif scattering_type in fs.SCATTERING_TYPES['electron']:
ff = fc.electron_scattering_factor(atom_type, qmag)
else:
ff = fc.xray_scattering_factor(atom_type, qmag)

Expand Down Expand Up @@ -474,10 +476,12 @@ def structure_factor(self, hkl=None, scattering_type=None, int_hkl=True, **kwarg

def intensity(self, hkl=None, scattering_type=None, int_hkl=True, **options):
"""
:param hkl:
:param scattering_type: str : one of ['xray','neutron','xray magnetic','neutron magnetic','xray resonant']
:return:
Return the structure factor squared
:param hkl: array[n,3] : reflection indexes (h, k, l)
:param scattering_type: str : one of ['xray','neutron', 'electron', 'xray magnetic','neutron magnetic','xray resonant']
:param int_hkl: Bool : when True, hkl values are converted to integer.
:param kwargs: additional options to pass to scattering function
:return: float array[n] : array of |SF|^2
"""
return fs.intensity(self.new_structure_factor(hkl, scattering_type, int_hkl, **options))
new_intensity = intensity
Expand Down Expand Up @@ -623,7 +627,7 @@ def x_ray(self, HKL):

# Calculate structure factor
# Broadcasting used on 2D ff
SF = np.sum(ff*dw*occ*np.exp(1j*2*np.pi*dot_KR),axis=1)
SF = np.sum(ff*dw*occ*np.exp(1j*2*np.pi*dot_KR), axis=1)
#SF = np.zeros(Nref,dtype=complex)
#for ref in range(Nref):
# for at in range(Nat):
Expand Down Expand Up @@ -723,7 +727,16 @@ def xray_dispersion(self, HKL, energy_kev):
# Calculate intensity
I = sf * np.conj(sf)
return np.real(I)


def electron(self, HKL):
"""
Calculate the squared structure factor for the given HKL, using electron form factors
Scattering.electron([1,0,0])
Scattering.electron([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the real intensity at each reflection.
"""
return self.intensity(HKL, scattering_type='electron')

def neutron(self, HKL):
"""
Calculate the squared structure factor for the given HKL, using neutron scattering length
Expand Down
23 changes: 17 additions & 6 deletions Dans_Diffraction/functions_crystallography.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
OR
- from Dans_Diffraction import functions_crystallography as fc
Version 3.7.2
Last updated: 23/04/22
Version 3.8.0
Last updated: 07/05/23
Version History:
09/07/15 0.1 Version History started.
Expand Down Expand Up @@ -40,9 +40,11 @@
15/11/21 3.7 Added diffractometer orientation commands from Busing & Levy, H. You
12/01/22 3.7.1 Added gen_sym_axial_vector
23/04/22 3.7.2 Corrected magnitude of Q in magnetic_structure_factors
07/05/23 3.8.0 Added electron_scattering_factors and electron wavelength formula
Acknoledgements:
April 2020 Thanks to ChunHai Wang for helpful suggestions in readcif!
May 2023 Thanks to Carmelo Prestipino for adding electron scattering factors
@author: DGPorter
"""
Expand Down Expand Up @@ -966,6 +968,7 @@ def xray_scattering_factor(element, Qmag=0):
Qff[:, n] = f
return Qff


def electron_scattering_factor(element, Qmag=0):
"""
Read X-ray scattering factor table, calculate f(|Q|)
Expand All @@ -982,12 +985,10 @@ def electron_scattering_factor(element, Qmag=0):
Qmag = np.asarray(Qmag).reshape(-1)

try:
data = np.genfromtxt(PENGFILE, skip_header=0, dtype=None, names=True,
encoding='ascii', delimiter=',')
data = np.genfromtxt(PENGFILE, skip_header=0, dtype=None, names=True, encoding='ascii', delimiter=',')
except TypeError:
# Numpy version < 1.14
data = np.genfromtxt(PENGFILE, skip_header=0, dtype=None, names=True,
delimiter=',')
data = np.genfromtxt(PENGFILE, skip_header=0, dtype=None, names=True, delimiter=',')
# elements must be a list e.g. ['Co','O']
elements_l = np.asarray(element).reshape(-1)
all_elements = [el for el in data['Element']]
Expand Down Expand Up @@ -3104,6 +3105,16 @@ def wavevector(energy_kev=None, wavelength=None):
return 2 * np.pi / wavelength


def electron_wavelenth(energy_ev):
"""
Calcualte the electron wavelength in Angstroms using DeBroglie's formula
lambda [nm] ~ sqrt( 1.5 / E [eV] )
:param energy_ev: electron energy in eV
:return: wavelength in Anstroms
"""
return fg.h / np.sqrt(2 * fg.me * energy_ev * fg.e) / fg.A


def biso2uiso(biso):
"""
Convert B isotropic thermal parameters to U isotropic thermal parameters
Expand Down
5 changes: 4 additions & 1 deletion Dans_Diffraction/functions_scattering.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
'xray magnetic': ['xray magnetic', 'magnetic xray', 'spin xray', 'xray spin'],
'neutron magnetic': ['neutron magnetic', 'magnetic neutron', 'magnetic'],
'xray resonant': ['xray resonant', 'resonant', 'resonant xray', 'rxs'],
'xray dispersion': ['dispersion', 'xray dispersion']
'xray dispersion': ['dispersion', 'xray dispersion'],
'electron': ['electron', 'ele', 'e'],
}


Expand Down Expand Up @@ -812,6 +813,8 @@ def get_scattering_function(scattering_type):
return sf_xray_dispersion
if scattering_type in SCATTERING_TYPES['neutron']:
return sf_atom
if scattering_type in SCATTERING_TYPES['electron']:
return sf_atom
if scattering_type in SCATTERING_TYPES['xray magnetic']:
return sf_magnetic_xray
if scattering_type in SCATTERING_TYPES['neutron magnetic']:
Expand Down
63 changes: 63 additions & 0 deletions Dans_Diffraction/tkgui/basic_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
"""

import sys
import re

if sys.version_info[0] < 3:
import Tkinter as tk
import tkMessageBox as messagebox
else:
import tkinter as tk
from tkinter import messagebox

# Fonts
TF = ["Times", 12]
Expand Down Expand Up @@ -35,6 +38,66 @@
TTFG = 'red'


def popup_message(parent, title, message):
"""Create a message box"""
root = tk.Toplevel(parent)
root.title(title)
#frame = tk.Frame(root)
tk.Label(root, text=message, padx=20, pady=20).pack()
#root.after(2000, root.destroy)
return root


def popup_about():
"""Create about message"""
from Dans_Diffraction import version_info, module_info
msg = "%s\n\n" \
"A Python package for loading crystal structures from " \
"cif files and calculating diffraction information.\n\n" \
"Module Info:\n%s\n\n" \
"By Dan Porter, Diamond Light Source Ltd" % (version_info(), module_info())
messagebox.showinfo('About', msg)


def popup_help():
"""Create help message"""
from Dans_Diffraction import doc_str
return StringViewer(doc_str(), 'Dans_Diffraction Help', width=121)


def topmenu(root, menu_dict):
"""
Add a menubar to tkinter frame
:param root: tkinter root
:param menu_dict: {Menu name: {Item name: function}}
:return: None
"""
# Setup menubar
menubar = tk.Menu(root)

for item in menu_dict:
men = tk.Menu(menubar, tearoff=0)
for label, function in menu_dict[item].items():
men.add_command(label=label, command=function)
menubar.add_cascade(label=item, menu=men)
root.config(menu=menubar)


def menu_docs():
"""Open local docs"""
import os
import webbrowser
docs_dir = os.path.join(os.path.split(__file__)[0], '../../docs/Dans_Diffraction.html')
docs_dir = os.path.abspath(docs_dir)
webbrowser.open_new_tab(docs_dir)


def menu_github():
"""Open GitHub page"""
import webbrowser
webbrowser.open_new_tab("https://github.com/DanPorter/Dans_Diffraction#dans_diffaction")


class StringViewer:
"""
Simple GUI that displays strings
Expand Down
Loading

0 comments on commit 3ee9349

Please sign in to comment.