def test_link_edges(full_cell_mesh, full_cell_merge_log, full_cell_soma_pt): lcc_before = mesh_filters.filter_largest_component(full_cell_mesh) assert lcc_before.sum() == 1973174 full_cell_mesh.voxel_scaling = [10, 10, 10] full_cell_mesh.add_link_edges(merge_log=full_cell_merge_log, base_resolution=[1, 1, 1]) full_cell_mesh.voxel_scaling = None lcc_after = mesh_filters.filter_largest_component(full_cell_mesh) assert lcc_after.sum() == 2188351
def test_filter_two_points(full_cell_mesh, full_cell_soma_pt, tmp_path): pt_down = full_cell_soma_pt + np.array([0, 50000, 0]) is_large = mesh_filters.filter_largest_component(full_cell_mesh) full_cell_mesh = full_cell_mesh.apply_mask(is_large) on_ais = mesh_filters.filter_two_point_distance( full_cell_mesh, [full_cell_soma_pt, pt_down], 2000) ais_mesh = full_cell_mesh.apply_mask(on_ais) ais_actor = trimesh_vtk.mesh_actor(ais_mesh) fname = 'full_cell_ais.png' filepath = os.path.join(tmp_path, fname) trimesh_vtk.render_actors([ais_actor], back_color=(1, 1, 1), do_save=True, filename=filepath, scale=1) compare_img_to_test_file(filepath) pts_end = np.array([full_cell_soma_pt, pt_down]) ais_sloppy = mesh_filters.filter_close_to_line(full_cell_mesh, pts_end, 4000) assert (np.sum(ais_sloppy) == 12961)
def get_topo_points(client, segs, annos, min_size=1000, voxel_resolution=np.array([4, 4, 40])): mm = trimesh_io.MeshMeta(cv_path=client.info.segmentation_source(), map_gs_to_https=True, disk_cache_path='meshes') multi_seg = len(segs) > 1 all_bps = [] all_eps = [] for ii, oid in enumerate(segs): mesh = mm.mesh(seg_id=oid) lcs = mesh_filters.filter_largest_component(mesh) meshf = mesh.apply_mask(lcs) nrn = meshwork.Meshwork(meshf) if len(annos['center_point']) > 0: ctr_pt = np.array(annos['center_point']) * np.array([4, 4, 40]) nrn.skeletonize_mesh(soma_pt=ctr_pt, soma_thresh_distance=15000, compute_radius=False, collapse_function='sphere') else: nrn.skeletonize_mesh(compute_radius=False) if len(annos['ignore']) > 0: anno_df = pd.DataFrame({'pts': annos['ignore']}) nrn.add_annotations('ignore_beyond', anno_df, point_column='pts') ignore_masks = [] for ii in nrn.anno['ignore_beyond'].mesh_index: ignore_masks.append( np.invert(nrn.downstream_of(ii).to_mesh_mask_base)) for mask in ignore_masks: nrn.apply_mask(mask) bps, eps = _branch_and_end_points_ordered(nrn) all_bps.append([bp / voxel_resolution for bp in bps]) all_eps.append(eps / voxel_resolution) # bps = _branch_points_ordered(nrn) / voxel_resolution # all_bps.append(bps) # eps = _end_points_ordered(nrn) / voxel_resolution # all_eps.append(eps) return [all_bps, np.vstack(all_eps), np.vstack(annos['ignore'])]
def test_link_edges(full_cell_mesh, full_cell_merge_log, full_cell_soma_pt, monkeypatch): class MyChunkedGraph(object): def __init__(a, **kwargs): pass def get_merge_log(self, atomic_id): return full_cell_merge_log monkeypatch.setattr(trimesh_io.trimesh_repair.chunkedgraph, 'ChunkedGraphClient', MyChunkedGraph) full_cell_mesh.add_link_edges('test', 5) out = mesh_filters.filter_largest_component(full_cell_mesh) mesh_filter = full_cell_mesh.apply_mask(out) skel = skeletonize.skeletonize_mesh(mesh_filter, invalidation_d=10000, soma_pt=full_cell_soma_pt) assert (skel.n_branch_points == 83)
def test_masked_mesh(cv_path, full_cell_mesh_id, full_cell_soma_pt, tmpdir): mm = trimesh_io.MeshMeta(cv_path=cv_path, cache_size=0, disk_cache_path=os.path.join( tmpdir, 'mesh_cache')) mmesh = mm.mesh(seg_id=full_cell_mesh_id) assert (mmesh is not None) # read again to test file caching with memory caching on mmesh_cache = mm.mesh(seg_id=full_cell_mesh_id) # now set it up with memory caching enabled mm = trimesh_io.MeshMeta(cv_path=cv_path, cache_size=1) # read it again with memory caching enabled mmesh = mm.mesh(seg_id=full_cell_mesh_id) # read it again to use memory cache mmesh_mem_cache = mm.mesh(seg_id=full_cell_mesh_id) ds = np.linalg.norm(mmesh.vertices - full_cell_soma_pt, axis=1) soma_mesh = mmesh.apply_mask(ds < 15000) is_big = mesh_filters.filter_largest_component(soma_mesh) soma_mesh = soma_mesh.apply_mask(is_big) ds = np.linalg.norm(soma_mesh.vertices - full_cell_soma_pt, axis=1) double_soma_mesh = soma_mesh.apply_mask(ds < 10000) with pytest.raises(ValueError): bad_mask = mmesh.apply_mask([True, True]) random_indices = np.array([0, 500, 1500]) orig_indices = double_soma_mesh.map_indices_to_unmasked(random_indices) back_indices = double_soma_mesh.filter_unmasked_indices(orig_indices) assert np.all(random_indices == back_indices) fname = os.path.join(tmpdir, 'test_mask_mesh.h5') double_soma_mesh.write_to_file(fname) double_soma_read = mm.mesh(filename=fname)
def sk_dist(neuronID, pts, data_root, dataset_name='pinky100', filt=True, max_dist=2000): ''' Calculates distance of any point/points in the space to the closest point on the skeleton neuron of interest INPUTS: neuronID = String, id associated with the neuron of interest pts = np.array 3xN, N: number of points data_root = Location of the dataset datset_name (optional) = string,(defaul pinky100) filt (optional) = bool, filter the mesh based on segment size(default True) max_dist (optional) = float, maximum expected distance from the neuron in nm (defaul 500nm) RETURNS: dists = Nx1 np array, distances of each point to soma in nm ''' # set values voxel_size = [4, 4, 40] # Folders for the mesh and skeleton mesh_folder = os.path.join(data_root, 'meshes') skeleton_folder = os.path.join(data_root, 'skeletons') # Mesh meta data mm = trimesh_io.MeshMeta( cv_path= 'graphene://https://swdb.dynamicannotationframework.com/segmentation/1.0/pinky100_sv16', disk_cache_path=mesh_folder, cache_size=2) # load the mesh for the neuron mesh = mm.mesh(seg_id=neuronID) #load the skeleton for the neuron sk = skeleton_io.read_skeleton_h5(skeleton_folder + '/' + str(neuronID) + '.h5') if filt: # filter out the segmented portions of the mesh mask = mesh_filters.filter_largest_component(mesh) neuron_mesh = mesh.apply_mask(mask) else: neuron_mesh = mesh #load the skeleton for the neuron sk = skeleton_io.read_skeleton_h5(skeleton_folder + '/' + str(neuron) + '.h5') #convert vertecies to nm pt_nm = np.vstack(pts) * np.array(voxel_size) # use kdtree to find the shortest distance from the point to the mesh and the index associated with that dist, ind = neuron_mesh.kdtree.query(pt_nm, distance_upper_bound=max_dist) if filt: #find the index on original mask ind = neuron_mesh.map_indices_to_unmasked(ind_masked) neuron_mesh = mesh #find skeleton vertex of the point on the mesh syn_sk_ind = sk.mesh_to_skel_map[ind] syn_sk_mesh_ind = np.array(sk.vertex_properties['mesh_index'])[syn_sk_ind] dd = scipy.sparse.csgraph.dijkstra(neuron_mesh.csgraph, directed=False, indices=ind) dists = [dd[ind, mesh_ind] for ind, mesh_ind in enumerate(syn_sk_mesh_ind)] dists = np.array(dists) return dists
def soma_dist(neuronID, pts, data_root, dataset_name='pinky100', filt=True, max_dist=500): ''' Calculates distance of any point/points in the space to the center of the soma of neuron of interest INPUTS: neuronID = String, id associated with the neuron of interest pts = np.array 3xN, N: number of points data_root = Location of the dataset datset_name (optional) = string,(defaul pinky100) filt (optional) = bool, filter the mesh based on segment size(default True) max_dist (optional) = float, maximum expected distance from the neuron in nm (defaul 500nm) RETURNS: pt_soma_dist = Nx1 np array, distances of each point to soma in nm ''' # set values voxel_size = [4, 4, 40] # Folders for the mesh and skeleton mesh_folder = os.path.join(data_root, 'meshes') skeleton_folder = os.path.join(data_root, 'skeletons') # Mesh meta data mm = trimesh_io.MeshMeta( cv_path= 'graphene://https://swdb.dynamicannotationframework.com/segmentation/1.0/pinky100_sv16', disk_cache_path=mesh_folder, cache_size=2) # load the mesh for the neuron mesh = mm.mesh(seg_id=neuronID) #load the skeleton for the neuron sk = skeleton_io.read_skeleton_h5(skeleton_folder + '/' + str(neuronID) + '.h5') if filt: # filter out the segmented portions of the mesh mask = mesh_filters.filter_largest_component(mesh) neuron_mesh = mesh.apply_mask(mask) else: neuron_mesh = mesh # convert vertecies to nm pt_nm = np.vstack(pts) * np.array(voxel_size) # use kdtree to find the shortest distance from the point to the mesh and the index associated with that dist, ind = neuron_mesh.kdtree.query(pt_nm, distance_upper_bound=500) # use kdtree to find the shortest distance from the point to the mesh and the index associated with that dist, ind = neuron_mesh.kdtree.query(pt_nm, distance_upper_bound=max_dist) #find the vertices of the synapse point on the mesh pt_pos_mesh = neuron_mesh.vertices[ind] #find skeleton vertex of the point on the mesh if filt: ind_orig = neuron_mesh.map_indices_to_unmasked(ind) pt_sk_vert = sk.mesh_to_skel_map[ind_orig] else: pt_sk_vert = sk.mesh_to_skel_map[ind] pt_soma_dist = sk.distance_to_root[pt_sk_vert] + dist +sk_dist(neuronID, pts, data_root, dataset_name='pinky100', filt=True, max_dist=2000) return pt_soma_dist
# Find opening and point on skeleton closest to opening for each mesh spine1broken = trimesh.repair.broken_faces(spinemesh1_mp) spine1openings = spinemesh1_mp.submesh([spine1broken], append=True) spine1openings = meshparty.trimesh_io.Mesh(vertices=spine1openings.vertices, faces=spine1openings.faces) print(spine1openings) if spine1openings.body_count == 1: path_opening1_a = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh1_mp, skeleton1, spine1openings.vertices[0]) opening_ind1_a = np.where( skeleton1.vertices == spinemesh1.vertices[path_opening1_a[-1]]) opening_ind1_a = opening_ind1_a[0][0] opening_ind1_b = -1 elif spine1openings.body_count == 2: mask1 = mesh_filters.filter_largest_component(spine1openings) spine1openings_a = spine1openings.apply_mask(mask1) spine1openings_b_vertices = [] for i in spine1openings.vertices: if i not in spine1openings_a.vertices: spine1openings_b_vertices.append(i.tolist()) path_opening1_a = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh1_mp, skeleton1, spine1openings.vertices[0]) path_opening1_b = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh1_mp, skeleton1, spine1openings_b_vertices[0]) opening_ind1_a = np.where( skeleton1.vertices == spinemesh1.vertices[path_opening1_a[-1]]) opening_ind1_a = opening_ind1_a[0][0] opening_ind1_b = np.where( skeleton1.vertices == spinemesh1.vertices[path_opening1_b[-1]]) opening_ind1_b = opening_ind1_b[0][0]
def doubleheaded(): # Find opening and point on skeleton closest to opening for each mesh spine1broken = trimesh.repair.broken_faces(spinemesh1_mp) spine1openings = spinemesh1_mp.submesh([spine1broken], append=True) spine1openings = meshparty.trimesh_io.Mesh( vertices=spine1openings.vertices, faces=spine1openings.faces) print(spine1openings) if spine1openings.body_count == 1: path_opening1_a = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh1_mp, skeleton1, spine1openings.vertices[0]) opening_ind1_a = np.where( skeleton1.vertices == spinemesh1_mp.vertices[path_opening1_a[-1]]) opening_ind1_a = opening_ind1_a[0][0] opening_ind1_b = -1 elif spine1openings.body_count == 2: mask1 = mesh_filters.filter_largest_component(spine1openings) spine1openings_a = spine1openings.apply_mask(mask1) spine1openings_b_vertices = [] for i in spine1openings.vertices: if i not in spine1openings_a.vertices: spine1openings_b_vertices.append(i.tolist()) path_opening1_a = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh1_mp, skeleton1, spine1openings.vertices[0]) path_opening1_b = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh1_mp, skeleton1, spine1openings_b_vertices[0]) opening_ind1_a = np.where( skeleton1.vertices == spinemesh1_mp.vertices[path_opening1_a[-1]]) opening_ind1_a = opening_ind1_a[0][0] opening_ind1_b = np.where( skeleton1.vertices == spinemesh1_mp.vertices[path_opening1_b[-1]]) opening_ind1_b = opening_ind1_b[0][0] else: mask1 = mesh_filters.filter_largest_component(spine1openings) spine1openings = spine1openings.apply_mask(mask1) path_opening1_a = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh1_mp, skeleton1, spine1openings.vertices[0]) opening_ind1_a = np.where( skeleton1.vertices == spinemesh1_mp.vertices[path_opening1_a[-1]]) opening_ind1_a = opening_ind1_a[0][0] opening_ind1_b = -1 spine2broken = trimesh.repair.broken_faces(spinemesh2_mp) spine2openings = spinemesh2_mp.submesh([spine2broken], append=True) spine2openings = meshparty.trimesh_io.Mesh( vertices=spine2openings.vertices, faces=spine2openings.faces) print(spine2openings) if spine2openings.body_count == 1: path_opening2_a = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh2_mp, skeleton2, spine2openings.vertices[0]) opening_ind2_a = np.where( skeleton2.vertices == spinemesh2_mp.vertices[path_opening2_a[-1]]) opening_ind2_a = opening_ind2_a[0][0] opening_ind2_b = -1 elif spine2openings.body_count == 2: mask2 = mesh_filters.filter_largest_component(spine2openings) spine2openings_a = spine2openings.apply_mask(mask2) spine2openings_b_vertices = [] for i in spine2openings.vertices: if i not in spine2openings_a.vertices: spine2openings_b_vertices.append(i.tolist()) path_opening2_a = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh2_mp, skeleton2, spine2openings.vertices[0]) path_opening2_b = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh2_mp, skeleton2, spine2openings_b_vertices[0]) opening_ind2_a = np.where( skeleton2.vertices == spinemesh2_mp.vertices[path_opening2_a[-1]]) opening_ind2_a = opening_ind2_a[0][0] opening_ind2_b = np.where( skeleton2.vertices == spinemesh2_mp.vertices[path_opening2_b[-1]]) opening_ind2_b = opening_ind2_b[0][0] else: mask2 = mesh_filters.filter_largest_component(spine2openings) spine2openings = spine2openings.apply_mask(mask2) path_opening2_a = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh2_mp, skeleton2, spine2openings.vertices[0]) opening_ind2_a = np.where( skeleton2.vertices == spinemesh2_mp.vertices[path_opening2_a[-1]]) opening_ind2_a = opening_ind2_a[0][0] opening_ind2_b = -1 # Create a path from the synapse to the opening for each mesh/synapse # The path consists of two parts: (1) a path from the synapse to the nearest point on the skeleton, and # (2) a path along the skeleton to the opening path1_1 = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh1_mp, skeleton1, synapse1_loc) meshverts1 = spinemesh1_mp.vertices.tolist() skelverts1 = skeleton1.vertices.tolist() inds1_a = path1_1 inds1_b = path1_1[1:] index = np.where(skeleton1.vertices == spinemesh1_mp.vertices[path1_1[-1]]) index = index[0][0] if opening_ind1_b == -1: opening_ind1 = opening_ind1_a skeleton1.reroot(opening_ind1_a) path1_2 = skeleton1.path_to_root(index) for i in path1_2[1:]: mesh_ind = np.where( spinemesh1_mp.vertices == skeleton1.vertices[i]) mesh_ind = mesh_ind[0][0] inds1_a.append(mesh_ind) inds1_b.append(mesh_ind) inds1_b = np.append(inds1_b, inds1_b[-1]) line1 = meshparty.trimesh_vtk.linked_point_actor(np.array(meshverts1), np.array(meshverts1), inds_a=inds1_a, inds_b=inds1_b, opacity=1) else: skeleton1_a = skeleton1 skeleton1_a.reroot(opening_ind1_a) path1_2a = skeleton1_a.path_to_root(index) skeleton1_b = skeleton1 skeleton1_b.reroot(opening_ind1_b) path1_2b = skeleton1_b.path_to_root(index) if len(path1_2a) > len(path1_2b) and len(path1_2b) > 1: path1_2 = path1_2b opening_ind1 = opening_ind1_b else: path1_2 = path1_2a opening_ind1 = opening_ind1_a for i in path1_2[1:]: mesh_ind = np.where( spinemesh1_mp.vertices == skeleton1.vertices[i]) mesh_ind = mesh_ind[0][0] inds1_a.append(mesh_ind) inds1_b.append(mesh_ind) inds1_b = np.append(inds1_b, inds1_b[-1]) line1 = meshparty.trimesh_vtk.linked_point_actor(np.array(meshverts1), np.array(meshverts1), inds_a=inds1_a, inds_b=inds1_b, opacity=1) path2_1 = meshparty.mesh_skel_utils.point_to_skel_meshpath( spinemesh2_mp, skeleton2, synapse2_loc) meshverts2 = spinemesh2_mp.vertices.tolist() skelverts2 = skeleton2.vertices.tolist() inds2_a = path2_1 inds2_b = path2_1[1:] index = np.where(skeleton2.vertices == spinemesh2_mp.vertices[path2_1[-1]]) index = index[0][0] if opening_ind2_b == -1: opening_ind2 = opening_ind2_a skeleton2.reroot(opening_ind2_a) path2_2 = skeleton2.path_to_root(index) for i in path2_2[1:]: mesh_ind = np.where( spinemesh2_mp.vertices == skeleton2.vertices[i]) mesh_ind = mesh_ind[0][0] inds2_a.append(mesh_ind) inds2_b.append(mesh_ind) inds2_b = np.append(inds2_b, inds2_b[-1]) line2 = meshparty.trimesh_vtk.linked_point_actor(np.array(meshverts2), np.array(meshverts2), inds_a=inds2_a, inds_b=inds2_b, opacity=1) else: skeleton2_a = skeleton2 skeleton2_a.reroot(opening_ind2_a) path2_2a = skeleton2_a.path_to_root(index) skeleton2_b = skeleton2 skeleton2_b.reroot(opening_ind2_b) path2_2b = skeleton2_b.path_to_root(index) if len(path2_2a) > len(path2_2b) and len(path2_2b) > 1: path2_2 = path2_2b opening_ind2 = opening_ind2_b else: path2_2 = path2_2a opening_ind2 = opening_ind2_a for i in path2_2[1:]: mesh_ind = np.where( spinemesh2_mp.vertices == skeleton2.vertices[i]) mesh_ind = mesh_ind[0][0] inds2_a.append(mesh_ind) inds2_b.append(mesh_ind) inds2_b = np.append(inds2_b, inds2_b[-1]) line2 = meshparty.trimesh_vtk.linked_point_actor(np.array(meshverts2), np.array(meshverts2), inds_a=inds2_a, inds_b=inds2_b, opacity=1) end_actor1 = trimesh_vtk.point_cloud_actor([skelverts1[opening_ind1]], size=100, color=(0.7, 0.9, 1), opacity=1) end_actor2 = trimesh_vtk.point_cloud_actor([skelverts2[opening_ind2]], size=100, color=(0.9, 0.7, 0.6), opacity=1) # Compare the two lines line1points = [] verts_ind1 = 0 for i in meshverts1: if verts_ind1 in inds1_a: line1points.append(i) verts_ind1 += 1 line2points = [] verts_ind2 = 0 for i in meshverts2: if verts_ind2 in inds2_a: line2points.append(i) verts_ind2 += 1 class Linemesh: def __init__(self, vertices): self.vertices = vertices line1mesh = Linemesh(line1points) #cloud = trimesh.PointCloud(line1points) #line1mesh = cloud.convex_hull compare = meshparty.mesh_filters.filter_spatial_distance_from_points( line1mesh, line2points, 200) print(compare) numTrue = 0 for i in compare: if i == True: numTrue += 1 if numTrue > len(compare) / 2: return False else: return True