{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# **hkl_soleil** E4CV\n", "\n", "At X-ray synchrotrons, the vertical *E4CV* {ref}`geometry `\n", "is more common (than *E4CH*, common in labs) due to the polarization of the X-rays.\n", "\n", "![E4CV geometry](../_static/3S+1D-fourc.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup the *E4CV* diffractometer in **hklpy2**\n", "\n", "The *hkl_soleil* *E4CV* [geometry](https://people.debian.org/~picca/hkl/hkl.html)\n", "is described:\n", "\n", "axis | moves | rotation axis | vector\n", "--- | --- | --- | ---\n", "omega | sample | {math}`-\\vec{y}` | `[0 -1 0]`\n", "chi | sample | {math}`\\vec{x}` | `[1 0 0]`\n", "phi | sample | {math}`-\\vec{y}` | `[0 -1 0]`\n", "tth | detector | {math}`-\\vec{y}` | `[0 -1 0]`\n", "\n", "* xrays incident on the $\\vec{x}$ direction (1, 0, 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define _this_ diffractometer\n", "\n", "Use the **hklpy2** `creator()` function to create a diffractometer\n", "object. The diffractometer object will have simulated rotational axes.\n", "\n", "We'll provide the geometry and solver names.\n", "By convention, the `name` keyword is the same as the object name.\n", "\n", "See the [geometry tables](../geometry_tables.rst) for\n", "a more complete description of the available diffractometers.\n", "\n", "Create the Python diffractometer object (`fourc`)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import hklpy2\n", "\n", "fourc = hklpy2.creator(name=\"fourc\", geometry=\"E4CV\", solver=\"hkl_soleil\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(example.e4cv.add-sample)=\n", "## Add a sample with a crystal structure" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Sample(name='silicon', lattice=Lattice(a=5.431, system='cubic'))" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from hklpy2.user import add_sample, calc_UB, cahkl, cahkl_table, pa, set_diffractometer, setor, wh\n", "\n", "set_diffractometer(fourc)\n", "add_sample(\"silicon\", a=hklpy2.SI_LATTICE_PARAMETER)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup the UB orientation matrix using *hklpy*\n", "\n", "Define the crystal's orientation on the diffractometer using \n", "the 2-reflection method described by [Busing & Levy, Acta Cryst 22 (1967) 457](https://www.psi.ch/sites/default/files/import/sinq/zebra/PracticalsEN/1967-Busing-Levy-3-4-circle-Acta22.pdf)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Diffractometer wavelength\n", "\n", "Set the diffractometer's X-ray wavelength. This will be used for both reflections. `fourc.wavelength` is an\n", "ophyd [Signal](https://blueskyproject.io/ophyd/user/reference/signals.html). Use\n", "its `.put()` method." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "fourc.wavelength.put(1.54)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Specify the first reflection\n", "\n", "Provide the set of angles that correspond with the reflection's Miller indices: (_hkl_)\n", "\n", "The `setor()` (set orienting reflection) method uses the diffractometer's wavelength *at the time it is called*. (To add reflections at different wavelengths, add a `wavelength=1.0` keyword argument with the correct value.) " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "r1 = setor(4, 0, 0, tth=69.0966, omega=-145.451, chi=0, phi=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Specify the second reflection" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "r2 = setor(0, 4, 0, tth=69.0966, omega=-145.451, chi=90, phi=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Compute the *UB* orientation matrix\n", "\n", "The `calc_UB()` method returns the computed **UB** matrix." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[[-1.4134285e-05, -1.4134285e-05, -1.156906937382],\n", " [0.0, -1.156906937469, 1.4134285e-05],\n", " [-1.156906937469, 1.73e-10, 1.4134285e-05]]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "calc_UB(r1, r2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Report our setup" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "diffractometer='fourc'\n", "HklSolver(name='hkl_soleil', version='5.1.2', geometry='E4CV', engine_name='hkl', mode='bissector')\n", "Sample(name='silicon', lattice=Lattice(a=5.431, system='cubic'))\n", "Reflection(name='r_9ee9', h=4, k=0, l=0)\n", "Reflection(name='r_39f5', h=0, k=4, l=0)\n", "Orienting reflections: ['r_9ee9', 'r_39f5']\n", "U=[[-1.2217305e-05, -1.2217305e-05, -0.999999999851], [0.0, -0.999999999925, 1.2217305e-05], [-0.999999999925, 1.49e-10, 1.2217305e-05]]\n", "UB=[[-1.4134285e-05, -1.4134285e-05, -1.156906937382], [0.0, -1.156906937469, 1.4134285e-05], [-1.156906937469, 1.73e-10, 1.4134285e-05]]\n", "constraint: -180.0 <= omega <= 180.0\n", "constraint: -180.0 <= chi <= 180.0\n", "constraint: -180.0 <= phi <= 180.0\n", "constraint: -180.0 <= tth <= 180.0\n", "h=0, k=0, l=0\n", "wavelength=1.54\n", "omega=0, chi=0, phi=0, tth=0\n" ] } ], "source": [ "pa()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Check the orientation matrix\n", "\n", "Perform checks with `forward()` ($hkl$ to angle) and\n", "`inverse()` (angle to $hkl$) computations to verify the diffractometer\n", "will move to the same positions where the reflections were identified.\n", "\n", "### Constrain the motors to limited ranges\n", "\n", "* keep `tth` in the positive range\n", "* keep `omega` in the negative range\n", "* allow for slight roundoff errors\n", "* keep `phi` fixed at zero\n", "\n", "First, apply [constraints](../concepts/constraints.rst) to each of the\n", "rotational motors. Constraints are part of the diffractometer's `core`-level\n", "support.\n", "\n", "---\n", "\n", "**Note**: A constraint does not limit the range of the motor, it *constrains*\n", "the choice of solutions from the `forward()` computation.\n", "\n", "---" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['-180.0 <= omega <= 0.001', '-180.0 <= chi <= 180.0', '-180.0 <= phi <= 180.0', '-0.001 <= tth <= 180.0']" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fourc.core.constraints[\"tth\"].limits = -0.001, 180\n", "fourc.core.constraints[\"omega\"].limits = (-180, 0.001)\n", "fourc.core.constraints" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (400) reflection test\n", "\n", "1. Check the `inverse()` (angles -> (_hkl_)) computation.\n", "1. Check the `forward()` ((_hkl_) -> angles) computation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Check `inverse()` at (400)\n", "\n", "To calculate the (_hkl_) corresponding to a given set of motor angles,\n", "call `fourc.inverse()`.\n", "\n", "The _hkl_ values are provided as a Python [namedtuple](https://docs.python.org/3/library/collections.html#collections.namedtuple) structure." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Hklpy2DiffractometerPseudoPos(h=3.999916764257, k=0, l=0)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fourc.inverse((-145.451, 0, 0, 69.0966))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Check `forward(400)`\n", "\n", "Compute the angles necessary to position the diffractometer\n", "for the given reflection.\n", "\n", "---\n", "\n", "**Note**:\n", "\n", "For the `forward()` computation, more than one set of angles may be used to reach the same crystal reflection. This test will report the *default* selection. The *default* selection (which may be changed through methods described in module :mod:`hklpy2.ops`) is the first solution.\n", "\n", "function | returns\n", "--- | ---\n", "`cahkl()` | The *default* solution\n", "`cahkl_table()` | Table of all allowed solutions.\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before calling `forward()`, make sure we are using the desired operations\n", "*mode*. `\"bissector\"` maintains $\\omega = (2\\theta) / 2$" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "fourc.core.solver.mode = \"bissector\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we print the *default* solution (the one returned by calling `cahkl()`." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Hklpy2DiffractometerRealPos(omega=-145.450879077739, chi=0, phi=0.000699999914, tth=69.098241844523)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cahkl(4, 0, 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "**Note**: `cahkl()` is a shortcut to `fourc.forward()`." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Hklpy2DiffractometerRealPos(omega=-145.450879077739, chi=0, phi=0.000699999914, tth=69.098241844523)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fourc.forward(4, 0, 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Show the table of *all* `forward()` solutions for $(4\\ 0\\ 0)$ and $(0\\ 4\\ 0)$ allowed by the current constraints. Since this function accepts a *list* of $hkl$ reflections, extra Python syntax is applied." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "======= = ========= ======= ========= =======\n", "(hkl) # omega chi phi tth \n", "======= = ========= ======= ========= =======\n", "(4 0 0) 1 -145.4509 0 0.0007 69.0982\n", "(4 0 0) 2 -34.5491 0 -110.9011 69.0982\n", "(4 0 0) 3 -34.5491 -180.0 -69.0975 69.0982\n", "(4 0 0) 4 -145.4509 -180.0 -179.9993 69.0982\n", "(4 0 0) 5 -34.5491 180.0 -69.0975 69.0982\n", "(4 0 0) 6 -145.4509 180.0 -179.9993 69.0982\n", "(0 4 0) 1 -145.4509 89.9993 89.9997 69.0982\n", "(0 4 0) 2 -145.4509 89.9993 90.0003 69.0982\n", "(0 4 0) 3 -145.4509 90.0007 -89.9997 69.0982\n", "(0 4 0) 4 -145.4509 90.0007 -90.0003 69.0982\n", "======= = ========= ======= ========= =======\n", "\n" ] } ], "source": [ "cahkl_table((4, 0, 0), (0, 4, 0))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (040) reflection test\n", "\n", "Repeat the `inverse` and `forward` calculations for the\n", "second orientation reflection." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Check `inverse()` at (040)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Hklpy2DiffractometerPseudoPos(h=5.97e-10, k=3.999916764257, l=0)" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fourc.inverse(-145.451, 90, 0, 69.0966)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Check `forward(040)`" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Hklpy2DiffractometerRealPos(omega=-145.450879003913, chi=89.999299941632, phi=89.980126517349, tth=69.098241992175)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fourc.forward(0, 4, 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Scan in reciprocal space using Bluesky\n", "\n", "To scan with Bluesky, we need more setup." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from bluesky import RunEngine\n", "from bluesky import SupplementalData\n", "from bluesky.callbacks.best_effort import BestEffortCallback\n", "import bluesky.plans as bp\n", "import bluesky.plan_stubs as bps\n", "import databroker\n", "\n", "bec = BestEffortCallback()\n", "bec.disable_plots()\n", "cat = databroker.temp().v2\n", "sd = SupplementalData()\n", "\n", "RE = RunEngine({})\n", "RE.md = {}\n", "RE.preprocessors.append(sd)\n", "RE.subscribe(cat.v1.insert)\n", "RE.subscribe(bec)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Setup the `RE` to save the `fourc` {class}`~hklpy2.blocks.configure.Configuration` with every run." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "crw = hklpy2.ConfigurationRunWrapper(fourc)\n", "RE.preprocessors.append(crw.wrapper)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (_h00_) scan near (400)\n", "\n", "In this example, we have no detector. Still, we add the diffractometer\n", "object in the detector list so that the _hkl_ and motor positions will appear\n", "as columns in the table." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 1 Time: 2025-03-26 18:55:00\n", "Persistent Unique Scan ID: '8ccf2f40-03d0-4c52-9c3e-5f2b2d0bdfcb'\n", "New stream: 'primary'\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "| seq_num | time | fourc_h | fourc_k | fourc_l | fourc_omega | fourc_chi | fourc_phi | fourc_tth |\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "| 1 | 18:55:00.2 | 3.900 | 0.000 | 0.000 | -33.569 | 0 | -112.862 | 67.137 |\n", "| 2 | 18:55:00.2 | 3.950 | 0.000 | 0.000 | -34.057 | 0 | -111.884 | 68.115 |\n", "| 3 | 18:55:00.2 | 4.000 | 0.000 | 0.000 | -34.549 | 0 | -110.901 | 69.098 |\n", "| 4 | 18:55:00.2 | 4.050 | 0.000 | 0.000 | -35.044 | 0 | -109.912 | 70.087 |\n", "| 5 | 18:55:00.2 | 4.100 | 0.000 | 0.000 | -35.541 | 0 | -108.917 | 71.083 |\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "generator scan ['8ccf2f40'] (scan num: 1)\n", "\n", "\n", "\n" ] }, { "data": { "text/plain": [ "('8ccf2f40-03d0-4c52-9c3e-5f2b2d0bdfcb',)" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fourc.move(4, 0, 0)\n", "RE(bp.scan([fourc], fourc.h, 3.9, 4.1, 5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### chi scan from (400) to (040)\n", "\n", "If we do this with $\\omega=-145.4500$ and $2\\theta=69.0985$, this will be a scan between the two orientation reflections.\n", "\n", "Use `%mov` (IPython *magic* command) to move both motors at the same time." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 2 Time: 2025-03-26 18:55:00\n", "Persistent Unique Scan ID: 'c556ed70-1fa3-4f1d-899a-0fa025865276'\n", "New stream: 'primary'\n", "+-----------+------------+------------+------------+------------+------------+-------------+------------+------------+\n", "| seq_num | time | fourc_chi | fourc_h | fourc_k | fourc_l | fourc_omega | fourc_phi | fourc_tth |\n", "+-----------+------------+------------+------------+------------+------------+-------------+------------+------------+\n", "| 1 | 18:55:00.4 | 0.000 | -1.297 | -0.000 | -3.784 | -145.450 | -108.917 | 69.099 |\n", "| 2 | 18:55:00.4 | 10.000 | -1.277 | 0.695 | -3.727 | -145.450 | -108.917 | 69.099 |\n", "| 3 | 18:55:00.4 | 20.000 | -1.219 | 1.368 | -3.556 | -145.450 | -108.917 | 69.099 |\n", "| 4 | 18:55:00.4 | 30.000 | -1.123 | 2.000 | -3.277 | -145.450 | -108.917 | 69.099 |\n", "| 5 | 18:55:00.4 | 40.000 | -0.993 | 2.571 | -2.899 | -145.450 | -108.917 | 69.099 |\n", "| 6 | 18:55:00.4 | 50.000 | -0.834 | 3.064 | -2.432 | -145.450 | -108.917 | 69.099 |\n", "| 7 | 18:55:00.4 | 60.000 | -0.648 | 3.464 | -1.892 | -145.450 | -108.917 | 69.099 |\n", "| 8 | 18:55:00.4 | 70.000 | -0.443 | 3.759 | -1.294 | -145.450 | -108.917 | 69.099 |\n", "| 9 | 18:55:00.4 | 80.000 | -0.225 | 3.939 | -0.657 | -145.450 | -108.917 | 69.099 |\n", "| 10 | 18:55:00.4 | 90.000 | 0.000 | 4.000 | -0.000 | -145.450 | -108.917 | 69.099 |\n", "+-----------+------------+------------+------------+------------+------------+-------------+------------+------------+\n", "generator scan ['c556ed70'] (scan num: 2)\n", "\n", "\n", "\n" ] }, { "data": { "text/plain": [ "('c556ed70-1fa3-4f1d-899a-0fa025865276',)" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# same as orientation reflections\n", "RE(bps.mv(fourc.omega,-145.4500, fourc.tth,69.0985))\n", "\n", "RE(bp.scan([fourc], fourc.chi, 0, 90, 10))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (_0k0_) scan near (040)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 3 Time: 2025-03-26 18:55:00\n", "Persistent Unique Scan ID: 'ef28fef9-5b67-4d82-b9bd-a92cf78249ef'\n", "New stream: 'primary'\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "| seq_num | time | fourc_k | fourc_h | fourc_l | fourc_omega | fourc_chi | fourc_phi | fourc_tth |\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "| 1 | 18:55:00.6 | 3.900 | 0.000 | -0.000 | -146.431 | 90.001 | -90.002 | 67.137 |\n", "| 2 | 18:55:00.6 | 3.950 | 0.000 | -0.000 | -145.943 | 90.001 | -90.001 | 68.115 |\n", "| 3 | 18:55:00.6 | 4.000 | 0.000 | -0.000 | -145.451 | 90.001 | -90.001 | 69.098 |\n", "| 4 | 18:55:00.6 | 4.050 | 0.000 | 0.000 | -144.956 | 90.001 | -90.001 | 70.087 |\n", "| 5 | 18:55:00.7 | 4.100 | 0.000 | -0.000 | -144.459 | 90.001 | -90.000 | 71.083 |\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "generator scan ['ef28fef9'] (scan num: 3)\n", "\n", "\n", "\n" ] }, { "data": { "text/plain": [ "('ef28fef9-5b67-4d82-b9bd-a92cf78249ef',)" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fourc.move(0, 4, 0)\n", "RE(bp.scan([fourc], fourc.k, 3.9, 4.1, 5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (_hk0_) scan near (440)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 4 Time: 2025-03-26 18:55:00\n", "Persistent Unique Scan ID: '49a6588c-636b-40a2-a73e-003c6062933b'\n", "New stream: 'primary'\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "| seq_num | time | fourc_h | fourc_k | fourc_l | fourc_omega | fourc_chi | fourc_phi | fourc_tth |\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "| 1 | 18:55:00.8 | 3.900 | 3.900 | -0.000 | -128.559 | 135.000 | -179.999 | 102.882 |\n", "| 2 | 18:55:00.8 | 3.950 | 3.950 | 0.000 | -127.628 | 135.000 | -179.999 | 104.744 |\n", "| 3 | 18:55:00.8 | 4.000 | 4.000 | 0.000 | -126.677 | 135.000 | -179.999 | 106.647 |\n", "| 4 | 18:55:00.9 | 4.050 | 4.050 | -0.000 | -125.704 | 135.000 | -179.999 | 108.592 |\n", "| 5 | 18:55:00.9 | 4.100 | 4.100 | -0.000 | -124.708 | 135.000 | -179.999 | 110.585 |\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "generator scan ['49a6588c'] (scan num: 4)\n", "\n", "\n", "\n" ] }, { "data": { "text/plain": [ "('49a6588c-636b-40a2-a73e-003c6062933b',)" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fourc.move(4, 4, 0)\n", "RE(bp.scan([fourc], fourc.h, 3.9, 4.1, fourc.k, 3.9, 4.1, 5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Move to the (_440_) reflection." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fourc.position = Hklpy2DiffractometerPseudoPos(h=3.999999995224, k=3.999999999806, l=-2.094e-09)\n" ] } ], "source": [ "fourc.move((4, 4, 0))\n", "print(f\"{fourc.position = }\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Repeat the same scan about the (_440_) but use _relative_ positions." ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 5 Time: 2025-03-26 18:55:01\n", "Persistent Unique Scan ID: 'bef1c41b-af46-4131-b8bd-d58d86e719c4'\n", "New stream: 'primary'\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "| seq_num | time | fourc_h | fourc_k | fourc_l | fourc_omega | fourc_chi | fourc_phi | fourc_tth |\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "| 1 | 18:55:01.1 | 3.900 | 3.900 | -0.000 | -128.559 | 135.000 | -179.999 | 102.882 |\n", "| 2 | 18:55:01.1 | 3.950 | 3.950 | -0.000 | -127.628 | 135.000 | -179.999 | 104.744 |\n", "| 3 | 18:55:01.1 | 4.000 | 4.000 | 0.000 | -126.677 | 135.000 | -179.999 | 106.647 |\n", "| 4 | 18:55:01.1 | 4.050 | 4.050 | -0.000 | -125.704 | 135.000 | -179.999 | 108.592 |\n", "| 5 | 18:55:01.1 | 4.100 | 4.100 | -0.000 | -124.708 | 135.000 | -179.999 | 110.585 |\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "generator rel_scan ['bef1c41b'] (scan num: 5)\n", "\n", "\n", "\n" ] }, { "data": { "text/plain": [ "('bef1c41b-af46-4131-b8bd-d58d86e719c4',)" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "RE(bp.rel_scan([fourc], fourc.h, -0.1, 0.1, fourc.k, -0.1, 0.1, 5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### scan $(h40)$ with $\\varphi=0$" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "h=-4.0, k=4.0, l=0\n", "wavelength=1.54\n", "omega=-126.6767, chi=135.0, phi=0, tth=106.6465\n" ] } ], "source": [ "fourc.core.solver.mode = \"constant_phi\"\n", "fourc.phi.move(0, wait=True)\n", "wh()" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 6 Time: 2025-03-26 18:55:01\n", "Persistent Unique Scan ID: 'cb7e8801-bd88-4b51-bdb0-85d2585ff7fb'\n", "New stream: 'primary'\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "| seq_num | time | fourc_h | fourc_k | fourc_l | fourc_omega | fourc_chi | fourc_phi | fourc_tth |\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "| 1 | 18:55:01.3 | -4.100 | 3.900 | -0.000 | -126.653 | 136.432 | 0 | 106.695 |\n", "| 2 | 18:55:01.3 | -4.050 | 3.950 | 0.000 | -126.671 | 135.716 | 0 | 106.659 |\n", "| 3 | 18:55:01.3 | -4.000 | 4.000 | 0.000 | -126.677 | 135.000 | 0 | 106.647 |\n", "| 4 | 18:55:01.4 | -3.950 | 4.050 | -0.000 | -126.671 | 134.284 | 0 | 106.659 |\n", "| 5 | 18:55:01.4 | -3.900 | 4.100 | -0.000 | -126.653 | 133.568 | 0 | 106.695 |\n", "+-----------+------------+------------+------------+------------+-------------+------------+------------+------------+\n", "generator rel_scan ['cb7e8801'] (scan num: 6)\n", "\n", "\n", "\n" ] }, { "data": { "text/plain": [ "('cb7e8801-bd88-4b51-bdb0-85d2585ff7fb',)" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "RE(bp.rel_scan([fourc], fourc.h, -0.1, 0.1, fourc.k, -0.1, 0.1, 5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Show the configuration\n", "\n", "Print the diffractometer configuration that was saved with the run." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'_header': {'datetime': '2025-03-26 18:55:01.320422',\n", " 'hklpy2_version': '0.0.28.dev104+g1a2d5d7.d20250326',\n", " 'python_class': 'Hklpy2Diffractometer',\n", " 'source_type': 'X-ray',\n", " 'energy_units': 'keV',\n", " 'energy': 8.050921976530415,\n", " 'wavelength_units': 'angstrom',\n", " 'wavelength': 1.54},\n", " 'name': 'fourc',\n", " 'axes': {'pseudo_axes': ['h', 'k', 'l'],\n", " 'real_axes': ['omega', 'chi', 'phi', 'tth'],\n", " 'axes_xref': {'h': 'h',\n", " 'k': 'k',\n", " 'l': 'l',\n", " 'omega': 'omega',\n", " 'chi': 'chi',\n", " 'phi': 'phi',\n", " 'tth': 'tth'},\n", " 'extra_axes': {}},\n", " 'sample_name': 'silicon',\n", " 'samples': {'sample': {'name': 'sample',\n", " 'lattice': {'a': 1,\n", " 'b': 1,\n", " 'c': 1,\n", " 'alpha': 90.0,\n", " 'beta': 90.0,\n", " 'gamma': 90.0},\n", " 'reflections': {},\n", " 'reflections_order': [],\n", " 'U': [[1, 0, 0], [0, 1, 0], [0, 0, 1]],\n", " 'UB': [[6.283185307179586, 0.0, 0.0],\n", " [0.0, 6.283185307179586, 0.0],\n", " [0.0, 0.0, 6.283185307179586]],\n", " 'digits': 4},\n", " 'silicon': {'name': 'silicon',\n", " 'lattice': {'a': 5.431020511,\n", " 'b': 5.431020511,\n", " 'c': 5.431020511,\n", " 'alpha': 90,\n", " 'beta': 90,\n", " 'gamma': 90},\n", " 'reflections': {'r_9ee9': {'name': 'r_9ee9',\n", " 'geometry': 'E4CV',\n", " 'pseudos': {'h': 4, 'k': 0, 'l': 0},\n", " 'reals': {'omega': -145.451, 'chi': 0, 'phi': 0, 'tth': 69.0966},\n", " 'wavelength': 1.54,\n", " 'digits': 4},\n", " 'r_39f5': {'name': 'r_39f5',\n", " 'geometry': 'E4CV',\n", " 'pseudos': {'h': 0, 'k': 4, 'l': 0},\n", " 'reals': {'omega': -145.451, 'chi': 90, 'phi': 0, 'tth': 69.0966},\n", " 'wavelength': 1.54,\n", " 'digits': 4}},\n", " 'reflections_order': ['r_9ee9', 'r_39f5'],\n", " 'U': [[-1.2217305e-05, -1.2217305e-05, -0.999999999851],\n", " [0.0, -0.999999999925, 1.2217305e-05],\n", " [-0.999999999925, 1.49e-10, 1.2217305e-05]],\n", " 'UB': [[-1.4134285e-05, -1.4134285e-05, -1.156906937382],\n", " [0.0, -1.156906937469, 1.4134285e-05],\n", " [-1.156906937469, 1.73e-10, 1.4134285e-05]],\n", " 'digits': 4}},\n", " 'constraints': {'omega': {'label': 'omega',\n", " 'low_limit': -180.0,\n", " 'high_limit': 0.001,\n", " 'class': 'LimitsConstraint'},\n", " 'chi': {'label': 'chi',\n", " 'low_limit': -180.0,\n", " 'high_limit': 180.0,\n", " 'class': 'LimitsConstraint'},\n", " 'phi': {'label': 'phi',\n", " 'low_limit': -180.0,\n", " 'high_limit': 180.0,\n", " 'class': 'LimitsConstraint'},\n", " 'tth': {'label': 'tth',\n", " 'low_limit': -0.001,\n", " 'high_limit': 180.0,\n", " 'class': 'LimitsConstraint'}},\n", " 'solver': {'name': 'hkl_soleil',\n", " 'description': \"HklSolver(name='hkl_soleil', version='5.1.2', geometry='E4CV', engine_name='hkl', mode='constant_phi')\",\n", " 'geometry': 'E4CV',\n", " 'real_axes': ['omega', 'chi', 'phi', 'tth'],\n", " 'version': '5.1.2',\n", " 'engine': 'hkl'}}" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat.v2[-1].metadata[\"start\"][\"diffractometers\"][\"fourc\"]" ] } ], "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.2" } }, "nbformat": 4, "nbformat_minor": 4 }