Skip to content

Commit d5a0fce

Browse files
committed
update
1 parent 487d4e0 commit d5a0fce

File tree

9 files changed

+2296
-199
lines changed

9 files changed

+2296
-199
lines changed

notebooks/Imaging/D1-Diffraction_Rings.ipynb

Lines changed: 80 additions & 93 deletions
Large diffs are not rendered by default.

notebooks/Imaging/D2-Diffraction_Spots.ipynb

Lines changed: 1929 additions & 0 deletions
Large diffs are not rendered by default.
28.1 KB
Loading

notebooks/Spectroscopy/EDS.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@
893893
],
894894
"metadata": {
895895
"kernelspec": {
896-
"display_name": "base",
896+
"display_name": "Python 3 (ipykernel)",
897897
"language": "python",
898898
"name": "python3"
899899
},

pyTEMlib/diffraction_tools/__init__.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212

1313
from .kinematic import kinematic_scattering
1414
from .kinematic import calculate_kikuchi, calculate_holz
15-
from .kinematic import get_dynamical_allowed, calculate_laue_zones, center_of_laue_circle
16-
from .kinematic import find_sorted_bragg_reflections, get_incident_wave_vector
17-
from .kinematic import get_dynamically_allowed, ring_pattern_calculation, get_reflection_families
18-
from .kinematic import get_allowed_reflections
15+
from .kinematic import calculate_laue_zones, center_of_laue_circle
16+
from .kinematic import get_bragg_reflections, get_incident_wave_vector
17+
from .kinematic import get_dynamically_activated, ring_pattern_calculation, get_reflection_families
18+
from .kinematic import get_allowed_reflections, get_all_reflections
1919

2020
from .diffraction_plot import plot_diffraction_pattern, plot_ring_pattern, warp
2121
from .diffraction_plot import plot_saed_parameter, plot_cbed_parameter, plot_holz_parameter
@@ -28,9 +28,9 @@
2828
'get_metric_tensor', 'get_structure_factors', 'find_nearest_zone_axis',
2929
'find_angles', 'stage_rotation_matrix', 'get_zone_rotation', 'scattering_matrix',
3030
'gaussian', 'get_unit_cell', 'output_verbose', 'feq', 'form_factor',
31-
'kinematic_scattering', 'calculate_kikuchi', 'calculate_holz', 'get_dynamical_allowed',
32-
'calculate_laue_zones', 'center_of_laue_circle', 'find_sorted_bragg_reflections',
33-
'get_incident_wave_vector', 'get_dynamically_allowed', 'ring_pattern_calculation',
31+
'kinematic_scattering', 'calculate_kikuchi', 'calculate_holz', 'get_dynamically_activated',
32+
'calculate_laue_zones', 'center_of_laue_circle', 'get_bragg_reflections',
33+
'get_incident_wave_vector', 'ring_pattern_calculation', get_all_reflections,
3434
'get_reflection_families', 'get_allowed_reflections',
3535
'plot_diffraction_pattern', 'plot_ring_pattern', 'warp',
3636
'plot_saed_parameter', 'plot_cbed_parameter', 'plot_holz_parameter',

pyTEMlib/diffraction_tools/basic.py

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,20 @@
2828
import itertools
2929

3030
import numpy as np
31+
import scipy
3132
import matplotlib.pylab as plt # basic plotting
3233

3334
import ase
3435
import ase.build
3536

3637
import pyTEMlib
3738
from pyTEMlib.crystal_tools import electronFF
39+
from ..utilities import get_wavelength, get_rotation_matrix
40+
3841

3942
inputKeys = ['acceleration_voltage_V', 'zone_hkl', 'Sg_max', 'hkl_max']
4043
optional_input_keys = ['crystal', 'lattice_parameter_nm', 'convergence_angle_mrad',
41-
'mistilt', 'thickness', 'dynamic correction', 'dynamic correction K0']
44+
'mistilt', 'thickness', 'dynamic correction', 'dynamic correction K0']
4245

4346

4447
def read_poscar(filename):
@@ -141,7 +144,6 @@ def zuo_fig_3_18(verbose=True):
141144

142145
return atoms
143146

144-
get_rotation_matrix = pyTEMlib.utilities.get_rotation_matrix
145147

