Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save GenevieveBuckley/a38112a9dd31cf09a3ab1459768d64eb to your computer and use it in GitHub Desktop.
Save GenevieveBuckley/a38112a9dd31cf09a3ab1459768d64eb to your computer and use it in GitHub Desktop.
distributed skeleton analysis
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "hollywood-winning",
"metadata": {},
"source": [
"# Distributed skeleton analysis"
]
},
{
"cell_type": "markdown",
"id": "clean-meaning",
"metadata": {},
"source": [
"## Imports"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "instant-moment",
"metadata": {},
"outputs": [],
"source": [
"%load_ext autoreload\n",
"%autoreload 2"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "independent-relationship",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'2021.02.0'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import dask\n",
"dask.__version__"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "promotional-imperial",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import dask.array as da"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "removable-diamond",
"metadata": {},
"outputs": [],
"source": [
"from skan._testdata import skeleton0, skeleton1, skeleton2, skeleton3d, skeleton4"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "previous-kingdom",
"metadata": {},
"outputs": [],
"source": [
"from dask_image.ndfilters import convolve\n",
"from dask_image.ndmeasure import label"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "urban-edmonton",
"metadata": {},
"outputs": [],
"source": [
"from dask import delayed\n",
"import dask.dataframe as dd"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "competitive-dependence",
"metadata": {},
"outputs": [],
"source": [
"import scipy.ndimage\n",
"from scipy import sparse\n",
"from skan.csr import _write_pixel_graph\n",
"from skan.nputil import pad, raveled_steps_to_neighbors"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "stone-allah",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "mobile-office",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"id": "pending-frederick",
"metadata": {},
"source": [
"## Dask dashboard"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "chief-database",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/genevieve/anaconda3/envs/microfil/lib/python3.7/site-packages/distributed/node.py:155: UserWarning: Port 8787 is already in use.\n",
"Perhaps you already have a cluster running?\n",
"Hosting the HTTP server on port 37223 instead\n",
" http_address[\"port\"], self.http_server.port\n"
]
},
{
"data": {
"text/html": [
"<table style=\"border: 2px solid white;\">\n",
"<tr>\n",
"<td style=\"vertical-align: top; border: 0px solid white\">\n",
"<h3 style=\"text-align: left;\">Client</h3>\n",
"<ul style=\"text-align: left; list-style: none; margin: 0; padding: 0;\">\n",
" <li><b>Scheduler: </b>tcp://127.0.0.1:43943</li>\n",
" <li><b>Dashboard: </b><a href='http://127.0.0.1:37223/status' target='_blank'>http://127.0.0.1:37223/status</a></li>\n",
"</ul>\n",
"</td>\n",
"<td style=\"vertical-align: top; border: 0px solid white\">\n",
"<h3 style=\"text-align: left;\">Cluster</h3>\n",
"<ul style=\"text-align: left; list-style:none; margin: 0; padding: 0;\">\n",
" <li><b>Workers: </b>4</li>\n",
" <li><b>Cores: </b>12</li>\n",
" <li><b>Memory: </b>16.54 GB</li>\n",
"</ul>\n",
"</td>\n",
"</tr>\n",
"</table>"
],
"text/plain": [
"<Client: 'tcp://127.0.0.1:43943' processes=4 threads=12, memory=16.54 GB>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from dask.distributed import Client\n",
"\n",
"client = Client()\n",
"client"
]
},
{
"cell_type": "markdown",
"id": "brutal-hepatitis",
"metadata": {},
"source": [
"## Data"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "mathematical-pharmacology",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fc5fb754dd0>"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.imshow(skeleton0)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "grave-pharmacy",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"chunks: ((4,), (7, 7))\n"
]
},
{
"data": {
"text/html": [
"<table>\n",
"<tr>\n",
"<td>\n",
"<table>\n",
" <thead>\n",
" <tr><td> </td><th> Array </th><th> Chunk </th></tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr><th> Bytes </th><td> 56 B </td> <td> 28 B </td></tr>\n",
" <tr><th> Shape </th><td> (4, 14) </td> <td> (4, 7) </td></tr>\n",
" <tr><th> Count </th><td> 3 Tasks </td><td> 2 Chunks </td></tr>\n",
" <tr><th> Type </th><td> bool </td><td> numpy.ndarray </td></tr>\n",
" </tbody>\n",
"</table>\n",
"</td>\n",
"<td>\n",
"<svg width=\"170\" height=\"93\" style=\"stroke:rgb(0,0,0);stroke-width:1\" >\n",
"\n",
" <!-- Horizontal lines -->\n",
" <line x1=\"0\" y1=\"0\" x2=\"120\" y2=\"0\" style=\"stroke-width:2\" />\n",
" <line x1=\"0\" y1=\"43\" x2=\"120\" y2=\"43\" style=\"stroke-width:2\" />\n",
"\n",
" <!-- Vertical lines -->\n",
" <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"43\" style=\"stroke-width:2\" />\n",
" <line x1=\"60\" y1=\"0\" x2=\"60\" y2=\"43\" />\n",
" <line x1=\"120\" y1=\"0\" x2=\"120\" y2=\"43\" style=\"stroke-width:2\" />\n",
"\n",
" <!-- Colored Rectangle -->\n",
" <polygon points=\"0.0,0.0 120.0,0.0 120.0,43.37894337633637 0.0,43.37894337633637\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n",
"\n",
" <!-- Text -->\n",
" <text x=\"60.000000\" y=\"63.378943\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" >14</text>\n",
" <text x=\"140.000000\" y=\"21.689472\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(0,140.000000,21.689472)\">4</text>\n",
"</svg>\n",
"</td>\n",
"</tr>\n",
"</table>"
],
"text/plain": [
"dask.array<concatenate, shape=(4, 14), dtype=bool, chunksize=(4, 7), chunktype=numpy.ndarray>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"skel = da.block([skeleton0, skeleton0])\n",
"print(\"chunks: \", skel.chunks)\n",
"skel"
]
},
{
"cell_type": "markdown",
"id": "passive-region",
"metadata": {},
"source": [
"## Skeleton analysis"
]
},
{
"cell_type": "markdown",
"id": "intellectual-congress",
"metadata": {},
"source": [
"### skelint"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "combined-quantity",
"metadata": {},
"outputs": [],
"source": [
"ndim = skel.ndim\n",
"\n",
"structure_kernel = np.zeros((3,) * ndim)\n",
"structure_kernel[(1,) * ndim] = 1 # add centre pixel"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "bearing-density",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0., 0., 0.],\n",
" [0., 1., 0.],\n",
" [0., 0., 0.]])"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"structure_kernel"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "configured-struggle",
"metadata": {},
"outputs": [],
"source": [
"skelint, num_features = label(skel, structure=structure_kernel)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "prostate-mention",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"20\n"
]
}
],
"source": [
"print(num_features.compute())"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "interim-regression",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<table>\n",
"<tr>\n",
"<td>\n",
"<table>\n",
" <thead>\n",
" <tr><td> </td><th> Array </th><th> Chunk </th></tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr><th> Bytes </th><td> 224 B </td> <td> 112 B </td></tr>\n",
" <tr><th> Shape </th><td> (4, 14) </td> <td> (4, 7) </td></tr>\n",
" <tr><th> Count </th><td> 42 Tasks </td><td> 2 Chunks </td></tr>\n",
" <tr><th> Type </th><td> int32 </td><td> numpy.ndarray </td></tr>\n",
" </tbody>\n",
"</table>\n",
"</td>\n",
"<td>\n",
"<svg width=\"170\" height=\"93\" style=\"stroke:rgb(0,0,0);stroke-width:1\" >\n",
"\n",
" <!-- Horizontal lines -->\n",
" <line x1=\"0\" y1=\"0\" x2=\"120\" y2=\"0\" style=\"stroke-width:2\" />\n",
" <line x1=\"0\" y1=\"43\" x2=\"120\" y2=\"43\" style=\"stroke-width:2\" />\n",
"\n",
" <!-- Vertical lines -->\n",
" <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"43\" style=\"stroke-width:2\" />\n",
" <line x1=\"60\" y1=\"0\" x2=\"60\" y2=\"43\" />\n",
" <line x1=\"120\" y1=\"0\" x2=\"120\" y2=\"43\" style=\"stroke-width:2\" />\n",
"\n",
" <!-- Colored Rectangle -->\n",
" <polygon points=\"0.0,0.0 120.0,0.0 120.0,43.37894337633637 0.0,43.37894337633637\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n",
"\n",
" <!-- Text -->\n",
" <text x=\"60.000000\" y=\"63.378943\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" >14</text>\n",
" <text x=\"140.000000\" y=\"21.689472\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(0,140.000000,21.689472)\">4</text>\n",
"</svg>\n",
"</td>\n",
"</tr>\n",
"</table>"
],
"text/plain": [
"dask.array<getitem, shape=(4, 14), dtype=int32, chunksize=(4, 7), chunktype=numpy.ndarray>"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"skelint"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "ongoing-contract",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0],\n",
" [ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0],\n",
" [ 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0],\n",
" [ 4, 5, 6, 7, 8, 9, 10, 14, 15, 16, 17, 18, 19, 20]],\n",
" dtype=int32)"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"skelint.compute()"
]
},
{
"cell_type": "markdown",
"id": "laden-tenant",
"metadata": {},
"source": [
"### degree_image"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "executed-recipient",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[1. 1. 1.]\n",
" [1. 0. 1.]\n",
" [1. 1. 1.]]\n"
]
}
],
"source": [
"degree_kernel = np.ones((3,) * ndim)\n",
"degree_kernel[(1,) * ndim] = 0 # remove centre pixel\n",
"\n",
"print(degree_kernel)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "perfect-audience",
"metadata": {},
"outputs": [],
"source": [
"from dask_image.ndfilters import convolve\n",
"\n",
"degree_image = convolve(skel.astype(int), degree_kernel,\n",
" mode='constant') * skel"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "previous-grass",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<table>\n",
"<tr>\n",
"<td>\n",
"<table>\n",
" <thead>\n",
" <tr><td> </td><th> Array </th><th> Chunk </th></tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr><th> Bytes </th><td> 448 B </td> <td> 224 B </td></tr>\n",
" <tr><th> Shape </th><td> (4, 14) </td> <td> (4, 7) </td></tr>\n",
" <tr><th> Count </th><td> 19 Tasks </td><td> 2 Chunks </td></tr>\n",
" <tr><th> Type </th><td> int64 </td><td> numpy.ndarray </td></tr>\n",
" </tbody>\n",
"</table>\n",
"</td>\n",
"<td>\n",
"<svg width=\"170\" height=\"93\" style=\"stroke:rgb(0,0,0);stroke-width:1\" >\n",
"\n",
" <!-- Horizontal lines -->\n",
" <line x1=\"0\" y1=\"0\" x2=\"120\" y2=\"0\" style=\"stroke-width:2\" />\n",
" <line x1=\"0\" y1=\"43\" x2=\"120\" y2=\"43\" style=\"stroke-width:2\" />\n",
"\n",
" <!-- Vertical lines -->\n",
" <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"43\" style=\"stroke-width:2\" />\n",
" <line x1=\"60\" y1=\"0\" x2=\"60\" y2=\"43\" />\n",
" <line x1=\"120\" y1=\"0\" x2=\"120\" y2=\"43\" style=\"stroke-width:2\" />\n",
"\n",
" <!-- Colored Rectangle -->\n",
" <polygon points=\"0.0,0.0 120.0,0.0 120.0,43.37894337633637 0.0,43.37894337633637\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n",
"\n",
" <!-- Text -->\n",
" <text x=\"60.000000\" y=\"63.378943\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" >14</text>\n",
" <text x=\"140.000000\" y=\"21.689472\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(0,140.000000,21.689472)\">4</text>\n",
"</svg>\n",
"</td>\n",
"</tr>\n",
"</table>"
],
"text/plain": [
"dask.array<mul, shape=(4, 14), dtype=int64, chunksize=(4, 7), chunktype=numpy.ndarray>"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"degree_image"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "deadly-healing",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fc5fb4c2ed0>"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.imshow(degree_image)"
]
},
{
"cell_type": "markdown",
"id": "designing-information",
"metadata": {},
"source": [
"### skeleton graph"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "wanted-spotlight",
"metadata": {},
"outputs": [],
"source": [
"def _num_edges(skel):\n",
" degree_kernel = np.ones((3,) * ndim)\n",
" degree_kernel[(1,) * ndim] = 0 # remove centre pixel\n",
" degree_image = scipy.ndimage.convolve(skel.astype(int),\n",
" degree_kernel,\n",
" mode='constant') * skel\n",
" num_edges = np.sum(degree_image)\n",
" return int(num_edges)\n",
"\n",
"@delayed\n",
"def skeleton_graph_func(skelint, spacing=1):\n",
" ndim = skelint.ndim\n",
" spacing = np.ones(ndim, dtype=float) * spacing\n",
" num_edges = _num_edges(skelint.astype(bool))\n",
" padded_skelint = pad(skelint, 0) # pad image to prevent looparound errors\n",
" steps, distances = raveled_steps_to_neighbors(padded_skelint.shape, ndim,\n",
" spacing=spacing)\n",
"\n",
" # from function skan.csr._pixel_graph\n",
" row = np.empty(num_edges, dtype=int)\n",
" col = np.empty(num_edges, dtype=int)\n",
" data = np.empty(num_edges, dtype=float)\n",
" k = _write_pixel_graph(padded_skelint, steps, distances, row, col, data)\n",
"\n",
" return pd.DataFrame({\"row\": row, \"col\": col, \"data\": data})"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "collect-composition",
"metadata": {},
"outputs": [],
"source": [
"# Proposed slices_from_chunks_overlap function \n",
"# Mofified from slices_from_chunks from dask.array.core\n",
"from itertools import product\n",
"from dask.array.slicing import cached_cumsum\n",
"\n",
"\n",
"def slices_from_chunks_overlap(chunks, array_shape, depth=1):\n",
" \"\"\"Translate chunks tuple to a set of slices in product order\n",
"\n",
" Parameters\n",
" ----------\n",
" chunks : tuple\n",
" The chunks of the corresponding dask array.\n",
" array_shape : tuple\n",
" Shape of the corresponding dask array.\n",
" depth : int\n",
" The number of pixels to overlap, providing we're not at the array edge.\n",
"\n",
" Example\n",
" -------\n",
" >>> slices_from_chunks_overlap(((4,), (7, 7)), (4, 14), depth=1) # doctest: +NORMALIZE_WHITESPACE\n",
" [(slice(0, 5, None), slice(0, 8, None)),\n",
" (slice(0, 5, None), slice(6, 15, None))]\n",
" \"\"\"\n",
" cumdims = [cached_cumsum(bds, initial_zero=True) for bds in chunks]\n",
"\n",
" slices = []\n",
" for starts, shapes in zip(cumdims, chunks):\n",
" inner_slices = []\n",
" for s, dim, maxshape in zip(starts, shapes, array_shape):\n",
" slice_start = s\n",
" slice_stop = s + dim\n",
" if slice_start > 0:\n",
" slice_start -= depth\n",
" if slice_stop >= maxshape:\n",
" slice_stop += depth\n",
" inner_slices.append(slice(slice_start, slice_stop))\n",
" slices.append(inner_slices)\n",
" \n",
" return list(product(*slices))\n"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "automatic-retention",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"48\n"
]
},
{
"data": {
"text/html": [
"<div><strong>Dask DataFrame Structure:</strong></div>\n",
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>row</th>\n",
" <th>col</th>\n",
" <th>data</th>\n",
" </tr>\n",
" <tr>\n",
" <th>npartitions=2</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th></th>\n",
" <td>int64</td>\n",
" <td>int64</td>\n",
" <td>float64</td>\n",
" </tr>\n",
" <tr>\n",
" <th></th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th></th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>\n",
"<div>Dask Name: concat, 54 tasks</div>"
],
"text/plain": [
"Dask DataFrame Structure:\n",
" row col data\n",
"npartitions=2 \n",
" int64 int64 float64\n",
" ... ... ...\n",
" ... ... ...\n",
"Dask Name: concat, 54 tasks"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import functools\n",
"import operator\n",
"\n",
"import numpy as np\n",
"import dask.dataframe as dd\n",
"\n",
"\n",
"image = skelint\n",
"\n",
"block_iter = zip(\n",
" np.ndindex(*image.numblocks),\n",
" map(functools.partial(operator.getitem, image),\n",
" slices_from_chunks_overlap(image.chunks, image.shape, depth=1))\n",
")\n",
"\n",
"meta = dd.utils.make_meta([('row', np.int64), ('col', np.int64), ('data', np.float64)]) # it's very important to include meta\n",
"intermediate_results = [dd.from_delayed(skeleton_graph_func(block), meta=meta) for _, block in block_iter]\n",
"results = dd.concat(intermediate_results)\n",
"\n",
"print(len(results))\n",
"results"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "plastic-lebanon",
"metadata": {},
"outputs": [],
"source": [
"# drop duplicates from the results\n",
"results = results.drop_duplicates()"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "corporate-opera",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<21x21 sparse matrix of type '<class 'numpy.float64'>'\n",
"\twith 46 stored elements in Compressed Sparse Row format>"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# computes dask results, brings everything into memory before creating sparse graph\n",
"k = len(results)\n",
"row = np.array(results['row'])\n",
"col = np.array(results['col'])\n",
"data = np.array(results['data'])\n",
"\n",
"graph = sparse.coo_matrix((data[:k], (row[:k], col[:k]))).tocsr()\n",
"graph"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "nearby-vector",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.0\n",
"1.4142135623730951\n"
]
}
],
"source": [
"# sanity check\n",
"print(np.min(graph.todense()))\n",
"print(np.max(graph.todense())) # max should be 1.41421, NOT 2"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "later-lawrence",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fc5d2b687d0>"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.xticks(ticks=np.arange(0, 21, 1))\n",
"plt.yticks(ticks=np.arange(0, 21, 1))\n",
"plt.imshow(graph.todense())"
]
},
{
"cell_type": "markdown",
"id": "impossible-protection",
"metadata": {},
"source": [
"## Skeleton branch statistics"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "effective-example",
"metadata": {},
"outputs": [],
"source": [
"from skan import Skeleton\n",
"from skan._testdata import skeleton1"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "fatal-constitutional",
"metadata": {},
"outputs": [],
"source": [
"# Make the input boolean skeleton is DIFFERENT (smaller) data than the real deal\n",
"skel_obj = Skeleton(skeleton1) # initialize with dummy data\n",
"skel_obj.skeleton_image = skel\n",
"skel_obj.graph = graph # don't forget to update nbgraph, too"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "sound-issue",
"metadata": {},
"outputs": [],
"source": [
"# Can specify voxel spacing if need be\n",
"# skel_obj.spacing = [1, 1] # the default is skel_obj.spacing = [1, 1]"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "valuable-telephone",
"metadata": {},
"outputs": [],
"source": [
"# Update skel_obj.degrees (this thing is used way more than degrees_image)\n",
"nonzero_degree_values = degree_image[degree_image > 0].compute() # triggers Dask computation\n",
"degrees = np.concatenate((np.array([0]), nonzero_degree_values))\n",
"\n",
"skel_obj.degrees = degrees"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "bacterial-aquarium",
"metadata": {},
"outputs": [],
"source": [
"# May as well update skel_obj.degrees_image too, but this isn't really used for anything (except visualization)\n",
"skel_obj.degrees_image = degree_image"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "adequate-preservation",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/genevieve/anaconda3/envs/microfil/lib/python3.7/site-packages/dask/array/core.py:1467: FutureWarning: The `numpy.argsort` function is not implemented by Dask array. You may want to use the da.map_blocks function or something similar to silence this warning. Your code may stop working in a future release.\n",
" FutureWarning,\n"
]
}
],
"source": [
"# Do I need to do something to make skel_obj.nbgraph updated?\n",
"# node_prop for Skeleton class, so we can get the NBGraph (numba-ified graph)\n",
"nonzero_pixel_ids = skelint[skelint > 0]\n",
"sorted_indices = np.argsort(nonzero_pixel_ids) # coerces to a numpy array, Dask doesn't implement argsort()\n",
"\n",
"raw_data = da.random.random(skelint.shape)\n",
"nonzero_pixel_intensity = raw_data[skelint > 0]\n",
"nonzero_pixel_intensity.compute_chunk_sizes() # important, otherwise the indexing with sorted_indices thinks it's out of bounds\n",
"node_props = nonzero_pixel_intensity[sorted_indices].compute() # trigger Dask computation\n",
"node_props = np.concatenate((np.array([0]), node_props)) # add a weird dummy index - is this right?"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "extended-raleigh",
"metadata": {},
"outputs": [],
"source": [
"# If you have a raw data image\n",
"raw_data = da.random.random(skelint.shape) # here we approximate it with a random array\n",
"skel_obj.source_image = raw_data "
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "raised-globe",
"metadata": {},
"outputs": [],
"source": [
"from skan.csr import csr_to_nbgraph\n",
"\n",
"nbgraph = csr_to_nbgraph(graph, node_props=None) # node_props=None is the default\n",
"# Is this even accurate when we pass in node_props? It doesn't look like there's any sanity checking going on...\n",
"# nbgraph = csr_to_nbgraph(graph, node_props=node_props) # node_props=None is the default\n",
"\n",
"skel_obj.nbgraph = nbgraph"
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "antique-absolute",
"metadata": {},
"outputs": [],
"source": [
"# This one is really important! \n",
"# Summarize won't give you good results unless this is right\n",
"# also need to update skel_obj.paths\n",
"from skan.csr import _build_skeleton_path_graph\n",
"\n",
"_buffer_size_offset = None # I don't know what _buffer_size_offset is, no docstring info about it\n",
"paths = _build_skeleton_path_graph(nbgraph, _buffer_size_offset=_buffer_size_offset)\n",
"skel_obj.paths = paths\n",
"# also need to update skel_obj.n_paths\n",
"n_paths = paths.shape[0]\n",
"skel_obj.n_paths = n_paths"
]
},
{
"cell_type": "code",
"execution_count": 38,
"id": "novel-tourism",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<class 'numpy.ndarray'>\n",
"21\n"
]
}
],
"source": [
"# the transpose appears to trigger Dask computation\n",
"pixel_indices = np.concatenate(([[0.] * ndim],\n",
" np.transpose(np.nonzero(skel))), axis=0)\n",
"print(type(pixel_indices)) # a numpy array\n",
"print(len(pixel_indices))"
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "three-trace",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<class 'numpy.ndarray'>\n",
"21\n"
]
}
],
"source": [
"# Very important\n",
"# must also overwrite skel_obj.coordinates\n",
"# ---\n",
"# the transpose appears to trigger Dask computation\n",
"pixel_indices = np.concatenate(([[0.] * ndim],\n",
" np.transpose(np.nonzero(skel))), axis=0)\n",
"print(type(pixel_indices)) # a numpy array\n",
"print(len(pixel_indices))\n",
"# ---\n",
"\n",
"skel_obj.coordinates = pixel_indices"
]
},
{
"cell_type": "code",
"execution_count": 40,
"id": "velvet-spring",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2. 1. 3. 3.]\n",
"[2. 1.41421356 1. 1.41421356]\n"
]
}
],
"source": [
"# # also need to update skel_obj.distances. \n",
"# The path_lengths method should do that for us.\n",
"print(skel_obj.distances)\n",
"skel_obj.path_lengths()\n",
"print(skel_obj.distances)"
]
},
{
"cell_type": "code",
"execution_count": 41,
"id": "acoustic-passing",
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "arrays must all be same length",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-41-d4550f544736>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mskan\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0msummarize\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mstatistics\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msummarize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mskel_obj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0mstatistics\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/GitHub/skan/skan/csr.py\u001b[0m in \u001b[0;36msummarize\u001b[0;34m(skel)\u001b[0m\n\u001b[1;32m 502\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msqrt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcoords_real_dst\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mcoords_real_src\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0;36m2\u001b[0m \u001b[0;34m@\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mones\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 503\u001b[0m )\n\u001b[0;32m--> 504\u001b[0;31m \u001b[0mdf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mDataFrame\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msummary\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 505\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mdf\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 506\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/envs/microfil/lib/python3.7/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, data, index, columns, dtype, copy)\u001b[0m\n\u001b[1;32m 527\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 528\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdict\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 529\u001b[0;31m \u001b[0mmgr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0minit_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcolumns\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 530\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMaskedArray\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 531\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnumpy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmrecords\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mmrecords\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/envs/microfil/lib/python3.7/site-packages/pandas/core/internals/construction.py\u001b[0m in \u001b[0;36minit_dict\u001b[0;34m(data, index, columns, dtype)\u001b[0m\n\u001b[1;32m 285\u001b[0m \u001b[0marr\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mis_datetime64tz_dtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0marr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0marr\u001b[0m \u001b[0;32min\u001b[0m \u001b[0marrays\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 286\u001b[0m ]\n\u001b[0;32m--> 287\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0marrays_to_mgr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marrays\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata_names\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcolumns\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 288\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 289\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/envs/microfil/lib/python3.7/site-packages/pandas/core/internals/construction.py\u001b[0m in \u001b[0;36marrays_to_mgr\u001b[0;34m(arrays, arr_names, index, columns, dtype, verify_integrity)\u001b[0m\n\u001b[1;32m 78\u001b[0m \u001b[0;31m# figure out the index, if necessary\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 79\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mindex\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 80\u001b[0;31m \u001b[0mindex\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mextract_index\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marrays\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 81\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 82\u001b[0m \u001b[0mindex\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mensure_index\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/envs/microfil/lib/python3.7/site-packages/pandas/core/internals/construction.py\u001b[0m in \u001b[0;36mextract_index\u001b[0;34m(data)\u001b[0m\n\u001b[1;32m 399\u001b[0m \u001b[0mlengths\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mraw_lengths\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 400\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlengths\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 401\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"arrays must all be same length\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 402\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 403\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mhave_dicts\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mValueError\u001b[0m: arrays must all be same length"
]
}
],
"source": [
"from skan import summarize\n",
"\n",
"statistics = summarize(skel_obj)\n",
"statistics"
]
},
{
"cell_type": "code",
"execution_count": 42,
"id": "removed-india",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"> \u001b[0;32m/home/genevieve/anaconda3/envs/microfil/lib/python3.7/site-packages/pandas/core/internals/construction.py\u001b[0m(401)\u001b[0;36mextract_index\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32m 399 \u001b[0;31m \u001b[0mlengths\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mraw_lengths\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0m\u001b[0;32m 400 \u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlengths\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0m\u001b[0;32m--> 401 \u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"arrays must all be same length\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0m\u001b[0;32m 402 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0m\u001b[0;32m 403 \u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mhave_dicts\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0m\n",
"ipdb> len(lengths)\n",
"2\n",
"ipdb> len(raw_lengths)\n",
"16\n",
"ipdb> raw_lengths\n",
"[10, 10, 10, 4, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]\n",
"ipdb> q\n"
]
}
],
"source": [
"%debug"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "equivalent-eclipse",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 210,
"id": "altered-compromise",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([1, 1])"
]
},
"execution_count": 210,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"skel_obj.coordinates\n",
"skel_obj.distances\n",
"skel_obj.n_paths\n",
"skel_obj.paths"
]
},
{
"cell_type": "markdown",
"id": "friendly-inspector",
"metadata": {},
"source": [
"`Skeleton` class attributes:\n",
"\n",
"- coordinates - needs to be updated\n",
"- degrees - updated\n",
"- degrees_image - updated\n",
"- distances - needs to be updated\n",
"- graph - updated\n",
"- n_paths - needs to be updated\n",
"- nbgraph - updated\n",
"- paths - needs to be updated\n",
"- paths_list - method\n",
"- skeleton_image - updated\n",
"- source_image - updated\n",
"- spacing - updated\n",
"\n",
"`Skeleton` class methods:\n",
"\n",
"- path - method\n",
"- path_coordinates - method\n",
"- path_lengths - method\n",
"- path_means - method\n",
"- path_stdev - method\n",
"- path_with_data - method\n"
]
},
{
"cell_type": "markdown",
"id": "cooperative-removal",
"metadata": {},
"source": [
"# Summarize method guts"
]
},
{
"cell_type": "code",
"execution_count": 50,
"id": "known-passenger",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]\n"
]
}
],
"source": [
"from scipy.sparse import csgraph\n",
"\n",
"coordinates = pixel_indices\n",
"ndim = coordinates.shape[1]\n",
"_, skeleton_ids = csgraph.connected_components(graph, directed=False)\n",
"\n",
"print(skeleton_ids)"
]
},
{
"cell_type": "code",
"execution_count": 55,
"id": "hungry-australian",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ 1, 2, 3, 3, 6, 3, 7, 3, 8, 4, 5, 6, 8, 9, 10, 14, 15,\n",
" 16, 11, 12, 13, 13, 17, 13, 18, 18, 19, 20], dtype=int32)"
]
},
"execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"paths.indices"
]
},
{
"cell_type": "code",
"execution_count": 57,
"id": "fleet-baghdad",
"metadata": {},
"outputs": [],
"source": [
"from skan.csr import _build_skeleton_path_graph\n",
"\n",
"_buffer_size_offset = None # I don't know what _buffer_size_offset is, no docstring info about it\n",
"paths = _build_skeleton_path_graph(nbgraph, _buffer_size_offset=_buffer_size_offset)\n",
"n_paths = paths.shape[0] # you need this to compute the length of the distances array later on"
]
},
{
"cell_type": "code",
"execution_count": 67,
"id": "amber-rhythm",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[ 1 3 3 3 4 8 11 13 13 18]\n",
"[ 3 6 7 8 6 16 13 17 18 20]\n"
]
}
],
"source": [
"endpoints_src = paths.indices[paths.indptr[:-1]]\n",
"endpoints_dst = paths.indices[paths.indptr[1:] - 1]\n",
"\n",
"print(endpoints_src)\n",
"print(endpoints_dst)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "reflected-bhutan",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 74,
"id": "august-federation",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"None\n"
]
}
],
"source": [
"import numpy as np\n",
"from skan.csr import _compute_distances\n",
"\n",
"distances = np.empty(n_paths, dtype=float)\n",
"distances = _compute_distances(nbgraph, paths.indptr, paths.indices, distances)\n",
"\n",
"print(distances) # why is this None, it shouldn't be None"
]
},
{
"cell_type": "code",
"execution_count": 76,
"id": "toxic-confidence",
"metadata": {},
"outputs": [],
"source": [
"summary = {}\n",
"summary['skeleton-id'] = skeleton_ids[endpoints_src]\n",
"summary['node-id-src'] = endpoints_src\n",
"summary['node-id-dst'] = endpoints_dst\n",
"summary['branch-distance'] = distances"
]
},
{
"cell_type": "code",
"execution_count": 77,
"id": "hundred-german",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'skeleton-id': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32),\n",
" 'node-id-src': array([ 1, 3, 3, 3, 4, 8, 11, 13, 13, 18], dtype=int32),\n",
" 'node-id-dst': array([ 3, 6, 7, 8, 6, 16, 13, 17, 18, 20], dtype=int32),\n",
" 'branch-distance': None}"
]
},
"execution_count": 77,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"summary"
]
},
{
"cell_type": "code",
"execution_count": 83,
"id": "identified-reality",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0, 1, 1, 2, 2, 4, 4, 1, 2, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 2, 1])"
]
},
"execution_count": 83,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"degrees"
]
},
{
"cell_type": "code",
"execution_count": 85,
"id": "following-grocery",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1 2 1 2 2 2 2 2 2 1]\n"
]
}
],
"source": [
"deg_src = degrees[endpoints_src]\n",
"deg_dst = degrees[endpoints_dst]\n",
"kind = np.full(deg_src.shape, 2) # default: junction-to-junction\n",
"kind[(deg_src == 1) | (deg_dst == 1)] = 1 # tip-junction\n",
"kind[(deg_src == 1) & (deg_dst == 1)] = 0 # tip-tip\n",
"kind[endpoints_src == endpoints_dst] = 3 # cycle\n",
"\n",
"print(kind)"
]
},
{
"cell_type": "code",
"execution_count": 87,
"id": "fleet-fourth",
"metadata": {},
"outputs": [],
"source": [
"summary['branch-type'] = kind\n",
"summary['mean-pixel-value'] = skel_obj.path_means()\n",
"summary['stdev-pixel-value'] = skel_obj.path_stdev()"
]
},
{
"cell_type": "code",
"execution_count": 88,
"id": "analyzed-hollow",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'skeleton-id': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32),\n",
" 'node-id-src': array([ 1, 3, 3, 3, 4, 8, 11, 13, 13, 18], dtype=int32),\n",
" 'node-id-dst': array([ 3, 6, 7, 8, 6, 16, 13, 17, 18, 20], dtype=int32),\n",
" 'branch-distance': None,\n",
" 'branch-type': array([1, 2, 1, 2, 2, 2, 2, 2, 2, 1]),\n",
" 'mean-pixel-value': array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]),\n",
" 'stdev-pixel-value': array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])}"
]
},
"execution_count": 88,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"summary"
]
},
{
"cell_type": "code",
"execution_count": 90,
"id": "frank-movement",
"metadata": {},
"outputs": [],
"source": [
"for i in range(ndim): # keep loops separate for best insertion order\n",
" summary[f'image-coord-src-{i}'] = coordinates[endpoints_src, i]\n",
"for i in range(ndim):\n",
" summary[f'image-coord-dst-{i}'] = coordinates[endpoints_dst, i]\n",
"coords_real_src = coordinates[endpoints_src] * skel_obj.spacing\n",
"for i in range(ndim):\n",
" summary[f'coord-src-{i}'] = coords_real_src[:, i]\n",
"coords_real_dst = coordinates[endpoints_dst] * skel_obj.spacing\n",
"for i in range(ndim):\n",
" summary[f'coord-dst-{i}'] = coords_real_dst[:, i]\n",
"summary['euclidean-distance'] = (\n",
" np.sqrt((coords_real_dst - coords_real_src)**2 @ np.ones(ndim))\n",
")\n",
"df = pd.DataFrame(summary)"
]
},
{
"cell_type": "code",
"execution_count": 91,
"id": "designing-niger",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>skeleton-id</th>\n",
" <th>node-id-src</th>\n",
" <th>node-id-dst</th>\n",
" <th>branch-distance</th>\n",
" <th>branch-type</th>\n",
" <th>mean-pixel-value</th>\n",
" <th>stdev-pixel-value</th>\n",
" <th>image-coord-src-0</th>\n",
" <th>image-coord-src-1</th>\n",
" <th>image-coord-dst-0</th>\n",
" <th>image-coord-dst-1</th>\n",
" <th>coord-src-0</th>\n",
" <th>coord-src-1</th>\n",
" <th>coord-dst-0</th>\n",
" <th>coord-dst-1</th>\n",
" <th>euclidean-distance</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>None</td>\n",
" <td>1</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>6</td>\n",
" <td>None</td>\n",
" <td>2</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>2.0</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>2.0</td>\n",
" <td>10.0</td>\n",
" <td>7.071068</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>7</td>\n",
" <td>None</td>\n",
" <td>1</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>3.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>3.0</td>\n",
" <td>0.0</td>\n",
" <td>3.605551</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>8</td>\n",
" <td>None</td>\n",
" <td>2</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>2.828427</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" <td>6</td>\n",
" <td>None</td>\n",
" <td>2</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>10.0</td>\n",
" <td>2.0</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>10.0</td>\n",
" <td>2.0</td>\n",
" <td>10.0</td>\n",
" <td>1.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>1</td>\n",
" <td>8</td>\n",
" <td>16</td>\n",
" <td>None</td>\n",
" <td>2</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>9.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>9.0</td>\n",
" <td>8.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>1</td>\n",
" <td>11</td>\n",
" <td>13</td>\n",
" <td>None</td>\n",
" <td>2</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>4.0</td>\n",
" <td>3.0</td>\n",
" <td>6.0</td>\n",
" <td>3.0</td>\n",
" <td>4.0</td>\n",
" <td>3.0</td>\n",
" <td>6.0</td>\n",
" <td>2.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>1</td>\n",
" <td>13</td>\n",
" <td>17</td>\n",
" <td>None</td>\n",
" <td>2</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>6.0</td>\n",
" <td>3.0</td>\n",
" <td>10.0</td>\n",
" <td>3.0</td>\n",
" <td>6.0</td>\n",
" <td>3.0</td>\n",
" <td>10.0</td>\n",
" <td>4.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>1</td>\n",
" <td>13</td>\n",
" <td>18</td>\n",
" <td>None</td>\n",
" <td>2</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>6.0</td>\n",
" <td>3.0</td>\n",
" <td>11.0</td>\n",
" <td>3.0</td>\n",
" <td>6.0</td>\n",
" <td>3.0</td>\n",
" <td>11.0</td>\n",
" <td>5.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>1</td>\n",
" <td>18</td>\n",
" <td>20</td>\n",
" <td>None</td>\n",
" <td>1</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>11.0</td>\n",
" <td>3.0</td>\n",
" <td>13.0</td>\n",
" <td>3.0</td>\n",
" <td>11.0</td>\n",
" <td>3.0</td>\n",
" <td>13.0</td>\n",
" <td>2.000000</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" skeleton-id node-id-src node-id-dst branch-distance branch-type \\\n",
"0 1 1 3 None 1 \n",
"1 1 3 6 None 2 \n",
"2 1 3 7 None 1 \n",
"3 1 3 8 None 2 \n",
"4 1 4 6 None 2 \n",
"5 1 8 16 None 2 \n",
"6 1 11 13 None 2 \n",
"7 1 13 17 None 2 \n",
"8 1 13 18 None 2 \n",
"9 1 18 20 None 1 \n",
"\n",
" mean-pixel-value stdev-pixel-value image-coord-src-0 image-coord-src-1 \\\n",
"0 1.0 0.0 0.0 3.0 \n",
"1 1.0 0.0 1.0 3.0 \n",
"2 1.0 0.0 1.0 3.0 \n",
"3 1.0 0.0 1.0 3.0 \n",
"4 1.0 0.0 1.0 10.0 \n",
"5 1.0 0.0 3.0 1.0 \n",
"6 1.0 0.0 3.0 4.0 \n",
"7 1.0 0.0 3.0 6.0 \n",
"8 1.0 0.0 3.0 6.0 \n",
"9 1.0 0.0 3.0 11.0 \n",
"\n",
" image-coord-dst-0 image-coord-dst-1 coord-src-0 coord-src-1 \\\n",
"0 1.0 3.0 0.0 3.0 \n",
"1 2.0 10.0 1.0 3.0 \n",
"2 3.0 0.0 1.0 3.0 \n",
"3 3.0 1.0 1.0 3.0 \n",
"4 2.0 10.0 1.0 10.0 \n",
"5 3.0 9.0 3.0 1.0 \n",
"6 3.0 6.0 3.0 4.0 \n",
"7 3.0 10.0 3.0 6.0 \n",
"8 3.0 11.0 3.0 6.0 \n",
"9 3.0 13.0 3.0 11.0 \n",
"\n",
" coord-dst-0 coord-dst-1 euclidean-distance \n",
"0 1.0 3.0 1.000000 \n",
"1 2.0 10.0 7.071068 \n",
"2 3.0 0.0 3.605551 \n",
"3 3.0 1.0 2.828427 \n",
"4 2.0 10.0 1.000000 \n",
"5 3.0 9.0 8.000000 \n",
"6 3.0 6.0 2.000000 \n",
"7 3.0 10.0 4.000000 \n",
"8 3.0 11.0 5.000000 \n",
"9 3.0 13.0 2.000000 "
]
},
"execution_count": 91,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "exceptional-dictionary",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.7.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment