pyemaps 2.0.0__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.
Files changed (112) hide show
  1. pyemaps/COPYING +798 -0
  2. pyemaps/CifFile/CifFile_module.py +3117 -0
  3. pyemaps/CifFile/StarFile.py +2496 -0
  4. pyemaps/CifFile/TypeContentsParser.py +82 -0
  5. pyemaps/CifFile/YappsStarParser_1_0.py +289 -0
  6. pyemaps/CifFile/YappsStarParser_1_1.py +288 -0
  7. pyemaps/CifFile/YappsStarParser_2_0.py +369 -0
  8. pyemaps/CifFile/YappsStarParser_STAR2.py +382 -0
  9. pyemaps/CifFile/__init__.py +7 -0
  10. pyemaps/CifFile/drel/__init__.py +1 -0
  11. pyemaps/CifFile/drel/drel_ast_yacc.py +582 -0
  12. pyemaps/CifFile/drel/drel_lex.py +228 -0
  13. pyemaps/CifFile/drel/drel_runtime.py +126 -0
  14. pyemaps/CifFile/drel/parsetab.py +185 -0
  15. pyemaps/CifFile/drel/py_from_ast.py +628 -0
  16. pyemaps/CifFile/parsetab.py +185 -0
  17. pyemaps/CifFile/yapps3_compiled_rt.py +390 -0
  18. pyemaps/README.md +201 -0
  19. pyemaps/__config__.py +91 -0
  20. pyemaps/__init__.py +233 -0
  21. pyemaps/__main__.py +219 -0
  22. pyemaps/__version__.py +1 -0
  23. pyemaps/cdata/Aluminium.xtl +4 -0
  24. pyemaps/cdata/AluminiumOxide.xtl +5 -0
  25. pyemaps/cdata/Aluminium_FCC.xtl +4 -0
  26. pyemaps/cdata/BariumTitanate_180k.xtl +6 -0
  27. pyemaps/cdata/BariumTitanate_270k.xtl +7 -0
  28. pyemaps/cdata/BariumTitanate_Tetra.xtl +7 -0
  29. pyemaps/cdata/BiMnO3.xtl +27 -0
  30. pyemaps/cdata/Boron_Tetra.xtl +8 -0
  31. pyemaps/cdata/CadmiumSelenide_Hex.xtl +5 -0
  32. pyemaps/cdata/CadmiumSulfide_Cubic.xtl +5 -0
  33. pyemaps/cdata/CadmiumSulfide_Hex.xtl +5 -0
  34. pyemaps/cdata/Chromium_BCC.xtl +4 -0
  35. pyemaps/cdata/CoSb3_Skutterudite.xtl +5 -0
  36. pyemaps/cdata/CopperOxide.xtl +5 -0
  37. pyemaps/cdata/Copper_FCC.xtl +4 -0
  38. pyemaps/cdata/Cu2O_Cuprite.xtl +5 -0
  39. pyemaps/cdata/Diamond.xtl +4 -0
  40. pyemaps/cdata/ErbiumPyrogermanate.xtl +9 -0
  41. pyemaps/cdata/FePd_Tetra.xtl +5 -0
  42. pyemaps/cdata/FeS2_Pyrite.xtl +15 -0
  43. pyemaps/cdata/GalliumAntimonide.xtl +5 -0
  44. pyemaps/cdata/GalliumArsenide.xtl +5 -0
  45. pyemaps/cdata/GalliumNitride.xtl +5 -0
  46. pyemaps/cdata/Germanium.xtl +4 -0
  47. pyemaps/cdata/Gold_FCC.xtl +4 -0
  48. pyemaps/cdata/IndiumArsenide.xtl +5 -0
  49. pyemaps/cdata/LaMnO3.xtl +7 -0
  50. pyemaps/cdata/LeadZirconateTitanate.xtl +8 -0
  51. pyemaps/cdata/Li2MnO3.xtl +13 -0
  52. pyemaps/cdata/NaFeO2.xtl +6 -0
  53. pyemaps/cdata/Nb3Sn.xtl +5 -0
  54. pyemaps/cdata/Pentacene.xtl +39 -0
  55. pyemaps/cdata/Silicon.xtl +4 -0
  56. pyemaps/cdata/StrontiumTitanate.xtl +6 -0
  57. pyemaps/cdata/TelluriumDioxide.xtl +5 -0
  58. pyemaps/cdata/TinDioxide_RT.xtl +5 -0
  59. pyemaps/cdata/TitaniumDioxide_Anatase.xtl +5 -0
  60. pyemaps/cdata/TitaniumDioxide_Rutile.xtl +5 -0
  61. pyemaps/cdata/TungstenDiselenide.xtl +5 -0
  62. pyemaps/cdata/VanadiumDioxide_RT.xtl +6 -0
  63. pyemaps/cdata/ZincOxide.xtl +5 -0
  64. pyemaps/cdata/Zinc_HCP.xtl +4 -0
  65. pyemaps/cdata/ZirconiumNitride.xtl +5 -0
  66. pyemaps/cdata/limno2.xtl +6 -0
  67. pyemaps/crystals.py +1415 -0
  68. pyemaps/ddiffs.py +147 -0
  69. pyemaps/diffract/__init__.py +70 -0
  70. pyemaps/diffract/bloch_dec.py +779 -0
  71. pyemaps/diffract/csf_dec.py +242 -0
  72. pyemaps/diffract/dif_dec.py +519 -0
  73. pyemaps/diffract/dpgen_dec.py +175 -0
  74. pyemaps/diffract/mxtal_dec.py +201 -0
  75. pyemaps/diffract/powder_dec.py +137 -0
  76. pyemaps/diffract/stereo_dec.py +111 -0
  77. pyemaps/display.py +791 -0
  78. pyemaps/emcontrols.py +1017 -0
  79. pyemaps/errors.py +266 -0
  80. pyemaps/fileutils.py +1001 -0
  81. pyemaps/kdiffs.py +1221 -0
  82. pyemaps/license.txt +42 -0
  83. pyemaps/samples/adf.py +137 -0
  84. pyemaps/samples/al.img +0 -0
  85. pyemaps/samples/al_dpgen.py +57 -0
  86. pyemaps/samples/al_ediom.py +94 -0
  87. pyemaps/samples/convert_image.py +88 -0
  88. pyemaps/samples/dm_diff.py +225 -0
  89. pyemaps/samples/mask.im3 +0 -0
  90. pyemaps/samples/powder.py +51 -0
  91. pyemaps/samples/raw.img +0 -0
  92. pyemaps/samples/si_bloch.py +120 -0
  93. pyemaps/samples/si_constructor.py +51 -0
  94. pyemaps/samples/si_csf.py +59 -0
  95. pyemaps/samples/si_dif.py +134 -0
  96. pyemaps/samples/si_lacbed.py +59 -0
  97. pyemaps/samples/si_pyemaps.py +80 -0
  98. pyemaps/samples/si_scm.py +156 -0
  99. pyemaps/samples/si_stereo.py +116 -0
  100. pyemaps/scattering/__init__.py +26 -0
  101. pyemaps/scattering/sct_dec.py +31 -0
  102. pyemaps/spg/__init__.py +25 -0
  103. pyemaps/spg/spg_dec.py +60 -0
  104. pyemaps/stackimg.py +1031 -0
  105. pyemaps/xtal.py +222 -0
  106. pyemaps-2.0.0.dist-info/METADATA +231 -0
  107. pyemaps-2.0.0.dist-info/RECORD +112 -0
  108. pyemaps-2.0.0.dist-info/WHEEL +5 -0
  109. pyemaps-2.0.0.dist-info/entry_points.txt +2 -0
  110. pyemaps-2.0.0.dist-info/licenses/COPYING +798 -0
  111. pyemaps-2.0.0.dist-info/licenses/license.txt +42 -0
  112. pyemaps-2.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,519 @@
