{ "cells": [ { "cell_type": "markdown", "id": "4d8e73c9", "metadata": { "nbsphinx": "hidden" }, "source": [ "This notebook is part of the *orix* documentation https://orix.readthedocs.io. Links to the documentation wonâ€™t work from the notebook." ] }, { "cell_type": "markdown", "id": "a59fef6b", "metadata": {}, "source": [ "# Sampling unit vectors\n", "\n", "Sampling unit vectors or directions in 3D space is equivalent to sampling points on the surface of the unit sphere ($S_2$).\n", "There are multiple use cases for discretizing and sampling this space, for example for creating custom legends for inverse pole figure maps or for creating a list of unique crystal directions.\n", "Except for the platonic solids, it is not possible to sample the sphere surface such that each vector has an identical neighborhood, i.e. equal angles between nearest neighbors.\n", "A number of sampling or \"meshing\" techniques exist, a number of which have been implemented in [orix.sampling.sample_S2()](../reference/generated/orix.sampling.sample_S2.rst) and demonstrated in this tutorial." ] }, { "cell_type": "code", "execution_count": null, "id": "a3034ae9", "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "\n", "import matplotlib.pyplot as plt\n", "\n", "from orix import plot\n", "from orix.quaternion import symmetry\n", "from orix.sampling import sample_S2_methods, sample_S2\n", "\n", "\n", "plt.rcParams.update({\"font.size\": 20, \"lines.markersize\": 2})" ] }, { "cell_type": "markdown", "id": "c7f9e64c", "metadata": {}, "source": [ "## Sampling methods\n", "\n", "Currently, seven sampling methods are supported, demonstrated below by plotting in stereographic projection, each with different regions of higher and lower sampling density.\n", "We should mainly decide on the resolution parameter, which determines the maximum angle (in degrees) between nearest neighbors except in the random sample where it determines the *average* angle between nearest neighbors." ] }, { "cell_type": "code", "execution_count": null, "id": "4c696bea", "metadata": { "nbsphinx-thumbnail": { "tooltip": "Sampling directions on orientation space S2" }, "tags": [ "nbsphinx-thumbnail" ] }, "outputs": [], "source": [ "fig, axes = plt.subplots(\n", " 2,\n", " 4,\n", " subplot_kw=dict(projection=\"stereographic\"),\n", " figsize=(20, 10),\n", " facecolor=\"white\",\n", ")\n", "axes = axes.ravel()\n", "\n", "for i, sampling_method in enumerate(sample_S2_methods):\n", " vectors = sample_S2(resolution=5, method=sampling_method)\n", " axes[i].set_title(sampling_method, pad=20)\n", " axes[i].set_labels(\"X\", \"Y\", None)\n", " axes[i].scatter(vectors);" ] }, { "cell_type": "markdown", "id": "a8fe0e70", "metadata": {}, "source": [ "## Sampling the fundamental zone\n", "\n", "Sampling of directions is most relevant when combined with crystal symmetry functionality.\n", "In this case, we would want to sample directions in the real crystallographic basis.\n", "Usually one only wants to sample the fundamental zone, not the entire sphere, as in the context of a crystal, many directions are symmetrically equivalent.\n", "The fundamental zone of a point group represents the smallest region of symmetrically unique directions.\n", "The higher the symmetry of the point group, the smaller the fundamental zone.\n", "\n", "The symmetry operations are independent of the $S_2$ sampling methods, so any set of vectors can be limited to the fundamental zone.\n", "However, different meshes may be more appropriate for different point groups, as we illustrate below.\n", "In general, to sample vectors for crystals with $\\alpha=\\beta=\\gamma=90^\\circ$, one of the cube meshes is recommended.\n", "For trigonal or hexagonal crystals that have a 3 or 6-fold axis along [001], a hexagonal mesh is recommended.\n", "This ensures that the boundary of the fundamental zone is also sampled at regular intervals, otherwise some of these edges may appear \"ragged\".\n", "For lower symmetry crystals, most samplings methods are suitable, and icosahedral sampling is recommended as the points are most evenly spaced.\n", "\n", "Below we demonstrate sampling of the fundamental zone for all 32 point groups." ] }, { "cell_type": "code", "execution_count": null, "id": "cf18d8c9", "metadata": {}, "outputs": [], "source": [ "point_groups = symmetry._groups\n", "\n", "color_map = {\n", " \"triclinic\": \"red\",\n", " \"monoclinic\": \"orange\",\n", " \"orthorhombic\": \"green\",\n", " \"tetragonal\": \"blue\",\n", " \"cubic\": \"brown\",\n", " \"trigonal\": \"magenta\",\n", " \"hexagonal\": \"purple\",\n", "}\n", "\n", "s2_sampling_map = {\n", " \"triclinic\": \"icosahedral\",\n", " \"monoclinic\": \"icosahedral\",\n", " \"orthorhombic\": \"spherified_cube_edge\",\n", " \"tetragonal\": \"spherified_cube_edge\",\n", " \"cubic\": \"spherified_cube_edge\",\n", " \"trigonal\": \"hexagonal\",\n", " \"hexagonal\": \"hexagonal\",\n", "}\n", "\n", "fig, axes = plt.subplots(\n", " len(point_groups),\n", " 2,\n", " subplot_kw=dict(projection=\"stereographic\"),\n", " figsize=(10, 5 * len(point_groups)),\n", " facecolor=\"white\",\n", ")\n", "\n", "for i, point_group in enumerate(point_groups):\n", " system = point_group.system\n", " color = color_map[system]\n", " sampling_method = s2_sampling_map[system]\n", " mesh = sample_S2(resolution=3, method=sampling_method)\n", " fundamental = mesh[mesh <= point_group.fundamental_sector]\n", " axes[i][0].set_title(\n", " f\"{point_group.name} ({system}) (upper)\", fontsize=17\n", " )\n", " axes[i][0].scatter(fundamental, c=color)\n", " axes[i][1].set_title(\n", " f\"{point_group.name} ({system}) (lower)\", fontsize=17\n", " )\n", " axes[i][1].hemisphere = \"lower\"\n", " axes[i][1].scatter(fundamental, c=color);" ] } ], "metadata": { "interpreter": { "hash": "4396f389b93e7269692bd3bea4c62813bbe379469bde939b058805f538feec11" }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.8" } }, "nbformat": 4, "nbformat_minor": 5 }