From 6bb78f2f4bca46860fcc632da81a6facc56ea513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ser=C3=B3dio?= Date: Sun, 12 May 2024 20:48:56 -0300 Subject: [PATCH] extend Tutorial 6 with Model Inference example --- examples/tutorials/Tutorial_6.ipynb | 383 +++++++++++++++++++++++++++- 1 file changed, 371 insertions(+), 12 deletions(-) diff --git a/examples/tutorials/Tutorial_6.ipynb b/examples/tutorials/Tutorial_6.ipynb index 31f75fc..53ccc3a 100644 --- a/examples/tutorials/Tutorial_6.ipynb +++ b/examples/tutorials/Tutorial_6.ipynb @@ -49,7 +49,7 @@ "(50, 50, 50)\n", "(50, 50, 50)\n", "(50, 50, 50)\n", - "Now the output shape is (99, 99, 99), because we added a overlap/padding that makes it possible to extarct patches that cover the whole data. 8 patches extracted\n", + "Now the output shape is (99, 99, 99), because we added an overlap/padding that makes it possible to extract patches that cover the whole data. 8 patches extracted\n", "(50, 50, 50)\n", "(50, 50, 50)\n", "(50, 50, 50)\n", @@ -66,7 +66,7 @@ "(50, 50, 50)\n", "(50, 50, 50)\n", "(50, 50, 50)\n", - "The output shape is (99, 99, 99) is the samebut we compute 8 patches from the base set and 8 from an overlapping set (patch extraction starts at (0, -1, -1), instead of (0, 0, 0))\n" + "The output shape is (99, 99, 99) is the same, but we compute 8 patches from the base set and 8 from an overlapping set (patch extraction starts at (0, -1, -1), instead of (0, 0, 0))\n" ] } ], @@ -131,7 +131,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 2, "id": "789c4521", "metadata": {}, "outputs": [], @@ -143,7 +143,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 3, "id": "1e0a444e", "metadata": {}, "outputs": [], @@ -156,18 +156,27 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 4, "id": "c68ca230-d319-4c35-8e4a-0fb3d017c0cd", "metadata": {}, "outputs": [], "source": [ - "def plot_panel(base_name, data_dict, outer):\n", + "def plot_panel(base_name, data_dict, outer, same_scale=False, transpose=False, cmap=\"bone\"):\n", " f, axarr = plt.subplots(1,len(data_dict), sharex = True,sharey=True)\n", + " mi = 1\n", + " ma = 1\n", + " for v in data_dict.values():\n", + " mi = min(mi, np.min(v))\n", + " ma = max(ma, np.max(v))\n", " f.set_size_inches(15,5)\n", " for i, data in enumerate(data_dict.items()):\n", " ax = axarr[i] if len(data_dict) != 1 else axarr\n", " panel = data[1][outer,:,:]\n", - " subfig = ax.imshow(panel, cmap=\"bone\", interpolation='nearest')\n", + " panel = panel.T if transpose else panel\n", + " if same_scale:\n", + " subfig = ax.imshow(panel, cmap=cmap, vmin=mi, vmax=ma, interpolation='nearest')\n", + " else:\n", + " subfig = ax.imshow(panel, cmap=cmap, interpolation='nearest')\n", " ax.title.set_text(f\"{base_name} - {data[0]}\")\n", " f.colorbar(subfig, ax=ax)\n", " f.show()\n", @@ -185,7 +194,7 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 5, "id": "ccf54994", "metadata": {}, "outputs": [ @@ -206,7 +215,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 6, "id": "ac097671", "metadata": {}, "outputs": [ @@ -227,7 +236,7 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 7, "id": "b529d5d7", "metadata": {}, "outputs": [ @@ -248,7 +257,7 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 8, "id": "e0aac4ed", "metadata": {}, "outputs": [ @@ -267,10 +276,360 @@ "plot_lines(\"Weights 25, 25\", weights, 25, 25)" ] }, + { + "cell_type": "markdown", + "id": "0d9efb8e", + "metadata": {}, + "source": [ + "#### Model Inference" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "a6c342e1", + "metadata": {}, + "outputs": [], + "source": [ + "import dask.array as da\n", + "import torch\n", + "import time\n", + "import numpy as np\n", + "try:\n", + " import cupy as cp\n", + "except:\n", + " pass\n", + "\n", + "from dasf.transforms.operations import ApplyPatchesVoting\n", + "from dasf.transforms import Transform\n", + "from dasf.datasets import DatasetZarr\n", + "from dasf.pipeline import Pipeline\n", + "from dasf.ml.inference.loader.torch import TorchLoader\n", + "from dasf.pipeline.executors import DaskPipelineExecutor\n", + "from dasf.utils.funcs import get_dask_running_client\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "b87e5a19", + "metadata": {}, + "outputs": [], + "source": [ + "# Execution Params\n", + "data_path = \"\"\n", + "model = \"\"\n", + "model_definition_file = \"\"\n", + "checkpoint = None\n", + "device = \"gpu\"\n", + "\n", + "# Global Min and Max must be obtained from input data\n", + "data = da.from_zarr(data_path)\n", + "glbl_mi = da.min(data).compute()\n", + "globl_ma = da.max(data).compute()\n", + "voting = \"soft\" # hard or soft\n", + "output_1 = \"\"\n", + "output_2 = \"\"\n", + "chunks = {\n", + " 0: 3,\n", + " 1: 384,\n", + " 2: 384\n", + "}\n", + "\n", + "# Pipeline Executor\n", + "scheduler_ip = \"\" # To run this experiment create a Dask Cluster prior to executing this cell\n", + "port = \"\"\n", + "executor = DaskPipelineExecutor(local=False, use_gpu=device==\"gpu\", address=scheduler_ip, port=port)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c64b0d9", + "metadata": {}, + "outputs": [], + "source": [ + "client = get_dask_running_client()\n", + "client.upload_file(model_definition_file) # might be necessary to upload the model definition file to workers" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "9c4d2bf4", + "metadata": {}, + "outputs": [], + "source": [ + "OFFSETS = [\n", + " [],\n", + " [(0, -64, -64)],\n", + " [(0, -16, -16), (0, -32, -32), (0, -64, -64)],\n", + " [(0, -12, -12), (0, -24, -24), (0, -36, -36), (0, -48, -48), (0, -60, -60), (0, -72, -72),(0, -84, -84), (0, -96, -96), (0, -108, -108)],\n", + " [(0, 0, -12), (0, 0, -24), (0, 0, -36), (0, 0, -48), (0, 0, -60), (0, 0, -72),(0, 0, -84), (0, 0, -96), (0, 0, -108),\n", + " (0, -12, -12), (0, -12, -24), (0, -12, -36), (0, -12, -48), (0, -12, -60), (0, -12, -72),(0, -12, -84), (0, -12, -96), (0, -12, -108),\n", + " (0, -24, -12), (0, -24, -24), (0, -24, -36), (0, -24, -48), (0, -24, -60), (0, -24, -72),(0, -24, -84), (0, -24, -96), (0, -24, -108),\n", + " (0, -36, -12), (0, -36, -24), (0, -36, -36), (0, -36, -48), (0, -36, -60), (0, -36, -72),(0, -36, -84), (0, -36, -96), (0, -36, -108),\n", + " (0, -48, -12), (0, -48, -24), (0, -48, -36), (0, -48, -48), (0, -48, -60), (0, -48, -72),(0, -48, -84), (0, -48, -96), (0, -48, -108),\n", + " (0, -60, -12), (0, -60, -24), (0, -60, -36), (0, -60, -48), (0, -60, -60), (0, -60, -72),(0, -60, -84), (0, -60, -96), (0, -60, -108),\n", + " (0, -72, -12), (0, -72, -24), (0, -72, -36), (0, -72, -48), (0, -72, -60), (0, -72, -72),(0, -72, -84), (0, -72, -96), (0, -72, -108),\n", + " (0, -84, -12), (0, -84, -24), (0, -84, -36), (0, -84, -48), (0, -84, -60), (0, -84, -72),(0, -84, -84), (0, -84, -96), (0, -84, -108),\n", + " (0, -96, -12), (0, -96, -24), (0, -96, -36), (0, -96, -48), (0, -96, -60), (0, -96, -72),(0, -96, -84), (0, -96, -96), (0, -96, -108),\n", + " (0, -108, -12), (0, -108, -24), (0, -108, -36), (0, -108, -48), (0, -108, -60), (0, -108, -72),(0, -108, -84), (0, -108, -96), (0, -108, -108),\n", + " ]\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "012b4dcd", + "metadata": {}, + "outputs": [], + "source": [ + "class Data(Transform):\n", + " def transform(self, X):\n", + " return X._data\n", + " \n", + "class Finalize(Transform):\n", + " def _lazy_transform_cpu(self, X, **kwargs):\n", + " return X\n", + "\n", + " def _lazy_transform_gpu(self, X, **kwargs):\n", + " return X.map_blocks(cp.asnumpy)\n", + "\n", + " def _transform_cpu(self, X, **kwargs):\n", + " return X\n", + "\n", + " def _transform_gpu(self, X, **kwargs):\n", + " return cp.asarray(X)\n", + " \n", + "class SaveZarr(Transform):\n", + " def __init__(self, output):\n", + " self._output = output\n", + " def transform(self, X):\n", + " X = X.to_zarr(self._output)\n", + " return X\n", + " \n", + "class ModelLoader(TorchLoader):\n", + " def preprocessing(self, data):\n", + " data = (2*data - (glbl_mi+globl_ma))/(globl_ma - glbl_mi)\n", + " data = np.concatenate([data, np.zeros(data.shape), np.zeros(data.shape)] , axis=1)\n", + " return data\n", + " \n", + " def postprocessing(self, data):\n", + " data = np.transpose(data, (0, 2, 3, 1))\n", + " data = np.expand_dims(data, axis=1)\n", + " return data\n", + " \n", + " def inference(self, model, data):\n", + " data = torch.from_numpy(data)\n", + " device = torch.device(\"cuda\" if self.device == \"gpu\" else \"cpu\")\n", + " data = data.to(device, dtype=self.dtype)\n", + " with torch.no_grad():\n", + " output = torch.softmax(model(data), dim=1)\n", + " return output.cpu().numpy() if self.device == \"gpu\" else output.numpy()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f74a560c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Without Overlap\n", + "dataset = DatasetZarr(name=\"Input data\", root=data_path, download=False, chunks=chunks)\n", + "data = Data()\n", + "loader = ModelLoader(\n", + " model_class_or_file=model,\n", + " dtype=torch.float32,\n", + " checkpoint=checkpoint,\n", + " device=device\n", + ")\n", + "\n", + "apply_patches = ApplyPatchesVoting(loader,\n", + " weight_function=None,\n", + " input_size=(1, 128, 128), \n", + " overlap={\n", + " \"padding\": (0, 128, 128),\n", + " \"boundary\": 0,\n", + " },\n", + " offsets=OFFSETS[0],\n", + " voting=voting,\n", + " num_classes=21\n", + ")\n", + "finalize = Finalize()\n", + "\n", + "save = SaveZarr(output_1)\n", + "\n", + "\n", + "# Create the pipeline\n", + "pipeline = Pipeline(\"Model Inference...\", executor=executor)\n", + "pipeline.add(data, X=dataset)\n", + "pipeline.add(loader)\n", + "pipeline.add(apply_patches, X=data, model=loader)\n", + "pipeline.add(finalize, X=apply_patches)\n", + "pipeline.add(save, X=finalize)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "47104d4c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2024-05-12 20:21:22-0300] INFO - Beginning pipeline run for 'Model Inference...'\n", + "[2024-05-12 20:21:22-0300] INFO - Task 'DatasetZarr.load': Starting task run...\n", + "[2024-05-12 20:21:22-0300] INFO - Task 'DatasetZarr.load': Finished task run\n", + "[2024-05-12 20:21:22-0300] INFO - Task 'ModelLoader.load': Starting task run...\n", + "[2024-05-12 20:21:23-0300] INFO - Task 'ModelLoader.load': Finished task run\n", + "[2024-05-12 20:21:23-0300] INFO - Task 'Data.transform': Starting task run...\n", + "[2024-05-12 20:21:23-0300] INFO - Task 'Data.transform': Finished task run\n", + "[2024-05-12 20:21:23-0300] INFO - Task 'ApplyPatchesVoting.transform': Starting task run...\n", + "[2024-05-12 20:21:23-0300] INFO - Task 'ApplyPatchesVoting.transform': Finished task run\n", + "[2024-05-12 20:21:23-0300] INFO - Task 'Finalize.transform': Starting task run...\n", + "[2024-05-12 20:21:23-0300] INFO - Task 'Finalize.transform': Finished task run\n", + "[2024-05-12 20:21:23-0300] INFO - Task 'SaveZarr.transform': Starting task run...\n", + "[2024-05-12 20:21:31-0300] INFO - Task 'SaveZarr.transform': Finished task run\n", + "[2024-05-12 20:21:31-0300] INFO - Pipeline run successfully\n", + "Execution without overlap took 8.567719459533691 seconds\n" + ] + } + ], + "source": [ + "start = time.time()\n", + "pipeline.run()\n", + "end = time.time()\n", + "print(f\"Execution without overlap took {end-start} seconds\")" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "03355506", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# With Overlap\n", + "dataset = DatasetZarr(name=\"Input data\", root=data_path, download=False, chunks=chunks)\n", + "data = Data()\n", + "loader = ModelLoader(\n", + " model_class_or_file=model,\n", + " dtype=torch.float32,\n", + " checkpoint=checkpoint,\n", + " device=device\n", + ")\n", + "\n", + "apply_patches = ApplyPatchesVoting(loader,\n", + " weight_function=None,\n", + " input_size=(1, 128, 128), \n", + " overlap={\n", + " \"padding\": (0, 128, 128),\n", + " \"boundary\": 0,\n", + " },\n", + " offsets=OFFSETS[4],\n", + " voting=voting,\n", + " num_classes=21\n", + ")\n", + "finalize = Finalize()\n", + "\n", + "save = SaveZarr(output_2)\n", + "\n", + "\n", + "# Create the pipeline\n", + "pipeline = Pipeline(\"Model Inference...\", executor=executor)\n", + "pipeline.add(data, X=dataset)\n", + "pipeline.add(loader)\n", + "pipeline.add(apply_patches, X=data, model=loader)\n", + "pipeline.add(finalize, X=apply_patches)\n", + "pipeline.add(save, X=finalize)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "4357fc4f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Execution with overlap took 667.155853509903 seconds\n" + ] + } + ], + "source": [ + "start = time.time()\n", + "pipeline.run()\n", + "end = time.time()\n", + "print(f\"Execution with overlap took {end-start} seconds\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "d77cef97", + "metadata": {}, + "outputs": [], + "source": [ + "results = {\n", + " \"No Overlap\": da.from_zarr(output_1).compute(),\n", + " \"Overlap\": da.from_zarr(output_2).compute()\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "d65ff63b", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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v+ikk05Sy5Yt1bx5cx1xxBG67bbbtGPHDq83D0AjGC6HhDVr1kzTpk3TCSecEHX9okWL9PnnnysvL8+jLfPOa6+9pgMOOED33nuv15tirblz52rZsmXq3bt3Wh9nx44dGjhwoBYtWqRBgwZp2LBhysnJ0bx583T11Vfr2Wef1Ysvvqh99903rdsBuCWkvUfzHa3DGHc2BkDWIh/WRz5MXXV1tS688ELNmDFDJ554osaNG6fmzZvr73//u8aPH6+ZM2fq1VdfVXFxsdebCqSVGzlP8ibr0cmEhJ1++umaOXOm9uzZE3X9tGnT1Lt3b7Vr186jLfPO5s2b1bJlS9fWZ4zR999/79r6/K5Tp07ab7/9NH78+LQ/1ujRo7Vo0SI98MADmjNnjkaOHKkrrrhCzz//vB588EEtWrRI1113Xdq3o7Zse73hsiZN3LkAgAPkw/rIh6m76667NGPGDF133XV64403VF5erhEjRugvf/mLZs+erQ8//NCT6QW+++67jD8mspxbOc+DrEeRCQm74IIL9M033+iVV16JXLd7927NmjVLF154Ycz77NixQ9dee606duyovLw8HXLIIfrTn/4kU6eiumvXLl1zzTVq06aNWrRooTPOOEOff/55zHVu2LBBl1xyiYqLi5WXl6eePXvq8ccfd20/x40bp1AopDVr1mjYsGFq2bKlioqKNHz48MgPTHg418KFC/XBBx9E2sVff/11SVJNTY0mTpyonj17qlmzZiouLlZZWZm+/fbbqMfq0qWLBg0apPnz56tPnz7Kz89XRUWFJGnr1q0qLy+PPHfdu3fXnXfeqZqamsj9aw8rmzx5srp166a8vDwdffTRevvtt+vt20cffaTzzjtPbdq0UX5+vg455BDdfPPNGX1+a2vRooWuueYazZkzR++++26jy3/yySc699xz1apVKzVv3lzHHnusXnzxxUbv9/nnn+uxxx7Tz3/+c40aNare7SNHjtQpp5yiRx99NPK+O/zww3XKKafUW7ampkYHHHCAfv3rX0dd5/T1rmvLli267rrrdMQRR6igoECFhYUaMGCA/vWvf0UtF27pnz59um666Sa1a9dO++67r8444wytX7++0ecGAAAnyIfkQ7d8//33uvvuu3XwwQdrwoQJ9W4fPHiwhg4dqnnz5mnJkiWSpEGDBuknP/lJzPWVlJSoT58+Udc99dRT6t27t/Lz89WqVSudf/759fLSySefrMMPP1zLli3TSSedpObNm+umm26K+Ri7d+/Wrbfeqt69e6uoqEj77ruvTjzxRC1cuDBqudqvyb333qvOnTsrPz9f/fr10/vvv5/wcwTYgEOYSFiXLl1UUlKi//3f/9WAAQMkSS+//LIqKyt1/vnn6/77749a3hijM844QwsXLtSll16qo446SvPnz9f111+vDRs2RLUQX3bZZXrqqad04YUX6rjjjtNrr72mgQMH1tuGTZs26dhjj1UoFNKoUaPUpk0bvfzyy7r00ktVVVWl8vJy1/b3vPPOU9euXTVhwgS9++67evTRR9W2bVvdeeedatOmjf7yl7/o9ttv1/bt2yM/hIcddpgkqaysTFOnTtXw4cN11VVXae3atXrwwQe1fPly/eMf/9A+++wTeZxVq1bpggsuUFlZmS6//HIdcsgh+u6779SvXz9t2LBBZWVl6tSpk/75z39qzJgx+vLLLzVx4sSobZ02bZq2bdumsrIyhUIh3XXXXTr77LP1ySefRB7rvffe04knnqh99tlHI0aMUJcuXfTxxx9rzpw5uv322zP+/IZdffXVuvfeezVu3Di98MILcZfbtGmTjjvuOH333Xe66qqr1Lp1az3xxBM644wzNGvWLJ111llx7/vyyy+rurpaF198cdxlLr74Yi1cuFDz5s3TZZddpiFDhmjcuHHauHFj1FHYN998U1988YXOP//8yHVOX+9YPvnkE82ePVvnnnuuunbtqk2bNqmiokL9+vXThx9+qA4dOkQtf/vttysUCumGG27Q5s2bNXHiRJWWlmrFihXKz8+Pu9+wWJMmktM2amOkOt0HAJAM8iH50K3n980339S3336rq6++Wk3idF9cfPHFmjJliubOnatjjz1WQ4YM0cUXX6y3335bRx99dGS5Tz/9VEuWLNHdd98due7222/XLbfcovPOO0+XXXaZvvrqKz3wwAM66aSTtHz58qjus2+++UYDBgzQ+eefr9/85jdxh+dVVVXp0Ucf1QUXXKDLL79c27Zt02OPPab+/fvrrbfe0lFHHRW1/JNPPqlt27Zp5MiR2rlzp+677z79/Oc/18qVKxkCiGhu5DzJm6xngEZMmTLFSDJvv/22efDBB02LFi3Md999Z4wx5txzzzWnnHKKMcaYzp07m4EDB0buN3v2bCPJ/OEPf4ha369//WsTCoXMmjVrjDHGrFixwkgyV155ZdRyF154oZFkxo4dG7nu0ksvNe3btzdff/111LLnn3++KSoqimzX2rVrjSQzZcqUBvdt4cKFRpKZOXNm5LqxY8caSeaSSy6JWvass84yrVu3jrquX79+pmfPnlHX/f3vfzeSzNNPPx11/bx58+pd37lzZyPJzJs3L2rZ3//+92bfffc1//73v6Ouv/HGG01ubq757LPPovazdevWZsuWLZHlnn/+eSPJzJkzJ3LdSSedZFq0aGE+/fTTqHXW1NRE/j/R59cNtZ+78ePHG0lm2bJlUft19913R5YvLy83kszf//73yHXbtm0zXbt2NV26dDHV1dVxHyt83+XLl8dd5t133zWSzOjRo40xxqxatcpIMg888EDUcldeeaUpKCiIPBduvN7h24YOHRr5986dO+vt09q1a01eXp657bbbIteF38MHHHCAqaqqilw/Y8YMI8ncd999cfcZdqqsrDSSTGVBgTEtWji6VBYU7F1XZaXXuwXAMuTDvciH7uXDiRMnGknmueeei7vMli1bjCRz9tlnG2P2/ibm5eWZa6+9Nmq5u+66y4RCoch+rVu3zuTm5prbb789armVK1eaJk2aRF3fr18/I8k88sgj9R6/X79+pl+/fpF/79mzx+zatStqmW+//dYUFxdHvVfCr0l+fr75/PPPI9cvXbrUSDLXXHNN3H1GdnEz53mV9Rguh6Scd955+v777zV37lxt27ZNc+fOjdsK/dJLLyk3N1dXXXVV1PXXXnutjDF6+eWXI8tJqrdc3aMixhj99a9/1eDBg2WM0ddffx259O/fX5WVlQkNuUrUb3/726h/n3jiifrmm29UVVXV4P1mzpypoqIi/eIXv4jaxt69e6ugoKBe+2zXrl3Vv3//eus48cQTtd9++0Wto7S0VNXV1XrjjTeilh8yZIj222+/qG2V9nbDSNJXX32lN954Q5dccok6deoUdd/whHKZfn5ru/rqqxudm+mll17SMcccEzWxaEFBgUaMGKF169bpww8/jHvfbdu2Sdo7PC+e8G3h1/fggw/WUUcdpenTp0eWqa6u1qxZszR48OBId5Abr3cseXl5ysnJiTzuN998o4KCAh1yyCExX4eLL744av9+/etfq3379pHPFwAA6UI+JB+6IZW8Fp5OYMaMGVHDLadPn65jjz02sl/PPvusampqdN5550XtQ7t27XTQQQfVe/7z8vI0fPjwRrc5NzdXTZs2lbR3OOSWLVu0Z88e9enTJ+bzcuaZZ+qAAw6I/PuYY45R3759yWsIFIbLISlt2rRRaWmppk2bpu+++07V1dVRc9PU9umnn6pDhw71fijCLcOffvpp5L85OTnq1q1b1HJ1hxF99dVX2rp1qyZPnqzJkyfHfMzNmzentF+x1P2xDf9If/vttyosLIx7v9WrV6uyslJt27ZNaBu7du0acx3vvfee2rRpk9A6GtpW6ccwcfjhh8fdbqfP75YtW7R79+7Iv/Pz81VUVBR3+dqKiopUXl6usWPHavny5VGBKOzTTz9V3759611f+/0Ub//C78FweIklVrAZMmSIbrrpJm3YsEEHHHCAXn/9dW3evFlDhgyJLOPG6x1LTU2N7rvvPj388MNau3atqqurI7e1bt263vIHHXRQ1L9DoZC6d++udevWJfR4sJBbw+UAwCHyIfkwnmTyoZO8Nnv2bC1evFjHHXecPv74Yy1btixq+ODq1atljKmXl8JqD1WUpAMOOCBSPGrME088oT//+c/66KOP9MMPP0Suj/Uaxnr8gw8+WDNmzEjosZBF3Bwul2EUmZC0Cy+8UJdffrk2btyoAQMGuHr2jIaEJzT8zW9+o6FDh8Zc5sgjj3Tt8XJzc2Nebxr5oNbU1Kht27Z6+umnY95eNxjEmi+npqZGv/jFL/S73/0u5joOPvhgV7a17mNKqT+/Z599thYtWhT599ChQzV16tSEHz88N9P48ePrzSngVDi4vvfee/XGxoe99957kqQePXpErhsyZIjGjBmjmTNnqry8XDNmzFBRUZF++ctfRpZx4/WO5Y9//KNuueUWXXLJJfr973+vVq1aKScnR+Xl5VGTeyKL5eZKOQ4bknkvAXAJ+ZB8GEsy+bB2XjvzzDNjLhMrrw0ePFjNmzfXjBkzdNxxx2nGjBnKycnRueeeG7UfoVBIL7/8csznpaCgIOrfiea1p556SsOGDdOZZ56p66+/Xm3btlVubq4mTJigjz/+OKF1ADG5kfMkT7IeRSYk7ayzzlJZWZmWLFkSNZSors6dO+vVV1/Vtm3boo42fPTRR5Hbw/+tqanRxx9/HHV0atWqVVHrC59ZpLq6WqWlpW7ukqu6deumV199Vccff3zKEy5369ZN27dvd20/w2fdaOjsFU6f3z//+c9RZ0epOzF1Y8LdTOPGjYsZYjp37lzvPSHVfz/FMmDAAOXm5uovf/lL3Mm/n3zySTVp0iSqgNS1a1cdc8wxmj59ukaNGqVnn31WZ555pvLy8iLLuPF6xzJr1iydcsopeuyxx6Ku37p1q/bff/96y69evTrq38YYrVmzxtVgDQBAPOTDhpEP92ooH55wwglq2bKlpk2bpptvvjlmMejJJ5+UtPescmH77ruvBg0apJkzZ+qee+7R9OnTdeKJJ0Y9Vrdu3WSMUdeuXesV45yYNWuWfvKTn+jZZ5+NDDGUpLFjx8Zcvm5ek6R///vf6tKli2vbBHiNOZmQtIKCAk2aNEnjxo3T4MGD4y53+umnq7q6Wg8++GDU9ffee69CoVDkDCTh/9Y9+0jdbpbc3Fydc845+utf/xrzx/Crr75KZXdcd95556m6ulq///3v6922Z88ebd26NaF1LF68WPPnz69329atW7UnyTMEtGnTRieddJIef/xxffbZZ1G3hY9mOX1+e/furdLS0sil9hGmRJWXl6tly5a67bbb6t12+umn66233tLixYsj1+3YsUOTJ09Wly5dGny8jh07avjw4Xr11Vc1adKkerc/8sgjeu2113TppZfqwAMPjLptyJAhWrJkiR5//HF9/fXXUUPlJHde71hyc3PrHWmcOXOmNmzYEHP58NlKwmbNmqUvv/wy8vlCADVp4s4FAFxAPmwY+bDxfNi8eXNdd911WrVqlW6++eZ6t7/44ouaOnWq+vfvr2OPPTbqtiFDhuiLL77Qo48+qn/961/18trZZ5+t3NxcjR8/vl6+Msbom2++aXA/4gkXwmqvc+nSpVF5tbbZs2dHZbm33npLS5cuJa+hPrdyngdZj3SJlMRrl61t8ODBOuWUU3TzzTdr3bp16tWrl/72t7/p+eefV3l5eWSM/VFHHaULLrhADz/8sCorK3XcccdpwYIFWrNmTb113nHHHVq4cKH69u2ryy+/XD169NCWLVv07rvv6tVXX9WWLVtc39dk9evXT2VlZZowYYJWrFih0047Tfvss49Wr16tmTNn6r777os7T0HY9ddfrxdeeEGDBg3SsGHD1Lt3b+3YsUMrV67UrFmztG7dupjdLA25//77dcIJJ+hnP/uZRowYoa5du2rdunV68cUXtWLFCkneP79FRUW6+uqrY04AfuONN0ZOj3zVVVepVatWeuKJJ7R27Vr99a9/jUySHc+9996rjz76SFdeeaXmzZsX6ViaP3++nn/+efXr109//vOf693vvPPO03XXXafrrrtOrVq1qncUz43XO5ZBgwbptttu0/Dhw3Xcccdp5cqVevrppyNHHetq1aqVTjjhBA0fPlybNm3SxIkT1b17d11++eVJPzYs0aQJw+UA+Ar5MD7yYWJuvPFGLV++XHfeeacWL16sc845R/n5+XrzzTf11FNP6bDDDtMTTzxR736nn366WrRooeuuuy5SGKutW7du+sMf/qAxY8Zo3bp1OvPMM9WiRQutXbtWzz33nEaMGKHrrrsu6e0dNGiQnn32WZ111lkaOHCg1q5dq0ceeUQ9evTQ9u3b6y3fvXt3nXDCCbriiiu0a9cuTZw4Ua1bt447BBJZzI2cJzFcDsGSk5OjF154QbfeequmT5+uKVOmqEuXLrr77rt17bXXRi37+OOPq02bNnr66ac1e/Zs/fznP9eLL76ojh07Ri1XXFyst956S7fddpueffZZPfzww2rdurV69uypO++8M5O716BHHnlEvXv3VkVFhW666SY1adJEXbp00W9+8xsdf/zxjd6/efPmWrRokf74xz9q5syZevLJJ1VYWKiDDz5Y48ePT3hC7dp69eqlJUuW6JZbbtGkSZO0c+dOde7cWeedd15kGT88v+Xl5Zo4caIqKyujri8uLtY///lP3XDDDXrggQe0c+dOHXnkkZozZ44GDhzY6HoLCgq0YMECPfzww3rqqad0/fXXyxijQw89VBMnTtSVV15Zb9JHSTrwwAN13HHH6R//+Icuu+yymMs4fb1juemmm7Rjxw5NmzZN06dP189+9jO9+OKLuvHGG+Mu/95772nChAnatm2bTj31VD388MNq3rx5So8PAEA6kA/Jhw3Jzc3VjBkz9OSTT+rRRx/VLbfcot27d6tbt24aO3asrr32Wu2777717tesWTOdccYZevrpp1VaWhpzgvUbb7xRBx98cGQOUGlvt/tpp52mM844I6XtHTZsmDZu3KiKigrNnz9fPXr00FNPPaWZM2fq9ddfr7f8xRdfrJycHE2cOFGbN2/WMcccowcffFDt27dP6fEBPwqZZGZ+AwD4yuuvv65TTjlFM2fOTKlj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d5iioiIze/Zs869//cucccYZpmvXrub777+PLPPLX/7S9OrVyyxZssT8/e9/N927dzcXXHBBhvckMf379zdTpkwx77//vlmxYoU5/fTTTadOncz27dsjy/z2t781HTt2NAsWLDDvvPOOOfbYY81xxx0XuX3Pnj3m8MMPN6WlpWb58uXmpZdeMvvvv78ZM2aMF7vUoBdeeMG8+OKL5t///rdZtWqVuemmm8w+++xj3n//fWNMsPa1rrfeest06dLFHHnkkebqq6+OXB+0fR47dqzp2bOn+fLLLyOXr776KnJ70PZ3y5YtpnPnzmbYsGFm6dKl5pNPPjHz5883a9asiSwTtO+tzZs3R72+r7zyipFkFi5caIzx5jWurKw0kkxBQaVp0cI4uhQU7F1XZWWl06cKcAU5z97vS3IeOS9o+0zOI+fZnvO8ynrWFZmOOeYYM3LkyMi/q6urTYcOHcyECRM83Crn6oaPmpoa065dO3P33XdHrtu6davJy8sz//u//2uMMebDDz80kszbb78dWebll182oVDIbNiwIWPbnqrNmzcbSWbRokXGmL37t88++5iZM2dGlvm///s/I8ksXrzYGLM3sOXk5JiNGzdGlpk0aZIpLCw0u3btyuwOpGC//fYzjz76aKD3ddu2beaggw4yr7zyiunXr18kfARxn8eOHWt69eoV87Yg7u8NN9xgTjjhhLi3Z8P31tVXX226detmampqPHuNKTIhyMh5wfm+JOcFc1/JeXsFcX/JecHLeV5lPauGy+3evVvLli1TaWlp5LqcnByVlpZq8eLFHm6Z+9auXauNGzdG7WtRUZH69u0b2dfFixerZcuW6tOnT2SZ0tJS5eTkaOnSpRnf5mRVVlZKklq1aiVJWrZsmX744YeofT700EPVqVOnqH0+4ogjVFxcHFmmf//+qqqq0gcffJDBrU9OdXW1nnnmGe3YsUMlJSWB3teRI0dq4MCBUfsmBff1Xb16tTp06KCf/OQnuuiii/TZZ59JCub+vvDCC+rTp4/OPfdctW3bVj/96U/1P//zP5Hbg/69tXv3bj311FO65JJLFAqFPH+N3Wih9nHHPrIQOS8435cSOS+o+0rOI+cF9XsrqDnPi6xn1dnlvv76a1VXV0e9iJJUXFysjz76yKOtSo+NGzdKUsx9Dd+2ceNGtW3bNur2Jk2aqFWrVpFl/Kqmpkbl5eU6/vjjdfjhh0vauz9NmzZVy5Yto5atu8+xnpPwbX6zcuVKlZSUaOfOnSooKNBzzz2nHj16aMWKFYHbV0l65pln9O677+rtt9+ud1sQX9++fftq6tSpOuSQQ/Tll19q/PjxOvHEE/X+++8Hcn8/+eQTTZo0SaNHj9ZNN92kt99+W1dddZWaNm2qoUOHBv57a/bs2dq6dauGDRsmyfv39J49UijkaBUyxtn9ATeR84LzfUnOI+eF2bzP5Dxynu05T/Im61lVZEJwjBw5Uu+//77efPNNrzclrQ455BCtWLFClZWVmjVrloYOHapFixZ5vVlpsX79el199dV65ZVX1KxZM683JyMGDBgQ+f8jjzxSffv2VefOnTVjxgzl5+d7uGXpUVNToz59+uiPf/yjJOmnP/2p3n//fT3yyCMaOnSox1uXfo899pgGDBigDh06eL0pAOBr5LzgIeeR84KOnOceq4bL7b///srNza03o/umTZvUrl07j7YqPcL709C+tmvXTps3b466fc+ePdqyZYuvn49Ro0Zp7ty5WrhwoQ488MDI9e3atdPu3bu1devWqOXr7nOs5yR8m980bdpU3bt3V+/evTVhwgT16tVL9913XyD3ddmyZdq8ebN+9rOfqUmTJmrSpIkWLVqk+++/X02aNFFxcXHg9rmuli1b6uCDD9aaNWsC+Rq3b99ePXr0iLrusMMOi7SOB/l769NPP9Wrr76qyy67LHKd16+xrS3UQDzkvGB8X5LzyHm12bzPdZHzgvu9FeSc50XWs6rI1LRpU/Xu3VsLFiyIXFdTU6MFCxaopKTEwy1zX9euXdWuXbuofa2qqtLSpUsj+1pSUqKtW7dq2bJlkWVee+011dTUqG/fvhnf5sYYYzRq1Cg999xzeu2119S1a9eo23v37q199tknap9XrVqlzz77LGqfV65cGfXl9corr6iwsLDel6If1dTUaNeuXYHc11NPPVUrV67UihUrIpc+ffrooosuivx/0Pa5ru3bt+vjjz9W+/btA/kaH3/88fVOR/3vf/9bnTt3lhTM762wKVOmqG3btho4cGDkOu9f4xoZ4+wi1TjcBsA95Dy7vy/JeeS8oO1zXeS84H1vhQU153mW9TI2xbhLnnnmGZOXl2emTp1qPvzwQzNixAjTsmXLqBndbbFt2zazfPlys3z5ciPJ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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_panel(\"Model Inference\", results, 10, same_scale=True, transpose=True, cmap=\"seismic\")" + ] + }, { "cell_type": "code", "execution_count": null, - "id": "5f22943b", + "id": "62058e34", "metadata": {}, "outputs": [], "source": []