1
+ '''
2
+ .. This file is part of pyEMAPS
3
+
4
+ .. ----
5
+
6
+ .. pyEMAPS is free software. You can redistribute it and/or modify
7
+ .. it under the terms of the GNU General Public License as published
8
+ .. by the Free Software Foundation, either version 3 of the License,
9
+ .. or (at your option) any later version..
10
+
11
+ .. pyEMAPS is distributed in the hope that it will be useful,
12
+ .. but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ .. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ .. GNU General Public License for more details.
15
+
16
+ .. You should have received a copy of the GNU General Public License
17
+ .. along with pyEMAPS. If not, see `<https://www.gnu.org/licenses/>`_.
18
+
19
+ .. Contact supprort@emlabsoftware.com for any questions and comments.
20
+
21
+ .. ----
22
+
23
+ .. Author: EMLab Solutions, Inc.
24
+ .. Date Created: May 07, 2022
25
+
26
+ '''
27
+ def add_dif(target):
28
+ import numpy as np
29
+ from numpy import asfortranarray as farray
30
+
31
+ from . import dif
32
+ from .. import EMC, DP
33
+ from .. import DEF_MODE, DEF_CBED_DSIZE, DEF_XAXIS
34
+ from .. import EMCError,DPListError,CrystalClassError,DPError
35
+
36
+ def load(self, cty=0):
37
+ '''
38
+ Prepare and load crystal data into backend simulation module.
39
+
40
+ Once loaded into simulation modules, the crystal data will be
41
+ in backend module's memory until unload() method is called or
42
+ another crystal object calls this method.
43
+
44
+ Since all crystal objects use this method to load its data into
45
+ the shared silmulation modules, data races need to be avoided.
46
+
47
+ One way to prevent data races is to guard all simulations for
48
+ one crystal object between its load() and unload() methods.
49
+
50
+ :param cty: 0 - normal crystal loading, 1 - loading for crystal constructor
51
+ :type cty: int, optional
52
+
53
+ .. note::
54
+
55
+ This routine is designed to minimize trips to the backend simulation modules
56
+ and therefore miximizing the performance. Users do not need to handle this calls
57
+ directly.
58
+
59
+ '''
60
+ if self.loaded() and cty == self._ltype:
61
+ return
62
+
63
+ diff_cell = self._cell.prepare() #cell constant
64
+
65
+ num_atoms = len(self._atoms)
66
+ atn = farray(np.empty((num_atoms, 10), dtype='c'))
67
+
68
+ atnarr = [at.symb for at in self._atoms]
69
+ for i, an in enumerate(atnarr):
70
+ if len(an) > 10:
71
+ raise CrystalClassError(f"Atomic symbol {an} length cannot exceed 10")
72
+ atn[i] = an.ljust(10)
73
+
74
+ diff_atoms = farray([at.prepare() for at in self._atoms], dtype=float)
75
+
76
+ diff_spg = self._spg.prepare()
77
+
78
+ ret = dif.loadcrystal(diff_cell, diff_atoms, atn, diff_spg, ndw=self._dw, cty=cty)
79
+
80
+ if ret != 0:
81
+ self.unload() #remove any memory from backend module
82
+ raise CrystalClassError('Failed to load crystal')
83
+
84
+ self._loaded = True
85
+ self._ltype = cty
86
+
87
+ def unload(self):
88
+ '''
89
+ Remove crystal data from the memory in the backend simulation modules.
90
+
91
+ '''
92
+ dif.crystaldelete()
93
+ self._loaded = False
94
+
95
+ def generateDP(self, mode = None, dsize = None, em_controls = None):
96
+ """
97
+ Kinematic diffraction simulation.
98
+
99
+ :param mode: Mode of kinemetic diffraction - normal(1) or CBED(2).
100
+ :type mode: int, optional
101
+
102
+ :param dsize: diffractted beam size, only applied to CBED mode.
103
+ :type dsize: float, optional
104
+
105
+ :param em_controls: `Microscope control <pyemaps.emcontrols.html#module-pyemaps.emcontrols>`_ object.
106
+ :type em_controls: pyemaps.EMC, optional
107
+
108
+ :return: A tuple (emc, dp) where emc is the microscope control and dp is a `diffPattern <pyemaps.kdiffs.html#pyemaps.kdiffs.diffPattern>`_ object .
109
+ :rtype: tuple.
110
+
111
+ """
112
+
113
+ if em_controls is None:
114
+ em_controls =EMC()
115
+
116
+ # if not sim_controls:
117
+ # em_controls =SIMC()
118
+
119
+ tx0, ty0 = em_controls.tilt
120
+ dx0, dy0 = em_controls.defl
121
+ cl, vt = em_controls.cl, em_controls.vt
122
+ zone = em_controls.zone
123
+ sc = em_controls.simc
124
+ if em_controls.xaxis != DEF_XAXIS:
125
+ xa = em_controls.xaxis
126
+ else:
127
+ xa = None
128
+
129
+ if not mode:
130
+ mode = DEF_MODE
131
+
132
+ if mode == 2 and dsize is None:
133
+ dsize = DEF_CBED_DSIZE
134
+
135
+ ret, diffp = self._get_diffraction(zone,mode,tx0,ty0,dx0,dy0,cl,vt,dsize,xa,sc)
136
+
137
+
138
+ if ret != 200:
139
+ raise DPError('failed to generate diffraction patterns')
140
+
141
+ # update the controls
142
+
143
+ em_controls(mode=mode)
144
+ if mode == 2:
145
+ em_controls(dsize=dsize)
146
+
147
+ # @70323 merge
148
+ # update x-axis if it was set to (0,0,0)
149
+ # and new xaxis is calculated by the backend
150
+
151
+ if em_controls.xaxis == DEF_XAXIS:
152
+ xa1 = 0
153
+ xa2 = 2
154
+ xa3 = 0
155
+ xa1, xa2, xa3 = dif.get_xaxis()
156
+ em_controls(xaxis = (xa1,xa2,xa3))
157
+
158
+ return em_controls, DP(diffp)
159
+
160
+ def _get_diffraction(self, zone = None,
161
+ mode = None,
162
+ tx0 = None,
163
+ ty0 = None,
164
+ dx0 = None,
165
+ dy0 = None,
166
+ cl = None,
167
+ vt = None,
168
+ dsize = None,
169
+ xa = None,
170
+ simc = None):
171
+ """
172
+ This routine returns raw diffraction data from emaps dif extension
173
+
174
+ If none of the parameters are supplied, the routine will
175
+ generate the diffraction patterns in default set in the fortran
176
+ backend indicated below:
177
+ zone = (0,0,1) zone axis
178
+ mode = normal kinematic diffraction mode (CBED is the other)
179
+ (tx0,ty0) = (0.0,0.0) tilt angles
180
+ (dx0,dy0) = (0.0,0.0) deflection move
181
+ cl = 1000 EM length
182
+ vt = 200 voltage
183
+ cl and vt must be set togather
184
+ dsize = 0.05 spot disk size in nm
185
+ If any of the values are set, the following tuples must be set togather
186
+ (tx0,ty0,dx0,dy0)
187
+ (cl,vt)
188
+ if mode == 2 (CBED), then dsize must be set
189
+
190
+ """
191
+ import copy
192
+
193
+ if mode != DEF_MODE and mode != DEF_MODE + 1:
194
+ raise EMCError('Simulation mode is invalid: 1 = normal (default), 2 = CBED')
195
+
196
+ dif.initcontrols()
197
+ # mode defaults to DEF_MODE, in which dsize is not used
198
+ # Electron Microscope controls defaults - DEF_CONTROLS
199
+
200
+ if mode == 2:
201
+ dif.setmode(mode)
202
+ try:
203
+ fd = float(dsize)
204
+ except ValueError:
205
+ raise EMCError('Invalid diffracted beams disk size')
206
+ else:
207
+ dif.setdisksize(fd)
208
+
209
+ if tx0 is not None and \
210
+ ty0 is not None and \
211
+ dx0 is not None and \
212
+ dy0 is not None:
213
+
214
+ dif.setsamplecontrols(tx0, ty0, dx0, dy0)
215
+ else:
216
+ print(f'tilt and deflection values: {tx0},{ty0}, {dx0}, {dy0}')
217
+ raise EMCError('Control parameters invalid: tilt and deflection')
218
+
219
+ if cl is not None and vt is not None:
220
+ dif.setemcontrols(cl, vt)
221
+ else:
222
+ raise EMCError('Control parameters invalid: cl and vt')
223
+
224
+ if zone is not None:
225
+ dif.setzone(zone[0], zone[1], zone[2])
226
+ else:
227
+ raise EMCError('Control parameters invalid: zone')
228
+
229
+ # setting simulation parameters
230
+ self.set_sim_controls(simc)
231
+ if xa:
232
+ dif.set_xaxis(1, xa[0], xa[1], xa[2])
233
+
234
+ self.load()
235
+
236
+ ret = dif.diffract()
237
+ if ret == 0:
238
+ return 500, ({})
239
+
240
+ shiftx, shifty = dif.get_shifts()
241
+ bounds = (shiftx, shifty)
242
+
243
+ # dif.diff_printall()
244
+ #remove module internal global memory
245
+ dif.diff_internaldelete(0)
246
+
247
+ klines=[]
248
+ num_klines = dif.getknum()
249
+
250
+ if (num_klines > 0):
251
+ klines_arr = farray(np.zeros((num_klines, 5)), dtype=np.single)
252
+
253
+ if dif.get_klines(klines_arr) == 0:
254
+ for i in range(num_klines):
255
+ j=i+1
256
+ x1,y1,x2,y2,intensity=klines_arr[i][0:]
257
+ klines.append((x1,y1,x2,y2,intensity))
258
+ else:
259
+ print(f"Error: retrieving klines!")
260
+ return 500, ({})
261
+
262
+ disks=[]
263
+ num_disks = dif.getdnum()
264
+ if (num_disks > 0):
265
+ disks_arr = farray(np.zeros((num_disks, 6)), dtype=np.single)
266
+ if dif.get_disks(disks_arr) == 0:
267
+ # for i in range(num_disks):
268
+ # x1,y1,r,i1,i2,i3=disks_arr[i][0:]
269
+ # disk={}
270
+ # disk['c']=(x1,y1)
271
+ # disk['r']=r
272
+ # disk['idx']=(int(i1),int(i2),int(i3))
273
+ # disks.append(disk)
274
+ for d in disks_arr:
275
+ x1,y1,r,i1,i2,i3=d
276
+ disk={}
277
+ disk['c']=(x1,y1)
278
+ disk['r']=r
279
+ disk['idx']=(int(i1),int(i2),int(i3))
280
+ disks.append(disk)
281
+
282
+ else:
283
+ print(f"Error: retrieving disks!")
284
+ return 500, ({})
285
+
286
+ hlines=[]
287
+ num_hlines = 0
288
+ if (mode == 2):
289
+ num_hlines = dif.gethnum()
290
+
291
+ if (num_hlines > 0):
292
+ hlines_arr = farray(np.zeros((num_hlines, 5)), dtype=np.single)
293
+ if dif.get_hlines(hlines_arr) == 0:
294
+ for i in range(num_hlines):
295
+ x1,y1,x2,y2,intensity = hlines_arr[i][0:]
296
+ hlines.append((x1,y1,x2,y2,intensity))
297
+ else:
298
+ print(f"Info: no hlines detected!")
299
+ return 500, ({})
300
+
301
+ nums = {"nklines" : num_klines, "ndisks" : num_disks, "nhlines" : num_hlines}
302
+ data = {"nums" : copy.deepcopy(nums), "bounds": copy.deepcopy(bounds), \
303
+ "klines": copy.deepcopy(klines), "hlines": copy.deepcopy(hlines), \
304
+ "disks": copy.deepcopy(disks), "name" : self.name}
305
+
306
+ # delete diff pattern memory
307
+ dif.diff_delete()
308
+ return 200, data
309
+
310
+ def generateDif(self, mode = None, dsize = None, em_controls = None):
311
+ """
312
+ Another kinematic diffraction simulation method to be deprecated in
313
+ stabel production soon. Its replacement is:
314
+ `generateDP <pyemaps.crystals.html#pyemaps.crystals.Crystal.generateDP>`_.
315
+
316
+ :param mode: mode of kinemetic diffraction - normal(1) or CBED(2).
317
+ :type mode: int
318
+
319
+ :param dsize: diffractted beam size, only applied to CBED mode.
320
+ :type dsize: float
321
+
322
+ :param em_controls: electron microscope controls object.
323
+ :type em_controls: pyemaps.EMC
324
+
325
+ :return: myDif.
326
+ :rtype: pyemaps.DPList.
327
+
328
+ """
329
+ from .. import DPList
330
+ if mode is None:
331
+ mode = 1
332
+ try:
333
+ emc, cdp = self.generateDP(mode = mode, dsize=dsize, em_controls = em_controls)
334
+ myDif = DPList(self._name, mode = mode)
335
+ myDif.add(emc, cdp)
336
+
337
+ except (DPListError, EMCError, DPError) as e:
338
+ raise CrystalClassError('failed to generate diffraction')
339
+
340
+ return myDif
341
+
342
+ def d2r(self, v = (0.0, 0.0, 0.0)):
343
+ '''
344
+ Transform vector from real to recriprocal space
345
+
346
+ :param v: A vector of float coordinates
347
+ :type v: tuple, optional
348
+
349
+ :return: a transformed vector
350
+ :rtype: tuple
351
+
352
+ '''
353
+
354
+ self.load()
355
+
356
+ x, y, z = v
357
+ rx, ry, rz = dif.drtrans(x, y, z, 0)
358
+
359
+ # dif.crystaldelete()
360
+ return rx, ry, rz
361
+
362
+ def r2d(self, v = (0.0, 0.0, 0.0)):
363
+ '''
364
+ Transform vector from recriprocal to real space
365
+
366
+ :param v: A vector of float coordinates
367
+ :type v: tuple, optional
368
+
369
+ :return: Tranformed vector
370
+ :rtype: tuple of floats
371
+
372
+ '''
373
+
374
+ self.load()
375
+
376
+ x, y, z = v
377
+ dx, dy, dz = dif.drtrans(x, y, z, 1)
378
+
379
+ # dif.crystaldelete()
380
+ return dx, dy, dz
381
+
382
+ def angle(self, v1 =(1.0, 0.0, 0.0), \
383
+ v2 = (0.0, 0.0, 1.0),
384
+ ty = 0):
385
+ '''
386
+ Calculates angle between two real space vectors or
387
+ two reciprocal space vectors
388
+
389
+ :param v1: A vector of float coordinates
390
+ :type v1: tuple, optional
391
+
392
+ :param v2: A vector of float coordinates
393
+ :type v2: tuple, optional
394
+
395
+ :param ty: 0 real space, 1 reciprocal space
396
+ :type ty: int, optional
397
+
398
+ :return: an angle between v1 and v2.
399
+ :rtype: float
400
+
401
+
402
+ '''
403
+ x1, y1, z1 = v1
404
+ if x1 == 0.0 and y1 == 0.0 and z1 == 0.0:
405
+ raise ValueError("Error: input vector can't be zero")
406
+
407
+ x2, y2, z2 = v2
408
+ if x2 == 0.0 and y2 == 0.0 and z2 == 0.0:
409
+ raise ValueError("Error: input vector can't be zero")
410
+
411
+ self.load()
412
+
413
+ a = dif.ang(x1, y1, z1, x2, y2, z2, ty)
414
+
415
+ # dif.crystaldelete()
416
+ return a
417
+
418
+ def vlen(self, v = (1.0, 0.0, 0.0), ty = 0):
419
+
420
+ '''
421
+ Calculates vector length real space vectors or in reciprocal
422
+ space vectors.
423
+
424
+ :param v: A vector of float coordinates
425
+ :type v: tuple, optional
426
+
427
+ :param ty: 0 real space, 1 reciprocal space
428
+ :type ty: int, optional
429
+
430
+ :return: vector length in reciprical space or in reciprocal space
431
+ :rtype: float
432
+
433
+ '''
434
+
435
+ self.load()
436
+
437
+ x, y, z = v
438
+ ln = dif.vlen(x, y, z, ty)
439
+
440
+ # dif.crystaldelete()
441
+ return ln
442
+
443
+ @staticmethod
444
+ def wavelength(kv = 100):
445
+ '''
446
+ Calculates electron wavelength.
447
+
448
+ :param kv: High voltage
449
+ :type kv: float or int, optional
450
+
451
+ return: wave length
452
+ rtype: float
453
+
454
+ '''
455
+ import math
456
+
457
+ if kv <= 0.0:
458
+ raise ValueError("Error: input kv must be positive number")
459
+
460
+ wlen = 0.3878314/math.sqrt(kv*(1.0+0.97846707e-03*kv))
461
+ return wlen
462
+
463
+ def set_sim_controls(self, simc = None):
464
+ '''
465
+ Sets simulation controls in the backend.
466
+
467
+ This method also tries to minimize the trip to the backend
468
+ simulation module by skipping the call to the backend if
469
+ default values are given.
470
+
471
+ :param simc: `Simulation control <pyemaps.emcontrols.html#pyemaps.emcontrols.SIMControl>`_ objects
472
+ :type simc: pyemaps.SIMC, optional
473
+
474
+ .. note::
475
+
476
+ *pyemaps" assumes that attributes in sim_control class are
477
+ rarely changed.
478
+
479
+ '''
480
+ # from pyemaps import
481
+ if not simc:
482
+ # all defaults set in backend set by dif.initcontrols()
483
+ return
484
+
485
+ if not simc._check_def('excitation'):
486
+ sgmin, sgmax = simc.excitation
487
+ dif.setexcitation(sgmin, sgmax)
488
+
489
+ if not simc._check_def('gmax'):
490
+ dif.setglen(simc.gmax)
491
+
492
+ if not simc._check_def('bmin'):
493
+ dif.setgcutoff(simc.bmin)
494
+
495
+ if not simc._check_def('intensity'):
496
+ intz0, intctl = simc.intensity
497
+ dif.setintensities(intctl, intz0)
498
+
499
+ if simc._check_def('gctl'):
500
+ dif.setgctl(simc.gctl)
501
+
502
+ if simc._check_def('zctl'):
503
+ dif.setzctl(simc.zctl)
504
+ dif.setzctl(simc.zctl)
505
+
506
+ target.generateDP = generateDP
507
+ target._get_diffraction = _get_diffraction
508
+ target.generateDif=generateDif
509
+ target.d2r = d2r
510
+ target.r2d = r2d
511
+ target.angle = angle
512
+ target.vlen = vlen
513
+ target.wavelength = wavelength
514
+ target.set_sim_controls = set_sim_controls
515
+ target.load = load
516
+ target.unload = unload
517
+
518
+
519
+ return target
@@ -0,0 +1,175 @@
1
+ '''
2
+ .. This file is part of pyEMAPS
3
+
4
+ .. ----
5
+
6
+ .. pyEMAPS is free software. You can redistribute it and/or modify
7
+ .. it under the terms of the GNU General Public License as published
8
+ .. by the Free Software Foundation, either version 3 of the License,
9
+ .. or (at your option) any later version..
10
+
11
+ .. pyEMAPS is distributed in the hope that it will be useful,
12
+ .. but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ .. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ .. GNU General Public License for more details.
15
+
16
+ .. You should have received a copy of the GNU General Public License
17
+ .. along with pyEMAPS. If not, see `<https://www.gnu.org/licenses/>`_.
18
+
19
+ .. Contact supprort@emlabsoftware.com for any questions and comments.
20
+
21
+ .. ----
22
+
23
+ .. Author: EMLab Solutions, Inc.
24
+ .. Date Created: May 07, 2022
25
+
26
+ '''
27
+ def add_dpgen(target):
28
+ try:
29
+ from . import dif, dpgen
30
+
31
+ except ImportError as e:
32
+ # return an empty target if non-extant
33
+ return target
34
+ else:
35
+ LOW_RES = dpgen.get_lowres()
36
+ HIGH_RES = dpgen.get_highres()
37
+
38
+ import numpy as np
39
+ from numpy import asfortranarray as farray
40
+ from .. import DEF_XAXIS, DEF_KV, DEF_ZONE, DEF_CL, \
41
+ SIMC, EMC
42
+
43
+ from .. import DPError
44
+
45
+ DPDB_EXT = 'bin'
46
+ MAX_DPDBFN = 256
47
+ DEF_VERTMAT = [[0,0,1],[1,1,1],[0,1,1]]
48
+
49
+ def _getDPDBFN(self):
50
+ '''
51
+ Constructs a bloch image output file name.
52
+
53
+ Refer to :ref:`Environment Variables <Environment Variables>`
54
+ for how this file name is constructed.
55
+
56
+ '''
57
+
58
+ from ..fileutils import compose_ofn
59
+
60
+ cfn = compose_ofn(None, self.name, ty='dpdb')
61
+
62
+ l = len(cfn)
63
+ if l > MAX_DPDBFN:
64
+ raise DPError('Diffraction database file name must not excced 256')
65
+
66
+ return cfn
67
+
68
+ def generateDPDB(self, emc = EMC(),
69
+ xa = DEF_XAXIS,
70
+ res = LOW_RES,
71
+ vertices = DEF_VERTMAT
72
+ ):
73
+
74
+ """
75
+ Generate a list diffraction patterns and save them in proprietory
76
+ binary formatted database file with extension .bin.
77
+
78
+ The database created will be used for diffraction pattern indexing
79
+ and matchig functions in pyemaps STEM4D module.
80
+
81
+ The generated database file is saved to directory pointed by environment variable
82
+ *PYEMAPS_DATA* or in current working directory if *PYEMAPS_DATA* is not set.
83
+
84
+ :param emc: Control parameters
85
+ :type emc: EMControls, optional
86
+
87
+ :param xa: x-axis, optional
88
+ :type xa: three integer tuple.
89
+
90
+ :param res: resolution of stereo projection map, ranging from *LOW_RES*=100 to *HIGH_RES*=300 that is
91
+ the number of sampling points along the radius. The higher the resolution, the more
92
+ diffraction patterns are generated in the database file.
93
+
94
+ :type res: integer, defaults to 100, optional.
95
+
96
+ :param vertices: an array of 3 or 4 zone axis indexes that form an enclosed orientation
97
+ surface area within which the diffraction patterns are generated. See the following
98
+ graphic illustration of the vertices input.
99
+
100
+ :type vertices: three integer tuple, optional
101
+
102
+ :return: a tuple of a status code and database file name
103
+ :rtype: tuple of an integer and a string
104
+
105
+
106
+ Input zone axis indexes define the vertices of the stereo projection map. The default
107
+ for a cubic crystal is *DEF_VERTMAT* = [[0,0,1],[1,1,1],[0,1,1]].
108
+
109
+ .. image:: https://github.com/emlab-solutions/imagepypy/raw/main/stereoprojectionmap.png
110
+ :width: 75%
111
+ :align: center
112
+
113
+ The diffraction patterns database file produced will be consumed by pyemaps stem4d module
114
+ for experimental diffraction pattern serach and indexing.
115
+
116
+ """
117
+ import os
118
+
119
+ if (res > HIGH_RES) or (res < LOW_RES):
120
+ print(f'Resolution input {res} is out of range: ({LOW_RES}, {HIGH_RES})')
121
+ return -1, None
122
+
123
+ self.load()
124
+ dif.initcontrols()
125
+
126
+ vt = emc.vt
127
+ zone = emc.zone
128
+ emc(xaxis=xa)
129
+ simc = emc.simc
130
+
131
+ if vt != DEF_KV:
132
+ dif.setemcontrols(DEF_CL, vt)
133
+
134
+ if zone != DEF_ZONE:
135
+ dif.setzone(zone[0], zone[1], zone[2])
136
+
137
+ if xa != DEF_XAXIS:
138
+ dif.set_xaxis(1, xa[0], xa[1], xa[2])
139
+
140
+ self.set_sim_controls(simc=simc)
141
+
142
+
143
+ # TODO: need to replace hard code of 2 here later
144
+ ret = dif.diffract(2)
145
+
146
+ if ret == 0:
147
+ print('Error running dif module')
148
+ return -1, None
149
+ vert = np.array(vertices).transpose()
150
+ vertices = farray(vert, dtype=int)
151
+
152
+ output_fn = self._getDPDBFN()
153
+
154
+ final_fp= output_fn+'.' + DPDB_EXT
155
+
156
+ ret = dpgen.do_dpgen(res, vertices, output_fn)
157
+
158
+ #release the memory
159
+ dpgen.cleanup()
160
+
161
+ if ret != 0:
162
+ print(f'Error generating diffraction patterns for {self.name}')
163
+ return -1, final_fp
164
+
165
+ print('*******************************************************************************')
166
+ print(f'* The diffraction pattern database for {self.name} has been generated successfully')
167
+ print(f'* and saved in:')
168
+ print(f'* {final_fp}')
169
+ print('*******************************************************************************')
170
+ return 0, final_fp
171
+
172
+ target.generateDPDB = generateDPDB
173
+ target._getDPDBFN = _getDPDBFN
174
+
175
+ return target