diff --git a/.gitignore b/.gitignore index a4d98312..6ed8410d 100644 --- a/.gitignore +++ b/.gitignore @@ -212,3 +212,4 @@ notebooks/Imaging/data/lineweight.txt notebooks/EELS/relax.csv Untitled.ipynb example_data/GOLD-NP-DIFF-2-3.hf5 +example_data/GOLD-NP-DIFF-2-4.hf5 diff --git a/notebooks/EELS/Analyse_Low_Loss.ipynb b/notebooks/EELS/Analyse_Low_Loss.ipynb index db7846ed..55e68ae9 100644 --- a/notebooks/EELS/Analyse_Low_Loss.ipynb +++ b/notebooks/EELS/Analyse_Low_Loss.ipynb @@ -65,15 +65,71 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "installing pyTEMlib\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\numpy-1.24.4.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pywinpty-2.0.10.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pyzmq-25.1.0.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\numpy-1.24.4.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pywinpty-2.0.10.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pyzmq-25.1.0.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\numpy-1.24.4.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pywinpty-2.0.10.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pyzmq-25.1.0.dist-info due to invalid metadata entry 'name'\n", + " WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + " WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\numpy-1.24.4.dist-info due to invalid metadata entry 'name'\n", + " WARNING: The script f2py.exe is installed in 'C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Scripts' which is not on PATH.\n", + " Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\n", + "ERROR: Cannot uninstall 'llvmlite'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pywinpty-2.0.10.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pyzmq-25.1.0.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n" + ] + }, { "name": "stdout", "output_type": "stream", "text": [ "done\n" ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pywinpty-2.0.10.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pyzmq-25.1.0.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pywinpty-2.0.10.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pyzmq-25.1.0.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pywinpty-2.0.10.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pyzmq-25.1.0.dist-info due to invalid metadata entry 'name'\n", + "ERROR: Cannot uninstall 'llvmlite'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pywinpty-2.0.10.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\pyzmq-25.1.0.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n", + "WARNING: Skipping C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pyTEMlib\\Lib\\site-packages\\matplotlib-3.7.2.dist-info due to invalid metadata entry 'name'\n" + ] } ], "source": [ @@ -88,7 +144,7 @@ " return version\n", "\n", "# pyTEMlib setup ------------------\n", - "if test_package('pyTEMlib') < '0.2023.9.1':\n", + "if test_package('pyTEMlib') < '0.2024.1.0':\n", " print('installing pyTEMlib')\n", " !{sys.executable} -m pip install --upgrade git+https://github.com/pycroscopy/SciFiReaders.git@main -q\n", " !{sys.executable} -m pip install --upgrade git+https://github.com/pycroscopy/pyTEMlib.git@main -q --upgrade\n", @@ -113,7 +169,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 5, "metadata": { "hideCode": false, "hidePrompt": false, @@ -124,10 +180,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "You don't have igor2 installed. If you wish to open igor files, you will need to install it (pip install igor2) before attempting.\n", - "You don't have gwyfile installed. If you wish to open .gwy files, you will need to install it (pip install gwyfile) before attempting.\n", - "Symmetry functions of spglib enabled\n", - "Using kinematic_scattering library version {_version_ } by G.Duscher\n", + "The autoreload extension is already loaded. To reload it, use:\n", + " %reload_ext autoreload\n", "pyTEM version: 0.2024.01.0\n" ] } @@ -180,7 +234,7 @@ }, { "cell_type": "code", - "execution_count": 168, + "execution_count": 7, "metadata": { "hideCode": false, "hidePrompt": false, @@ -188,18 +242,18 @@ }, "outputs": [ { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c1cbca65c75a4c88b5ae89d4428bc3bd", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(Dropdown(description='directory:', layout=Layout(width='90%'), options=('C:\\\\Users\\\\gduscher\\\\D…" - ] - }, - "metadata": {}, - "output_type": "display_data" + "ename": "FileNotFoundError", + "evalue": "[WinError 3] The system cannot find the path specified: '../example_data'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[7], line 6\u001b[0m\n\u001b[0;32m 4\u001b[0m filename \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m../../example_data/AL-DFoffset0.00.dm3\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[0;32m 5\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpyTEMlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01minfo_widget\u001b[39;00m\n\u001b[1;32m----> 6\u001b[0m infoWidget\u001b[38;5;241m=\u001b[39m \u001b[43mpyTEMlib\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minfo_widget\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mInfoWidget\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m.\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32m~\\Documents\\Github\\pyTEMlib\\notebooks\\EELS\\../..\\pyTEMlib\\info_widget.py:565\u001b[0m, in \u001b[0;36mInfoWidget.__init__\u001b[1;34m(self, datasets)\u001b[0m\n\u001b[0;32m 562\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\u001b[38;5;28mself\u001b[39m, datasets\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m):\n\u001b[0;32m 564\u001b[0m sidebar \u001b[38;5;241m=\u001b[39m get_info_sidebar()\n\u001b[1;32m--> 565\u001b[0m \u001b[38;5;28;43msuper\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;21;43m__init__\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mdatasets\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msidebar\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 566\u001b[0m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39mset_dataset()\n\u001b[0;32m 567\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mset_action()\n", + "File \u001b[1;32m~\\Documents\\Github\\pyTEMlib\\notebooks\\EELS\\../..\\pyTEMlib\\info_widget.py:163\u001b[0m, in \u001b[0;36mEELSWidget.__init__\u001b[1;34m(self, datasets, sidebar, tab_title)\u001b[0m\n\u001b[0;32m 160\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39misdir(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdir_name):\n\u001b[0;32m 161\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdir_name \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m--> 163\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_directory\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdir_name\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 164\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdir_list \u001b[38;5;241m=\u001b[39m [\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m'\u001b[39m]\n\u001b[0;32m 165\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mextensions \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m*\u001b[39m\u001b[38;5;124m'\u001b[39m\n", + "File \u001b[1;32m~\\Documents\\Github\\pyTEMlib\\notebooks\\EELS\\../..\\pyTEMlib\\info_widget.py:500\u001b[0m, in \u001b[0;36mEELSWidget.get_directory\u001b[1;34m(self, directory)\u001b[0m\n\u001b[0;32m 498\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdir_dictionary \u001b[38;5;241m=\u001b[39m {}\n\u001b[0;32m 499\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdir_list \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m--> 500\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdir_list \u001b[38;5;241m=\u001b[39m [\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m..\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m+\u001b[39m \u001b[43mos\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlistdir\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdirectory\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[1;31mFileNotFoundError\u001b[0m: [WinError 3] The system cannot find the path specified: '../example_data'" + ] } ], "source": [ @@ -208,7 +262,7 @@ " \n", "filename = '../../example_data/AL-DFoffset0.00.dm3'\n", "import pyTEMlib.info_widget\n", - "infoWidget= pyTEMlib.info_widget.InfoWidget()" + "infoWidget= pyTEMlib.info_widget.InfoWidget('.')" ] }, { diff --git a/notebooks/Imaging/Register_Image_Stack.ipynb b/notebooks/Imaging/Register_Image_Stack.ipynb index 4f9cea41..dd85c70f 100644 --- a/notebooks/Imaging/Register_Image_Stack.ipynb +++ b/notebooks/Imaging/Register_Image_Stack.ipynb @@ -171,8 +171,7 @@ "\n", "import skimage\n", "\n", - "if 'google.colab' in sys.modules:\n", - " drive.mount(\"/content/drive\")\n", + "\n", " \n", "# For archiving reasons it is a good idea to print the version numbers out at this point\n", "print('pyTEM version: ',pyTEMlib.__version__)\n", @@ -215,6 +214,8 @@ } ], "source": [ + "if 'google.colab' in sys.modules:\n", + " drive.mount(\"/content/drive\")\n", "fileWidget = ft.FileWidget()" ] }, diff --git a/pyTEMlib/config_dir.py b/pyTEMlib/config_dir.py index 863816e1..8e3ee19e 100644 --- a/pyTEMlib/config_dir.py +++ b/pyTEMlib/config_dir.py @@ -7,7 +7,6 @@ config_dir: setup of directory ~/.pyTEMlib for custom sources and database """ import os -import numpy as np # import wget if os.name == 'posix': diff --git a/pyTEMlib/image_tools.py b/pyTEMlib/image_tools.py index 60d79f81..96a9ec79 100644 --- a/pyTEMlib/image_tools.py +++ b/pyTEMlib/image_tools.py @@ -247,6 +247,8 @@ def diffractogram_spots(dset, spot_threshold, return_center = True, eps = 0.1): # third row is angles spots[:, 2] = np.arctan2(spots[:, 0], spots[:, 1]) + center = [0, 0] + if return_center == True: points = spots[:, 0:2] @@ -802,7 +804,7 @@ def onclick(event): else: vmax = data.max() vmin = data.min() - onselect(vmin, vmax) + onselect(vmin, vmax) fig2 = plt.figure() diff --git a/pyTEMlib/kinematic_scattering.py b/pyTEMlib/kinematic_scattering.py index f48769fb..a30aef44 100644 --- a/pyTEMlib/kinematic_scattering.py +++ b/pyTEMlib/kinematic_scattering.py @@ -26,9 +26,12 @@ # numerical packages used import numpy as np -import scipy.constants as const +import scipy import itertools +import ase +import ase.build + # plotting package used import matplotlib.pylab as plt # basic plotting @@ -86,8 +89,6 @@ def Zuo_fig_3_18(verbose=True): # Create Silicon structure (Could be produced with Silicon routine) if verbose: print('Sample Input for Figure 3.18 in Zuo and Spence \"Advanced TEM\", 2017') - import ase - import ase.build a = 5.14 # A atoms = ase.build.bulk('Si', 'diamond', a=a, cubic=True) @@ -147,31 +148,31 @@ def Zuo_fig_3_18(verbose=True): return atoms -def zone_mistilt(zone, angles): +def get_rotation_matrix(angles, in_radians=False): """ Rotation of zone axis by mistilt - Parameters - ---------- - zone: list or numpy array of int - zone axis in Miller indices - angles: ist or numpy array of float - list of mistilt angles in degree + Parameters + ---------- + angles: ist or numpy array of float + list of mistilt angles (default in degrees) + in_radians: boolean default False + default is angles in degrees - Returns - ------- - new_zone_axis: np.ndarray (3) - new tilted zone axis - """ + Returns + ------- + rotation_matrix: np.ndarray (3x3) + rotation matrix in 3d + """ if not isinstance(angles, (np.ndarray, list)): raise TypeError('angles must be a list of float of length 3') if len(angles) != 3: raise TypeError('angles must be a list of float of length 3') - if not isinstance(zone, (np.ndarray, list)): - raise TypeError('Miller indices must be a list of int of length 3') - - alpha, beta, gamma = np.radians(angles) + if in_radians: + alpha, beta, gamma = angles + else: + alpha, beta, gamma = np.radians(angles) # first we rotate alpha about x-axis c, s = np.cos(alpha), np.sin(alpha) rot_x = np.array([[1, 0, 0], [0, c, -s], [0, s, c]]) @@ -183,8 +184,29 @@ def zone_mistilt(zone, angles): # third we rotate gamma about z-axis c, s = np.cos(gamma), np.sin(gamma) rot_z = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]]) + return np.dot(np.dot(rot_x, rot_y), rot_z) + + +def zone_mistilt(zone, angles): + """ Rotation of zone axis by mistilt + + Parameters + ---------- + zone: list or numpy array of int + zone axis in Miller indices + angles: ist or numpy array of float + list of mistilt angles in degree + + Returns + ------- + new_zone_axis: np.ndarray (3) + new tilted zone axis + """ + if not isinstance(zone, (np.ndarray, list)): + raise TypeError('Miller indices must be a list of int of length 3') - return np.dot(np.dot(np.dot(zone, rot_x), rot_y), rot_z) + rotation_matrix = get_rotation_matrix(angles) + return np.dot(zone, rotation_matrix) def get_metric_tensor(matrix): @@ -213,12 +235,27 @@ def get_wavelength(acceleration_voltage): Returns: ------- wavelength: float - wave length in Angstrom + wave length in Angstrom (= meter *10**10) """ if not isinstance(acceleration_voltage, (int, float)): raise TypeError('Acceleration voltage has to be a real number') - eU = const.e * acceleration_voltage - return const.h/np.sqrt(2*const.m_e*eU*(1+eU/(2*const.m_e*const.c**2)))*10**10 + + E = acceleration_voltage * scipy.constants.elementary_charge + h = scipy.constants.Planck + m0 = scipy.constants.electron_mass + c = scipy.constants.speed_of_light + wavelength = h / np.sqrt(2 * m0 * E * (1 + (E / (2 * m0 * c ** 2)))) + return wavelength * 10**10 + + +def get_all_miller_indices(hkl_max): + h = np.linspace(-hkl_max, hkl_max, 2 * hkl_max + 1) # all evaluated single Miller Indices + hkl = np.array(list(itertools.product(h, h, h))) # all evaluated Miller indices + + # delete [0,0,0] + index_center = int(len(hkl) / 2) + hkl = np.delete(hkl, index_center, axis=0) # delete [0,0,0] + return hkl def find_nearest_zone_axis(tags): @@ -226,12 +263,7 @@ def find_nearest_zone_axis(tags): hkl_max = 5 # Make all hkl indices - h = np.linspace(-hkl_max, hkl_max, 2 * hkl_max + 1) # all evaluated single Miller Indices - hkl = np.array(list(itertools.product(h, h, h))) # all evaluated Miller indices - - # delete [0,0,0] - index = int(len(hkl) / 2) - zones_hkl = np.delete(hkl, index, axis=0) # delete [0,0,0] + zones_hkl = get_all_miller_indices(hkl_max) # make zone axis in reciprocal space zones_g = np.dot(zones_hkl, tags['reciprocal_unit_cell']) # all evaluated reciprocal_unit_cell points @@ -285,15 +317,10 @@ def find_angles(zone): def stage_rotation_matrix(alpha, beta): """ Microscope stage coordinate system """ - - # FIRST we rotate beta about x-axis - c, s = np.cos(beta), np.sin(beta) - rot_x = np.array([[1, 0, 0], [0, c, -s], [0, s, c]]) - # second we rotate alpha about y-axis - c, s = np.cos(alpha), np.sin(alpha) - rot_y = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]]) - return np.dot(rot_x, rot_y) + # FIRST we rotate beta about x-axis + angles = [beta, alpha, 0.] + return get_rotation_matrix(angles, in_radians=True) # ################## @@ -301,7 +328,8 @@ def stage_rotation_matrix(alpha, beta): # We determine spherical coordinates to do that # ################## -def get_rotation_matrix(tags): + +def get_zone_rotation(tags): """zone axis in global coordinate system""" zone_hkl = tags['zone_hkl'] @@ -504,13 +532,7 @@ def ring_pattern_calculation(atoms, verbose=False): # inverse_metric_tensor = get_metric_tensor(reciprocal_unit_cell) hkl_max = tags['hkl_max'] - - h = np.linspace(-hkl_max, hkl_max, 2 * hkl_max + 1) # all evaluated single Miller Indices - hkl = np.array(list(itertools.product(h, h, h))) # all evaluated Miller indices - - # delete [0,0,0] - index_center = int(len(hkl) / 2) - hkl = np.delete(hkl, index_center, axis=0) # delete [0,0,0] + hkl = get_all_miller_indices(hkl_max) g_hkl = np.dot(hkl, reciprocal_unit_cell) # all evaluated reciprocal_unit_cell points @@ -527,7 +549,7 @@ def ring_pattern_calculation(atoms, verbose=False): structure_factors.append(F) - F = structure_factors = np.array(structure_factors) + F = np.array(structure_factors) # structure factors # Sort reflection in allowed and forbidden # @@ -673,7 +695,7 @@ def kinematic_scattering(atoms, verbose=False): # Check sanity if atoms.info is None: atoms.info = {'output': {}, 'experimental': {}} - elif 'output' in atoms.info: + if 'output' in atoms.info: output = atoms.info['output'] else: output = atoms.info['output'] = {} @@ -719,7 +741,11 @@ def kinematic_scattering(atoms, verbose=False): angstrom_conversion = 1.0e10 # So [1A (in m)] * angstrom_conversion = 1 # NanometerConversion = 1.0e9 - scattering_factor_to_volts = (const.h ** 2) * (1e10 ** 2) / (2 * np.pi * const.m_e * const.e) * volume_unit_cell + e = scipy.constants.elementary_charge + h = scipy.constants.Planck + m0 = scipy.constants.electron_mass + + scattering_factor_to_volts = (h**2) * (1e10**2) / (2 * np.pi * m0 * e) * volume_unit_cell tags['inner_potential_V'] = u0 * scattering_factor_to_volts if verbose: print(f'The inner potential is {u0:.1f} V') @@ -746,7 +772,7 @@ def kinematic_scattering(atoms, verbose=False): # ############ # get rotation matrix to rotate zone axis onto z-axis - rotation_matrix = get_rotation_matrix(tags) + rotation_matrix = get_zone_rotation(tags) if verbose: print(f"Rotation alpha {np.rad2deg(tags['y-axis rotation alpha']):.1f} degree, " @@ -854,22 +880,7 @@ def kinematic_scattering(atoms, verbose=False): dif['allowed']['hkl'] = hkl_allowed dif['allowed']['g'] = g_allowed dif['allowed']['structure factor'] = F_allowed - - # Calculate Extinction Distance Reimer 7.23 - # - makes only sense for non-zero F - - xi_g = np.real(np.pi * volume_unit_cell * k_0 / F_allowed) - # Calculate Intensity of beams Reimer 7.25 - if 'thickness' not in tags: - tags['thickness'] = 0. - thickness = tags['thickness'] - if thickness > 0.1: - I_g = np.real(np.pi ** 2 / xi_g ** 2 * np.sin(np.pi * thickness * s_g_allowed) ** 2 / (np.pi * s_g_allowed)**2) - dif['allowed']['Ig'] = I_g - - dif['allowed']['intensities'] = intensities = np.real(F_allowed) ** 2 - # Calculate Extinction Distance Reimer 7.23 # - makes only sense for non-zero F @@ -894,7 +905,7 @@ def kinematic_scattering(atoms, verbose=False): Sg_forbidden = Sg[forbidden] hkl_forbidden = hkl[forbidden] g_forbidden = g_hkl[forbidden] - F_forbidden = F[forbidden] + # F_forbidden = F[forbidden] dif['forbidden'] = {} dif['forbidden']['Sg'] = Sg_forbidden @@ -1050,7 +1061,7 @@ def kinematic_scattering(atoms, verbose=False): tags_kikuchi['Laue_circle'] = laue_circle # Rotate to nearest zone axis - rotation_matrix = get_rotation_matrix(tags_kikuchi) + rotation_matrix = get_zone_rotation(tags_kikuchi) g_kikuchi_all = np.dot(g_non_rot, rotation_matrix) @@ -1098,452 +1109,6 @@ def kinematic_scattering(atoms, verbose=False): print('pyTEMlib\'s \"kinematic_scattering\" finished') -def kinematic_scattering2(atoms, verbose=False): - """ - All kinematic scattering calculation - - Calculates Bragg spots, Kikuchi lines, excess, and deficient HOLZ lines - - Parameters - ---------- - atoms: ase.Atoms - object with crystal structure: - and with experimental parameters in info attribute: - 'acceleration_voltage_V', 'zone_hkl', 'Sg_max', 'hkl_max' - Optional parameters are: - 'mistilt', convergence_angle_mrad', and 'crystal_name' - verbose = True will give extended output of the calculation - verbose: boolean - default is False - - Returns - ------- - ato,s: - There are three sub_dictionaries in info attribute: - ['allowed'], ['forbidden'], and ['HOLZ'] - ['allowed'] and ['forbidden'] dictionaries contain: - ['Sg'], ['hkl'], ['g'], ['structure factor'], ['intensities'], - ['ZOLZ'], ['FOLZ'], ['SOLZ'], ['HOLZ'], ['HHOLZ'], ['label'], and ['Laue_zone'] - the ['HOLZ'] dictionary contains: - ['slope'], ['distance'], ['theta'], ['g_deficient'], ['g_excess'], ['hkl'], ['intensities'], - ['ZOLZ'], ['FOLZ'], ['SOLZ'], ['HOLZ'], and ['HHOLZ'] - Please note that the Kikuchi lines are the HOLZ lines of ZOLZ - - There are also a few parameters stored in the main dictionary: - ['wave_length_nm'], ['reciprocal_unit_cell'], ['inner_potential_V'], ['incident_wave_vector'], - ['volume'], ['theta'], ['phi'], and ['incident_wave_vector_vacuum'] - """ - - # Check sanity - if atoms.info is None: - atoms.info = {'output': {}, 'experimental': {}} - elif 'output' in atoms.info: - output = atoms.info['output'] - else: - output = atoms.info['output'] = {} - - output['SpotPattern'] = True - - if 'experimental' not in atoms.info: - tags = atoms.info['experimental'] = {} - - if not check_sanity(atoms): - print('Input is not complete, stopping') - print('Try \'example()\' for example input') - return - - tags = atoms.info['experimental'] - - # wavelength - tags['wave_length'] = get_wavelength(tags['acceleration_voltage_V']) - - # volume of unit_cell - unit_cell = atoms.cell.array - metric_tensor = get_metric_tensor(unit_cell) # converts hkl to g vectors and back - tags['metric_tensor'] = metric_tensor - volume_unit_cell = atoms.cell.volume - - # reciprocal_unit_cell - - # We use the linear algebra package of numpy to invert the unit_cell "matrix" - reciprocal_unit_cell = atoms.cell.reciprocal() # np.linalg.inv(unit_cell).T # transposed of inverted unit_cell - tags['reciprocal_unit_cell'] = reciprocal_unit_cell - inverse_metric_tensor = get_metric_tensor(reciprocal_unit_cell) - - if verbose: - print('reciprocal_unit_cell') - print(np.round(reciprocal_unit_cell, 3)) - - ############################################ - # Incident wave vector k0 in vacuum and material - ############################################ - - u0 = 0.0 # in (Ang) - # atom form factor of zero reflection angle is the inner potential in 1/A - for i in range(len(atoms)): - u0 += feq(atoms[i].symbol, 0.0) - - scattering_factor_to_volts = (const.h ** 2) * (1e10 ** 2) / (2 * np.pi * const.m_e * const.e) * volume_unit_cell - - tags['inner_potential_V'] = u0 * scattering_factor_to_volts - if verbose: - print(f'The inner potential is {u0:.1f} V') - - # Calculating incident wave vector magnitude 'k0' in material - wl = tags['wave_length'] - tags['incident_wave_vector_vacuum'] = 1 / wl - - k0 = tags['incident_wave_vector'] = np.sqrt(1 / wl**2 + u0) # 1/Ang - - tags['convergence_angle_A-1'] = k0 * np.sin(tags['convergence_angle_mrad'] / 1000.) - if verbose: - print(f"Using an acceleration voltage of {tags['acceleration_voltage_V']/1000:.1f}kV") - print(f'Magnitude of incident wave vector in material: {k0:.1f} 1/Ang and in vacuum: {1/wl:.1f} 1/Ang') - print(f"Which is an wave length of {1 / k0 * 100.:.3f} pm in the material and {wl * 100.:.3f} pm " - f"in the vacuum") - print(f"The convergence angle of {tags['convergence_angle_mrad']:.1f}mrad " - f"= {tags['convergence_angle_A-1']:.2f} 1/A") - print(f"Magnitude of incident wave vector in material: {k0:.1f} 1/A which is a wavelength {100/k0:.3f} pm") - - # ############ - # Rotate - # ############ - - # get rotation matrix to rotate zone axis onto z-axis - rotation_matrix = get_rotation_matrix(tags) - - if verbose: - print(f"Rotation alpha {np.rad2deg(tags['y-axis rotation alpha']):.1f} degree, " - f" beta {np.rad2deg(tags['x-axis rotation beta']):.1f} degree") - print(f"from zone axis {tags['zone_hkl']}") - print(f"Tilting {1} by {np.rad2deg(tags['mistilt_alpha']):.2f} " - f" in alpha and {np.rad2deg(tags['mistilt_beta']):.2f} in beta direction results in :") - # list(tags['zone_hkl']) - # - # print(f"zone axis {list(tags['nearest_zone_axis'])} with a mistilt of " - # f"{np.rad2deg(tags['mistilt_nearest_zone alpha']):.2f} in alpha " - # f"and {np.rad2deg(tags['mistilt_nearest_zone beta']):.2f} in beta direction") - nearest = tags['nearest_zone_axes'] - print('Next nearest zone axes are:') - for i in range(1, nearest['amount']): - print(f"{nearest[str(i)]['hkl']}: mistilt: {np.rad2deg(nearest[str(i)]['mistilt_alpha']):6.2f}, " - f"{np.rad2deg(nearest[str(i)]['mistilt_beta']):6.2f}") - k0_unit_vector = np.array([0, 0, 1]) # incident unit wave vector - k0_vector = k0_unit_vector * k0 # incident wave vector - cent = k0_vector # center of Ewald sphere - - if verbose: - print('Center of Ewald sphere ', cent) - - # Find all Miller indices whose reciprocal point lays near the Ewald sphere with radius k0 - # within a maximum excitation error Sg - hkl_max = tags['hkl_max'] - Sg_max = tags['Sg_max'] # 1/A maximum allowed excitation error - - h = np.linspace(-hkl_max, hkl_max, 2 * hkl_max + 1) # all evaluated single Miller indices - hkl = np.array(list(itertools.product(h, h, h))) # all evaluated Miller indices - g_non_rot = np.dot(hkl, reciprocal_unit_cell) # all evaluated reciprocal_unit_cell points - - g = np.dot(g_non_rot, rotation_matrix) # rotate these reciprocal_unit_cell points - g_norm = vector_norm(g) # length of all vectors - not_zero = g_norm > 0 - g = g[not_zero] # zero reflection will make problems further on, so we exclude it. - g_non_rot = g_non_rot[not_zero] - g_norm = g_norm[not_zero] - hkl = hkl[not_zero] - - # Calculate excitation errors for all reciprocal_unit_cell points - # Zuo and Spence, 'Adv TEM', 2017 -- Eq 3:14 - S = (k0 ** 2 - vector_norm(g - cent) ** 2) / (2 * k0) - g_mz = g - k0_vector - in_sqrt = g_mz[:, 2]**2 + np.linalg.norm(g_mz, axis=1)**2 - k0**2 - in_sqrt[in_sqrt < 0] = 0. - S2 = -g_mz[:, 2] - np.sqrt(in_sqrt) - - # Determine reciprocal_unit_cell points with excitation error less than the maximum allowed one: Sg_max - - reflections = abs(S) < Sg_max # This is now a boolean array with True for all possible reflections - hkl_all = hkl.copy() - s_g = S[reflections] - g_hkl = g[reflections] - - hkl = hkl[reflections] - g_hkl_non_rot = g_non_rot[reflections] - g_norm = g_norm[reflections] - - if verbose: - print(f"Of the {len(g)} tested reciprocal_unit_cell points, {len(g_hkl)} " - f"have an excitation error less than {Sg_max:.2f} 1/Angstrom") - - # Calculate Structure Factors - base = atoms.positions - structure_factors = [] - for j in range(len(g_hkl)): - F = 0 - for b in range(len(atoms)): - f = feq(atoms[b].symbol, np.linalg.norm(g_hkl[j])) - F += f * np.exp(-2 * np.pi * 1j * (g_hkl_non_rot[j] * atoms.positions[b]).sum()) - - structure_factors.append(F) - - F = structure_factors = np.array(structure_factors) - - # Sort reflection in allowed and forbidden # - allowed = np.absolute(F) > 0.000001 # allowed within numerical error - - if verbose: - print(f"Of the {hkl.shape[0]} possible reflection {allowed.sum()} are allowed.") - - # information of allowed reflections - s_g_allowed = s_g[allowed] - hkl_allowed = hkl[allowed][:] - g_allowed = g_hkl[allowed, :] - F_allowed = F[allowed] - g_norm_allowed = g_norm[allowed] - - atoms.info['diffraction'] = {} - dif = atoms.info['diffraction'] - dif['allowed'] = {} - dif['allowed']['Sg'] = s_g_allowed - dif['allowed']['hkl'] = hkl_allowed - dif['allowed']['g'] = g_allowed - dif['allowed']['structure factor'] = F_allowed - - # Calculate Extinction Distance Reimer 7.23 - # - makes only sense for non-zero F - - xi_g = np.real(np.pi * volume_unit_cell * k0 / F_allowed) - - # Calculate Intensity of beams Reimer 7.25 - if 'thickness' not in tags: - tags['thickness'] = 0. - thickness = tags['thickness'] - if thickness > 0.1: - I_g = np.real(np.pi ** 2 / xi_g ** 2 * np.sin(np.pi * thickness * s_g_allowed) ** 2 / (np.pi * s_g_allowed)**2) - dif['allowed']['Ig'] = I_g - - dif['allowed']['intensities'] = intensities = np.real(F_allowed) ** 2 - - # information of forbidden reflections - forbidden = np.logical_not(allowed) - s_g_forbidden = s_g[forbidden] - hkl_forbidden = hkl[forbidden] - g_forbidden = g_hkl[forbidden] - F_forbidden = F[forbidden] - - dif['forbidden'] = {} - dif['forbidden']['Sg'] = s_g_forbidden - dif['forbidden']['hkl'] = hkl_forbidden.copy() - dif['forbidden']['g'] = g_forbidden - - # Make pretty labels - hkl_label = make_pretty_labels(hkl_allowed) - dif['allowed']['label'] = hkl_label - hkl_label = make_pretty_labels(hkl_forbidden) - dif['forbidden']['label'] = hkl_label - - # Dynamically Allowed Reflection - """ - indices = range(len(hkl_allowed)) - combinations = [list(x) for x in itertools.permutations(indices, 2)] - hkl_forbidden = hkl_forbidden.tolist() - dynamically_allowed = np.zeros(len(hkl_forbidden), dtype=bool) - for [i, j] in combinations: - possible = (hkl_allowed[i] + hkl_allowed[j]).tolist() - if possible in hkl_forbidden: - dynamically - _allowed[hkl_forbidden.index(possible)] = True - dif['forbidden']['dynamically_allowed'] = dynamically_allowed - - if verbose: - print(f"Of the {g_forbidden.shape[0]} forbidden reflection {dif['dynamically_allowed']['g'].shape[0]} " - f"can be dynamically activated.") - # print(dif['forbidden']['hkl'][dynamically_allowed]) - """ - - # Center of Laue Circle - laue_circle = np.dot(tags['nearest_zone_axis'], tags['reciprocal_unit_cell']) - laue_circle = np.dot(laue_circle, rotation_matrix) - laue_circle = laue_circle / np.linalg.norm(laue_circle) * k0 - laue_circle[2] = 0 - - dif['Laue_circle'] = laue_circle - if verbose: - print('Laue_circle', laue_circle) - - # ########################### - # Calculate Laue Zones (of allowed reflections) - # ########################### - # Below is the expression given in most books. - # However, that would only work for orthogonal crystal systems - # Laue_Zone = abs(np.dot(hkl_allowed,tags['zone_hkl'])) # works only for orthogonal systems - - # This expression works for all crystal systems - # Remember we have already tilted, and so the dot product is trivial and gives only the z-component. - - Laue_Zone = abs(np.dot(hkl_allowed, tags['nearest_zone_axis'])) - dif['allowed']['Laue_Zone'] = Laue_Zone - - ZOLZ = Laue_Zone == 0 - FOLZ = Laue_Zone == 1 - SOLZ = Laue_Zone == 2 - HOLZ = Laue_Zone > 2 - - dif['allowed']['ZOLZ'] = ZOLZ - dif['allowed']['FOLZ'] = FOLZ - dif['allowed']['SOLZ'] = SOLZ - dif['allowed']['HOLZ'] = HOLZ - - if verbose: - print(' There are {0} allowed reflections in the zero order Laue Zone'.format(ZOLZ.sum())) - print(' There are {0} allowed reflections in the first order Laue Zone'.format((Laue_Zone == 1).sum())) - print(' There are {0} allowed reflections in the second order Laue Zone'.format((Laue_Zone == 2).sum())) - print(' There are {0} allowed reflections in the higher order Laue Zone'.format((Laue_Zone > 2).sum())) - - if verbose: - print(' hkl \t Laue zone \t Intensity (*1 and \t log) \t length \n') - for i in range(len(hkl_allowed)): - print(' {0} \t {1} \t {2:.3f} \t {3:.3f} \t {4:.3f} '.format(hkl_allowed[i], - g_allowed[i], intensities[i], - np.log(intensities[i] + 1), - g_norm_allowed[i])) - - #################################### - # Calculate HOLZ and Kikuchi Lines # - #################################### - - tags_new_zone = tags.copy() - tags_new_zone['mistilt_alpha'] = 0 - tags_new_zone['mistilt_beta'] = 0 - - for i in range(1): # tags['nearest_zone_axes']['amount']): - - zone_tags = tags['nearest_zone_axes'][str(i)] - - if verbose: - print('Calculating Kikuchi lines for zone: ', zone_tags['hkl']) - - laue_circle = np.dot(zone_tags['hkl'], tags['reciprocal_unit_cell']) - laue_circle = np.dot(laue_circle, rotation_matrix) - laue_circle = laue_circle / np.linalg.norm(laue_circle) * k0 - laue_circle[2] = 0 - - zone_tags['Laue_circle'] = laue_circle - # Rotate to nearest zone axis - - tags_new_zone['zone_hkl'] - - theta = -(zone_tags['mistilt_alpha']) - phi = -(zone_tags['mistilt_beta']) - - # first we rotate phi about z-axis - c, s = np.cos(phi), np.sin(phi) - rot_z = np.array([[1, 0, 0], [0, c, -s], [0, s, c]]) - - # second we rotate theta about y-axis - c, s = np.cos(theta), np.sin(theta) - rot_y = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]]) - - # the rotation now makes z-axis coincide with plane normal - - rotation_matrix2 = np.dot(rot_z, rot_y) - - g_kikuchi_all = np.dot(g, rotation_matrix2) - ZOLZ = abs(g_kikuchi_all[:, 2]) < 1 - - g_kikuchi = g_kikuchi_all[ZOLZ] - S = (k0 ** 2 - vector_norm(g_kikuchi - np.array([0, 0, k0])) ** 2) / (2 * k0) - reflections = abs(S) < 0.1 # This is now a boolean array with True for all possible reflections - g_hkl_kikuchi2 = g_kikuchi[reflections] - hkl_kikuchi2 = (hkl_all[ZOLZ])[reflections] - - structure_factors = [] - for j in range(len(g_hkl_kikuchi2)): - F = 0 - for b in range(len(atoms)): - f = feq(atoms[b].symbol, np.linalg.norm(g_hkl_kikuchi2[j])) - F += f * np.exp(-2 * np.pi * 1j * (g_hkl_kikuchi2[j] * atoms.positions[b]).sum()) - - structure_factors.append(F) - - F = np.array(structure_factors) - - allowed_kikuchi = np.absolute(F) > 0.000001 - - g_hkl_kikuchi = g_hkl_kikuchi2[allowed_kikuchi] - hkl_kikuchi = hkl_kikuchi2[allowed_kikuchi] - - gd2 = g_hkl_kikuchi / 2. - gd2[:, 2] = 0. - - # calculate and save line in Hough space coordinates (distance and theta) - slope2 = gd2[:, 0] / (gd2[:, 1] + 1e-20) - distance2 = np.sqrt(gd2[:, 0] * gd2[:, 0] + gd2[:, 1] * gd2[:, 1]) - theta2 = np.arctan(slope2) - - dif['Kikuchi'] = {} - dif['Kikuchi']['slope'] = slope2 - dif['Kikuchi']['distance'] = distance2 - dif['Kikuchi']['theta'] = theta2 - dif['Kikuchi']['hkl'] = hkl_kikuchi - dif['Kikuchi']['g_hkl'] = g_hkl_kikuchi - dif['Kikuchi']['g_deficient'] = gd2 - dif['Kikuchi']['min dist'] = gd2 + laue_circle - - k_g = k0 - - # Dynamic Correction - # Does not correct ZOLZ lines !!!! - # Equation Spence+Zuo 3.86a - if 'dynamic correction' in tags: - if tags['dynamic correction']: - gamma_1 = - 1. / (2. * k0) * (intensities / (2. * k0 * s_g_allowed)).sum() - if verbose: - print('Dynamic correction gamma_1: ', gamma_1) - - # Equation Spence+Zuo 3.84 - k_g = k0 - k0 * gamma_1 / g_allowed[:, 2] - - # k_g = np.dot( [0,0,k0], rotation_matrix) - # Calculate angle between k0 and deficient cone vector - # For dynamic calculations k0 is replaced by k_g - d_theta = np.arcsin(g_norm_allowed / k_g / 2.) - np.arcsin(np.abs(g_allowed[:, 2]) / g_norm_allowed) - - # calculate length of distance of deficient cone to k0 in ZOLZ plane - gd_length = 2 * np.sin(d_theta / 2) * k0 - - # Calculate nearest point of HOLZ and Kikuchi lines - gd = g_allowed.copy() - gd[:, 0] = -gd[:, 0] * gd_length / g_norm_allowed - gd[:, 1] = -gd[:, 1] * gd_length / g_norm_allowed - gd[:, 2] = 0. - - # calculate and save line in Hough space coordinates (distance and theta) - slope = gd[:, 0] / (gd[:, 1] + 1e-20) - distance = gd_length - theta = np.arctan(slope) - - dif['HOLZ'] = {} - dif['HOLZ']['slope'] = slope - # a line is now given by - dif['HOLZ']['distance'] = distance - dif['HOLZ']['theta'] = theta - dif['HOLZ']['g_deficient'] = gd - dif['HOLZ']['g_excess'] = gd + g_allowed - dif['HOLZ']['g_allowed'] = g_allowed.copy() - - dif['HOLZ']['ZOLZ'] = ZOLZ - dif['HOLZ']['HOLZ'] = np.logical_not(ZOLZ) - dif['HOLZ']['FOLZ'] = FOLZ - dif['HOLZ']['SOLZ'] = SOLZ - dif['HOLZ']['HHOLZ'] = HOLZ # even higher HOLZ - - dif['HOLZ']['hkl'] = dif['allowed']['hkl'] - dif['HOLZ']['intensities'] = intensities - - print('done') - - def make_pretty_labels(hkls, hex_label=False): """Make pretty labels diff --git a/tests/test_kinematic_scattering.py b/tests/test_kinematic_scattering.py index 9e5a1e30..c266ecea 100644 --- a/tests/test_kinematic_scattering.py +++ b/tests/test_kinematic_scattering.py @@ -64,7 +64,7 @@ def test_get_wavelength(self): def test_get_rotation_matrix(self): tags = {'zone_hkl': [1, 1, 1], 'mistilt_alpha': 0, 'mistilt_beta': 0, 'reciprocal_unit_cell': np.identity(3)} - matrix = ks.get_rotation_matrix(tags) + matrix = ks.get_zone_rotation(tags) matrix_desired = [[0.81649658, 0., 0.57735027], [-0.40824829, 0.70710678, 0.5773502], [-0.40824829, -0.70710678, 0.57735027]]