146148
def zone_mistilt(zone, angles):
147149
""" Rotation of zone axis by mistilt
@@ -173,28 +175,11 @@ def get_metric_tensor(matrix):
173175

174176
def vector_norm(g):
175177
""" Length of vector
176-
177178
depreciated - use np.linalg.norm
178179
"""
179180
return np.linalg.norm(g)
180181

181182

182-
def get_wavelength(acceleration_voltage) -> float:
183-
"""
184-
Calculates the relativistic corrected de Broglie wavelength of an electron in Angstrom
185-
186-
Parameter:
187-
---------
188-
acceleration_voltage: float or int
189-
acceleration voltage in volt
190-
Returns:
191-
-------
192-
wavelength: float
193-
wave length in Angstrom (= meter *10**10)
194-
"""
195-
return pyTEMlib.utilities.get_wavelength(acceleration_voltage) * 1e10
196-
197-
198183
def get_all_miller_indices(hkl_max):
199184
""" Get all Miller indices up to hkl_max"""
200185
h = np.linspace(-hkl_max, hkl_max, 2 * hkl_max + 1) # all evaluated single Miller Indices
@@ -220,6 +205,27 @@ def get_structure_factors(atoms, g_hkl):
220205
return np.array(structure_factors)
221206

222207

208+
def get_inner_potential(atoms):
209+
""" inner potential in Volts """
210+
u_0 = 0 # in (Ang)
211+
# atom form factor of zero reflection angle is the inner potential in 1/A
212+
for atom in atoms:
213+
u_0 += form_factor(atom.symbol, 0)
214+
scattering_factor_to_volts = ((scipy.constants.h*1e10)**2
215+
/ (2 * np.pi * scipy.constants.m_e * scipy.constants.e)
216+
/ atoms.cell.volume)
217+
return u_0 * scattering_factor_to_volts
218+
219+
def ewald_sphere_center(acceleration_voltage, atoms, zone_hkl):
220+
""" Ewald sphere center in 1/Angstrom """
221+
wavelength = get_wavelength(acceleration_voltage, unit='Å') # in Angstrom
222+
u_0 = get_inner_potential(atoms)
223+
incident_wave_vector = np.sqrt(1/wavelength**2 + u_0 )#1/Ang
224+
225+
center = np.dot(zone_hkl, atoms.cell.reciprocal())
226+
center = center / np.linalg.norm(center) * incident_wave_vector
227+
return center
228+
223229
def find_nearest_zone_axis(tags):
224230
"""Test all zone axis up to a maximum of hkl_max"""
225231

@@ -436,6 +442,7 @@ def gaussian(xx, pp):
436442
s1 = pp[2] / 2.3548
437443
prefactor = 1.0 / np.sqrt(2 * np.pi * s1 ** 2)
438444
y = (pp[1] * prefactor) * np.exp(-(xx - pp[0]) ** 2 / (2 * s1 ** 2))
445+
439446
return y
440447

441448

@@ -453,28 +460,28 @@ def get_unit_cell(atoms, tags):
453460
def output_verbose(atoms, tags):
454461
""" Verbose output of experimental parameters"""
455462
print('Experimental Parameters:')
456-
print(f"Acceleration Voltage: {tags['acceleration_voltage_V']*1000:.1f} kV")
457-
print(f"Convergence Angle: {tags['convergence_angle_mrad']:.2f} mrad",
458-
f" = {tags['convergence_angle_A-1']:.2f} 1/Ang")
459-
print(f"Wavelength: {tags['wave_length']*1000:.3f} pm")
460-
print(f"Incident Wave Vector: {tags['incident_wave_vector']*10} 1/nm in material ",
461-
f"; in vacumm: {1/tags['wave_length']:.4f} 1/nm")
463+
print(f"Acceleration Voltage: {tags.get('acceleration_voltage_V', 0)*1000:.1f} kV")
464+
print(f"Convergence Angle: {tags.get('convergence_angle_mrad', None):.2f} mrad",
465+
f" = {tags.get('convergence_angle_A-1', None):.2f} 1/Ang")
466+
print(f"Wavelength: {tags.get('wave_length', 0)*1000:.3f} pm")
467+
print(f"Incident Wave Vector: {tags.get('incident_wave_vector', 0)*10} 1/nm in material ",
468+
f"; in vacumm: {1/tags.get('wave_length', 0):.4f} 1/nm")
462469
print("\n Rotation to tilt zone axis onto z-axis:")
463-
print(f"Rotation alpha {np.rad2deg(tags['y-axis rotation alpha']):.1f} degree, "
464-
f" beta {np.rad2deg(tags['x-axis rotation beta']):.1f} degree")
465-
print(f"from zone axis {tags['zone_hkl']}")
466-
print(f"Tilting {1} by {np.rad2deg(tags['mistilt_alpha']):.2f} "
467-
f" in alpha and {np.rad2deg(tags['mistilt_beta']):.2f}" +
470+
print(f"Rotation alpha {np.rad2deg(tags.get('y-axis rotation alpha', None)):.1f} degree, "
471+
f" beta {np.rad2deg(tags.get('x-axis rotation beta', None)):.1f} degree")
472+
print(f"from zone axis {tags.get('zone_hkl', None)}")
473+
print(f"Tilting {1} by {np.rad2deg(tags.get('mistilt_alpha', None)):.2f} "
474+
f" in alpha and {np.rad2deg(tags.get('mistilt_beta', None)):.2f}" +
468475
" in beta direction results in :")
469-
nearest = tags['nearest_zone_axes']
476+
nearest = tags.get('nearest_zone_axes', {})
470477
print('Next nearest zone axes are:')
471-
for i in range(1, nearest['amount']):
478+
for i in range(1, nearest.get('amount', 0)):
472479
print(f"{nearest[str(i)]['hkl']}: mistilt:",
473480
f" {np.rad2deg(nearest[str(i)]['mistilt_alpha']):6.2f}, "
474481
f"{np.rad2deg(nearest[str(i)]['mistilt_beta']):6.2f}")
475-
print('Center of Ewald sphere ', tags['k0_vector'])
476-
dif = atoms.info['diffraction']
477-
print('Center or Laue circle', dif['Laue_circle'])
482+
print('Center of Ewald sphere ', tags.get('k0_vector', None))
483+
dif = atoms.info.get('diffraction', {})
484+
print('Center or Laue circle', dif.get('Laue_circle', None))
478485

479486

480487
def make_pretty_labels(hkls, hex_label=False):

pyTEMlib/diffraction_tools/diffraction_plot.py

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33
part of pyTEMlib's diffraction tools subpackage
44
author: Gerd Duscher, UTK
55
"""
6-
import matplotlib.pyplot as plt
76

