Implementation of Dijkstra's Shortest Path algorithm on 3D images.
Project description
dijkstra3d
Dijkstra's Shortest Path variants for 6, 18, and 26-connected 3D Image Volumes or 4 and 8-connected 2D images.
import dijkstra3d
import numpy as np
field = np.ones((512, 512, 512), dtype=np.int32)
source = (0,0,0)
target = (511, 511, 511)
# path is an [N,3] numpy array i.e. a list of x,y,z coordinates
# terminates early, default is 26 connected
path = dijkstra3d.dijkstra(field, source, target, connectivity=26)
path = dijkstra3d.dijkstra(field, source, target, bidirectional=True) # 2x memory usage, faster
# Use distance from target as a heuristic (A* search)
# Does nothing if bidirectional=True (it's just not implemented)
path = dijkstra3d.dijkstra(field, source, target, compass=True)
parents = dijkstra3d.parental_field(field, source=(0,0,0), connectivity=6) # default is 26 connected
path = dijkstra3d.path_from_parents(parents, target=(511, 511, 511))
print(path.shape)
dist_field = dijkstra3d.euclidean_distance_field(field, source=(0,0,0), anisotropy=(4,4,40))
dist_field = dijkstra3d.distance_field(field, source=(0,0,0))
Perform dijkstra's shortest path algorithm on a 3D image grid. Vertices are voxels and edges are the nearest neighbors. For 6 connected images, these are the faces of the voxel, 18 is faces and edges, 26 is faces, edges, and corners. For given input voxels A and B, the edge weight from A to B is B and from B to A is A. All weights must be non-negative (incl. negative zero).
What Problem does this Package Solve?
This package was developed in the course of exploring TEASAR skeletonization of 3D image volumes (now available in Kimimaro). Other commonly available packages implementing Dijkstra used matricies or object graphs as their underlying implementation. In either case, these generic graph packages necessitate explicitly creating the graph's edges and vertices, which turned out to be a significant computational cost compared with the search time. Additionally, some implementations required memory quadratic in the number of vertices (e.g. an NxN matrix for N nodes) which becomes prohibitive for large arrays. In some cases, a compressed sparse matrix representation was used to remain within memory limits.
Neither of graph construction nor quadratic memory pressure are necessary for an image analysis application. The edges between voxels (3D pixels) are regular and implicit in the rectangular structure of the image. Additionally, the cost of each edge can be stored a single time instead of 26 times in contiguous uncompressed memory regions for faster performance.
Available Dijkstra Variants
The following variants are available in 2D and 3D:
- dijkstra - Shortest path between source and target. Early termination on finding the target. Bidirectional version available.
- parental_field / query_shortest_path - Compute shortest path between source and all targets. Use query_shortest_path to make repeated queries against the result set.
- euclidean_distance_field - Given a boolean label field and a source vertex, compute the anisotropic euclidean distance from the source to all labeled vertices.
- distance_field - Given a numerical field, for each directed edge from adjacent voxels A and B, use B as the edge weight. In this fashion, compute the distance from a source point for all finite voxels.
C++ Use
#include <vector>
#include "dijkstra3d.hpp"
// 3d array represented as 1d array
float* labels = new float[512*512*512]();
// x + sx * y + sx * sy * z
int source = 0 + 512 * 5 + 512 * 512 * 3; // coordinate <0, 5, 3>
int target = 128 + 512 * 128 + 512 * 512 * 128; // coordinate <128, 128, 128>
vector<unsigned int> path = dijkstra::dijkstra3d<float>(
labels, /*sx=*/512, /*sy=*/512, /*sz=*/512,
source, target, /*connectivity=*/26 // 26 is default
);
vector<unsigned int> path = dijkstra::bidirectional_dijkstra3d<float>(
labels, /*sx=*/512, /*sy=*/512, /*sz=*/512,
source, target, /*connectivity=*/26 // 26 is default
);
// A* search using a distance to target heuristic
vector<unsigned int> path = dijkstra::compass_guided_dijkstra3d<float>(
labels, /*sx=*/512, /*sy=*/512, /*sz=*/512,
source, target, /*connectivity=*/26 // 26 is default
);
uint32_t* parents = dijkstra::parental_field3d<float>(
labels, /*sx=*/512, /*sy=*/512, /*sz=*/512,
source, /*connectivity=*/26 // 26 is default
);
vector<unsigned int> path = dijkstra::query_shortest_path(parents, target);
float* field = dijkstra::euclidean_distance_field3d<float>(
labels,
/*sx=*/512, /*sy=*/512, /*sz=*/512,
/*wx=*/4, /*wy=*/4, /*wz=*/40,
source
);
float* field = dijkstra::distance_field3d<float>(labels, /*sx=*/512, /*sy=*/512, /*sz=*/512, source);
Python pip
Binary Installation
pip install dijkstra3d
Python pip
Source Installation
Requires a C++ compiler.
pip install numpy
pip install dijkstra3d
Python Direct Installation
Requires a C++ compiler.
git clone https://github.com/seung-lab/dijkstra3d.git
cd dijkstra3d
virtualenv -p python3 venv
source venv/bin/activate
pip install -r requirements.txt
python setup.py develop
Performance
I ran three algorithms on a field of ones from the bottom left corner to the top right corner of a 512x512x512 int8 image using a 3.7 GHz Intel i7-4920K CPU. Unidirectional search takes about 42 seconds (3.2 MVx/sec) with a maximum memory usage of about 1300 MB. In the unidirectional case, this test forces the algorithm to process nearly all of the volume (dijkstra aborts early when the target is found). In the bidirectional case, the volume is processed in about 11.8 seconds (11.3 MVx/sec) with a peak memory usage of about 2300 MB. The A* version processes the volume in 0.5 seconds (268.4 MVx/sec) with an identical memory profile to unidirectional search. A* works very well in this simple case, but may not be superior in all configurations.
Theoretical unidirectional memory allocation breakdown: 128 MB source image, 512 MB distance field, 512 MB parents field (1152 MB). Theoretical bidirectional memory allocation breakdown: 128 MB source image, 2x 512 distance field, 2x 512 MB parental field (2176 MB).
Fig. 1: A benchmark of dijkstra.dijkstra run on a 5123 voxel field of ones from bottom left source to top right target. (black) unidirectional search (blue) bidirectional search (red) A* search aka compass=True
.
import numpy as np
import time
import dijkstra3d
field = np.ones((512,512,512), order='F', dtype=np.int8)
source = (0,0,0)
target = (511,511,511)
path = dijkstra3d.dijkstra(field, source, target) # black line
path = dijkstra3d.dijkstra(field, source, target, bidirectional=True) # blue line
path = dijkstra3d.dijkstra(field, source, target, compass=True) # red line
Fig. 2: A benchmark of dijkstra.dijkstra run on a 503 voxel field of random integers of increasing variation from random source to random target. (blue/squares) unidirectional search (yellow/triangles) bidirectional search (red/diamonds) A* search aka compass=True
.
import numpy as np
import time
import dijkstra3d
N = 250
sx, sy, sz = 50, 50, 50
def trial(bi, compass):
for n in range(0, 100, 1):
accum = 0
for i in range(N):
if n > 0:
values = np.random.randint(1,n+1, size=(sx,sy,sz))
else:
values = np.ones((sx,sy,sz))
values = np.asfortranarray(values)
start = np.random.randint(0,min(sx,sy,sz), size=(3,))
target = np.random.randint(0,min(sx,sy,sz), size=(3,))
s = time.time()
path_orig = dijkstra3d.dijkstra(values, start, target, bidirectional=bi, compass=compass)
accum += (time.time() - s)
MVx_per_sec = N * sx * sy * sz / accum / 1000000
print(n, ',', '%.3f' % MVx_per_sec)
print("Unidirectional")
trial(False, False)
print("Bidirectional")
trial(True, False)
print("Compass")
trial(False, True)
What is that pairing_heap.hpp?
Early on, I anticipated using decrease key in my heap and implemented a pairing heap, which is supposed to be an improvement on the Fibbonacci heap. However, I ended up not using decrease key, and the STL priority queue ended up being faster. If you need a pairing heap outside of boost, check it out.
References
- E. W. Dijkstra. "A Note on Two Problems in Connexion with Graphs" Numerische Mathematik 1. pp. 269-271. (1959)
- E. W. Dijkstra. "Go To Statement Considered Harmful". Communications of the ACM. Vol. 11, No. 3, pp. 147-148. (1968)
- Pohl, Ira. "Bi-directional Search", in Meltzer, Bernard; Michie, Donald (eds.), Machine Intelligence, 6, Edinburgh University Press, pp. 127–140. (1971)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
File details
Details for the file dijkstra3d-1.3.0.tar.gz
.
File metadata
- Download URL: dijkstra3d-1.3.0.tar.gz
- Upload date:
- Size: 293.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.6.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7a0b87804608a6692c0a85a029bc970566ccd103523504b4fb01d01991bb27a3 |
|
MD5 | 2963a8de9169987802299a347e266f6d |
|
BLAKE2b-256 | a9353506cbd8ef723671536070d0934146bc28143c32a5f9a932a87058bac5b6 |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp38-cp38-win_amd64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp38-cp38-win_amd64.whl
- Upload date:
- Size: 164.4 kB
- Tags: CPython 3.8, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/28.8.0 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.5.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5b87f5956b403dea39bddadab16647ca50160c29ab53e901085db19379b350b6 |
|
MD5 | 40ec9c861f2a6c33df09fb9ca7798d40 |
|
BLAKE2b-256 | 6d3c495bfac34ad9520f3d7a828924004752e682f484f29950053fab3af3e6b9 |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp38-cp38-manylinux1_x86_64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp38-cp38-manylinux1_x86_64.whl
- Upload date:
- Size: 957.9 kB
- Tags: CPython 3.8
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.6.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 68ba8c0cf253042e0f5e96576c54124336b20ec781e2572757e9d9fc8f02d29b |
|
MD5 | 070178e019389cb0a5cb19347bdfeede |
|
BLAKE2b-256 | f03b358c74da9201b2ef5134c5cf21e7d946d72162b0348dc4c1cab64437b36e |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl
- Upload date:
- Size: 229.6 kB
- Tags: CPython 3.8, macOS 10.9+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 945c993bd49fb1010c19f222feb1b32dab2446ef140cece15b76a0cb991c3285 |
|
MD5 | 0beebdd56dbfaba81d45b412df84568f |
|
BLAKE2b-256 | 8284f36262a15bbb01ba194fde93e5073ca2c6888f184ac8fd9c40da7a7b7c9d |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp37-cp37m-win_amd64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp37-cp37m-win_amd64.whl
- Upload date:
- Size: 171.5 kB
- Tags: CPython 3.7m, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/28.8.0 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.5.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | df3380ceef74af1fc89e16f6dee1a5cc81270da3c905049f2e244322b9330538 |
|
MD5 | 19c0fe174fcf4fbef57383a68e76d21b |
|
BLAKE2b-256 | 2d52f3181b23dd5fc65ce86347d1ee8b7926d68ffe02516b8104553db0581feb |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp37-cp37m-manylinux1_x86_64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp37-cp37m-manylinux1_x86_64.whl
- Upload date:
- Size: 860.3 kB
- Tags: CPython 3.7m
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.6.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2731f0f94f478195f0fd71c5e256dba3a1fa9ac6fe82ea1e484d8a21dd15e1a0 |
|
MD5 | b1060005b39a4841ee58ebcfedf48c41 |
|
BLAKE2b-256 | bb7edbc6da84f87ebcc543adc807b203d6ed17f71ef0d29fcad51ad553e37a7b |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl
- Upload date:
- Size: 229.8 kB
- Tags: CPython 3.7m, macOS 10.9+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | f4cac6cf1f62131ec7849466330cce7695bceebfe2764a2d35b7b547397322ad |
|
MD5 | 1c749af9e73fddf0aa514bf067588759 |
|
BLAKE2b-256 | 1251e14500753d91b352f4caad678b741c0f83f1b074eb09869915a2a2375132 |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp36-cp36m-win_amd64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp36-cp36m-win_amd64.whl
- Upload date:
- Size: 171.4 kB
- Tags: CPython 3.6m, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/28.8.0 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.5.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9cf6eb8504dab16cce0b3b5ea43722e63895be88b90aa7fdb3884f3d7daaa318 |
|
MD5 | 380ef65b7c23070cf3140180b87120d5 |
|
BLAKE2b-256 | d0618f496ab5a5f04c7fdaea86d1c4871f1f48b2c869dac12c824eee753c7605 |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp36-cp36m-manylinux1_x86_64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp36-cp36m-manylinux1_x86_64.whl
- Upload date:
- Size: 864.4 kB
- Tags: CPython 3.6m
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.6.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d83f0f6ab695dc64eb2bc05a8f0c91148410356f221ab3350b088ee12809443f |
|
MD5 | d38f40011a641ee3d5ab77e91a74d6ad |
|
BLAKE2b-256 | 9f1768b9f3851dbb788102fc3a7f6d69c80d291e87302006dec95131a5c0fd5c |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp36-cp36m-macosx_10_9_x86_64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp36-cp36m-macosx_10_9_x86_64.whl
- Upload date:
- Size: 229.4 kB
- Tags: CPython 3.6m, macOS 10.9+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | a79184175cd7ca1c76cf4bcbc1ee29ef5689cab779ed4c1d185c103df86c3e06 |
|
MD5 | b81de687a2681ac7a3fa7fb5bac61a06 |
|
BLAKE2b-256 | caa07d3d5cd5abfa814a7c4e53e54842defe27f4adcfb2953b5bc6eab5f51a90 |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp35-cp35m-manylinux1_x86_64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp35-cp35m-manylinux1_x86_64.whl
- Upload date:
- Size: 848.3 kB
- Tags: CPython 3.5m
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.6.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 30043edf90af17095e689e74431d10f33ce8b8950d7a7b20a1aaed141fa7f126 |
|
MD5 | 52e41eb9e88f7fd99c57208342d7d691 |
|
BLAKE2b-256 | 0e018c6e0153f2b44fbb017126f04a5f146fbf6e1715c623242c0e64fd8ea1d2 |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp35-cp35m-macosx_10_6_intel.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp35-cp35m-macosx_10_6_intel.whl
- Upload date:
- Size: 404.9 kB
- Tags: CPython 3.5m, macOS 10.6+ intel
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d56738fc1063ca2174088d5687919e2402fb4bbd84f04f03cdcf92fc140dd0d3 |
|
MD5 | 095612a4e8bb1ead8694710c1bedc824 |
|
BLAKE2b-256 | b73c6e6ea4e71d2ec674af1217256d955652afb27deb48cb85b0430959b36d01 |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp27-cp27m-manylinux1_x86_64.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp27-cp27m-manylinux1_x86_64.whl
- Upload date:
- Size: 814.7 kB
- Tags: CPython 2.7m
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.6.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4179242575b5cd43a46c0d033a4eaabc27dea25a438eb0b6051f87ea2d665c86 |
|
MD5 | dfb008d397303e75ac561ac455316355 |
|
BLAKE2b-256 | 83cb3b7366c9ef8dad74aa570cbd11acca6696ee4e2054888ddbbc8e808d970d |
Provenance
File details
Details for the file dijkstra3d-1.3.0-cp27-cp27m-macosx_10_14_intel.whl
.
File metadata
- Download URL: dijkstra3d-1.3.0-cp27-cp27m-macosx_10_14_intel.whl
- Upload date:
- Size: 222.9 kB
- Tags: CPython 2.7m, macOS 10.14+ intel
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 623df600780ca9aa76bc517a6d3ce5d48168a0f192832092f2caed57ccfd00d9 |
|
MD5 | 1a269b15dd908e75af32b10a4e042ad4 |
|
BLAKE2b-256 | 94a1f4c4539ae6ac483a49dd578770d0804dcee3876cabe82f751986a611ef08 |