def make_manifold(self, verbose=False): """ Reconstruct a manifold clean surface from input mesh. Updates mesh in-place. Requires pymeshfix Parameters ---------- verbose : bool, optional Controls output printing. Default False. """ try: import pymeshfix except: raise ImportError('pymeshfix not installed. Please run: \n' + 'pip install pymeshfix') # Run meshfix import pymeshfix meshfix = pymeshfix.MeshFix(self.v, self.f) meshfix.repair(verbose) # overwrite this object with cleaned mesh self.v = meshfix.v self.f = meshfix.f
def GetClosedTrimesh(self, v, f, data): unzipped_tri = gzip.decompress(data) sub_face_id = [] for i in range(f.shape[0]): if (unzipped_tri[i * 3:i * 3 + 3] == b'\x01\x01\x01'): sub_face_id.append(f[i, :]) part_mesh = pymeshfix.MeshFix(v, np.array(sub_face_id)) part_mesh.repair() part_mesh.plot() # Visualization of cloased meshes # voxels = pv.voxelize(part_mesh, density=part_mesh.length/200) # p = pv.Plotter() # p.add_mesh(voxels, color=True, show_edges=True, opacity=0.5) # p.add_mesh(surface, color="lightblue", opacity=0.5) # p.show() closed_v = part_mesh.v # numpy np.float array closed_f = part_mesh.f # numpy np.int32 array closed_mesh = trimesh.Trimesh(vertices=closed_v, faces=closed_f) closed_mesh.merge_vertices() closed_mesh.remove_degenerate_faces() closed_mesh.remove_duplicate_faces() # print("Volume: ", closed_mesh.volume) # Numpy-stl (mesh) にも同ルーチン有 return closed_mesh
def surface_from_multiwfn(self, file: Union[str, PathLike], fix_mesh: bool = True) -> "Dispersion": """Adds surface from Multiwfn vertex file with connectivity information. Args: file: Vertex.pdb file fix_mesh: Whether to fix holes in the mesh with pymeshfix (recommended) Returns: self: Self """ # Read the vertices and faces from the Multiwfn output file parser = VertexParser(file) vertices = np.array(parser.vertices) faces = np.array(parser.faces) faces = np.insert(faces, 0, values=3, axis=1) # Construct surface and fix it with pymeshfix surface = pv.PolyData(vertices, faces, show_edges=True) if fix_mesh: meshfix = pymeshfix.MeshFix(surface) meshfix.repair() surface = meshfix.mesh # Process surface self._surface = surface self._process_surface() return self
def repair_mesh(mesh: Trimesh) -> Trimesh: """ Repair the given mesh using pymeshfix. """ mf = pymeshfix.MeshFix(mesh.vertices, mesh.faces) mf.repair() return Trimesh(mf.v, mf.f)
def WithVTK(plot=True): """ Tests VTK interface and mesh repair of Stanford Bunny Mesh """ mesh = vtki.PolyData(bunny_scan) meshfix = pymeshfix.MeshFix(mesh) if plot: print('Plotting input mesh') meshfix.Plot() meshfix.Repair() if plot: print('Plotting repaired mesh') meshfix.Plot() return meshfix.mesh
def repair_holes(vertices, faces_): # trimesh has a hole fixing function, but it just deals with # 3 or 4 vertices holes. meshfix = pymeshfix.MeshFix(vertices, faces_) meshfix.repair() vertices = meshfix.v # numpy np.float array faces_ = meshfix.f # numpy np.int32 array # The return mesh has a solid angle of -1 instead of 1. # Correcting this. mesh_ = trimesh.Trimesh(vertices=vertices, faces=faces_) trimesh.repair.fix_normals(mesh_, multibody=False) return mesh_.vertices, mesh_.faces
def test_repair_vtk(): meshin = vtki.PolyData(bunny_scan) meshfix = pymeshfix.MeshFix(meshin) meshfix.repair() # check arrays and output mesh assert np.any(meshfix.v) assert np.any(meshfix.f) meshout = meshfix.mesh assert meshfix.mesh.n_points # test for any holes pdata = meshout.extract_edges(non_manifold_edges=False, feature_edges=False, manifold_edges=False) assert pdata.n_points == 0
def test_repairVTK(): meshin = vtki.PolyData(bunny_scan) meshfix = pymeshfix.MeshFix(meshin) meshfix.Repair() # check arrays and output mesh assert np.any(meshfix.v) assert np.any(meshfix.f) meshout = meshfix.mesh assert meshfix.mesh.GetNumberOfPoints() # test for any holes pdata = meshout.ExtractEdges(non_manifold_edges=False, feature_edges=False, manifold_edges=False) assert pdata.GetNumberOfPoints() == 0
import pyvista as pv import pymeshfix as mf from pyvista import examples ################################################################################ bunny = examples.download_bunny() # Define a camera position that shows the holes in the mesh cpos = [(-0.2, -0.13, 0.12), (-0.015, 0.10, -0.0), (0.28, 0.26, 0.9)] # Show mesh bunny.plot(cpos=cpos) ################################################################################ # Genereate a meshfix mesh ready for fixing and extract the holes meshfix = mf.MeshFix(bunny) holes = meshfix.extract_holes() ################################################################################ # Render the mesh and outline the holes p = pv.Plotter() p.add_mesh(bunny, color=True) p.add_mesh(holes, color='r', line_width=8) p.camera_position = cpos p.enable_eye_dome_lighting() # helps depth perception p.show() ################################################################################ # Repair the mesh meshfix.repair(verbose=True)
def make(self, key): print("----------Working on " + str(key['segment_id']) + ":----------") split_significance_threshold = 200 global_time = time.time() #get the mesh with the error segments filtered away start_time = time.time() mesh, face_indexes = get_mesh_minus_errors_and_spines(key) new_key = dict(segmentation=key["segmentation"], segment_id=key["segment_id"]) """ Handle the poosibility that there is no mesh """ if len(mesh.faces) < 50: print( f"There were only {len(mesh.faces)} faces in mesh so not doing skeletonization" ) new_key["n_edges"] = 0 new_key["edges"] = np.array([]).astype(float) new_key["n_bodies"] = 0 new_key["n_bodies_stitched"] = 0 new_key["largest_mesh_perc"] = 0 new_key["largest_mesh_distance_perc"] = 0 new_key["n_faces_in_filtered"] = len(face_indexes) new_key["faces_in_filtered"] = face_indexes self.insert1(new_key, skip_duplicates=True) else: print( f"Step 1: Retrieving Mesh and removing error segments: {time.time() - start_time}" ) # Don't need these attributes #vertices=key["vertices"], # triangles=new_key["triangles"],n_vertices=key["n_vertices"], # n_triangles=key["n_triangles"]) start_time = time.time() """ OLDER WAY OF JUST GETTING THE LARGEST MESH PIECE count, labels = trimesh_io.trimesh.graph.csgraph.connected_components( mesh.edges_sparse, directed=False, return_labels=True) label_counter = Counter(labels) new_key["n_bodies"] = count values = np.array(labels) list_counter = Counter(labels) max_counter = max(list_counter.values()) max_label = -1 for label_key,label_number in list_counter.items(): if label_number==max_counter: max_label = label_key print("max label = " + str(max_label)) searchval = max_label ii = np.where(values == searchval)[0] new_key["largest_mesh_perc"] = len(ii)/len(labels) print("n_bodies = " + str(new_key["n_bodies"])) print("largest mesh perc = " + str(new_key["largest_mesh_perc"])) """ total_splits = mesh.split(only_watertight=False) print( f"There were {len(total_splits)} after split and significance threshold" ) mesh_pieces = [ k for k in total_splits if len(k.faces) > split_significance_threshold ] print( f"There were {len(mesh_pieces)} after split and significance threshold" ) for g, mh in enumerate(mesh_pieces): print(f"Mesh piece {g} with number of faces {len(mh.faces)}") print( f"Step 2a: Getting the number of splits: {time.time() - start_time}" ) #get the largest mesh piece largest_mesh_index = -1 largest_mesh_size = 0 for t, msh in enumerate(mesh_pieces): if len(msh.faces) > largest_mesh_size: largest_mesh_index = t largest_mesh_size = len(msh.faces) #largest mesh piece largest_mesh_perc = largest_mesh_size / len(mesh.faces) new_key["largest_mesh_perc"] = largest_mesh_perc print("largest mesh perc = " + str(largest_mesh_perc)) largest_mesh_skeleton_distance = -1 paths_used = [] total_edges = np.array([]) for h, m in enumerate(mesh_pieces): print(f"Working on split {h} with face total = {len(m.faces)}") # start_time = time.time() # #pass the vertices and faces to pymeshfix to become watertight # meshfix = pymeshfix.MeshFix(m.vertices,m.faces) # meshfix.repair(verbose=False,joincomp=True,remove_smallest_components=False) # print(f"Step 2b: Pymesh shrinkwrapping: {time.time() - start_time}") # #print("Step 2: Writing Off File") # start_time = time.time() # #write the new mesh to off file # path_and_filename,filename,file_loc = write_Whole_Neuron_Off_file(str(new_key["segment_id"]) + "_piece_" + str(h),meshfix.v,meshfix.f) # print(f"Step 3: Writing shrinkwrap off file: {time.time() - start_time}") #add the path to be deleted later #send the data through the hole patching function from pymesh: cleaned_verts, cleaned_triangles = clean_from_arrays_celii( m.vertices, m.faces, verbose=True, joincomp=True, remove_smallest_components=False, clean=False) #cleaned_mesh = make_trimesh_object(m.vertices,m.faces) path_and_filename, filename, file_loc = write_Whole_Neuron_Off_file( str(new_key["segment_id"]) + "_piece_" + str(h), cleaned_verts, cleaned_triangles) paths_used.append(path_and_filename) #Run the meshlabserver scripts start_time = time.time() #output_mesh = meshlab_fix_manifold_path(path_and_filename,key["segment_id"]) meshlab_script = str( pathlib.Path.cwd()) + "/" + "pymesh_fix_substitute_2.mls" output_mesh = meshlab_fix_manifold_path_specific_mls( path_and_filename, key["segment_id"], meshlab_script) meshlab_script_2 = str( pathlib.Path.cwd()) + "/" + "remove_intersecting_faces.mls" output_mesh = meshlab_fix_manifold_path_specific_mls( output_mesh, key["segment_id"], meshlab_script_2) print("About to run pymeshfix") start_time_py = time.time() loaded_mesh = trimesh.load_mesh(output_mesh, process=False) meshfix = pymeshfix.MeshFix(loaded_mesh.vertices, loaded_mesh.faces) meshfix.repair(verbose=False, joincomp=True, remove_smallest_components=False) print( f"Total time for pymeshfix = {time.time() - start_time_py}" ) path_and_filename, filename, file_loc = write_Whole_Neuron_Off_file( str(new_key["segment_id"]) + "_piece_" + str(h), meshfix.v, meshfix.f) print( f"Step 4: Meshlab fixing non-manifolds: {time.time() - start_time}" ) print(path_and_filename) #send to be skeletonized start_time = time.time() mls_mesh = trimesh.load_mesh(path_and_filename + ".off") if len(mls_mesh.faces) < 20: print( "Number of faces are less than 20 so not generating skeleton" ) continue return_value = cm.calcification(path_and_filename) if return_value > 0: raise Exception( 'skeletonization for neuron ' + str(new_key["segment_id"]) + ' did not finish... exited with error code: ' + str(return_value)) print("Trying skeletonization with pymesh") #try to run the same skeletonization but now with skeletonization # start_time = time.time() #pass the vertices and faces to pymeshfix to become watertight meshfix = pymeshfix.MeshFix(mls_mesh.vertices, mls_mesh.faces) meshfix.repair(verbose=False, joincomp=True, remove_smallest_components=False) print( f"Step 2b: Pymesh shrinkwrapping: {time.time() - start_time}" ) if len(meshfix.f) < 20: print( "Number of faces are less than 20 so not generating skeleton" ) continue #print("Step 2: Writing Off File") start_time = time.time() #write the new mesh to off file path_and_filename, filename, file_loc = write_Whole_Neuron_Off_file( str(new_key["segment_id"]) + "_piece_" + str(h), meshfix.v, meshfix.f) print( f"Step 3: Writing shrinkwrap off file: {time.time() - start_time}" ) #add the path to be deleted later paths_used.append(path_and_filename) #Run the meshlabserver scripts start_time = time.time() #output_mesh = meshlab_fix_manifold_path(path_and_filename,key["segment_id"]) meshlab_script = str(pathlib.Path.cwd( )) + "/" + "pymesh_fix_substitute_2.mls" output_mesh = meshlab_fix_manifold_path_specific_mls( path_and_filename, key["segment_id"], meshlab_script) print( f"Step 4: Meshlab fixing non-manifolds: {time.time() - start_time}" ) #print(output_mesh[:-4]) #send to be skeletonized start_time = time.time() mls_mesh = trimesh.load_mesh(output_mesh) if len(mls_mesh.faces) < 20: print( "Number of faces are less than 20 so not generating skeleton" ) continue return_value = cm.calcification(output_mesh[:-4]) if return_value > 0: raise Exception( 'skeletonization for neuron ' + str(new_key["segment_id"]) + ' did not finish EVEN AFTER TRYING PYMESH... exited with error code: ' + str(return_value)) print( f"Step 5: Generating Skeleton: {time.time() - start_time}") #read in the skeleton files into an array bone_array = read_skeleton_revised(path_and_filename + "_skeleton.cgal") #print(bone_array) if len(bone_array) <= 0: raise Exception('No skeleton generated for ' + str(new_key["segment_id"])) print( f"Step 5: Generating and reading Skeleton: {time.time() - start_time}" ) #get the largest mesh skeleton distance if h == largest_mesh_index: largest_mesh_skeleton_distance = find_skeleton_distance( bone_array) #add the skeleton edges to the total edges if not total_edges.any(): total_edges = bone_array else: total_edges = np.vstack([total_edges, bone_array]) total_edges_stitched = stitch_skeleton_with_degree_check( total_edges) #get the total skeleton distance for the stitched skeleton total_skeleton_distance = find_skeleton_distance( total_edges_stitched) largest_mesh_distance_perc = largest_mesh_skeleton_distance / total_skeleton_distance start_time = time.time() new_key["n_edges"] = len(total_edges_stitched) new_key["edges"] = total_edges_stitched new_key["n_bodies"] = len(total_splits) new_key["n_bodies_stitched"] = len(mesh_pieces) new_key["largest_mesh_perc"] = largest_mesh_perc new_key["largest_mesh_distance_perc"] = largest_mesh_distance_perc new_key["n_faces_in_filtered"] = len(face_indexes) new_key["faces_in_filtered"] = face_indexes #print("new_key=" + str(new_key)) self.insert1(new_key, skip_duplicates=True) print(f"Step 6: Inserting dictionary: {time.time() - start_time}") #raise Exception("done with one neuron") for path_and_filename in paths_used: os.system("rm " + str(path_and_filename) + "*") print(f"Total time: {time.time() - global_time}") print("\n\n")
def make(self, key): global_time = time.time() #get the mesh with the error segments filtered away start_time = time.time() print(str(key['segment_id']) + ":") my_dict = (pinky.Mesh & pinky.Neurite.proj() & pinky.CurrentSegmentation & key).fetch1() print( f"Step 1: Retrieving Mesh and removing error segments: {time.time() - start_time}" ) new_key = dict(segmentation=key["segmentation"], segment_id=key["segment_id"]) # Don't need these attributes #vertices=key["vertices"], # triangles=new_key["triangles"],n_vertices=key["n_vertices"], # n_triangles=key["n_triangles"]) start_time = time.time() #pass the vertices and faces to pymeshfix to become watertight mesh = trimesh_io.Mesh(vertices=my_dict["vertices"], faces=my_dict["triangles"]) count, labels = trimesh_io.trimesh.graph.csgraph.connected_components( mesh.edges_sparse, directed=False, return_labels=True) label_counter = Counter(labels) new_key["n_bodies"] = count values = np.array(labels) list_counter = Counter(labels) max_counter = max(list_counter.values()) max_label = -1 for label_key, label_number in list_counter.items(): if label_number == max_counter: max_label = label_key print("max label = " + str(max_label)) searchval = max_label ii = np.where(values == searchval)[0] new_key["largest_mesh_perc"] = len(ii) / len(labels) print("n_bodies = " + str(new_key["n_bodies"])) print("largest mesh perc = " + str(new_key["largest_mesh_perc"])) print( f"Step 2a: Getting the number of splits: {time.time() - start_time}" ) start_time = time.time() #pass the vertices and faces to pymeshfix to become watertight meshfix = pymeshfix.MeshFix(my_dict["vertices"], my_dict["triangles"]) meshfix.repair(verbose=False, joincomp=True, remove_smallest_components=False) print(f"Step 2b: Pymesh shrinkwrapping: {time.time() - start_time}") #print("Step 2: Writing Off File") start_time = time.time() #write the new mesh to off file path_and_filename, filename, file_loc = write_Whole_Neuron_Off_file( str(new_key["segment_id"]), meshfix.v, meshfix.f) print( f"Step 3: Writing shrinkwrap off file: {time.time() - start_time}") #Run the meshlabserver scripts start_time = time.time() output_mesh = meshlab_fix_manifold(key) print( f"Step 4: Meshlab fixing non-manifolds: {time.time() - start_time}" ) print(output_mesh[:-4]) #send to be skeletonized start_time = time.time() return_value = cm.calcification(output_mesh[:-4]) if return_value > 0: raise Exception('skeletonization for neuron ' + str(new_key["segment_id"]) + ' did not finish... exited with error code: ' + str(return_value)) #print(f"Step 5: Generating Skeleton: {time.time() - start_time}") #read in the skeleton files into an array bone_array = read_skeleton_revised(output_mesh[:-4] + "_skeleton.cgal") #print(bone_array) if len(bone_array) <= 0: raise Exception('No skeleton generated for ' + str(new_key["segment_id"])) print( f"Step 5: Generating and reading Skeleton: {time.time() - start_time}" ) start_time = time.time() new_key["n_edges"] = len(bone_array) new_key["edges"] = bone_array #new_key["branches"] = [] #print(key) #if all goes well then write to database self.insert1(new_key, skip_duplicates=True) #raise Exception("done with one neuron") os.system("rm " + str(path_and_filename) + "*") print(f"Step 6: Inserting dictionary: {time.time() - start_time}") print(f"Total time: {time.time() - global_time}") print("\n\n")
def open_mesh(self): """ add a mesh to the pyqt frame """ global int_surface, ext_surface, mesh_vol, mesh global x_range, y_range, z_range, Vol_centroid global open_mesh_run global mesh_name # track pre-processing starting time open_mesh_start = time.time() # open file file_info = QtWidgets.QFileDialog.getOpenFileName() file_path = file_info[0] # determine file type and if conversion needed _, file_name = os.path.split(file_path) mesh_name, mesh_type = os.path.splitext(file_name) # read mesh & transform according to principal axes print(file_path) pre = trimesh.load(file_path) orient = pre.principal_inertia_transform pre = pre.apply_transform(orient) post_file_path = 'data/'+ mesh_name + '_oriented.stl' pre.export(post_file_path) ext_surface = pv.read(post_file_path) # scale meshes accordingly if mesh_name == 'elephant': ext_surface.points *= 12 # Elephant elif mesh_name == 'Bracket S24D1': ext_surface.points /= 10 # Bracket elif mesh_name == 'knight': ext_surface.points /= 2 # Knight # create internal offset thickness = 0.1 # inches grid = pv.create_grid(ext_surface).triangulate() solid = grid.clip_surface(ext_surface) solid.compute_implicit_distance(ext_surface, inplace=True) imp_dis_max = max(solid['implicit_distance']) shell_threshold = imp_dis_max - thickness shell = solid.clip_scalar('implicit_distance', value = shell_threshold) int_surface = shell.extract_geometry() meshfix = mf.MeshFix(int_surface) meshfix.repair(verbose=True) mesh = solid.clip_surface(int_surface, invert=False) # print mesh info print("Mesh Name:", mesh_name) print("Mesh Type:", mesh_type[1:]) # find mesh centroid and translate the mesh so that's the origin Vol_centroid = np.array([0,0,0]) self.skewed_centroid_action.setCheckable(True) # reset plotter self.reset_plotter(Vol_centroid) # find the max and min of x,y,z axes of mesh ranges = mesh.bounds x_range = abs(ranges[0] - ranges[1]) y_range = abs(ranges[2] - ranges[3]) z_range = abs(ranges[4] - ranges[5]) print("x:", float(format(x_range, ".2f")), "in") print("y:", float(format(y_range, ".2f")), "in") print("z:", float(format(z_range, ".2f")), "in") # mesh volume mesh_vol = float(format(mesh.volume, ".2f")) print("Mesh Volume:", mesh_vol, "in^3") # track pre-processing ending time & duration open_mesh_end = time.time() open_mesh_run = open_mesh_end - open_mesh_start print("Pre-Processing run time: %g seconds" % (open_mesh_run)) print("Mesh Cells:", mesh.n_cells)
import pyvista as pv import pymeshfix as mf from pyvista import examples mesh = examples.download_torso() print(mesh) ################################################################################ cpos = [(-1053., -1251., 83.), (2., -15., -276.), (0.12, 0.18, 1)] mesh.plot(color=True, show_edges=True, cpos=cpos) ################################################################################ # Appy a triangle filter to ensure the mesh is simply polyhedral meshfix = mf.MeshFix(mesh.tri_filter()) holes = meshfix.extract_holes() ################################################################################ # Outline the holes in the mesh p = pv.Plotter() p.add_mesh(mesh) p.add_mesh(holes, color='r', line_width=8) p.enable_eye_dome_lighting() # helps with depth perception p.camera_position = cpos p.show() ################################################################################ # Emphasize the hole near the ear - this needs to be repaired so that the mesh # is absolutely water tight. cpos_ear = [(180., -206., 17.), (107., -122.9, -11.9), (-0.13, 0.22, 0.96)]
def SimplifyMeshSubj(self): '''Function to simplify a mesh from a subject folder, the simplification also cleans problems and suppresses small disconnected objects. The meshes created are displayed for the user to check that there aren´t any problems, close the window of the displayed mesh for the script to continue. The function doesn´t return outputs, it saves the new faces and vertices in .npy files in the subject folder. Function call: SimplifyMeshSubj()''' ###### Mesh simplification warnings.filterwarnings("ignore") proceed = True if os.path.isfile(os.path.join(self.Subj_folder, 'vertices_simple.npy')) and\ os.path.isfile(os.path.join(self.Subj_folder,'faces_simple.npy')): print( 'Simplified mesh already exists, do you want to re-calculate?') proceed_ = input("Yes(y)/No(n): ") if proceed_ == 'y' or proceed_ == 'Y': proceed = True else: proceed = False if proceed: # Plots the original surf # Plot the final reduced mesh if self.quiet == 0: print('Loaded mesh. Close window to proceed!') mlab.triangular_mesh(self.vertices_full[:, 0], self.vertices_full[:, 1], self.vertices_full[:, 2], self.faces_full) mlab.show() ######## GM ######## print('Simplifying cortical surface') ####### Initial Mesh cleaning (fixes problems and deletes disconnected components) repaired = fix.MeshFix(self.vertices_full, self.faces_full) repaired.repair() vertices_simple = repaired.v faces_simpl = repaired.f ######## Mesh decimation ######## x = vertices_simple[:, 0] y = vertices_simple[:, 1] z = vertices_simple[:, 2] mesh = mlab.pipeline.triangular_mesh_source( x, y, z, faces_simpl) # creates mesh structure dec = mlab.pipeline.quadric_decimation( mesh) # Creates the decimation filter dec.filter.target_reduction = self.reductions_ratio # Set the decimation value (reduces to 25%,changed due to post-fixing) new_nodes = np.array( dec.outputs[0]._get_output()._get_points()) # Get the nodes new_faces = np.array( dec.outputs[0]._get_output()._get_polys()._get_data()).astype( int) # get the faces bad_index = range( 0, len(new_faces), 4 ) # values to discard (probably reference to the number of nodes in the face) new_faces = np.delete(new_faces, bad_index) # obtain the real face values new_faces = np.reshape(new_faces, (-1, 3)) # generate the faces matrix ####### Final Mesh cleaning (fixes problems and deletes disconnected components) repaired = fix.MeshFix(new_nodes, new_faces) repaired.repair() vertices_simple = repaired.v faces_simple = repaired.f if self.quiet == 0: # Plot the final reduced mesh print('Check the mesh! Close the window to proceed!') mlab.triangular_mesh(vertices_simple[:, 0], vertices_simple[:, 1], vertices_simple[:, 2], faces_simple) mlab.show() print('Done!') # Calculates normals! print('Calculating faces normals!') # Calculates faces normals with trimesh meshTRIM_simply = trimesh.Trimesh(vertices_simple, faces_simple) trimesh.repair.fix_inversion(meshTRIM_simply, multibody=True) trimesh.repair.fix_normals(meshTRIM_simply, multibody=True) #Updates attributes of the class! self.vertices_simple = meshTRIM_simply.vertices self.faces_simple = np.int32(meshTRIM_simply.faces) s_snorm = meshTRIM_simply.face_normals # Saves nodes and faces! np.save(os.path.join(self.Subj_folder, 'vertices_simple.npy'), self.vertices_simple) np.save(os.path.join(self.Subj_folder, 'faces_simple.npy'), self.faces_simple) print('Done!') print('Calculating faces/normals areas!') self.Area_calc() print('Done!') print('Calculates normals in each node!') self.normals_simple = self.triangles2nodes(data_2_remap=s_snorm, normalize=True) np.save(os.path.join(self.Subj_folder, 'normals_simple.npy'), self.normals_simple) print('Done!') print( 'Calculates dot products of normals (convenient for EMOD calculation)!' ) n = self.normals_simple.shape[0] normals_vector = np.zeros(np.int(0.5 * n * (n - 1) + n)) finish_vector = 1 init_vector = 0 final_node = 1 for i in self.normals_simple: nodes2use = self.normals_simple[0:final_node, ] dot_norm = np.dot(nodes2use, i) normals_vector[init_vector:finish_vector] = dot_norm init_vector = finish_vector finish_vector = init_vector + dot_norm.shape[0] + 1 final_node = final_node + 1 np.save(os.path.join(self.Subj_folder, 'dot_normals_half.npy'), np.float32(normals_vector)) print('Done!') print( 'Calculates products of areas (convenient for EMOD calculation)!' ) n = self.area_nodes_simple.shape[0] areas_vector = np.zeros(np.int(0.5 * n * (n - 1) + n)) single_areas_vector = np.zeros(np.int(0.5 * n * (n - 1) + n)) finish_vector = 1 init_vector = 0 final_node = 1 for i in progressbar.progressbar(self.area_nodes_simple): nodes2use = self.area_nodes_simple[0:final_node, ] dot_norm = nodes2use * i dot_norm_single = i * np.ones(np.shape(nodes2use)) areas_vector[init_vector:finish_vector] = dot_norm single_areas_vector[ init_vector:finish_vector] = dot_norm_single init_vector = finish_vector finish_vector = init_vector + dot_norm.shape[0] + 1 final_node = final_node + 1 np.save(os.path.join(self.Subj_folder, 'dot_areas_half.npy'), np.float32(areas_vector)) np.save( os.path.join(self.Subj_folder, 'dot_areas_single_half.npy'), np.float32(single_areas_vector)) print('Done!') print( 'Saved simplified mesh and its attributes in subject folder!') else: self.vertices_simple = np.load( os.path.join(self.Subj_folder, 'vertices_simple.npy')) self.faces_simple = np.load( os.path.join(self.Subj_folder, 'faces_simple.npy')) self.normals_simple = np.load( os.path.join(self.Subj_folder, 'normals_simple.npy')) self.area_nodes_simple = np.load( os.path.join(self.Subj_folder, 'area_per_node.npy')) self.area_faces_simple = np.load( os.path.join(self.Subj_folder, 'area_per_face.npy'))
mesh = examples.download_torso() print(mesh) ################################################################################ cpos = [(-1053., -1251., 83.), (2., -15., -276.), (0.12, 0.18, 1)] mesh.plot(color=True, show_edges=True, cpos=cpos) ################################################################################ # Appy a triangle filter to ensure the mesh is simply polyhedral meshfix = mf.MeshFix(mesh.triangulate()) holes = meshfix.extract_holes() ################################################################################ # Outline the holes in the mesh p = pv.Plotter() p.add_mesh(mesh) p.add_mesh(holes, color='r', line_width=8) p.enable_eye_dome_lighting() # helps with depth perception p.camera_position = cpos p.show() ################################################################################ # Emphasize the hole near the ear - this needs to be repaired so that the mesh # is absolutely water tight. cpos_ear = [(180., -206., 17.),
""" Functional Test: vtk and native """ out_file = 'repaired.ply' Native() outmesh = vtki.PolyData(out_file) os.remove(out_file) assert outmesh.GetNumberOfPoints() # test for any holes pdata = outmesh.ExtractEdges(non_manifold_edges=False, feature_edges=False, manifold_edges=False) assert pdata.GetNumberOfPoints() == 0 # test vtk meshin = vtki.PolyData(bunny_scan) meshfix = pymeshfix.MeshFix(meshin) meshfix.Repair() # check arrays and output mesh assert np.any(meshfix.v) assert np.any(meshfix.f) meshout = meshfix.mesh assert meshfix.mesh.GetNumberOfPoints() # test for any holes pdata = meshout.ExtractEdges(non_manifold_edges=False, feature_edges=False, manifold_edges=False) assert pdata.GetNumberOfPoints() == 0 print('PASS')
import numpy as np ################################################################################ cow = examples.download_cow() # Add holes and cast to triangulated PolyData cow['random'] = np.random.rand(cow.n_cells) holy_cow = cow.threshold(0.9, invert=True).extract_geometry().tri_filter() print(holy_cow) ################################################################################ # A nice camera location of the cow cpos = [(6.56, 8.73, 22.03), (0.77, -0.44, 0.0), (-0.13, 0.93, -0.35)] meshfix = mf.MeshFix(holy_cow) holes = meshfix.extract_holes() # Render the mesh and outline the holes p = pv.Plotter() p.add_mesh(holy_cow, color=True) p.add_mesh(holes, color='r', line_width=8) p.camera_position = cpos p.enable_eye_dome_lighting() # helps depth perception p.show() ################################################################################ # Repair the holey cow meshfix.repair(verbose=True)
def make(self, key): global_time = time.time() #get the mesh with the error segments filtered away start_time = time.time() new_key = remove_error_segments(key) print(f"Step 1: Retrieving Mesh and removing error segments: {time.time() - start_time}") #where i deal with the error segments if new_key["vertices"].size<2: start_time = time.time() print("All faces were error segments, inserting dummy entry") #create the key with None new_key["n_vertices"] = 0 new_key["n_triangles"] = 0 new_key["vertices"] = np.array([]).astype(float) new_key["triangles"] = np.array([]).astype(float) new_key["n_edges"] = 0 new_key["edges"] = np.array([]).astype(float) self.insert1(new_key,skip_duplicates=True) #insert dummy dictionary into correspondence table # new_correspondence_dict = dict(segmentation=key["segmentation"], # segment_id=key["segment_id"], # time_updated=str(datetime.datetime.now()), # n_correspondence = 0, # correspondence=np.array([]).astype(float)) # #if all goes well then write to correspondence database # ta3p100.NeuronRawSkeletonCorrespondence.insert1(new_correspondence_dict,skip_duplicates=True) print(f"Step 2: Inserting dummy dictionary: {time.time() - start_time}") print(f"Total time: {time.time() - global_time}") print("\n\n") else: #print("Step 2: Remove all error semgents") start_time = time.time() #pass the vertices and faces to pymeshfix to become watertight meshfix = pymeshfix.MeshFix(new_key["vertices"],new_key["triangles"]) meshfix.repair(verbose=False,joincomp=True,remove_smallest_components=False) print(f"Step 2: Pymesh shrinkwrapping: {time.time() - start_time}") #print("Step 2: Writing Off File") start_time = time.time() #write the new mesh to off file path_and_filename,filename,file_loc = write_Whole_Neuron_Off_file(str(new_key["segment_id"]),meshfix.v,meshfix.f) print(f"Step 3: Writing shrinkwrap off file: {time.time() - start_time}") #Run the meshlabserver scripts start_time = time.time() output_mesh = meshlab_fix_manifold(key) print(f"Step 4: Meshlab fixing non-manifolds: {time.time() - start_time}") print(output_mesh[:-4]) #send to be skeletonized start_time = time.time() return_value = cm.calcification(output_mesh[:-4]) if return_value > 0: raise Exception('skeletonization for neuron ' + str(new_key["segment_id"]) + ' did not finish... exited with error code: ' + str(return_value)) #print(f"Step 5: Generating Skeleton: {time.time() - start_time}") #read in the skeleton files into an array #start_time = time.time() ##****** this needs to be changed for reading them in****** bone_array = read_skeleton_revised(output_mesh[:-4]+"_skeleton.cgal") #correspondence_array = read_skeleton_revised(output_mesh[:-4]+"_correspondance.cgal") #print(bone_array) if len(bone_array) <= 0: raise Exception('No skeleton generated for ' + str(new_key["segment_id"])) # if len(correspondence_array) <= 0: # raise Exception('No CORRESPONDENCE generated for ' + str(new_key["segment_id"])) print(f"Step 5: Generating and reading Skeleton: {time.time() - start_time}") start_time = time.time() new_key["n_edges"] = bone_array.shape[0] new_key["edges"] = bone_array #new_key["branches"] = [] #print(key) #if all goes well then write to database self.insert1(new_key,skip_duplicates=True) #create a new dictionary key to be inserted into correspondence table """ time_updated :timestamp # the time at which the component labels were updated --- n_correspondence :int unsigned #number of mappings from skeleton vert to original surface vert correspondence :longblob #array storing mapping of every skeleton vert to original surface vert """ # #insert dummy dictionary into correspondence table # new_correspondence_dict = dict(segmentation=key["segmentation"], # segment_id=key["segment_id"], # time_updated=str(datetime.datetime.now()), # n_correspondence = correspondence_array.shape[0], # correspondence=correspondence_array) # #if all goes well then write to correspondence database # ta3p100.NeuronRawSkeletonCorrespondence.insert1(new_correspondence_dict,skip_duplicates=True) os.system("rm "+str(path_and_filename)+"*") print(f"Step 6: Inserting both dictionaries: {time.time() - start_time}") print(f"Total time: {time.time() - global_time}") print("\n\n")