{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# **hkl_soleil** UB matrix : calculate from 2 reflections.\n",
    "\n",
    "$UB$ is the 3x3 orientation matrix used to transform coordinates between\n",
    "reciprocal space directions (of the crystal lattice planes) and the rotational\n",
    "axes of the diffractometer."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create a diffractometer object\n",
    "\n",
    "First, create a diffractometer object that uses the `\"hkl_soleil\"` solver with\n",
    "the `\"hkl\"` computation engine.  This solver provides support for many\n",
    "diffractometer geometries.  This example will use the simulated 4-circle\n",
    "geometry from the solver's `\"E4CV\"`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import hklpy2\n",
    "\n",
    "diffractometer = hklpy2.creator(name=\"diffractometer\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Defaults\n",
    "\n",
    "The diffractometer object starts with a default sample.  The structure is cubic ($a=b=c$, 90 degree corners)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Sample(name='sample', lattice=Lattice(a=1, system='cubic'))"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diffractometer.sample"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Add 2 reflections\n",
    "\n",
    "Two reflections are needed to calculate $UB$.  Since we do not specify the wavelength, the support assumes the diffractometer's current wavelength."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diffractometer.wavelength.get()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add two non-parallel reflections.  Here, just the values of the pseudos and\n",
    "reals are specified as Python tuples, in the exact order expected by the\n",
    "*solver* geometry."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "r100 = diffractometer.add_reflection((1, 0, 0), (-145.451, 5, -5, 69.0966), name=\"(100)\")\n",
    "r010 = diffractometer.add_reflection((0, 1, 0), (-145.451, 5, 85, 69.0966), name=\"(010)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Compute UB\n",
    "\n",
    "Compute $UB$ with these two reflections:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0.545455242664, -6.239788247453, -0.49592954663],\n",
       " [-0.547615556651, -0.543471893498, 6.235636483453],\n",
       " [-6.235462715682, -0.498106806877, -0.591013170474]]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diffractometer.core.calc_UB(r100, r010)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Show the calculated $UB$ matrix:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0.545455242664, -6.239788247453, -0.49592954663],\n",
       " [-0.547615556651, -0.543471893498, 6.235636483453],\n",
       " [-6.235462715682, -0.498106806877, -0.591013170474]]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diffractometer.core.solver.UB"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Try it out\n",
    "\n",
    " corresponding to the $(1,0,0)$ reflection:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Hklpy2DiffractometerRealPos(omega=-150.000007544679, chi=4.999999954605, phi=-4.999297290893, tth=59.999984910642)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diffractometer.forward(1, 0, 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Show the (first set of computed) angles corresponding to the $(1 \\bar1 1)$ reflection:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Hklpy2DiffractometerRealPos(omega=-120.000010083233, chi=-34.93175944456, phi=-44.822654638391, tth=119.999979833534)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diffractometer.forward(1, -1, 1)"
   ]
  }
 ],
 "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.13.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}