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