def test_dijkstra2d_10x10_off_origin(): for dtype in TEST_TYPES: values = np.ones((10, 10, 1), dtype=dtype) path = dijkstra3d.dijkstra(values, (2, 0, 0), (3, 0, 0)) assert len(path) == 2 assert np.all(path == np.array([ [2, 0, 0], [3, 0, 0], ])) path = dijkstra3d.dijkstra(values, (2, 1, 0), (3, 0, 0)) assert len(path) == 2 assert np.all(path == np.array([ [2, 1, 0], [3, 0, 0], ])) path = dijkstra3d.dijkstra(values, (9, 9, 0), (5, 5, 0)) assert len(path) == 5 assert np.all(path == np.array([ [9, 9, 0], [8, 8, 0], [7, 7, 0], [6, 6, 0], [5, 5, 0], ]))
def test_dijkstra3d_3x3x3_6(bidirectional, dtype, compass): values = np.ones((3, 3, 3), dtype=dtype) path = dijkstra3d.dijkstra(values, (1, 1, 1), (1, 1, 1), bidirectional=bidirectional, connectivity=6, compass=compass) assert len(path) == 1 assert np.all(path == np.array([[1, 1, 1]])) path = dijkstra3d.dijkstra(values, (0, 0, 0), (2, 2, 2), bidirectional=bidirectional, connectivity=6, compass=compass) assert len(path) == 7 assert tuple(path[0]) == (0, 0, 0) assert tuple(path[-1]) == (2, 2, 2) path = dijkstra3d.dijkstra(values, (2, 2, 2), (0, 0, 0), bidirectional=bidirectional, connectivity=6, compass=compass) assert len(path) == 7 assert tuple(path[0]) == (2, 2, 2) assert tuple(path[-1]) == (0, 0, 0)
def test_compass(): field = np.array([ [6, 9, 7, 7, 1, 7, 4, 3, 5, 9], [4, 8, 7, 8, 1, 2, 5, 8, 3, 9], [5, 9, 4, 5, 7, 9, 2, 1, 5, 1], [1, 3, 6, 9, 6, 1, 7, 9, 5, 8], [2, 7, 3, 6, 1, 8, 9, 2, 1, 5], [7, 3, 7, 2, 9, 9, 8, 8, 9, 6], [3, 3, 8, 9, 3, 6, 8, 1, 6, 4], [9, 7, 5, 7, 9, 7, 8, 6, 7, 2], [6, 3, 7, 1, 1, 5, 2, 1, 3, 9], [2, 4, 8, 2, 9, 5, 2, 3, 3, 2], ]) start = (8, 1) target = (1, 5) dijkstra_path = dijkstra3d.dijkstra(field, start, target, compass=False) compass_path = dijkstra3d.dijkstra(field, start, target, compass=True) def path_len(path): length = 0 for p in path: length += field[tuple(p)] return length if not np.all(dijkstra_path == compass_path): print(field) print(dijkstra_path) print("dijkstra cost: %d" % path_len(dijkstra_path)) print(compass_path) print("compass cost: %d" % path_len(compass_path)) assert np.all(dijkstra_path == compass_path)
def test_dijkstra2d_10x10_off_origin(bidirectional, dtype, compass): values = np.ones((10, 10, 1), dtype=dtype) path = dijkstra3d.dijkstra(values, (2, 0, 0), (3, 0, 0), bidirectional=bidirectional, compass=compass) assert len(path) == 2 assert np.all(path == np.array([ [2, 0, 0], [3, 0, 0], ])) path = dijkstra3d.dijkstra(values, (2, 1, 0), (3, 0, 0), bidirectional=bidirectional, compass=compass) assert len(path) == 2 assert np.all(path == np.array([ [2, 1, 0], [3, 0, 0], ])) path = dijkstra3d.dijkstra(values, (9, 9, 0), (5, 5, 0), bidirectional=bidirectional, compass=compass) assert len(path) == 5 assert np.all(path == np.array([ [9, 9, 0], [8, 8, 0], [7, 7, 0], [6, 6, 0], [5, 5, 0], ]))
def diagonal_ones(): print("Running diagonal_ones.") N = 1 sx, sy, sz = 512, 512, 512 values = np.ones((sx,sy,sz), dtype=np.uint32) s = time.time() dijkstra3d.dijkstra(values, (0,0,0), (sx-1,sy-1,sz-1), compass=False) e = time.time() accum = e-s mvx = N * sx * sy * sz / accum / 1000000 print(f"{mvx:.3f} MVx/sec ({accum:.3f} sec)")
def test_dijkstra3d_3x3x3(): for dtype in TEST_TYPES: values = np.ones((3, 3, 3), dtype=dtype) path = dijkstra3d.dijkstra(values, (1, 1, 1), (1, 1, 1)) assert len(path) == 1 assert np.all(path == np.array([[1, 1, 1]])) path = dijkstra3d.dijkstra(values, (0, 0, 0), (2, 2, 2)) assert np.all(path == np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]])) path = dijkstra3d.dijkstra(values, (2, 2, 2), (0, 0, 0)) assert np.all(path == np.array([[2, 2, 2], [1, 1, 1], [0, 0, 0]]))
def test_dijkstra3d_3x3x3_18(bidirectional, dtype, compass): values = np.ones((3, 3, 3), dtype=dtype) path = dijkstra3d.dijkstra(values, (1, 1, 1), (1, 1, 1), bidirectional=bidirectional, connectivity=18, compass=compass) assert len(path) == 1 assert np.all(path == np.array([[1, 1, 1]])) path = dijkstra3d.dijkstra(values, (0, 0, 0), (2, 2, 2), bidirectional=bidirectional, connectivity=18, compass=compass) assert np.all(path == np.array([ [0, 0, 0], [1, 0, 1], [1, 1, 2], [2, 2, 2], ])) or np.all(path == np.array([ [0, 0, 0], [0, 1, 1], [1, 1, 2], [2, 2, 2], ])) or np.all(path == np.array([ [0, 0, 0], [0, 1, 1], [1, 2, 1], [2, 2, 2], ])) or np.all(path == np.array([ [0, 0, 0], [1, 1, 0], [1, 2, 1], [2, 2, 2], ])) path = dijkstra3d.dijkstra(values, (2, 2, 2), (0, 0, 0), bidirectional=bidirectional, connectivity=18, compass=compass) assert np.all(path == np.array( [[2, 2, 2], [1, 2, 1], [1, 1, 0], [0, 0, 0]])) or np.all( path == np.array([[2, 2, 2], [1, 2, 1], [0, 1, 1], [0, 0, 0]]) ) or np.all(path == np.array( [[2, 2, 2], [2, 1, 1], [1, 0, 1], [0, 0, 0]])) or np.all( path == np.array([[2, 2, 2], [1, 1, 2], [1, 0, 1], [0, 0, 0]]) ) or np.all( path == np.array([[2, 2, 2], [1, 1, 2], [1, 1, 0], [0, 0, 0]]) ) or np.all( path == np.array([[2, 2, 2], [2, 1, 1], [1, 1, 0], [0, 0, 0]]))
def test_dijkstra_2d_loop(bidirectional, compass): x = 20000 values = np.array([ [x, x, x, x, x, x, 0, x, x, x], [x, x, x, x, x, x, 0, x, x, x], [x, x, 1, x, 0, 0, 0, x, x, x], [x, x, 2, x, 0, x, 0, x, x, x], [x, 0, x, 3, x, x, 0, x, x, x], [x, 0, x, 4, 0, 0, 0, x, x, x], [x, 0, x, 5, x, x, x, x, x, x], [x, 0, x, 6, x, x, x, x, x, x], [x, 0, x, 7, x, x, x, x, x, x], [x, x, x, 1, 8, 9, 10, x, x, x], [x, x, x, 4, x, x, 11, 12, x, x], [x, x, x, x, x, x, x, x, 13, 14], ], order='F') path = dijkstra3d.dijkstra(values, (2, 2), (11, 9), bidirectional=bidirectional, compass=compass) correct_path = np.array([[2, 2], [3, 2], [4, 3], [5, 4], [6, 3], [7, 3], [8, 3], [9, 4], [9, 5], [9, 6], [10, 7], [11, 8], [11, 9]]) assert np.all(path == correct_path)
def random_paths(): print("Running random_paths.") values = np.random.randint(1,255, size=(7,7,7)) values = np.asfortranarray(values) start = np.random.randint(0,7, size=(3,)) target = np.random.randint(0,7, size=(3,)) N = 1 sx, sy, sz = 500, 500, 500 for n in range(1, 100, 1): accum = 0 for i in range(N): values = np.random.randint(1,n+1, size=(sx,sy,sz)) values = np.asfortranarray(values) # values = np.ones((sx,sy,sz)) / 1000 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=True) accum += (time.time() - s) mvx = N * sx * sy * sz / accum / 1000000 print(f"{n} {mvx:.3f} MVx/sec ({accum:.3f} sec)")
def test_dijkstra_parental(): for dtype in TEST_TYPES: values = np.ones((10, 10, 1), dtype=dtype) parents = dijkstra3d.parental_field(values, (0, 0, 0)) path = dijkstra3d.path_from_parents(parents, (3, 0, 0)) assert len(path) == 4 assert np.all(path == np.array([ [0, 0, 0], [1, 1, 0], [2, 1, 0], [3, 0, 0], ])) # Symmetric Test for _ in range(50): values = np.random.randint(1, 255, size=(10, 10, 10)) start = np.random.randint(0, 9, size=(3, )) target = np.random.randint(0, 9, size=(3, )) parents = dijkstra3d.parental_field(values, start) path = dijkstra3d.path_from_parents(parents, target) path_orig = dijkstra3d.dijkstra(values, start, target) assert np.all(path == path_orig) # Asymmetric Test for _ in range(50): values = np.random.randint(1, 255, size=(11, 10, 10)) start = np.random.randint(0, 9, size=(3, )) target = np.random.randint(0, 9, size=(3, )) parents = dijkstra3d.parental_field(values, start) path = dijkstra3d.path_from_parents(parents, target) path_orig = dijkstra3d.dijkstra(values, start, target) print(start, target) print(path) print(path_orig) assert np.all(path == path_orig)
def dijk(src, target, graph): return dijkstra3d.dijkstra(img, src, target, connectivity=6, voxel_graph=graph, bidirectional=bidirectional, compass=compass)
def test_dijkstra2d_10x10_6(dtype, bidirectional, compass): values = np.ones((10, 10, 1), dtype=dtype) path = dijkstra3d.dijkstra(values, (1, 1, 0), (1, 1, 0), bidirectional=bidirectional, connectivity=6, compass=compass) assert len(path) == 1 assert np.all(path == np.array([[1, 1, 0]])) path = dijkstra3d.dijkstra(values, (0, 0, 0), (3, 0, 0), bidirectional=bidirectional, connectivity=6, compass=compass) assert len(path) == 4 assert np.all(path == np.array([ [0, 0, 0], [1, 0, 0], [2, 0, 0], [3, 0, 0], ]))
def compute_paths(root, labels, DBF, DAF, parents, scale, const, anisotropy, soma_mode, soma_radius, fix_branching): """ Given the labels, DBF, DAF, dijkstra parents, and associated invalidation knobs, find the set of paths that cover the object. Somas are given special treatment in that we attempt to cull vertices within a radius of the root vertex. """ invalid_vertices = {} if soma_mode: invalid_vertices[root] = True paths = [] valid_labels = np.count_nonzero(labels) while valid_labels > 0: target = kimimaro.skeletontricks.find_target(labels, DAF) if fix_branching: path = dijkstra3d.dijkstra(parents, root, target) else: path = dijkstra3d.path_from_parents(parents, target) if soma_mode: dist_to_soma_root = np.linalg.norm(anisotropy * (path - root), axis=1) # remove all path points which are within soma_radius of root path = np.concatenate( (path[:1, :], path[dist_to_soma_root > soma_radius, :])) invalidated, labels = kimimaro.skeletontricks.roll_invalidation_cube( labels, DBF, path, scale, const, anisotropy=anisotropy, invalid_vertices=invalid_vertices, ) valid_labels -= invalidated for vertex in path: invalid_vertices[tuple(vertex)] = True if fix_branching: parents[tuple(vertex)] = 0.0 paths.append(path) return paths
def diffusion_paths(local_maxima, connections, field, T = 77.0, cut_off=1E8): import dijkstra3d as d3d import numpy as np from tqdm import tqdm # * Define the scalar field # dk_field = egrid # dk_field[dk_field>=cut_off]=cut_off # dk_field = (dk_field - np.min(egrid))/T +1 # Weight cannot be zero # dk_field = dk_field.astype(np.int) # field = np.asfortranarray(dk_field) # exp(+\beta*E) local_maxima = np.vstack(np.where(local_maxima)).T paths = [d3d.dijkstra(field, source=local_maxima[c[0]-1], target=local_maxima[c[1]-1]) for c in tqdm(connections)] return paths
def test_dijkstra2d_10x10(): for dtype in TEST_TYPES: values = np.ones((10, 10, 1), dtype=dtype) path = dijkstra3d.dijkstra(values, (1, 1, 0), (1, 1, 0)) assert len(path) == 1 assert np.all(path == np.array([[1, 1, 0]])) path = dijkstra3d.dijkstra(values, (0, 0, 0), (3, 0, 0)) assert len(path) == 4 assert np.all(path == np.array([ [0, 0, 0], [1, 1, 0], [2, 1, 0], [3, 0, 0], ])) path = dijkstra3d.dijkstra(values, (0, 0, 0), (5, 5, 0)) assert len(path) == 6 assert np.all(path == np.array([ [0, 0, 0], [1, 1, 0], [2, 2, 0], [3, 3, 0], [4, 4, 0], [5, 5, 0], ])) path = dijkstra3d.dijkstra(values, (0, 0, 0), (9, 9, 0)) assert len(path) == 10 assert np.all(path == np.array( [[0, 0, 0], [1, 1, 0], [2, 2, 0], [3, 3, 0], [4, 4, 0], [5, 5, 0], [6, 6, 0], [7, 7, 0], [8, 8, 0], [9, 9, 0]]))
def test_dijkstra_2d_loop(): x = 20000 values = np.array([ [x, x, x, x, x, x, 0, x, x, x], [x, x, x, x, x, x, 0, x, x, x], [x, x, 1, x, 0, 0, 0, x, x, x], [x, x, 2, x, 0, x, 0, x, x, x], [x, 0, x, 3, x, x, 0, x, x, x], [x, 0, x, 4, 0, 0, 0, x, x, x], [x, 0, x, 5, x, x, x, x, x, x], [x, 0, x, 6, x, x, x, x, x, x], [x, 0, x, 7, x, x, x, x, x, x], [x, x, x, 1, 8, 9, 10, x, x, x], [x, x, x, 4, x, x, 11, 12, x, x], [x, x, x, x, x, x, x, x, 13, 14], ]) path = dijkstra3d.dijkstra(np.asfortranarray(values), (2, 2), (11, 9)) correct_path = np.array([[2, 2], [3, 2], [4, 3], [5, 4], [6, 3], [7, 3], [8, 3], [9, 4], [9, 5], [9, 6], [10, 7], [11, 8], [11, 9]]) assert np.all(path == correct_path)
def test_voxel_connectivity_graph(): from PIL import Image import cc3d img = Image.open("./multi-color-self-touch.png") img = np.array(img) root_img = img > 0 root_img = root_img.astype(np.float32) root_img[root_img == 0] = np.inf boundary_x = 106 graph = np.zeros(img.shape, dtype=np.uint8, order="F") graph[:boundary_x] = cc3d.voxel_connectivity_graph(img[:boundary_x], connectivity=6) graph[boundary_x:] = cc3d.voxel_connectivity_graph(img[boundary_x:], connectivity=6) path = dijkstra3d.dijkstra(root_img, (199, 199), (173, 170), connectivity=8, voxel_graph=graph) assert len(path) == 528
def test_dijkstra_parental(dtype, compass): values = np.ones((10, 10, 1), dtype=dtype, order='F') parents = dijkstra3d.parental_field(values, (0, 0, 0)) path = dijkstra3d.path_from_parents(parents, (3, 0, 0)) assert len(path) == 4 assert np.all(path == np.array([ [0, 0, 0], [1, 1, 0], [2, 1, 0], [3, 0, 0], ])) def path_len(path, values): length = 0 for p in path: length += values[tuple(p)] return length # Symmetric Test for _ in range(500): values = np.random.randint(1, 10, size=(10, 10, 1)) values = np.asfortranarray(values) start = np.random.randint(0, 9, size=(3, )) target = np.random.randint(0, 9, size=(3, )) start[2] = 0 target[2] = 0 parents = dijkstra3d.parental_field(values, start) path = dijkstra3d.path_from_parents(parents, target) path_orig = dijkstra3d.dijkstra(values, start, target, compass=compass) if path_len(path, values) != path_len(path_orig, values): print(start, target) print(path) print(path_orig) print(values[:, :, 0]) print('parents_path') for p in path: print(values[tuple(p)]) print('compass_path') for p in path_orig: print(values[tuple(p)]) assert path_len(path, values) == path_len(path_orig, values) if compass == False: assert np.all(path == path_orig) # Asymmetric Test for _ in range(500): values = np.random.randint(1, 255, size=(11, 10, 10)) values = np.asfortranarray(values) start = np.random.randint(0, 9, size=(3, )) target = np.random.randint(0, 9, size=(3, )) start[0] = np.random.randint(0, 10) target[0] = np.random.randint(0, 10) parents = dijkstra3d.parental_field(values, start) path = dijkstra3d.path_from_parents(parents, target) path_orig = dijkstra3d.dijkstra(values, start, target, compass=compass) if path_len(path, values) != path_len(path_orig, values): print(start, target) print(path) print(path_orig) assert path_len(path, values) == path_len(path_orig, values) if compass == False: assert np.all(path == path_orig)
def test_bidirectional(): x = 20000 values = np.array([ [x, x, x, x, x, x, x, x, x, x], [x, x, x, x, x, x, x, x, x, x], [x, x, x, x, x, x, x, x, x, x], [x, 1, x, x, x, 6, x, x, x, x], [x, x, 1, x, 4, x, 7, x, x, x], # two paths: cost 22, length 8 [x, x, x, 1, 8, x, 1, x, x, x], # cost 23, length 9 [x, x, x, x, x, 8, x, 1, x, x], [x, x, x, x, x, x, x, x, 1, x], [x, x, x, x, x, x, x, x, x, x], [x, x, x, x, x, x, x, x, x, x], ]) path_reg = dijkstra3d.dijkstra(np.asfortranarray(values), (3, 1), (7, 8), bidirectional=False) path_bi = dijkstra3d.dijkstra(np.asfortranarray(values), (3, 1), (7, 8), bidirectional=True) print(path_reg) print(path_bi) assert np.all(path_reg == path_bi) assert len(path_bi) == 8 assert np.all(path_bi == [ [3, 1], [4, 2], [5, 3], [5, 4], # critical [6, 5], [5, 6], [6, 7], [7, 8] ]) values = np.array([ [x, x, x, x, x, x, x, x, x, x], [x, x, x, x, x, x, x, x, x, x], [x, x, x, x, x, x, x, x, x, x], [x, x, x, 6, 6, 6, 6, x, x, x], [1, 1, 1, x, x, x, x, 6, 6, 6], # 42, 45 [x, x, 9, x, x, x, 7, x, x, x], [x, x, 1, x, x, x, 1, x, x, x], [x, x, 1, x, x, x, 1, x, x, x], [x, x, 1, 1, 1, 1, 1, x, x, x], [x, x, x, x, x, x, x, x, x, x], ]) path_reg = dijkstra3d.dijkstra(np.asfortranarray(values), (4, 0), (4, 9), bidirectional=False) path_bi = dijkstra3d.dijkstra(np.asfortranarray(values), (4, 0), (4, 9), bidirectional=True) print(path_reg) print(path_bi) assert np.all(path_reg == path_bi) assert len(path_bi) == 14 assert np.all(path_bi == [ [4, 0], [4, 1], # [4,2], [5, 2], [6, 2], [7, 2], # [8,2], [8, 3], [8, 4], [8, 5], # [8,6], [7, 6], [6, 6], [5, 6], [4, 7], [4, 8], [4, 9] ])
def compute_paths(root, labels, DBF, DAF, parents, scale, const, anisotropy, soma_mode, soma_radius, fix_branching, manual_targets_before, manual_targets_after, max_paths): """ Given the labels, DBF, DAF, dijkstra parents, and associated invalidation knobs, find the set of paths that cover the object. Somas are given special treatment in that we attempt to cull vertices within a radius of the root vertex. """ invalid_vertices = {} paths = [] valid_labels = np.count_nonzero(labels) root = tuple(root) if soma_mode: invalid_vertices[root] = True if max_paths is None: max_paths = valid_labels if len(manual_targets_before) + len(manual_targets_after) >= max_paths: return [] while (valid_labels > 0 or manual_targets_before or manual_targets_after) \ and len(paths) < max_paths: if manual_targets_before: target = manual_targets_before.pop() elif valid_labels == 0: target = manual_targets_after.pop() else: target = kimimaro.skeletontricks.find_target(labels, DAF) if fix_branching: # faster to trace from target to root than root to target # because that way local exploration finds any zero weighted path # and finishes vs exploring from the neighborhood of the entire zero # weighted path path = dijkstra3d.dijkstra(parents, target, root, bidirectional=soma_mode) else: path = dijkstra3d.path_from_parents(parents, target) if soma_mode: dist_to_soma_root = np.linalg.norm(anisotropy * (path - root), axis=1) # remove all path points which are within soma_radius of root path = np.concatenate( (path[:1, :], path[dist_to_soma_root > soma_radius, :])) if valid_labels > 0: invalidated, labels = kimimaro.skeletontricks.roll_invalidation_cube( labels, DBF, path, scale, const, anisotropy=anisotropy, invalid_vertices=invalid_vertices, ) valid_labels -= invalidated for vertex in path: invalid_vertices[tuple(vertex)] = True if fix_branching: parents[tuple(vertex)] = 0.0 paths.append(path) return paths
def test_dijkstra2d_10x10_26(dtype, bidirectional, connectivity, compass): values = np.ones((10, 10, 1), dtype=dtype) path = dijkstra3d.dijkstra(values, (1, 1, 0), (1, 1, 0), bidirectional=bidirectional, connectivity=connectivity, compass=compass) assert len(path) == 1 assert np.all(path == np.array([[1, 1, 0]])) path = dijkstra3d.dijkstra(values, (0, 0, 0), (3, 0, 0), bidirectional=bidirectional, connectivity=connectivity, compass=compass) assert len(path) == 4 assert np.all(path == np.array([ [0, 0, 0], [1, 1, 0], [2, 1, 0], [3, 0, 0], ])) or np.all(path == np.array([ [0, 0, 0], [1, 1, 0], [2, 0, 0], [3, 0, 0], ])) or np.all(path == np.array([ [0, 0, 0], [1, 0, 0], [2, 1, 0], [3, 0, 0], ])) or np.all(path == np.array([ [0, 0, 0], [1, 0, 0], [2, 0, 0], [3, 0, 0], ])) path = dijkstra3d.dijkstra(values, (0, 0, 0), (5, 5, 0), bidirectional=bidirectional, connectivity=connectivity, compass=compass) assert len(path) == 6 assert np.all(path == np.array([ [0, 0, 0], [1, 1, 0], [2, 2, 0], [3, 3, 0], [4, 4, 0], [5, 5, 0], ])) path = dijkstra3d.dijkstra(values, (0, 0, 0), (9, 9, 0), bidirectional=bidirectional, connectivity=connectivity, compass=compass) assert len(path) == 10 assert np.all(path == np.array([[0, 0, 0], [1, 1, 0], [2, 2, 0], [3, 3, 0], [4, 4, 0], [5, 5, 0], [6, 6, 0], [7, 7, 0], [8, 8, 0], [9, 9, 0]])) path = dijkstra3d.dijkstra(values, (2, 1, 0), (3, 0, 0), compass=compass) assert len(path) == 2 assert np.all(path == np.array([ [2, 1, 0], [3, 0, 0], ])) path = dijkstra3d.dijkstra(values, (9, 9, 0), (5, 5, 0), compass=compass) assert len(path) == 5 assert np.all(path == np.array([ [9, 9, 0], [8, 8, 0], [7, 7, 0], [6, 6, 0], [5, 5, 0], ]))