{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Making a prediction\n",
    "\n",
    "## Introduction\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook offers an interactive tutorial on using PreFab to **predict** the fabrication result of a 500 nm-wide target nanostructure on a silicon-on-insulator (SOI) e-beam lithography process. This tutorial is structured as follows:\n",
    "\n",
    "1. Preparing a device image for prediction\n",
    "2. Executing a prediction\n",
    "3. Analyzing the prediction and uncertainty\n",
    "\n",
    "To begin, we need to import the necessary libraries:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import prefab as pf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Loading a device\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The first step involves preparing a device for prediction. `Device` is the base class that represents photonic design geometries in PreFab and can be instantiated by loading an image or GDS layout as an ndarray with binary pixel values: 0 or 1. In this tutorial, we'll use a small target structure, but feel free to explore other structures available in the `shapes.py` module, or add your own.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Axes: xlabel='x (nm)', ylabel='y (nm)'>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 16332 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "device = pf.shapes.target(width=500, arm_width=60)\n",
    "device.plot(show_buffer=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Predicting a device\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We proceed with the prediction of the device for a specific fabrication model. Each model is labeled by its fabrication facility and process name, model version, and dataset version. Refer to `docs/models.md` for a library of available models.\n",
    "\n",
    "You can also select if you want a binarized output. The prediction model, by default, produces raw outputs, which includes \"fuzzy\" edges of the structure that may vary between different fabrication runs or even different device instances on the same chip. When binarized, the prediction model outputs the most probable fabrication outcome (i.e., a threshold of 50%). Post-prediction binarization is also an option, as we'll show here.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> **Note:** Initial prediction/correction may take longer due to server startup and model loading. Subsequent predictions should be quicker.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Prediction: 100%|\u001b[32m██████████████████████████████\u001b[0m| 100/100 [00:02<00:00, 43.12%/s]\u001b[32m\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<Axes: xlabel='x (nm)', ylabel='y (nm)'>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 41308 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 22088 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "MODEL_NAME = \"ANT_NanoSOI_ANF1_d10\"\n",
    "prediction = device.predict(model=pf.models[MODEL_NAME])\n",
    "prediction_bin = prediction.binarize()\n",
    "\n",
    "prediction.plot(show_buffer=False)\n",
    "prediction_bin.plot(show_buffer=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Analyzing a prediction\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Comparing the (binary) prediction with the nominal device, we can observe erosion (or corner rounding, or over-etching) in the 60 nm-wide arms and convex corners of the target geometry. We also see dilation (or under-etching) for the concave corners in the center, as well as the complete filling of the center opening.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Axes: xlabel='x (nm)', ylabel='y (nm)'>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 32896 characters]",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "prediction_bin.plot_compare(ref_device=device, show_buffer=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To evaluate the quality of the prediction quantitatively, PreFab provides a function to compute the Intersection over Union (IoU) between the prediction and the nominal device. This metric measures the overlap between the two geometries, where 1.0 indicates a perfect match and 0.0 indicates no overlap.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Prediction IoU: 0.83\n"
     ]
    }
   ],
   "source": [
    "print(\n",
    "    f\"Prediction IoU: {pf.compare.intersection_over_union(device, prediction_bin):.2f}\"\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "83% is not great, but the feature size was demanding. Try other values for `arm_width` and see how it affects the results.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can further visualize and understand the prediction by highlighting the \"fuzzy\" edge regions. This is a measure of the uncertainty of the prediction model due to stochastic variance in the fabrication process and the modelling process. From device-to-device, run-to-run, the device edge may lie anywhere in this uncertainty region. Although PreFab cannot correct for uncertainty, visualizing it is valuable in identifying features with high variance.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Axes: xlabel='x (nm)', ylabel='y (nm)'>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 57640 characters]",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "prediction.plot_uncertainty(show_buffer=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And that's it! See the next example to learn how to restore this nanostructure using PreFab's correction capabilities.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "prefab-metal",
   "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.10.12"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