8-
import scipy
97
import matplotlib
8+
import matplotlib.pyplot as plt
109
from matplotlib.collections import PatchCollection
1110
from matplotlib.lines import Line2D
1211
from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar
1312

1413
import ase
1514
import numpy as np
15+
import scipy
1616
import sidpy
1717
import skimage
1818

@@ -37,7 +37,7 @@ def scattering_profiles(diff_pattern, center):
3737
"""
3838
polar_projection = skimage.transform.warp_polar(diff_pattern, center=center).T
3939
polar_projection[polar_projection<0.] = 0.
40-
40+
4141
out_tags={'center': center,
4242
'polar_projection': polar_projection,
4343
'radial_average': polar_projection.sum(axis=1)}
@@ -359,22 +359,25 @@ def transform(coords):
359359
return polar, (rads, angs)
360360

361361
def set_center(main_dataset, center, scale=None):
362+
""" Set the u and v axes of a diffraction pattern dataset to center on origin"""
362363
if scale is None:
363364
axes= main_dataset.get_image_dims(return_axis=True)
364365
scale = (axes[0].slope, axes[1].slope)
365366
if isinstance(scale, float):
366367
scale = (scale, scale)
367-
368+
368369
x_axis = np.linspace(0, main_dataset.shape[0]-1, main_dataset.shape[0])-center[1]
369370
x_axis *= scale[0]
370371
y_axis = np.linspace(0, main_dataset.shape[1]-1, main_dataset.shape[1])-center[0]
371372
y_axis *= -scale[1]
372373
x = sidpy.Dimension(name='u', values=x_axis)
373-
374+
374375
main_dataset.set_dimension(0, sidpy.Dimension(name='u', values=x_axis, units='1/nm',
375-
dimension_type='spatial', quantity='reciprocal distance'))
376+
dimension_type='spatial',
377+
quantity='reciprocal distance'))
376378
main_dataset.set_dimension(1, sidpy.Dimension(name='v', values=y_axis, units='1/nm',
377-
dimension_type='spatial', quantity='reciprocal distance'))
379+
dimension_type='spatial',
380+
quantity='reciprocal distance'))
378381

379382

380383
def plot_ring_pattern(atoms, diffraction_pattern=None):
@@ -420,22 +423,19 @@ def plot_ring_pattern(atoms, diffraction_pattern=None):
420423
profile *= extent[1]*0.5 /profile.max()
421424
profile_x = np.linspace(1,len(profile),len(profile))*scale
422425
intensity *= extent[1]*0.25 /intensity.max()
423-
426+
424427
tags.setdefault('label_color', 'navy')
425428
tags.setdefault('profile color', 'navy')
426429
tags.setdefault('ring color', 'red')
427430
tags.setdefault('label_size', 10)
428431
tags.setdefault('profile height', 5)
429432
tags.setdefault('plot_scalebar', False)
430-
431-
fig = plt.figure()
432-
433433

434-
435-
####
434+
fig = plt.figure()
435+
# ###
436436
# show image in background
437-
####
438-
437+
# ###
438+
439439
if diffraction_pattern is not None:
440440
im = plt.imshow(np.log2(1+diffraction_pattern), extent=extent, cmap='gray')
441441
plt.colorbar(im)
@@ -463,12 +463,12 @@ def f(axis):
463463
if unique[j] < len(profile)*scale:
464464
# plot lines
465465
plt.plot([unique[j],unique[j]], [0, intensity[j]],c='r')
466-
arc = matplotlib.patches.Arc((0,0), unique[j]*2, unique[j]*2,
467-
angle=90.0,
468-
theta1=0.0, theta2=270.0,
466+
arc = matplotlib.patches.Arc((0,0), unique[j]*2, unique[j]*2,
467+
angle=90.0,
468+
theta1=0.0, theta2=270.0,
469469
color='r', fill= False, alpha = 0.5)
470470
ax.add_artist(arc)
471-
471+
472472
# ####
473473
# plot profile
474474
# ####
@@ -480,7 +480,6 @@ def f(axis):
480480
index = '{'+f'{family[i][0]:.0f} {family[i][1]:.0f} {family[i][2]:.0f}'+'}' # pretty index string
481481
ax.text(unique[i],-0.05, index, horizontalalignment='center',
482482
verticalalignment='top', rotation = 'vertical', fontsize=8, color = 'white')
483-
484483
return fig
485484

486485

0 commit comments

Comments
 (0)