def extract_areas_from_graph( tg, csv_file, exclude_borders=1, gt_file=None, vtp_file=None): """ Extract triangle areas from a TriangleGraph into a CSV file. Args: tg (TriangleGraph): graph object csv_file (str): CSV file path to be saved exclude_borders (int): if > 0 (default 1), exclude triangles within 1 nm to the triangles at surface border. gt_file (str): if specified, saves changes into this graph file path. vtp_file (str): if specified, saves changes into this surface file path. Returns: None """ # If don't want to include triangles near borders, filter out those if exclude_borders > 0: tg.find_vertices_near_border(exclude_borders, purge=True) # Saving the changes into graph and surface files, if specified: if gt_file is not None: tg.graph.save(gt_file) if vtp_file is not None: # Transforming the resulting graph to a surface with triangles: surf = tg.graph_to_triangle_poly() io.save_vtp(surf, vtp_file) # Getting triangle areas from the graph: triangle_areas = tg.get_vertex_property_array("area") # Writing the triangle areas into a CSV file: df = pd.DataFrame() df["triangleAreas"] = triangle_areas df.to_csv(csv_file, sep=';')
def _extract_distances_from_graph(tg, csv_file, exclude_borders, name, gt_file=None, vtp_file=None): # If don't want to include distances near borders, filter out those if exclude_borders > 0: tg.find_vertices_near_border(exclude_borders, purge=True) # Saving the changes into graph and surface files, if specified: if gt_file is not None: tg.graph.save(gt_file) if vtp_file is not None: # Transforming the resulting graph to a surface with triangles: surf = tg.graph_to_triangle_poly() io.save_vtp(surf, vtp_file) # Getting the distances and triangle areas from the output graph: distances = tg.get_vertex_property_array(name) triangle_areas = tg.get_vertex_property_array("area") # Writing the distances and triangle areas into a csv file: df = pd.DataFrame() df[name] = distances df["triangleAreas"] = triangle_areas df.to_csv(csv_file, sep=';')
def generate_mem_lumen_graph_and_surface(segmentation_mrc_file, pixel_size, mem_surf_outfile, mem_graph_outfile, lbl_mem=2, lbl_mem_lumen=3, mem="cER", smooth=True): """ Extracts inner membrane surface from a segmentation with labels for the membrane and its lumen. Args: segmentation_mrc_file (string): segmentation '.mrc' file path pixel_size (float): pixel size in given units for scaling the surface and the graph mem_surf_outfile (string): membrane surface '.vtp' output file mem_graph_outfile (string): membrane graph '.gt' output file lbl_mem (int, optional): label of the membrane (default 2) lbl_mem_lumen (int, optional): label of the membrane lumen (default=3) mem (str, optional): name of the first membrane (default "cER") smooth (boolean, optional): if True (default), the membrane masks will be smoothed using a Gaussian kernel with sigma 1. Returns: None """ # Extract the three masks: segmentation = io.load_tomo(segmentation_mrc_file) # Generate isosurface around the mask of membrane lumen: if smooth: mem_surface = surface.gen_isosurface(segmentation, lbl_mem_lumen, mask=lbl_mem, sg=1, thr=THRESH_SIGMA1) else: mem_surface = surface.gen_isosurface(segmentation, lbl_mem_lumen, mask=lbl_mem) # Generate graph and remove 3 pixels from borders: mem_tg = TriangleGraph() scale = (pixel_size, pixel_size, pixel_size) mem_tg.build_graph_from_vtk_surface(mem_surface, scale) print('The raw {} graph has {} vertices and {} edges'.format( mem, mem_tg.graph.num_vertices(), mem_tg.graph.num_edges())) mem_tg.find_vertices_near_border(MAX_DIST_SURF * pixel_size, purge=True) print('The cleaned {} graph has {} vertices and {} edges'.format( mem, mem_tg.graph.num_vertices(), mem_tg.graph.num_edges())) if mem_tg.graph.num_vertices() == 0: raise IOError("Graph does not have vertices") # Save final graph as .gt and surface as .vtp files: mem_tg.graph.save(mem_graph_outfile) mem_surf_clean = mem_tg.graph_to_triangle_poly() io.save_vtp(mem_surf_clean, mem_surf_outfile)
def run_calculate_density(mem_graph_file, ribo_mask, scale_factor_to_nm=1, vtp_files_base=None, verbose=False): """ Reads in the membrane graph from a file and calculates ribosome density for each membrane voxel. Args: mem_graph_file (str): name of the input membrane graph file (preferably with '.gt' or '.graphml' extension) ribo_mask (numpy ndarray): binary mask of ribosomes centers on membrane in form of 3D array, where a voxel with value 1 means a particle is present at that membrane coordinate scale_factor_to_nm (float, optional): pixel size in nanometers, default 1 (if the graph was not scaled to nanometers) vtp_files_base (str, optional): if given (default None), the VoxelGraph is converted to VTK PolyData points and lines objects and written to '<vtp_files_base>.vertices.vtp' and '<vtp_files_base>.edges.vtp' files, respectively verbose (boolean, optional): if True (default False), some extra information will be printed out Returns: a numpy ndarray (with the same shape as the mask) with the densities """ t_begin = time.time() # Read in the graph from the file: print('\nReading in the graph from the file {}'.format(mem_graph_file)) vg = VoxelGraph() vg.graph = load_graph(mem_graph_file) print(vg.graph) vg.graph.list_properties() # Fill the dictionary of VoxelGraph, coordinates_to_vertex_index: vg.update_coordinates_to_vertex_index() print('Size of coordinates_to_vertex_index: {}'.format( len(vg.coordinates_to_vertex_index))) # Calculate shortest distances for each node in the graph (membrane voxel) # to each reachable voxel of ribosome center mapped on the membrane, and # from the distances a density measure of ribosomes at each membrane voxel: now = datetime.now() print('\nStarting calculating shortest distances to each reachable ' 'ribosome center and ribosome density for each membrane voxel on: ' '{}-{}-{} {}:{}:{}'.format(now.year, now.month, now.day, now.hour, now.minute, now.second)) densities = vg.calculate_density(ribo_mask.shape, scale_factor_to_nm, mask=ribo_mask, verbose=verbose) now = datetime.now() print('\nFinished calculating the shortest distances and density on: ' '{}-{}-{} {}:{}:{}'.format(now.year, now.month, now.day, now.hour, now.minute, now.second)) vg.graph.list_properties() if vtp_files_base is not None: print('\nConverting the VoxelGraph to a VTK PolyData object and ' 'writing it to .vtp files...') poly_verts, poly_lines = vg.graph_to_points_and_lines_polys() io.save_vtp(poly_verts, vtp_files_base + '.vertices.vtp') io.save_vtp(poly_lines, vtp_files_base + '.edges.vtp') t_end = time.time() duration = t_end - t_begin print('Elapsed time: {} s'.format(duration)) return densities
def run_build_graph_from_np_ndarray_and_calculate_density( mem_mask, ribo_mask, scale_factor_to_nm=1, vtp_files_base=None, verbose=False): """ Builds a graph from a membrane mask and calculates ribosome density for each membrane voxel. Args: mem_mask (numpy ndarray): binary membrane mask in form of 3D array, segmenting the underlying tomogram into membrane (voxels with value 1) and background (voxels with value 0) ribo_mask (numpy ndarray): binary mask of ribosomes centers on membrane in form of 3D array, where a voxel with value 1 means a particle is present at that membrane coordinate scale_factor_to_nm (float, optional): pixel size in nanometers, default 1 (if no scaling to nanometers is desired) vtp_files_base (str, optional): If not None (default None), the VoxelGraph is converted to VTK PolyData points and lines objects and written to '<vtp_files_base>.vertices.vtp' and '<vtp_files_base>.edges.vtp' files, respectively verbose (boolean, optional): if True (default False), some extra information will be printed out Returns: a numpy ndarray (with the same shape as the masks) with the densities Note: Both masks - mem_mask and ribo_mask - have to have the same shape. """ t_begin = time.time() assert (mem_mask.shape == ribo_mask.shape) # Build a graph from the membrane mask: now = datetime.now() print('\nStarting building the VoxelGraph on: {}-{}-{} {}:{}:{}'.format( now.year, now.month, now.day, now.hour, now.minute, now.second)) vg = VoxelGraph() scale3 = (scale_factor_to_nm, scale_factor_to_nm, scale_factor_to_nm) vg.build_graph_from_np_ndarray(mem_mask, scale=scale3, verbose=verbose) now = datetime.now() print('\nFinished building the graph on: {}-{}-{} {}:{}:{}'.format( now.year, now.month, now.day, now.hour, now.minute, now.second)) print(vg.graph) vg.graph.list_properties() # Calculate shortest distances for each node in the graph (membrane voxel) # to each reachable voxel of ribosome center mapped on the membrane, and # from the distances a density measure of ribosomes at each membrane voxel: now = datetime.now() print('\nStarting calculating shortest distances to each reachable ' 'ribosome center and ribosome density for each membrane voxel on: ' '{}-{}-{} {}:{}:{}'.format(now.year, now.month, now.day, now.hour, now.minute, now.second)) densities = vg.calculate_density(mem_mask.shape, scale_factor_to_nm, mask=ribo_mask, verbose=verbose) now = datetime.now() print('\nFinished calculating the shortest distances and density on: ' '{}-{}-{} {}:{}:{}'.format(now.year, now.month, now.day, now.hour, now.minute, now.second)) vg.graph.list_properties() if vtp_files_base is not None: print('\nConverting the VoxelGraph to a VTK PolyData object and ' 'writing it to .vtp files...') poly_verts, poly_lines = vg.graph_to_points_and_lines_polys() io.save_vtp(poly_verts, vtp_files_base + '.vertices.vtp') io.save_vtp(poly_lines, vtp_files_base + '.edges.vtp') t_end = time.time() duration = t_end - t_begin print('Elapsed time: {} s'.format(duration)) return densities
def main(): """ Code generating some surfaces. Returns: None """ fold = "/fs/pool/pool-ruben/Maria/curvature/synthetic_surfaces/" fold2 = "/fs/pool/pool-ruben/Maria/curvature/missing_wedge_sphere/" # Plane pg = PlaneGenerator() plane = pg.generate_plane_surface(half_size=10, res=30) # io.save_vtp(plane, fold + "plane_half_size10_res30.vtp") noisy_plane = add_gaussian_noise_to_surface(plane, percent=10) io.save_vtp(noisy_plane, "{}plane_half_size10_res30_noise10.vtp".format(fold)) # UV Sphere sg = SphereGenerator() sphere = sg.generate_UV_sphere_surface(r=10, latitude_res=50, longitude_res=50) are_triangle_vertices_on_smooth_sphere_surface(sphere, r=10, error=0.001) sphere_noise = add_gaussian_noise_to_surface(sphere, percent=10) io.save_vtp(sphere_noise, fold + "sphere_r10_res50_noise10.vtp") # Sphere from gauss mask sg = SphereGenerator() sphere = sg.generate_gauss_sphere_surface(r=10) io.save_vtp(sphere, "{}gauss_sphere_surf_r10.vtp".format(fold2)) are_triangle_vertices_on_smooth_sphere_surface(sphere, r=10, center=[12, 12, 12], error=0.009) sphere_noise = add_gaussian_noise_to_surface(sphere, percent=10) io.save_vtp(sphere_noise, "{}gauss_sphere_r10_noise10.vtp".format(fold)) # Sphere from gauss mask with missing wedge mask_mrc = "{}gauss_sphere_mask_r10_box25_with_wedge30deg.mrc".format( fold2) surf_vtp = "{}gauss_sphere_surf_r10_with_wedge30deg.vtp".format(fold2) sphere_wedge_30deg_mask = io.load_tomo(mask_mrc) sg = SphereGenerator() sphere_wedge_30deg_surf = sg.generate_gauss_sphere_surface( r=10, mask=sphere_wedge_30deg_mask) io.save_vtp(sphere_wedge_30deg_surf, surf_vtp) # Sphere from smoothed voxel mask without missing wedge r = 20 box = int(2.5 * r) thresh = 0.6 # 0.3 for r=50, 0.45 for r=10, 0.4 for r=20 first mask_mrc = "{}smooth_sphere_r{}_t1_box{}.mrc".format(fold2, r, box) mask = io.load_tomo(mask_mrc) # Isosurface - generates a double surface: isosurf = isosurface_from_mask(mask, threshold=thresh) isosurf_vtp = "{}smooth_sphere_r{}_t1_isosurf_thresh{}.vtp".format( fold2, r, thresh) io.save_vtp(isosurf, isosurf_vtp) # Turn to a voxel mask: bin_mask = (mask > thresh).astype(int) bin_mask_mrc = "{}bin_sphere_r{}_t1_box{}_thresh{}.mrc".format( fold2, r, box, thresh) io.save_numpy(bin_mask, bin_mask_mrc) # and generate signed-surface: surf_base = "{}bin_sphere_r{}_t1_thresh{}".format(fold2, r, thresh) run_gen_surface(bin_mask, surf_base, lbl=1, mask=True) # r=10: 1856 cells # r= 20: 8134 cells # Sphere from smoothed voxel mask with missing wedge mask_mrc = "{}smooth_sphere_r{}_t1_box{}_with_wedge30deg.mrc".format( fold2, r, box) mask = io.load_tomo(mask_mrc) # Isosurface - generates a double surface: isosurf = isosurface_from_mask(mask, threshold=thresh) isosurf_vtp = ( "{}smooth_sphere_r{}_t1_with_wedge30deg_isosurf_thresh{}.vtp".format( fold2, r, thresh)) io.save_vtp(isosurf, isosurf_vtp) # Turn to a voxel mask: bin_mask = (mask > thresh).astype(int) bin_mask_mrc = ( "{}bin_sphere_r{}_t1_box{}_with_wedge30deg_thresh{}.mrc".format( fold2, r, box, thresh)) io.save_numpy(bin_mask, bin_mask_mrc) # and generate signed-surface: surf_base = "{}bin_sphere_r{}_t1_with_wedge30deg_thresh{}".format( fold2, r, thresh) run_gen_surface(bin_mask, surf_base, lbl=1, mask=True) # r=10: 2446 cells # r= 20: 9065 cells with thresh 0.4, 9228 with thresh 0.6 # Cylinder cg = CylinderGenerator() # cylinder_r10_h20 = cg.generate_cylinder_surface(r=10, h=20, res=50) # io.save_vtp(cylinder_r10_h20, fold + "cylinder_r10_h20_res50.vtp") rad = 10 cylinder = cg.generate_gauss_cylinder_surface(rad) io.save_vtp(cylinder, "{}gauss_cylinder_r{}.vtp".format(fold, rad)) # icosphere noise addition chdir(fold) poly = io.load_poly("sphere/ico1280_noise0/sphere_r10.surface.vtp") poly_noise = add_gaussian_noise_to_surface(poly, percent=10) io.save_vtp(poly_noise, "sphere/ico1280_noise10/sphere_r10.surface.vtp") # Torus sg = SaddleGenerator() rr = 25 csr = 10 torus = sg.generate_parametric_torus(rr, csr) io.save_vtp(torus, "{}torus_rr{}_csr{}.vtp".format(fold, rr, csr)) # Cone pg = ConeGenerator() r = 6 h = 8 res = 38 cone = pg.generate_cone(r, h, res) io.save_vtp(cone, "{}cone/cone_r{}_h{}_res{}.vtp".format(fold, r, h, res)) subdiv = 3 decimate = 0.8 iter = 0 cone_smooth = pg.generate_cone(r, h, res, subdiv, decimate, iter, verbose=True) io.save_vtp( cone_smooth, "{}cone/cone_r{}_h{}_res{}_linear_subdiv{}_decimate{}_smooth_iter{}.vtp" .format(fold, r, h, res, subdiv, decimate, iter)) r = 6 h = 6 cone_voxel = pg.generate_voxel_cone_surface(r, h) io.save_vtp(cone_voxel, "{}cone/cone_r{}_h{}.vtp".format(fold, r, h))
shortest_distance(tg.graph, source=v, target=None, weights=tg.graph.ep.distance, dist_map=tg.graph.vp.dist_to_v) # Transform the resulting graph to a surface with triangles: surface_with_dist_to_v = tg.graph_to_triangle_poly() return surface_with_dist_to_v if __name__ == "__main__": rh = 4 v_id = 379 # 89 res = 20 # 10 fold = ("/fs/pool/pool-ruben/Maria/curvature/synthetic_surfaces/plane/" "res{}_noise10/files4plotting/with_borders/".format(res)) in_surface_vtp = "{}plane_half_size{}.VCTV_rh{}.vtp".format(fold, res, rh) out_surface_vtp = "{}plane_half_size{}.VCTV_rh{}_dist_to_v{}.vtp".format( fold, res, rh, v_id) in_surface = io.load_poly(in_surface_vtp) out_surface = calculate_distances_from_triangle(in_surface, scale=(1, 1, 1), triangle_index=v_id, verbose=True) io.save_vtp(out_surface, out_surface_vtp) calculate_g_max_from_radius_hit(4) calculate_g_max_from_radius_hit(8)
from graph_tool import load_graph import os from pycurv import TriangleGraph from pycurv import pycurv_io as io """ Contains a script getting triangle vertices and edges from a TriangleGraph and saving them in to separate VTP file s for visualization with ParaView. Author: Maria Salfer (Max Planck Institute for Biochemistry) """ __author__ = 'Maria Salfer' tg_file = '/fs/pool/pool-ruben/Maria/workspace/github/pycurv/' \ 'experimental_data_sets/ER/AVV/TCB_180830_l2_t2half.ER.AVV_rh10.gt' tg = TriangleGraph() tg.graph = load_graph(tg_file) poly_verts, poly_lines = tg.graph_to_points_and_lines_polys() vtp_files_base = os.path.splitext(tg_file)[0] io.save_vtp(poly_verts, vtp_files_base + '.vertices.vtp') io.save_vtp(poly_lines, vtp_files_base + '.edges.vtp')
def distances_and_thicknesses_calculation(fold, segmentation_file, base_filename, lbl_mem1=1, lbl_mem2=2, lbl_between_mem1_mem2=4, lbl_mem2_lumen=3, pixel_size=1.368, radius_hit=10, maxdist=50, maxthick=80, offset_voxels=1, both_directions=True, reverse_direction=False, mem1="PM", mem2="cER", smooth=True): """ Takes input/output folder, input segmentation MRC file and base name for output files and calculates distances between the first and the second membrane and thicknesses between two sides of the second membrane. Default distance measures are given in nanometers. """ log_file = '{}{}.distances_and_thicknesses_calculation.log'.format( fold, base_filename) sys.stdout = open(log_file, 'a') offset = offset_voxels * pixel_size if not fold.endswith('/'): fold += '/' segmentation_file = '{}{}'.format(fold, segmentation_file) mem1_surf_file = '{}{}.{}.vtp'.format(fold, base_filename, mem1) mem1_graph_file = '{}{}.{}.gt'.format(fold, base_filename, mem1) mem2_surf_file = '{}{}.{}.vtp'.format(fold, base_filename, mem2) mem2_graph_file = '{}{}.{}.gt'.format(fold, base_filename, mem2) mem1_normals_surf_file = '{}{}.{}.NVV_rh{}.vtp'.format( fold, base_filename, mem1, radius_hit) mem1_normals_graph_file = '{}{}.{}.NVV_rh{}.gt'.format( fold, base_filename, mem1, radius_hit) mem2_dist_surf_file = '{}{}.{}.distancesFrom{}.vtp'.format( fold, base_filename, mem2, mem1) mem2_dist_graph_file = '{}{}.{}.distancesFrom{}.gt'.format( fold, base_filename, mem2, mem1) distances_outfile = '{}{}.{}.distancesFrom{}.csv'.format( fold, base_filename, mem2, mem1) if (not isfile(mem1_surf_file) or not isfile(mem1_graph_file) or not isfile(mem2_surf_file) or not isfile(mem2_graph_file)): print('Generating {} and {} graphs and surface files'.format( mem1, mem2)) generate_mem1_mem2_graphs_and_surface(segmentation_file, pixel_size, mem1_graph_file, mem2_surf_file, mem2_graph_file, mem1_surf_file, lbl_mem1, lbl_mem2, lbl_between_mem1_mem2, mem1, mem2, smooth=smooth) if not isfile(mem1_normals_graph_file): print('Estimating normals for {} graph'.format(mem1)) mem1_tg = TriangleGraph() mem1_tg.graph = load_graph(mem1_graph_file) normals_estimation(mem1_tg, radius_hit) mem1_tg.graph.save(mem1_normals_graph_file) mem1_surf = mem1_tg.graph_to_triangle_poly() io.save_vtp(mem1_surf, mem1_normals_surf_file) if not isfile(distances_outfile): print('Calculating and saving distances between {} and {}'.format( mem1, mem2)) run_calculate_distances(mem1_normals_graph_file, mem2_surf_file, mem2_graph_file, mem2_dist_surf_file, mem2_dist_graph_file, distances_outfile, maxdist, offset, both_directions, reverse_direction, mem1) if maxthick > 0: inner_mem2_surf_file = '{}{}.inner{}.vtp'.format( fold, base_filename, mem2) inner_mem2_graph_file = '{}{}.inner{}.gt'.format( fold, base_filename, mem2) inner_mem2_thick_surf_file = '{}{}.inner{}.thicknesses.vtp'.format( fold, base_filename, mem2) inner_mem2_thick_graph_file = '{}{}.inner{}.thicknesses.gt'.format( fold, base_filename, mem2) thicknesses_outfile = '{}{}.inner{}.thicknesses.csv'.format( fold, base_filename, mem2) if not isfile(inner_mem2_surf_file) or not isfile( inner_mem2_graph_file): print('Generating inner {} graphs and surface files'.format(mem2)) generate_mem_lumen_graph_and_surface(segmentation_file, pixel_size, inner_mem2_surf_file, inner_mem2_graph_file, lbl_mem2, lbl_mem2_lumen, mem2, smooth=smooth) if not isfile(thicknesses_outfile): print('Calculating and saving {} thicknesses'.format(mem2)) run_calculate_thicknesses( mem1_normals_graph_file, inner_mem2_surf_file, inner_mem2_graph_file, inner_mem2_thick_surf_file, inner_mem2_thick_graph_file, thicknesses_outfile, maxdist, maxthick, offset, both_directions, reverse_direction, mem2)
def generate_mem1_mem2_graphs_and_surface(segmentation_mrc_file, pixel_size, mem1_graph_outfile, mem2_surf_outfile, mem2_graph_outfile, mem1_surf_outfile=None, lbl_mem1=1, lbl_mem2=2, lbl_between_mem1_mem2=4, mem1="PM", mem2="cER", smooth=True): """ Extracts two membrane surfaces from a segmentations with labels for both membranes and a space between them. Args: segmentation_mrc_file (string): segmentation '.mrc' file path pixel_size (float): pixel size in given units for scaling the surface and the graph mem1_graph_outfile (string): first surface graph '.gt' output file mem2_surf_outfile (string): second surface '.vtp' output file mem2_graph_outfile (string): second surface graph '.gt' output file mem1_surf_outfile (string, optional): first surface '.vtp' output file, if None (default) not generated lbl_mem1 (int, optional): label of first membrane (default 1) lbl_mem2 (int, optional): label of second membrane (default 2) lbl_between_mem1_mem2 (int, optional): label of inter-membrane space (default 4) mem1 (str, optional): name of the first membrane (default "PM") mem2 (str, optional): name of the second membrane (default "cER") smooth (boolean, optional): if True (default), the membrane masks will be smoothed using a Gaussian kernel with sigma 1. Returns: None """ # Extract the three masks: segmentation = io.load_tomo(segmentation_mrc_file) # Generate isosurface around the mask in between the membranes, # applying the first and then the second membrane mask: if smooth: mem1_surface = surface.gen_isosurface(segmentation, lbl_between_mem1_mem2, mask=lbl_mem1, sg=1, thr=THRESH_SIGMA1) mem2_surface = surface.gen_isosurface(segmentation, lbl_between_mem1_mem2, mask=lbl_mem2, sg=1, thr=THRESH_SIGMA1) else: mem1_surface = surface.gen_isosurface(segmentation, lbl_between_mem1_mem2, mask=lbl_mem1) mem2_surface = surface.gen_isosurface(segmentation, lbl_between_mem1_mem2, mask=lbl_mem2) # Generate graphs and remove 3 pixels from borders: mem1_tg = TriangleGraph() scale = (pixel_size, pixel_size, pixel_size) mem1_tg.build_graph_from_vtk_surface(mem1_surface, scale) print('The raw {} graph has {} vertices and {} edges'.format( mem1, mem1_tg.graph.num_vertices(), mem1_tg.graph.num_edges())) mem1_tg.find_vertices_near_border(MAX_DIST_SURF * pixel_size, purge=True) print('The cleaned {} graph has {} vertices and {} edges'.format( mem1, mem1_tg.graph.num_vertices(), mem1_tg.graph.num_edges())) if mem1_tg.graph.num_vertices() == 0: raise IOError("Graph does not have vertices") mem2_tg = TriangleGraph() mem2_tg.build_graph_from_vtk_surface(mem2_surface, scale) print('The raw {} graph has {} vertices and {} edges'.format( mem2, mem2_tg.graph.num_vertices(), mem2_tg.graph.num_edges())) mem2_tg.find_vertices_near_border(MAX_DIST_SURF * pixel_size, purge=True) print('The cleaned {} graph has {} vertices and {} edges'.format( mem2, mem2_tg.graph.num_vertices(), mem2_tg.graph.num_edges())) if mem2_tg.graph.num_vertices() == 0: raise IOError("Graph does not have vertices") # Save final graphs as .gt and surfaces as .vtp files: mem1_tg.graph.save(mem1_graph_outfile) mem2_tg.graph.save(mem2_graph_outfile) if mem1_surf_outfile is not None: mem1_surf_clean = mem1_tg.graph_to_triangle_poly() io.save_vtp(mem1_surf_clean, mem1_surf_outfile) mem2_surf_clean = mem2_tg.graph_to_triangle_poly() io.save_vtp(mem2_surf_clean, mem2_surf_outfile)
def run_calculate_thicknesses(mem1_graph_file, mem2_surf_file, mem2_graph_file, mem2_surf_outfile, mem2_graph_outfile, thicknesses_outfile, maxdist, maxthick, offset=0.0, both_directions=True, reverse_direction=False, mem2="cER", verbose=False): """ A script running calculate_thicknesses with graphs and surface loaded from files, transforming the resulting graph to a surface with triangles and saving the resulting graph and surface into files. All distance measures and in units of the graphs and surfaces Args: mem1_graph_file (str): .gt input file with the first membrane's TriangleGraph with corrected normals mem2_surf_file (str): .vtp input file with the the second membrane's vtkPolyData surface mem2_graph_file (str): .gt input file with the the second membrane's TriangleGraph mem2_surf_outfile: .vtp output file with the the second membrane's vtkPolyData surface with thicknesses mem2_graph_outfile: .gt output file with the the second membrane's TriangleGraph with thicknesses thicknesses_outfile: .csv output file for the thicknesses list maxdist (float): maximal distance from the first to the second membrane maxthick (float): maximal thickness of the second organelle offset (float, optional): positive or negative offset (default 0) to add to the distances, depending on how the surfaces where generated and/or in order to account for membrane thickness both_directions (boolean, optional): if True, look in both directions of each first membrane's normal (default), otherwise only in the normal direction reverse_direction (boolean, optional): if True, look in opposite direction of each first membrane's normals (default=False; if both_directions True, will look in both directions) mem2 (str, optional): name of the second membrane (default "cER") verbose (boolean, optional): if True (default False), some extra information will be printed out Returns: None """ # Load the input files: tg_mem1 = TriangleGraph() tg_mem1.graph = load_graph(mem1_graph_file) surf_mem2 = io.load_poly(mem2_surf_file) tg_mem2 = TriangleGraph() tg_mem2.graph = load_graph(mem2_graph_file) # Calculate distances: d2s = calculate_thicknesses(tg_mem1, tg_mem2, surf_mem2, maxdist, maxthick, offset, both_directions, reverse_direction, mem2, verbose) print("{} d2s".format(len(d2s))) # Save the distances into distances_outfile: df = pd.DataFrame() df["d2"] = d2s df.to_csv(thicknesses_outfile, sep=';') # Transform the modified graph to a surface with triangles: mem2_surf_thick = tg_mem2.graph_to_triangle_poly() # Save the modified graph and surface into files: tg_mem2.graph.save(mem2_graph_outfile) io.save_vtp(mem2_surf_thick, mem2_surf_outfile)
from pycurv import TriangleGraph, calculate_curvedness from pycurv import pycurv_io as io """ A script calculating VTK curvedness for each graph vertex from a GT file generated by a curvature calculation workflow using PyCurv and writing a VTP surface file containing this property. Author: Maria Salfer (Max Planck Institute for Biochemistry) """ __author__ = 'Maria Salfer' # Read in graph GT file tg_file = '/fs/pool/pool-ruben/Maria/workspace/github/pycurv/' \ 'experimental_data_sets/ER/AVV/TCB_180830_l2_t2half.ER.AVV_rh10.gt' tg = TriangleGraph() tg.graph = load_graph(tg_file) # Read in VTK principle curvatures for each vertex, # calculate curvedness and add as a new property tg.graph.vp.vtk_curvedness = tg.graph.new_vertex_property("float") for v in tg.graph.vertices(): v_vtk_kappa_1 = tg.graph.vp.max_curvature[v] v_vtk_kappa_2 = tg.graph.vp.min_curvature[v] v_vtk_curvedness = calculate_curvedness(v_vtk_kappa_1, v_vtk_kappa_2) tg.graph.vp.vtk_curvedness[v] = v_vtk_curvedness # Transform the graph to surface and write to a VTP file surf = tg.graph_to_triangle_poly(verbose=False) surf_file = os.path.splitext(tg_file)[0] + "_VTKcurvedness.vtp" io.save_vtp(surf, surf_file)