{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "96637152-70c6-4f09-99de-a7557de22834",
   "metadata": {},
   "source": [
    "# Installing Dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "37bb512e-9bb9-4ac6-9334-ff11dbdb03aa",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: ipywidgets in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (8.1.8)\n",
      "Requirement already satisfied: comm>=0.1.3 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipywidgets) (0.2.3)\n",
      "Requirement already satisfied: ipython>=6.1.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipywidgets) (9.13.0)\n",
      "Requirement already satisfied: traitlets>=4.3.1 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipywidgets) (5.15.0)\n",
      "Requirement already satisfied: widgetsnbextension~=4.0.14 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipywidgets) (4.0.15)\n",
      "Requirement already satisfied: jupyterlab_widgets~=3.0.15 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipywidgets) (3.0.16)\n",
      "Requirement already satisfied: decorator>=5.1.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets) (5.3.1)\n",
      "Requirement already satisfied: ipython-pygments-lexers>=1.0.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets) (1.1.1)\n",
      "Requirement already satisfied: jedi>=0.18.2 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets) (0.20.0)\n",
      "Requirement already satisfied: matplotlib-inline>=0.1.6 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets) (0.2.2)\n",
      "Requirement already satisfied: pexpect>4.6 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets) (4.9.0)\n",
      "Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets) (3.0.52)\n",
      "Requirement already satisfied: psutil>=7 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets) (7.2.2)\n",
      "Requirement already satisfied: pygments>=2.14.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets) (2.20.0)\n",
      "Requirement already satisfied: stack_data>=0.6.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets) (0.6.3)\n",
      "Requirement already satisfied: wcwidth in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython>=6.1.0->ipywidgets) (0.7.0)\n",
      "Requirement already satisfied: parso<0.9.0,>=0.8.6 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from jedi>=0.18.2->ipython>=6.1.0->ipywidgets) (0.8.7)\n",
      "Requirement already satisfied: ptyprocess>=0.5 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from pexpect>4.6->ipython>=6.1.0->ipywidgets) (0.7.0)\n",
      "Requirement already satisfied: executing>=1.2.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=6.1.0->ipywidgets) (2.2.1)\n",
      "Requirement already satisfied: asttokens>=2.1.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=6.1.0->ipywidgets) (3.0.1)\n",
      "Requirement already satisfied: pure-eval in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=6.1.0->ipywidgets) (0.2.3)\n",
      "Requirement already satisfied: ipycanvas in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (0.14.3)\n",
      "Requirement already satisfied: ipywidgets<9,>=7.6.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipycanvas) (8.1.8)\n",
      "Requirement already satisfied: numpy in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipycanvas) (2.4.6)\n",
      "Requirement already satisfied: pillow>=6.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipycanvas) (12.2.0)\n",
      "Requirement already satisfied: comm>=0.1.3 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipywidgets<9,>=7.6.0->ipycanvas) (0.2.3)\n",
      "Requirement already satisfied: ipython>=6.1.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipywidgets<9,>=7.6.0->ipycanvas) (9.13.0)\n",
      "Requirement already satisfied: traitlets>=4.3.1 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipywidgets<9,>=7.6.0->ipycanvas) (5.15.0)\n",
      "Requirement already satisfied: widgetsnbextension~=4.0.14 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipywidgets<9,>=7.6.0->ipycanvas) (4.0.15)\n",
      "Requirement already satisfied: jupyterlab_widgets~=3.0.15 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipywidgets<9,>=7.6.0->ipycanvas) (3.0.16)\n",
      "Requirement already satisfied: decorator>=5.1.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (5.3.1)\n",
      "Requirement already satisfied: ipython-pygments-lexers>=1.0.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (1.1.1)\n",
      "Requirement already satisfied: jedi>=0.18.2 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (0.20.0)\n",
      "Requirement already satisfied: matplotlib-inline>=0.1.6 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (0.2.2)\n",
      "Requirement already satisfied: pexpect>4.6 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (4.9.0)\n",
      "Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (3.0.52)\n",
      "Requirement already satisfied: psutil>=7 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (7.2.2)\n",
      "Requirement already satisfied: pygments>=2.14.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (2.20.0)\n",
      "Requirement already satisfied: stack_data>=0.6.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (0.6.3)\n",
      "Requirement already satisfied: wcwidth in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (0.7.0)\n",
      "Requirement already satisfied: parso<0.9.0,>=0.8.6 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from jedi>=0.18.2->ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (0.8.7)\n",
      "Requirement already satisfied: ptyprocess>=0.5 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from pexpect>4.6->ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (0.7.0)\n",
      "Requirement already satisfied: executing>=1.2.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (2.2.1)\n",
      "Requirement already satisfied: asttokens>=2.1.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (3.0.1)\n",
      "Requirement already satisfied: pure-eval in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=6.1.0->ipywidgets<9,>=7.6.0->ipycanvas) (0.2.3)\n",
      "Requirement already satisfied: pynrrd in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (1.1.3)\n",
      "Requirement already satisfied: numpy>=1.21 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from pynrrd) (2.4.6)\n",
      "Requirement already satisfied: typing_extensions in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from pynrrd) (4.15.0)\n",
      "Requirement already satisfied: pillow in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (12.2.0)\n",
      "Requirement already satisfied: scikit-image in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (0.26.0)\n",
      "Requirement already satisfied: numpy>=1.24 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from scikit-image) (2.4.6)\n",
      "Requirement already satisfied: scipy>=1.11.4 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from scikit-image) (1.17.1)\n",
      "Requirement already satisfied: networkx>=3.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from scikit-image) (3.6.1)\n",
      "Requirement already satisfied: pillow>=10.1 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from scikit-image) (12.2.0)\n",
      "Requirement already satisfied: imageio!=2.35.0,>=2.33 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from scikit-image) (2.37.3)\n",
      "Requirement already satisfied: tifffile>=2022.8.12 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from scikit-image) (2026.5.15)\n",
      "Requirement already satisfied: packaging>=21 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from scikit-image) (26.2)\n",
      "Requirement already satisfied: lazy-loader>=0.4 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from scikit-image) (0.5)\n",
      "Requirement already satisfied: rich in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (15.0.0)\n",
      "Requirement already satisfied: markdown-it-py>=2.2.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from rich) (4.2.0)\n",
      "Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from rich) (2.20.0)\n",
      "Requirement already satisfied: mdurl~=0.1 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from markdown-it-py>=2.2.0->rich) (0.1.2)\n",
      "Requirement already satisfied: ProjectiveGeometry23 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (0.0.0)\n",
      "Requirement already satisfied: numpy in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ProjectiveGeometry23) (2.4.6)\n",
      "Requirement already satisfied: scipy in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from ProjectiveGeometry23) (1.17.1)\n",
      "Requirement already satisfied: svg_snip in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (1.1.9)\n",
      "Requirement already satisfied: numpy>=1.21 in /home/aaichert/.virtualenvs/jupyter/lib/python3.12/site-packages (from svg_snip) (2.4.6)\n"
     ]
    }
   ],
   "source": [
    "!pip install ipywidgets\n",
    "!pip install ipycanvas\n",
    "!pip install pynrrd\n",
    "!pip install pillow\n",
    "!pip install scikit-image\n",
    "!pip install rich\n",
    "\n",
    "# Libraries by Andre Aichert:\n",
    "!pip install ProjectiveGeometry23\n",
    "!pip install svg_snip\n",
    "\n",
    "# !python -m pip install -e /home/aaichert/nc_local/work/ProjectiveGeometry23/\n",
    "# !python -m pip install -e /home/aaichert/nc_local/work/svg_snip/\n",
    "\n",
    "!mkdir -p output"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ee503047-f43f-4dab-b563-3f1a8512c87d",
   "metadata": {},
   "source": [
    "# Load Example Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "2230d54e-987e-4a70-b7de-b3526264c6e7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import nrrd\n",
    "\n",
    "I0, meta0 = nrrd.read(\"input/proj000.nrrd\")\n",
    "I1, meta1 = nrrd.read(\"input/proj040.nrrd\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "37c40121-157f-4a1d-a753-9b0d00bf0fd5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0., ..., 0., 0., 0.],\n",
       "       [0., 0., 0., ..., 0., 0., 0.],\n",
       "       [0., 0., 0., ..., 0., 0., 0.],\n",
       "       ...,\n",
       "       [0., 0., 0., ..., 0., 0., 0.],\n",
       "       [0., 0., 0., ..., 0., 0., 0.],\n",
       "       [0., 0., 0., ..., 0., 0., 0.]], shape=(1024, 760), dtype=float32)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "I0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a4cbb983-86cd-4925-8f6a-902c08d983ef",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('dimension', 2),\n",
       "             ('encoding', 'raw'),\n",
       "             ('endian', 'little'),\n",
       "             ('sizes', array([1024,  760])),\n",
       "             ('spacings', array([0.308, 0.308])),\n",
       "             ('type', 'float'),\n",
       "             ('Projection Matrix',\n",
       "              '[-506.148 -0 -3532.97 376726; -384 -3532.97 -0 285811; -1 -0 -0 744.3]')])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "meta0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6dd3d564-0c5c-4156-b997-1efe28700f1c",
   "metadata": {},
   "source": [
    "# Show Projection Images"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "a08ed734-ff3d-4fad-aa45-755e586702ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from PIL import Image\n",
    "\n",
    "def to_gray_image(img, scale=1.0, fast_axis_is_x=True):\n",
    "    img = np.asarray(img, dtype=np.float32)\n",
    "    if fast_axis_is_x:\n",
    "        img = img.T  # convert (x, y) → (y, x)\n",
    "    img = (img - img.min()) / (img.max() - img.min())\n",
    "    img = (img * 255).astype(np.uint8)\n",
    "    im = Image.fromarray(img, mode=\"L\")\n",
    "    if scale != 1.0:\n",
    "        new_size = (int(im.width * scale), int(im.height * scale))\n",
    "        im = im.resize(new_size, Image.BILINEAR)\n",
    "    return im"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a94e2b2e-02d1-45bd-b74f-2424962687fb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "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",
      "image/png": "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",
      "text/plain": [
       "<PIL.Image.Image image mode=L size=256x190>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "to_gray_image(I0, .25)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "488eaae5-11f8-4bf0-8729-07390283da11",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "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FFAJByDirsGq3lvjZMxA7GtS38WXMYAkQNV1fGIH/LNh+NSL4vhYfMHBqJvFqhsqpI96gk8Y3BPyRAD3NVJ/FOoTKVVlTPoKypbqeYkySsxPqahoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooor//2Q==",
      "image/png": "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",
      "text/plain": [
       "<PIL.Image.Image image mode=L size=256x190>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "to_gray_image(I1, .25)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b959a25-8bc8-4d62-9503-53c3acc2c645",
   "metadata": {},
   "source": [
    "# Projection Matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "210fac76-ea5d-482a-90b2-664e8412c225",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[-5.06148e+02, -0.00000e+00, -3.53297e+03,  3.76726e+05],\n",
       "        [-3.84000e+02, -3.53297e+03, -0.00000e+00,  2.85811e+05],\n",
       "        [-1.00000e+00, -0.00000e+00, -0.00000e+00,  7.44300e+02]]),\n",
       " array([[-1.97544e+03, -0.00000e+00,  2.97249e+03,  3.76726e+05],\n",
       "        [ 2.86441e+02, -3.53297e+03,  2.55749e+02,  2.85811e+05],\n",
       "        [ 7.45941e-01, -0.00000e+00,  6.66012e-01,  7.44300e+02]]),\n",
       " array([0.308, 0.308]))"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "import numpy as np\n",
    "\n",
    "def parse_matrix(s):\n",
    "    s = s.strip().replace('[', '').replace(']', '')\n",
    "    rows = s.split(';')\n",
    "    return np.array([[float(x) for x in row.split()] for row in rows])\n",
    "\n",
    "\n",
    "P0_np = parse_matrix(meta0['Projection Matrix'])\n",
    "P1_np = parse_matrix(meta1['Projection Matrix'])\n",
    "\n",
    "spacing = meta0['spacings']\n",
    "\n",
    "P0_np, P1_np, spacing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "09c2d25d-407c-4776-b57c-c7e45354e5c2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(ProjectionMatrix:\n",
       " [[-5.06148e+02 -0.00000e+00 -3.53297e+03  3.76726e+05]\n",
       "  [-3.84000e+02 -3.53297e+03 -0.00000e+00  2.85811e+05]\n",
       "  [-1.00000e+00 -0.00000e+00 -0.00000e+00  7.44300e+02]]\n",
       " Image Size: [1024  760]\n",
       " Pixel Spacing: 0.308,\n",
       " ProjectionMatrix:\n",
       " [[-1.97544e+03 -0.00000e+00  2.97249e+03  3.76726e+05]\n",
       "  [ 2.86441e+02 -3.53297e+03  2.55749e+02  2.85811e+05]\n",
       "  [ 7.45941e-01 -0.00000e+00  6.66012e-01  7.44300e+02]]\n",
       " Image Size: [1024  760]\n",
       " Pixel Spacing: 0.308)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from ProjectiveGeometry23.central_projection import ProjectionMatrix\n",
    "\n",
    "P0 = ProjectionMatrix(P0_np, I0.shape, pixel_spacing=spacing[0])\n",
    "P1 = ProjectionMatrix(P1_np, I1.shape, pixel_spacing=spacing[0])\n",
    "\n",
    "P0, P1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "6562f096-ce0d-4e69-b990-364850933444",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[31mInit signature:\u001b[39m ProjectionMatrix(P, image_size=(\u001b[32m400\u001b[39m, \u001b[32m300\u001b[39m), pixel_spacing=\u001b[32m1.0\u001b[39m)\n",
       "\u001b[31mDocstring:\u001b[39m      <no docstring>\n",
       "\u001b[31mInit docstring:\u001b[39m\n",
       "Pinhole projection model as 3x4 projection matrix with optional\n",
       "information of detector size and pixel spacing [mm per px].\n",
       "\u001b[31mFile:\u001b[39m           ~/.virtualenvs/jupyter/lib/python3.12/site-packages/ProjectiveGeometry23/central_projection.py\n",
       "\u001b[31mType:\u001b[39m           type\n",
       "\u001b[31mSubclasses:\u001b[39m     "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ProjectionMatrix?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "ff2cda03-e073-451e-b766-1a3308d7910e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "backproject\n",
      "computeFundamentalMatrix\n",
      "decomposition\n",
      "from_dict\n",
      "from_json\n",
      "getCenterOfProjection\n",
      "getDetectorAxisDirections\n",
      "getDetectorAxisDirectionsPx\n",
      "getDetectorPlane\n",
      "getFocalLengthPx\n",
      "getPrincipalPoint\n",
      "getPrincipalRay\n",
      "normalize\n",
      "perspective_look_at\n",
      "principal_ray\n",
      "pseudoinverse\n",
      "to_dict\n",
      "to_json\n",
      "to_ompl\n"
     ]
    }
   ],
   "source": [
    "for f in dir(ProjectionMatrix):\n",
    "    if not f.startswith('__'):\n",
    "        print(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "0dfc630b-4e26-4a78-af3e-c7b9e25c4e15",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.60102035e-10,  1.08105982e-03, -4.15126676e-01],\n",
       "       [ 1.08106000e-03, -4.30956671e-18, -2.00411569e+00],\n",
       "       [-4.15126960e-01,  9.09762940e-01,  4.20231307e+02]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "P0.computeFundamentalMatrix(P1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b314c1b7-4e1a-4b81-8eed-82cccadde8d6",
   "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.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
