{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Lateral Force Processing Demo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook demonstrates how to open a Nanosurf image file (*.nid) containing lateral force data and perform basic post-processing operations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import required modules\n",
    "from NSFopen.read import read\n",
    "\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib import cm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reading Header\n",
      "Reading Data\n",
      "Elapsed Time: 0.02 sec\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# import the data\n",
    "data_file = \"SBS-PMMA.nid\"\n",
    "afm = read(data_file)\n",
    "data = afm.data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# load the data from the lateral channel\n",
    "frict0 = data['Image']['Forward']['Friction force']\n",
    "frict1 = data['Image']['Backward']['Friction force']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We need to calculate both the sum and difference between the forward and backward channels.  Frictional forces will appear as contrast in the difference between the two channels.  Because of the length of the AFM tip, there will be an offset between the forward and backward channels, which we will have to subtract."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "offset = 5 # pixels\n",
    "\n",
    "sum = (frict1[:, :-offset] + frict0[:, offset:])/2\n",
    "diff = (frict1[:, :-offset] - frict0[:, offset:])/2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# X and Y data is stored in the parameters\n",
    "param = afm.param\n",
    "Xmin = param.X['min'][0] * 1e6  # the minimum of X of channel 0 scaled to um\n",
    "Xmax = param.X['range'][0] * 1e6  # the range of X of channel 0 scaled to um\n",
    "\n",
    "Ymin = param.Y['min'][0] * 1e6  # the minimum of Y for channel 0 scaled to um\n",
    "Ymax = param.Y['range'][0] * 1e6  # the range of Y for channel 0 scaled to um\n",
    "\n",
    "# calculate the new X-range with the offset removed\n",
    "pixel_size = Xmax/np.shape(frict0)[0]\n",
    "Xmax -= pixel_size * offset\n",
    "\n",
    "extents = [Xmin, Xmax, Ymin, Ymax]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 437664 characters]\n",
      "text/plain": [
       "<Figure size 1440x720 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(1,2, figsize=(20,10))\n",
    "ax[0].imshow(sum, extent=extents)\n",
    "ax[0].set_title('Sum')\n",
    "ax[1].imshow(diff, extent=extents)\n",
    "ax[1].set_title('Difference')\n",
    "\n",
    "[ax[i].set_xlabel('[$\\mu$m]') for i in range(2)];\n",
    "[ax[i].set_ylabel('[$\\mu$m]') for i in range(2)];\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.8.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
