Content under Creative Commons Attribution license CC-BY 4.0, code under MIT license (c)2014 Sergio Rojas (srojas@usb.ve) and Erik A Christensen (erikcny@aol.com).
NOTE: This IPython notebook should be read alonside the corresponding chapter in the book, where each piece of code is fully explained.
This chapter explores the construction of triangulation of points, convex hulls, Voronoi diagrams, and many applications. At this point in the book, it will be possible to combine techniques from all the previous chapters to show state-of-the-art research performed with ease with SciPy, and we will explore a few good examples from Material Sciences and Experimental Physics.
In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
In [2]:
import scipy.stats
import scipy.spatial
In [3]:
data = scipy.stats.randint.rvs(0.4,10,size=(10,2))
triangulation = scipy.spatial.Delaunay(data)
In [4]:
#locations=scipy.stats.randint.rvs(0,511,size=(2,8))
from numpy.random import RandomState
rv = RandomState(123456789)
locations = rv.randint(0, 511, size=(2,8))
triangulation=scipy.spatial.Delaunay(locations.T)
In [5]:
assign_vertex = lambda index: triangulation.points[index]
triangle_set = map(assign_vertex, triangulation.vertices)
In [6]:
plt.triplot(locations[1], locations[0], triangles=triangle_set, color='r')
Out[6]:
In [7]:
voronoiSet=scipy.spatial.Voronoi(locations.T)
scipy.spatial.voronoi_plot_2d(voronoiSet)
plt.show()
In [8]:
fig = plt.figure()
thefig = plt.subplot(1,1,1)
scipy.spatial.voronoi_plot_2d(voronoiSet, ax=thefig)
plt.triplot(locations[1], locations[0], triangles=triangle_set, color='r')
plt.xlim((0,550))
plt.ylim((0,550))
plt.show()
In [9]:
import numpy
import scipy
from scipy.ndimage import *
from scipy.misc import imfilter
import matplotlib.cm as cm
In [10]:
img=imread('./NbW-STEM.png')
In [11]:
plt.rcParams['figure.figsize'] = (10.0, 8.0)
img=imread('./NbW-STEM.png')
minVal = numpy.min(img)
maxVal = numpy.max(img)
img = (1.0/(maxVal-minVal))*(img - minVal)
plt.imshow(img, cmap = cm.Greys_r)
plt.show()
In [12]:
print(img)
In [13]:
print("Image dtype: %s"%(img.dtype))
print("Image size: %6d"%(img.size))
print("Image shape: %3dx%3d"%(img.shape[0],img.shape[1]))
print("Max value %1.2f at pixel %6d"%(img.max(),img.argmax()))
print("Min value %1.2f at pixel %6d"%(img.min(),img.argmin()))
print("Variance: %1.5f\nStandard deviation: %1.5f"%(img.var(),img.std()))
In [14]:
plt.subplot(1, 2, 1)
plt.imshow(img > 0.2, cmap = cm.Greys_r)
plt.xlabel('img > 0.2')
plt.subplot(1, 2, 2)
plt.imshow(img > 0.7, cmap = cm.Greys_r)
plt.xlabel('img > 0.7')
plt.show()
In [15]:
BWatoms = (img> 0.62)
BWatoms = binary_opening(BWatoms,structure=numpy.ones((2,2)))
In [16]:
structuring_element = [[0,1,0],[1,1,1],[0,1,0]]
segmentation,segments = label(BWatoms,structuring_element)
In [17]:
coords = center_of_mass(img, segmentation, range(1,segments+1))
xcoords = numpy.array([x[1] for x in coords])
ycoords = numpy.array([x[0] for x in coords])
In [18]:
plt.imshow(img, cmap = cm.Greys_r)
plt.axis('off')
plt.plot(xcoords,ycoords,'b.')
plt.show()
In [19]:
L1,L2 = distance_transform_edt(segmentation==0,
return_distances=False,
return_indices=True)
Voronoi = segmentation[L1,L2]
Voronoi_edges= imfilter(Voronoi,'find_edges')
Voronoi_edges=(Voronoi_edges>0)
In [20]:
plt.imshow(Voronoi_edges);
plt.axis('off');
plt.gray()
plt.plot(xcoords,ycoords,'r.',markersize=2.0)
plt.show()
In [21]:
import numpy
from numpy import linspace
import scipy
from scipy.spatial import Delaunay
%matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (15.0, 10.0)
In [22]:
xmin = 0 ; xmax = 1 ; nXpoints = 10
ymin = 0 ; ymax = 1 ; nYpoints = 10
horizontal = linspace(xmin,xmax,nXpoints)
vertical = linspace(ymin,ymax,nYpoints)
y, x = numpy.meshgrid(horizontal, vertical)
vertices = numpy.array([x.flatten(),y.flatten()])
In [23]:
triangulation = Delaunay(vertices.T)
index2point = lambda index: triangulation.points[index]
all_centers = index2point(triangulation.vertices).mean(axis=1)
trngl_set=triangulation.vertices
In [24]:
plt.rcdefaults()
plt.triplot(vertices[0],vertices[1],triangles=trngl_set)
plt.show()
This is the problem formulation
This is the solution
In [25]:
from numpy import cross
from scipy.sparse import dok_matrix
points=triangulation.points.shape[0]
stiff_matrix=dok_matrix((points,points))
In [26]:
for triangle in triangulation.vertices:
helper_matrix=dok_matrix((points,points))
pt1,pt2,pt3=index2point(triangle)
area=abs(0.5*cross(pt2-pt1,pt3-pt1))
coeffs=0.5*numpy.vstack((pt2-pt3,pt3-pt1,pt1-pt2))/area
#helper_matrix[triangle,triangle]=array(mat(coeffs)*mat(coeffs).T)
u=None
u=numpy.array(numpy.mat(coeffs)*numpy.mat(coeffs).T)
for i in range(len(triangle)):
for j in range(len(triangle)):
helper_matrix[triangle[i],triangle[j]] = u[i,j]
stiff_matrix=stiff_matrix+helper_matrix
In [27]:
allNodes = numpy.unique(trngl_set)
boundaryNodes = numpy.unique(triangulation.convex_hull)
NonBoundaryNodes = numpy.array([])
for x in allNodes:
if x not in boundaryNodes:
NonBoundaryNodes = numpy.append(NonBoundaryNodes,x)
NonBoundaryNodes = NonBoundaryNodes.astype(int)
nbnodes = len(boundaryNodes) # number of boundary nodes
FbVals=numpy.zeros([nbnodes,1]) # Values on the boundary
FbVals[(nbnodes-nXpoints+1):-1]=numpy.ones([nXpoints-2, 1])
In [28]:
totalNodes = len(allNodes)
stiff_matrixDense = stiff_matrix.todense()
stiffNonb = stiff_matrixDense[numpy.ix_(NonBoundaryNodes,NonBoundaryNodes)]
stiffAtb = stiff_matrixDense[numpy.ix_(NonBoundaryNodes,boundaryNodes)]
U=numpy.zeros([totalNodes, 1])
U[NonBoundaryNodes] = numpy.linalg.solve( - stiffNonb , stiffAtb * FbVals )
U[boundaryNodes] = FbVals
In [29]:
X = vertices[0]
Y = vertices[1]
Z = U.T.flatten()
In [30]:
plt.rcdefaults()
from mpl_toolkits.mplot3d import axes3d
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_trisurf(X, Y, Z, cmap=cm.jet, linewidth=0)
fig.colorbar(surf)
fig.tight_layout()
ax.set_xlabel('X',fontsize=16)
ax.set_ylabel('Y',fontsize=16)
ax.set_zlabel(r"$\phi$",fontsize=36)
plt.show()
In [31]:
from numpy import pi, sinh, sin, cos, sum
def f(x,y):
return sum(
2*(1.0/(n*pi) - cos(n*pi)/(n*pi))*(sinh(n*pi*x)/sinh(n*pi))*sin(n*pi*y)
for n in range(1,200))
The following plot shows the difference between the exact solution and the numerical one
In [32]:
Ze = f(X,Y)
ZdiffZe = Ze - Z
plt.plot(ZdiffZe)
plt.show()
Content under Creative Commons Attribution license CC-BY 4.0, code under MIT license (c)2014 Sergio Rojas (srojas@usb.ve) and Erik A Christensen (erikcny@aol.com).