{ "cells": [ { "cell_type": "markdown", "id": "541ea465", "metadata": {}, "source": [ "# APS ISN Diffractometer\n", "\n", "Model of the ISN diffractometer at APS 19ID. This is a 3-axis diffractometer,\n", "based on the *psic* geometry described by Hoydoo Yoo (*J Appl Cryst*, 1999,\n", "**32**, 614-623). This diffractometer geometry is very similar to the TARDIS\n", "diffractometer at NSLS-II.\n", "\n", "Some *psic* axes do not exist in *ISN*; they are fixed at zero. The ISN\n", "diffractometer renames the {math}`\\nu` and {math}`\\delta` axes:\n", "\n", "psic axis | ISN axis | range\n", "--- | --- | ---\n", "mu | mu | {math}`\\pm 180`\n", "eta | eta | fixed at 0\n", "chi | chi | fixed at 0\n", "phi | phi | fixed at 0\n", "nu | yaw | {math}`\\pm 180`\n", "delta | pitch | {math}`\\pm 180`\n", "\n", "ISN has an additional `radius` motion with range 0-1000 (mm). This axis is not\n", "part of the defined *psic* geometry.\n", "\n", "The *E6C* geometry (see *hkl_soleil, E6C* geometry in the\n", "[tables](../diffractometers.rst)) has a `lifting_detector_mu` mode that keeps\n", "`eta` (E6C calls this axis `omega`), `chi`, and `phi` fixed. This is the only\n", "E6C mode using the `hkl` engine where none of these axes are listed as\n", "*writeable(s)*.\n", "\n", "In `hkl_soleil`, this is the *E6C* geometry.\n", "\n", "![*psic* drawing](../_static/psic.png)\n", "\n", "Here, we setup a simulated ISN diffractometer, orient a GaAs crystal using two\n", "orientation reflections with the method of Busing & Levy, *Acta Cryst* 1967, **22**,\n", "457, then calculate, move, and scan in {math}`hkl`.\n" ] }, { "cell_type": "markdown", "id": "f6860750", "metadata": {}, "source": [ "## Create the Simulated ISN Diffractometer\n", "\n", "The simulator defines all the motor axes using\n", "[`ophyd.SoftPositioner`](https://blueskyproject.io/ophyd/user/reference/positioners.html#softpositioner).\n", "The six axes are specified in the order expected by the E6C geometry. The\n", "additional `radius` axis is added to the list after all the expected axes.\n", "Specified in this order, *hklpy2* will use the first axes to compute {math}`h`,\n", "{math}`k`, & {math}`l` and ignore any remaining *reals*." ] }, { "cell_type": "code", "execution_count": 1, "id": "2712f037", "metadata": {}, "outputs": [], "source": [ "import hklpy2\n", "import numpy as np\n", "\n", "np.set_printoptions(precision=3, suppress=True)\n", "\n", "psic = hklpy2.creator(\n", " name=\"psic\",\n", " geometry=\"E6C\",\n", " solver=\"hkl_soleil\",\n", " solver_kwargs={\"engine\": \"hkl\"},\n", " reals=\"mu eta chi phi yaw pitch radius\".split(),\n", ") " ] }, { "cell_type": "markdown", "id": "ba0d4f5b", "metadata": {}, "source": [ "Configure some basic operating parameters.\n", "Length units are *angstrom*, angles are degrees, and energy is keV." ] }, { "cell_type": "code", "execution_count": 2, "id": "7e918c7b", "metadata": {}, "outputs": [], "source": [ "psic.beam.wavelength.put(12.3984 / 20)\n", "psic.yaw.move(40)\n", "psic.mu.move(psic.yaw.position/2)\n", "psic.radius._egu = \"mm\"\n", "psic.radius._limits = 0, 1000\n", "psic.radius.move(800)\n", "psic.core.mode = \"lifting_detector_mu\"" ] }, { "cell_type": "markdown", "id": "d55b0eb0", "metadata": {}, "source": [ "Print a brief summary of the ISN." ] }, { "cell_type": "code", "execution_count": 3, "id": "aa08faa7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "wavelength=0.6199\n", "pseudos: h=0, k=1.1034, l=0\n", "reals: mu=20.0, eta=0, chi=0, phi=0, yaw=40, pitch=0\n", "auxiliaries: radius=800\n" ] }, { "data": { "text/plain": [ "HklSolver(name='hkl_soleil', version='5.1.2', geometry='E6C', engine_name='hkl', mode='lifting_detector_mu')" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "psic.wh()\n", "psic.core.solver" ] }, { "cell_type": "markdown", "id": "f42b5194", "metadata": {}, "source": [ "In this mode, there are no extra parameters such as {math}`hkl_2` or\n", "{math}`psi`. No azimuthal scans are provided in this mode." ] }, { "cell_type": "code", "execution_count": 23, "id": "07923824", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "psic.core.mode='lifting_detector_mu' psic.core.extras={}\n" ] } ], "source": [ "print(f\"{psic.core.mode=} {psic.core.extras=}\")" ] }, { "cell_type": "markdown", "id": "f2eb88c7", "metadata": {}, "source": [ "## Add a sample" ] }, { "cell_type": "code", "execution_count": 5, "id": "04492933", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Sample(name='GaAs', lattice=Lattice(a=5.75, system='cubic'))" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "psic.core.add_sample(\"GaAs\", 5.75)" ] }, { "cell_type": "markdown", "id": "6da169f8", "metadata": {}, "source": [ "## Orient the sample\n", "\n", "Add two observed reflections and the motor positions associated with those\n", "{math}`hkl` values.\n", "\n", "We specify the motor positions in the order expected by E6C. We don't need to\n", "specify the axis names." ] }, { "cell_type": "code", "execution_count": 6, "id": "f056b2bc", "metadata": {}, "outputs": [], "source": [ "r001 = psic.core.add_reflection(\n", " (0, 0, 1),\n", " (6.18 / 2, 0, 0, 0, 6.18, 0),\n", " name=\"r001\",\n", ")\n", "r100 = psic.core.add_reflection(\n", " (1, 0, 0),\n", " (6.18 / 2, 0, 90, 0, 6.18, 0),\n", " name=\"r100\",\n", ")" ] }, { "cell_type": "markdown", "id": "af870bdc", "metadata": {}, "source": [ "Print the two reflections." ] }, { "cell_type": "code", "execution_count": 7, "id": "0d3f40c8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "r001=Reflection(name='r001', h=0, k=0, l=1)\n", "r100=Reflection(name='r100', h=1, k=0, l=0)\n" ] } ], "source": [ "print(f\"{r001=}\")\n", "print(f\"{r100=}\")" ] }, { "cell_type": "markdown", "id": "44ce7540", "metadata": {}, "source": [ "Calculate the {math}`UB` (orientation) matrix from the two orienting reflections." ] }, { "cell_type": "code", "execution_count": 8, "id": "dab91625", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[[-0.0, -1.092727879509, -0.0],\n", " [-0.0, -0.0, 1.092727879509],\n", " [-1.092727879509, 0.0, 0.0]]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "psic.core.calc_UB(r001, r100)" ] }, { "cell_type": "markdown", "id": "865da50c", "metadata": {}, "source": [ "## Compute *hkl* from motor positions\n", "\n", "Just **calculate** the *hkl* positions. These commands do not move the motors.\n", "\n", "That is: `pseudos = inverse(reals)`. Specify the motor positions in the\n", "expected order." ] }, { "cell_type": "code", "execution_count": 9, "id": "c43d1e55", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "psic.inverse(6.18 / 2, 0, 0, 0, 6.18, 0)=Hklpy2DiffractometerPseudoPos(h=0, k=0, l=1.0)\n", "psic.inverse(6.18 / 2, 0, 90, 0, 6.18, 0)=Hklpy2DiffractometerPseudoPos(h=1.0, k=0, l=0)\n" ] } ], "source": [ "print(f\"{psic.inverse(6.18 / 2, 0, 0, 0, 6.18, 0)=}\")\n", "print(f\"{psic.inverse(6.18 / 2, 0, 90, 0, 6.18, 0)=}\")" ] }, { "cell_type": "markdown", "id": "64e74462", "metadata": {}, "source": [ "## Compute motor positions from *hkl*\n", "\n", "Just **calculate** the motor positions. These commands do not move the motors.\n", "\n", "That is: `reals = forward(pseudos)`.\n", "\n", "### List of solutions\n", "\n", "First, use the `.core.forward()` method to show the **full list** of possible motor\n", "positions. Note that the `forward()` calculation produces a list of possible\n", "solutions. \n", "\n", "The (0,0,1) reflection should match the first orienting reflection.\n", "\n", "The list may be empty, indicating no solutions were found, such as\n", "the case for the (1,0,0) reflection which needs `chi=90`." ] }, { "cell_type": "code", "execution_count": 10, "id": "0a0202f9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "psic.core.forward((0, 0, 1))=[Hklpy2DiffractometerRealPos(mu=3.0901, eta=0, chi=0, phi=0, yaw=6.1802, pitch=0), Hklpy2DiffractometerRealPos(mu=176.9099, eta=0, chi=0, phi=0, yaw=-6.1802, pitch=0), Hklpy2DiffractometerRealPos(mu=3.0901, eta=0, chi=0, phi=0, yaw=-173.8198, pitch=-180.0), Hklpy2DiffractometerRealPos(mu=3.0901, eta=0, chi=0, phi=0, yaw=-173.8198, pitch=180.0), Hklpy2DiffractometerRealPos(mu=176.9099, eta=0, chi=0, phi=0, yaw=173.8198, pitch=-180.0), Hklpy2DiffractometerRealPos(mu=176.9099, eta=0, chi=0, phi=0, yaw=173.8198, pitch=180.0)]\n", "psic.core.forward((1, 0, 0))=[]\n" ] } ], "source": [ "print(f\"{psic.core.forward((0, 0, 1))=}\")\n", "print(f\"{psic.core.forward((1, 0, 0))=}\")" ] }, { "cell_type": "markdown", "id": "906506c3", "metadata": {}, "source": [ "### Default solution\n", "\n", "Next, use the diffractometer's `forward()` method (the one used when moving and\n", "scanning the diffractometer position). This method, by default setting, returns\n", "the first solution returned from the `.core.forward()` method. A\n", "`NoForwardSolutions` exception is raised if the list of solutions is empty." ] }, { "cell_type": "code", "execution_count": 11, "id": "36b63ee6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "psic.forward((0, 0, 1))=Hklpy2DiffractometerRealPos(mu=3.0901, eta=0, chi=0, phi=0, yaw=6.1802, pitch=0)\n", "Cannot compute forward((1,0,0)): No solutions.\n" ] } ], "source": [ "print(f\"{psic.forward((0, 0, 1))=}\")\n", "try:\n", " print(f\"{psic.forward((1, 0, 0))=}\") # unreachable, chi=90\n", "except hklpy2.misc.NoForwardSolutions as exc:\n", " print(f\"Cannot compute forward((1,0,0)): {exc}\")" ] }, { "cell_type": "markdown", "id": "1d40a9ef", "metadata": {}, "source": [ "The `forward()` calculation computes new values for the *writeable* axes, using\n", "the current positions of the remaining axes.\n", "\n", "Unlike the physical diffractometer, the simulator can be positioned to the\n", "unreachable `chi=90` position to check the (1,0,0) position. With this\n", "adjustment, the computed (1,0,0) reflection should match the second orienting\n", "reflection." ] }, { "cell_type": "code", "execution_count": 12, "id": "697c76fd", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "psic.forward((1, 0, 0))=Hklpy2DiffractometerRealPos(mu=3.0901, eta=0, chi=90.0, phi=0, yaw=6.1802, pitch=0)\n" ] }, { "data": { "text/plain": [ "MoveStatus(done=True, pos=psic_chi, elapsed=0.0, success=True, settle_time=0.0)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "psic.chi.move(90) # unreachable: ISN chi axis won't move for ISN diffractometer, but we can simulate it\n", "print(f\"{psic.forward((1, 0, 0))=}\")\n", "psic.chi.move(0) # put it back" ] }, { "cell_type": "markdown", "id": "92294256", "metadata": {}, "source": [ "### Table of solutions" ] }, { "cell_type": "code", "execution_count": null, "id": "c57dc2cd", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "======= = ======== === === === ========= =========\n", "(hkl) # mu eta chi phi yaw pitch \n", "======= = ======== === === === ========= =========\n", "(0 0 1) 1 3.0901 0 0 0 6.1802 0 \n", "(0 0 1) 2 176.9099 0 0 0 -6.1802 0 \n", "(0 0 1) 3 3.0901 0 0 0 -173.8198 -180 \n", "(0 0 1) 4 3.0901 0 0 0 -173.8198 180 \n", "(0 0 1) 5 176.9099 0 0 0 173.8198 -180 \n", "(0 0 1) 6 176.9099 0 0 0 173.8198 180 \n", "(0 1 1) 1 -40.6278 0 0 0 8.7443 0 \n", "(0 1 1) 2 -40.6278 0 0 0 -171.2557 -180 \n", "(0 1 1) 3 -40.6278 0 0 0 -171.2557 180 \n", "(1 1 1) 1 -38.4337 0 0 0 8.7636 -6.1892 \n", "(1 1 1) 2 -38.4337 0 0 0 -171.2364 -173.8108\n", "======= = ======== === === === ========= =========\n", "\n" ] } ], "source": [ "from hklpy2.user import cahkl_table\n", "from hklpy2.user import set_diffractometer\n", "\n", "set_diffractometer(psic)\n", "cahkl_table((0, 0, 1), (0, 1, 1), (1,1,1))" ] }, { "cell_type": "markdown", "id": "eb3e028c", "metadata": {}, "source": [ "## Save the orientation to a file" ] }, { "cell_type": "code", "execution_count": 14, "id": "188d8ba5", "metadata": {}, "outputs": [], "source": [ "psic.export(\n", " \"dev_aps-isn.yml\",\n", " comment=\"APS ISN diffractometer with oriented GaAs sample\",\n", ")" ] }, { "cell_type": "markdown", "id": "2b64c1a3", "metadata": {}, "source": [ "Show that configuration." ] }, { "cell_type": "code", "execution_count": 15, "id": "d89ab37b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[38;5;66;03m#hklpy2 configuration file\u001b[39;00m\n", "\n", "_header:\n", " datetime: \u001b[33m'2025-11-19 15:44:06.163052'\u001b[39m\n", " hklpy2_version: \u001b[32m0.2\u001b[39m\u001b[32m.1\u001b[39m.dev5+gbbdb58469\n", " python_class: Hklpy2Diffractometer\n", " file: dev_aps-isn.yml\n", " comment: APS ISN diffractometer \u001b[38;5;28;01mwith\u001b[39;00m oriented GaAs sample\n", "name: psic\n", "axes:\n", " pseudo_axes:\n", " - h\n", " - k\n", " - l\n", " real_axes:\n", " - mu\n", " - eta\n", " - chi\n", " - phi\n", " - yaw\n", " - pitch\n", " axes_xref:\n", " h: h\n", " k: k\n", " l: l\n", " mu: mu\n", " eta: omega\n", " chi: chi\n", " phi: phi\n", " yaw: gamma\n", " pitch: delta\n", " extra_axes:\n", " h2: \u001b[32m0\u001b[39m\n", " k2: \u001b[32m0\u001b[39m\n", " l2: \u001b[32m0\u001b[39m\n", " psi: \u001b[32m0\u001b[39m\n", "digits: \u001b[32m4\u001b[39m\n", "sample_name: GaAs\n", "samples:\n", " sample:\n", " name: sample\n", " lattice:\n", " a: \u001b[32m1\u001b[39m\n", " b: \u001b[32m1\u001b[39m\n", " c: \u001b[32m1\u001b[39m\n", " alpha: \u001b[32m90.0\u001b[39m\n", " beta: \u001b[32m90.0\u001b[39m\n", " gamma: \u001b[32m90.0\u001b[39m\n", " digits: \u001b[32m4\u001b[39m\n", " angle_units: degrees\n", " length_units: angstrom\n", " reflections: {}\n", " reflections_order: []\n", " U:\n", " - - \u001b[32m1\u001b[39m\n", " - \u001b[32m0\u001b[39m\n", " - \u001b[32m0\u001b[39m\n", " - - \u001b[32m0\u001b[39m\n", " - \u001b[32m1\u001b[39m\n", " - \u001b[32m0\u001b[39m\n", " - - \u001b[32m0\u001b[39m\n", " - \u001b[32m0\u001b[39m\n", " - \u001b[32m1\u001b[39m\n", " UB:\n", " - - \u001b[32m6.283185307179586\u001b[39m\n", " - \u001b[32m0.0\u001b[39m\n", " - \u001b[32m0.0\u001b[39m\n", " - - \u001b[32m0.0\u001b[39m\n", " - \u001b[32m6.283185307179586\u001b[39m\n", " - \u001b[32m0.0\u001b[39m\n", " - - \u001b[32m0.0\u001b[39m\n", " - \u001b[32m0.0\u001b[39m\n", " - \u001b[32m6.283185307179586\u001b[39m\n", " digits: \u001b[32m4\u001b[39m\n", " GaAs:\n", " name: GaAs\n", " lattice:\n", " a: \u001b[32m5.75\u001b[39m\n", " b: \u001b[32m5.75\u001b[39m\n", " c: \u001b[32m5.75\u001b[39m\n", " alpha: \u001b[32m90.0\u001b[39m\n", " beta: \u001b[32m90.0\u001b[39m\n", " gamma: \u001b[32m90.0\u001b[39m\n", " digits: \u001b[32m4\u001b[39m\n", " angle_units: degrees\n", " length_units: angstrom\n", " reflections:\n", " r001:\n", " name: r001\n", " geometry: E6C\n", " pseudos:\n", " h: \u001b[32m0\u001b[39m\n", " k: \u001b[32m0\u001b[39m\n", " l: \u001b[32m1\u001b[39m\n", " reals:\n", " mu: \u001b[32m3.09\u001b[39m\n", " eta: \u001b[32m0\u001b[39m\n", " chi: \u001b[32m0\u001b[39m\n", " phi: \u001b[32m0\u001b[39m\n", " yaw: \u001b[32m6.18\u001b[39m\n", " pitch: \u001b[32m0\u001b[39m\n", " reals_units: angstrom\n", " wavelength: \u001b[32m0.61992\u001b[39m\n", " wavelength_units: angstrom\n", " digits: \u001b[32m4\u001b[39m\n", " r100:\n", " name: r100\n", " geometry: E6C\n", " pseudos:\n", " h: \u001b[32m1\u001b[39m\n", " k: \u001b[32m0\u001b[39m\n", " l: \u001b[32m0\u001b[39m\n", " reals:\n", " mu: \u001b[32m3.09\u001b[39m\n", " eta: \u001b[32m0\u001b[39m\n", " chi: \u001b[32m90\u001b[39m\n", " phi: \u001b[32m0\u001b[39m\n", " yaw: \u001b[32m6.18\u001b[39m\n", " pitch: \u001b[32m0\u001b[39m\n", " reals_units: angstrom\n", " wavelength: \u001b[32m0.61992\u001b[39m\n", " wavelength_units: angstrom\n", " digits: \u001b[32m4\u001b[39m\n", " reflections_order:\n", " - r001\n", " - r100\n", " U:\n", " - - -\u001b[32m0.0\u001b[39m\n", " - -\u001b[32m1.0\u001b[39m\n", " - -\u001b[32m0.0\u001b[39m\n", " - - -\u001b[32m0.0\u001b[39m\n", " - -\u001b[32m0.0\u001b[39m\n", " - \u001b[32m1.0\u001b[39m\n", " - - -\u001b[32m1.0\u001b[39m\n", " - \u001b[32m0.0\u001b[39m\n", " - -\u001b[32m0.0\u001b[39m\n", " UB:\n", " - - -\u001b[32m0.0\u001b[39m\n", " - -\u001b[32m1.092727879509\u001b[39m\n", " - -\u001b[32m0.0\u001b[39m\n", " - - -\u001b[32m0.0\u001b[39m\n", " - -\u001b[32m0.0\u001b[39m\n", " - \u001b[32m1.092727879509\u001b[39m\n", " - - -\u001b[32m1.092727879509\u001b[39m\n", " - \u001b[32m0.0\u001b[39m\n", " - \u001b[32m0.0\u001b[39m\n", " digits: \u001b[32m4\u001b[39m\n", "constraints:\n", " mu:\n", " label: mu\n", " low_limit: -\u001b[32m180.0\u001b[39m\n", " high_limit: \u001b[32m180.0\u001b[39m\n", " \u001b[38;5;28;01mclass\u001b[39;00m: LimitsConstraint\n", " eta:\n", " label: eta\n", " low_limit: -\u001b[32m180.0\u001b[39m\n", " high_limit: \u001b[32m180.0\u001b[39m\n", " \u001b[38;5;28;01mclass\u001b[39;00m: LimitsConstraint\n", " chi:\n", " label: chi\n", " low_limit: -\u001b[32m180.0\u001b[39m\n", " high_limit: \u001b[32m180.0\u001b[39m\n", " \u001b[38;5;28;01mclass\u001b[39;00m: LimitsConstraint\n", " phi:\n", " label: phi\n", " low_limit: -\u001b[32m180.0\u001b[39m\n", " high_limit: \u001b[32m180.0\u001b[39m\n", " \u001b[38;5;28;01mclass\u001b[39;00m: LimitsConstraint\n", " yaw:\n", " label: yaw\n", " low_limit: -\u001b[32m180.0\u001b[39m\n", " high_limit: \u001b[32m180.0\u001b[39m\n", " \u001b[38;5;28;01mclass\u001b[39;00m: LimitsConstraint\n", " pitch:\n", " label: pitch\n", " low_limit: -\u001b[32m180.0\u001b[39m\n", " high_limit: \u001b[32m180.0\u001b[39m\n", " \u001b[38;5;28;01mclass\u001b[39;00m: LimitsConstraint\n", "solver:\n", " name: hkl_soleil\n", " description: HklSolver(name=\u001b[33m'hkl_soleil'\u001b[39m, version=\u001b[33m'5.1.2'\u001b[39m, geometry=\u001b[33m'E6C'\u001b[39m, engine_name=\u001b[33m'hkl'\u001b[39m,\n", " mode=\u001b[33m'lifting_detector_mu'\u001b[39m)\n", " geometry: E6C\n", " real_axes:\n", " - mu\n", " - omega\n", " - chi\n", " - phi\n", " - gamma\n", " - delta\n", " version: \u001b[32m5.1\u001b[39m\u001b[32m.2\u001b[39m\n", " engine: hkl\n", "beam:\n", " \u001b[38;5;28;01mclass\u001b[39;00m: WavelengthXray\n", " source_type: Synchrotron X-ray Source\n", " energy: \u001b[32m20.000032010351074\u001b[39m\n", " wavelength: \u001b[32m0.61992\u001b[39m\n", " energy_units: keV\n", " wavelength_units: angstrom\n" ] } ], "source": [ "%pycat dev_aps-isn.yml" ] }, { "cell_type": "code", "execution_count": 16, "id": "d6b58fd1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "wavelength=0.6199\n", "pseudos: h=0, k=1.0, l=1.0\n", "reals: mu=-40.6278, eta=0, chi=0, phi=0, yaw=8.7443, pitch=0\n", "auxiliaries: radius=800\n" ] } ], "source": [ "psic.move(0, 1, 1)\n", "psic.wh()" ] }, { "cell_type": "markdown", "id": "7beb0255", "metadata": {}, "source": [ "## (0k1) scan" ] }, { "cell_type": "markdown", "id": "aef59f19", "metadata": {}, "source": [ "Setup bluesky for scanning." ] }, { "cell_type": "code", "execution_count": 17, "id": "13f49e6f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import bluesky\n", "from bluesky.callbacks.best_effort import BestEffortCallback\n", "from bluesky import plans as bp\n", "\n", "bec = BestEffortCallback()\n", "bec.disable_plots()\n", "bec.disable_baseline()\n", "RE = bluesky.RunEngine()\n", "RE.subscribe(bec)" ] }, { "cell_type": "markdown", "id": "72027ae6", "metadata": {}, "source": [ "Move ISN to (001) which presets both {math}`h` and {math}`l`." ] }, { "cell_type": "code", "execution_count": 18, "id": "25988359", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "wavelength=0.6199\n", "pseudos: h=0, k=0, l=1.0\n", "reals: mu=3.0901, eta=0, chi=0, phi=0, yaw=6.1802, pitch=0\n", "auxiliaries: radius=800\n" ] } ], "source": [ "psic.move(0, 0, 1)\n", "psic.wh()" ] }, { "cell_type": "markdown", "id": "fa4d925a", "metadata": {}, "source": [ "Scan from {math}`(011)` to {math}`(001)`, showing both {math}`(hkl)` and the\n", "three writeable angles." ] }, { "cell_type": "code", "execution_count": 19, "id": "b5d2ff73", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 1 Time: 2025-11-19 15:44:06\n", "Persistent Unique Scan ID: 'a6406340-324b-4c84-8078-1eec366a4fe4'\n", "New stream: 'primary'\n", "+-----------+------------+------------+------------+------------+------------+------------+------------+\n", "| seq_num | time | psic_k | psic_yaw | psic_h | psic_l | psic_pitch | psic_mu |\n", "+-----------+------------+------------+------------+------------+------------+------------+------------+\n", "| 1 | 15:44:06.6 | 1.000 | 8.744 | 0 | 1.000 | 0 | -40.628 |\n", "| 2 | 15:44:06.6 | 0.800 | 7.917 | 0 | 1.000 | 0 | -34.701 |\n", "| 3 | 15:44:06.6 | 0.600 | 7.209 | 0 | 1.000 | 0 | -27.359 |\n", "| 4 | 15:44:06.6 | 0.400 | 6.657 | 0 | 1.000 | 0 | -18.473 |\n", "| 5 | 15:44:06.6 | 0.200 | 6.303 | 0 | 1.000 | 0 | -8.159 |\n", "| 6 | 15:44:06.6 | -0.000 | 6.180 | 0 | 1.000 | 0 | 3.090 |\n", "+-----------+------------+------------+------------+------------+------------+------------+------------+\n", "generator scan ['a6406340'] (scan num: 1)\n" ] }, { "data": { "text/plain": [ "('a6406340-324b-4c84-8078-1eec366a4fe4',)" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "RE(bp.scan([psic.h, psic.k, psic.l, psic.mu, psic.yaw, psic.pitch], psic.k, 1, 0, 6))" ] }, { "cell_type": "markdown", "id": "1fa1ca1a", "metadata": {}, "source": [ "Do a relative {math}`\\theta : 2\\theta` scan:" ] }, { "cell_type": "code", "execution_count": 20, "id": "6ecdf372", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 2 Time: 2025-11-19 15:44:06\n", "Persistent Unique Scan ID: '6ade00e8-5c04-4d72-849b-83dfb15b9aa2'\n", "New stream: 'primary'\n", "+-----------+------------+------------+------------+------------+------------+------------+------------+\n", "| seq_num | time | psic_yaw | psic_mu | psic_h | psic_l | psic_pitch | psic_k |\n", "+-----------+------------+------------+------------+------------+------------+------------+------------+\n", "| 1 | 15:44:06.8 | 4.000 | 2.000 | 0 | 0.647 | 0 | 0 |\n", "| 2 | 15:44:06.8 | 5.000 | 2.500 | 0 | 0.809 | 0 | 0 |\n", "| 3 | 15:44:06.8 | 6.000 | 3.000 | 0 | 0.971 | 0 | 0 |\n", "| 4 | 15:44:06.8 | 7.000 | 3.500 | 0 | 1.132 | 0 | 0 |\n", "| 5 | 15:44:06.8 | 8.000 | 4.000 | 0 | 1.294 | 0 | 0 |\n", "+-----------+------------+------------+------------+------------+------------+------------+------------+\n", "generator x2x_scan ['6ade00e8'] (scan num: 2)\n" ] }, { "data": { "text/plain": [ "('6ade00e8-5c04-4d72-849b-83dfb15b9aa2',)" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "psic.move_reals(3, 0, 0, 0, 6, 0)\n", "RE(bp.x2x_scan([psic.h, psic.k, psic.l, psic.mu, psic.yaw, psic.pitch], psic.yaw, psic.mu, -2, 2, 5))" ] }, { "cell_type": "markdown", "id": "8c797e08", "metadata": {}, "source": [ "Scan the `pitch` rotation." ] }, { "cell_type": "code", "execution_count": 21, "id": "55b262f2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 3 Time: 2025-11-19 15:44:07\n", "Persistent Unique Scan ID: 'd766361e-ecf9-4ff7-8149-51545e041e88'\n", "New stream: 'primary'\n", "+-----------+------------+------------+------------+------------+------------+------------+------------+\n", "| seq_num | time | psic_pitch | psic_yaw | psic_h | psic_l | psic_k | psic_mu |\n", "+-----------+------------+------------+------------+------------+------------+------------+------------+\n", "| 1 | 15:44:07.0 | -1.000 | 6.180 | 0.162 | 1.000 | 0.001 | 3.090 |\n", "| 2 | 15:44:07.0 | 0.000 | 6.180 | 0.000 | 1.000 | -0.000 | 3.090 |\n", "| 3 | 15:44:07.0 | 1.000 | 6.180 | -0.162 | 1.000 | 0.001 | 3.090 |\n", "| 4 | 15:44:07.0 | 2.000 | 6.180 | -0.324 | 1.000 | 0.006 | 3.090 |\n", "| 5 | 15:44:07.0 | 3.000 | 6.180 | -0.485 | 0.999 | 0.013 | 3.090 |\n", "| 6 | 15:44:07.1 | 4.000 | 6.180 | -0.647 | 0.999 | 0.023 | 3.090 |\n", "| 7 | 15:44:07.1 | 5.000 | 6.180 | -0.808 | 0.998 | 0.035 | 3.090 |\n", "| 8 | 15:44:07.1 | 6.000 | 6.180 | -0.970 | 0.997 | 0.051 | 3.090 |\n", "+-----------+------------+------------+------------+------------+------------+------------+------------+\n", "generator rel_scan ['d766361e'] (scan num: 3)\n" ] }, { "data": { "text/plain": [ "('d766361e-ecf9-4ff7-8149-51545e041e88',)" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "psic.move(0, 0, 1)\n", "RE(bp.rel_scan([psic.h, psic.k, psic.l, psic.mu, psic.yaw, psic.pitch], psic.pitch, -1, 6, 8))" ] } ], "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.12.11" } }, "nbformat": 4, "nbformat_minor": 5 }