{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b780b7af-aee0-4d92-b830-64e9b9d3c2f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib ipympl\n",
    "import numpy as np\n",
    "from numba import jit, vectorize, float64, types, int64\n",
    "import matplotlib.pyplot as plt\n",
    "from tqdm.notebook import trange, tqdm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6fbf192f-aebc-4bce-ae38-339b5610fad1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Coupling formula\n",
    "alpha = 1\n",
    "\n",
    "# Lattive parameters:\n",
    "lattice_x = np.array([1, 0, 0])\n",
    "lattice_y = np.array([0, 1, 0])\n",
    "lattice_z = np.array([0, 0, 1])\n",
    "\n",
    "lattice_s = np.array([\n",
    "    [0,0,0],\n",
    "    [0.2,0,0]\n",
    "])\n",
    "\n",
    "site_nb = lattice_s.shape[0]\n",
    "\n",
    "\n",
    "@vectorize([float64(int64, int64, int64, int64, int64)])\n",
    "def compute_coupling(x, y, z, a, b):\n",
    "    vec = x*lattice_x + y*lattice_y + z*lattice_z + lattice_s[a] - lattice_s[b]\n",
    "    norm = np.linalg.norm(vec)\n",
    "    return alpha/norm**3*np.abs(3*vec[2]**2/norm**2 - 1)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8719ddbb-3348-48d2-b949-3221ca298b09",
   "metadata": {},
   "source": [
    "# State generation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "062e190f-1561-4f9f-8ffc-aca8e43db8f4",
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate_lattice_sites(n, cell_number = 5):\n",
    "    # TODO: Improve using random picking\n",
    "    r = np.unique(np.random.randint([[cell_number, cell_number, cell_number, len(lattice_s)]], size=(n, 4)), axis = 0)\n",
    "    np.random.shuffle(r)\n",
    "    return r\n",
    "\n",
    "def add_noise(couplings, sigma):\n",
    "    return np.max(0, couplings + np.random.normal(scale = sigma, size = couplings.shape))\n",
    "\n",
    "@jit\n",
    "def couplings(sites):\n",
    "    n = sites.shape[0]\n",
    "    couplings = np.full((n , n), np.nan)\n",
    "    for i in range(sites.shape[0]-1):\n",
    "        for j in range(i+1, sites.shape[0]):\n",
    "            x = sites[i][0] - sites[j][0]\n",
    "            y = sites[i][1] - sites[j][1]\n",
    "            z = sites[i][2] - sites[j][2]\n",
    "            couplings[i, j] = compute_coupling(x, y, z, sites[i][3], sites[j][3])\n",
    "    return couplings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "3d1d36c3-1fc4-42e4-af71-8eda4fb34d86",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_sites = generate_lattice_sites(25, cell_number=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "ae4ecda6-14db-4e50-bfd2-affcd6153630",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_couplings = couplings(test_sites)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "35313d97-d4d6-4435-b648-bb4e30c306fe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4ff187e4309849bab70fe6a501f6ba52",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 77816 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, 77816 characters]' width=640.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": [
    "fig = plt.figure()\n",
    "ax = fig.add_subplot(projection='3d')\n",
    "\n",
    "positions = lattice_x[None,:]*test_sites[:,0][:,None] + lattice_y[None,:] * test_sites[:,1][:,None] + lattice_z[None,:] * test_sites[:,2][:,None] + lattice_s[test_sites[:,3]]\n",
    "\n",
    "ax.scatter(positions[:,0], positions[:,1], positions[:,2])\n",
    "\n",
    "ax.set_xlabel('X Label')\n",
    "ax.set_ylabel('Y Label')\n",
    "ax.set_zlabel('Z Label')\n",
    "\n",
    "for i in range(test_sites.shape[0]):\n",
    "    ax.text(positions[i,0], positions[i,1], positions[i,2], str(i))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "311c7c64-84ed-45c2-9f49-5993c67bc21e",
   "metadata": {},
   "source": [
    "# State reconstruction"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "daaa4792-069c-44fd-bdbd-90af6f51858f",
   "metadata": {},
   "outputs": [],
   "source": [
    "tolerance = 1\n",
    "\n",
    "@jit\n",
    "def index_to_coord(index, max_distance, site_nb):\n",
    "    center = max_distance // 2\n",
    "    return (\n",
    "        index // (max_distance**2 * site_nb**2) - center,\n",
    "        index // (max_distance * site_nb**2) % max_distance - center,\n",
    "        index // site_nb**2 % max_distance - center,\n",
    "        index // site_nb % site_nb,\n",
    "        index % site_nb\n",
    "    )  \n",
    "\n",
    "@jit\n",
    "def coord_to_index(vec, max_distance, site_nb):\n",
    "    center = max_distance // 2\n",
    "    return site_nb**2 * ((vec[0] + center)*max_distance**2 + (vec[1] + center) * max_distance + (vec[2] + center)) + vec[3]*site_nb + vec[4]\n",
    "\n",
    "#@jit #(locals={'current_set': types.Set(types.UniTuple(float64, 3))})\n",
    "def vector_couplings(max_distance, site_nb, tolerance):\n",
    "    print(\"Computing vector -> couplings lookup\")\n",
    "    couplings = np.empty(max_distance**3*site_nb**2)\n",
    "    for i in range(max_distance**3*site_nb**2):\n",
    "        couplings[i] = compute_coupling(\n",
    "                    *index_to_coord(i, max_distance, site_nb)\n",
    "                )\n",
    "    # Revert the map\n",
    "    print(\"Reverting the map\")\n",
    "    coupling_values = [] # OK to append to that list because O(number_spins)\n",
    "    current_set = set(((0,0,0,0),))\n",
    "    current_set.remove((0,0,0,0)) # HACK for type inference\n",
    "    vectors = [current_set.copy()] # OK to append because O(number_spins)\n",
    "    sorted_couplings = np.argsort(couplings)\n",
    "    # i_max = coupling index st coupling + tolerance < cureent cursor\n",
    "    # i_min = coupling index st coupling - tolerance < cureent cursor\n",
    "    i_min, i_max = 0,0\n",
    "    while not np.isnan(couplings[sorted_couplings[i_max]]):\n",
    "        if np.isnan(couplings[sorted_couplings[i_min]]) or couplings[sorted_couplings[i_min]] - tolerance > couplings[sorted_couplings[i_max]] + tolerance:\n",
    "            # Depile du côté des maxima (ie on retire un vecteur au set)\n",
    "            vec = index_to_coord(sorted_couplings[i_max], max_distance, site_nb)\n",
    "            current_set.remove(vec) # We want unmutable type here\n",
    "            coupling_values.append(couplings[sorted_couplings[i_max]] + tolerance)\n",
    "            i_max += 1\n",
    "        else:\n",
    "            # Depile du côté des minima (ie on ajoute un vecteur au set)\n",
    "            vec = index_to_coord(sorted_couplings[i_min], max_distance, site_nb)\n",
    "            current_set.add(vec) # We want unmutable type here\n",
    "            coupling_values.append(couplings[sorted_couplings[i_min]] - tolerance)\n",
    "            i_min += 1\n",
    "        vectors.append(current_set.copy())\n",
    "    return np.array(coupling_values), vectors\n",
    "#vector_couplings(tolerance = 0.01, max_distance = lattice_size*2, site_nb = site_nb)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "4a78bf20-e87b-4aeb-99f0-2bccc9dc4233",
   "metadata": {},
   "outputs": [],
   "source": [
    "@jit\n",
    "def cost_function(sites, couplings):\n",
    "    couplings_theory = couplings(sites)\n",
    "    cost = 0\n",
    "    for i in range(sites.shape[0]-1):\n",
    "        for j in range(i+1, sites.shape[0]):\n",
    "            if np.isnan(couplings[i,j]):\n",
    "                continue\n",
    "            x = sites[i][0] - sites[j][0]\n",
    "            y = sites[i][1] - sites[j][1]\n",
    "            z = sites[i][2] - sites[j][2]\n",
    "            cost += (couplings[i,j] - compute_coupling(x, y, z, sites[i][3], sites[j][3]))**2\n",
    "    return cost\n",
    "\n",
    "#def get_placing_order(couplings):\n",
    "    \n",
    "\n",
    "def compute_sites(couplings, lattice_size = 5, tolerance = 0.01):\n",
    "    print(\"Begin\")\n",
    "    n_placed = 1\n",
    "    n_tot = couplings.shape[0]\n",
    "    couplings_vectors_tup = vector_couplings(tolerance = tolerance, max_distance = lattice_size*2, site_nb = site_nb) # TODO better names\n",
    "    possible_configurations = []\n",
    "    for i in range(site_nb):\n",
    "        c = np.zeros((n_tot, 4), dtype = np.int64)\n",
    "        c[0][3] = i\n",
    "        possible_configurations.append(c)\n",
    "        \n",
    "    current_couplings = np.empty(n_tot) # stores current coupling values to other spins\n",
    "\n",
    "    print(\"Initialization successful\")\n",
    "    while n_placed < n_tot:\n",
    "        print(f\"Placing {n_placed}\")\n",
    "        # First place them in order\n",
    "        n_to_place = n_placed\n",
    "\n",
    "        for i in range(n_tot):\n",
    "            current_couplings[i] = np.nanmax([couplings[n_to_place, i], couplings[i, n_to_place]])\n",
    "        # Be careful, position relative to n_to_place-1\n",
    "        candidates = couplings_vectors_tup[1][np.searchsorted(couplings_vectors_tup[0], current_couplings[n_to_place-1])]\n",
    "        new_possible_configurations = []\n",
    "        for config in tqdm(possible_configurations):\n",
    "            for candidate in candidates:\n",
    "                good_candidate = True\n",
    "                # First check the origin lattice site\n",
    "                if candidate[4] != config[n_to_place - 1][3]:\n",
    "                    continue\n",
    "                for i in range(n_placed-1):\n",
    "                    if np.isnan(current_couplings[i]):\n",
    "                        # no data for this already placed spin\n",
    "                        continue\n",
    "                    coupling_candidate = compute_coupling(\n",
    "                        x := candidate[0] + config[n_to_place-1][0] - config[i][0],\n",
    "                        y := candidate[1] + config[n_to_place-1][1] - config[i][1],\n",
    "                        z := candidate[2] + config[n_to_place-1][2] - config[i][2],\n",
    "                        candidate[3],\n",
    "                        config[i][3],\n",
    "                    )\n",
    "                    if np.isnan(coupling_candidate) or np.abs(current_couplings[i] - coupling_candidate) > tolerance:\n",
    "                        good_candidate = False\n",
    "                        break\n",
    "                if good_candidate:\n",
    "                    new_config = config.copy()\n",
    "                    new_config[n_to_place] = np.array((candidate[0] + config[n_to_place-1][0], candidate[1] + config[n_to_place-1][1], candidate[2] + config[n_to_place-1][2], candidate[3]))\n",
    "                    new_possible_configurations.append(new_config)\n",
    "        possible_configurations = new_possible_configurations\n",
    "        n_placed+=1\n",
    "    return possible_configurations\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "880aae08-77bb-4964-aa86-bff1da5a2815",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Begin\n",
      "Computing vector -> couplings lookup\n",
      "Reverting the map\n",
      "Initialization successful\n",
      "Placing 1\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_775710/552860360.py:38: RuntimeWarning: All-NaN axis encountered\n",
      "  current_couplings[i] = np.nanmax([couplings[n_to_place, i], couplings[i, n_to_place]])\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "2fb9d12c60324138a84ec9b8397847bb",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/2 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Placing 2\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "5c510ea65ad14c49900f1b0ec0ac7dda",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/2647 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "final_configs = compute_sites(test_couplings, tolerance = 0.005)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "fd1e7f80-1628-4750-bb71-1ebebb69f83e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(final_configs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cd6d7404-d14f-4d7f-81f4-396b15ad04b9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "f4eace44-2364-4be4-acc6-4da8b82ae5a2",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_35830/4115954874.py:2: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.\n",
      "  fig = plt.figure()\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "796660ed44d14de48e3519edf01653b8",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 80820 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, 80820 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "58069fd0298143c9891d6281f541d429",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 79060 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, 79060 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "72c9ce6a8b0b470db535b0c520e17edd",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 76616 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, 76616 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "8755b342165f42bd9f9ae67f3aa396f4",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 80476 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, 80476 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6ce6bc79a740403ea9c4576f024caa71",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 76536 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, 76536 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "5fee28dcad6544568934f1bfd0998b91",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 79036 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, 79036 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "87cc137c9717409b99e6d0b0b9c42f7a",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 80720 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, 80720 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "3ddaa74a94794f1d8e00b98fc1aeae24",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 80440 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, 80440 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a095dde3bae24458ab35ff6056d04d23",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 79052 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, 79052 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4ad682887ade4a2186e7a67bb59a1b6e",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 81144 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, 81144 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "9e68c383951043998f572ad805f0255e",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 82084 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, 82084 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "8f5c753a427b41f685ed168b92ba002c",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 81132 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, 81132 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6c5c285777c4496282253bee1d0c878e",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 79192 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, 79192 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6c8e020aa5bd405c8fac4e34f195a859",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 82344 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, 82344 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "99db0949af0846eda41837c0260695d5",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 82008 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, 82008 characters]' width=640.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"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "bd70c7490b6d46a485181eee331aee90",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 82184 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, 82184 characters]' width=640.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": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "efebe894-f645-4516-8727-2cf81c18d518",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "902da0a3-5db3-4ca1-ac9c-f57edcb7eb94",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ec667531-91d7-451f-8f64-c48f5799f081",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.12.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
