Files
sam3_local/examples/sam3_image_interactive.ipynb
facebook-github-bot a13e358df4 Initial commit
fbshipit-source-id: da6be2f26e3a1202f4bffde8cb980e2dcb851294
2025-11-18 23:07:54 -08:00

758 lines
44 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "5d0e0b69",
"metadata": {},
"outputs": [],
"source": [
"# Copyright (c) Meta Platforms, Inc. and affiliates."
]
},
{
"cell_type": "markdown",
"id": "11912666",
"metadata": {},
"source": [
"# <a target=\"_blank\" href=\"https://colab.research.google.com/github/facebookresearch/sam3/blob/main/notebooks/sam3_image_interactive.ipynb\">\n",
"# <img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/>\n",
"# </a>"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "8517f5f6",
"metadata": {},
"outputs": [],
"source": [
"using_colab = False"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "2540e376",
"metadata": {},
"outputs": [],
"source": [
"if using_colab:\n",
" import torch\n",
" import torchvision\n",
" print(\"PyTorch version:\", torch.__version__)\n",
" print(\"Torchvision version:\", torchvision.__version__)\n",
" print(\"CUDA is available:\", torch.cuda.is_available())\n",
" import sys\n",
" !{sys.executable} -m pip install opencv-python matplotlib scikit-learn\n",
" !{sys.executable} -m pip install 'git+https://github.com/facebookresearch/sam3.git'"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "90073483-58f6-404e-90ac-c22efcd76216",
"metadata": {},
"outputs": [],
"source": [
"%matplotlib widget"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "13325376-658b-48d6-8528-2a006f223d44",
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"# turn on tfloat32 for Ampere GPUs\n",
"# https://pytorch.org/docs/stable/notes/cuda.html#tensorfloat-32-tf32-on-ampere-devices\n",
"torch.backends.cuda.matmul.allow_tf32 = True\n",
"torch.backends.cudnn.allow_tf32 = True\n",
"\n",
"# use bfloat16 for the entire notebook. If your card doesn't support it, try float16 instead\n",
"torch.autocast(\"cuda\", dtype=torch.bfloat16).__enter__()\n",
"\n",
"# inference mode for the whole notebook. Disable if you need gradients\n",
"torch.inference_mode().__enter__()"
]
},
{
"cell_type": "markdown",
"id": "fb863772-56a9-4ee2-be52-5d8933066519",
"metadata": {},
"source": [
"# Load the model"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "f84b4ccc-9db2-4d88-ac8f-4c272694d25a",
"metadata": {},
"outputs": [],
"source": [
"import sam3\n",
"from sam3 import build_sam3_image_model\n",
"import os\n",
"sam3_root = os.path.join(os.path.dirname(sam3.__file__), \"..\")\n",
"bpe_path = f\"{sam3_root}/assets/bpe_simple_vocab_16e6.txt.gz\""
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "de01a36e-1221-4497-a5ab-e6c796689480",
"metadata": {},
"outputs": [],
"source": [
"model = build_sam3_image_model(bpe_path=bpe_path)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "b01ec8a9-d9f6-4baf-96ac-1e5d21fd90b8",
"metadata": {},
"outputs": [],
"source": [
"from sam3.model.sam3_image_processor import Sam3Processor\n",
"processor = Sam3Processor(model)"
]
},
{
"cell_type": "markdown",
"id": "e6172a69-35ca-487c-bd67-6f1f1ecb20d5",
"metadata": {},
"source": [
"# Jupyter widget"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "2a4ac22f-5d5c-4272-a5a1-dfe0c04253a7",
"metadata": {},
"outputs": [],
"source": [
"import io\n",
"\n",
"import ipywidgets as widgets\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import PIL.Image\n",
"import requests\n",
"from IPython.display import clear_output, display, HTML\n",
"from matplotlib.patches import Rectangle\n",
"\n",
"\n",
"class Sam3SegmentationWidget:\n",
" \"\"\"Interactive Jupyter widget for SAM3 segmentation with text and box prompts.\"\"\"\n",
"\n",
" def __init__(self, processor):\n",
" \"\"\"\n",
" Initialize the segmentation widget.\n",
"\n",
" Args:\n",
" processor: Sam3Processor instance\n",
" \"\"\"\n",
" self.processor = processor\n",
" self.state = None\n",
" self.current_image = None\n",
" self.current_image_array = None\n",
" self.box_mode = \"positive\"\n",
" self.drawing_box = False\n",
" self.box_start = None\n",
" self.current_rect = None\n",
"\n",
" self._setup_ui()\n",
" self._setup_plot()\n",
"\n",
" def _setup_ui(self):\n",
" \"\"\"Set up the UI components.\"\"\"\n",
" self.upload_widget = widgets.FileUpload(\n",
" accept=\"image/*\", multiple=False, description=\"Upload Image\"\n",
" )\n",
" self.upload_widget.observe(self._on_image_upload, names=\"value\")\n",
"\n",
" self.url_input = widgets.Text(\n",
" placeholder=\"Or enter image URL\",\n",
" )\n",
" self.url_button = widgets.Button(description=\"Load URL\", button_style=\"info\")\n",
" self.url_button.on_click(self._on_load_url)\n",
" url_box = widgets.HBox(\n",
" [self.url_input, self.url_button],\n",
" layout=widgets.Layout(width=\"100%\", justify_content=\"space-between\"),\n",
" )\n",
"\n",
" self.text_input = widgets.Text(\n",
" placeholder='Enter segmentation prompt (e.g., \"person\", \"dog\")',\n",
" continuous_update=False,\n",
" )\n",
" self.text_input.observe(self._on_text_submit, names=\"value\")\n",
" self.text_button = widgets.Button(description=\"Segment\", button_style=\"success\")\n",
" self.text_button.on_click(self._on_text_prompt)\n",
" text_box = widgets.HBox(\n",
" [self.text_input, self.text_button],\n",
" layout=widgets.Layout(width=\"100%\", justify_content=\"space-between\"),\n",
" )\n",
"\n",
" self.box_mode_buttons = widgets.ToggleButtons(\n",
" options=[\"Positive Boxes\", \"Negative Boxes\"],\n",
" description=\"Box Mode:\",\n",
" button_style=\"\",\n",
" tooltips=[\n",
" \"Draw boxes around objects to include\",\n",
" \"Draw boxes around objects to exclude\",\n",
" ],\n",
" )\n",
" self.box_mode_buttons.observe(self._on_box_mode_change, names=\"value\")\n",
"\n",
" self.clear_button = widgets.Button(\n",
" description=\"Clear All Prompts\", button_style=\"warning\"\n",
" )\n",
" self.clear_button.on_click(self._on_clear_prompts)\n",
"\n",
" self.confidence_slider = widgets.FloatSlider(\n",
" value=0.5,\n",
" min=0.0,\n",
" max=1.0,\n",
" step=0.01,\n",
" description=\"Confidence:\",\n",
" continuous_update=False,\n",
" style={\"description_width\": \"initial\"},\n",
" )\n",
" self.confidence_slider.observe(self._on_confidence_change, names=\"value\")\n",
"\n",
" self.size_slider = widgets.IntSlider(\n",
" value=960,\n",
" min=300,\n",
" max=2000,\n",
" step=10,\n",
" description=\"Image Size:\",\n",
" continuous_update=False,\n",
" style={\"description_width\": \"initial\"},\n",
" )\n",
" self.size_slider.observe(self._on_size_change, names=\"value\")\n",
"\n",
" slider_box = widgets.HBox(\n",
" [self.confidence_slider, self.size_slider],\n",
" layout=widgets.Layout(justify_content=\"space-between\"),\n",
" )\n",
"\n",
" self.output = widgets.Output()\n",
" self.status_label = widgets.Label(value=\"Upload an image to begin\")\n",
"\n",
" # This box will hold our matplotlib output and we can target it with CSS.\n",
" self.plot_container = widgets.Box([self.output])\n",
" self.plot_container.add_class(\"no-drag\")\n",
"\n",
" # CSS to make the cursor a crosshair over the matplotlib canvas\n",
" css_style = widgets.HTML(\n",
" \"\"\"\n",
" <style>\n",
" .jupyter-matplotlib-canvas, canvas {\n",
" cursor: crosshair !important;\n",
" }\n",
" </style>\n",
" \"\"\"\n",
" )\n",
" # Create VBoxes for each accordion pane\n",
" source_pane = widgets.VBox([self.upload_widget, url_box])\n",
" prompt_pane = widgets.VBox(\n",
" [\n",
" widgets.Label(\"Text Prompt:\"),\n",
" text_box,\n",
" self.box_mode_buttons,\n",
" self.confidence_slider,\n",
" self.clear_button,\n",
" ]\n",
" )\n",
" display_pane = widgets.VBox([self.size_slider])\n",
"\n",
" # Create the Accordion to hold the control panes\n",
" self.accordion = widgets.Accordion(\n",
" children=[source_pane, prompt_pane, display_pane]\n",
" )\n",
" self.accordion.set_title(0, \"Image Source\")\n",
" self.accordion.set_title(1, \"Segmentation Prompts\")\n",
" self.accordion.set_title(2, \"Display Settings\")\n",
" self.accordion.selected_index = 0 # Start with the first pane open\n",
"\n",
" # Create the left sidebar for controls\n",
" sidebar = widgets.VBox(\n",
" [self.status_label, widgets.HTML(\"<h4>Controls</h4>\"), self.accordion]\n",
" )\n",
" sidebar.layout = widgets.Layout(\n",
" width=\"380px\",\n",
" min_width=\"380px\",\n",
" max_width=\"380px\",\n",
" border=\"1px solid #e0e0e0\",\n",
" padding=\"10px\",\n",
" margin=\"0 15px 0 0\",\n",
" flex=\"0 0 auto\",\n",
" )\n",
"\n",
" # Create the main area for the image display\n",
" main_area = widgets.VBox([self.plot_container])\n",
" main_area.layout = widgets.Layout(flex=\"1\", min_width=\"500px\", overflow=\"auto\")\n",
"\n",
" # Combine sidebar and main area into the final app layout\n",
" app_layout = widgets.HBox([sidebar, main_area])\n",
" app_layout.layout = widgets.Layout(\n",
" width=\"100%\",\n",
" display=\"flex\",\n",
" flex_flow=\"row\",\n",
" align_items=\"stretch\",\n",
" )\n",
"\n",
" # Set the main container\n",
" self.container = widgets.VBox(\n",
" [\n",
" css_style,\n",
" widgets.HTML(\"<h3>🖼️ SAM3 Interactive Segmentation</h3>\"),\n",
" app_layout,\n",
" ]\n",
" )\n",
"\n",
" def _setup_plot(self):\n",
" \"\"\"Set up the matplotlib figure.\"\"\"\n",
" # plt.ioff()\n",
" self.fig, self.ax = plt.subplots(figsize=(12, 8))\n",
" # plt.ion()\n",
" self.ax.axis(\"off\")\n",
" self.fig.subplots_adjust(left=0, right=1, top=1, bottom=0)\n",
" self.fig.canvas.toolbar_visible = False\n",
" self.fig.canvas.header_visible = False\n",
" self.fig.canvas.footer_visible = False\n",
" self.fig.canvas.resizable = False\n",
"\n",
" # plt.close(self.fig)\n",
"\n",
" def _set_loading(self, is_loading, message=\"Processing...\"):\n",
" \"\"\"Show/hide loading state and disable/enable controls.\"\"\"\n",
" if is_loading:\n",
" self.status_label.value = f\"⏳ {message}\"\n",
" self.upload_widget.disabled = True\n",
" self.url_button.disabled = True\n",
" self.text_button.disabled = True\n",
" self.clear_button.disabled = True\n",
" self.box_mode_buttons.disabled = True\n",
" self.confidence_slider.disabled = True\n",
" else:\n",
" self.upload_widget.disabled = False\n",
" self.url_button.disabled = False\n",
" self.text_button.disabled = False\n",
" self.clear_button.disabled = False\n",
" self.box_mode_buttons.disabled = False\n",
" self.confidence_slider.disabled = False\n",
"\n",
" def _on_image_upload(self, change):\n",
" \"\"\"Handle image upload.\"\"\"\n",
" if change[\"new\"]:\n",
" uploaded_file = change[\"new\"][0]\n",
" image = PIL.Image.open(io.BytesIO(uploaded_file[\"content\"])).convert(\"RGB\")\n",
" self._set_image(image)\n",
"\n",
" def _on_load_url(self, button):\n",
" \"\"\"Handle loading image from URL.\"\"\"\n",
" url = self.url_input.value.strip()\n",
" if not url:\n",
" self.status_label.value = \"Please enter a URL\"\n",
" return\n",
"\n",
" self._set_loading(True, \"Downloading image from URL...\")\n",
"\n",
" try:\n",
" response = requests.get(url, timeout=10)\n",
" response.raise_for_status()\n",
" image = PIL.Image.open(io.BytesIO(response.content)).convert(\"RGB\")\n",
" self._set_image(image)\n",
" except Exception as e:\n",
" self._set_loading(False)\n",
" self.status_label.value = f\"Error loading image: {str(e)}\"\n",
"\n",
" def _set_image(self, image):\n",
" \"\"\"Set the current image, adjust figure size, and initialize state.\"\"\"\n",
" self._set_loading(True, \"Processing image through model...\")\n",
"\n",
" try:\n",
"\n",
" self.current_image = image\n",
" self.current_image_array = np.array(image)\n",
" self.state = self.processor.set_image(image)\n",
" self._set_loading(False)\n",
" self.status_label.value = (\n",
" f\"Image loaded: {image.size[0]}x{image.size[1]} pixels\"\n",
" )\n",
" self._resize_figure()\n",
" self._update_display()\n",
" self._connect_plot_events()\n",
" self.accordion.selected_index = 1\n",
" except Exception as e:\n",
" self._set_loading(False)\n",
" self.status_label.value = f\"Error processing image: {str(e)}\"\n",
"\n",
" def _on_text_submit(self, change):\n",
" \"\"\"Handle text prompt submission via Enter key.\"\"\"\n",
" # Call the same handler as the button click\n",
" self._on_text_prompt(None)\n",
"\n",
" def _on_text_prompt(self, button):\n",
" \"\"\"Handle text prompt submission.\"\"\"\n",
" if self.state is None:\n",
" self.status_label.value = \"Please load an image first\"\n",
" return\n",
"\n",
" prompt = self.text_input.value.strip()\n",
" if not prompt:\n",
" self.status_label.value = \"Please enter a prompt\"\n",
" return\n",
"\n",
" self._set_loading(True, f'Segmenting with prompt: \"{prompt}\"...')\n",
"\n",
" try:\n",
" self.state = self.processor.set_text_prompt(prompt, self.state)\n",
" self._set_loading(False)\n",
" self.status_label.value = f'Segmented with prompt: \"{prompt}\"'\n",
" self._update_display()\n",
" except Exception as e:\n",
" self._set_loading(False)\n",
" self.status_label.value = f\"Error: {str(e)}\"\n",
"\n",
" def _on_box_mode_change(self, change):\n",
" \"\"\"Handle box mode toggle.\"\"\"\n",
" self.box_mode = \"positive\" if change[\"new\"] == \"Positive Boxes\" else \"negative\"\n",
"\n",
" def _on_clear_prompts(self, button):\n",
" \"\"\"Clear all prompts and reset to image only.\"\"\"\n",
" if self.current_image is not None:\n",
" try:\n",
" self._set_loading(True, \"Clearing prompts and resetting...\")\n",
" self.state = self.processor.reset_all_prompts(self.state)\n",
" if \"prompted_boxes\" in self.state:\n",
" del self.state[\"prompted_boxes\"]\n",
" self.text_input.value = \"\"\n",
" self._set_loading(False)\n",
" self.status_label.value = \"Cleared all prompts\"\n",
" self._update_display()\n",
" except Exception as e:\n",
" self._set_loading(False)\n",
" import traceback\n",
"\n",
" self.status_label.value = f\"Error: {str(e)} {traceback.format_exc()}\"\n",
"\n",
" def _on_confidence_change(self, change):\n",
" \"\"\"Handle confidence threshold change.\"\"\"\n",
" if self.state is not None:\n",
" self.state = self.processor.set_confidence_threshold(\n",
" change[\"new\"], self.state\n",
" )\n",
" self._update_display()\n",
"\n",
" def _connect_plot_events(self):\n",
" \"\"\"Connect matplotlib event handlers for box drawing.\"\"\"\n",
" # Disable matplotlib's toolbar navigation to allow custom box drawing\n",
" if hasattr(self.fig.canvas, \"toolbar\") and self.fig.canvas.toolbar is not None:\n",
" self.fig.canvas.toolbar.pan()\n",
" self.fig.canvas.toolbar.pan()\n",
"\n",
" self.fig.canvas.mpl_connect(\"button_press_event\", self._on_press)\n",
" self.fig.canvas.mpl_connect(\"button_release_event\", self._on_release)\n",
" self.fig.canvas.mpl_connect(\"motion_notify_event\", self._on_motion)\n",
"\n",
" def _on_press(self, event):\n",
" \"\"\"Handle mouse press for box drawing.\"\"\"\n",
" if event.inaxes != self.ax:\n",
" return\n",
" self.drawing_box = True\n",
" self.box_start = (event.xdata, event.ydata)\n",
"\n",
" def _on_motion(self, event):\n",
" \"\"\"Handle mouse motion for box preview.\"\"\"\n",
" if not self.drawing_box or event.inaxes != self.ax or self.box_start is None:\n",
" return\n",
"\n",
" if self.current_rect is not None:\n",
" self.current_rect.remove()\n",
"\n",
" x0, y0 = self.box_start\n",
" x1, y1 = event.xdata, event.ydata\n",
" width = x1 - x0\n",
" height = y1 - y0\n",
"\n",
" color = \"green\" if self.box_mode == \"positive\" else \"red\"\n",
" self.current_rect = Rectangle(\n",
" (x0, y0),\n",
" width,\n",
" height,\n",
" fill=False,\n",
" edgecolor=color,\n",
" linewidth=2,\n",
" linestyle=\"--\",\n",
" )\n",
" self.ax.add_patch(self.current_rect)\n",
" self.fig.canvas.draw_idle()\n",
"\n",
" def _on_release(self, event):\n",
" \"\"\"Handle mouse release to finalize box.\"\"\"\n",
" if not self.drawing_box or event.inaxes != self.ax or self.box_start is None:\n",
" self.drawing_box = False\n",
" return\n",
"\n",
" self.drawing_box = False\n",
"\n",
" if self.current_rect is not None:\n",
" self.current_rect.remove()\n",
" self.current_rect = None\n",
"\n",
" if self.state is None:\n",
" return\n",
"\n",
" x0, y0 = self.box_start\n",
" x1, y1 = event.xdata, event.ydata\n",
"\n",
" x_min = min(x0, x1)\n",
" x_max = max(x0, x1)\n",
" y_min = min(y0, y1)\n",
" y_max = max(y0, y1)\n",
"\n",
" if abs(x_max - x_min) < 5 or abs(y_max - y_min) < 5:\n",
" return\n",
"\n",
" # Get image dimensions\n",
" img_h = self.state[\"original_height\"]\n",
" img_w = self.state[\"original_width\"]\n",
"\n",
" # Convert from xyxy pixel coordinates to cxcywh normalized format\n",
" center_x = (x_min + x_max) / 2.0 / img_w\n",
" center_y = (y_min + y_max) / 2.0 / img_h\n",
" width = (x_max - x_min) / img_w\n",
" height = (y_max - y_min) / img_h\n",
"\n",
" box = [center_x, center_y, width, height]\n",
" label = self.box_mode == \"positive\"\n",
" mode_str = \"positive\" if label else \"negative\"\n",
"\n",
" # Store the prompted box in pixel coordinates for display\n",
" if \"prompted_boxes\" not in self.state:\n",
" self.state[\"prompted_boxes\"] = []\n",
" self.state[\"prompted_boxes\"].append(\n",
" {\"box\": [x_min, y_min, x_max, y_max], \"label\": label}\n",
" )\n",
"\n",
" self._set_loading(True, f\"Adding {mode_str} box and re-segmenting...\")\n",
"\n",
" try:\n",
" self.state = self.processor.add_geometric_prompt(box, label, self.state)\n",
" self._set_loading(False)\n",
" self.status_label.value = f\"Added {mode_str} box\"\n",
" self._update_display()\n",
" except Exception as e:\n",
" self._set_loading(False)\n",
" self.status_label.value = f\"Error adding box: {str(e)}\"\n",
"\n",
" def _resize_figure(self):\n",
" \"\"\"Calculate and apply new figure size based on image and slider value.\"\"\"\n",
" if self.current_image is None:\n",
" return\n",
"\n",
" # 1. Get original image dimensions\n",
" img_w, img_h = self.current_image.size\n",
"\n",
" # 2. The slider's value is now the direct target width for the display\n",
" display_w = float(self.size_slider.value)\n",
"\n",
" # 3. Calculate the corresponding height to maintain the original aspect ratio\n",
" aspect_ratio = img_h / img_w\n",
" display_h = int(display_w * aspect_ratio)\n",
"\n",
" # 4. Convert pixel dimensions to inches for Matplotlib and apply\n",
" dpi = self.fig.dpi\n",
" new_figsize = (display_w / dpi, display_h / dpi)\n",
" self.fig.set_size_inches(new_figsize, forward=True)\n",
"\n",
" def _on_size_change(self, change):\n",
" \"\"\"Handle a change from the image size slider.\"\"\"\n",
" if self.current_image is not None:\n",
" self._resize_figure()\n",
" # After resizing the canvas, we must redraw the content\n",
" self._update_display()\n",
"\n",
" def _update_display(self):\n",
" \"\"\"Update the display with current results.\"\"\"\n",
" if self.current_image_array is None:\n",
" return\n",
"\n",
" with self.output:\n",
" clear_output(wait=True)\n",
"\n",
" self.ax.clear()\n",
" self.ax.axis(\"off\")\n",
" self.ax.imshow(self.current_image_array)\n",
"\n",
" if self.state is not None and \"masks\" in self.state:\n",
" masks = self.state.get(\"masks\", [])\n",
" boxes = self.state.get(\"boxes\", [])\n",
" scores = self.state.get(\"scores\", [])\n",
"\n",
" if len(masks) > 0:\n",
" mask_overlay = np.zeros((*self.current_image_array.shape[:2], 4))\n",
"\n",
" for i, (mask, box, score) in enumerate(zip(masks, boxes, scores)):\n",
" mask_np = mask[0].cpu().numpy()\n",
"\n",
" color = plt.cm.tab10(i % 10)[:3]\n",
" mask_overlay[mask_np > 0.5] = (*color, 0.5)\n",
"\n",
" x0, y0, x1, y1 = box.cpu().numpy()\n",
" rect = Rectangle(\n",
" (x0, y0),\n",
" x1 - x0,\n",
" y1 - y0,\n",
" fill=False,\n",
" edgecolor=color,\n",
" linewidth=2,\n",
" )\n",
" self.ax.add_patch(rect)\n",
"\n",
" self.ax.text(\n",
" x0,\n",
" y0 - 5,\n",
" f\"{score:.2f}\",\n",
" color=\"white\",\n",
" fontsize=10,\n",
" bbox=dict(\n",
" facecolor=color, alpha=0.7, edgecolor=\"none\", pad=2\n",
" ),\n",
" )\n",
"\n",
" self.ax.imshow(mask_overlay)\n",
" self.status_label.value = f\"Found {len(masks)} object(s)\"\n",
" else:\n",
" self.status_label.value = (\n",
" \"No objects found above confidence threshold\"\n",
" )\n",
"\n",
" # Display prompted boxes with dashed lines\n",
" if self.state is not None and \"prompted_boxes\" in self.state:\n",
" for prompted_box in self.state[\"prompted_boxes\"]:\n",
" box_coords = prompted_box[\"box\"]\n",
" is_positive = prompted_box[\"label\"]\n",
"\n",
" x0, y0, x1, y1 = box_coords\n",
" color = \"green\" if is_positive else \"red\"\n",
"\n",
" rect = Rectangle(\n",
" (x0, y0),\n",
" x1 - x0,\n",
" y1 - y0,\n",
" fill=False,\n",
" edgecolor=color,\n",
" linewidth=2,\n",
" linestyle=\"--\",\n",
" )\n",
" self.ax.add_patch(rect)\n",
"\n",
" # display(self.fig.canvas)\n",
"\n",
" def display(self):\n",
" display(self.container)\n",
"\n",
" # Add this for more convenient display in notebooks\n",
" def _ipython_display_(self):\n",
" self.display()\n"
]
},
{
"cell_type": "markdown",
"id": "1b9bda74-b455-4957-9767-2a46a041b50f",
"metadata": {},
"source": [
"# Run!"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "ebfb9b85-2318-4328-bb0e-e93e4a57fefe",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ea0e04a1bfd7486b93baae650d87e0b2",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(HTML(value='\\n <style>\\n .jupyter-matplotlib-canvas, canvas {\\n …"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "bbdcb3374c29461bb379d4bf9c319a49",
"version_major": 2,
"version_minor": 0
},
"image/png": "iVBORw0KGgoAAAANSUhEUgAABLAAAAMgCAYAAAAz4JsCAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAFf1JREFUeJzt2DEBACAMwDDAv+fhgJceiYLe3TMzCwAAAACizu8AAAAAAHgxsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEi710EKPFzQ9BwAAAAASUVORK5CYII=",
"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,iVBORw0KGgoAAAANSUhEUgAABLAAAAMgCAYAAAAz4JsCAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAFf1JREFUeJzt2DEBACAMwDDAv+fhgJceiYLe3TMzCwAAAACizu8AAAAAAHgxsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEi710EKPFzQ9BwAAAAASUVORK5CYII=' width=1200.0/>\n",
" </div>\n",
" "
],
"text/plain": [
"Canvas(footer_visible=False, header_visible=False, resizable=False, toolbar=Toolbar(toolitems=[('Home', 'Reset…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"widget = Sam3SegmentationWidget(processor)\n",
"widget.display()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "50a14560-573a-4784-9f55-689fda9147be",
"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.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}