I've written a code for my school project. The u and v matrices are generated already. I've made a 2D contour, but I wish to plot u and v in 3D.
import numpy as np
#import matplotlib.pyplot as plt
#inputs
m = 40
n = 20
Uinf = 2
delX = 0.05
delY = 0.05
nu = 0.8e-2
u= np.zeros((m+1,n))
v= np.zeros((m+1,n))
#intializing boundry conditions
u[:,0] = v[:,0] = v[:,n-1] = v[0,:] = 0
u[:,n-1] = u[0,:] = Uinf
#main program
for i in range(0,m):
for j in range(1,n-1):
a = (nu*delX) / (u[i,j]*delY**2)
b = (v[i,j]*delX) / (2*u[i,j]*delY)
u[i+1,j] = (a-b)*u[i,j+1]+(1-2*a)*u[i,j]+(a+b)*u[i,j-1]
v[i+1,j] = v[i+1,j-1]-(delY/(2*delX))*(u[i+1,j]-u[i,j]+u[i+1,j-1]-u[i,j-1])
I have to mention that I don't wanna generate an arbitrary function; u[i,j] and v[i,j] are present.
Thanks!
I am trying to map surface curvature (mean, gaussian and principle curvature) values to surface faces. I have computed the curvature values for an artificially generated 3D surface (eg. cylinder). The resulting 3D surface that I am trying to get is something like this mean curvature mapped to surface. Can somebody guide me in how to get this?
The code for the surface I am creating is:
import math
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
xindex = []
yindex = []
zindex = []
x = []
y = []
z = []
count = 1
surfaceSt = []
import numpy
numpy.set_printoptions(threshold=numpy.nan)
#surfaceStX = numpy.empty((10,36))
#surfaceStY = numpy.empty((10,36))
#surfaceStZ = numpy.empty((10,36))
surfaceStZ = []
surfaceStX = []
surfaceStY = []
for i in range(1,21):
if i < 11:
x = []
y = []
z = []
pt = []
ptX = []
ptY = []
ptZ = []
for t in range(0,360,10):
x = i*math.sin(math.radians(t))
y = i*math.cos(math.radians(t))
z = i-1
ptX.append(x)
ptY.append(y)
ptZ.append(z)
pt.append([x,y,z])
ptX.append(ptX[0])
ptY.append(ptY[0])
ptZ.append(ptZ[0])
surfaceStX.append(ptX)
surfaceStY.append(ptY)
surfaceStZ.append(ptZ)
# numpy.append(surfaceStX,ptX)
# numpy.append(surfaceStY,ptY)
# numpy.append(surfaceStZ,ptZ)
#ax.scatter(x,y,z)
elif i >= 11:
x = []
y = []
z = []
pt = []
ptX = []
ptY = []
ptZ = []
for t in range(0,360,10):
x = (i-count)*math.sin(math.radians(t))
y = (i-count)*math.cos(math.radians(t))
z = i-1
ptX.append(x)
ptY.append(y)
ptZ.append(z)
pt.append([x,y,z])
ptX.append(ptX[0])
ptY.append(ptY[0])
ptZ.append(ptZ[0])
surfaceStX.append(ptX)
surfaceStY.append(ptY)
surfaceStZ.append(ptZ)
count +=2
X = numpy.array(surfaceStX)
Y = numpy.array(surfaceStY)
Z = numpy.array(surfaceStZ)
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1,shade = 'True' )
from surfaceCurvature import surface_curvature
Pcurvature,Gcurvature,Mcurvature = surface_curvature(X,Y,Z)
plt.show()
My surface curvature computation is given below (courtesy: https://github.com/sujithTSR/surface-curvature):
def surface_curvature(X,Y,Z):
(lr,lb)=X.shape
#print lr
#print "awfshss-------------"
#print lb
#First Derivatives
Xv,Xu=np.gradient(X)
Yv,Yu=np.gradient(Y)
Zv,Zu=np.gradient(Z)
#Second Derivatives
Xuv,Xuu=np.gradient(Xu)
Yuv,Yuu=np.gradient(Yu)
Zuv,Zuu=np.gradient(Zu)
Xvv,Xuv=np.gradient(Xv)
Yvv,Yuv=np.gradient(Yv)
Zvv,Zuv=np.gradient(Zv)
#2D to 1D conversion
#Reshape to 1D vectors
Xu=np.reshape(Xu,lr*lb)
Yu=np.reshape(Yu,lr*lb)
Zu=np.reshape(Zu,lr*lb)
Xv=np.reshape(Xv,lr*lb)
Yv=np.reshape(Yv,lr*lb)
Zv=np.reshape(Zv,lr*lb)
Xuu=np.reshape(Xuu,lr*lb)
Yuu=np.reshape(Yuu,lr*lb)
Zuu=np.reshape(Zuu,lr*lb)
Xuv=np.reshape(Xuv,lr*lb)
Yuv=np.reshape(Yuv,lr*lb)
Zuv=np.reshape(Zuv,lr*lb)
Xvv=np.reshape(Xvv,lr*lb)
Yvv=np.reshape(Yvv,lr*lb)
Zvv=np.reshape(Zvv,lr*lb)
Xu=np.c_[Xu, Yu, Zu]
Xv=np.c_[Xv, Yv, Zv]
Xuu=np.c_[Xuu, Yuu, Zuu]
Xuv=np.c_[Xuv, Yuv, Zuv]
Xvv=np.c_[Xvv, Yvv, Zvv]
# First fundamental Coeffecients of the surface (E,F,G)
E=np.einsum('ij,ij->i', Xu, Xu)
F=np.einsum('ij,ij->i', Xu, Xv)
G=np.einsum('ij,ij->i', Xv, Xv)
m=np.cross(Xu,Xv,axisa=1, axisb=1)
p=np.sqrt(np.einsum('ij,ij->i', m, m))
n=m/np.c_[p,p,p]
# Second fundamental Coeffecients of the surface (L,M,N), (e,f,g)
L= np.einsum('ij,ij->i', Xuu, n) #e
M= np.einsum('ij,ij->i', Xuv, n) #f
N= np.einsum('ij,ij->i', Xvv, n) #g
# Gaussian Curvature
K=(L*N-M**2)/(E*G-F**2)
K=np.reshape(K,lr*lb)
# Mean Curvature
H = (E*N + G*L - 2*F*M)/((E*G - F**2))
H = np.reshape(H,lr*lb)
# Principle Curvatures
Pmax = H + np.sqrt(H**2 - K)
Pmin = H - np.sqrt(H**2 - K)
#[Pmax, Pmin]
Principle = [Pmax,Pmin]
return Principle,K,H
EDIT 1:
I tried a few things based on the link provided by armatita. Following is my code:
'''
Creat half cylinder
'''
import numpy
import matplotlib.pyplot as plt
import math
ptX= []
ptY = []
ptZ = []
ptX1 = []
ptY1 = []
ptZ1 = []
for i in range(0,10):
x = []
y = []
z = []
for t in range(0,200,20):
x.append(10*math.cos(math.radians(t)))
y.append(10*math.sin(math.radians(t)))
z.append(i)
x1= 5*math.cos(math.radians(t))
y1 = 5*math.sin(math.radians(t))
z1 = i
ptX1.append(x1)
ptY1.append(y1)
ptZ1.append(z1)
ptX.append(x)
ptY.append(y)
ptZ.append(z)
X = numpy.array(ptX)
Y = numpy.array(ptY)
Z = numpy.array(ptZ)
fig = plt.figure()
ax = fig.add_subplot(111,projection = '3d')
from surfaceCurvature import surface_curvature
p,g,m= surface_curvature(X,Y,Z)
n = numpy.reshape(m,numpy.shape(X))
ax.plot_surface(X,Y,Z, rstride=1, cstride=1)
plt.show()
'''
Map mean curvature to color
'''
import numpy as np
X1 = X.ravel()
Y1 = Y.ravel()
Z1 = Z.ravel()
from scipy.interpolate import RectBivariateSpline
# Define the points at the centers of the faces:
y_coords, x_coords = np.unique(Y1), np.unique(X1)
y_centers, x_centers = [ arr[:-1] + np.diff(arr)/2 for arr in (y_coords, x_coords)]
# Convert back to a 2D grid, required for plot_surface:
#Y1 = Y.reshape(y_coords.size, -1)
#X1 = X.reshape(-1, x_coords.size)
#Z1 = Z.reshape(X.shape)
C = m.reshape(X.shape)
C -= C.min()
C /= C.max()
interp_func = RectBivariateSpline(x_coords, y_coords, C.T, kx=1, ky=1)
I get the following error:
raise TypeError('y dimension of z must have same number of y')
TypeError: y dimension of z must have same number of elements as y
All the dimensions are same. Can anybody tell what's going wrong with my implementation?
I think you need to figure out exactly what you need. Looking at your code I notice you are producing variables that have no use. Also you seem to have a function to calculate the surface curvature but than you try to make some calculations using the np.unique function for which I cannot see the purpose here (and that is why that error appears).
So let's assume this:
You have a function that returns the curvature value for each cell.
You have the X,Y and Z meshes to plot that surface.
Using your code, and assuming you m variable is the curvature (again this is in your code), if I do this:
import numpy
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import math
# Here would be the surface_curvature function
X = numpy.array(ptX)
Y = numpy.array(ptY)
Z = numpy.array(ptZ)
p,g,m= surface_curvature(X,Y,Z)
C = m.reshape(X.shape)
C -= C.min()
C /= C.max()
fig = plt.figure()
ax = fig.add_subplot(111,projection = '3d')
n = numpy.reshape(m,numpy.shape(X))
ax.plot_surface(X,Y,Z,facecolors = cm.jet(C), rstride=1, cstride=1)
plt.show()
, I obtain this:
Which is a value mapped to color in a matplotlib surface. If that C you've built is not the actual curvature you need to replace it by the one that is.
Is there an elegant way finding the number of connected components using a pre-calculated KDTree? Right now find the connected components using a breath-first search algorithm with the adjacency matrix given by the KDTree of k-nearest neighbours, but is there a better possibility?
import collections
import numpy as np
from sklearn import neighbors
N = 100
N_k = 8
ra = np.random.random
X0,X1 = ra(N),ra(N)
X0[0:N//2]+= 2
X1[0:N//2]+= 2
X = np.array([X0,X1]).T
tree = neighbors.KDTree(X)
dist, adj = tree.query(X, k = N_k+1)
dist = dist[:,1::]
adj = adj[:,1::]
print("Inside of find_components_lifo")
print("N = %d/ N_k = %d"%(N,N_k))
labels = np.zeros(N, dtype = np.int) - 1
n = 0
steps = 0
remains = (labels == -1)
while n < N:
i = np.arange(0,N,1)[remains][np.random.randint(0,N - n)]
# This is important for directed graphs
labels[i] = i
lifo = collections.deque([i])
while lifo:
ele = lifo.pop()
for k in adj[ele,:]:
if labels[k] == -1:
labels[k] = labels[i]
lifo.append(k)
elif labels[k] != labels[i]:
labels[labels == labels[i]] = labels[k]
remains = (labels == -1)
n = N - len(np.nonzero(remains)[0])
unique = np.unique(labels)
labels_ = np.zeros(N, dtype = np.int) - 1
for i, label in enumerate(unique):
choice = (labels == label)
N_cl = len(np.nonzero(choice)[0])
print("We found a cluster with N = %d"%N_cl)
labels_[choice] = i
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
fixticks(ax)
plt.show()
colors_ = np.array(colors)
for i in range(N):
for j in range(N_k):
ax.plot([X0[i],X0[adj[i,j]]],[X1[i],X1[adj[i,j]]], color = colors_[labels_[i]], alpha = 0.3)
ax.grid(True)
ax.scatter(X0,X1, s = 60, color = "Black")
plt.show()
I
I think you can use scipy's connected_components and scikit-learn's kneighbors_graph together. Does this produce what you're looking for?
from sklearn import neighbors
from scipy.sparse import csgraph
adj = neighbors.kneighbors_graph(X, N_k)
n_components, labels = csgraph.connected_components(adj)
I want to plot large data in one graph sample by sample. The newly sampled data should be added to the previous samples on the same plot. I have tried the code below, but it doesn't work as intended. It only displays the current sample; it does not display all the previous samples. Any idea how to do it using bokeh?
import numpy as np
import time
from bokeh.plotting import *
from bokeh.session import Session
from random import randint
from bokeh.objects import GLyph,GridPlot, HoverTool
output_notebook(url="default")
#output_notebook()
figure(x_range=[0,1000000],y_range=[0,100],plot_width=1000,plot_height=600,title="Hello World!")
hold()
xs = []
ys = []
x = []
y = []
for num in range(0,1000000):
xs.append(num)
for num in range(0,1000000):
ys.append(randint(0,100))
scatter(x, y, color='#33A02C', fill_color=None, size=8)
renderer = [r for r in curplot().renderers if isinstance(r, Glyph)][0]
ds = renderer.data_source
show()
i = 0
iteration = 0
last = len(xs)
sampleSize = 1000
while(iteration <= len(xs)/sampleSize):
x = xs[i:i+sampleSize]
y = ys[i:i+sampleSize]
ds.data["x"] = x
ds.data["y"] = y
ds._dirty = True
cursession().store_objects(ds)
iteration = iteration + 1
i = i + sampleSize
I adapted a code for solving 1d wave equation. My problem is animating the time dependent results. I tried it with the following code, any idea what I made wrong? I used the animation package, but somehiw it always says that more than one element is ambigous...
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
import matplotlib.animation as animation
#Set Helvetica Font
rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
## for Palatino and other serif fonts use:
#rc('font',**{'family':'serif','serif':['Palatino']})
rc('text', usetex=True)
class wave1d(object):
def __init__(self,width,T,nx,nt,c):
self.x = np.linspace(-0.5*width,0.5*width,nx)
self.t = np.linspace(0,T,nt+1)
self.dx = self.x[1]-self.x[0]
self.dt = self.t[1]-self.t[0]
self.xx = self.x
# Gamma_x squared
self.gx2 = c*self.dt/self.dx
# 2*(1-gamma_x^2-gamma_y^2)
self.gamma = 2*(1 - self.gx2)
def solve(self,ffun,gfun):
f = ffun(self.xx)
g = gfun(self.xx)
u = np.zeros((nx,nt+1))
# Set initial condition
u[:,0] = f
""" Compute first time step """
u[:,1] = 0.5*self.gamma*f+self.dt*g
u[1:-1,1] += 0.5*self.gx2*(f[2:]+f[:-2])
for k in range(1,nt):
# Every point contains these terms
u[:,k+1] = self.gamma*u[:,k] - u[:,k-1]
# Interior points
u[1:-1,k+1] += self.gx2*(u[2:,k]+u[:-2,k])
# Right boundary
u[-1,k+1] += 2*self.gx2*u[-2,k]
# Left boundary
u[0,k+1] += 2*self.gx2*u[1,k]
return u
if __name__ == '__main__':
# Final time
T = 2
# Domain dimensions
width = 8
# Wave speed
c = 1
# Number of time steps
nt = 400
# Grid points in x direction
nx = 500
wave_eq = wave1d(width,T,nx,nt,c)
# Initial value functions
f = lambda x: np.sin(x-width)
g = lambda x: 0
u = wave_eq.solve(f,g)
x = wave_eq.x
frames = []
fig = plt.figure(1,(16,8))
for k in range(nt+1):
frame = plt.show(u[:,k])
frames.append([frame])
ani = animation.ArtistAnimation(fig,frames,interval=50, blit=True,repeat_delay=1000)
# ani.save('wave1d.mp4',dpi=300)
plt.show()