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 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 compute_paths(root, labels, DBF, DAF, parents, scale, const, anisotropy, soma_mode, soma_radius, fix_branching, manual_targets_before, manual_targets_after, max_paths, voxel_graph): """ 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 [] target_finder = None def find_target(): nonlocal target_finder if target_finder is None: target_finder = kimimaro.skeletontricks.CachedTargetFinder( labels, DAF[0]) DAF.pop(0) return target_finder.find_target(labels) parents[tuple(root)] = 0 # provide initial rail for dijkstra.railroad 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 = find_target() if fix_branching: # Draw a path (a "road") from the target to the nearest zero weighted # path (a "rail"). This has some minor efficiencies vs drawing # from a target all the way to the source. Also, target -> source # is much more efficient than source -> target for three reasons. # (a) target -> catches a rail instead of exploring all rails # (b) target has a natural edge effect that restrict exploration # (c) in soma, target -> source follows gradients vs fights them path = dijkstra3d.railroad(parents, target, voxel_graph=voxel_graph) 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_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 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