pyTEMlib 0.2025.4.1__py3-none-any.whl → 0.2025.9.1__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 (94) hide show
  1. build/lib/pyTEMlib/__init__.py +33 -0
  2. build/lib/pyTEMlib/animation.py +640 -0
  3. build/lib/pyTEMlib/atom_tools.py +238 -0
  4. build/lib/pyTEMlib/config_dir.py +31 -0
  5. build/lib/pyTEMlib/crystal_tools.py +1219 -0
  6. build/lib/pyTEMlib/diffraction_plot.py +756 -0
  7. build/lib/pyTEMlib/dynamic_scattering.py +293 -0
  8. build/lib/pyTEMlib/eds_tools.py +826 -0
  9. build/lib/pyTEMlib/eds_xsections.py +432 -0
  10. build/lib/pyTEMlib/eels_tools/__init__.py +44 -0
  11. build/lib/pyTEMlib/eels_tools/core_loss_tools.py +751 -0
  12. build/lib/pyTEMlib/eels_tools/eels_database.py +134 -0
  13. build/lib/pyTEMlib/eels_tools/low_loss_tools.py +655 -0
  14. build/lib/pyTEMlib/eels_tools/peak_fit_tools.py +175 -0
  15. build/lib/pyTEMlib/eels_tools/zero_loss_tools.py +264 -0
  16. build/lib/pyTEMlib/file_reader.py +274 -0
  17. build/lib/pyTEMlib/file_tools.py +811 -0
  18. build/lib/pyTEMlib/get_bote_salvat.py +69 -0
  19. build/lib/pyTEMlib/graph_tools.py +1153 -0
  20. build/lib/pyTEMlib/graph_viz.py +599 -0
  21. build/lib/pyTEMlib/image/__init__.py +37 -0
  22. build/lib/pyTEMlib/image/image_atoms.py +270 -0
  23. build/lib/pyTEMlib/image/image_clean.py +197 -0
  24. build/lib/pyTEMlib/image/image_distortion.py +299 -0
  25. build/lib/pyTEMlib/image/image_fft.py +277 -0
  26. build/lib/pyTEMlib/image/image_graph.py +926 -0
  27. build/lib/pyTEMlib/image/image_registration.py +316 -0
  28. build/lib/pyTEMlib/image/image_utilities.py +309 -0
  29. build/lib/pyTEMlib/image/image_window.py +421 -0
  30. build/lib/pyTEMlib/image_tools.py +699 -0
  31. build/lib/pyTEMlib/interactive_image.py +1 -0
  32. build/lib/pyTEMlib/kinematic_scattering.py +1196 -0
  33. build/lib/pyTEMlib/microscope.py +61 -0
  34. build/lib/pyTEMlib/probe_tools.py +906 -0
  35. build/lib/pyTEMlib/sidpy_tools.py +153 -0
  36. build/lib/pyTEMlib/simulation_tools.py +104 -0
  37. build/lib/pyTEMlib/test.py +437 -0
  38. build/lib/pyTEMlib/utilities.py +314 -0
  39. build/lib/pyTEMlib/version.py +5 -0
  40. build/lib/pyTEMlib/xrpa_x_sections.py +20976 -0
  41. pyTEMlib/__init__.py +25 -3
  42. pyTEMlib/animation.py +31 -22
  43. pyTEMlib/atom_tools.py +29 -34
  44. pyTEMlib/config_dir.py +2 -28
  45. pyTEMlib/crystal_tools.py +129 -165
  46. pyTEMlib/eds_tools.py +559 -342
  47. pyTEMlib/eds_xsections.py +432 -0
  48. pyTEMlib/eels_tools/__init__.py +44 -0
  49. pyTEMlib/eels_tools/core_loss_tools.py +751 -0
  50. pyTEMlib/eels_tools/eels_database.py +134 -0
  51. pyTEMlib/eels_tools/low_loss_tools.py +655 -0
  52. pyTEMlib/eels_tools/peak_fit_tools.py +175 -0
  53. pyTEMlib/eels_tools/zero_loss_tools.py +264 -0
  54. pyTEMlib/file_reader.py +274 -0
  55. pyTEMlib/file_tools.py +260 -1130
  56. pyTEMlib/get_bote_salvat.py +69 -0
  57. pyTEMlib/graph_tools.py +101 -174
  58. pyTEMlib/graph_viz.py +150 -0
  59. pyTEMlib/image/__init__.py +37 -0
  60. pyTEMlib/image/image_atoms.py +270 -0
  61. pyTEMlib/image/image_clean.py +197 -0
  62. pyTEMlib/image/image_distortion.py +299 -0
  63. pyTEMlib/image/image_fft.py +277 -0
  64. pyTEMlib/image/image_graph.py +926 -0
  65. pyTEMlib/image/image_registration.py +316 -0
  66. pyTEMlib/image/image_utilities.py +309 -0
  67. pyTEMlib/image/image_window.py +421 -0
  68. pyTEMlib/image_tools.py +154 -915
  69. pyTEMlib/kinematic_scattering.py +1 -1
  70. pyTEMlib/probe_tools.py +1 -1
  71. pyTEMlib/test.py +437 -0
  72. pyTEMlib/utilities.py +314 -0
  73. pyTEMlib/version.py +2 -3
  74. pyTEMlib/xrpa_x_sections.py +14 -10
  75. {pytemlib-0.2025.4.1.dist-info → pytemlib-0.2025.9.1.dist-info}/METADATA +13 -16
  76. pytemlib-0.2025.9.1.dist-info/RECORD +86 -0
  77. {pytemlib-0.2025.4.1.dist-info → pytemlib-0.2025.9.1.dist-info}/WHEEL +1 -1
  78. pytemlib-0.2025.9.1.dist-info/top_level.txt +6 -0
  79. pyTEMlib/core_loss_widget.py +0 -721
  80. pyTEMlib/eels_dialog.py +0 -754
  81. pyTEMlib/eels_dialog_utilities.py +0 -1199
  82. pyTEMlib/eels_tools.py +0 -2359
  83. pyTEMlib/file_tools_qt.py +0 -193
  84. pyTEMlib/image_dialog.py +0 -158
  85. pyTEMlib/image_dlg.py +0 -146
  86. pyTEMlib/info_widget.py +0 -1086
  87. pyTEMlib/info_widget3.py +0 -1120
  88. pyTEMlib/low_loss_widget.py +0 -479
  89. pyTEMlib/peak_dialog.py +0 -1129
  90. pyTEMlib/peak_dlg.py +0 -286
  91. pytemlib-0.2025.4.1.dist-info/RECORD +0 -38
  92. pytemlib-0.2025.4.1.dist-info/top_level.txt +0 -1
  93. {pytemlib-0.2025.4.1.dist-info → pytemlib-0.2025.9.1.dist-info}/entry_points.txt +0 -0
  94. {pytemlib-0.2025.4.1.dist-info → pytemlib-0.2025.9.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,599 @@
1
+ """
2
+ ##################################################################
3
+ # plotting functions for graph_tools
4
+ ##################################################################
5
+
6
+ part of pyTEMlib
7
+ a pycrosccopy package
8
+
9
+ Author: Gerd Duscher
10
+ First Version: 2022-01-08
11
+ """
12
+ import numpy as np
13
+ import ase
14
+
15
+ import plotly.graph_objects as go
16
+ import plotly.express as px
17
+
18
+ import pyTEMlib.crystal_tools
19
+ import pyTEMlib.graph_tools
20
+
21
+
22
+ def get_plot_bonds(atoms):
23
+ """Get plotly data for bonds."""
24
+ connectivity_matrix = atoms.info['bonds']['connectivity_matrix']
25
+ data = []
26
+ for row in range(1, connectivity_matrix.shape[0]):
27
+ for column in range(row):
28
+ if connectivity_matrix[column, row]:
29
+ lines = dict(type='scatter3d',
30
+ x=atoms.positions[[column, row],0],
31
+ y=atoms.positions[[column, row],1],
32
+ z=atoms.positions[[column, row],2],
33
+ mode='lines',
34
+ name='',
35
+ line=dict(color='rgb(70,70,70)', width=1.5))
36
+ data.append(lines)
37
+ return data
38
+
39
+ def plot_atoms(atoms: ase.Atoms, polyhedra_indices=None, plot_bonds=False, color='', template=None, atom_size=None, max_size=35) -> go.Figure:
40
+ """
41
+ Plot structure in a ase.Atoms object with plotly
42
+
43
+ If the info dictionary of the atoms object contains bond or polyedra information, these can be set tobe plotted
44
+
45
+ Partameter:
46
+ -----------
47
+ atoms: ase.Atoms object
48
+ structure of supercell
49
+ polyhedra_indices: list of integers
50
+ indices of polyhedra to be plotted
51
+ plot_bonds: boolean
52
+ whether to plot bonds or not
53
+
54
+ Returns:
55
+ --------
56
+ fig: plotly figure object
57
+ handle to figure needed to modify appearance
58
+ """
59
+ energies = np.zeros(len(atoms))
60
+ if 'bonds' in atoms.info:
61
+ if 'atom_energy' in atoms.info['bonds']:
62
+ energies = np.round(np.array(atoms.info['bonds']['atom_energy'] - 12 * atoms.info['bonds']['ideal_bond_energy']) *1000,0)
63
+
64
+ for atom in atoms:
65
+ if atom.index not in atoms.info['bonds']['super_cell_atoms']:
66
+ energies[atom.index] = 0.
67
+ if color == 'coordination':
68
+ colors = atoms.info['bonds']['coordination']
69
+ elif color == 'layer':
70
+ colors = atoms.positions[:, 2]
71
+ elif color == 'energy':
72
+ colors = energies
73
+ colors[colors>50] = 50
74
+ colors = np.log(1+ energies)
75
+
76
+ else:
77
+ colors = atoms.get_atomic_numbers()
78
+
79
+ if atom_size is None:
80
+ atom_size = atoms.get_atomic_numbers()*4
81
+ elif isinstance(atom_size, float):
82
+ atom_size = atoms.get_atomic_numbers()*4*atom_size
83
+ atom_size[atom_size>max_size] = max_size
84
+ elif isinstance(atom_size, int):
85
+ atom_size = [atom_size]*len(atoms)
86
+ if len(atom_size) != len(atoms):
87
+ atom_size = [10]*len(atoms)
88
+ print('wrong length of atom_size parameter')
89
+ plot_polyhedra = False
90
+ data = []
91
+ if polyhedra_indices is not None:
92
+ if 'polyhedra' in atoms.info:
93
+ if polyhedra_indices == -1:
94
+ data = plot_polyhedron(atoms.info['polyhedra']['polyhedra'], range(len(atoms.info['polyhedra']['polyhedra'])))
95
+ plot_polyhedra = True
96
+ elif isinstance(polyhedra_indices, list):
97
+ data = plot_polyhedron(atoms.info['polyhedra']['polyhedra'], polyhedra_indices)
98
+ plot_polyhedra = True
99
+ text = []
100
+ if 'bonds' in atoms.info:
101
+ coord = atoms.info['bonds']['coordination']
102
+ for atom in atoms:
103
+ if atom.index in atoms.info['bonds']['super_cell_atoms']:
104
+
105
+ text.append(f'Atom {atom.index}: coordination={coord[atom.index]}' +
106
+ f'x:{atom.position[0]:.2f} \n y:{atom.position[1]:.2f} \n z:{atom.position[2]:.2f}')
107
+ if 'atom_energy' in atoms.info['bonds']:
108
+ text[-1] += f"\n energy: {energies[atom.index]:.0f} meV"
109
+ else:
110
+ text.append('')
111
+ else:
112
+ text = [''] * len(atoms)
113
+
114
+ if plot_bonds:
115
+ data += get_plot_bonds(atoms)
116
+ if plot_polyhedra or plot_bonds:
117
+ fig = go.Figure(data=data)
118
+ else:
119
+ fig = go.Figure()
120
+ if color=='energy':
121
+ fig.add_trace(go.Scatter3d(
122
+ mode='markers',
123
+ x=atoms.positions[:,0], y=atoms.positions[:,1], z=atoms.positions[:,2],
124
+ hovertemplate='<b>%{text}</b><extra></extra>',
125
+ text = text,
126
+ marker=dict(
127
+ color=colors,
128
+ size=atom_size,
129
+ sizemode='diameter',
130
+ colorscale='Rainbow', #px.colors.qualitative.Light24,
131
+ colorbar=dict(thickness=10, orientation='h'))))
132
+ #hover_name = colors))) # ["blue", "green", "red"])))
133
+
134
+ elif 'bonds' in atoms.info:
135
+ fig.add_trace(go.Scatter3d(
136
+ mode='markers',
137
+ x=atoms.positions[:,0], y=atoms.positions[:,1], z=atoms.positions[:,2],
138
+ hovertemplate='<b>%{text}</b><extra></extra>',
139
+ text = text,
140
+ marker=dict(
141
+ color=colors,
142
+ size=atom_size,
143
+ sizemode='diameter',
144
+ colorscale= px.colors.qualitative.Light24)))
145
+ #hover_name = colors))) # ["blue", "green", "red"])))
146
+
147
+ else:
148
+ fig.add_trace(go.Scatter3d(
149
+ mode='markers',
150
+ x=atoms.positions[:,0], y=atoms.positions[:,1], z=atoms.positions[:,2],
151
+ marker=dict(
152
+ color=colors,
153
+ size=atom_size,
154
+ sizemode='diameter',
155
+ colorbar=dict(thickness=10),
156
+ colorscale= px.colors.qualitative.Light24)))
157
+ #hover_name = colors))) # ["blue", "green", "red"])))
158
+ fig.update_layout(width=1000, height=700, showlegend=False, template=template)
159
+ fig.update_layout(scene_aspectmode='data',
160
+ scene_aspectratio=dict(x=1, y=1, z=1))
161
+
162
+ camera = {'up': {'x': 0, 'y': 1, 'z': 0},
163
+ 'center': {'x': 0, 'y': 0, 'z': 0},
164
+ 'eye': {'x': 0, 'y': 0, 'z': 1}}
165
+ fig.update_coloraxes(showscale=True)
166
+ fig.update_layout(scene_camera=camera, title=r"Al-GB $")
167
+ fig.update_scenes(camera_projection_type="orthographic" )
168
+ fig.show()
169
+ return fig
170
+
171
+
172
+ def plot_super_cell(super_cell, shift_x=0.):
173
+ """ make a super_cell to plot with extra atoms at periodic boundaries"""
174
+
175
+ if not isinstance(super_cell, ase.Atoms):
176
+ raise TypeError('Need an ase Atoms object')
177
+
178
+ plot_boundary = super_cell * (2, 2, 3)
179
+ plot_boundary.positions[:, 0] = plot_boundary.positions[:, 0] - super_cell.cell[0, 0] * shift_x
180
+
181
+ del plot_boundary[plot_boundary.positions[:, 2] > super_cell.cell[2, 2] * 1.5 + 0.1]
182
+ del plot_boundary[plot_boundary.positions[:, 1] > super_cell.cell[1, 1] + 0.1]
183
+ del plot_boundary[plot_boundary.positions[:, 0] > super_cell.cell[0, 0] + 0.1]
184
+ del plot_boundary[plot_boundary.positions[:, 0] < -0.1]
185
+ plot_boundary.cell = super_cell.cell * (1, 1, 1.5)
186
+
187
+ return plot_boundary
188
+
189
+
190
+ def plot_polyhedron(polyhedra, indices, center=False):
191
+ """
192
+ Information to plot polyhedra with plotly
193
+
194
+ Parameter
195
+ ---------
196
+ polyhedra: dict
197
+ dictionary of all polyhedra
198
+ indices: list or integer
199
+ list or index of polyhedron to plot.
200
+ center: boolean
201
+ whether to center polyhedra on origin
202
+
203
+ Returns
204
+ -------
205
+ data: dict
206
+ instructions to plot for plotly
207
+ """
208
+
209
+ if isinstance(indices, int):
210
+ indices = [indices]
211
+ if len(indices) == 0:
212
+ print('Did not find any polyhedra')
213
+ return {}
214
+
215
+ center_point = np.mean(polyhedra[indices[0]]['vertices'], axis=0)
216
+
217
+ if center:
218
+ print(center_point)
219
+ center = center_point
220
+ else:
221
+ center = [0, 0, 0]
222
+
223
+ data = []
224
+ for index in indices:
225
+ polyhedron = polyhedra[index]
226
+
227
+ vertices = polyhedron['vertices'] - center
228
+ faces = np.array(polyhedron['triangles'])
229
+ x, y, z = vertices.T
230
+ i_i, j_j, k_k = faces.T
231
+
232
+ mesh = dict(type='mesh3d',
233
+ x=x,
234
+ y=y,
235
+ z=z,
236
+ i=i_i,
237
+ j=j_j,
238
+ k=k_k,
239
+ name='',
240
+ opacity=0.2,
241
+ color=px.colors.qualitative.Light24[len(vertices) % 24]
242
+ )
243
+ tri_vertices = vertices[faces]
244
+ x_e = []
245
+ y_e = []
246
+ z_e = []
247
+ for t_v in tri_vertices:
248
+ x_e += [t_v[k % 3][0] for k in range(4)] + [None]
249
+ y_e += [t_v[k % 3][1] for k in range(4)] + [None]
250
+ z_e += [t_v[k % 3][2] for k in range(4)] + [None]
251
+
252
+ # define the lines to be plotted
253
+ lines = dict(type='scatter3d',
254
+ x=x_e,
255
+ y=y_e,
256
+ z=z_e,
257
+ mode='lines',
258
+ name='',
259
+ line=dict(color='rgb(70,70,70)', width=1.5))
260
+ data.append(mesh)
261
+ data.append(lines)
262
+ return data
263
+
264
+
265
+ def plot_bonds(polyhedra):
266
+ """
267
+ Information to plot bonds with plotly
268
+
269
+ Parameter
270
+ ---------
271
+ polyhedra: dict
272
+ dictionary of all polyhedra
273
+
274
+ Returns
275
+ -------
276
+ data: dict
277
+ instructions to plot for plotly
278
+ """
279
+ indices = range(len(polyhedra))
280
+
281
+ data = []
282
+ for index in indices:
283
+ polyhedron = polyhedra[index]
284
+
285
+ vertices = polyhedron['vertices']
286
+ faces = np.array(polyhedron['triangles'])
287
+ x, y, z = vertices.T
288
+ i_i, j_j, k_k = faces.T
289
+
290
+ tri_vertices = vertices[faces]
291
+ x_e = []
292
+ y_e = []
293
+ z_e = []
294
+ for t_v in tri_vertices:
295
+ x_e += [t_v[k % 3][0] for k in range(4)] + [None]
296
+ y_e += [t_v[k % 3][1] for k in range(4)] + [None]
297
+ z_e += [t_v[k % 3][2] for k in range(4)] + [None]
298
+
299
+ # define the lines to be plotted
300
+ lines = dict(type='scatter3d',
301
+ x=x_e,
302
+ y=y_e,
303
+ z=z_e,
304
+ mode='lines',
305
+ name='',
306
+ line=dict(color='rgb(70,70,70)', width=1.5))
307
+ data.append(lines)
308
+ return data
309
+
310
+
311
+ def get_boundary_polyhedra(polyhedra, boundary_x=0, boundary_width=0.5, verbose=True, z_lim=[0, 100]):
312
+ """
313
+ get indices of polyhedra at boundary (assumed to be parallel to x-axis)
314
+
315
+ Parameter
316
+ ---------
317
+ polyhedra: dict
318
+ dictionary of all polyhedra
319
+ boundary_x: float
320
+ position of boundary in Angstrom
321
+ boundary_width: float
322
+ width of boundary where center of polyhedra are considered in Angstrom
323
+ verbose: boolean
324
+ optional
325
+ z_lim: list
326
+ upper and lower limit of polyhedra to plot
327
+
328
+ Returns
329
+ -------
330
+ boundary_polyhedra: list
331
+ list of polyhedra at boundary
332
+ """
333
+ boundary_polyhedra = []
334
+ for key, polyhedron in polyhedra.items():
335
+ center = polyhedron['vertices'].mean(axis=0)
336
+ if abs(center[0] - boundary_x) < 0.5 and (z_lim[0] < center[2] < z_lim[1]):
337
+ boundary_polyhedra.append(key)
338
+ if verbose:
339
+ print(key, polyhedron['length'], center)
340
+
341
+ return boundary_polyhedra
342
+
343
+
344
+ def plot_with_polyhedra(polyhedra, indices, atoms=None, title=''):
345
+ """
346
+ plot atoms and polyhedra with plotly
347
+
348
+ Parameter
349
+ ---------
350
+ polyhedra: dict
351
+ dictionary of all polyhedra
352
+ indices: list or integer
353
+ list or index of polyhedron to plot.
354
+ atoms: ase.Atoms
355
+ optional structure info to plot atoms (with correct color)
356
+
357
+ Returns
358
+ -------
359
+ fig: plotly.figure
360
+ plotly figure instance
361
+ """
362
+
363
+ data = plot_polyhedron(polyhedra, indices)
364
+ if not isinstance(atoms, ase.Atoms):
365
+ atoms = None
366
+
367
+ data[0]['opacity'] = 0.05
368
+ fig = go.Figure(data=data)
369
+ if atoms is not None:
370
+ fig.add_trace(go.Scatter3d(
371
+ mode='markers',
372
+ x=atoms.positions[:, 0], y=atoms.positions[:, 1], z=atoms.positions[:, 2],
373
+ marker=dict(
374
+ color=atoms.get_atomic_numbers(),
375
+ size=5,
376
+ sizemode='diameter',
377
+ colorscale=["blue", "green", "red"])))
378
+
379
+ fig.update_layout(width=1000, height=700, showlegend=False)
380
+ fig.update_layout(scene_aspectmode='data',
381
+ scene_aspectratio=dict(x=1, y=1, z=1))
382
+
383
+ camera = {'up': {'x': 1, 'y': 0, 'z': 0},
384
+ 'center': {'x': 0, 'y': 0, 'z': 0},
385
+ 'eye': {'x': 0, 'y': 0, 'z': 1}}
386
+
387
+ fig.update_layout(scene_camera=camera, title=title)
388
+ fig.update_scenes(camera_projection_type="orthographic")
389
+ return fig
390
+
391
+
392
+ def plot_supercell(supercell, size=(1, 1, 1), shift_x=0.25, title=''):
393
+ """
394
+ plot supercell with plotly
395
+
396
+ Parameter
397
+ ---------
398
+ supercell: ase.Atoms
399
+ optional structure info to plot atoms (with correct color)
400
+ shift_x: float
401
+ amount of shift in x direction of supercell
402
+ title: str
403
+ title of plot
404
+
405
+ Returns
406
+ -------
407
+ fig: plotly.figure
408
+ plotly figure instance
409
+ """
410
+
411
+ plot_cell = pyTEMlib.graph_tools.plot_super_cell(supercell * size, shift_x=shift_x)
412
+
413
+ # grain_boundary.cell.volume
414
+ supercell_area = supercell.cell.lengths()[1] / supercell.cell.lengths()[2]
415
+ print(supercell.symbols)
416
+ volume__bulk_atom = 16.465237835776012
417
+ ideal_volume = len(supercell.positions) * volume__bulk_atom
418
+ print(len(supercell.positions) * volume__bulk_atom, supercell.cell.volume)
419
+ x_0 = ideal_volume / supercell.cell.lengths()[1] / supercell.cell.lengths()[2]
420
+ print(f'Zero volume expansion supercell length: {x_0 / 10:.2f} nm; '
421
+ f' compared to actual {supercell.cell.lengths()[0] / 10:.2f} nm')
422
+
423
+ fig = go.Figure(data=[
424
+ go.Scatter3d(x=plot_cell.positions[:, 0], y=plot_cell.positions[:, 1], z=plot_cell.positions[:, 2],
425
+ mode='markers',
426
+ marker=dict(
427
+ color=plot_cell.get_atomic_numbers(),
428
+ size=5,
429
+ sizemode='diameter',
430
+ colorscale=["blue", "green", "red"]))])
431
+
432
+ fig.update_layout(width=700, margin=dict(r=10, l=10, b=10, t=10))
433
+ fig.update_layout(scene_aspectmode='data',
434
+ scene_aspectratio=dict(x=1, y=1, z=1))
435
+
436
+ camera = dict(
437
+ up=dict(x=0, y=1, z=0),
438
+ center=dict(x=0, y=0, z=0),
439
+ eye=dict(x=0, y=0, z=1)
440
+ )
441
+ fig.update_layout(scene_camera=camera, title=title)
442
+ fig.update_scenes(camera_projection_type="orthographic")
443
+ return fig
444
+
445
+
446
+ def plot_supercell_bonds(polyhedra, atoms, volumes=None, atom_size=15, title=''):
447
+ """
448
+ plot atoms and bonds with plotly
449
+
450
+ Parameter
451
+ ---------
452
+ polyhedra: dict
453
+ dictionary of all polyhedra
454
+ atoms: ase.Atoms
455
+ optional structure info to plot atoms (with correct color)
456
+ volumes: list
457
+ list of volumes, optional structure
458
+ atoms_size: float
459
+ sie of atoms to plot
460
+ title: str
461
+ title of plot
462
+
463
+ Returns
464
+ -------
465
+ fig: plotly.figure
466
+ plotly figure instance
467
+ """
468
+
469
+ data = plot_bonds(polyhedra)
470
+ if volumes is None:
471
+ volumes = [atom_size] * len(atoms.get_atomic_numbers())
472
+
473
+ fig = go.Figure(data=data)
474
+ fig.add_trace(go.Scatter3d(
475
+ mode='markers',
476
+ x=atoms.positions[:, 0], y=atoms.positions[:, 1], z=atoms.positions[:, 2],
477
+ marker=dict(
478
+ color=atoms.get_atomic_numbers(),
479
+ size=np.asarray(volumes) ** 2 / 10,
480
+ sizemode='diameter',
481
+ colorscale=["blue", "green", "red"])))
482
+
483
+ fig.update_layout(width=1000, height=700, showlegend=False)
484
+ fig.update_layout(scene_aspectmode='data',
485
+ scene_aspectratio=dict(x=1, y=1, z=1))
486
+
487
+ camera = {'up': {'x': 0, 'y': 1, 'z': 0},
488
+ 'center': {'x': 0, 'y': 0, 'z': 0},
489
+ 'eye': {'x': 0, 'y': 0, 'z': 1}}
490
+ fig.update_layout(scene_camera=camera, title=title)
491
+ fig.update_scenes(camera_projection_type="orthographic")
492
+ return fig
493
+
494
+
495
+ def plot_supercell_polyhedra(polyhedra, indices, atoms, volumes=None, title=''):
496
+ """
497
+ plot atoms and polyhedra with plotly
498
+
499
+ Parameter
500
+ ---------
501
+ polyhedra: dict
502
+ dictionary of all polyhedra
503
+ indices: list
504
+ list of indices of polyhedra to plot
505
+ atoms: ase.Atoms
506
+ optional structure info to plot atoms (with correct color)
507
+ volumes: list
508
+ list of volumes, optional structure
509
+ title: str
510
+ title of plot
511
+
512
+ Returns
513
+ -------
514
+ fig: plotly.figure
515
+ plotly figure instance
516
+ """
517
+ data = plot_polyhedron(polyhedra, indices)
518
+ if volumes is None:
519
+ volumes = [10] * len(atoms.get_atomic_numbers())
520
+
521
+ fig = go.Figure(data=data)
522
+ fig.add_trace(go.Scatter3d(
523
+ mode='markers',
524
+ x=atoms.positions[:, 0], y=atoms.positions[:, 1], z=atoms.positions[:, 2],
525
+ marker=dict(
526
+ color=atoms.get_atomic_numbers(),
527
+ size=np.asarray(volumes)**2 / 10,
528
+ sizemode='diameter',
529
+ colorscale=["blue", "green", "red"])))
530
+
531
+ fig.update_layout(width=1000, height=700, showlegend=False)
532
+ fig.update_layout(scene_aspectmode='data',
533
+ scene_aspectratio=dict(x=1, y=1, z=1))
534
+
535
+ camera = {'up': {'x': 0, 'y': 1, 'z': 0},
536
+ 'center': {'x': 0, 'y': 0, 'z': 0},
537
+ 'eye': {'x': 0, 'y': 0, 'z': 1}}
538
+ fig.update_layout(scene_camera=camera, title=title)
539
+ fig.update_scenes(camera_projection_type="orthographic")
540
+ return fig
541
+
542
+
543
+ def show_polyhedra(polyhedra, boundary_polyhedra, atoms, volumes=None, title=f''):
544
+ """
545
+ plot polyhedra and atoms of vertices with plotly
546
+
547
+ Parameter
548
+ ---------
549
+ polyhedra: dict
550
+ dictionary of all polyhedra
551
+ boundary_polyhedra: list
552
+ list of indices of polyhedra to plot
553
+ atoms: ase.Atoms
554
+ optional structure info to plot atoms (with correct color)
555
+ volumes: list
556
+ list of volumes, optional structure
557
+ title: str
558
+ title of plot
559
+
560
+ Returns
561
+ -------
562
+ fig: plotly.figure
563
+ plotly figure instance
564
+ """
565
+
566
+ data = plot_polyhedron(polyhedra, boundary_polyhedra)
567
+ atom_indices = []
568
+ for poly in boundary_polyhedra:
569
+ atom_indices.extend(polyhedra[poly]['indices'])
570
+ atom_indices = list(set(atom_indices))
571
+ atomic_numbers = []
572
+ atomic_volumes = []
573
+ for atom in atom_indices:
574
+ atomic_numbers.append(atoms[atom].number)
575
+ atomic_volumes.append(volumes[atoms[atom].index] ** 2 / 10)
576
+
577
+ if volumes is None:
578
+ atomic_volumes = [10] * len(atoms.get_atomic_numbers())
579
+ fig = go.Figure(data=data)
580
+
581
+ fig.add_trace(go.Scatter3d(
582
+ mode='markers',
583
+ x=atoms.positions[atom_indices, 0], y=atoms.positions[atom_indices, 1], z=atoms.positions[atom_indices, 2],
584
+ marker=dict(
585
+ color=atomic_numbers,
586
+ size=atomic_volumes,
587
+ sizemode='diameter',
588
+ colorscale=["blue", "green", "red"])))
589
+
590
+ fig.update_layout(width=1000, height=700, showlegend=False)
591
+ fig.update_layout(scene_aspectmode='data',
592
+ scene_aspectratio=dict(x=1, y=1, z=1))
593
+
594
+ camera = {'up': {'x': 1, 'y': 0, 'z': 0},
595
+ 'center': {'x': 0, 'y': 0, 'z': 0},
596
+ 'eye': {'x': 0, 'y': 0, 'z': 1}}
597
+ fig.update_layout(scene_camera=camera, title=title)
598
+ fig.update_scenes(camera_projection_type="orthographic")
599
+ return fig
@@ -0,0 +1,37 @@
1
+ """
2
+ Image Module
3
+
4
+ Should contain
5
+ - general feature extraction
6
+ - geometry feature extraction
7
+ - atom finding
8
+ - denoising
9
+ - windowing
10
+ - transforms (e.g., radon, hough)
11
+
12
+ Submodules
13
+ ----------
14
+ .. autosummary::
15
+ :toctree: _autosummary
16
+
17
+ """
18
+
19
+ from .image_window import ImageWindowing
20
+ from .image_utilities import crop_image, flatten_image, inpaint_image, warp, rebin
21
+ from .image_clean import decon_lr, clean_svd, background_correction
22
+ from .image_atoms import find_atoms, atom_refine, intensity_area, atoms_clustering
23
+ from .image_graph import find_polyhedra, breadth_first_search, breadth_first_search_flexible
24
+ from .image_graph import get_base_atoms
25
+ from .image_distortion import get_distortion_matrix, undistort, undistort_sitk
26
+ from .image_registration import complete_registration, rigid_registration, demon_registration
27
+ from .image_fft import power_spectrum, diffractogram_spots, adaptive_fourier_filter
28
+ from .image_fft import rotational_symmetry_diffractogram
29
+
30
+
31
+ __all__ = ['ImageWindowing', 'crop_image', 'decon_lr', 'clean_svd', 'background_correction',
32
+ 'find_atoms', 'atom_refine', 'intensity_area', 'atoms_clustering',
33
+ 'find_polyhedra', 'breadth_first_search', 'breadth_first_search_flexible', 'get_base_atoms',
34
+ 'get_distortion_matrix', 'undistort', 'undistort_sitk',
35
+ 'complete_registration', 'demon_registration', 'rigid_registration',
36
+ 'flatten_image', 'inpaint_image', 'warp', 'rebin',
37
+ 'power_spectrum', 'diffractogram_spots', 'adaptive_fourier_filter', 'rotational_symmetry_diffractogram']