Source code for cellcomplex.property_topomesh.utils.matplotlib_tools

import logging

import numpy as np

from cellcomplex.property_topomesh.analysis import compute_topomesh_property, is_triangular

from matplotlib import cm
from matplotlib import tri
from matplotlib.colors import Normalize
from matplotlib.collections import PolyCollection, LineCollection, EllipseCollection
import matplotlib.pyplot as plt

[docs]def plot_tensor_data(figure, X, Y, tensors, C=None, tensor_style='crosshair', color='k', colormap='jet', value_range=None, scale=1., linewidth=1, alpha=1.): """ Parameters ---------- figure X Y tensors C tensor_style color colormap value_range scale linewidth alpha Returns ------- """ assert tensor_style in ['crosshair','ellipse'] if C is not None: if value_range is None: value_range = (np.nanmin(C), np.nanmax(C)) norm = Normalize(vmin=value_range[0], vmax=value_range[1]) evals, evecs = np.linalg.eigh(tensors) evecs = np.array([np.transpose(vec[:,np.argsort(val)[::-1]]) for val,vec in zip(evals,evecs)]) evals = np.array([val[np.argsort(val)[::-1]] for val,vec in zip(evals,evecs)]) if tensor_style == 'ellipse': thetas = np.degrees(np.arctan2(evecs[:, 0, 0], evecs[:, 0, 1])) widths, heights = np.transpose(2. * scale * np.sqrt(np.maximum(0,evals)[:,:2])) if C is not None: ellipse_collection = EllipseCollection(widths, heights, thetas, offsets=np.transpose([X,Y]), array=C, units='x', transOffset=figure.gca().transData, linewidth=linewidth, alpha=alpha, cmap=colormap, norm=norm) else: ellipse_collection = EllipseCollection(widths, heights, thetas, offsets=np.transpose([X,Y]), color=color, units='x', transOffset=figure.gca().transData, linewidth=linewidth, alpha=alpha) figure.gca().add_collection(ellipse_collection) plot_to_return = ellipse_collection elif tensor_style == 'crosshair': vector_points = np.concatenate([np.transpose([[X - scale*evals[:,k]*evecs[:,k,0], X + scale*evals[:,k]*evecs[:,k,0]],[Y - scale*evals[:,k]*evecs[:,k,1],Y + scale*evals[:,k]*evecs[:,k,1]]]) for k in range(3)]) if C is not None: line_collection = LineCollection([p[:,:2] for p in vector_points], array=C, linewidth=linewidth, alpha=alpha, cmap=colormap, norm=norm) else: line_collection = LineCollection([p[:,:2] for p in vector_points], color=color, linewidth=linewidth, alpha=alpha) figure.gca().add_collection(line_collection) plot_to_return = line_collection return plot_to_return
[docs]def mpl_draw_topomesh(topomesh,figure,degree=2,coef=1,property_name="",property_degree=None,colormap='viridis',color='k',alpha=1.0,cell_edges=False,intensity_range=None,linewidth=1,size=40,plot_ids=False): """ Parameters ---------- topomesh figure degree coef property_name property_degree colormap color alpha cell_edges intensity_range linewidth size plot_ids Returns ------- """ if property_degree is None: property_degree = degree plot_to_return = None positions = topomesh.wisp_property('barycenter',0) if (degree>0) & (topomesh.nb_wisps(2)>0): if not topomesh.has_wisp_property('vertices',degree=2,is_computed=True): compute_topomesh_property(topomesh,'vertices',2) faces = topomesh.wisp_property('vertices',2).values(list(topomesh.wisps(2))) if not topomesh.has_wisp_property('barycenter',degree=2,is_computed=True): compute_topomesh_property(topomesh,'barycenter',2) face_positions = np.concatenate([b + coef*(p-b) for p,b in zip(positions.values(faces),topomesh.wisp_property('barycenter',2).values())]) if is_triangular(topomesh): face_triangles = np.arange(3*len(faces)).reshape((len(faces),3)) triangulation = tri.Triangulation(face_positions[:,0],face_positions[:,1],face_triangles) if degree==3: if is_triangular(topomesh): compute_topomesh_property(topomesh,'barycenter',3) compute_topomesh_property(topomesh,'faces',3) cell_triangles = np.concatenate(topomesh.wisp_property('vertices',2).values(topomesh.wisp_property('faces',3).values())) cell_triangle_cells = np.concatenate([c*np.ones_like(topomesh.wisp_property('faces',3)[c]) for c in topomesh.wisps(3)]) cell_triangle_positions = np.concatenate([b + coef*(p-b) for p,b in zip(positions.values(cell_triangles),topomesh.wisp_property('barycenter',3).values(cell_triangle_cells))]) cell_triangle_triangles = np.arange(3*len(cell_triangles)).reshape((len(cell_triangles),3)) cell_triangulation = tri.Triangulation(cell_triangle_positions[:,0],cell_triangle_positions[:,1],cell_triangle_triangles) if (property_name is None) or (property_name == ""): cell_triangle_property = cell_triangle_cells if intensity_range is None: intensity_range = (cell_triangle_property.min(), cell_triangle_property.max()) plot_to_return = figure.gca().tripcolor(cell_triangulation, cell_triangle_property, cmap=colormap, alpha=alpha, vmin=intensity_range[0], vmax=intensity_range[1]) else: cell_property = topomesh.wisp_property(property_name, property_degree).values(list(topomesh.wisps(property_degree))) if cell_property.ndim == 1: if property_degree == 3: cell_triangle_property = topomesh.wisp_property(property_name,property_degree).values(cell_triangle_cells) elif property_degree == 2: cell_triangle_property = topomesh.wisp_property(property_name,property_degree).values(np.concatenate(topomesh.wisp_property('faces',3).values())) elif property_degree == 0: cell_triangle_property = topomesh.wisp_property(property_name,property_degree).values(cell_triangles) if intensity_range is None: intensity_range = (cell_triangle_property.min(),cell_triangle_property.max()) plot_to_return = figure.gca().tripcolor(cell_triangulation,cell_triangle_property,cmap=colormap,alpha=alpha,vmin=intensity_range[0],vmax=intensity_range[1]) elif cell_property.ndim == 2: if property_degree == 3: cell_centers = topomesh.wisp_property('barycenter', 3).values(list(topomesh.wisps(3))) plot_to_return = figure.gca().quiver(cell_centers[:, 0], cell_centers[:, 1], cell_property[:, 0], cell_property[:, 1], color=color, units='xy', scale=1. / coef) else: if not topomesh.has_wisp_property('oriented_vertices', degree=2, is_computed=True): compute_topomesh_property(topomesh, 'oriented_vertices', 2) compute_topomesh_property(topomesh, 'barycenter', 3) compute_topomesh_property(topomesh, 'borders', 3) cell_faces = topomesh.wisp_property('borders',3).values(list(topomesh.wisps(3))) oriented_cell_faces = np.concatenate(topomesh.wisp_property('oriented_vertices', 2).values(cell_faces)) oriented_cell_face_cells = np.concatenate([[c for f in topomesh.wisp_property('borders',3)[c]] for c in topomesh.wisps(3)]) oriented_cell_face_positions = [b + coef * (p - b) for p, b in zip(positions.values(oriented_cell_faces), topomesh.wisp_property('barycenter',3).values(oriented_cell_face_cells))] if (property_name is None) or (property_name == ""): colors = np.zeros((len(faces), 3)) poly_collection = PolyCollection([p[:, :2] for p in oriented_cell_face_positions], facecolors=colors, linewidth=0.5, alpha=0.8 * alpha) figure.gca().add_collection(poly_collection) plot_to_return = poly_collection else: cell_property = topomesh.wisp_property(property_name, property_degree).values(list(topomesh.wisps(property_degree))) if cell_property.ndim == 1: if property_degree == 3: cell_face_property = topomesh.wisp_property(property_name, property_degree).values(oriented_cell_face_cells) if intensity_range is None: intensity_range = (cell_face_property.min(), cell_face_property.max()) if property_degree == 3: norm = Normalize(vmin=intensity_range[0], vmax=intensity_range[1]) poly_collection = PolyCollection([p[:, :2] for p in oriented_cell_face_positions], array=cell_face_property, linewidth=0.5, alpha=alpha, cmap=colormap, norm=norm) figure.gca().add_collection(poly_collection) plot_to_return = poly_collection elif cell_property.ndim == 2: if property_degree == 3: cell_centers = topomesh.wisp_property('barycenter', 3).values(list(topomesh.wisps(3))) plot_to_return = figure.gca().quiver(cell_centers[:, 0], cell_centers[:, 1], cell_property[:, 0], cell_property[:, 1], color=color, units='xy', scale=1. / coef) if plot_ids: for c in topomesh.wisps(3): figure.gca().text(topomesh.wisp_property('barycenter',3)[c][0],topomesh.wisp_property('barycenter',3)[c][1],str(c),size=12,ha='center',color=color) elif degree==2: if not is_triangular(topomesh): if not topomesh.has_wisp_property('oriented_vertices',degree=2,is_computed=True): compute_topomesh_property(topomesh,'oriented_vertices',2) oriented_faces = topomesh.wisp_property('oriented_vertices',2).values(list(topomesh.wisps(2))) oriented_face_positions = [b + coef*(p-b) for p,b in zip(positions.values(oriented_faces),topomesh.wisp_property('barycenter',2).values(list(topomesh.wisps(2))))] if (property_name is None) or (property_name == ""): if topomesh.has_wisp_property('color',2): colors = topomesh.wisp_property('color',2).values(list(topomesh.wisps(2))) else: colors = [color for f in faces] if is_triangular(topomesh): poly_collection = PolyCollection(face_positions[:,:2].reshape((len(faces),3,2)),facecolors=colors,linewidth=0.5,alpha=0.8*alpha) figure.gca().add_collection(poly_collection) plot_to_return = poly_collection else: poly_collection = PolyCollection([p[:,:2] for p in oriented_face_positions],facecolors=colors,linewidth=0.5,alpha=0.8*alpha) figure.gca().add_collection(poly_collection) plot_to_return = poly_collection else: if property_degree == 2: face_property = topomesh.wisp_property(property_name,property_degree).values(list(topomesh.wisps(2))) elif property_degree == 0: face_property = np.concatenate(topomesh.wisp_property(property_name,property_degree).values(faces)) if face_property.ndim == 1: if intensity_range is None: intensity_range = (face_property.min(),face_property.max()) # mpl_colormap = cm.ScalarMappable(norm=Normalize(vmin=intensity_range[0], vmax=intensity_range[1]),cmap=cm.cmap_d[colormap]) # colors = mpl_colormap.to_rgba(face_property)[:,:3] # print colors if is_triangular(topomesh): if property_degree == 2: plot_to_return = figure.gca().tripcolor(triangulation,face_property,cmap=colormap,alpha=alpha,vmin=intensity_range[0],vmax=intensity_range[1]) elif property_degree == 0: plot_to_return = figure.gca().tripcolor(triangulation,face_property,cmap=colormap,alpha=alpha,vmin=intensity_range[0],vmax=intensity_range[1],shading='gouraud') else: if property_degree == 2: norm = Normalize(vmin=intensity_range[0], vmax=intensity_range[1]) poly_collection = PolyCollection([p[:, :2] for p in oriented_face_positions], array=face_property, linewidth=0.5, alpha=alpha, cmap=colormap, norm=norm) figure.gca().add_collection(poly_collection) plot_to_return = poly_collection elif face_property.ndim == 2: face_centers = topomesh.wisp_property('barycenter',2).values(list(topomesh.wisps(2))) plot_to_return = figure.gca().quiver(face_centers[:,0],face_centers[:,1],face_property[:,0],face_property[:,1],color=color,units='xy',scale=1./coef) elif face_property.ndim == 3: face_centers = topomesh.wisp_property('barycenter',2).values(list(topomesh.wisps(2))) plot_to_return = plot_tensor_data(figure, face_centers[:,0], face_centers[:,1], face_property, color=color, colormap=colormap, value_range=None, scale=coef, linewidth=linewidth, alpha=alpha) if plot_ids: for f in topomesh.wisps(2): figure.gca().text(topomesh.wisp_property('barycenter',2)[f][0],topomesh.wisp_property('barycenter',2)[f][1],str(f),size=12,ha='center',color=color) elif degree==1: if not topomesh.has_wisp_property('barycenter',degree=1,is_computed=True): compute_topomesh_property(topomesh,'barycenter',1) # if is_triangular(topomesh) and (topomesh.nb_wisps(2) > 0) and not cell_edges: if False: figure.gca().triplot(triangulation,color=color,linewidth=linewidth,alpha=alpha,zorder=5) else: compute_topomesh_property(topomesh,'vertices',1) if cell_edges: boundary_edges = [e for e in topomesh.wisps(1) if topomesh.nb_regions(1,e)==1] cell_boundary_edges = [e for e in topomesh.wisps(1) if len(list(topomesh.regions(1,e,2)))>1] considered_edges = np.unique(cell_boundary_edges+boundary_edges) else: considered_edges = list(topomesh.wisps(1)) edge_points = topomesh.wisp_property('barycenter',0).values(topomesh.wisp_property('vertices',1).values(considered_edges)) if (property_name is None) or (property_name == ""): colors = [color for e in considered_edges] line_collection = LineCollection([p[:, :2] for p in edge_points], colors=colors, linewidth=linewidth, alpha=alpha) figure.gca().add_collection(line_collection) plot_to_return = line_collection else: if property_degree == 1: if topomesh.has_wisp_property(property_name,property_degree): edge_property = topomesh.wisp_property(property_name, property_degree).values(considered_edges) else: edge_property = np.array([0 for e in considered_edges]) if intensity_range is None: intensity_range = (edge_property.min(), edge_property.max()) if property_degree == 1: if edge_property.ndim == 1: norm = Normalize(vmin=intensity_range[0], vmax=intensity_range[1]) line_collection = LineCollection([p[:, :2] for p in edge_points], array=edge_property, linewidth=linewidth, alpha=alpha, cmap=colormap, norm=norm) figure.gca().add_collection(line_collection) plot_to_return = line_collection elif edge_property.ndim == 2: edge_centers = topomesh.wisp_property('barycenter', 1).values(list(topomesh.wisps(1))) plot_to_return = figure.gca().quiver(edge_centers[:, 0], edge_centers[:, 1], edge_property[:, 0], edge_property[:, 1], color=color, units='xy', scale=1./coef) elif edge_property.ndim == 3: edge_centers = topomesh.wisp_property('barycenter', 1).values(list(topomesh.wisps(1))) plot_to_return = plot_tensor_data(figure, edge_centers[:,0], edge_centers[:,1], edge_property, color=color, colormap=colormap, value_range=None, scale=coef, linewidth=linewidth, alpha=alpha) if plot_ids: for e in topomesh.wisps(1): figure.gca().text(topomesh.wisp_property('barycenter',1)[e][0],topomesh.wisp_property('barycenter',1)[e][1],str(e),size=12,ha='center',color=color) elif degree==0: if (property_name is None) or (property_name == ""): if topomesh.has_wisp_property('color',0): colors = topomesh.wisp_property('color',0).values() else: colors = color plot_to_return = figure.gca().scatter(positions.values()[:,0],positions.values()[:,1],s=20,edgecolor=color,color=colors,alpha=alpha,zorder=6) else: vertex_property = topomesh.wisp_property(property_name,0).values(list(topomesh.wisps(0))) vertex_points = positions.values(list(topomesh.wisps(0))) if vertex_property.ndim == 1: if intensity_range is None: intensity_range = (vertex_property.min(),vertex_property.max()) plot_to_return = figure.gca().scatter(vertex_points[:,0],vertex_points[:,1],c=vertex_property,s=size,linewidth=linewidth,cmap=colormap,edgecolor=color,alpha=alpha,vmin=intensity_range[0],vmax=intensity_range[1],zorder=6) elif vertex_property.ndim == 2: plot_to_return = figure.gca().quiver(vertex_points[:,0],vertex_points[:,1],vertex_property[:,0],vertex_property[:,1],color=color,units='xy',scale=1./coef) elif vertex_property.ndim == 3: plot_to_return = plot_tensor_data(figure, vertex_points[:, 0], vertex_points[:, 1], vertex_property, color=color, colormap=colormap, value_range=None, scale=coef, linewidth=linewidth, alpha=alpha) if plot_ids: for v in topomesh.wisps(0): figure.gca().text(topomesh.wisp_property('barycenter',0)[v][0],topomesh.wisp_property('barycenter',0)[v][1],str(v),size=12,ha='center',color=color) return plot_to_return
# if wisp_ids: # if not topomesh.has_wisp_property('barycenter',degree): # compute_topomesh_property(topomesh,'barycenter',degree) # for e in topomesh.wisps(degree): # figure.gca().text(topomesh.wisp_property('barycenter',degree)[e][0],topomesh.wisp_property('barycenter',degree)[e][1],str(e),color=color) # elif degree==2: # if not is_triangular(topomesh): # if not topomesh.has_wisp_property('oriented_vertices',degree=2,is_computed=True): # compute_topomesh_property(topomesh,'oriented_vertices',2) # oriented_faces = topomesh.wisp_property('oriented_vertices',2).values(list(topomesh.wisps(2))) # oriented_face_positions = [b + coef*(p-b) for p,b in zip(positions.values(oriented_faces),topomesh.wisp_property('barycenter',2).values())] # if (property_name is None) or (property_name == ""): # if topomesh.has_wisp_property('color',2): # colors = topomesh.wisp_property('color',2).values() # else: # colors = np.zeros((len(faces),3)) # if is_triangular(topomesh): # figure.gca().add_collection(PolyCollection(face_positions[:,:2].reshape((len(faces),3,2)),facecolors=colors,linewidth=0.5,alpha=0.8*alpha)) # else: # figure.gca().add_collection(PolyCollection([p[:,:2] for p in oriented_face_positions],facecolors=colors,linewidth=0.5,alpha=0.8*alpha)) # else: # if property_degree == 2: # face_property = topomesh.wisp_property(property_name,property_degree).values() # elif property_degree == 0: # face_property = np.concatenate(topomesh.wisp_property(property_name,property_degree).values(faces)) # if face_property.ndim == 1: # if intensity_range is None: # intensity_range = (face_property.min(),face_property.max()) # # mpl_colormap = cm.ScalarMappable(norm=Normalize(vmin=intensity_range[0], vmax=intensity_range[1]),cmap=cm.cmap_d[colormap]) # # colors = mpl_colormap.to_rgba(face_property)[:,:3] # # print colors # if is_triangular(topomesh): # if property_degree == 2: # figure.gca().tripcolor(triangulation,face_property,cmap=colormap,alpha=alpha,vmin=intensity_range[0],vmax=intensity_range[1]) # elif property_degree == 0: # figure.gca().tripcolor(triangulation,face_property,cmap=colormap,alpha=alpha,vmin=intensity_range[0],vmax=intensity_range[1],shading='gouraud') # else: # if property_degree == 2: # mpl_colormap = cm.ScalarMappable(norm=Normalize(vmin=intensity_range[0], vmax=intensity_range[1]),cmap=cm.cmap_d[colormap]) # colors = mpl_colormap.to_rgba(face_property)[:,:3] # figure.gca().add_collection(PolyCollection([p[:,:2] for p in oriented_face_positions],facecolors=colors,linewidth=0.5,alpha=alpha)) # # if (property_name is None) or (property_name == ""): # # if topomesh.has_wisp_property('color',2): # # colors = topomesh.wisp_property('color',2).values() # # else: # # colors = np.zeros((len(triangles),3)) # # figure.gca().add_collection(PolyCollection(triangle_positions[:,:2].reshape((len(triangles),3,2)),facecolors=colors,linewidth=0.5,alpha=0.8*alpha)) # # else: # # if property_degree == 2: # # triangle_property = topomesh.wisp_property(property_name,property_degree).values() # # elif property_degree == 0: # # triangle_property = np.concatenate(topomesh.wisp_property(property_name,property_degree).values(triangles)) # # if triangle_property.ndim == 1: # # if intensity_range is None: # # intensity_range = (triangle_property.min(),triangle_property.max()) # # # mpl_colormap = cm.ScalarMappable(norm=Normalize(vmin=intensity_range[0], vmax=intensity_range[1]),cmap=cm.cmap_d[colormap]) # # # colors = mpl_colormap.to_rgba(triangle_property)[:,:3] # # # print colors # # # figure.gca().add_collection(PolyCollection(triangle_positions[:,:2].reshape((len(triangles),3,2)),facecolors=colors,cmap=colormap,linewidth=0.5,alpha=0.8*alpha)) # # if property_degree == 2: # # figure.gca().tripcolor(triangulation,triangle_property,cmap=colormap,alpha=alpha,vmin=intensity_range[0],vmax=intensity_range[1]) # # elif property_degree == 0: # # figure.gca().tripcolor(triangulation,triangle_property,cmap=colormap,alpha=alpha,vmin=intensity_range[0],vmax=intensity_range[1],shading='gouraud') # elif degree==1: # if is_triangular(topomesh) and not cell_edges: # figure.gca().triplot(triangulation,color=color,linewidth=linewidth,alpha=alpha) # else: # compute_topomesh_property(topomesh,'vertices',1) # if cell_edges: # boundary_edges = [e for e in topomesh.wisps(1) if topomesh.nb_regions(1,e)==1] # cell_boundary_edges = [e for e in topomesh.wisps(1) if len(list(topomesh.regions(1,e,2)))>1] # considered_edges = np.unique(cell_boundary_edges+boundary_edges) # else: # considered_edges = list(topomesh.wisps(1)) # edge_points = topomesh.wisp_property('barycenter',0).values(topomesh.wisp_property('vertices',1).values(considered_edges)) # for p in edge_points: # figure.gca().plot(p[:,0],p[:,1],color=color,linewidth=linewidth,alpha=alpha) # elif degree==0: # if (property_name is None) or (property_name == ""): # if topomesh.has_wisp_property('color',0): # colors = topomesh.wisp_property('color',0).values() # else: # colors = color # figure.gca().scatter(positions.values()[:,0],positions.values()[:,1],s=20,edgecolor=color,color=colors,alpha=alpha) # else: # vertex_property = topomesh.wisp_property(property_name,0).values(list(topomesh.wisps(0))) # if vertex_property.ndim == 1: # if intensity_range is None: # intensity_range = (vertex_property.min(),vertex_property.max()) # figure.gca().scatter(positions.values(list(topomesh.wisps(0)))[:,0],positions.values(list(topomesh.wisps(0)))[:,1],c=vertex_property,s=size,linewidth=linewidth,cmap=colormap,alpha=alpha,vmin=intensity_range[0],vmax=intensity_range[1]) # figure.canvas.draw() # plt.pause(1e-3)
[docs]def mpl_draw_incidence_graph(topomesh,figure,colors={0:'m',1:'b',2:'g',3:'r'},size=40,linewidth=1,degree=None,plot_ids=False): """ Parameters ---------- topomesh figure colors size linewidth plot_ids Returns ------- """ plot_to_return = None if degree is None: degree = topomesh.degree() n_max = np.max([topomesh.nb_wisps(d) for d in range(degree+1)]) wisp_x = {} wisp_y = {} for d in range(degree+1): wisp_x[d] = dict([(w,(degree+1)*(i-0.5*float(topomesh.nb_wisps(d)-1))/n_max) for i,w in enumerate(topomesh.wisps(d))]) wisp_y[d] = dict([(w,d) for i,w in enumerate(topomesh.wisps(d))]) for d in range(degree): for w in topomesh.wisps(d): for r in topomesh.regions(d,w): figure.gca().plot([wisp_x[d][w],wisp_x[d+1][r]],[wisp_y[d][w],wisp_y[d+1][r]],color='k',linewidth=linewidth) for d in range(degree+1): figure.gca().scatter(wisp_x[d].values(),wisp_y[d].values(),color=colors[d],s=size,linewidth=linewidth,zorder=5) if plot_ids: for w in topomesh.wisps(d): figure.gca().text(wisp_x[d][w],wisp_y[d][w],str(w),size=12,ha='center',color=colors[d]) return plot_to_return