pyTEMlib 0.2020.11.0__py3-none-any.whl → 0.2024.8.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyTEMlib might be problematic. Click here for more details.

Files changed (59) hide show
  1. pyTEMlib/__init__.py +11 -11
  2. pyTEMlib/animation.py +631 -0
  3. pyTEMlib/atom_tools.py +240 -222
  4. pyTEMlib/config_dir.py +57 -29
  5. pyTEMlib/core_loss_widget.py +658 -0
  6. pyTEMlib/crystal_tools.py +1255 -0
  7. pyTEMlib/diffraction_plot.py +756 -0
  8. pyTEMlib/dynamic_scattering.py +293 -0
  9. pyTEMlib/eds_tools.py +609 -0
  10. pyTEMlib/eels_dialog.py +749 -486
  11. pyTEMlib/{interactive_eels.py → eels_dialog_utilities.py} +1199 -1524
  12. pyTEMlib/eels_tools.py +2031 -1731
  13. pyTEMlib/file_tools.py +1276 -491
  14. pyTEMlib/file_tools_qt.py +193 -0
  15. pyTEMlib/graph_tools.py +1166 -450
  16. pyTEMlib/graph_viz.py +449 -0
  17. pyTEMlib/image_dialog.py +158 -0
  18. pyTEMlib/image_dlg.py +146 -0
  19. pyTEMlib/image_tools.py +1399 -956
  20. pyTEMlib/info_widget.py +933 -0
  21. pyTEMlib/interactive_image.py +1 -0
  22. pyTEMlib/kinematic_scattering.py +1196 -0
  23. pyTEMlib/low_loss_widget.py +176 -0
  24. pyTEMlib/microscope.py +61 -78
  25. pyTEMlib/peak_dialog.py +1047 -350
  26. pyTEMlib/peak_dlg.py +286 -248
  27. pyTEMlib/probe_tools.py +653 -202
  28. pyTEMlib/sidpy_tools.py +153 -129
  29. pyTEMlib/simulation_tools.py +104 -87
  30. pyTEMlib/version.py +6 -3
  31. pyTEMlib/xrpa_x_sections.py +20972 -0
  32. {pyTEMlib-0.2020.11.0.dist-info → pyTEMlib-0.2024.8.4.dist-info}/LICENSE +21 -21
  33. pyTEMlib-0.2024.8.4.dist-info/METADATA +93 -0
  34. pyTEMlib-0.2024.8.4.dist-info/RECORD +37 -0
  35. {pyTEMlib-0.2020.11.0.dist-info → pyTEMlib-0.2024.8.4.dist-info}/WHEEL +6 -5
  36. {pyTEMlib-0.2020.11.0.dist-info → pyTEMlib-0.2024.8.4.dist-info}/entry_points.txt +0 -1
  37. pyTEMlib/KinsCat.py +0 -2685
  38. pyTEMlib/__version__.py +0 -2
  39. pyTEMlib/data/TEMlibrc +0 -68
  40. pyTEMlib/data/edges_db.csv +0 -189
  41. pyTEMlib/data/edges_db.pkl +0 -0
  42. pyTEMlib/data/fparam.txt +0 -103
  43. pyTEMlib/data/microscopes.csv +0 -7
  44. pyTEMlib/data/microscopes.xml +0 -167
  45. pyTEMlib/data/path.txt +0 -1
  46. pyTEMlib/defaults_parser.py +0 -86
  47. pyTEMlib/dm3_reader.py +0 -609
  48. pyTEMlib/edges_db.py +0 -76
  49. pyTEMlib/eels_dlg.py +0 -240
  50. pyTEMlib/hdf_utils.py +0 -481
  51. pyTEMlib/image_tools1.py +0 -2194
  52. pyTEMlib/info_dialog.py +0 -227
  53. pyTEMlib/info_dlg.py +0 -205
  54. pyTEMlib/nion_reader.py +0 -293
  55. pyTEMlib/nsi_reader.py +0 -165
  56. pyTEMlib/structure_tools.py +0 -316
  57. pyTEMlib-0.2020.11.0.dist-info/METADATA +0 -20
  58. pyTEMlib-0.2020.11.0.dist-info/RECORD +0 -42
  59. {pyTEMlib-0.2020.11.0.dist-info → pyTEMlib-0.2024.8.4.dist-info}/top_level.txt +0 -0
