{ "cells": [ { "cell_type": "markdown", "id": "af57c171", "metadata": {}, "source": [ "# Zone Scan\n", "\n", "A crystallographic **zone** is characterized by a set of planes which are all\n", "parallel to one line, called the *zone axis*. (*) If the axis of a zone has indices\n", "{math}`[uvw]`, then any plane belongs to that zone whose indices {math}`(hkl)`\n", "satisfy the relation:\n", "\n", "{math}`hu+kv+lw=0`\n", "\n", "In diffractometer use, a zone is used to align, index, and interpret diffraction patterns. Key uses and practical steps:\n", "\n", "## Purpose\n", " - *Crystal Alignment*: Orient the sample so a chosen zone axis is parallel\n", " to the incident beam or goniometer rotation axis. That places high symmetry\n", " directions into the diffractometer frame and often maximizes systematic\n", " reflections.\n", "- *Indexing*: When the crystal is on a zone axis, all observed\n", " diffraction spots correspond to reflections whose reciprocal-lattice vectors\n", " lie in a plane perpendicular to that axis. This simplifies assignment of\n", " Miller indices.\n", "- *Symmetry determination*: A zone-axis pattern reveals symmetry of the lattice\n", " projection, helping determine lattice type, possible space groups, and\n", " systematic absences.\n", "- *Setting up data collection*: Choosing zone axes for multiple orientations\n", " (e.g., principal axes) helps plan rotation ranges and ensures coverage of\n", " independent reflections.\n", "\n", "\n", "(*) *Elements of X-ray Diffraction*, B.D. Cullity, 1978, Second Edition." ] }, { "cell_type": "code", "execution_count": 1, "id": "85607af9", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from hklpy2.blocks.zone import OrthonormalZone, zone_series, scan_zone\n", "\n", "np.set_printoptions(precision=4, suppress=True, floatmode=\"maxprec\")" ] }, { "cell_type": "code", "execution_count": 2, "id": "6450962e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "zone=OrthonormalZone(axis='undefined')\n", "zone=OrthonormalZone(axis=array([-0.5774, 0.5774, 0.5774]))\n", "OrthonormalZone(axis=v1)=OrthonormalZone(axis=array([0.7071, 0.7071, 0. ]))\n", "OrthonormalZone(axis=[0, 1, 1])=OrthonormalZone(axis=array([0. , 0.7071, 0.7071]))\n", "OrthonormalZone(axis=(1, 2, 3))=OrthonormalZone(axis=array([0.2673, 0.5345, 0.8018]))\n", "OrthonormalZone(axis=dict(u=11, v=22, w=33))=OrthonormalZone(axis=array([0.2673, 0.5345, 0.8018]))\n", "OrthonormalZone(b1=v1, b2=v2)=OrthonormalZone(axis=array([-0.5774, 0.5774, 0.5774]))\n", "zone.in_zone(v1)=True\n", "zone.in_zone(v2)=True\n", "zone.in_zone(v3)=False\n", "v1=array([1, 1, 0])\n", "v2=array([-3, -2, -1])\n" ] } ], "source": [ "v1 = np.array((1, 1, 0))\n", "v2 = np.array((-3, -2, -1))\n", "v3 = np.array((-1, 1, 1))\n", "\n", "zone = OrthonormalZone()\n", "print(f\"{zone=}\")\n", "zone.axis = v3\n", "print(f\"{zone=}\")\n", "print(f\"{OrthonormalZone(axis=v1)=}\")\n", "print(f\"{OrthonormalZone(axis=[0, 1, 1])=}\")\n", "print(f\"{OrthonormalZone(axis=(1, 2, 3))=}\")\n", "print(f\"{OrthonormalZone(axis=dict(u=11, v=22, w=33))=}\")\n", "print(f\"{OrthonormalZone(b1=v1, b2=v2)=}\")\n", "\n", "print(f\"{zone.in_zone(v1)=}\")\n", "print(f\"{zone.in_zone(v2)=}\")\n", "print(f\"{zone.in_zone(v3)=}\")\n", "\n", "print(f\"{v1=}\")\n", "print(f\"{v2=}\")" ] }, { "cell_type": "code", "execution_count": 3, "id": "6af4cea8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "sim.forward([-0.5, -1., 1.])=Hklpy2DiffractometerRealPos(omega=48.5904, chi=-41.8103, phi=-26.5651, tth=97.1808)\n", "sim.forward([0, -1, 0.5])=Hklpy2DiffractometerRealPos(omega=33.9879, chi=-63.435, phi=-0.0, tth=67.9757)\n" ] } ], "source": [ "import hklpy2\n", "\n", "sim = hklpy2.creator()\n", "print(f\"{sim.forward([-0.5, -1., 1.])=}\")\n", "print(f\"{sim.forward([0, -1, 0.5])=}\")" ] }, { "cell_type": "code", "execution_count": 4, "id": "20ad40de", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hkl_1=(1, 0, 0) hkl_2=[0, 1, 0] n=5\n", "====== ====== ====== ======= ======= ======= =======\n", "h k l omega chi phi tth \n", "====== ====== ====== ======= ======= ======= =======\n", "1.0000 0.0000 0.0000 30.0000 0.0000 90.0000 60.0000\n", "0.9239 0.3827 0.0000 30.0000 22.5000 90.0000 60.0000\n", "0.7071 0.7071 0.0000 30.0000 45.0000 90.0000 60.0000\n", "0.3827 0.9239 0.0000 30.0000 67.5000 90.0000 60.0000\n", "0.0000 1.0000 0.0000 30.0000 90.0000 0.0000 60.0000\n", "====== ====== ====== ======= ======= ======= =======\n", "\n" ] } ], "source": [ "sim.core.constraints[\"tth\"].limits = -0.01, 180.01\n", "zone_series(sim, (1, 0, 0), [0, 1, 0], 5)\n", "# zone_series(sim, v1, v3, 17)\n", "# zone_series(sim, (1, 0, 0), [0, -1, 0.5], 17)" ] }, { "cell_type": "code", "execution_count": 5, "id": "2c0b5d55", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 0.2714, 1.2877, -0.4837],\n", " [ 0.2756, 0.2108, 0.9575],\n", " [ 1.5393, -0.1109, -0.2144]])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sim.add_sample(\"test\", 4, 5, 6, 75, 85, 95, replace=True)\n", "r1 = sim.add_reflection((4, 0, 0), (30.345, 10, 10, 60.69))\n", "r2 = sim.add_reflection((0, 4, 0), (-24.63, -9.265, -85.08, -49.27))\n", "np.asarray(sim.core.calc_UB(r1, r2), dtype=float)" ] }, { "cell_type": "code", "execution_count": 6, "id": "65d706f4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hkl_1=(4, 0, 0) hkl_2=[0, 4, 0] n=5\n", "====== ====== ====== ======= ======= ======= =======\n", "h k l omega chi phi tth \n", "====== ====== ====== ======= ======= ======= =======\n", "4.0000 0.0000 0.0000 30.3449 10.0000 10.0000 60.6899\n", "4.0398 1.3746 0.0000 33.0559 11.8130 25.2925 66.1118\n", "3.3304 2.6643 0.0000 31.9896 12.8420 41.8998 63.9792\n", "1.9204 3.6121 0.0000 28.0637 12.6122 63.7067 56.1274\n", "0.0000 4.0000 0.0000 24.6345 9.2657 94.9203 49.2691\n", "====== ====== ====== ======= ======= ======= =======\n", "\n" ] } ], "source": [ "zone_series(sim, (4, 0, 0), [0, 4, 0], 5)" ] }, { "cell_type": "code", "execution_count": 7, "id": "d1236513", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from bluesky import RunEngine\n", "from bluesky.callbacks.best_effort import BestEffortCallback\n", "from ophyd.sim import noisy_det\n", "\n", "RE = RunEngine()\n", "bec = BestEffortCallback()\n", "bec.disable_plots()\n", "RE.subscribe(bec)" ] }, { "cell_type": "code", "execution_count": 8, "id": "8b0520af", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 1 Time: 2025-12-11 10:51:40\n", "Persistent Unique Scan ID: '07cb65c6-8065-49a7-86a8-b11aa4553144'\n", "New stream: 'primary'\n", "+-----------+------------+------------+----------------------+------------------+------------+------------+------------+------------+------------+------------+------------+\n", "| seq_num | time | noisy_det | e4cv_beam_wavelength | e4cv_beam_energy | e4cv_h | e4cv_k | e4cv_l | e4cv_omega | e4cv_chi | e4cv_phi | e4cv_tth |\n", "+-----------+------------+------------+----------------------+------------------+------------+------------+------------+------------+------------+------------+------------+\n", "| 1 | 10:51:40.5 | 0.973 | 1.000 | 12.398 | 1.000 | 0.000 | -0.000 | 7.256 | 10.000 | 10.000 | 14.512 |\n", "| 2 | 10:51:40.5 | 0.958 | 1.000 | 12.398 | 1.010 | 0.344 | 0.000 | 7.838 | 11.813 | 25.293 | 15.675 |\n", "| 3 | 10:51:40.5 | 1.058 | 1.000 | 12.398 | 0.833 | 0.666 | -0.000 | 7.611 | 12.842 | 41.900 | 15.221 |\n", "| 4 | 10:51:40.5 | 0.919 | 1.000 | 12.398 | 0.480 | 0.903 | 0.000 | 6.754 | 12.612 | 63.707 | 13.509 |\n", "| 5 | 10:51:40.5 | 1.057 | 1.000 | 12.398 | 0.000 | 1.000 | -0.000 | 5.981 | 9.266 | 94.920 | 11.963 |\n", "+-----------+------------+------------+----------------------+------------------+------------+------------+------------+------------+------------+------------+------------+\n", "Plan ['07cb65c6'] (scan num: 1)\n", "\n", "\n", "\n" ] } ], "source": [ "uid, = RE(scan_zone([noisy_det], sim, (1,0,0), (0,1,0), 5))" ] } ], "metadata": { "kernelspec": { "display_name": "hklpy2", "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.13.9" } }, "nbformat": 4, "nbformat_minor": 5 }