{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "7a1dc6b7-2324-419f-bece-7e01054d3f5a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b]0;⊚slic\u0007"
     ]
    }
   ],
   "source": [
    "import sys\n",
    "sys.path.append('/sf/cristallina/applications/slic/cristallina/crq_exp/')\n",
    "from diffractometer import Diffractometer\n",
    "from slic.core.adjustable import PVAdjustable,Adjustable\n",
    "dm1 = Diffractometer(\"SARES31-GPS\")\n",
    "dm2 = Diffractometer(\"SARES32-GPS\")\n",
    "from time import sleep\n",
    "import h5py\n",
    "import matplotlib.pyplot as plt\n",
    "from bsread import source, PULL\n",
    "from slic.core.acquisition import PVAcquisition\n",
    "from slic.core.adjustable import Collection\n",
    "from slic.core.acquisition.pvacquisition import epics_to_h5_polling\n",
    "from sfdata import SFDataFile\n",
    "from collections import defaultdict\n",
    "import numpy as np\n",
    "from tqdm.notebook import tqdm\n",
    "from slic.devices.general.motor import Motor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "cb01491d-669d-431a-b774-84181c1e266b",
   "metadata": {},
   "outputs": [],
   "source": [
    "dm1_chs = ['SARES31-GPS:ROT2THETA-BS',\n",
    "'SARES31-GPS:ROTTHETA-BS',\n",
    "'SARES31-GPS:ROTX-BS',\n",
    "'SARES31-GPS:ROTZ-BS',\n",
    "'SARES31-GPS:TD-BS',\n",
    "'SARES31-GPS:TRX-BS',\n",
    "'SARES31-GPS:TRXBASE-BS',\n",
    "'SARES31-GPS:TRY-BS',\n",
    "'SARES31-GPS:TRYBASE-Avg-BS',\n",
    "'SARES31-GPS:TRYBASE-BS',\n",
    "'SARES31-GPS:TRZ-BS',\n",
    "          ]\n",
    "dm1_axis_names = ['SARES31-GPS:ROT2THETA',\n",
    "'SARES31-GPS:ROTTHETA',\n",
    "'SARES31-GPS:ROTX',\n",
    "'SARES31-GPS:ROTZ',\n",
    "'SARES31-GPS:TD',\n",
    "'SARES31-GPS:TRX',\n",
    "'SARES31-GPS:TRXBASE',\n",
    "'SARES31-GPS:TRY',\n",
    "'SARES31-GPS:TRYBASE-Avg',\n",
    "'SARES31-GPS:TRYBASE',\n",
    "'SARES31-GPS:TRZ',\n",
    "          ]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "62731901-0b18-41a7-84ae-c4ada693ce48",
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_pid_adjustables(axis):\n",
    "    adj_p = PVAdjustable(axis.ID+'-Ctrl-Kp')\n",
    "    adj_i = PVAdjustable(axis.ID+'-Ctrl-Ki')\n",
    "    adj_d = PVAdjustable(axis.ID+'-Ctrl-Kd')\n",
    "    return [adj_p,adj_i,adj_d]\n",
    "\n",
    "def get_pids(axis):\n",
    "    pid_adjs = get_pid_adjustables(axis)\n",
    "    vals = []\n",
    "    for pid_adj in pid_adjs:\n",
    "        vals.append(pid_adj.get())\n",
    "    return vals\n",
    "\n",
    "def set_pids(axis,pid_list,check_if_done=True):\n",
    "    pid_adjs = get_pid_adjustables(axis)\n",
    "    for i,pid_val in enumerate(pid_list):\n",
    "        pid_adjs[i].set(pid_val)\n",
    "    if check_if_done:\n",
    "        while pid_list != get_pids(axis):\n",
    "            sleep(0.1)\n",
    "\n",
    "def set_axis_enable_status(axis_list_or_name,enable_value):\n",
    "    \n",
    "    if type(axis_list_or_name) == str:\n",
    "        PVAdjustable(axis_list_or_name+'-EnaCmd').set_target_value(enable_value)\n",
    "    if type(axis_list_or_name) == list:\n",
    "        for axis in axis_list_or_name:\n",
    "            PVAdjustable(axis+'-EnaCmd').set_target_value(enable_value)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "5773b239-c854-4b57-8a52-b0f1a003ca26",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "ca9d6764-c7ff-43e0-a727-bf0996540b94",
   "metadata": {},
   "outputs": [],
   "source": [
    "def record_channels(channel_list, second_interval = 1, dispatcher_url = 'http://localhost:8080'): \n",
    "    data = defaultdict()\n",
    "    with source(channels=channel_list, dispatcher_url=dispatcher_url, mode=PULL) as stream:\n",
    "        for channel in channel_list:\n",
    "                data[channel] = []\n",
    "        for i in tqdm(range(int(second_interval*100))):\n",
    "            message = stream.receive()\n",
    "            for channel in channel_list:\n",
    "                data[channel].append(message.data.data[channel].value)\n",
    "    return data\n",
    "\n",
    "def plot_all_channels(d,remove_from_titles = 'SARES31-GPS:'):\n",
    "    n_channels = len(d.keys())\n",
    "    fig_dim = int(np.sqrt(n_channels))\n",
    "    \n",
    "    fig,ax = plt.subplots( fig_dim, fig_dim+1, figsize = (4*fig_dim,4*fig_dim),constrained_layout=True )\n",
    "    ax =ax.flatten()\n",
    "    for i,channel in enumerate(d.keys()):\n",
    "        ax[i].plot(d[channel],label=channel)\n",
    "        if remove_from_titles:\n",
    "            title = str(channel).replace(remove_from_titles,\"\")\n",
    "        else:\n",
    "            title = str(channel)\n",
    "        ax[i].set_title(title)\n",
    "    # plt.legend()\n",
    "    # plt.tight_layout()\n",
    "\n",
    "def plot_channel(d,channel,remove_from_titles = 'SARES31-GPS:'):\n",
    "    fig,ax = plt.subplots( 1,1, figsize = (6,6),constrained_layout=True )\n",
    "    ax.plot(d[channel],label=channel)\n",
    "    if remove_from_titles:\n",
    "        title = str(channel).replace(remove_from_titles,\"\")\n",
    "    else:\n",
    "        title = str(channel)\n",
    "    ax.set_title(title)\n",
    "    # plt.legend()\n",
    "    # plt.tight_layout()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "a17c3527-45b0-4266-8296-ad757013ff4a",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "set_axis_enable_status(dm1_axis_names,False)\n",
    "\n",
    "#set_axis_enable_status(dm1.tr_x.ID,True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "dda1012f-7c0e-4ec2-84da-efdc57e57f3d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Task: running"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dm1.twotheta.deadband_ecmc.set_target_value(1e-6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "1ff845ae-b730-4b4b-86ce-2e26c463d310",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Task: running"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dm1.theta.set_target_value(0.01)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "86b087c5-9d64-40ea-a350-c27f6ec5b859",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Task: running"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dm1.td.deadband_ecmc.set_target_value(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "854e9b48-dc57-486c-9165-2046ef6643e8",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b4724811f2e04a49b526da0170e50be3",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/2000 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n",
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n",
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n",
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n",
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n",
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n",
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n",
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n",
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n",
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n",
      "[WARNING] bsread.data.helpers - 'type' channel field not found. Parse as 64-bit floating-point number float64 (default).\n"
     ]
    }
   ],
   "source": [
    "# dm1.twotheta.set_target_value(0)\n",
    "d = record_channels(dm1_chs,second_interval=20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "2bb599b7-04f6-4309-a526-62ff6bd30b26",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 185840 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 120\u001b[0m\u001b[1;36m0x1200\u001b[0m\u001b[39m with \u001b[0m\u001b[1;36m12\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_all_channels(d,remove_from_titles='SARES31-GPS:')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "6ee6da90-186d-4149-8e00-c7df21569cc5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 209964 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 120\u001b[0m\u001b[1;36m0x1200\u001b[0m\u001b[39m with \u001b[0m\u001b[1;36m12\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_all_channels(d,remove_from_titles='SARES31-GPS:')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "11698bd6-f8a2-40b2-911a-a23891e49d96",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 191756 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 120\u001b[0m\u001b[1;36m0x1200\u001b[0m\u001b[39m with \u001b[0m\u001b[1;36m12\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_all_channels(d,remove_from_titles='SARES31-GPS:')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "545b47d9-8ab5-4daf-b274-2509522012a8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 203120 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 120\u001b[0m\u001b[1;36m0x1200\u001b[0m\u001b[39m with \u001b[0m\u001b[1;36m12\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_all_channels(d,remove_from_titles='SARES31-GPS:')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 249,
   "id": "70020083-763b-4727-b3c1-2b394f55ddcc",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/sf/cristallina/applications/conda/envs/slic/lib/python3.9/site-packages/traitlets/traitlets.py:1385: DeprecationWarning: Passing unrecognized arguments to super(Toolbar).__init__().\n",
      "__init__() missing 1 required positional argument: 'canvas'\n",
      "This is deprecated in traitlets 4.2.This error will be raised in a future release of traitlets.\n",
      "  warn(\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "ac75dafac6e6472582598f554927133f",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 223668 characters]",
      "text/html": [
       "\n",
       "            <div style=\"display: inline-block;\">\n",
       "                <div class=\"jupyter-widgets widget-label\" style=\"text-align: center;\">\n",
       "                    Figure\n",
       "                </div>\n",
       "                <img src='data:image/png;base64,[encoded data, 223668 characters]' width=1200.0/>\n",
       "            </div>\n",
       "        "
      ],
      "text/plain": [
       "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_all_channels(d,remove_from_titles='SARES31-GPS:')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 256,
   "id": "ecd2fa4b-7481-4cb3-bfde-ab7ccf4b463e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "0f0a01d826134c888328a9a74ddd6279",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 217164 characters]",
      "text/html": [
       "\n",
       "            <div style=\"display: inline-block;\">\n",
       "                <div class=\"jupyter-widgets widget-label\" style=\"text-align: center;\">\n",
       "                    Figure\n",
       "                </div>\n",
       "                <img src='data:image/png;base64,[encoded data, 217164 characters]' width=1200.0/>\n",
       "            </div>\n",
       "        "
      ],
      "text/plain": [
       "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_all_channels(d,remove_from_titles='SARES31-GPS:')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f14be8e7-f7f4-45f0-90cf-b7bee2850964",
   "metadata": {},
   "source": [
    "# Notes\n",
    "## TRXYZ sample stages\n",
    "There is about ~0.25um random offset error of the position, which is constintent with a deadband of about 0.5um. The system generally overshoots in the direction of travel by this amount.\n",
    "### TRX\n",
    "P=10 is about maximum that does not oscillate, adding I does not seem to improve the final approach to the right value, already 0.1 destabilises the system (0.01 is the max tolerable, but one does not gain much with it)\n",
    "### TRY\n",
    "P=10 works quite well, no need for other terms\n",
    "### TRZ\n",
    "P=10 is a bit much as it overshoots by a few um. Adding D does not seem to help. P=7 seems to be about the best overshoot/undersoot tradeoff.\n",
    "\n",
    "## Thetas\n",
    "### ROTTHETA\n",
    "P=10 works. Values above P=20 start to shake the other axes when starting and stopping the motion. Thus, P=10 seems reasonable. The deadband in EPICS is 1mdeg. In ECMC it seems to be about 1mdeg (or a little less) as well. I does not seem to do much. For P=10, the shaking does not come from start/stop, so adding D does not help. \n",
    "\n",
    "### ROTTWOTHETA\n",
    "Same as above.  P=20 disturbs theta encoder. Adding D does make it slower, but maybe a bit less stable\n",
    "\n",
    "## Other\n",
    "### TRXBASE\n",
    "Large movements shake the top axes a bit already, so it just shouldn't shame more on the start-stop of the motion. P=10 works.\n",
    "\n",
    "### TRYBASE\n",
    "Currently P=10 with small I=0.001. The motor is very slow, so this can also be set very conservatively. It's quite important to keep these four motors disabled, because they can fight with other stages above and cause oscillations.\n",
    "\n",
    "### TD\n",
    "P=10 is fine. This motor is already extremely slow, so as long as it's stable it's fine.\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "a1297202-4610-4f64-86dc-f679ae127af5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Notes after decreasing "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4075f7d2-3ab6-44d5-8dd1-6761cf7a2ecf",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:conda-slic]",
   "language": "python",
   "name": "conda-env-conda-slic-py"
  },
  "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.9.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