pyTEMlib/KinsCat.py DELETED
@@ -1,2685 +0,0 @@
1
- """
2
- KinsCat
3
- Kinematic Scattering Theory
4
- Copyright by Gerd Duscher
5
-
6
- The University of Tennessee, Knoxville
7
- Department of Materials Science & Engineering
8
-
9
- Sources:
10
- Scattering Theory:
11
- Zuo and Spence, "Advanced TEM", 2017
12
-
13
- Spence and Zuo, Electron Microdiffraction, Plenum 1992
14
-
15
- Atomic Form Factor:
16
- Kirkland: Advanced Computing in Electron Microscopy 2nd edition
17
- Appendix C
18
-
19
- Units: everything is in SI units, except length is given in nm.
20
-
21
- Usage:
22
- All the input and output is done through a dictionary
23
- (See Zuo_fig_3_18 for full example input)
24
-
25
- Available Subroutines:
26
-
27
- Kinematic_Scattering(tags, verbose=False ) # Main Routine
28
-
29
- CsCl()
30
- Silicon()
31
- Zuo_fig_3_18()
32
-
33
- feq(element, q) # atomic form factor at reciprocal distance q
34
- get_rotation_matrix(zone, verbose = False):
35
- zone_mistilt (zone, angles):
36
- vector_norm(g) # Length of vector
37
- get_wavelength(E0) # Wavelength in 1/nm
38
-
39
- plotSAED(tags, grey=False)
40
- holzLZ(tags, grey=False)
41
- plotKikuchi(tags, grey=False)
42
- """
43
- # numerical packages used
44
- import numpy as np
45
- import scipy.constants as const
46
- import itertools
47
- from scipy import spatial
48
-
49
- import sidpy
50
- # plotting package used
51
- import matplotlib.pylab as plt # basic plotting
52
- import matplotlib as mpl
53
- from mpl_toolkits.mplot3d import Axes3D # 3D plotting
54
- from matplotlib.patches import Circle, Ellipse, Rectangle
55
- from matplotlib.collections import PatchCollection
56
-
57
- from ase.io import read, write
58
- import pyTEMlib.file_tools as ft
59
- import os
60
-
61
-
62
- _version_ = 0.5
63
-
64
- print('Using KinsCat library version ', _version_, ' by G.Duscher')
65
- _spglib_present = True
66
- try:
67
- import spglib
68
- except ModuleNotFoundError:
69
- _spglib_present = False
70
-
71
- if _spglib_present:
72
- print('Symmetry functions of spglib enabled')
73
- else:
74
- print('spglib not installed; Symmetry functions of spglib disabled')
75
-
76
-
77
- def read_poscar(): # open file dialog to select poscar file
78
- file_name = ft.openfile_dialog('POSCAR (POSCAR*.txt);;All files (*)')
79
- # use ase package to read file
80
-
81
- base = os.path.basename(file_name)
82
- base_name = os.path.splitext(base)[0]
83
- crystal = read(file_name, format='vasp', parallel=False)
84
-
85
- # make dictionary and plot structure (not essential for further notebook)
86
- tags = {'unit_cell': crystal.cell * 1e-1, 'elements': crystal.get_chemical_symbols(),
87
- 'base': crystal.get_scaled_positions(), 'max_bond_length': 0.23, 'name': base_name}
88
-
89
- return tags
90
-
91
- # Some Structure Determination Routines
92
-
93
-
94
- def example():
95
- return Zuo_fig_3_18()
96
-
97
-
98
- def Zuo_fig_3_18():
99
-
100
- # Create Silicon structure (Could be produced with Silicon routine)
101
- # INPUT
102
- print('Sample Input for Figure 3.18 in Zuo and Spence \"Advanced TEM\", 2017')
103
- tags = {'crystal_name': 'Silicon'}
104
- print('tags[\'crystal\'] = ', tags['crystal_name'])
105
- a = 0.514 # nm
106
- tags['lattice_parameter_nm'] = a
107
- print('tags[\'lattice_parameter_nm\'] =', tags['lattice_parameter_nm'])
108
- tags['unit_cell'] = [[a, 0, 0], [0, a, 0], [0, 0, a]]
109
- print('tags[\'unit_cell\'] =', tags['unit_cell'])
110
- tags['elements'] = list(itertools.repeat('Si', 8))
111
- print('tags[\'elements\'] =', tags['elements'])
112
- base = [(0., 0., 0.), (0.5, 0.0, 0.5), (0.5, 0.5, 0.), (0., 0.5, 0.5)]
113
- tags['base'] = np.array(base + (np.array(base) + (.25, .25, .25)).tolist())
114
- print('tags[\'base\'] =', tags['base'])
115
-
116
- # Define Experimental Conditions
117
- tags['convergence_angle_mrad'] = 7
118
-
119
- tags['acceleration_voltage_V'] = 101.6*1000.0 # V
120
- print('tags[\'acceleration_voltage_V\'] =', tags['acceleration_voltage_V'])
121
-
122
- tags['convergence_angle_mrad'] = 7.1 # mrad; 0 is parallel illumination
123
- print('tags[\'convergence_angle_mrad\'] =', tags['convergence_angle_mrad'])
124
-
125
- tags['zone_hkl'] = np.array([-2, 2, 1]) # incident neares zone axis: defines Laue Zones!!!!
126
- print('tags[\'zone_hkl\'] =', tags['zone_hkl'])
127
- tags['mistilt'] = np.array([0, 0, 0]) # mistilt in degrees
128
- print('tags[\'mistilt\'] =', tags['mistilt'])
129
-
130
- # Define Simulation Parameters
131
-
132
- tags['Sg_max'] = .2 # 1/nm maximum allowed excitation error
133
- print('tags[\'Sg_max\'] =', tags['Sg_max'])
134
-
135
- tags['hkl_max'] = 9 # Highest evaluated Miller indices
136
- print('tags[\'hkl_max\'] =', tags['hkl_max'])
137
-
138
- print('##################')
139
- print('# Output Options #')
140
- print('##################')
141
-
142
- # Output options
143
-
144
- tags['background'] = 'black' # 'white' 'grey'
145
- print('tags[\'background\'] =', tags['background'], '# \'white\', \'grey\' ')
146
- tags['color map'] = 'plasma'
147
- print('tags[\'color map\'] =', tags['color map'], '#,\'cubehelix\',\'Greys\',\'jet\' ')
148
-
149
- tags['plot HOLZ'] = 1
150
- print('tags[\'plot HOLZ\'] =', tags['plot HOLZ'])
151
- tags['plot HOLZ excess'] = 1
152
- print('tags[\'plot HOLZ excess\'] =', tags['plot HOLZ excess'])
153
- tags['plot Kikuchi'] = 1
154
- print('tags[\'plot Kikuchi\'] =', tags['plot Kikuchi'])
155
- tags['plot reflections'] = 1
156
- print('tags[\'plot reflections\'] =', tags['plot reflections'])
157
-
158
- tags['label HOLZ'] = 0
159
- print('tags[\'label HOLZ\'] =', tags['label HOLZ'])
160
- tags['label Kikuchi'] = 0
161
- print('tags[\'label Kikuchi\'] =', tags['label Kikuchi'])
162
- tags['label reflections'] = 0
163
- print('tags[\'label reflections\'] =', tags['label reflections'])
164
-
165
- tags['label color'] = 'black'
166
- print('tags[\'label color\'] =', tags['label color'])
167
- tags['label size'] = 10
168
- print('tags[\'label size\'] =', tags['label size'])
169
-
170
- tags['color Laue Zones'] = ['red', 'blue', 'green', 'blue', 'green'] # , 'green', 'red'] #for OLZ give a sequence
171
- print('tags[\'color Laue Zones\'] =', tags['color Laue Zones'], ' #[\'red\', \'blue\', \'lightblue\']')
172
-
173
- tags['color Kikuchi'] = 'green'
174
- print('tags[\'color Kikuchi\'] =', tags['color Kikuchi'])
175
- tags['linewidth HOLZ'] = -1 # -1: linewidth according to intensity (structure factor F^2
176
- print('tags[\'linewidth HOLZ\'] =', tags['linewidth HOLZ'], '# -1: linewidth according to intensity '
177
- '(structure factor F^2')
178
- tags['linewidth Kikuchi'] = -1 # -1: linewidth according to intensity (structure factor F^2
179
- print('tags[\'linewidth Kikuchi\'] =', tags['linewidth Kikuchi'], '# -1: linewidth according to intensity '
180
- '(structure factor F^2')
181
-
182
- tags['color reflections'] = 'intensity' # 'Laue Zone'
183
- print('tags[\'color reflections\'] =', tags['color reflections'], '#\'Laue Zone\' ')
184
- tags['color zero'] = 'white' # 'None', 'white', 'blue'
185
- print('tags[\'color zero\'] =', tags['color zero'], '#\'None\', \'white\', \'blue\' ')
186
- tags['color ring zero'] = 'None' # 'Red' #'white' #, 'None'
187
- print('tags[\'color ring zero\'] =', tags['color ring zero'], '#\'None\', \'white\', \'Red\' ')
188
-
189
- print('########################')
190
- print('# End of Example Input #')
191
- print('########################\n\n')
192
-
193
- return tags
194
-
195
-
196
- def h5_add_crystal_structure(h5_file, crystal_tags):
197
- """
198
- Adds the basic crystal information to a pyNSID style hdf5 file.
199
-
200
- example usage:
201
- >> crystal_tags = ks.structure_by_name(h5_file, 'Graphite')
202
- >> ks.add_crystal_structure(h5_file, crystal_tags)
203
- """
204
- structure_group = sidpy.hdf.prov_utils.create_indexed_group(h5_file, 'Structure')
205
-
206
- structure_group['unit_cell'] = crystal_tags['unit_cell']
207
- structure_group['relative_positions'] = crystal_tags['base']
208
- structure_group['title'] = str(crystal_tags['crystal_name'])
209
- structure_group['_'+crystal_tags['crystal_name']] = str(crystal_tags['crystal_name'])
210
- structure_group['elements'] = np.array(crystal_tags['elements'], dtype='S')
211
- if 'zone_axis' in structure_group:
212
- structure_group['zone_axis'] = np.array(crystal_tags['zone_axis'], dtype=float)
213
- else:
214
- structure_group['zone_axis'] = np.array([1., 1., 1.], dtype=float)
215
-
216
- h5_file.flush()
217
-
218
- return structure_group
219
-
220
-
221
- def h5_add_to_structure(structure_group, crystal_tags):
222
- for key in crystal_tags:
223
- if key in structure_group.keys():
224
- print(key, ' not written; use new name')
225
- else:
226
- structure_group[key] = crystal_tags[key]
227
-
228
-
229
- def cubic(a):
230
- """ Cubic lattice of dimensions a x a x a. """
231
- return np.identity(3)*a
232
-
233
-
234
- def from_parameters(a, b, c, alpha, beta, gamma):
235
- """ Create a Lattice using unit cell lengths and angles (in degrees)."""
236
-
237
- alpha_r = np.radians(alpha)
238
- beta_r = np.radians(beta)
239
- gamma_r = np.radians(gamma)
240
- val = (np.cos(alpha_r) * np.cos(beta_r) - np.cos(gamma_r)) / (np.sin(alpha_r) * np.sin(beta_r))
241
-
242
- # Sometimes rounding errors result in values slightly > 1.
243
- if val > 1.:
244
- val = 1.
245
- if val < -1.:
246
- val = -1.
247
-
248
- gamma_star = np.arccos(val)
249
- vector_a = [a * np.sin(beta_r), 0.0, a * np.cos(beta_r)]
250
- vector_b = [-b * np.sin(alpha_r) * np.cos(gamma_star),
251
- b * np.sin(alpha_r) * np.sin(gamma_star),
252
- b * np.cos(alpha_r)]
253
- vector_c = [0.0, 0.0, float(c)]
254
- return np.array([vector_a, vector_b, vector_c])
255
-
256
-
257
- def tetragonal(a, c):
258
- """Tetragonal lattice of dimensions a x a x c."""
259
- return from_parameters(a, a, c, 90, 90, 90)
260
-
261
-
262
- def bcc(lattice_parameter, elements):
263
- unit_cell = cubic(lattice_parameter)
264
- base = np.array([(0., 0., 0.), (0.5, 0.5, 0.5)])
265
- if len(elements) > 1:
266
- atoms = [elements[0], elements[1]]
267
- else:
268
- atoms = [elements[0], elements[0]]
269
- return unit_cell, base, atoms
270
-
271
-
272
- def fcc(lattice_parameter, elements):
273
- unit_cell = cubic(lattice_parameter)
274
- base = np.array([(0., 0., 0.), (0.5, 0.0, 0.5), (0.5, 0.5, 0.0), (0., 0.5, 0.5)])
275
- if len(elements) > 3:
276
- atoms = [elements[0], elements[1], elements[2], elements[3]]
277
- elif len(elements) > 1:
278
- atoms = [elements[0], elements[1], elements[1], elements[1]]
279
- else:
280
- atoms = [elements[0]]*4
281
- return unit_cell, base, atoms
282
-
283
-
284
- def dichalcogenide(a, c, u, elements):
285
- unit_cell = from_parameters(a, a, c, 90., 90., 120.)
286
- base = [(1/3., 2/3., 1/4.), (2/3., 1/3., 3/4.),
287
- (2/3., 1/3., 1/4.+u), (2/3., 1/3., 1/4.-u),
288
- (1/3., 2/3., 3/4.+u), (1/3., 2/3., 3/4.-u)]
289
-
290
- if len(elements) > 1:
291
- atoms = [elements[0]]*2 + [elements[1]]*4
292
- else:
293
- atoms = elements[0]*6
294
- return unit_cell, base, atoms
295
-
296
-
297
- def wurzite(a, c, u, elements):
298
- unit_cell = from_parameters(a, a, c, 90., 90., 120.)
299
- base = [(2./3., 1./3., .500), (1./3., 2./3., 0.000), (2./3., 1./3., 0.5+u), (1./3., 2./3., u)]
300
- if len(elements) > 1:
301
- atoms = [elements[0]]*2 + [elements[1]]*2
302
- else:
303
- atoms = [elements[0]]*4
304
- return unit_cell, base, atoms
305
-
306
-
307
- def rocksalt(lattice_parameter, elements):
308
- unit_cell = np.identity(3) * lattice_parameter
309
- base = [(0., 0., 0.), (0.5, 0.0, 0.5), (0.5, 0.5, 0.), (0., 0.5, 0.5)]
310
- base2 = np.array(base)+(0.5, 0.5, 0.5)
311
- base2 = np.where(base2 == 1., 0, base2)
312
- base = base + base2.tolist()
313
- if len(elements) > 1:
314
- atoms = [elements[0]]*4 + [elements[1]]*4
315
- else:
316
- atoms = [elements[0]]*8
317
- return unit_cell, base, atoms
318
-
319
-
320
- def zinc_blende(lattice_parameter, elements):
321
- unit_cell = np.identity(3) * lattice_parameter
322
- base = [(0., 0., 0.), (0.5, 0.0, 0.5), (0.5, 0.5, 0.), (0., 0.5, 0.5)]
323
- base = base + (np.array(base) + (.25, .25, .25)).tolist()
324
- if len(elements) > 3:
325
- atoms = [elements[0], elements[0], elements[1], elements[1], elements[2], elements[2], elements[3], elements[3]]
326
- # Z = [electronFF[elements[0]][Z],
327
- elif len(elements) > 1:
328
- atoms = [elements[0]]*4 + [elements[1]]*4
329
- else:
330
- atoms = [elements[0]]*8
331
- return unit_cell, base, atoms
332
-
333
-
334
- def perovskite(lattice_parameter, elements):
335
- unit_cell = cubic(lattice_parameter)
336
- base = np.array([(0., 0., 0.), (0.5, 0.5, 0.5), (0.5, 0.0, 0.5), (0.5, 0.5, 0.), (0., 0.5, 0.5)])
337
- if len(elements) > 2:
338
- atoms = [elements[0], elements[1]] + [elements[2]]*3
339
- elif len(elements) > 1:
340
- atoms = [elements[0]] + [elements[1]]*4
341
- else:
342
- atoms = [elements[0]]*5
343
- return unit_cell, base, atoms
344
-
345
-
346
- def zone_mistilt(zone, angles):
347
- alpha, beta, gamma = np.radians(angles)
348
-
349
- # first we rotate alpha about x axis
350
- c, s = np.cos(alpha), np.sin(alpha)
351
- rotx = np.array([[1, 0, 0], [0, c, -s], [0, s, c]])
352
-
353
- # second we rotate beta about y axis
354
- c, s = np.cos(beta), np.sin(beta)
355
- roty = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]])
356
-
357
- # third we rotate gamma about z-axis
358
- c, s = np.cos(gamma), np.sin(gamma)
359
- rotz = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
360
-
361
- return np.dot(np.dot(np.dot(zone, rotx), roty), rotz)
362
-
363
-
364
- def structure_by_name(crystal):
365
- """
366
- Provides unit cell as a structure matrix, the list of elements and the atom base
367
-
368
- Input:
369
- ------
370
- crystal name as string:
371
- type "print(ks.crystal_data_base.keys())" for a list of pre-defined crystal structures
372
-
373
- Please note that the chemical expressions are case sensitive.
374
-
375
- Output:
376
- ------
377
- new dictionary with the following keys:
378
-
379
- ['unit_cell']: the structure matrix
380
- ['base']: relative coordinates of atoms
381
- ['elements']: name of elements in same order as base
382
-
383
- an empty dictionary will be returned if the name is not recognized.
384
- """
385
-
386
- # Check whether name is in the crystal_data_base
387
-
388
- if crystal in cdb:
389
- tags = cdb[crystal].copy()
390
- else:
391
- print('Crystal name not defined')
392
- return {}
393
- print(tags['elements'])
394
- # Make crystal structure dictionary based on symmetry
395
- if 'symmetry' in tags:
396
- if tags['symmetry'] == 'BCC':
397
- unit_cell, base, atoms = bcc(tags['a'], tags['elements'])
398
-
399
- elif tags['symmetry'] == 'FCC':
400
- unit_cell, base, atoms = fcc(tags['a'], tags['elements'])
401
-
402
- elif tags['symmetry'] == 'perovskite':
403
- unit_cell, base, atoms = perovskite(tags['a'], tags['elements'])
404
-
405
- elif tags['symmetry'] == 'zinc_blende':
406
- unit_cell, base, atoms = zinc_blende(tags['a'], tags['elements'])
407
-
408
- elif tags['symmetry'] == 'wurzite':
409
- unit_cell, base, atoms = wurzite(tags['a'], tags['c'], tags['u'], tags['elements'])
410
-
411
- elif tags['symmetry'] == 'rocksalt':
412
- unit_cell, base, atoms = rocksalt(tags['a'], tags['elements'])
413
-
414
- elif tags['symmetry'] == 'dichalcogenide':
415
- unit_cell, base, atoms = dichalcogenide(tags['a'], tags['c'], tags['u'], tags['elements'])
416
-
417
- tags['unit_cell'] = unit_cell
418
- tags['elements'] = atoms
419
- tags['base'] = base
420
-
421
- return tags
422
-
423
-
424
- def get_symmetry(unit_cell, base, atoms):
425
- if _spglib_present:
426
-
427
- print('#####################')
428
- print('# Symmetry Analysis #')
429
- print('#####################')
430
-
431
- atomic_number = []
432
- for i in range(len(atoms)):
433
- a = atoms[i]
434
- b = base[i]
435
- atomic_number.append(electronFF[a]['Z'])
436
- print(f'{i+1}: {atomic_number[i]} = {2} : [{base[i][0]:.2f}, {base[i][1]:.2f}, {base[i][2]:.2f}]')
437
-
438
- lattice = (unit_cell, base, atomic_number)
439
- spgroup = spglib.get_spacegroup(lattice)
440
- sym = spglib.get_symmetry(lattice)
441
-
442
- print(" Spacegroup is %s." % spgroup)
443
- print(' Crystal has {0} symmetry operation'.format(sym['rotations'].shape[0]))
444
-
445
- p_lattice, p_positions, p_numbers = spglib.find_primitive(lattice, symprec=1e-5)
446
- print("\n########################\n #Basis vectors of primitive Cell:")
447
- for i in range(3):
448
- print('[{0:.4f}, {1:.4f}, {2:.4f}]'.format(p_lattice[i][0], p_lattice[i][1], p_lattice[i][2]))
449
-
450
- print('There {0} atoms and {1} species in primitive unit cell:'.format(len(p_positions), p_numbers))
451
- else:
452
- print('spglib is not installed')
453
-
454
-
455
- def ball_and_stick(tags, extend=1, max_bond_length=0.):
456
-
457
- """
458
- calculates the data to plot a ball and stick model
459
-
460
- Input:
461
- ------
462
- tags: dictionary containing the 'unit_cell', 'base' and 'elements' tags.
463
-
464
- extend: 1 or 3 integers
465
- The *extend* argument scales the effective cell in which atoms
466
- will be included. It must either be a list of three integers or a single
467
- integer scaling all 3 directions. By setting this value to one,
468
- all corner and edge atoms will be included in the returned cell.
469
- This will of cause make the returned cell non-repeatable, but this is
470
- very useful for visualisation.
471
-
472
- max_bond_length: 1 float
473
- The max_bond_length argument defines the distance for which a bond will be shown.
474
- If max_bond_length is zero, the tabulated atom radii will be used.
475
-
476
-
477
- Output:
478
- -------
479
- corners,balls, Z, bonds: lists
480
- These lists can be used to plot the
481
- unit cell:
482
- for x, y, z in corners:
483
- l=mlab.plot3d( x,y,z, tube_radius=0.002)
484
- bonds:
485
- for x, y, z in bonds:
486
- mlab.plot3d( x,y,z, tube_radius=0.02)
487
- and atoms:
488
- for i,atom in enumerate(balls):
489
- mlab.points3d(atom[0],atom[1],atom[2],
490
- scale_factor=0.1,##ks.vdw_radii[Z[i]]/5,
491
- resolution=20,
492
- color=tuple(ks.jmol_colors [Z[i]]),
493
- scale_mode='none')
494
-
495
- Please note that you'll need the *Z* list for coloring, or for radii that depend on elements
496
-
497
- """
498
- # Check in which form extend is given
499
- if isinstance(extend, int):
500
- extend = [extend]*3
501
-
502
- extend = np.array(extend, dtype=int)
503
-
504
- # Make the x,y, and z multiplicators
505
- if len(extend) == 3:
506
- x = np.linspace(0, extend[0], extend[0]+1)
507
- y = np.linspace(0, extend[1], extend[1]+1)
508
- z = np.linspace(0, extend[2], extend[2]+1)
509
- else:
510
- print('wrong extend parameter')
511
- return
512
-
513
- # Check whether this is the right kind of dictionary
514
- if 'unit_cell' not in tags:
515
- return
516
- cell = tags['unit_cell']
517
-
518
- # Corners and Outline of unit cell
519
- h = (0, 1)
520
- corner_vectors = np.dot(np.array(list(itertools.product(h, h, h))), cell)
521
- trace = [[0, 1], [1, 3], [3, 2], [2, 0], [0, 4], [4, 5], [5, 7], [6, 7], [6, 4], [1, 5], [2, 6], [3, 7]]
522
- corners = []
523
- for s, e in trace:
524
- corners.append([*zip(corner_vectors[s], corner_vectors[e])])
525
-
526
- # ball position and elements in supercell
527
- super_cell = np.array(list(itertools.product(x, y, z))) # all evaluated Miller indices
528
-
529
- pos = np.add(super_cell, np.array(tags['base'])[:, np.newaxis])
530
-
531
- atomic_number = []
532
- for i in range(len(tags['elements'])):
533
- atomic_number.append(electronFF[tags['elements'][i]]['Z'])
534
-
535
- # List of bond lengths taken from electronFF database below
536
- bond_lengths = []
537
- for atom in tags['elements']:
538
- bond_lengths.append(electronFF[atom]['bond_length'][0])
539
-
540
- # extend list of atomic numbers
541
- zpp = []
542
- for z in atomic_number:
543
- zpp.append([z]*pos.shape[1])
544
- zpp = np.array(zpp).flatten()
545
-
546
- # reshape supercell atom positions
547
- pos = pos.reshape((pos.shape[0]*pos.shape[1], pos.shape[2]))
548
-
549
- # Make a mask that excludes all atoms outside of super cell
550
- maskz = pos[:, 2] <= extend[2]
551
- masky = pos[:, 1] <= extend[1]
552
- maskx = pos[:, 0] <= extend[0]
553
- mask = np.logical_and(maskx, np.logical_and(masky, maskz)) # , axis=1)
554
-
555
- # Only use balls and elements inside super cell
556
- balls = np.dot(pos[mask], cell)
557
- atomic_number = zpp[mask]
558
-
559
- # Get maximum bond length from list of bond -lengths taken from electronFF database
560
- if max_bond_length == 0:
561
- max_bond_length = np.median(bond_lengths)/5
562
- # Check nearest neighbours within max_bond_length
563
- tree = spatial.KDTree(balls)
564
- nearest_neighbours = np.array(tree.query(balls, k=8, distance_upper_bound=max_bond_length))
565
-
566
- # Calculate bonds
567
- bonds = []
568
- bond_indices = []
569
- for i in range(nearest_neighbours.shape[1]):
570
- for j in range(nearest_neighbours.shape[2]):
571
- if nearest_neighbours[0, i, j] < max_bond_length:
572
- if nearest_neighbours[0, i, j] > 0:
573
- # print(atoms[i],atoms[int(bonds[1,i,j])],bonds[:,i,j])
574
- bonds.append([*zip(balls[i], balls[int(nearest_neighbours[1, i, j])])])
575
- bond_indices.append([i, int(nearest_neighbours[1, i, j])])
576
-
577
- return corners, balls, atomic_number, bonds
578
-
579
-
580
- def plot_unitcell_mayavi(tags):
581
- """
582
- Makes a 3D plot of crystal structure
583
-
584
- Input:
585
- ------
586
- Dictionary with tags: 'unit_cell, 'elements', 'base'
587
-
588
- Output:
589
- -------
590
- 3D plot
591
-
592
- Dependencies:
593
- -------------
594
- ball_and_stick function of KinsCat
595
- mlab of mayavi
596
- """
597
- from mayavi import mlab
598
-
599
- # Make sure "max_bond_length" and "extend" variables are initialized
600
- if 'max_bond_length' not in tags:
601
- max_bond_length = 0.
602
- else:
603
- max_bond_length = tags['max_bond_length']
604
-
605
- if 'extend' not in tags:
606
- extend = 1
607
- else:
608
- extend = tags['extend']
609
-
610
- # get balls, sticks and atomic numbers for colors and sizes
611
- corners, balls, atomic_number, bonds = ball_and_stick(tags, extend=extend, max_bond_length=max_bond_length)
612
-
613
- print('Now plotting')
614
- fig = mlab.figure(1, bgcolor=(0, 0, 0), size=(350, 350))
615
-
616
- mlab.clf() # clear figure
617
-
618
- # parallel projection
619
- mlab.gcf().scene.parallel_projection = True
620
- mlab.gcf().scene.camera.parallel_scale = 5
621
-
622
- # plot unit cell
623
- for x, y, z in corners:
624
- ll = mlab.plot3d(x, y, z, tube_radius=0.002)
625
-
626
- # plot bonds as sticks
627
- for x, y, z in bonds:
628
- mlab.plot3d(x, y, z, tube_radius=0.02)
629
-
630
- # plot atoms
631
- for i, atom in enumerate(balls):
632
- mlab.points3d(atom[0], atom[1], atom[2],
633
- scale_factor=0.1, # ks.vdw_radii[Z[i]]/50,
634
- resolution=20,
635
- color=tuple(jmol_colors[atomic_number[i]]),
636
- scale_mode='none')
637
-
638
- # parallel projection
639
- mlab.gcf().scene.parallel_projection = True
640
- mlab.gcf().scene.camera.parallel_scale = 5
641
- # show plot
642
- mlab.show()
643
-
644
-
645
- def plot_unitcell(tags):
646
-
647
- if 'max_bond_length' not in tags:
648
- max_bond_length = 0.
649
- else:
650
- max_bond_length = tags['max_bond_length']
651
-
652
- if 'extend' not in tags:
653
- extend = 1
654
- else:
655
- extend = tags['extend']
656
-
657
- corners, balls, atomic_number, bonds = ball_and_stick(tags, extend=extend, max_bond_length=max_bond_length)
658
-
659
- maximum_position = balls.max()*1.05
660
- maximum_x = balls[:, 0].max()
661
- maximum_y = balls[:, 1].max()
662
- maximum_z = balls[:, 2].max()
663
-
664
- balls = balls - [maximum_x/2, maximum_y/2, maximum_z/2]
665
-
666
- fig = plt.figure()
667
- ax = fig.add_subplot(111, projection='3d')
668
- # draw unit_cell
669
- for x, y, z in corners:
670
- ax.plot3D(x-maximum_x/2, y-maximum_y/2, z-maximum_z/2, color="blue")
671
-
672
- # draw bonds
673
- for x, y, z in bonds:
674
- ax.plot3D(x-maximum_x/2, y-maximum_y/2, z-maximum_z/2, color="black", linewidth=4) # , tube_radius=0.02)
675
-
676
- # draw atoms
677
- for i, atom in enumerate(balls):
678
- ax.scatter(atom[0], atom[1], atom[2],
679
- color=tuple(jmol_colors[atomic_number[i]]),
680
- alpha=1.0, s=50)
681
- maximum_position = balls.max()*1.05
682
- ax.set_proj_type('ortho')
683
-
684
- ax.set_zlim(-maximum_position/2, maximum_position/2)
685
- ax.set_ylim(-maximum_position/2, maximum_position/2)
686
- ax.set_xlim(-maximum_position/2, maximum_position/2)
687
-
688
- if 'name' in tags:
689
- ax.set_title(tags['name'])
690
-
691
- ax.set_xlabel('x [nm]')
692
- ax.set_ylabel('y [nm]')
693
- ax.set_zlabel('z [nm]')
694
-
695
-
696
- # The metric tensor of the lattice.
697
- def metric_tensor(matrix):
698
- # Use like: metric_tensor(unit_cell)
699
- metric_tensor2 = np.dot(matrix, matrix.T)
700
- return metric_tensor2
701
-
702
-
703
- # Length of vector
704
- def vector_norm(g):
705
- return np.sqrt(g[:, 0]**2+g[:, 1]**2+g[:, 2]**2)
706
-
707
-
708
- def make_pretty_labels(hkls, hex_label=False):
709
- """
710
- ###########################
711
- # Make pretty labels
712
- ###########################
713
- Input:
714
- ------
715
- hkls: a numpy array with all the Miller indices to be labeled
716
- Optional:
717
- ---------
718
- hex_label: if True this will make for Miller indices.
719
-
720
- Output:
721
- ------
722
- list of labels in Latex format
723
- """
724
- hkl_label = []
725
- for i in range(len(hkls)):
726
- h, k, l = np.array(hkls)[i]
727
-
728
- if h < 0:
729
- h_string = r'[$\bar {'+str(int(-h))+'},'
730
- else:
731
- h_string = r'[$\bar {'+str(int(h))+'},'
732
- if k < 0:
733
- k_string = r'\bar {'+str(int(-k))+'},'
734
- else:
735
- k_string = str(int(k))+','
736
- if hex_label:
737
- ii = -(h+k)
738
- if ii < 0:
739
- k_string = k_string + r'\bar {'+str(int(-ii))+'},'
740
- else:
741
- k_string = k_string + str(int(ii))+','
742
- if l < 0:
743
- l_string = r'\bar {'+str(int(-l))+'} $]'
744
- else:
745
- l_string = str(int(l))+'} $]'
746
- label = h_string+k_string+l_string
747
- hkl_label.append(label)
748
- return hkl_label
749
-
750
-
751
- # Wavelength in 1/nm
752
- def get_wavelength(e0):
753
- """
754
- Calculates the relativistic corrected de Broglie wave length of an electron
755
-
756
- Input:
757
- ------
758
- acceleration voltage in volt
759
- Output:
760
- -------
761
- wave length in nm
762
- """
763
-
764
- eV = const.e * e0
765
- return const.h/np.sqrt(2*const.m_e*eV*(1+eV/(2*const.m_e*const.c**2)))*10**9
766
-
767
-
768
- # Rotation of zone axis by mistilt
769
- def zone_mistilt(zone, angles):
770
- alpha, beta, gamma = np.radians(angles)
771
-
772
- # first we rotate alpha about x axis
773
- c, s = np.cos(alpha), np.sin(alpha)
774
- rotx = np.array([[1, 0, 0], [0, c, -s], [0, s, c]])
775
-
776
- # second we rotate beta about y axis
777
- c, s = np.cos(beta), np.sin(beta)
778
- roty = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]])
779
-
780
- # third we rotate gamma about z-axis
781
- c, s = np.cos(gamma), np.sin(gamma)
782
- rotz = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
783
-
784
- return np.dot(np.dot(np.dot(zone, rotx), roty), rotz)
785
-
786
-
787
- # Determine rotation matrix to tilt zone axis onto z-axis
788
- # We determine spherical coordinates to do that
789
- def get_rotation_matrix(zone, verbose=False):
790
- """
791
- Calculates the rotation matrix to rotate the zone axis parallel to the cartasian z-axis.
792
-
793
- We use spherical coordinates to first rotate around the z-axis and then around the y-axis.
794
- This makes it easier to apply additional tilts, than to use the cross product to determine a single rotation
795
- axis (Rodrigues Formula)
796
-
797
- INPUT:
798
- - zone axis has to be in cartesian coordinates also.
799
- The dot product of zone axis and unit cell will accomplish that.
800
-
801
- Output:
802
- - rotation_matrix
803
- - theta (degrees)
804
- - phi (degrees)
805
- """
806
- # spherical coordinates of zone
807
- r = np.sqrt((zone*zone).sum())
808
- theta = np.arccos(zone[2]/r)
809
- if zone[0] < 0:
810
- theta = -theta
811
- if zone[0] == 0:
812
- phi = np.pi/2
813
- else:
814
- phi = (np.arctan(zone[1]/zone[0]))
815
-
816
- if verbose:
817
- print('Rotation theta ', np.degrees(theta), ' phi ', np.degrees(phi))
818
- # unit = np.array([[1, 0, 0],[0,1, 0],[0, 0,1]])
819
-
820
- # first we rotate phi about z-axis
821
- c, s = np.cos(phi), np.sin(phi)
822
- rotz = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
823
-
824
- # second we rotate theta about y axis
825
- c, s = np.cos(theta), np.sin(theta)
826
- roty = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]])
827
-
828
- # the rotation now makes zone-axis coincide with plane normal
829
- return np.dot(rotz, roty), np.degrees(theta), np.degrees(phi)
830
-
831
-
832
- def check_sanity(tags):
833
- ############################################
834
- # Check sanity
835
- ############################################
836
- stop = False
837
- if 'unit_cell' not in tags:
838
- print(' No unit_cell defined')
839
- stop = True
840
- if 'base' not in tags:
841
- print(' No base defined')
842
- stop = True
843
- if 'elements' not in tags:
844
- print(' No atoms defined')
845
- stop = True
846
- if 'acceleration_voltage_V' not in tags:
847
- print(' No acceleration_voltage_V defined')
848
- stop = True
849
- if 'zone_hkl' not in tags:
850
- print(' No zone_hkl defined')
851
- stop = True
852
- if 'Sg_max' not in tags:
853
- print(' No Sg_max defined')
854
- stop = True
855
- if 'hkl_max' not in tags:
856
- print(' No hkl_max defined')
857
- stop = True
858
-
859
- if 'crystal_name' not in tags:
860
- tags['crystal_name'] = 'undefined'
861
- print('tags[\'crystal\'] = \'undefined\'')
862
- if 'mistilt' not in tags:
863
- tags['mistilt'] = [0., 0., 0.]
864
- print('tags[\'mistilt\'] = [0., 0., 0.]')
865
- if 'convergence_angle_mrad' not in tags:
866
- tags['convergence_angle_mrad'] = 0.
867
- print('tags[\'convergence_angle_mrad\'] = 0')
868
-
869
- return stop
870
-
871
-
872
- def ring_pattern_calculation(tags, verbose=False):
873
- # Reciprocal Lattice
874
- # We use the linear algebra package of numpy to invert the unit_cell "matrix"
875
- reciprocal_unit_cell = np.linalg.inv(tags['unit_cell']).T # transposed of inverted unit_cell
876
-
877
- # INPUT
878
- hkl_max = 7 # maximum allowed Miller index
879
-
880
- acceleration_voltage = 200.0*1000.0 # V
881
- wave_length = get_wavelength(acceleration_voltage)
882
-
883
- h = np.linspace(-hkl_max, hkl_max, 2*hkl_max+1) # all to be evaluated single Miller Index
884
- hkl = np.array(list(itertools.product(h, h, h))) # all to be evaluated Miller indices
885
- g_hkl = np.dot(hkl, reciprocal_unit_cell)
886
-
887
- # Calculate Structure Factors
888
-
889
- structure_factors = []
890
-
891
- base = np.dot(tags['base'], tags['unit_cell']) # transformation from relative to Cartesian coordinates
892
- for j in range(len(g_hkl)):
893
- F = 0
894
- for b in range(len(base)):
895
- # Atomic formfactor for element and momentum change (g vector)
896
- f = feq(tags['elements'][b], np.linalg.norm(g_hkl[j]))
897
- F += f * np.exp(-2*np.pi*1j*(g_hkl[j]*base[b]).sum())
898
- structure_factors.append(F)
899
- F = structure_factors = np.array(structure_factors)
900
-
901
- # Allowed reflections have a non zero structure factor F (with a bit of numerical error)
902
- allowed = np.absolute(structure_factors) > 0.001
903
-
904
- distances = np.linalg.norm(g_hkl, axis=1)
905
-
906
- if verbose:
907
- print(f' Of the evaluated {hkl.shape[0]} Miller indices {allowed.sum()} are allowed. ')
908
- # We select now all the
909
- zero = distances == 0.
910
- allowed = np.logical_and(allowed, np.logical_not(zero))
911
-
912
- F = F[allowed]
913
- g_hkl = g_hkl[allowed]
914
- hkl = hkl[allowed]
915
- distances = distances[allowed]
916
-
917
- sorted_allowed = np.argsort(distances)
918
-
919
- distances = distances[sorted_allowed]
920
- hkl = hkl[sorted_allowed]
921
- F = F[sorted_allowed]
922
-
923
- # How many have unique distances and what is their multiplicity
924
-
925
- unique, indices = np.unique(distances, return_index=True)
926
-
927
- if verbose:
928
- print(f' Of the {allowed.sum()} allowed Bragg reflections there are {len(unique)} families of reflections.')
929
-
930
- intensity = np.absolute(F[indices]**2*(np.roll(indices, -1)-indices))
931
- if verbose:
932
- print('\n index \t hkl \t 1/d [1/nm] d [pm] F multip. intensity')
933
- family = []
934
- out_tags = {}
935
- for j in range(len(unique)-1):
936
- i = indices[j]
937
- i2 = indices[j+1]
938
- family.append(hkl[i+np.argmax(hkl[i:i2].sum(axis=1))])
939
- index = '{'+f'{family[j][0]:.0f} {family[j][1]:.0f} {family[j][2]:.0f}'+'}'
940
- if verbose:
941
- print(f'{i:3g}\t {index} \t {distances[i]:.2f} \t {1/distances[i]*1000:.0f} \t {np.absolute(F[i]):.2f},'
942
- f' \t {indices[j+1]-indices[j]:3g} \t {intensity[j]:.2f}')
943
- out_tags[index] = {}
944
- out_tags[index]['reciprocal_distance'] = distances[i]
945
- out_tags[index]['real_distance'] = 1/distances[i]
946
- out_tags[index]['F'] = np.absolute(F[i])
947
- out_tags[index]['multiplicity'] = indices[j+1]-indices[j]
948
- out_tags[index]['intensity'] = intensity[j]
949
- return out_tags
950
-
951
-
952
- # All the kinematic scattering
953
- # Calculates SAED, Kikuchi, and HOLZ pattern
954
- def kinematic_scattering(tags, verbose=False):
955
- """
956
- All kinematic scattering calculation
957
- Calculates Bragg spots, Kikuchi lines, excess, and deficient HOLZ lines
958
-
959
- Input:
960
- ------
961
- a dictionary with crystal structure:
962
- 'unit_cell', 'base' 'elements'
963
- and with experimental parameters:
964
- 'acceleration_voltage_V', 'zone_hkl', 'Sg_max', 'hkl_max'
965
- Optional parameters are:
966
- 'mistilt', convergence_angle_mrad', and 'crystal_name'
967
-
968
- vebose = True will give extended output of the calculation
969
-
970
- Output to dictionary:
971
- ---------------------
972
-
973
- There are three sub_dictionaries: ['allowed'], ['forbidden'], and ['HOLZ']
974
- ['allowed'] and ['forbidden'] dictionaries contain:
975
- ['Sg'], ['hkl'], ['g'], ['structure factor'], ['intensities'],
976
- ['ZOLZ'], ['FOLZ'], ['SOLZ'], ['HOLZ'], ['HHOLZ'], ['label'], and ['Laue_zone']
977
- the ['HOLZ'] dictionary contains:
978
- ['slope'], ['distance'], ['theta'], ['g deficient'], ['g excess'], ['hkl'], ['intensities'],
979
- ['ZOLZ'], ['FOLZ'], ['SOLZ'], ['HOLZ'], and ['HHOLZ']
980
- Please note that the Kikuchi lines are the HOLZ lines of ZOLZ
981
-
982
- There are also a few parameters stored in the main dictionary:
983
- ['wave_length_nm'], ['reciprocal_unit_cell'], ['inner_potential_V'], ['incident_wave_vector'],
984
- ['volume'], ['theta'], ['phi'], and ['incident_wave_vector_vacuum']
985
- """
986
-
987
- if check_sanity(tags):
988
- print('Input is not complete, stopping')
989
- print('Try \'example()\' for example input')
990
- return
991
-
992
- tags['wave_length_nm'] = get_wavelength(tags['acceleration_voltage_V'])
993
-
994
- ############################################
995
- # reciprocal_unit_cell
996
- ############################################
997
- unit_cell = np.array(tags['unit_cell'])
998
- # We use the linear algebra package of numpy to invert the unit_cell "matrix"
999
- reciprocal_unit_cell = np.linalg.inv(unit_cell).T # transposed of inverted unit_cell
1000
- tags['reciprocal_unit_cell'] = reciprocal_unit_cell
1001
-
1002
- if verbose:
1003
- print('reciprocal_unit_cell')
1004
- print(np.round(reciprocal_unit_cell, 3))
1005
-
1006
- ############################################
1007
- # Incident wave vector K0 in vacuum and material
1008
- ############################################
1009
-
1010
- # Incident wave vector K0 in vacuum and material
1011
- U0 = 0
1012
- for i in range(len(tags['elements'])):
1013
- a = tags['elements'][i]
1014
- U0 += feq(a, 0)*0.023933754
1015
-
1016
- tags['volume'] = np.linalg.det(tags['unit_cell'])
1017
- volume = tags['volume']*1000, # Needs to be in Angstrom for form factors
1018
- AngstromConversion = 1.0e10 # So [1A (in m)] * AngstromConversion = 1
1019
- NanometerConversion = 1.0e9
1020
-
1021
- ScattFacToVolts = (const.h**2)*(AngstromConversion**2)/(2*np.pi*const.m_e*const.e)*volume
1022
- U0 = U0*ScattFacToVolts
1023
- tags['inner_potential_A'] = U0
1024
- tags['inner_potential_V'] = U0*ScattFacToVolts
1025
- if verbose:
1026
- print('The inner potential is {0:.3f}kV'.format(tags['inner_potential_V']/1000))
1027
-
1028
- # Calculating incident wave vector magnitude 'K0' in material
1029
- wl = tags['wave_length_nm']
1030
- tags['incident_wave_vector_vacuum'] = 1/wl
1031
-
1032
- K0 = tags['incident_wave_vector'] = np.sqrt(1/wl**2 - (U0/volume*100.)) # 1/nm
1033
-
1034
- tags['convergence_angle_nm-1'] = K0*np.sin(tags['convergence_angle_mrad']/1000.)
1035
-
1036
- if verbose:
1037
- print('Magnitude of incident wave vector in material {0:.1f} 1/nm and vacuum {1:.1f} 1/nm'.format(K0, 1/wl))
1038
- print('The convergence angle of {0}mrad = {1:.2f} 1/nm'.format(tags['convergence_angle_mrad'],
1039
- tags['convergence_angle_nm-1']))
1040
-
1041
- #############
1042
- # Rotate
1043
- #############
1044
-
1045
- # first we take care of mistilt: zone axis is then in fractional Miller indices
1046
- zone = tags['zone'] = zone_mistilt(tags['zone_hkl'], tags['mistilt'])
1047
-
1048
- # zone axis in global coordinate system
1049
- zone_vector = np.dot(zone, reciprocal_unit_cell)
1050
-
1051
- rotation_matrix, theta, phi = get_rotation_matrix(zone_vector, verbose=False)
1052
-
1053
- if verbose:
1054
- print('Rotation angles are {0:.1f} deg and {1:.1f} deg'.format(theta, phi))
1055
- tags['theta'] = theta
1056
- tags['phi'] = phi
1057
-
1058
- # rotate incident wave vector
1059
- w_vector = np.dot(zone_vector, rotation_matrix)
1060
- K0_unit_vector = w_vector / np.linalg.norm(w_vector) # incident unit wave vector
1061
- K0_vector = K0_unit_vector*K0 # incident wave vector
1062
-
1063
- if verbose:
1064
- print('Center of Ewald sphere ', K0_vector)
1065
-
1066
- ########################
1067
- # Find all Miller indices whose reciprocal point lays near the Ewald sphere with radius K0
1068
- # within a maximum excitation error Sg
1069
- ########################
1070
-
1071
- hkl_max = tags['hkl_max']
1072
- Sg_max = tags['Sg_max'] # 1/nm maximum allowed excitation error
1073
-
1074
- h = np.linspace(-hkl_max, hkl_max, 2*hkl_max+1) # all evaluated single Miller Indices
1075
- hkl = np.array(list(itertools.product(h, h, h))) # all evaluated Miller indices
1076
- g = np.dot(hkl, reciprocal_unit_cell) # all evaluated reciprocal_unit_cell points
1077
- g_norm = np.linalg.norm(g, axis=1) # length of all vectors
1078
- not_zero = g_norm > 0
1079
- g = g[not_zero] # zero reflection will make problems further on, so we exclude it.
1080
- g_norm = g_norm[not_zero]
1081
- hkl = hkl[not_zero]
1082
- g_non_rot = g
1083
- g = np.dot(g, rotation_matrix)
1084
-
1085
- ########################
1086
- # Calculate excitation errors for all reciprocal_unit_cell points
1087
- ########################
1088
-
1089
- # Zuo and Spence, 'Adv TEM', 2017 -- Eq 3:14
1090
- # S=(K0**2-np.linalg.norm(g - K0_vector, axis=1)**2)/(2*K0)
1091
- gMz = g - K0_vector
1092
-
1093
- in_sqrt = gMz[:, 2]**2 + np.linalg.norm(gMz, axis=1)**2 - K0**2
1094
- in_sqrt[in_sqrt < 0] = 0.
1095
- S = -gMz[:, 2] - np.sqrt(in_sqrt)
1096
-
1097
- ########################
1098
- # Determine reciprocal_unit_cell points with excitation error less than the maximum allowed one: Sg_max
1099
- ########################
1100
-
1101
- reflections = abs(S) < Sg_max # This is now a boolean array with True for all possible reflections
1102
-
1103
- Sg = S[reflections]
1104
- g_hkl = g[reflections]
1105
- g_hkl_non_rot = g_non_rot[reflections]
1106
- hkl = hkl[reflections]
1107
- g_norm = g_norm[reflections]
1108
-
1109
- if verbose:
1110
- print('Of the {0} tested reciprocal_unit_cell points, {1} have an excitation error less than {2:.2f} 1/nm'.
1111
- format(len(g), len(g_hkl), Sg_max))
1112
-
1113
- ##################################
1114
- # Calculate Structure Factors
1115
- #################################
1116
-
1117
- structure_factors = []
1118
- """for j in range(len(g_hkl)):
1119
- F = 0
1120
- for b in range(len(tags['base'])):
1121
- f = feq(tags['elements'][b],np.linalg.norm(g_hkl[j]))
1122
- #F += f * np.exp(-2*np.pi*1j*(hkl*tags['base'][b]).sum()) # may only work for cubic Gerd
1123
- F += f * np.exp(-2*np.pi*1j*(g_hkl_non_rot*np.dot(tags['base'][b],unit_cell)).sum())
1124
-
1125
-
1126
- structure_factors.append(F)
1127
-
1128
- F = structure_factors = np.array(structure_factors)
1129
- """
1130
- base = np.dot(tags['base'], tags['unit_cell']) # transformation from relative to Cartesian coordinates
1131
- for j in range(len(g_hkl)):
1132
- F = 0
1133
- for b in range(len(base)):
1134
- f = feq(tags['elements'][b], g_norm[j]) # Atomic form factor for element and momentum change (g vector)
1135
- F += f * np.exp(-2*np.pi*1j*(g_hkl_non_rot[j]*base[b]).sum())
1136
- structure_factors.append(F)
1137
- F = structure_factors = np.array(structure_factors)
1138
-
1139
- ############################################
1140
- # Sort reflection in allowed and forbidden #
1141
- ############################################
1142
-
1143
- allowed = np.absolute(F) > 0.000001 # allowed within numerical error
1144
-
1145
- if verbose:
1146
- print('Of the {0} possible reflection {1} are allowed.'.format(hkl.shape[0], allowed.sum()))
1147
-
1148
- # information of allowed reflections
1149
- Sg_allowed = Sg[allowed]
1150
- hkl_allowed = hkl[allowed][:]
1151
- g_allowed = g_hkl[allowed, :]
1152
- F_allowed = F[allowed]
1153
- g_norm_allowed = g_norm[allowed]
1154
-
1155
- tags['allowed'] = {}
1156
- tags['allowed']['Sg'] = Sg_allowed
1157
- tags['allowed']['hkl'] = hkl_allowed
1158
- tags['allowed']['g'] = g_allowed
1159
- tags['allowed']['structure factor'] = F_allowed
1160
-
1161
- # information of forbidden reflections
1162
- forbidden = np.logical_not(allowed)
1163
- Sg_forbidden = Sg[forbidden]
1164
- hkl_forbidden = hkl[forbidden]
1165
- g_forbidden = g_hkl[forbidden]
1166
-
1167
- tags['forbidden'] = {}
1168
- tags['forbidden']['Sg'] = Sg_forbidden
1169
- tags['forbidden']['hkl'] = hkl_forbidden
1170
- tags['forbidden']['g'] = g_forbidden
1171
-
1172
- ###########################
1173
- # Make pretty labels
1174
- ###########################
1175
- hkl_label = make_pretty_labels(hkl_allowed)
1176
- tags['allowed']['label'] = hkl_label
1177
-
1178
- # hkl_label = make_pretty_labels(hkl_forbidden)
1179
- # tags['forbidden']['label'] = hkl_label
1180
-
1181
- ############################
1182
- # Calculate Intensities (of allowed reflections)
1183
- ############################
1184
-
1185
- intensities = np.absolute(F_allowed)**2
1186
-
1187
- tags['allowed']['intensities'] = intensities
1188
-
1189
- ############################
1190
- # Calculate Laue Zones (of allowed reflections)
1191
- ############################
1192
- # Below is the expression given in most books.
1193
- # However, that would only work for orthogonal crystal systems
1194
- # Laue_Zone = abs(np.dot(hkl_allowed,tags['zone_hkl'])) # works only for orthogonal systems
1195
-
1196
- # This expression works for all crystal systems
1197
- # Remember we have already tilted, and so the dot product is trivial and gives only the z-component.
1198
- length_zone_axis = np.linalg.norm(np.dot(tags['zone_hkl'], tags['unit_cell']))
1199
- Laue_Zone = abs(np.floor(g_allowed[:, 2]*length_zone_axis+0.5))
1200
-
1201
- tags['allowed']['Laue_Zone'] = Laue_Zone
1202
-
1203
- ZOLZ_forbidden = abs(np.floor(g_forbidden[:, 2]*length_zone_axis+0.5)) == 0
1204
-
1205
- tags['forbidden']['Laue_Zone'] = ZOLZ_forbidden
1206
- ZOLZ = Laue_Zone == 0
1207
- FOLZ = Laue_Zone == 1
1208
- SOLZ = Laue_Zone == 2
1209
- HOLZ = Laue_Zone > 0
1210
- HOLZp = Laue_Zone > 2
1211
-
1212
- tags['allowed']['ZOLZ'] = ZOLZ
1213
- tags['allowed']['FOLZ'] = FOLZ
1214
- tags['allowed']['SOLZ'] = SOLZ
1215
- tags['allowed']['HOLZ'] = HOLZ
1216
- tags['allowed']['HOLZ_plus'] = tags['allowed']['HHOLZ'] = HOLZp
1217
-
1218
- if verbose:
1219
- print(' There are {0} allowed reflections in the zero order Laue Zone'.format(ZOLZ.sum()))
1220
- print(' There are {0} allowed reflections in the first order Laue Zone'.format((Laue_Zone == 1).sum()))
1221
- print(' There are {0} allowed reflections in the second order Laue Zone'.format((Laue_Zone == 2).sum()))
1222
- print(' There are {0} allowed reflections in the other higher order Laue Zones'.format((Laue_Zone > 2).sum()))
1223
-
1224
- if verbose == 2:
1225
- print(' hkl \t Laue zone \t Intensity (*1 and \t log) \t length \n')
1226
- for i in range(len(hkl_allowed)):
1227
- print(' {0} \t {1} \t {2:.3f} \t {3:.3f} \t {4:.3f} '.format(hkl_allowed[i], g_allowed[i],
1228
- intensities[i], np.log(intensities[i]+1),
1229
- g_norm_allowed[i]))
1230
-
1231
- ###########################
1232
- # Dynamically Activated forbidden reflections
1233
- ###########################
1234
-
1235
- double_diffraction = (np.sum(np.array(list(itertools.combinations(hkl_allowed[ZOLZ], 2))), axis=1))
1236
-
1237
- dynamical_allowed = []
1238
- still_forbidden = []
1239
- for i, hkl in enumerate(hkl_forbidden):
1240
- if ZOLZ_forbidden[i]:
1241
- if hkl.tolist() in double_diffraction.tolist():
1242
- dynamical_allowed.append(i)
1243
- else:
1244
- still_forbidden.append(i)
1245
- tags['forbidden']['dynamically_activated'] = dynamical_allowed
1246
- tags['forbidden']['forbidden'] = dynamical_allowed
1247
- if verbose:
1248
- print('Length of zone axis vector in real space {0} nm'.format(np.round(length_zone_axis, 3)))
1249
- print(f'There are {len(dynamical_allowed)} forbidden but dynamical activated diffraction spots:')
1250
- # print(tags['forbidden']['hkl'][dynamical_allowed])
1251
-
1252
- ####################################
1253
- # Calculate HOLZ and Kikuchi Lines #
1254
- ####################################
1255
-
1256
- # Dynamic Correction
1257
-
1258
- # Equation Spence+Zuo 3.86a
1259
- gamma_1 = - 1./(2.*K0) * (intensities / (2.*K0*Sg_allowed)).sum()
1260
- # print('gamma_1',gamma_1)
1261
-
1262
- # Equation Spence+Zuo 3.84
1263
- Kg = K0 - K0*gamma_1/(g_allowed[:, 2]+1e-15)
1264
- Kg[ZOLZ] = K0
1265
-
1266
- # print(Kg, Kg.shape)
1267
-
1268
- # Calculate angle between K0 and deficient cone vector
1269
- # For dynamic calculations K0 is replaced by Kg
1270
- Kg[:] = K0
1271
- dtheta = np.arcsin(g_norm_allowed/Kg/2.)-np.arcsin(np.abs(g_allowed[:, 2])/g_norm_allowed)
1272
-
1273
- # calculate length of distance of deficient cone to K0 in ZOLZ plane
1274
- gd_length = 2*np.sin(dtheta/2)*K0
1275
-
1276
- # Calculate nearest point of HOLZ and Kikuchi lines
1277
- g_closest = g_allowed.copy()
1278
- g_closest = g_closest*(gd_length/np.linalg.norm(g_closest, axis=1))[:, np.newaxis]
1279
-
1280
- g_closest[:, 2] = 0.
1281
-
1282
- # calculate and save line in Hough space coordinates (distance and theta)
1283
- slope = g_closest[:, 0]/(g_closest[:, 1]+1e-10)
1284
- distance = gd_length
1285
- theta = np.arctan2(g_allowed[:, 0], g_allowed[:, 1])
1286
-
1287
- tags['HOLZ'] = {}
1288
- tags['HOLZ']['slope'] = slope
1289
- # a line is now given by
1290
-
1291
- tags['HOLZ']['distance'] = distance
1292
- tags['HOLZ']['theta'] = theta
1293
-
1294
- tags['HOLZ']['g deficient'] = g_closest
1295
- tags['HOLZ']['g excess'] = g_closest+g_allowed
1296
-
1297
- tags['HOLZ']['ZOLZ'] = ZOLZ
1298
- tags['HOLZ']['HOLZ'] = HOLZ
1299
- tags['HOLZ']['FOLZ'] = FOLZ
1300
- tags['HOLZ']['SOLZ'] = SOLZ
1301
- tags['HOLZ']['HHOLZ'] = HOLZp # even higher HOLZ
1302
-
1303
- tags['HOLZ']['hkl'] = tags['allowed']['hkl']
1304
- tags['HOLZ']['intensities'] = intensities
1305
-
1306
- if verbose:
1307
- print('KinsCat\'s \"Kinematic_Scattering\" finished')
1308
-
1309
-
1310
- #####################
1311
- # Plot SAED Pattern #
1312
- #####################
1313
- def plotSAED(tags, gray=False):
1314
-
1315
- saed = tags.copy()
1316
- saed['convergence_angle_nm-1'] = 0
1317
-
1318
- saed['background'] = 'white' # 'white' 'grey'
1319
- saed['color map'] = 'plasma' # ,'cubehelix'#'Greys'#'plasma'
1320
- saed['color reflections'] = 'ZOLZ'
1321
-
1322
- if gray:
1323
- saed['color map'] = 'gray'
1324
- saed['background'] = '#303030' # 'darkgray'
1325
- saed['color reflections'] = 'intensity'
1326
- saed['plot HOLZ'] = 0
1327
- saed['plot HOLZ excess'] = 0
1328
- saed['plot Kikuchi'] = 0
1329
- saed['plot reflections'] = 1
1330
-
1331
- saed['label HOLZ'] = 0
1332
- saed['label Kikuchi'] = 0
1333
- saed['label reflections'] = 0
1334
-
1335
- saed['label color'] = 'white'
1336
- saed['label size'] = 10
1337
-
1338
- saed['color Laue Zones'] = ['red', 'blue', 'green', 'blue', 'green'] # , 'green', 'red'] #for OLZ give a sequence
1339
- saed['color zero'] = 'red' # 'None' #'white'
1340
- saed['color ring zero'] = 'None' # 'Red' #'white' #, 'None'
1341
- saed['width ring zero'] = 2
1342
-
1343
- plot_diffraction_pattern(saed, True)
1344
-
1345
-
1346
- ########################
1347
- # Plot Kikuchi Pattern #
1348
- ########################
1349
- def plotKikuchi(tags, grey=False):
1350
- Kikuchi = tags.copy()
1351
-
1352
- Kikuchi['background'] = 'black' # 'white' 'grey'
1353
- Kikuchi['color map'] = 'plasma' # ,'cubehelix'#'Greys'#'plasma'
1354
- Kikuchi['color reflections'] = 'intensity'
1355
-
1356
- Kikuchi['plot HOLZ'] = 0
1357
- Kikuchi['plot HOLZ excess'] = 0
1358
- Kikuchi['plot Kikuchi'] = 1
1359
- Kikuchi['plot reflections'] = 1
1360
-
1361
- Kikuchi['label HOLZ'] = 0
1362
- Kikuchi['label Kikuchi'] = 0
1363
- Kikuchi['label reflections'] = 0
1364
-
1365
- Kikuchi['label color'] = 'white'
1366
- Kikuchi['label size'] = 10
1367
-
1368
- Kikuchi['color Kikuchi'] = 'green'
1369
- Kikuchi['linewidth HOLZ'] = -1 # -1: linewidth according to intensity (structure factor F^2
1370
- Kikuchi['linewidth Kikuchi'] = -1 # -1: linewidth according to intensity (structure factor F^2
1371
-
1372
- Kikuchi['color Laue Zones'] = ['red', 'blue', 'green', 'blue', 'green'] # , 'green', 'red']
1373
- # #for OLZ give a sequence
1374
- Kikuchi['color zero'] = 'white' # 'None' #'white'
1375
- Kikuchi['color ring zero'] = 'None' # 'Red' #'white' #, 'None'
1376
- Kikuchi['width ring zero'] = 2
1377
-
1378
- plot_diffraction_pattern(Kikuchi, True)
1379
-
1380
-
1381
- ########################
1382
- # Plot HOLZ Pattern #
1383
- ########################
1384
- def plotHOLZ(tags, grey=False):
1385
- holz = tags.copy()
1386
-
1387
- holz['background'] = 'black' # 'white' 'grey'
1388
- holz['color map'] = 'plasma' # ,'cubehelix'#'Greys'#'plasma'
1389
- holz['color reflections'] = 'intensity'
1390
-
1391
- holz['plot HOLZ'] = 1
1392
- holz['plot HOLZ excess'] = 0
1393
- holz['plot Kikuchi'] = 1
1394
- holz['plot reflections'] = 0
1395
-
1396
- holz['label HOLZ'] = 0
1397
- holz['label Kikuchi'] = 0
1398
- holz['label reflections'] = 0
1399
-
1400
- holz['label color'] = 'white'
1401
- holz['label size'] = 10
1402
-
1403
- holz['color Kikuchi'] = 'green'
1404
- holz['linewidth HOLZ'] = -1 # -1: linewidth according to intensity (structure factor F^2
1405
- holz['linewidth Kikuchi'] = -1 # -1: linewidth according to intensity (structure factor F^2
1406
-
1407
- holz['color Laue Zones'] = ['red', 'blue', 'green'] # , 'green', 'red'] #for OLZ give a sequence
1408
- holz['color zero'] = 'white' # 'None' #'white'
1409
- holz['color ring zero'] = 'Red' # 'Red' #'white' #, 'None'
1410
- holz['width ring zero'] = 2
1411
-
1412
- plot_diffraction_pattern(holz, True)
1413
-
1414
-
1415
- ########################
1416
- # Plot CBED Pattern #
1417
- ########################
1418
- def plotCBED(tags, grey=False):
1419
- cbed = tags.copy()
1420
-
1421
- cbed['background'] = 'black' # 'white' 'grey'
1422
- cbed['color map'] = 'plasma' # ,'cubehelix'#'Greys'#'plasma'
1423
- cbed['color reflections'] = 'intensity'
1424
-
1425
- cbed['plot HOLZ'] = 1
1426
- cbed['plot HOLZ excess'] = 1
1427
- cbed['plot Kikuchi'] = 1
1428
- cbed['plot reflections'] = 1
1429
-
1430
- cbed['label HOLZ'] = 0
1431
- cbed['label Kikuchi'] = 0
1432
- cbed['label reflections'] = 0
1433
-
1434
- cbed['label color'] = 'white'
1435
- cbed['label size'] = 10
1436
-
1437
- cbed['color Kikuchi'] = 'green'
1438
- cbed['linewidth HOLZ'] = -1 # -1: linewidth according to intensity (structure factor F^2
1439
- cbed['linewidth Kikuchi'] = -1 # -1: linewidth according to intensity (structure factor F^2
1440
-
1441
- cbed['color reflections'] = 'intensity'
1442
-
1443
- cbed['color Laue Zones'] = ['red', 'blue', 'green'] # , 'green', 'red'] #for OLZ give a sequence
1444
- cbed['color zero'] = 'white' # 'None' #'white'
1445
- cbed['color ring zero'] = 'Red' # 'Red' #'white' #, 'None'
1446
- cbed['width ring zero'] = 2
1447
-
1448
- plot_diffraction_pattern(cbed, True)
1449
-
1450
-
1451
- ########################
1452
- # Plot HOLZ Pattern #
1453
- ########################
1454
- def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs):
1455
- """
1456
- Make a scatter plot of circles.
1457
- Similar to plt.scatter, but the size of circles are in data scale.
1458
- Parameters
1459
- ----------
1460
- x, y : scalar or array_like, shape (n, )
1461
- Input data
1462
- s : scalar or array_like, shape (n, )
1463
- Radius of circles.
1464
- c : color or sequence of color, optional, default : 'b'
1465
- `c` can be a single color format string, or a sequence of color
1466
- specifications of length `N`, or a sequence of `N` numbers to be
1467
- mapped to colors using the `cmap` and `norm` specified via kwargs.
1468
- Note that `c` should not be a single numeric RGB or RGBA sequence
1469
- because that is indistinguishable from an array of values
1470
- to be colormapped. (If you insist, use `color` instead.)
1471
- `c` can be a 2-D array in which the rows are RGB or RGBA, however.
1472
- vmin, vmax : scalar, optional, default: None
1473
- `vmin` and `vmax` are used in conjunction with `norm` to normalize
1474
- luminance data. If either are `None`, the min and max of the
1475
- color array is used.
1476
- kwargs : `~matplotlib.collections.Collection` properties
1477
- Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls),
1478
- norm, cmap, transform, etc.
1479
- Returns
1480
- -------
1481
- paths : `~matplotlib.collections.PathCollection`
1482
- Examples
1483
- --------
1484
- a = np.arange(11)
1485
- circles(a, a, s=a*0.2, c=a, alpha=0.5, ec='none')
1486
- plt.colorbar()
1487
- License
1488
- --------
1489
- This code is under [The BSD 3-Clause License]
1490
- (http://opensource.org/licenses/BSD-3-Clause)
1491
- """
1492
-
1493
- if np.isscalar(c):
1494
- kwargs.setdefault('color', c)
1495
- c = None
1496
-
1497
- if 'fc' in kwargs:
1498
- kwargs.setdefault('facecolor', kwargs.pop('fc'))
1499
- if 'ec' in kwargs:
1500
- kwargs.setdefault('edgecolor', kwargs.pop('ec'))
1501
- if 'ls' in kwargs:
1502
- kwargs.setdefault('linestyle', kwargs.pop('ls'))
1503
- if 'lw' in kwargs:
1504
- kwargs.setdefault('linewidth', kwargs.pop('lw'))
1505
- # You can set `facecolor` with an array for each patch,
1506
- # while you can only set `facecolors` with a value for all.
1507
-
1508
- zipped = np.broadcast(x, y, s)
1509
- patches = [Circle((x_, y_), s_)
1510
- for x_, y_, s_ in zipped]
1511
- collection = PatchCollection(patches, **kwargs)
1512
- if c is not None:
1513
- c = np.broadcast_to(c, zipped.shape).ravel()
1514
- collection.set_array(c)
1515
- collection.set_clim(vmin, vmax)
1516
-
1517
- ax = plt.gca()
1518
- ax.add_collection(collection)
1519
- ax.autoscale_view()
1520
- plt.draw_if_interactive()
1521
- if c is not None:
1522
- plt.sci(collection)
1523
- return collection
1524
-
1525
-
1526
- def plot_diffraction_pattern(tags, grey=False):
1527
- if 'plot_rotation' not in tags:
1528
- tags['plot_rotation'] = 0.
1529
-
1530
- if 'new_plot' not in tags:
1531
- tags['new_plot'] = True
1532
-
1533
- if tags['new_plot']:
1534
- fig = plt.figure()
1535
- ax = fig.add_subplot(111, facecolor=tags['background'])
1536
-
1537
- diffraction_pattern(tags, grey)
1538
-
1539
- plt.axis('equal')
1540
- if 'plot FOV' in tags:
1541
- x = tags['plot FOV'] # in 1/nm
1542
- plt.xlim(-x, x)
1543
- plt.ylim(-x, x)
1544
- plt.title(tags['crystal_name'])
1545
- plt.show()
1546
- else:
1547
- diffraction_pattern(tags, grey)
1548
-
1549
-
1550
- def diffraction_pattern(tags, grey=False):
1551
-
1552
- # Get information from dictionary
1553
- HOLZ = tags['allowed']['HOLZ']
1554
- ZOLZ = tags['allowed']['ZOLZ']
1555
-
1556
- Laue_Zone = tags['allowed']['Laue_Zone']
1557
-
1558
- if 'label' in tags['allowed']:
1559
- label = tags['allowed']['label']
1560
-
1561
- angle = np.radians(tags['plot_rotation']) # mrad
1562
- c = np.cos(angle)
1563
- s = np.sin(angle)
1564
- r_mat = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
1565
-
1566
- # HOLZ and Kikuchi lines coordinates in Hough space
1567
- gd = np.dot(tags['HOLZ']['g deficient'], r_mat)
1568
- ge = np.dot(tags['HOLZ']['g excess'], r_mat)
1569
-
1570
- points = np.dot(tags['allowed']['g'], r_mat)
1571
-
1572
- theta = tags['HOLZ']['theta']+angle
1573
-
1574
- intensity = tags['allowed']['intensities']
1575
- radius = tags['convergence_angle_nm-1']
1576
- tags['Bragg'] = {}
1577
- tags['Bragg']['points'] = points
1578
- tags['Bragg']['intensity'] = intensity
1579
- tags['Bragg']['radius'] = radius
1580
-
1581
- if radius < 0.1:
1582
- radiusI = 2
1583
- else:
1584
- radiusI = radius
1585
- # Beginning and ends of HOLZ lines
1586
- maxlength = radiusI * 1.3
1587
- Hxp = gd[:, 0] + maxlength * np.cos(np.pi-theta)
1588
- Hyp = gd[:, 1] + maxlength * np.sin(np.pi-theta)
1589
- Hxm = gd[:, 0] - maxlength * np.cos(np.pi-theta)
1590
- Hym = gd[:, 1] - maxlength * np.sin(np.pi-theta)
1591
- tags['HOLZ lines'] = {}
1592
- tags['HOLZ lines']['Hxp'] = Hxp
1593
- tags['HOLZ lines']['Hyp'] = Hyp
1594
- tags['HOLZ lines']['Hxm'] = Hxm
1595
- tags['HOLZ lines']['Hym'] = Hym
1596
-
1597
- # Beginning and ends of excess HOLZ lines
1598
- maxlength = radiusI * 0.8
1599
- Exp = ge[:, 0] + maxlength * np.cos(np.pi-theta)
1600
- Eyp = ge[:, 1] + maxlength * np.sin(np.pi-theta)
1601
- Exm = ge[:, 0] - maxlength * np.cos(np.pi-theta)
1602
- Eym = ge[:, 1] - maxlength * np.sin(np.pi-theta)
1603
- tags['excess HOLZ lines'] = {}
1604
- tags['excess HOLZ lines']['Exp'] = Exp
1605
- tags['excess HOLZ lines']['Eyp'] = Eyp
1606
- tags['excess HOLZ lines']['Exm'] = Exm
1607
- tags['excess HOLZ lines']['Eym'] = Eym
1608
-
1609
- # Beginning and ends of HOLZ lines
1610
- maxlength = 20
1611
- Kxp = gd[:, 0] + maxlength * np.cos(np.pi-theta)
1612
- Kyp = gd[:, 1] + maxlength * np.sin(np.pi-theta)
1613
- Kxm = gd[:, 0] - maxlength * np.cos(np.pi-theta)
1614
- Kym = gd[:, 1] - maxlength * np.sin(np.pi-theta)
1615
- tags['Kikuchi lines'] = {}
1616
- tags['Kikuchi lines']['Kxp'] = Kxp
1617
- tags['Kikuchi lines']['Kyp'] = Kyp
1618
- tags['Kikuchi lines']['Kxm'] = Kxm
1619
- tags['Kikuchi lines']['Kym'] = Kym
1620
-
1621
- intensity_Kikuchi = intensity*4./intensity[ZOLZ].max()
1622
- if len(intensity[tags['HOLZ']['HOLZ']]) > 1:
1623
- intensity_HOLZ = intensity*4./intensity[tags['HOLZ']['HOLZ']].max()*.75
1624
- tags['HOLZ lines']['intensity_HOLZ'] = intensity_HOLZ
1625
- tags['Kikuchi lines']['intensity_Kikuchi'] = intensity_Kikuchi
1626
- ########
1627
- # Plot #
1628
- ########
1629
- cms = mpl.cm
1630
- # cm = cms.plasma#jet#, cms.gray, cms.autumn]
1631
- cm = plt.get_cmap(tags['color map'])
1632
-
1633
- fig = plt.gcf()
1634
-
1635
- ax = plt.gca()
1636
-
1637
- if 'plot image' in tags:
1638
- l = -tags['plot image FOV']/2+tags['plot shift x']
1639
- r = tags['plot image FOV']/2+tags['plot shift x']
1640
- t = -tags['plot image FOV']/2+tags['plot shift y']
1641
- b = tags['plot image FOV']/2+tags['plot shift y']
1642
- ax.imshow(tags['plot image'], extent=(l, r, t, b))
1643
- print('image')
1644
-
1645
- ix = np.argsort((points**2).sum(axis=1))
1646
- # print(tags['allowed']['hkl'][ix])
1647
- p = points[ix]
1648
- inten = intensity[ix]
1649
- tags['Bragg']['points'] = p
1650
- tags['Bragg']['intensity'] = inten
1651
-
1652
- Lauecolor = []
1653
- for i in range(int(Laue_Zone.max())+1):
1654
- if i < len(tags['color Laue Zones']):
1655
- Lauecolor.append(tags['color Laue Zones'][i])
1656
- else:
1657
- Lauecolor.append(tags['color Laue Zones'][-1])
1658
-
1659
- if tags['plot reflections']:
1660
- if radius < 0.1:
1661
- if tags['color reflections'] == 'intensity':
1662
- ax.scatter(points[:, 0], points[:, 1], c=np.log(intensity), cmap=cm, s=20)
1663
- else:
1664
- for i in range(len(Laue_Zone)):
1665
- color = Lauecolor[int(Laue_Zone[i])]
1666
- ax.scatter(points[i, 0], points[i, 1], c=color, cmap=cm, s=20)
1667
-
1668
- ax.scatter(0, 0, c=tags['color zero'], s=100)
1669
- radius = 2
1670
- else:
1671
- ix = np.argsort((points**2).sum(axis=1))
1672
- p = points[ix]
1673
- inten = intensity[ix]
1674
- if tags['color reflections'] == 'intensity':
1675
- circles(p[:, 0], p[:, 1], s=radius, c=np.log(inten+1), cmap=cm, alpha=0.9, edgecolor='')
1676
- else:
1677
- for i in range(len(Laue_Zone)):
1678
- color = Lauecolor[int(Laue_Zone[i])]
1679
- circles(p[i, 0], p[i, 1], s=radius, c=color, cmap=cm, alpha=0.9, edgecolor='')
1680
-
1681
- if not tags['color zero'] == 'None':
1682
- circle = plt.Circle((0, 0), radius, color=tags['color zero'])
1683
- ax.add_artist(circle)
1684
-
1685
- for i in range(len(Hxp)):
1686
- if tags['HOLZ']['HOLZ'][i]:
1687
- color = Lauecolor[int(Laue_Zone[i])]
1688
- if tags['plot HOLZ']:
1689
- # plot HOLZ lines
1690
- ax.plot((Hxp[i], Hxm[i]), (Hyp[i], Hym[i]), c=color, linewidth=intensity_HOLZ[i])
1691
- if tags['plot HOLZ excess']:
1692
- ax.plot((Exp[i], Exm[i]), (Eyp[i], Eym[i]), c=color, linewidth=intensity_HOLZ[i])
1693
-
1694
- if tags['label HOLZ']: # Add indices
1695
- ax.text(Hxp[i], Hyp[i], label[i], fontsize=10)
1696
- ax.text(Exp[i], Eyp[i], label[i], fontsize=10)
1697
- else:
1698
- # Plot Kikuchi lines
1699
- if tags['plot Kikuchi']:
1700
- ax.plot((Kxp[i], Kxm[i]), (Kyp[i], Kym[i]), c=tags['color Kikuchi'], linewidth=intensity_Kikuchi[i])
1701
- if tags['label Kikuchi']: # Add indices
1702
- ax.text(Kxp[i], Kyp[i], label[i], fontsize=tags['label size'], color=tags['label color'])
1703
- tags['Kikuchi lines']
1704
-
1705
- if not (tags['color ring zero'] == 'None'):
1706
- ring = plt.Circle((0, 0), radius, color=tags['color ring zero'], fill=False, linewidth=2)
1707
- ax.add_artist(ring)
1708
- print(ring)
1709
-
1710
- return tags
1711
-
1712
-
1713
- electronFF = {
1714
- # form factor coefficients
1715
- # Z= 6, chisq= 0.143335
1716
- # a1 b1 a2 b2
1717
- # a3 b3 c1 d1
1718
- # c2 d2 c3 d3
1719
-
1720
- # name of the file: feKirkland.txt
1721
- # converted with program sortFF.py
1722
- # form factor parametrized in 1/Angstrom
1723
- # bond_length as a list of atom Sizes, bond radii, angle radii, H-bond radii
1724
-
1725
- 'H': {'Z': 1, 'chisq': 0.170190,
1726
- 'bond_length': [0.98, 0.78, 1.20, 0],
1727
- 'fa': [4.20298324e-003, 6.27762505e-002, 3.00907347e-002],
1728
- 'fb': [2.25350888e-001, 2.25366950e-001, 2.25331756e-001],
1729
- 'fc': [6.77756695e-002, 3.56609237e-003, 2.76135815e-002],
1730
- 'fd': [4.38854001e+000, 4.03884823e-001, 1.44490166e+000]},
1731
- 'He': {'Z': 2, 'chisq': 0.396634,
1732
- 'bond_length': [1.45, 1.25, 1.40, 0],
1733
- 'fa': [1.87543704e-005, 4.10595800e-004, 1.96300059e-001],
1734
- 'fb': [2.12427997e-001, 3.32212279e-001, 5.17325152e-001],
1735
- 'fc': [8.36015738e-003, 2.95102022e-002, 4.65928982e-007],
1736
- 'fd': [3.66668239e-001, 1.37171827e+000, 3.75768025e+004]},
1737
- 'Li': {'Z': 3, 'chisq': 0.286232,
1738
- 'bond_length': [1.76, 1.56, 1.82, 0],
1739
- 'fa': [7.45843816e-002, 7.15382250e-002, 1.45315229e-001],
1740
- 'fb': [8.81151424e-001, 4.59142904e-002, 8.81301714e-001],
1741
- 'fc': [1.12125769e+000, 2.51736525e-003, 3.58434971e-001],
1742
- 'fd': [1.88483665e+001, 1.59189995e-001, 6.12371000e+000]},
1743
- 'Be': {'Z': 4, 'chisq': 0.195442,
1744
- 'bond_length': [1.33, 1.13, 1.70, 0],
1745
- 'fa': [6.11642897e-002, 1.25755034e-001, 2.00831548e-001],
1746
- 'fb': [9.90182132e-002, 9.90272412e-002, 1.87392509e+000],
1747
- 'fc': [7.87242876e-001, 1.58847850e-003, 2.73962031e-001],
1748
- 'fd': [9.32794929e+000, 8.91900236e-002, 3.20687658e+000]},
1749
- 'B': {'Z': 5, 'chisq': 0.146989,
1750
- 'bond_length': [1.18, 0.98, 2.08, 0],
1751
- 'fa': [1.25716066e-001, 1.73314452e-001, 1.84774811e-001],
1752
- 'fb': [1.48258830e-001, 1.48257216e-001, 3.34227311e+000],
1753
- 'fc': [1.95250221e-001, 5.29642075e-001, 1.08230500e-003],
1754
- 'fd': [1.97339463e+000, 5.70035553e+000, 5.64857237e-002]},
1755
- 'C': {'Z': 6, 'chisq': 0.102440,
1756
- 'bond_length': [1.12, 0.92, 1.95, 0],
1757
- 'fa': [2.12080767e-001, 1.99811865e-001, 1.68254385e-001],
1758
- 'fb': [2.08605417e-001, 2.08610186e-001, 5.57870773e+000],
1759
- 'fc': [1.42048360e-001, 3.63830672e-001, 8.35012044e-004],
1760
- 'fd': [1.33311887e+000, 3.80800263e+000, 4.03982620e-002]},
1761
- 'N': {'Z': 7, 'chisq': 0.060249,
1762
- 'bond_length': [1.08, 0.88, 1.85, 1.30],
1763
- 'fa': [5.33015554e-001, 5.29008883e-002, 9.24159648e-002],
1764
- 'fb': [2.90952515e-001, 1.03547896e+001, 1.03540028e+001],
1765
- 'fc': [2.61799101e-001, 8.80262108e-004, 1.10166555e-001],
1766
- 'fd': [2.76252723e+000, 3.47681236e-002, 9.93421736e-001]},
1767
- 'O': {'Z': 8, 'chisq': 0.039944,
1768
- 'bond_length': [1.09, 0.89, 1.70, 1.40],
1769
- 'fa': [3.39969204e-001, 3.07570172e-001, 1.30369072e-001],
1770
- 'fb': [3.81570280e-001, 3.81571436e-001, 1.91919745e+001],
1771
- 'fc': [8.83326058e-002, 1.96586700e-001, 9.96220028e-004],
1772
- 'fd': [7.60635525e-001, 2.07401094e+000, 3.03266869e-002]},
1773
- 'F': {'Z': 9, 'chisq': 0.027866,
1774
- 'bond_length': [1.30, 1.10, 1.73, 0],
1775
- 'fa': [2.30560593e-001, 5.26889648e-001, 1.24346755e-001],
1776
- 'fb': [4.80754213e-001, 4.80763895e-001, 3.95306720e+001],
1777
- 'fc': [1.24616894e-003, 7.20452555e-002, 1.53075777e-001],
1778
- 'fd': [2.62181803e-002, 5.92495593e-001, 1.59127671e+000]},
1779
- 'Ne': {'Z': 10, 'chisq': 0.021836,
1780
- 'bond_length': [1.50, 1.30, 1.54, 0],
1781
- 'fa': [4.08371771e-001, 4.54418858e-001, 1.44564923e-001],
1782
- 'fb': [5.88228627e-001, 5.88288655e-001, 1.21246013e+002],
1783
- 'fc': [5.91531395e-002, 1.24003718e-001, 1.64986037e-003],
1784
- 'fd': [4.63963540e-001, 1.23413025e+000, 2.05869217e-002]},
1785
- 'Na': {'Z': 11, 'chisq': 0.064136,
1786
- 'bond_length': [2.10, 1.91, 2.27, 0],
1787
- 'fa': [1.36471662e-001, 7.70677865e-001, 1.56862014e-001],
1788
- 'fb': [4.99965301e-002, 8.81899664e-001, 1.61768579e+001],
1789
- 'fc': [9.96821513e-001, 3.80304670e-002, 1.27685089e-001],
1790
- 'fd': [2.00132610e+001, 2.60516254e-001, 6.99559329e-001]},
1791
- 'Mg': {'Z': 12, 'chisq': 0.051303,
1792
- 'bond_length': [1.80, 1.60, 1.73, 0],
1793
- 'fa': [3.04384121e-001, 7.56270563e-001, 1.01164809e-001],
1794
- 'fb': [8.42014377e-002, 1.64065598e+000, 2.97142975e+001],
1795
- 'fc': [3.45203403e-002, 9.71751327e-001, 1.20593012e-001],
1796
- 'fd': [2.16596094e-001, 1.21236852e+001, 5.60865838e-001]},
1797
- 'Al': {'Z': 13, 'chisq': 0.049529,
1798
- 'bond_length': [1.60, 1.43, 2.05, 0],
1799
- 'fa': [7.77419424e-001, 5.78312036e-002, 4.26386499e-001],
1800
- 'fb': [2.71058227e+000, 7.17532098e+001, 9.13331555e-002],
1801
- 'fc': [1.13407220e-001, 7.90114035e-001, 3.23293496e-002],
1802
- 'fd': [4.48867451e-001, 8.66366718e+000, 1.78503463e-001]},
1803
- 'Si': {'Z': 14, 'chisq': 0.071667,
1804
- 'bond_length': [1.52, 1.32, 2.10, 0],
1805
- 'fa': [1.06543892e+000, 1.20143691e-001, 1.80915263e-001],
1806
- 'fb': [1.04118455e+000, 6.87113368e+001, 8.87533926e-002],
1807
- 'fc': [1.12065620e+000, 3.05452816e-002, 1.59963502e+000],
1808
- 'fd': [3.70062619e+000, 2.14097897e-001, 9.99096638e+000]},
1809
- 'P': {'Z': 15, 'chisq': 0.047673,
1810
- 'bond_length': [1.48, 1.28, 2.08, 0],
1811
- 'fa': [1.05284447e+000, 2.99440284e-001, 1.17460748e-001],
1812
- 'fb': [1.31962590e+000, 1.28460520e-001, 1.02190163e+002],
1813
- 'fc': [9.60643452e-001, 2.63555748e-002, 1.38059330e+000],
1814
- 'fd': [2.87477555e+000, 1.82076844e-001, 7.49165526e+000]},
1815
- 'S': {'Z': 16, 'chisq': 0.033482,
1816
- 'bond_length': [1.47, 1.27, 2.00, 0],
1817
- 'fa': [1.01646916e+000, 4.41766748e-001, 1.21503863e-001],
1818
- 'fb': [1.69181965e+000, 1.74180288e-001, 1.67011091e+002],
1819
- 'fc': [8.27966670e-001, 2.33022533e-002, 1.18302846e+000],
1820
- 'fd': [2.30342810e+000, 1.56954150e-001, 5.85782891e+000]},
1821
- 'Cl': {'Z': 17, 'chisq': 0.206186,
1822
- 'bond_length': [1.70, 1.50, 1.97, 0],
1823
- 'fa': [9.44221116e-001, 4.37322049e-001, 2.54547926e-001],
1824
- 'fb': [2.40052374e-001, 9.30510439e+000, 9.30486346e+000],
1825
- 'fc': [5.47763323e-002, 8.00087488e-001, 1.07488641e-002],
1826
- 'fd': [1.68655688e-001, 2.97849774e+000, 6.84240646e-002]},
1827
- 'Ar': {'Z': 18, 'chisq': 0.263904,
1828
- 'bond_length': [2.00, 1.80, 1.88, 0],
1829
- 'fa': [1.06983288e+000, 4.24631786e-001, 2.43897949e-001],
1830
- 'fb': [2.87791022e-001, 1.24156957e+001, 1.24158868e+001],
1831
- 'fc': [4.79446296e-002, 7.64958952e-001, 8.23128431e-003],
1832
- 'fd': [1.36979796e-001, 2.43940729e+000, 5.27258749e-002]},
1833
- 'K': {'Z': 19, 'chisq': 0.161900,
1834
- 'bond_length': [2.58, 2.38, 2.75, 0],
1835
- 'fa': [6.92717865e-001, 9.65161085e-001, 1.48466588e-001],
1836
- 'fb': [7.10849990e+000, 3.57532901e-001, 3.93763275e-002],
1837
- 'fc': [2.64645027e-002, 1.80883768e+000, 5.43900018e-001],
1838
- 'fd': [1.03591321e-001, 3.22845199e+001, 1.67791374e+000]},
1839
- 'Ca': {'Z': 20, 'chisq': 0.085209,
1840
- 'bond_length': [2.17, 1.97, 1.97, 0],
1841
- 'fa': [3.66902871e-001, 8.66378999e-001, 6.67203300e-001],
1842
- 'fb': [6.14274129e-002, 5.70881727e-001, 7.82965639e+000],
1843
- 'fc': [4.87743636e-001, 1.82406314e+000, 2.20248453e-002],
1844
- 'fd': [1.32531318e+000, 2.10056032e+001, 9.11853450e-002]},
1845
- 'Sc': {'Z': 21, 'chisq': 0.052352,
1846
- 'bond_length': [1.84, 1.64, 1.70, 0],
1847
- 'fa': [3.78871777e-001, 9.00022505e-001, 7.15288914e-001],
1848
- 'fb': [6.98910162e-002, 5.21061541e-001, 7.87707920e+000],
1849
- 'fc': [1.88640973e-002, 4.07945949e-001, 1.61786540e+000],
1850
- 'fd': [8.17512708e-002, 1.11141388e+000, 1.80840759e+001]},
1851
- 'Ti': {'Z': 22, 'chisq': 0.035298,
1852
- 'bond_length': [1.66, 1.46, 1.70, 0],
1853
- 'fa': [3.62383267e-001, 9.84232966e-001, 7.41715642e-001],
1854
- 'fb': [7.54707114e-002, 4.97757309e-001, 8.17659391e+000],
1855
- 'fc': [3.62555269e-001, 1.49159390e+000, 1.61659509e-002],
1856
- 'fd': [9.55524906e-001, 1.62221677e+001, 7.33140839e-002]},
1857
- 'V': {'Z': 23, 'chisq': 0.030745,
1858
- 'bond_length': [1.55, 1.35, 1.70, 0],
1859
- 'fa': [3.52961378e-001, 7.46791014e-001, 1.08364068e+000],
1860
- 'fb': [8.19204103e-002, 8.81189511e+000, 5.10646075e-001],
1861
- 'fc': [1.39013610e+000, 3.31273356e-001, 1.40422612e-002],
1862
- 'fd': [1.48901841e+001, 8.38543079e-001, 6.57432678e-002]},
1863
- 'Cr': {'Z': 24, 'chisq': 0.015287,
1864
- 'bond_length': [1.56, 1.36, 1.70, 0],
1865
- 'fa': [1.34348379e+000, 5.07040328e-001, 4.26358955e-001],
1866
- 'fb': [1.25814353e+000, 1.15042811e+001, 8.53660389e-002],
1867
- 'fc': [1.17241826e-002, 5.11966516e-001, 3.38285828e-001],
1868
- 'fd': [6.00177061e-002, 1.53772451e+000, 6.62418319e-001]},
1869
- 'Mn': {'Z': 25, 'chisq': 0.031274,
1870
- 'bond_length': [1.54, 1.30, 1.70, 0],
1871
- 'fa': [3.26697613e-001, 7.17297000e-001, 1.33212464e+000],
1872
- 'fb': [8.88813083e-002, 1.11300198e+001, 5.82141104e-001],
1873
- 'fc': [2.80801702e-001, 1.15499241e+000, 1.11984488e-002],
1874
- 'fd': [6.71583145e-001, 1.26825395e+001, 5.32334467e-002]},
1875
- 'Fe': {'Z': 26, 'chisq': 0.031315,
1876
- 'bond_length': [1.47, 1.27, 1.70, 0],
1877
- 'fa': [3.13454847e-001, 6.89290016e-001, 1.47141531e+000],
1878
- 'fb': [8.99325756e-002, 1.30366038e+001, 6.33345291e-001],
1879
- 'fc': [1.03298688e+000, 2.58280285e-001, 1.03460690e-002],
1880
- 'fd': [1.16783425e+001, 6.09116446e-001, 4.81610627e-002]},
1881
- 'Co': {'Z': 27, 'chisq': 0.031643,
1882
- 'bond_length': [1.45, 1.25, 1.70, 0],
1883
- 'fa': [3.15878278e-001, 1.60139005e+000, 6.56394338e-001],
1884
- 'fb': [9.46683246e-002, 6.99436449e-001, 1.56954403e+001],
1885
- 'fc': [9.36746624e-001, 9.77562646e-003, 2.38378578e-001],
1886
- 'fd': [1.09392410e+001, 4.37446816e-002, 5.56286483e-001]},
1887
- 'Ni': {'Z': 28, 'chisq': 0.032245,
1888
- 'bond_length': [1.45, 1.25, 1.63, 0],
1889
- 'fa': [1.72254630e+000, 3.29543044e-001, 6.23007200e-001],
1890
- 'fb': [7.76606908e-001, 1.02262360e-001, 1.94156207e+001],
1891
- 'fc': [9.43496513e-003, 8.54063515e-001, 2.21073515e-001],
1892
- 'fd': [3.98684596e-002, 1.04078166e+001, 5.10869330e-001]},
1893
- 'Cu': {'Z': 29, 'chisq': 0.010467,
1894
- 'bond_length': [1.48, 1.28, 1.40, 0],
1895
- 'fa': [3.58774531e-001, 1.76181348e+000, 6.36905053e-001],
1896
- 'fb': [1.06153463e-001, 1.01640995e+000, 1.53659093e+001],
1897
- 'fc': [7.44930667e-003, 1.89002347e-001, 2.29619589e-001],
1898
- 'fd': [3.85345989e-002, 3.98427790e-001, 9.01419843e-001]},
1899
- 'Zn': {'Z': 30, 'chisq': 0.026698,
1900
- 'bond_length': [1.59, 1.39, 1.39, 0],
1901
- 'fa': [5.70893973e-001, 1.98908856e+000, 3.06060585e-001],
1902
- 'fb': [1.26534614e-001, 2.17781965e+000, 3.78619003e+001],
1903
- 'fc': [2.35600223e-001, 3.97061102e-001, 6.85657228e-003],
1904
- 'fd': [3.67019041e-001, 8.66419596e-001, 3.35778823e-002]},
1905
- 'Ga': {'Z': 31, 'chisq': 0.008110,
1906
- 'bond_length': [1.61, 1.41, 1.87, 0],
1907
- 'fa': [6.25528464e-001, 2.05302901e+000, 2.89608120e-001],
1908
- 'fb': [1.10005650e-001, 2.41095786e+000, 4.78685736e+001],
1909
- 'fc': [2.07910594e-001, 3.45079617e-001, 6.55634298e-003],
1910
- 'fd': [3.27807224e-001, 7.43139061e-001, 3.09411369e-002]},
1911
- 'Ge': {'Z': 32, 'chisq': 0.032198,
1912
- 'bond_length': [1.57, 1.37, 1.70, 0],
1913
- 'fa': [5.90952690e-001, 5.39980660e-001, 2.00626188e+000],
1914
- 'fb': [1.18375976e-001, 7.18937433e+001, 1.39304889e+000],
1915
- 'fc': [7.49705041e-001, 1.83581347e-001, 9.52190743e-003],
1916
- 'fd': [6.89943350e+000, 3.64667232e-001, 2.69888650e-002]},
1917
- 'As': {'Z': 33, 'chisq': 0.034014,
1918
- 'bond_length': [1.59, 1.39, 1.85, 0],
1919
- 'fa': [7.77875218e-001, 5.93848150e-001, 1.95918751e+000],
1920
- 'fb': [1.50733157e-001, 1.42882209e+002, 1.74750339e+000],
1921
- 'fc': [1.79880226e-001, 8.63267222e-001, 9.59053427e-003],
1922
- 'fd': [3.31800852e-001, 5.85490274e+000, 2.33777569e-002]},
1923
- 'Se': {'Z': 34, 'chisq': 0.035703,
1924
- 'bond_length': [1.60, 1.40, 1.90, 0],
1925
- 'fa': [9.58390681e-001, 6.03851342e-001, 1.90828931e+000],
1926
- 'fb': [1.83775557e-001, 1.96819224e+002, 2.15082053e+000],
1927
- 'fc': [1.73885956e-001, 9.35265145e-001, 8.62254658e-003],
1928
- 'fd': [3.00006024e-001, 4.92471215e+000, 2.12308108e-002]},
1929
- 'Br': {'Z': 35, 'chisq': 0.039250,
1930
- 'bond_length': [1.80, 1.60, 2.10, 0],
1931
- 'fa': [1.14136170e+000, 5.18118737e-001, 1.85731975e+000],
1932
- 'fb': [2.18708710e-001, 1.93916682e+002, 2.65755396e+000],
1933
- 'fc': [1.68217399e-001, 9.75705606e-001, 7.24187871e-003],
1934
- 'fd': [2.71719918e-001, 4.19482500e+000, 1.99325718e-002]},
1935
- 'Kr': {'Z': 36, 'chisq': 0.045421,
1936
- 'bond_length': [2.10, 1.90, 2.02, 0],
1937
- 'fa': [3.24386970e-001, 1.31732163e+000, 1.79912614e+000],
1938
- 'fb': [6.31317973e+001, 2.54706036e-001, 3.23668394e+000],
1939
- 'fc': [4.29961425e-003, 1.00429433e+000, 1.62188197e-001],
1940
- 'fd': [1.98965610e-002, 3.61094513e+000, 2.45583672e-001]},
1941
- 'Rb': {'Z': 37, 'chisq': 0.130044,
1942
- 'bond_length': [2.75, 2.55, 1.70, 0],
1943
- 'fa': [2.90445351e-001, 2.44201329e+000, 7.69435449e-001],
1944
- 'fb': [3.68420227e-002, 1.16013332e+000, 1.69591472e+001],
1945
- 'fc': [1.58687000e+000, 2.81617593e-003, 1.28663830e-001],
1946
- 'fd': [2.53082574e+000, 1.88577417e-002, 2.10753969e-001]},
1947
- 'Sr': {'Z': 38, 'chisq': 0.188055,
1948
- 'bond_length': [2.35, 2.15, 1.70, 0],
1949
- 'fa': [1.37373086e-002, 1.97548672e+000, 1.59261029e+000],
1950
- 'fb': [1.87469061e-002, 6.36079230e+000, 2.21992482e-001],
1951
- 'fc': [1.73263882e-001, 4.66280378e+000, 1.61265063e-003],
1952
- 'fd': [2.01624958e-001, 2.53027803e+001, 1.53610568e-002]},
1953
- 'Y': {'Z': 39, 'chisq': 0.174927,
1954
- 'bond_length': [2.00, 1.80, 1.70, 0],
1955
- 'fa': [6.75302747e-001, 4.70286720e-001, 2.63497677e+000],
1956
- 'fb': [6.54331847e-002, 1.06108709e+002, 2.06643540e+000],
1957
- 'fc': [1.09621746e-001, 9.60348773e-001, 5.28921555e-003],
1958
- 'fd': [1.93131925e-001, 1.63310938e+000, 1.66083821e-002]},
1959
- 'Zr': {'Z': 40, 'chisq': 0.072078,
1960
- 'bond_length': [1.80, 1.60, 1.70, 0],
1961
- 'fa': [2.64365505e+000, 5.54225147e-001, 7.61376625e-001],
1962
- 'fb': [2.20202699e+000, 1.78260107e+002, 7.67218745e-002],
1963
- 'fc': [6.02946891e-003, 9.91630530e-002, 9.56782020e-001],
1964
- 'fd': [1.55143296e-002, 1.76175995e-001, 1.54330682e+000]},
1965
- 'Nb': {'Z': 41, 'chisq': 0.011800,
1966
- 'bond_length': [1.67, 1.47, 1.70, 0],
1967
- 'fa': [6.59532875e-001, 1.84545854e+000, 1.25584405e+000],
1968
- 'fb': [8.66145490e-002, 5.94774398e+000, 6.40851475e-001],
1969
- 'fc': [1.22253422e-001, 7.06638328e-001, 2.62381591e-003],
1970
- 'fd': [1.66646050e-001, 1.62853268e+000, 8.26257859e-003]},
1971
- 'Mo': {'Z': 42, 'chisq': 0.008976,
1972
- 'bond_length': [1.60, 1.40, 1.70, 0],
1973
- 'fa': [6.10160120e-001, 1.26544000e+000, 1.97428762e+000],
1974
- 'fb': [9.11628054e-002, 5.06776025e-001, 5.89590381e+000],
1975
- 'fc': [6.48028962e-001, 2.60380817e-003, 1.13887493e-001],
1976
- 'fd': [1.46634108e+000, 7.84336311e-003, 1.55114340e-001]},
1977
- 'Tc': {'Z': 43, 'chisq': 0.023771,
1978
- 'bond_length': [1.56, 1.36, 1.70, 0],
1979
- 'fa': [8.55189183e-001, 1.66219641e+000, 1.45575475e+000],
1980
- 'fb': [1.02962151e-001, 7.64907000e+000, 1.01639987e+000],
1981
- 'fc': [1.05445664e-001, 7.71657112e-001, 2.20992635e-003],
1982
- 'fd': [1.42303338e-001, 1.34659349e+000, 7.90358976e-003]},
1983
- 'Ru': {'Z': 44, 'chisq': 0.010613,
1984
- 'bond_length': [1.54, 1.34, 1.70, 0],
1985
- 'fa': [4.70847093e-001, 1.58180781e+000, 2.02419818e+000],
1986
- 'fb': [9.33029874e-002, 4.52831347e-001, 7.11489023e+000],
1987
- 'fc': [1.97036257e-003, 6.26912639e-001, 1.02641320e-001],
1988
- 'fd': [7.56181595e-003, 1.25399858e+000, 1.33786087e-001]},
1989
- 'Rh': {'Z': 45, 'chisq': 0.012895,
1990
- 'bond_length': [1.54, 1.34, 1.70, 0],
1991
- 'fa': [4.20051553e-001, 1.76266507e+000, 2.02735641e+000],
1992
- 'fb': [9.38882628e-002, 4.64441687e-001, 8.19346046e+000],
1993
- 'fc': [1.45487176e-003, 6.22809600e-001, 9.91529915e-002],
1994
- 'fd': [7.82704517e-003, 1.17194153e+000, 1.24532839e-001]},
1995
- 'Pd': {'Z': 46, 'chisq': 0.009172,
1996
- 'bond_length': [1.58, 1.38, 1.63, 0],
1997
- 'fa': [2.10475155e+000, 2.03884487e+000, 1.82067264e-001],
1998
- 'fb': [8.68606470e+000, 3.78924449e-001, 1.42921634e-001],
1999
- 'fc': [9.52040948e-002, 5.91445248e-001, 1.13328676e-003],
2000
- 'fd': [1.17125900e-001, 1.07843808e+000, 7.80252092e-003]},
2001
- 'Ag': {'Z': 47, 'chisq': 0.006648,
2002
- 'bond_length': [1.64, 1.44, 1.72, 0],
2003
- 'fa': [2.07981390e+000, 4.43170726e-001, 1.96515215e+000],
2004
- 'fb': [9.92540297e+000, 1.04920104e-001, 6.40103839e-001],
2005
- 'fc': [5.96130591e-001, 4.78016333e-001, 9.46458470e-002],
2006
- 'fd': [8.89594790e-001, 1.98509407e+000, 1.12744464e-001]},
2007
- 'Cd': {'Z': 48, 'chisq': 0.005588,
2008
- 'bond_length': [1.77, 1.57, 1.58, 0],
2009
- 'fa': [1.63657549e+000, 2.17927989e+000, 7.71300690e-001],
2010
- 'fb': [1.24540381e+001, 1.45134660e+000, 1.26695757e-001],
2011
- 'fc': [6.64193880e-001, 7.64563285e-001, 8.61126689e-002],
2012
- 'fd': [7.77659202e-001, 1.66075210e+000, 1.05728357e-001]},
2013
- 'In': {'Z': 49, 'chisq': 0.002569,
2014
- 'bond_length': [1.86, 1.66, 1.93, 0],
2015
- 'fa': [2.24820632e+000, 1.64706864e+000, 7.88679265e-001],
2016
- 'fb': [1.51913507e+000, 1.30113424e+001, 1.06128184e-001],
2017
- 'fc': [8.12579069e-002, 6.68280346e-001, 6.38467475e-001],
2018
- 'fd': [9.94045620e-002, 1.49742063e+000, 7.18422635e-001]},
2019
- 'Sn': {'Z': 50, 'chisq': 0.005051,
2020
- 'bond_length': [1.82, 1.62, 2.17, 0],
2021
- 'fa': [2.16644620e+000, 6.88691021e-001, 1.92431751e+000],
2022
- 'fb': [1.13174909e+001, 1.10131285e-001, 6.74464853e-001],
2023
- 'fc': [5.65359888e-001, 9.18683861e-001, 7.80542213e-002],
2024
- 'fd': [7.33564610e-001, 1.02310312e+001, 9.31104308e-002]},
2025
- 'Sb': {'Z': 51, 'chisq': 0.004383,
2026
- 'bond_length': [1.79, 1.59, 2.20, 0],
2027
- 'fa': [1.73662114e+000, 9.99871380e-001, 2.13972409e+000],
2028
- 'fb': [8.84334719e-001, 1.38462121e-001, 1.19666432e+001],
2029
- 'fc': [5.60566526e-001, 9.93772747e-001, 7.37374982e-002],
2030
- 'fd': [6.72672880e-001, 8.72330411e+000, 8.78577715e-002]},
2031
- 'Te': {'Z': 52, 'chisq': 0.004105,
2032
- 'bond_length': [1.80, 1.60, 2.06, 0],
2033
- 'fa': [2.09383882e+000, 1.56940519e+000, 1.30941993e+000],
2034
- 'fb': [1.26856869e+001, 1.21236537e+000, 1.66633292e-001],
2035
- 'fc': [6.98067804e-002, 1.04969537e+000, 5.55594354e-001],
2036
- 'fd': [8.30817576e-002, 7.43147857e+000, 6.17487676e-001]},
2037
- 'I': {'Z': 53, 'chisq': 0.004068,
2038
- 'bond_length': [1.90, 1.70, 2.15, 0],
2039
- 'fa': [1.60186925e+000, 1.98510264e+000, 1.48226200e+000],
2040
- 'fb': [1.95031538e-001, 1.36976183e+001, 1.80304795e+000],
2041
- 'fc': [5.53807199e-001, 1.11728722e+000, 6.60720847e-002],
2042
- 'fd': [5.67912340e-001, 6.40879878e+000, 7.86615429e-002]},
2043
- 'Xe': {'Z': 54, 'chisq': 0.004381,
2044
- 'bond_length': [2.30, 2.10, 2.16, 0],
2045
- 'fa': [1.60015487e+000, 1.71644581e+000, 1.84968351e+000],
2046
- 'fb': [2.92913354e+000, 1.55882990e+001, 2.22525983e-001],
2047
- 'fc': [6.23813648e-002, 1.21387555e+000, 5.54051946e-001],
2048
- 'fd': [7.45581223e-002, 5.56013271e+000, 5.21994521e-001]},
2049
- 'Cs': {'Z': 55, 'chisq': 0.042676,
2050
- 'bond_length': [2.93, 2.73, 1.70, 0],
2051
- 'fa': [2.95236854e+000, 4.28105721e-001, 1.89599233e+000],
2052
- 'fb': [6.01461952e+000, 4.64151246e+001, 1.80109756e-001],
2053
- 'fc': [5.48012938e-002, 4.70838600e+000, 5.90356719e-001],
2054
- 'fd': [7.12799633e-002, 4.56702799e+001, 4.70236310e-001]},
2055
- 'Ba': {'Z': 56, 'chisq': 0.043267,
2056
- 'bond_length': [2.44, 2.24, 1.70, 0],
2057
- 'fa': [3.19434243e+000, 1.98289586e+000, 1.55121052e-001],
2058
- 'fb': [9.27352241e+000, 2.28741632e-001, 3.82000231e-002],
2059
- 'fc': [6.73222354e-002, 4.48474211e+000, 5.42674414e-001],
2060
- 'fd': [7.30961745e-002, 2.95703565e+001, 4.08647015e-001]},
2061
- 'La': {'Z': 57, 'chisq': 0.033249,
2062
- 'bond_length': [2.08, 1.88, 1.70, 0],
2063
- 'fa': [2.05036425e+000, 1.42114311e-001, 3.23538151e+000],
2064
- 'fb': [2.20348417e-001, 3.96438056e-002, 9.56979169e+000],
2065
- 'fc': [6.34683429e-002, 3.97960586e+000, 5.20116711e-001],
2066
- 'fd': [6.92443091e-002, 2.53178406e+001, 3.83614098e-001]},
2067
- 'Ce': {'Z': 58, 'chisq': 0.029355,
2068
- 'bond_length': [2.02, 1.82, 1.70, 0],
2069
- 'fa': [3.22990759e+000, 1.57618307e-001, 2.13477838e+000],
2070
- 'fb': [9.94660135e+000, 4.15378676e-002, 2.40480572e-001],
2071
- 'fc': [5.01907609e-001, 3.80889010e+000, 5.96625028e-002],
2072
- 'fd': [3.66252019e-001, 2.43275968e+001, 6.59653503e-002]},
2073
- 'Pr': {'Z': 59, 'chisq': 0.029725,
2074
- 'bond_length': [2.03, 1.83, 1.70, 0],
2075
- 'fa': [1.58189324e-001, 3.18141995e+000, 2.27622140e+000],
2076
- 'fb': [3.91309056e-002, 1.04139545e+001, 2.81671757e-001],
2077
- 'fc': [3.97705472e+000, 5.58448277e-002, 4.85207954e-001],
2078
- 'fd': [2.61872978e+001, 6.30921695e-002, 3.54234369e-001]},
2079
- 'Nd': {'Z': 60, 'chisq': 0.027597,
2080
- 'bond_length': [2.02, 1.82, 1.70, 0],
2081
- 'fa': [1.81379417e-001, 3.17616396e+000, 2.35221519e+000],
2082
- 'fb': [4.37324793e-002, 1.07842572e+001, 3.05571833e-001],
2083
- 'fc': [3.83125763e+000, 5.25889976e-002, 4.70090742e-001],
2084
- 'fd': [2.54745408e+001, 6.02676073e-002, 3.39017003e-001]},
2085
- 'Pm': {'Z': 61, 'chisq': 0.025208,
2086
- 'bond_length': [2.01, 1.81, 1.70, 0],
2087
- 'fa': [1.92986811e-001, 2.43756023e+000, 3.17248504e+000],
2088
- 'fb': [4.37785970e-002, 3.29336996e-001, 1.11259996e+001],
2089
- 'fc': [3.58105414e+000, 4.56529394e-001, 4.94812177e-002],
2090
- 'fd': [2.46709586e+001, 3.24990282e-001, 5.76553100e-002]},
2091
- 'Sm': {'Z': 62, 'chisq': 0.023540,
2092
- 'bond_length': [2.00, 1.80, 1.70, 0],
2093
- 'fa': [2.12002595e-001, 3.16891754e+000, 2.51503494e+000],
2094
- 'fb': [4.57703608e-002, 1.14536599e+001, 3.55561054e-001],
2095
- 'fc': [4.44080845e-001, 3.36742101e+000, 4.65652543e-002],
2096
- 'fd': [3.11953363e-001, 2.40291435e+001, 5.52266819e-002]},
2097
- 'Eu': {'Z': 63, 'chisq': 0.022204,
2098
- 'bond_length': [2.24, 2.04, 1.70, 0],
2099
- 'fa': [2.59355002e+000, 3.16557522e+000, 2.29402652e-001],
2100
- 'fb': [3.82452612e-001, 1.17675155e+001, 4.76642249e-002],
2101
- 'fc': [4.32257780e-001, 3.17261920e+000, 4.37958317e-002],
2102
- 'fd': [2.99719833e-001, 2.34462738e+001, 5.29440680e-002]},
2103
- 'Gd': {'Z': 64, 'chisq': 0.017492,
2104
- 'bond_length': [2.00, 1.80, 1.70, 0],
2105
- 'fa': [3.19144939e+000, 2.55766431e+000, 3.32681934e-001],
2106
- 'fb': [1.20224655e+001, 4.08338876e-001, 5.85819814e-002],
2107
- 'fc': [4.14243130e-002, 2.61036728e+000, 4.20526863e-001],
2108
- 'fd': [5.06771477e-002, 1.99344244e+001, 2.85686240e-001]},
2109
- 'Tb': {'Z': 65, 'chisq': 0.020036,
2110
- 'bond_length': [1.98, 1.78, 1.70, 0],
2111
- 'fa': [2.59407462e-001, 3.16177855e+000, 2.75095751e+000],
2112
- 'fb': [5.04689354e-002, 1.23140183e+001, 4.38337626e-001],
2113
- 'fc': [2.79247686e+000, 3.85931001e-002, 4.10881708e-001],
2114
- 'fd': [2.23797309e+001, 4.87920992e-002, 2.77622892e-001]},
2115
- 'Dy': {'Z': 66, 'chisq': 0.019351,
2116
- 'bond_length': [1.97, 1.77, 1.70, 0],
2117
- 'fa': [3.16055396e+000, 2.82751709e+000, 2.75140255e-001],
2118
- 'fb': [1.25470414e+001, 4.67899094e-001, 5.23226982e-002],
2119
- 'fc': [4.00967160e-001, 2.63110834e+000, 3.61333817e-002],
2120
- 'fd': [2.67614884e-001, 2.19498166e+001, 4.68871497e-002]},
2121
- 'Ho': {'Z': 67, 'chisq': 0.018720,
2122
- 'bond_length': [1.98, 1.78, 1.70, 0],
2123
- 'fa': [2.88642467e-001, 2.90567296e+000, 3.15960159e+000],
2124
- 'fb': [5.40507687e-002, 4.97581077e-001, 1.27599505e+001],
2125
- 'fc': [3.91280259e-001, 2.48596038e+000, 3.37664478e-002],
2126
- 'fd': [2.58151831e-001, 2.15400972e+001, 4.50664323e-002]},
2127
- 'Er': {'Z': 68, 'chisq': 0.018677,
2128
- 'bond_length': [1.96, 1.76, 1.70, 0],
2129
- 'fa': [3.15573213e+000, 3.11519560e-001, 2.97722406e+000],
2130
- 'fb': [1.29729009e+001, 5.81399387e-002, 5.31213394e-001],
2131
- 'fc': [3.81563854e-001, 2.40247532e+000, 3.15224214e-002],
2132
- 'fd': [2.49195776e-001, 2.13627616e+001, 4.33253257e-002]},
2133
- 'Tm': {'Z': 69, 'chisq': 0.018176,
2134
- 'bond_length': [1.95, 1.75, 1.70, 0],
2135
- 'fa': [3.15591970e+000, 3.22544710e-001, 3.05569053e+000],
2136
- 'fb': [1.31232407e+001, 5.97223323e-002, 5.61876773e-001],
2137
- 'fc': [2.92845100e-002, 3.72487205e-001, 2.27833695e+000],
2138
- 'fd': [4.16534255e-002, 2.40821967e-001, 2.10034185e+001]},
2139
- 'Yb': {'Z': 70, 'chisq': 0.018460,
2140
- 'bond_length': [2.10, 1.90, 1.70, 0],
2141
- 'fa': [3.10794704e+000, 3.14091221e+000, 3.75660454e-001],
2142
- 'fb': [6.06347847e-001, 1.33705269e+001, 7.29814740e-002],
2143
- 'fc': [3.61901097e-001, 2.45409082e+000, 2.72383990e-002],
2144
- 'fd': [2.32652051e-001, 2.12695209e+001, 3.99969597e-002]},
2145
- 'Lu': {'Z': 71, 'chisq': 0.015021,
2146
- 'bond_length': [1.93, 1.73, 1.70, 0],
2147
- 'fa': [3.11446863e+000, 5.39634353e-001, 3.06460915e+000],
2148
- 'fb': [1.38968881e+001, 8.91708508e-002, 6.79919563e-001],
2149
- 'fc': [2.58563745e-002, 2.13983556e+000, 3.47788231e-001],
2150
- 'fd': [3.82808522e-002, 1.80078788e+001, 2.22706591e-001]},
2151
- 'Hf': {'Z': 72, 'chisq': 0.012070,
2152
- 'bond_length': [1.78, 1.58, 1.70, 0],
2153
- 'fa': [3.01166899e+000, 3.16284788e+000, 6.33421771e-001],
2154
- 'fb': [7.10401889e-001, 1.38262192e+001, 9.48486572e-002],
2155
- 'fc': [3.41417198e-001, 1.53566013e+000, 2.40723773e-002],
2156
- 'fd': [2.14129678e-001, 1.55298698e+001, 3.67833690e-002]},
2157
- 'Ta': {'Z': 73, 'chisq': 0.010775,
2158
- 'bond_length': [1.67, 1.47, 1.70, 0],
2159
- 'fa': [3.20236821e+000, 8.30098413e-001, 2.86552297e+000],
2160
- 'fb': [1.38446369e+001, 1.18381581e-001, 7.66369118e-001],
2161
- 'fc': [2.24813887e-002, 1.40165263e+000, 3.33740596e-001],
2162
- 'fd': [3.52934622e-002, 1.46148877e+001, 2.05704486e-001]},
2163
- 'W': {'Z': 74, 'chisq': 0.009479,
2164
- 'bond_length': [1.61, 1.41, 1.70, 0],
2165
- 'fa': [9.24906855e-001, 2.75554557e+000, 3.30440060e+000],
2166
- 'fb': [1.28663377e-001, 7.65826479e-001, 1.34471170e+001],
2167
- 'fc': [3.29973862e-001, 1.09916444e+000, 2.06498883e-002],
2168
- 'fd': [1.98218895e-001, 1.35087534e+001, 3.38918459e-002]},
2169
- 'Re': {'Z': 75, 'chisq': 0.004620,
2170
- 'bond_length': [1.58, 1.38, 1.70, 0],
2171
- 'fa': [1.96952105e+000, 1.21726619e+000, 4.10391685e+000],
2172
- 'fb': [4.98830620e+001, 1.33243809e-001, 1.84396916e+000],
2173
- 'fc': [2.90791978e-002, 2.30696669e-001, 6.08840299e-001],
2174
- 'fd': [2.84192813e-002, 1.90968784e-001, 1.37090356e+000]},
2175
- 'Os': {'Z': 76, 'chisq': 0.003085,
2176
- 'bond_length': [1.55, 1.35, 1.70, 0],
2177
- 'fa': [2.06385867e+000, 1.29603406e+000, 3.96920673e+000],
2178
- 'fb': [4.05671697e+001, 1.46559047e-001, 1.82561596e+000],
2179
- 'fc': [2.69835487e-002, 2.31083999e-001, 6.30466774e-001],
2180
- 'fd': [2.84172045e-002, 1.79765184e-001, 1.38911543e+000]},
2181
- 'Ir': {'Z': 77, 'chisq': 0.003924,
2182
- 'bond_length': [1.56, 1.36, 1.70, 0],
2183
- 'fa': [2.21522726e+000, 1.37573155e+000, 3.78244405e+000],
2184
- 'fb': [3.24464090e+001, 1.60920048e-001, 1.78756553e+000],
2185
- 'fc': [2.44643240e-002, 2.36932016e-001, 6.48471412e-001],
2186
- 'fd': [2.82909938e-002, 1.70692368e-001, 1.37928390e+000]},
2187
- 'Pt': {'Z': 78, 'chisq': 0.003817,
2188
- 'bond_length': [1.59, 1.39, 1.72, 0],
2189
- 'fa': [9.84697940e-001, 2.73987079e+000, 3.61696715e+000],
2190
- 'fb': [1.60910839e-001, 7.18971667e-001, 1.29281016e+001],
2191
- 'fc': [3.02885602e-001, 2.78370726e-001, 1.52124129e-002],
2192
- 'fd': [1.70134854e-001, 1.49862703e+000, 2.83510822e-002]},
2193
- 'Au': {'Z': 79, 'chisq': 0.003143,
2194
- 'bond_length': [1.64, 1.44, 1.66, 0],
2195
- 'fa': [9.61263398e-001, 3.69581030e+000, 2.77567491e+000],
2196
- 'fb': [1.70932277e-001, 1.29335319e+001, 6.89997070e-001],
2197
- 'fc': [2.95414176e-001, 3.11475743e-001, 1.43237267e-002],
2198
- 'fd': [1.63525510e-001, 1.39200901e+000, 2.71265337e-002]},
2199
- 'Hg': {'Z': 80, 'chisq': 0.002717,
2200
- 'bond_length': [1.77, 1.57, 1.55, 0],
2201
- 'fa': [1.29200491e+000, 2.75161478e+000, 3.49387949e+000],
2202
- 'fb': [1.83432865e-001, 9.42368371e-001, 1.46235654e+001],
2203
- 'fc': [2.77304636e-001, 4.30232810e-001, 1.48294351e-002],
2204
- 'fd': [1.55110144e-001, 1.28871670e+000, 2.61903834e-002]},
2205
- 'Tl': {'Z': 81, 'chisq': 0.003492,
2206
- 'bond_length': [1.92, 1.72, 1.96, 0],
2207
- 'fa': [3.75964730e+000, 3.21195904e+000, 6.47767825e-001],
2208
- 'fb': [1.35041513e+001, 6.66330993e-001, 9.22518234e-002],
2209
- 'fc': [2.76123274e-001, 3.18838810e-001, 1.31668419e-002],
2210
- 'fd': [1.50312897e-001, 1.12565588e+000, 2.48879842e-002]},
2211
- 'Pb': {'Z': 82, 'chisq': 0.001158,
2212
- 'bond_length': [1.95, 1.75, 2.02, 0],
2213
- 'fa': [1.00795975e+000, 3.09796153e+000, 3.61296864e+000],
2214
- 'fb': [1.17268427e-001, 8.80453235e-001, 1.47325812e+001],
2215
- 'fc': [2.62401476e-001, 4.05621995e-001, 1.31812509e-002],
2216
- 'fd': [1.43491014e-001, 1.04103506e+000, 2.39575415e-002]},
2217
- 'Bi': {'Z': 83, 'chisq': 0.026436,
2218
- 'bond_length': [1.90, 1.70, 1.70, 0],
2219
- 'fa': [1.59826875e+000, 4.38233925e+000, 2.06074719e+000],
2220
- 'fb': [1.56897471e-001, 2.47094692e+000, 5.72438972e+001],
2221
- 'fc': [1.94426023e-001, 8.22704978e-001, 2.33226953e-002],
2222
- 'fd': [1.32979109e-001, 9.56532528e-001, 2.23038435e-002]},
2223
- 'Po': {'Z': 84, 'chisq': 0.008962,
2224
- 'bond_length': [1.96, 1.76, 1.70, 0],
2225
- 'fa': [1.71463223e+000, 2.14115960e+000, 4.37512413e+000],
2226
- 'fb': [9.79262841e+001, 2.10193717e-001, 3.66948812e+000],
2227
- 'fc': [2.16216680e-002, 1.97843837e-001, 6.52047920e-001],
2228
- 'fd': [1.98456144e-002, 1.33758807e-001, 7.80432104e-001]},
2229
- 'At': {'Z': 85, 'chisq': 0.033776,
2230
- 'bond_length': [2.00, 1.80, 1.70, 0],
2231
- 'fa': [1.48047794e+000, 2.09174630e+000, 4.75246033e+000],
2232
- 'fb': [1.25943919e+002, 1.83803008e-001, 4.19890596e+000],
2233
- 'fc': [1.85643958e-002, 2.05859375e-001, 7.13540948e-001],
2234
- 'fd': [1.81383503e-002, 1.33035404e-001, 7.03031938e-001]},
2235
- 'Rn': {'Z': 86, 'chisq': 0.050132,
2236
- 'bond_length': [2.40, 2.20, 1.70, 0],
2237
- 'fa': [6.30022295e-001, 3.80962881e+000, 3.89756067e+000],
2238
- 'fb': [1.40909762e-001, 3.08515540e+001, 6.51559763e-001],
2239
- 'fc': [2.40755100e-001, 2.62868577e+000, 3.14285931e-002],
2240
- 'fd': [1.08899672e-001, 6.42383261e+000, 2.42346699e-002]},
2241
- 'Fr': {'Z': 87, 'chisq': 0.056720,
2242
- 'bond_length': [3.00, 2.80, 1.70, 0],
2243
- 'fa': [5.23288135e+000, 2.48604205e+000, 3.23431354e-001],
2244
- 'fb': [8.60599536e+000, 3.04543982e-001, 3.87759096e-002],
2245
- 'fc': [2.55403596e-001, 5.53607228e-001, 5.75278889e-003],
2246
- 'fd': [1.28717724e-001, 5.36977452e-001, 1.29417790e-002]},
2247
- 'Ra': {'Z': 88, 'chisq': 0.081498,
2248
- 'bond_length': [2.46, 2.26, 1.70, 0],
2249
- 'fa': [1.44192685e+000, 3.55291725e+000, 3.91259586e+000],
2250
- 'fb': [1.18740873e-001, 1.01739750e+000, 6.31814783e+001],
2251
- 'fc': [2.16173519e-001, 3.94191605e+000, 4.60422605e-002],
2252
- 'fd': [9.55806441e-002, 3.50602732e+001, 2.20850385e-002]},
2253
- 'Ac': {'Z': 89, 'chisq': 0.077643,
2254
- 'bond_length': [2.09, 1.88, 1.70, 0],
2255
- 'fa': [1.45864127e+000, 4.18945405e+000, 3.65866182e+000],
2256
- 'fb': [1.07760494e-001, 8.89090649e+001, 1.05088931e+000],
2257
- 'fc': [2.08479229e-001, 3.16528117e+000, 5.23892556e-002],
2258
- 'fd': [9.09335557e-002, 3.13297788e+001, 2.08807697e-002]},
2259
- 'Th': {'Z': 90, 'chisq': 0.048096,
2260
- 'bond_length': [2.00, 1.80, 1.70, 0],
2261
- 'fa': [1.19014064e+000, 2.55380607e+000, 4.68110181e+000],
2262
- 'fb': [7.73468729e-002, 6.59693681e-001, 1.28013896e+001],
2263
- 'fc': [2.26121303e-001, 3.58250545e-001, 7.82263950e-003],
2264
- 'fd': [1.08632194e-001, 4.56765664e-001, 1.62623474e-002]},
2265
- 'Pa': {'Z': 91, 'chisq': 0.070186,
2266
- 'bond_length': [1.83, 1.63, 1.70, 0],
2267
- 'fa': [4.68537504e+000, 2.98413708e+000, 8.91988061e-001],
2268
- 'fb': [1.44503632e+001, 5.56438592e-001, 6.69512914e-002],
2269
- 'fc': [2.24825384e-001, 3.04444846e-001, 9.48162708e-003],
2270
- 'fd': [1.03235396e-001, 4.27255647e-001, 1.77730611e-002]},
2271
- 'U': {'Z': 92, 'chisq': 0.072478,
2272
- 'bond_length': [1.76, 1.56, 1.86, 0],
2273
- 'fa': [4.63343606e+000, 3.18157056e+000, 8.76455075e-001],
2274
- 'fb': [1.63377267e+001, 5.69517868e-001, 6.88860012e-002],
2275
- 'fc': [2.21685477e-001, 2.72917100e-001, 1.11737298e-002],
2276
- 'fd': [9.84254550e-002, 4.09470917e-001, 1.86215410e-002]},
2277
- 'Np': {'Z': 93, 'chisq': 0.074792,
2278
- 'bond_length': [1.80, 1.60, 1.70, 0],
2279
- 'fa': [4.56773888e+000, 3.40325179e+000, 8.61841923e-001],
2280
- 'fb': [1.90992795e+001, 5.90099634e-001, 7.03204851e-002],
2281
- 'fc': [2.19728870e-001, 2.38176903e-001, 1.38306499e-002],
2282
- 'fd': [9.36334280e-002, 3.93554882e-001, 1.94437286e-002]},
2283
- 'Pu': {'Z': 94, 'chisq': 0.071877,
2284
- 'bond_length': [1.84, 1.64, 1.70, 0],
2285
- 'fa': [5.45671123e+000, 1.11687906e-001, 3.30260343e+000],
2286
- 'fb': [1.01892720e+001, 3.98131313e-002, 3.14622212e-001],
2287
- 'fc': [1.84568319e-001, 4.93644263e-001, 3.57484743e+000],
2288
- 'fd': [1.04220860e-001, 4.63080540e-001, 2.19369542e+001]},
2289
- 'Am': {'Z': 95, 'chisq': 0.062156,
2290
- 'bond_length': [2.01, 1.81, 1.70, 0],
2291
- 'fa': [5.38321999e+000, 1.23343236e-001, 3.46469090e+000],
2292
- 'fb': [1.07289857e+001, 4.15137806e-002, 3.39326208e-001],
2293
- 'fc': [1.75437132e-001, 3.39800073e+000, 4.69459519e-001],
2294
- 'fd': [9.98932346e-002, 2.11601535e+001, 4.51996970e-001]},
2295
- 'Cm': {'Z': 96, 'chisq': 0.050111,
2296
- 'bond_length': [2.20, 2.00, 1.70, 0],
2297
- 'fa': [5.38402377e+000, 3.49861264e+000, 1.88039547e-001],
2298
- 'fb': [1.11211419e+001, 3.56750210e-001, 5.39853583e-002],
2299
- 'fc': [1.69143137e-001, 3.19595016e+000, 4.64393059e-001],
2300
- 'fd': [9.60082633e-002, 1.80694389e+001, 4.36318197e-001]},
2301
- 'Bk': {'Z': 97, 'chisq': 0.044081,
2302
- 'bond_length': [2.20, 2.00, 1.70, 0],
2303
- 'fa': [3.66090688e+000, 2.03054678e-001, 5.30697515e+000],
2304
- 'fb': [3.84420906e-001, 5.48547131e-002, 1.17150262e+001],
2305
- 'fc': [1.60934046e-001, 3.04808401e+000, 4.43610295e-001],
2306
- 'fd': [9.21020329e-002, 1.73525367e+001, 4.27132359e-001]},
2307
- 'Cf': {'Z': 98, 'chisq': 0.041053,
2308
- 'bond_length': [2.20, 2.00, 1.70, 0],
2309
- 'fa': [3.94150390e+000, 5.16915345e+000, 1.61941074e-001],
2310
- 'fb': [4.18246722e-001, 1.25201788e+001, 4.81540117e-002],
2311
- 'fc': [4.15299561e-001, 2.91761325e+000, 1.51474927e-001],
2312
- 'fd': [4.24913856e-001, 1.90899693e+001, 8.81568925e-002]}
2313
- }
2314
-
2315
-
2316
- # From Appendix C of Kirkland, "Advanced Computing in Electron Microscopy", 2nd ed.
2317
- # Calculation of electron form factor for specific q:
2318
- # Using equation Kirkland C.15
2319
-
2320
- def feq(element, q):
2321
- # form factor parametrized in 1/Angstrom
2322
- # but we think in 1/nm
2323
- q = q/10
2324
- # q is now magnitude of scattering vector in 1/A -- (=> exp(-i*g.r), physics negative convention)
2325
- param = electronFF[element]
2326
- fL = 0
2327
- fG = 0
2328
- for i in range(3):
2329
- fL += param['fa'][i]/(q**2 + param['fb'][i])
2330
- fG += param['fc'][i]*np.exp(-q**2 * param['fd'][i])
2331
-
2332
- # Conversion factor from scattering factors to volts. h^2/(2pi*m0*e), see e.g. Kirkland eqn. C.5
2333
- # !NB RVolume is already in A unlike RPlanckConstant
2334
- # ScattFacToVolts=(PlanckConstant**2)*(AngstromConversion**2)/(2*np.pi*ElectronMass*ElectronCharge)
2335
- return fL+fG # * ScattFacToVolts
2336
-
2337
-
2338
- # Jmol colors. See: http://jmol.sourceforge.net/jscolors/#color_U
2339
- jmol_colors = np.array([
2340
- (1.000, 0.000, 0.000), # None1.000,1.000,1.000), # H
2341
- (0.851, 1.000, 1.000), # He
2342
- (0.800, 0.502, 1.000), # Li
2343
- (0.761, 1.000, 0.000), # Be
2344
- (1.000, 0.710, 0.710), # B
2345
- (0.565, 0.565, 0.565), # C
2346
- (0.188, 0.314, 0.973), # N
2347
- (1.000, 0.051, 0.051), # O
2348
- (0.565, 0.878, 0.314), # F
2349
- (0.702, 0.890, 0.961), # Ne
2350
- (0.671, 0.361, 0.949), # Na
2351
- (0.541, 1.000, 0.000), # Mg
2352
- (0.749, 0.651, 0.651), # Al
2353
- (0.941, 0.784, 0.627), # Si
2354
- (1.000, 0.502, 0.000), # P
2355
- (1.000, 1.000, 0.188), # S
2356
- (0.122, 0.941, 0.122), # Cl
2357
- (0.502, 0.820, 0.890), # Ar
2358
- (0.561, 0.251, 0.831), # K
2359
- (0.239, 1.000, 0.000), # Ca
2360
- (0.902, 0.902, 0.902), # Sc
2361
- (0.749, 0.761, 0.780), # Ti
2362
- (0.651, 0.651, 0.671), # V
2363
- (0.541, 0.600, 0.780), # Cr
2364
- (0.612, 0.478, 0.780), # Mn
2365
- (0.878, 0.400, 0.200), # Fe
2366
- (0.941, 0.565, 0.627), # Co
2367
- (0.314, 0.816, 0.314), # Ni
2368
- (0.784, 0.502, 0.200), # Cu
2369
- (0.490, 0.502, 0.690), # Zn
2370
- (0.761, 0.561, 0.561), # Ga
2371
- (0.400, 0.561, 0.561), # Ge
2372
- (0.741, 0.502, 0.890), # As
2373
- (1.000, 0.631, 0.000), # Se
2374
- (0.651, 0.161, 0.161), # Br
2375
- (0.361, 0.722, 0.820), # Kr
2376
- (0.439, 0.180, 0.690), # Rb
2377
- (0.000, 1.000, 0.000), # Sr
2378
- (0.580, 1.000, 1.000), # Y
2379
- (0.580, 0.878, 0.878), # Zr
2380
- (0.451, 0.761, 0.788), # Nb
2381
- (0.329, 0.710, 0.710), # Mo
2382
- (0.231, 0.620, 0.620), # Tc
2383
- (0.141, 0.561, 0.561), # Ru
2384
- (0.039, 0.490, 0.549), # Rh
2385
- (0.000, 0.412, 0.522), # Pd
2386
- (0.753, 0.753, 0.753), # Ag
2387
- (1.000, 0.851, 0.561), # Cd
2388
- (0.651, 0.459, 0.451), # In
2389
- (0.400, 0.502, 0.502), # Sn
2390
- (0.620, 0.388, 0.710), # Sb
2391
- (0.831, 0.478, 0.000), # Te
2392
- (0.580, 0.000, 0.580), # I
2393
- (0.259, 0.620, 0.690), # Xe
2394
- (0.341, 0.090, 0.561), # Cs
2395
- (0.000, 0.788, 0.000), # Ba
2396
- (0.439, 0.831, 1.000), # La
2397
- (1.000, 1.000, 0.780), # Ce
2398
- (0.851, 1.000, 0.780), # Pr
2399
- (0.780, 1.000, 0.780), # Nd
2400
- (0.639, 1.000, 0.780), # Pm
2401
- (0.561, 1.000, 0.780), # Sm
2402
- (0.380, 1.000, 0.780), # Eu
2403
- (0.271, 1.000, 0.780), # Gd
2404
- (0.188, 1.000, 0.780), # Tb
2405
- (0.122, 1.000, 0.780), # Dy
2406
- (0.000, 1.000, 0.612), # Ho
2407
- (0.000, 0.902, 0.459), # Er
2408
- (0.000, 0.831, 0.322), # Tm
2409
- (0.000, 0.749, 0.220), # Yb
2410
- (0.000, 0.671, 0.141), # Lu
2411
- (0.302, 0.761, 1.000), # Hf
2412
- (0.302, 0.651, 1.000), # Ta
2413
- (0.129, 0.580, 0.839), # W
2414
- (0.149, 0.490, 0.671), # Re
2415
- (0.149, 0.400, 0.588), # Os
2416
- (0.090, 0.329, 0.529), # Ir
2417
- (0.816, 0.816, 0.878), # Pt
2418
- (1.000, 0.820, 0.137), # Au
2419
- (0.722, 0.722, 0.816), # Hg
2420
- (0.651, 0.329, 0.302), # Tl
2421
- (0.341, 0.349, 0.380), # Pb
2422
- (0.620, 0.310, 0.710), # Bi
2423
- (0.671, 0.361, 0.000), # Po
2424
- (0.459, 0.310, 0.271), # At
2425
- (0.259, 0.510, 0.588), # Rn
2426
- (0.259, 0.000, 0.400), # Fr
2427
- (0.000, 0.490, 0.000), # Ra
2428
- (0.439, 0.671, 0.980), # Ac
2429
- (0.000, 0.729, 1.000), # Th
2430
- (0.000, 0.631, 1.000), # Pa
2431
- (0.000, 0.561, 1.000), # U
2432
- (0.000, 0.502, 1.000), # Np
2433
- (0.000, 0.420, 1.000), # Pu
2434
- (0.329, 0.361, 0.949), # Am
2435
- (0.471, 0.361, 0.890), # Cm
2436
- (0.541, 0.310, 0.890), # Bk
2437
- (0.631, 0.212, 0.831), # Cf
2438
- (0.702, 0.122, 0.831), # Es
2439
- (0.702, 0.122, 0.729), # Fm
2440
- (0.702, 0.051, 0.651), # Md
2441
- (0.741, 0.051, 0.529), # No
2442
- (0.780, 0.000, 0.400), # Lr
2443
- (0.800, 0.000, 0.349), # Rf
2444
- (0.820, 0.000, 0.310), # Db
2445
- (0.851, 0.000, 0.271), # Sg
2446
- (0.878, 0.000, 0.220), # Bh
2447
- (0.902, 0.000, 0.180), # Hs
2448
- (0.922, 0.000, 0.149), # Mt
2449
- ])
2450
-
2451
- # encoding: utf-8
2452
- # crystal data base cbd
2453
- cdb = {'aluminum': {}}
2454
- cdb['aluminum']['crystal_name'] = 'aluminum'
2455
- cdb['aluminum']['symmetry'] = 'FCC'
2456
- cdb['aluminum']['elements'] = ['Al']
2457
- cdb['aluminum']['a'] = 0.405 # nm
2458
- cdb['aluminum']['reference'] = 'W. Witt, Z. Naturforsch. A, 1967, 22A, 92'
2459
- cdb['aluminum']['link'] = 'http://doi.org/10.1515/zna-1967-0115'
2460
- cdb['Al'] = cdb['Aluminum'] = cdb['aluminum']
2461
-
2462
- cdb['gold'] = {}
2463
- cdb['gold']['crystal_name'] = 'gold'
2464
- cdb['gold']['symmetry'] = 'FCC'
2465
- cdb['gold']['elements'] = ['Au']
2466
- cdb['gold']['a'] = 0.40782 # nm
2467
- cdb['gold']['reference'] = ''
2468
- cdb['gold']['link'] = ''
2469
- cdb['Au'] = cdb['Gold'] = cdb['gold']
2470
-
2471
- cdb['silver'] = {}
2472
- cdb['silver']['crystal_name'] = 'silver'
2473
- cdb['silver']['symmetry'] = 'FCC'
2474
- cdb['silver']['elements'] = ['Ag']
2475
- cdb['silver']['a'] = 0.40853 # nm
2476
- cdb['silver']['reference'] = ''
2477
- cdb['silver']['link'] = ''
2478
- cdb['Ag'] = cdb['Silver'] = cdb['silver']
2479
-
2480
- cdb['diamond'] = {}
2481
- cdb['diamond']['crystal_name'] = 'diamond'
2482
- cdb['diamond']['symmetry'] = 'zinc_blende'
2483
- cdb['diamond']['elements'] = ['C']
2484
- cdb['diamond']['a'] = 0.35668 # nm
2485
- cdb['diamond']['reference'] = ''
2486
- cdb['diamond']['link'] = ''
2487
- cdb['Diamond'] = cdb['diamond']
2488
-
2489
- cdb['germanium'] = {}
2490
- cdb['germanium']['crystal_name'] = 'germanium'
2491
- cdb['germanium']['symmetry'] = 'zinc_blende'
2492
- cdb['germanium']['elements'] = ['Ge']
2493
- cdb['germanium']['a'] = 0.566806348 # nm for 300K
2494
- cdb['germanium']['reference'] = 'H. P. Singh, Acta Crystallogr., 1968, 24A, 469'
2495
- cdb['germanium']['link'] = 'https://doi.org/10.1107/S056773946800094X'''
2496
- cdb['Ge'] = cdb['Germanium'] = cdb['germanium']
2497
-
2498
- cdb['silicon'] = {}
2499
- cdb['silicon']['crystal_name'] = 'silicon'
2500
- cdb['silicon']['symmetry'] = 'zinc_blende'
2501
- cdb['silicon']['elements'] = ['Si']
2502
- cdb['silicon']['a'] = 0.566806348 # nm for 300K
2503
- cdb['silicon']['reference'] = 'C. R. Hubbard, H. E. Swanson, and F. A. Mauer, J. Appl. Crystallogr., 1975, 8, 45'
2504
- cdb['silicon']['link'] = 'https://doi.org/10.1107/S0021889875009508'
2505
- cdb['Si'] = cdb['Silicon'] = cdb['silicon']
2506
-
2507
- cdb['GaAs'] = {}
2508
- cdb['GaAs']['crystal_name'] = 'GaAs'
2509
- cdb['GaAs']['symmetry'] = 'zinc_blende'
2510
- cdb['GaAs']['elements'] = ['Ga', 'As']
2511
- cdb['GaAs']['a'] = 0.565325 # nm for 300K
2512
- cdb['GaAs']['reference'] = 'J.F.C. Baker, M. Hart, M.A.G. Halliwell, R. Heckingbottom, Solid-State Electronics, 19, ' \
2513
- '1976, 331-334,'
2514
- cdb['GaAs']['link'] = 'https://doi.org/10.1016/0038-1101(76)90031-9'
2515
-
2516
- cdb['FCC Fe'] = {}
2517
- cdb['FCC Fe']['crystal_name'] = 'FCC Fe'
2518
- cdb['FCC Fe']['symmetry'] = 'FCC'
2519
- cdb['FCC Fe']['elements'] = ['Fe']
2520
- cdb['FCC Fe']['a'] = 0.3571 # nm
2521
- cdb['FCC Fe']['reference'] = 'R. Kohlhaas, P. Donner, and N. Schmitz-Pranghe, Z. Angew. Phys., 1967, 23, 245'
2522
- cdb['FCC Fe']['link'] = ''
2523
- cdb['fcc fe'] = cdb['FCC Fe']
2524
-
2525
-
2526
- cdb['BCC Fe'] = {}
2527
- cdb['BCC Fe']['crystal_name'] = 'BCC Fe'
2528
- cdb['BCC Fe']['symmetry'] = 'BCC'
2529
- cdb['BCC Fe']['elements'] = ['Fe']
2530
- cdb['BCC Fe']['a'] = 0.2866 # nm
2531
- cdb['BCC Fe']['reference'] = 'Z. S. Basinski, W. Hume-Rothery and A. L. Sutton, Proceedings of the Royal Society of ' \
2532
- 'London. Series A, Mathematical and Physical Sciences Vol. 229, No. 1179 ' \
2533
- '(May 24, 1955), pp. 459-467'
2534
- cdb['BCC Fe']['link'] = 'http://www.jstor.org/stable/99693'
2535
- cdb['bcc fe'] = cdb['BCC Fe']
2536
-
2537
- cdb['SrTiO3'] = {}
2538
- cdb['SrTiO3']['crystal_name'] = 'SrTiO3'
2539
- cdb['SrTiO3']['symmetry'] = 'perovskite'
2540
- cdb['SrTiO3']['elements'] = ['Sr', 'Ti', 'O']
2541
- cdb['SrTiO3']['a'] = 0.3905268 # nm
2542
- cdb['SrTiO3']['reference'] = 'M. Schmidbauer, A. Kwasniewski and J. Schwarzkopf, Acta Cryst. (2012). B68, 8-14'
2543
- cdb['SrTiO3']['link'] = 'http://doi.org/10.1107/S0108768111046738'
2544
-
2545
- cdb['ZnO Wurzite'] = {}
2546
- cdb['ZnO Wurzite']['crystal_name'] = 'ZnO Wurzite'
2547
- cdb['ZnO Wurzite']['symmetry'] = 'wurzite'
2548
- cdb['ZnO Wurzite']['elements'] = ['Zn', 'O']
2549
- cdb['ZnO Wurzite']['a'] = 0.3278 # nm
2550
- cdb['ZnO Wurzite']['c'] = 0.5292 # nm
2551
- cdb['ZnO Wurzite']['u'] = 0.382 # nm
2552
- cdb['ZnO Wurzite']['reference'] = ''
2553
- cdb['ZnO Wurzite']['link'] = ''
2554
- cdb['ZnO'] = cdb['ZnO wurzite'] = cdb['wZnO'] = cdb['ZnO Wurzite']
2555
-
2556
- cdb['GaN'] = {}
2557
- cdb['GaN']['crystal_name'] = 'GaN Wurzite'
2558
- cdb['GaN']['symmetry'] = 'wurzite'
2559
- cdb['GaN']['elements'] = ['Ga', 'N']
2560
- cdb['GaN']['a'] = 0.3186 # nm
2561
- cdb['GaN']['c'] = 0.5186 # nm
2562
- cdb['GaN']['u'] = 0.376393 # nm
2563
- cdb['GaN']['reference'] = ''
2564
- cdb['GaN']['link'] = ''
2565
- cdb['GaN wurzite'] = cdb['wGaN'] = cdb['GaN Wurzite'] = cdb['GaN']
2566
-
2567
- cdb['MgO'] = {}
2568
- cdb['MgO']['crystal_name'] = 'MgO'
2569
- cdb['MgO']['symmetry'] = 'rocksalt'
2570
- cdb['MgO']['elements'] = ['Mg', 'O']
2571
- cdb['MgO']['a'] = 0.4256483 # nm
2572
- cdb['MgO']['reference'] = ''
2573
- cdb['MgO']['link'] = ''
2574
-
2575
- cdb['TiN'] = {}
2576
- cdb['TiN']['crystal_name'] = 'TiN'
2577
- cdb['TiN']['symmetry'] = 'rocksalt'
2578
- cdb['TiN']['elements'] = ['Ti', 'N']
2579
- cdb['TiN']['a'] = 0.425353445 # nm
2580
- cdb['TiN']['reference'] = ''
2581
- cdb['TiN']['link'] = ''
2582
- cdb['TiN']['space_group'] = 225
2583
- cdb['TiN']['symmetry_name'] = 'Fm-3m'
2584
-
2585
- cdb['MoS2'] = {}
2586
- cdb['MoS2']['crystal_name'] = 'MoS2'
2587
- cdb['MoS2']['symmetry'] = 'dichalcogenide'
2588
- cdb['MoS2']['elements'] = ['Mo', 'S']
2589
- cdb['MoS2']['a'] = 0.319031573 # nm
2590
- cdb['MoS2']['c'] = 1.487900430 # nm
2591
- cdb['MoS2']['u'] = 0.105174 # nm
2592
- cdb['MoS2']['reference'] = ''
2593
- cdb['MoS2']['link'] = ''
2594
-
2595
- cdb['WS2'] = {}
2596
- cdb['WS2']['crystal_name'] = 'WS2'
2597
- cdb['WS2']['symmetry'] = 'dichalcogenide'
2598
- cdb['WS2']['elements'] = ['W', 'S']
2599
- cdb['WS2']['a'] = 0.319073051 # nm
2600
- cdb['WS2']['c'] = 1.420240204 # nm
2601
- cdb['WS2']['u'] = 0.110759 # nm
2602
- cdb['WS2']['reference'] = ''
2603
- cdb['WS2']['link'] = ''
2604
-
2605
- cdb['WSe2'] = {}
2606
- cdb['WSe2']['crystal_name'] = 'WSe2'
2607
- cdb['WSe2']['symmetry'] = 'dichalcogenide'
2608
- cdb['WSe2']['elements'] = ['W', 'Se']
2609
- cdb['WSe2']['a'] = 0.332706918 # nm
2610
- cdb['WSe2']['c'] = 1.506895072 # nm
2611
- cdb['WSe2']['u'] = 0.111569 # nm
2612
- cdb['WSe2']['reference'] = ''
2613
- cdb['WSe2']['link'] = ''
2614
-
2615
- cdb['MoSe2'] = {}
2616
- cdb['MoSe2']['crystal_name'] = 'MoSe2'
2617
- cdb['MoSe2']['elements'] = ['Mo', 'Se']
2618
- cdb['MoSe2']['a'] = 0.332694913 # nm
2619
- cdb['MoSe2']['c'] = 1.545142322 # nm
2620
- cdb['MoSe2']['u'] = 0.108249 # nm
2621
- cdb['MoSe2']['reference'] = ''
2622
- cdb['MoSe2']['link'] = ''
2623
-
2624
- cdb['ZnO hexagonal'] = {}
2625
- cdb['ZnO hexagonal']['crystal_name'] = 'ZnO hexagonal'
2626
- # cdb['ZnO hexagonal']['symmetry'] = 'hexagonal'
2627
- cdb['ZnO hexagonal']['a'] = a_l = 0.3336 # nm
2628
- cdb['ZnO hexagonal']['c'] = c_l = 0.4754 # not np.sqrt(8/3)*1
2629
- cdb['ZnO hexagonal']['unit_cell'] = [[a_l, 0., 0.],
2630
- [np.cos(120/180*np.pi)*a_l, np.sin(120/180*np.pi)*a_l, 0.],
2631
- [0., 0., c_l]]
2632
- cdb['ZnO hexagonal']['elements'] = ['Zn', 'Zn', 'O', 'O']
2633
- base_l = [(2./3., 1./3., .500), (1./3., 2./3., 0.000), (2./3., 1./3., 0.0), (1./3., 2./3., .5)]
2634
- cdb['ZnO hexagonal']['base'] = np.array(base_l)
2635
-
2636
- cdb['Graphite'] = {}
2637
- cdb['Graphite']['crystal_name'] = 'Graphite'
2638
- # cdb['Graphite']['symmetry'] = 'hexagonal'
2639
- # ### Create graphite unit cell (or structure matrix)
2640
- cdb['Graphite']['a'] = a_l = b_l = 0.2464 # nm
2641
- cdb['Graphite']['c'] = c_l = 0.6711
2642
- gamma_l = 60
2643
- alpha_l = beta_l = 90
2644
-
2645
- cdb['Graphite']['unit_cell'] = from_parameters(a_l, b_l, c_l, alpha_l, beta_l, gamma_l)
2646
-
2647
- # ### Create graphite atom base
2648
- # Elements of base
2649
- cdb['Graphite']['elements'] = ['C']*4
2650
- # atom positions in relative coordinates
2651
- base_l = np.array([(0, 0, 0), (0, 0, 0.5), (1./3., 1./3., 0.000), (2./3., 2./3., 0.5)])
2652
- cdb['Graphite']['base'] = np.array(base_l)
2653
- cdb['Graphite']['reference'] = 'P. Trucano and R. Chen, Nature, 1975, 258, 136'
2654
- cdb['Graphite']['link'] = 'https://doi.org/10.1038/258136a0'
2655
-
2656
- cdb['graphite'] = cdb['Graphite']
2657
-
2658
- cdb['CsCl'] = {}
2659
- # Create CsCl structure
2660
- cdb['CsCl']['a'] = a_l = 0.4209 # nm
2661
- cdb['CsCl']['crystal_name'] = 'CsCl'
2662
- cdb['CsCl']['unit_cell'] = np.identity(3)*a_l
2663
- cdb['CsCl']['elements'] = ['Cs', 'Cl']
2664
- cdb['CsCl']['base'] = np.array([[0, 0, 0], [0.5, 0.5, 0.5]])
2665
- cdb['CsCl']['reference'] = ''
2666
- cdb['CsCl']['link'] = ''
2667
-
2668
- cdb['PdSe2'] = {}
2669
- # Create CsCl structure
2670
- cdb['PdSe2']['crystal_name'] = 'PdSe2'
2671
- cdb['PdSe2']['unit_cell'] = (np.identity(3)*(.579441832, 0.594542204, 0.858506072))
2672
- cdb['PdSe2']['elements'] = ['Pd']*4 + ['Se']*8
2673
- cdb['PdSe2']['base'] = np.array([[.5, .0, .0], [.0, 0.5, 0.0], [.5, 0.5, 0.5], [.0, 0.5, 0.5],
2674
- [0.611300, 0.119356, 0.585891],
2675
- [0.111300, 0.380644, 0.414109],
2676
- [0.388700, 0.619356, 0.914109],
2677
- [0.888700, 0.880644, 0.085891],
2678
- [0.111300, 0.119356, 0.914109],
2679
- [0.611300, 0.380644, 0.085891],
2680
- [0.888700, 0.619356, 0.585891],
2681
- [0.388700, 0.880644, 0.414109]])
2682
- cdb['PdSe2']['reference'] = ''
2683
- cdb['PdSe2']['link'] = ''
2684
-
2685
- crystal_data_base = cdb