{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Sample orientation: export & restore diffractometer configuration\n", "\n", "A common user request is to preserve the orientation (**UB**) matrix and\n", "related terms used to compute it. Terms such as the list of orientation\n", "reflections, samples, and diffractometer geometry from their current session.\n", "The configuration should be saved somewhere so it is available, even after\n", "bluesky stops. Multiple sessions could (optionally) access the same\n", "configuration or use a different one.\n", "\n", "It is a local choice how and where to save this configuration. The first step\n", "is to define a common structure to be exported and restored by *hklpy*. The\n", "structure would be stored in any of a variety of possibilities (some of these\n", "are provided by *hklpy*, the others are suggestions).\n", "\n", "- text file: stored in:\n", " - the local file directory\n", " - some other directory\n", " - network storage\n", "- NeXus HDF5 file: stored in the `pwd` or elsewhere\n", "- EPICS [Channel\n", " Access](https://epics-controls.org/resources-and-support/documents/ca/) string\n", " [*waveform*](https://epics.anl.gov/base/R7-0/3-docs/waveformRecord.html) record\n", "- EPICS [pvAccess](https://epics-controls.org/resources-and-support/documents/pvaccess/) structure\n", "- in-memory cache, such as:\n", " - [redis](https://redis.io)\n", "- database, such as:\n", " - [MySQL](https://mysql.com)\n", " - [SQLite](https://sqlite.org)\n", "- Python object: (such as used in this documentation)\n", " - dictionary\n", " - JSON string\n", " - YAML string\n", "\n", "A session could restore the configuration automatically from the chosen storage.\n", "Later, the session would export the configuration both automatically, and to a\n", "different location at the choice of the user.\n", "\n", "**Objective**\n", "\n", "Show how to export diffractometer configuration to a file and later restore it.\n", "Demonstrate with a 4-circle diffractometer (E4CV geometry)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup a (simulated) 4-circle diffractometer\n", "\n", "Load the support for a 4-circle diffractometer using the *E4CV* geometry. Since\n", "this is a simulation, we do not need an EPICS system with motors. The\n", "[SimulatedE4CV](https://blueskyproject.io/hklpy/ready_to_use.html#simulatede4cv)\n", "structure (a Python class) provides all that is needed." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from hkl import SimulatedE4CV\n", "\n", "sim4c = SimulatedE4CV(\"\", name=\"sim4c\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Print all the details about this `sim4c` diffractometer we just created. Since this is a default configuration, no orientation reflections have been reported. The **UB** matrix is the default $(2\\pi/1.54)$**U** where **U** is the identity matrix and 1.54 is the unit cell length. The geometry defines the names of the rotational axes `omega`, `chi`, `phi`, and `tth`. This is the canonical order. The *constraints* are applied when computing values for the rotational axes from reciprocal space coordinates." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "===================== ====================================================================\n", "term value \n", "===================== ====================================================================\n", "diffractometer sim4c \n", "geometry E4CV \n", "class SimulatedE4CV \n", "energy (keV) 8.05092 \n", "wavelength (angstrom) 1.54000 \n", "calc engine hkl \n", "mode bissector \n", "positions ===== ======= \n", " name value \n", " ===== ======= \n", " omega 0.00000 \n", " chi 0.00000 \n", " phi 0.00000 \n", " tth 0.00000 \n", " ===== ======= \n", "constraints ===== ========= ========== ===== ==== \n", " axis low_limit high_limit value fit \n", " ===== ========= ========== ===== ==== \n", " omega -180.0 180.0 0.0 True \n", " chi -180.0 180.0 0.0 True \n", " phi -180.0 180.0 0.0 True \n", " tth -180.0 180.0 0.0 True \n", " ===== ========= ========== ===== ==== \n", "sample: main ================ ===================================================\n", " term value \n", " ================ ===================================================\n", " unit cell edges a=1.54, b=1.54, c=1.54 \n", " unit cell angles alpha=90.0, beta=90.0, gamma=90.0 \n", " [U] [[1. 0. 0.] \n", " [0. 1. 0.] \n", " [0. 0. 1.]] \n", " [UB] [[ 4.07999046e+00 -2.49827363e-16 -2.49827363e-16] \n", " [ 0.00000000e+00 4.07999046e+00 -2.49827363e-16] \n", " [ 0.00000000e+00 0.00000000e+00 4.07999046e+00]]\n", " ================ ===================================================\n", "===================== ====================================================================\n", "\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sim4c.pa()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What is described in a diffractometer configuration?\n", "\n", "The `hkl.DiffractometerConfiguration` structure is used for export and restore.\n", "To show what an export contains (for this default diffractometer), we make a\n", "Python object specifically for the `sim4c` diffractometer. In this example, the\n", "object is called `agent` (you could pick some other name, such as `config`).\n", "\n", "Create `agent` specifically for the `sim4c` diffractometer to provide the\n", "methods in the next table.\n", "\n", "Python | description\n", "--- | ---\n", "`agent.export()` | describe a diffractometer’s configuration\n", "`agent.preview()` | preview a saved configuration\n", "`agent.restore()` | set a diffractometer’s configuration" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from hkl import DiffractometerConfiguration\n", "\n", "agent = DiffractometerConfiguration(sim4c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Export\n", "\n", "`export()` returns the current configuration of the diffractometer in any of several formats:\n", "\n", "- JSON string (default)\n", "- YAML string\n", "- Python dictionary\n", "- file (as defined by a Python *pathlib* object)\n", "\n", "Note: Internally, the code uses the Python dictionary for the actual export and\n", "restore operations. The other formats derive from the Python dictionary. All\n", "information in the Python dictionary is first validated before it is restored to\n", "the diffractometer." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Export: JSON string (default) format\n", "\n", "Describe `sim4c` using `agent.export()`. The information content is similar to\n", "`sim4c.pa()`, but in a format convenient for both saving (to a file or other\n", "structure) and for restoring.\n", "\n", "The default format is a [JSON](https://json.org) string, formatted with line\n", "endings and indentation. (Alternatives include Python dictionary,\n", "[YAML](https://yaml.org), and file.)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"geometry\": \"E4CV\",\n", " \"engine\": \"hkl\",\n", " \"library\": \"gi.repository.Hkl\",\n", " \"mode\": \"bissector\",\n", " \"canonical_axes\": [\n", " \"omega\",\n", " \"chi\",\n", " \"phi\",\n", " \"tth\"\n", " ],\n", " \"real_axes\": [\n", " \"omega\",\n", " \"chi\",\n", " \"phi\",\n", " \"tth\"\n", " ],\n", " \"reciprocal_axes\": [\n", " \"h\",\n", " \"k\",\n", " \"l\"\n", " ],\n", " \"constraints\": {\n", " \"omega\": {\n", " \"low_limit\": -180.0,\n", " \"high_limit\": 180.0,\n", " \"value\": 0.0,\n", " \"fit\": true\n", " },\n", " \"chi\": {\n", " \"low_limit\": -180.0,\n", " \"high_limit\": 180.0,\n", " \"value\": 0.0,\n", " \"fit\": true\n", " },\n", " \"phi\": {\n", " \"low_limit\": -180.0,\n", " \"high_limit\": 180.0,\n", " \"value\": 0.0,\n", " \"fit\": true\n", " },\n", " \"tth\": {\n", " \"low_limit\": -180.0,\n", " \"high_limit\": 180.0,\n", " \"value\": 0.0,\n", " \"fit\": true\n", " }\n", " },\n", " \"samples\": {\n", " \"main\": {\n", " \"name\": \"main\",\n", " \"lattice\": {\n", " \"a\": 1.54,\n", " \"b\": 1.54,\n", " \"c\": 1.54,\n", " \"alpha\": 90.0,\n", " \"beta\": 90.0,\n", " \"gamma\": 90.0\n", " },\n", " \"reflections\": [],\n", " \"UB\": [\n", " [\n", " 4.079990459207523,\n", " -2.4982736282101165e-16,\n", " -2.4982736282101165e-16\n", " ],\n", " [\n", " 0.0,\n", " 4.079990459207523,\n", " -2.4982736282101165e-16\n", " ],\n", " [\n", " 0.0,\n", " 0.0,\n", " 4.079990459207523\n", " ]\n", " ],\n", " \"U\": [\n", " [\n", " 1.0,\n", " 0.0,\n", " 0.0\n", " ],\n", " [\n", " 0.0,\n", " 1.0,\n", " 0.0\n", " ],\n", " [\n", " 0.0,\n", " 0.0,\n", " 1.0\n", " ]\n", " ]\n", " }\n", " },\n", " \"name\": \"sim4c\",\n", " \"datetime\": \"2023-11-16 12:48:44.500249\",\n", " \"wavelength_angstrom\": 1.54,\n", " \"energy_keV\": 8.050921974025975,\n", " \"hklpy_version\": \"1.0.5.dev207+g955ab4d\",\n", " \"library_version\": \"v5.0.0.3001\",\n", " \"python_class\": \"SimulatedE4CV\",\n", " \"other\": {}\n", "}\n" ] } ], "source": [ "print(agent.export())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Export: YAML string format\n", "\n", "View the same content in YAML format:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "geometry: E4CV\n", "engine: hkl\n", "library: gi.repository.Hkl\n", "mode: bissector\n", "canonical_axes:\n", "- omega\n", "- chi\n", "- phi\n", "- tth\n", "real_axes:\n", "- omega\n", "- chi\n", "- phi\n", "- tth\n", "reciprocal_axes:\n", "- h\n", "- k\n", "- l\n", "constraints:\n", " omega:\n", " low_limit: -180.0\n", " high_limit: 180.0\n", " value: 0.0\n", " fit: true\n", " chi:\n", " low_limit: -180.0\n", " high_limit: 180.0\n", " value: 0.0\n", " fit: true\n", " phi:\n", " low_limit: -180.0\n", " high_limit: 180.0\n", " value: 0.0\n", " fit: true\n", " tth:\n", " low_limit: -180.0\n", " high_limit: 180.0\n", " value: 0.0\n", " fit: true\n", "samples:\n", " main:\n", " name: main\n", " lattice:\n", " a: 1.54\n", " b: 1.54\n", " c: 1.54\n", " alpha: 90.0\n", " beta: 90.0\n", " gamma: 90.0\n", " reflections: []\n", " UB:\n", " - - 4.079990459207523\n", " - -2.4982736282101165e-16\n", " - -2.4982736282101165e-16\n", " - - 0.0\n", " - 4.079990459207523\n", " - -2.4982736282101165e-16\n", " - - 0.0\n", " - 0.0\n", " - 4.079990459207523\n", " U:\n", " - - 1.0\n", " - 0.0\n", " - 0.0\n", " - - 0.0\n", " - 1.0\n", " - 0.0\n", " - - 0.0\n", " - 0.0\n", " - 1.0\n", "name: sim4c\n", "datetime: '2023-11-16 12:48:44.571162'\n", "wavelength_angstrom: 1.54\n", "energy_keV: 8.050921974025975\n", "hklpy_version: 1.0.5.dev207+g955ab4d\n", "library_version: v5.0.0.3001\n", "python_class: SimulatedE4CV\n", "other: {}\n", "\n" ] } ], "source": [ "print(agent.export(\"yaml\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Export: Python dictionary format\n", "\n", "Or as Python dictionary:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'geometry': 'E4CV',\n", " 'engine': 'hkl',\n", " 'library': 'gi.repository.Hkl',\n", " 'mode': 'bissector',\n", " 'canonical_axes': ['omega', 'chi', 'phi', 'tth'],\n", " 'real_axes': ['omega', 'chi', 'phi', 'tth'],\n", " 'reciprocal_axes': ['h', 'k', 'l'],\n", " 'constraints': {'omega': {'low_limit': -180.0,\n", " 'high_limit': 180.0,\n", " 'value': 0.0,\n", " 'fit': True},\n", " 'chi': {'low_limit': -180.0, 'high_limit': 180.0, 'value': 0.0, 'fit': True},\n", " 'phi': {'low_limit': -180.0, 'high_limit': 180.0, 'value': 0.0, 'fit': True},\n", " 'tth': {'low_limit': -180.0,\n", " 'high_limit': 180.0,\n", " 'value': 0.0,\n", " 'fit': True}},\n", " 'samples': {'main': {'name': 'main',\n", " 'lattice': {'a': 1.54,\n", " 'b': 1.54,\n", " 'c': 1.54,\n", " 'alpha': 90.0,\n", " 'beta': 90.0,\n", " 'gamma': 90.0},\n", " 'reflections': [],\n", " 'UB': [[4.079990459207523,\n", " -2.4982736282101165e-16,\n", " -2.4982736282101165e-16],\n", " [0.0, 4.079990459207523, -2.4982736282101165e-16],\n", " [0.0, 0.0, 4.079990459207523]],\n", " 'U': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]}},\n", " 'name': 'sim4c',\n", " 'datetime': '2023-11-16 12:48:44.578586',\n", " 'wavelength_angstrom': 1.54,\n", " 'energy_keV': 8.050921974025975,\n", " 'hklpy_version': '1.0.5.dev207+g955ab4d',\n", " 'library_version': 'v5.0.0.3001',\n", " 'python_class': 'SimulatedE4CV',\n", " 'other': {}}" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "agent.export(\"dict\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Export: Data file (text)\n", "\n", "Or as a data file. To save as a data file, we need the name (and directory\n", "path) of that file. Could be a local file such as `sim4c-config.json` or a file\n", "in some other directory such as `~/.config/sim4c/autosave.json`. These are just\n", "ideas.\n", "\n", "In any case, we describe the file name and path using Python's\n", "[pathlib](https://docs.python.org/3/library/pathlib.html) support package.\n", "\n", "For this example, we'll use files created just for this notebook in a temporary\n", "directory using Python's\n", "[tempfile](https://docs.python.org/3/library/tempfile.html) package. The entire\n", "directory will be deleted when the notebook exits. (The `iterdir()` method\n", "prints the directory's contents. It's empty at the start.)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "config_path=PosixPath('/tmp/tmpvrwz9f7z')\n", "list(config_path.iterdir())=[]\n" ] } ], "source": [ "import pathlib\n", "import tempfile\n", "\n", "temp_dir = tempfile.TemporaryDirectory()\n", "config_path = pathlib.Path(temp_dir.name)\n", "print(f\"{config_path=}\")\n", "print(f\"{list(config_path.iterdir())=}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Export the configuration to file `sim4c.json` in the temporary directory. Show the file exists." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "list(config_path.iterdir())=[PosixPath('/tmp/tmpvrwz9f7z/sim4c.json')]\n" ] } ], "source": [ "config_file = config_path / \"sim4c.json\"\n", "agent.export(config_file)\n", "print(f\"{list(config_path.iterdir())=}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Show the contents of the new configuration file." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"geometry\": \"E4CV\",\n", " \"engine\": \"hkl\",\n", " \"library\": \"gi.repository.Hkl\",\n", " \"mode\": \"bissector\",\n", " \"canonical_axes\": [\n", " \"omega\",\n", " \"chi\",\n", " \"phi\",\n", " \"tth\"\n", " ],\n", " \"real_axes\": [\n", " \"omega\",\n", " \"chi\",\n", " \"phi\",\n", " \"tth\"\n", " ],\n", " \"reciprocal_axes\": [\n", " \"h\",\n", " \"k\",\n", " \"l\"\n", " ],\n", " \"constraints\": {\n", " \"omega\": {\n", " \"low_limit\": -180.0,\n", " \"high_limit\": 180.0,\n", " \"value\": 0.0,\n", " \"fit\": true\n", " },\n", " \"chi\": {\n", " \"low_limit\": -180.0,\n", " \"high_limit\": 180.0,\n", " \"value\": 0.0,\n", " \"fit\": true\n", " },\n", " \"phi\": {\n", " \"low_limit\": -180.0,\n", " \"high_limit\": 180.0,\n", " \"value\": 0.0,\n", " \"fit\": true\n", " },\n", " \"tth\": {\n", " \"low_limit\": -180.0,\n", " \"high_limit\": 180.0,\n", " \"value\": 0.0,\n", " \"fit\": true\n", " }\n", " },\n", " \"samples\": {\n", " \"main\": {\n", " \"name\": \"main\",\n", " \"lattice\": {\n", " \"a\": 1.54,\n", " \"b\": 1.54,\n", " \"c\": 1.54,\n", " \"alpha\": 90.0,\n", " \"beta\": 90.0,\n", " \"gamma\": 90.0\n", " },\n", " \"reflections\": [],\n", " \"UB\": [\n", " [\n", " 4.079990459207523,\n", " -2.4982736282101165e-16,\n", " -2.4982736282101165e-16\n", " ],\n", " [\n", " 0.0,\n", " 4.079990459207523,\n", " -2.4982736282101165e-16\n", " ],\n", " [\n", " 0.0,\n", " 0.0,\n", " 4.079990459207523\n", " ]\n", " ],\n", " \"U\": [\n", " [\n", " 1.0,\n", " 0.0,\n", " 0.0\n", " ],\n", " [\n", " 0.0,\n", " 1.0,\n", " 0.0\n", " ],\n", " [\n", " 0.0,\n", " 0.0,\n", " 1.0\n", " ]\n", " ]\n", " }\n", " },\n", " \"name\": \"sim4c\",\n", " \"datetime\": \"2023-11-16 12:48:44.591289\",\n", " \"wavelength_angstrom\": 1.54,\n", " \"energy_keV\": 8.050921974025975,\n", " \"hklpy_version\": \"1.0.5.dev207+g955ab4d\",\n", " \"library_version\": \"v5.0.0.3001\",\n", " \"python_class\": \"SimulatedE4CV\",\n", " \"other\": {}\n", "}\n" ] } ], "source": [ "with open(config_file) as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Preview & Restore\n", "\n", "To demonstrate `agent.preview()` and `agent.restore()`, let's compare the file\n", "we just wrote with a file found on the internet. The *hklpy* repository on\n", "GitHub has a *compatible* (same geometry, canonical motor names, and back-end\n", "computation library) file used for testing the *hklpy* source code.\n", "\n", "We'll use the [requests](https://docs.python-requests.org/) package for the\n", "download. With *requests*, we can keep the structure in memory. (There is no\n", "need to save it to a local file.)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test_e4c_config='{\\n \"geometry\": \"E4CV\",\\n \"engine\": \"hkl\",\\n \"library\": \"gi.repository.Hkl\",\\n \"mode\": \"bissector\",\\n \"canonical_axes\": [\\n \"omega\",\\n \"chi\",\\n \"phi\",\\n \"tth\"\\n ],\\n \"real_axes\": [\\n \"omega\",\\n \"chi\",\\n \"phi\",\\n \"tth\"\\n ],\\n \"reciprocal_axes\": [\\n \"h\",\\n \"k\",\\n \"l\"\\n ],\\n \"constraints\": {\\n \"omega\": {\\n \"low_limit\": -100.0,\\n \"high_limit\": 100.0,\\n \"value\": 0.0,\\n \"fit\": true\\n },\\n \"chi\": {\\n \"low_limit\": -100.0,\\n \"high_limit\": 100.0,\\n \"value\": 0.0,\\n \"fit\": true\\n },\\n \"phi\": {\\n \"low_limit\": -100.0,\\n \"high_limit\": 100.0,\\n \"value\": 0.0,\\n \"fit\": true\\n },\\n \"tth\": {\\n \"low_limit\": -100.0,\\n \"high_limit\": 100.0,\\n \"value\": 0.0,\\n \"fit\": true\\n }\\n },\\n \"samples\": {\\n \"main\": {\\n \"name\": \"main\",\\n \"lattice\": {\\n \"a\": 1.54,\\n \"b\": 1.54,\\n \"c\": 1.54,\\n \"alpha\": 90.0,\\n \"beta\": 90.0,\\n \"gamma\": 90.0\\n },\\n \"reflections\": [],\\n \"UB\": [\\n [\\n 4.079990459207523,\\n -2.4982736282101165e-16,\\n -2.4982736282101165e-16\\n ],\\n [\\n 0.0,\\n 4.079990459207523,\\n -2.4982736282101165e-16\\n ],\\n [\\n 0.0,\\n 0.0,\\n 4.079990459207523\\n ]\\n ],\\n \"U\": [\\n [\\n 1.0,\\n 0.0,\\n 0.0\\n ],\\n [\\n 0.0,\\n 1.0,\\n 0.0\\n ],\\n [\\n 0.0,\\n 0.0,\\n 1.0\\n ]\\n ]\\n },\\n \"vibranium\": {\\n \"name\": \"vibranium\",\\n \"lattice\": {\\n \"a\": 6.283185307179586,\\n \"b\": 6.283185307179586,\\n \"c\": 6.283185307179586,\\n \"alpha\": 90.0,\\n \"beta\": 90.0,\\n \"gamma\": 90.0\\n },\\n \"reflections\": [\\n {\\n \"reflection\": {\\n \"h\": 4.0,\\n \"k\": 0.0,\\n \"l\": 0.0\\n },\\n \"position\": {\\n \"omega\": -145.451,\\n \"chi\": 0.0,\\n \"phi\": 0.0,\\n \"tth\": 69.0966\\n },\\n \"wavelength\": 1.54,\\n \"orientation_reflection\": false,\\n \"flag\": 1\\n },\\n {\\n \"reflection\": {\\n \"h\": 0.0,\\n \"k\": 4.0,\\n \"l\": 0.0\\n },\\n \"position\": {\\n \"omega\": -145.451,\\n \"chi\": 0.0,\\n \"phi\": 90.0,\\n \"tth\": 69.0966\\n },\\n \"wavelength\": 1.54,\\n \"orientation_reflection\": true,\\n \"flag\": 1\\n },\\n {\\n \"reflection\": {\\n \"h\": 0.0,\\n \"k\": 0.0,\\n \"l\": 4.0\\n },\\n \"position\": {\\n \"omega\": -145.451,\\n \"chi\": 90.0,\\n \"phi\": 0.0,\\n \"tth\": 69.0966\\n },\\n \"wavelength\": 1.54,\\n \"orientation_reflection\": true,\\n \"flag\": 1\\n }\\n ],\\n \"UB\": [\\n [\\n 1.2217304763701863e-05,\\n -0.9999999999253688,\\n -1.7623547209572502e-15\\n ],\\n [\\n -1.4926257043558267e-10,\\n -1.4349296274686127e-42,\\n -1.0000000000000002\\n ],\\n [\\n 0.9999999999253688,\\n 1.221730476364063e-05,\\n -1.492626316575311e-10\\n ]\\n ],\\n \"U\": [\\n [\\n 1.2217304763701863e-05,\\n -0.9999999999253688,\\n -1.8235863128158895e-15\\n ],\\n [\\n -1.4926257043558267e-10,\\n -9.139696455822134e-27,\\n -1.0000000000000002\\n ],\\n [\\n 0.9999999999253688,\\n 1.2217304763701863e-05,\\n -1.4926257042444305e-10\\n ]\\n ]\\n }\\n },\\n \"name\": \"e4c\",\\n \"datetime\": \"2023-11-01 16:40\",\\n \"wavelength_angstrom\": 1.54,\\n \"energy_keV\": 8.050921974025975,\\n \"hklpy_version\": \"1.0.5.dev122+g473f61f\",\\n \"library_version\": \"v5.0.0.3001\",\\n \"python_class\": \"SimulatedE4CV\",\\n \"other\": {}\\n}\\n'\n" ] } ], "source": [ "import requests\n", "\n", "r = requests.get(\n", " \"https://raw.githubusercontent.com/bluesky/hklpy/main/hkl/tests/data/e4c-config.json\"\n", ")\n", "test_e4c_config = r.text\n", "print(f\"{test_e4c_config=}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Preview: JSON string\n", "\n", "The `agent.preview(structure)` method shows the sample information (name,\n", "crystal lattice parameters, and number of orientation reflections) from the\n", "configuration `structure` object, without loading it into the diffractometer.\n", "\n", "`agent.preview()` works with these types of `structure`: \n", "\n", "- JSON string\n", "- YAML string\n", "- Python dictionary\n", "- file (pathlib object)\n", "\n", "Here, `test_e4c_config` is recognized as a JSON string." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "name: e4c\n", "date: 2023-11-01 16:40\n", "geometry: E4CV\n", "\n", "Table of Samples\n", "= ========= ========= ========= ========= ===== ==== ===== =====\n", "# sample a b c alpha beta gamma #refl\n", "= ========= ========= ========= ========= ===== ==== ===== =====\n", "1 main 1.54 1.54 1.54 90.0 90.0 90.0 0 \n", "2 vibranium 6.2831853 6.2831853 6.2831853 90.0 90.0 90.0 3 \n", "= ========= ========= ========= ========= ===== ==== ===== =====\n", "\n" ] } ], "source": [ "print(type(test_e4c_config))\n", "print(agent.preview(test_e4c_config))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "See that `test_e4c_config` has an additional sample: `vibranium` (looks cubic\n", "with a lattice constant $a_o=2\\pi$ which is right since *vibranium* is\n", "fictional). Three orientation reflections are provided. Next, show the\n", "additional details." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "name: e4c\n", "date: 2023-11-01 16:40\n", "geometry: E4CV\n", "\n", "Table of Samples\n", "= ========= ========= ========= ========= ===== ==== ===== =====\n", "# sample a b c alpha beta gamma #refl\n", "= ========= ========= ========= ========= ===== ==== ===== =====\n", "1 main 1.54 1.54 1.54 90.0 90.0 90.0 0 \n", "2 vibranium 6.2831853 6.2831853 6.2831853 90.0 90.0 90.0 3 \n", "= ========= ========= ========= ========= ===== ==== ===== =====\n", "\n", "\n", "Table of Reflections for Sample: vibranium\n", "= === === === ======== ==== ==== ======= ========== =======\n", "# h k l omega chi phi tth wavelength orient?\n", "= === === === ======== ==== ==== ======= ========== =======\n", "1 4.0 0.0 0.0 -145.451 0.0 0.0 69.0966 1.54 False \n", "2 0.0 4.0 0.0 -145.451 0.0 90.0 69.0966 1.54 True \n", "3 0.0 0.0 4.0 -145.451 90.0 0.0 69.0966 1.54 True \n", "= === === === ======== ==== ==== ======= ========== =======\n", "\n", "\n", "Table of Axis Constraints\n", "===== ========= ========== ===== ====\n", "axis low_limit high_limit value fit?\n", "===== ========= ========== ===== ====\n", "omega -100.0 100.0 0.0 True\n", "chi -100.0 100.0 0.0 True\n", "phi -100.0 100.0 0.0 True\n", "tth -100.0 100.0 0.0 True\n", "===== ========= ========== ===== ====\n", "\n" ] } ], "source": [ "# options to show constraints and list of reflections\n", "print(agent.preview(test_e4c_config, show_constraints=True, show_reflections=True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the high and low limits in the constraints are now $\\pm100$. In the default, they were $\\pm180$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Restore: JSON string\n", "\n", "Let's restore the `test_e4c_config` configuration to our `sim4c` diffractometer.\n", "This is possible because we have identical matches of the diffractometer and the\n", "configuration:\n", "\n", "- name of geometry\n", "- name of computation engine\n", "- name of back-end support library\n", "- names and exact order of reciprocal-space axes\n", "- names and exact order of canonical real-space axes\n", "\n", "(Other validation steps are applied to make sure that the data in the\n", "configuration is specified correctly.)\n", "\n", "Once restore is complete, print all the diffractometer settings, as before using `sim4c.pa()`.\n", "\n", "Note: The `agent.restore()` method does not move any axes of the diffractometer.\n", "It only changes configuration settings in Python memory." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "===================== ===============================================================================\n", "term value \n", "===================== ===============================================================================\n", "diffractometer sim4c \n", "geometry E4CV \n", "class SimulatedE4CV \n", "energy (keV) 8.05092 \n", "wavelength (angstrom) 1.54000 \n", "calc engine hkl \n", "mode bissector \n", "positions ===== ======= \n", " name value \n", " ===== ======= \n", " omega 0.00000 \n", " chi 0.00000 \n", " phi 0.00000 \n", " tth 0.00000 \n", " ===== ======= \n", "constraints ===== ========= ========== ===== ==== \n", " axis low_limit high_limit value fit \n", " ===== ========= ========== ===== ==== \n", " omega -100.0 100.0 0.0 True \n", " chi -100.0 100.0 0.0 True \n", " phi -100.0 100.0 0.0 True \n", " tth -100.0 100.0 0.0 True \n", " ===== ========= ========== ===== ==== \n", "sample: vibranium ================= =============================================================\n", " term value \n", " ================= =============================================================\n", " unit cell edges a=6.283185307179586, b=6.283185307179586, c=6.283185307179586\n", " unit cell angles alpha=90.0, beta=90.0, gamma=90.0 \n", " ref 1 (hkl) h=4.0, k=0.0, l=0.0 \n", " ref 1 positioners omega=-145.45100, chi=0.00000, phi=0.00000, tth=69.09660 \n", " ref 2 (hkl) h=0.0, k=4.0, l=0.0 \n", " ref 2 positioners omega=-145.45100, chi=0.00000, phi=90.00000, tth=69.09660 \n", " ref 3 (hkl) h=0.0, k=0.0, l=4.0 \n", " ref 3 positioners omega=-145.45100, chi=90.00000, phi=0.00000, tth=69.09660 \n", " [U] [[ 1.22173048e-05 -1.00000000e+00 -1.82358631e-15] \n", " [-1.49262570e-10 -9.13969646e-27 -1.00000000e+00] \n", " [ 1.00000000e+00 1.22173048e-05 -1.49262570e-10]] \n", " [UB] [[ 1.22173048e-05 -1.00000000e+00 -1.76235472e-15] \n", " [-1.49262570e-10 -1.43492963e-42 -1.00000000e+00] \n", " [ 1.00000000e+00 1.22173048e-05 -1.49262632e-10]] \n", " ================= =============================================================\n", "===================== ===============================================================================\n", "\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "agent.restore(test_e4c_config)\n", "sim4c.pa()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Observe the list of three *vibranium* sample reflections. Two of them, as\n", "noted, have been used to compute the **UB** matrix." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Restore: file\n", "\n", "We can swap back to the default settings by restoring from the temporary\n", "configuration file we created above. This resets the constraints and removes\n", "the *vibranium* sample." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "===================== ====================================================================\n", "term value \n", "===================== ====================================================================\n", "diffractometer sim4c \n", "geometry E4CV \n", "class SimulatedE4CV \n", "energy (keV) 8.05092 \n", "wavelength (angstrom) 1.54000 \n", "calc engine hkl \n", "mode bissector \n", "positions ===== ======= \n", " name value \n", " ===== ======= \n", " omega 0.00000 \n", " chi 0.00000 \n", " phi 0.00000 \n", " tth 0.00000 \n", " ===== ======= \n", "constraints ===== ========= ========== ===== ==== \n", " axis low_limit high_limit value fit \n", " ===== ========= ========== ===== ==== \n", " omega -180.0 180.0 0.0 True \n", " chi -180.0 180.0 0.0 True \n", " phi -180.0 180.0 0.0 True \n", " tth -180.0 180.0 0.0 True \n", " ===== ========= ========== ===== ==== \n", "sample: main ================ ===================================================\n", " term value \n", " ================ ===================================================\n", " unit cell edges a=1.54, b=1.54, c=1.54 \n", " unit cell angles alpha=90.0, beta=90.0, gamma=90.0 \n", " [U] [[1. 0. 0.] \n", " [0. 1. 0.] \n", " [0. 0. 1.]] \n", " [UB] [[ 4.07999046e+00 -2.49827363e-16 -2.49827363e-16] \n", " [ 0.00000000e+00 4.07999046e+00 -2.49827363e-16] \n", " [ 0.00000000e+00 0.00000000e+00 4.07999046e+00]]\n", " ================ ===================================================\n", "===================== ====================================================================\n", "\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "agent.restore(config_file)\n", "sim4c.pa()" ] } ], "metadata": { "kernelspec": { "display_name": "base", "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.11.6" } }, "nbformat": 4, "nbformat_minor": 2 }