How to align two hyperplanes with plane equations - python
I am trying to Euclidean transform one plane to other plane. I have two equation of planes and they have different sizes. How can I align two planes in one coordinate system?
My two planes in form of ax+by+cz+d=0.
first plane => a = -5.297742252442251, b = 21.751836101364013, c = -2.470896764133499, d = -0.5601826186620921
Second plane => a = 45.42557999642176, b = -16.9433283673388, c = 2.5117971500097287, d = -8.528560240570203]
For plotting on the matplotlib, I used following code using matplotlib
import numpy as np
import pandas as pd
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from skimage import measure
import pandas as pd
# Data points 1 and 2
data1 = [[0.190133571624755, 0.146549582481384, 0.391435742378234, 'near'],
[0.0154470205307006, 0.0959569215774536, 0.484999418258667, 'near'],
[-0.119875073432922, 0.0414541959762573, 0.542818903923034, 'near'],
[0.104917883872985, 0.058539867401123, 0.171926498413085, 'far'],
[0.177520513534545, 0.130982756614685, 0.0330302715301513, 'far'],
[0.246979117393493, 0.173633933067321, 0.373323440551757, 'far']]
data2 = [[0.334545135498046, -0.0318257808685302, 0.282101511955261, 'near'],
[0.411889553070068, 0.0223467350006103, 0.183727979660034, 'near'],
[0.330880641937255, -0.00959080457687378, 0.178299665451049, 'near'],
[-0.00756144523620605, -0.07442307472229, -0.227764248847961, 'far'],
[-0.268512785434722, -0.309048891067504, 0.456292867660522, 'far'],
[-0.305409669876098, -0.304299354553222, 0.281461238861084, 'far']]
# Create the pandas DataFrame
df1 = pd.DataFrame(data1, columns=['A', 'B', 'C', 'NearOrFar'])
df2 = pd.DataFrame(data2, columns=['A', 'B', 'C', 'NearOrFar'])
# Data - 1
# Divide into X and y
X1 = df1.iloc[:,0:3]
Y1 = df1.iloc[:,3]
# Create scatter plot of data points for data 1
fig = plt.figure(figsize=(10, 10))
ax = plt.axes(projection='3d')
for grp_name, grp_idx in df1.groupby('NearOrFar').groups.items():
x = df1.iloc[grp_idx, 0]
y = df1.iloc[grp_idx, 1]
z = df1.iloc[grp_idx, 2]
if (grp_name == 'near'):
ax.scatter(x, y, z, label=grp_name, c = 'red')
else:
ax.scatter(x, y, z, label=grp_name, c = 'blue')
# Train LDA model for data 1
lda_clf_1 = LDA(store_covariance=True)
lda_clf_1.fit(X1, Y1)
# Decision boundary Coefficient
a,b,c,d = lda_clf_1.coef_[0][0],lda_clf_1.coef_[0] [1],lda_clf_1.coef_[0][2],lda_clf_1.intercept_
# Find limit of each coordinates
xlim = ax.get_xlim()
ylim = ax.get_ylim()
# Create meshgrid in xyz
xx = np.linspace(xlim[0], xlim[1], 50)
yy = np.linspace(ylim[0], ylim[1], 50)
X,Y = np.meshgrid(xx,yy)
Z = (-d - a*X - b*Y) / c
# plot decision boundary hyperplane
ax.plot_surface(X, Y, Z, alpha=0.45)
plt.show()
# Data - 2
# Divide into X and y
X2 = df2.iloc[:,0:3]
Y2 = df2.iloc[:,3]
# Create scatter plot of data points for data 2
fig = plt.figure(figsize=(10, 10))
ax = plt.axes(projection='3d')
for grp_name, grp_idx in df2.groupby('NearOrFar').groups.items():
x = df2.iloc[grp_idx, 0]
y = df2.iloc[grp_idx, 1]
z = df2.iloc[grp_idx, 2]
if (grp_name == 'near'):
ax.scatter(x, y, z, label=grp_name, c = 'red')
else:
ax.scatter(x, y, z, label=grp_name, c = 'blue')
# Train LDA model for data 2
lda_clf_2 = LDA(store_covariance=True)
lda_clf_2.fit(X2, Y2)
# Decision boundary Coefficient
a,b,c,d = lda_clf_2.coef_[0][0],lda_clf_2.coef_[0][1],lda_clf_2.coef_[0][2],lda_clf_2.intercept_
# Find limit of each coordinates
xlim = ax.get_xlim()
ylim = ax.get_ylim()
# Create meshgrid in xyz
xx = np.linspace(xlim[0], xlim[1], 50)
yy = np.linspace(ylim[0], ylim[1], 50)
X,Y = np.meshgrid(xx,yy)
Z = (-d - a*X - b*Y) / c
# plot decision boundary hyperplane
ax.plot_surface(X, Y, Z, alpha=0.45)
plt.show()
How can I align two planes and create 3d plot of two align planes in one graph with data points?
At the end, I want to transform(mostly roatation I think?) all the data points on data2 to coordinate system of data1 as data2 hyperplane align with data1 hyperplane
Each datapoints with hyperplane should looks like following
Data 1 =
enter image description here
and
Data 2 = enter image description here
If you simply want to plot the two planes on the same 3d axes, then you just need to compute two different values for Z and plot the two Zs relative to the same Xs and Ys, like so:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
# first plane:
a1 = -5.297742252442251
b1 = 21.751836101364013
c1 = -2.470896764133499
d1 = -0.5601826186620921
# second plane:
a2 = 45.42557999642176
b2 = -16.9433283673388
c2 = 2.5117971500097287
d2 = -8.528560240570203
x = np.linspace(-1, 1, 100)
y = np.linspace(-1, 1, 100)
X, Y = np.meshgrid(x, y)
Z1 = (-d1 - a1 * X - b1 * Y) / c1
Z2 = (-d2 - a2 * X - b2 * Y) / c2
fig = plt.figure(figsize=(10, 10))
ax = plt.axes(projection="3d")
ax.plot_surface(X, Y, Z1, alpha=0.45)
ax.plot_surface(X, Y, Z2, alpha=0.45)
plt.show()
This produces the following figure:
As to "aligning" the two planes, it's not clear to me what you're asking...? Two planes will be coplanar if they have the same values of a, b, c and d in the equation you gave above - if they have different values of a, b, c and d, they won't be coplanar. They may intersect, they may not - and to ensure you graph them where they intersect (should they do so), you'd need to determine the values of x and y where they have equal values of z and set your xrange and yrange accordingly. If you can explain the meaning of "align" for your particular purposes, perhaps I could expand on this answer to accommodate.
Related
python add values to Line3DCollection
I want to plot multiple lines in a 3d axis plot. I'm plotting the trajectory of a light ray, each line should be colored depending on the time of propagation for each path. I want to plot them independently, since I saved them in a binary three structure in which any ray may follow two different trajectories. I used Line3DCollection, but it doesn't seem to be the right way. In few words, import numpy as np x = np.linspace(0,1,100) y = x z = x t = np.linspace(0,1,100) #here I need to plot these points coloring them in function of t x1 = np.linspace(1,2,100) y1 = x z1 = x t1 = np.linspace(1,2,100) #I need to plot also this used the same colorbar used for former values x2 = -np.linspace(1,2,100) y2 = x z2 = x t2 = np.linspace(1,2,100) #idem having all the lines colored with the same colorbar scale, like this plot. I tried with the following but the output is not like I expected import numpy as np from matplotlib import pyplot as plt from mpl_toolkits.mplot3d.art3d import Line3DCollection x = np.linspace(0,1,100) y = x z = x t = np.linspace(0,1,100) points = np.array([x,y,z]).transpose().reshape(-1,1,3) segs = np.concatenate([points[:-1],points[1:]],axis=1) lc = Line3DCollection(segs, cmap=plt.get_cmap('jet')) lc.set_array(t) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.add_collection3d(lc) x1 = np.linspace(1,2,100) y1 = x1 z1 = x1 t1 = np.linspace(1,2,100) points1 = np.array([x1,y1,z1]).transpose().reshape(-1,1,3) segs1 = np.concatenate([points1[:-1],points1[1:]],axis=1) lc = Line3DCollection(segs1, cmap=plt.get_cmap('jet')) lc.set_array(t1) lc.update_scalarmappable() ax.add_collection3d(lc) x2 = np.linspace(1,2,100) y2 = -x2+2 z2 = -x2+2 t2 = np.linspace(1,2,100) points2 = np.array([x2,y2,z2]).transpose().reshape(-1,1,3) segs2 = np.concatenate([points2[:-1],points2[1:]],axis=1) lc = Line3DCollection(segs2, cmap=plt.get_cmap('jet')) lc.set_array(t1) lc.update_scalarmappable() ax.add_collection3d(lc) ax.set_xlim(0, 2) ax.set_ylim(0, 2) ax.set_zlim(0, 2) fig.colorbar(lc) plt.show() plotting this plot Thanks in advance
How to mask points below the line?
I was practicing with matplotlib.pyplot and getting used with masking data (np.ma.masked_where) point. Is there any math formula or way to mask data points below the line? Expected result:
Yes, check if the y-values are lower than the linear function of your x-values. In your case it seems to be angle bisector of the first quadrant, so offset is 0 and slope is 1: y < x In general check for y < m * x + t # with slope m and offset t I.e. in your case simply y.mask = y < x plt.plot(x, y) Example: import numpy as np import matplotlib.pyplot as plt plt.style.use('ggplot') fig = plt.figure() np.random.seed(7) # prepare data x = np.random.random(10) y = np.random.random(10) y = np.ma.masked_array(y) # plot all values plt.plot(x, y, 'o', ms=10, mec='k', mfc=(0,0,0,0), label = 'all points') y.mask = y < x # mask values below angular bisector plt.plot(x, y, 'bo', label = '$y \geq x$') # plot masked array plt.plot((0, 1), (0, 1), 'b') # plot angular bisector m = 3 # prepare the general case t = -1 y.mask = y < m * x + t # mask values below linear function plt.plot(x, y, 'rx', label = '$y \geq 3x - 1$') # plot masked array plt.plot((0, 1), (m*0+t, m*1+t), 'r') # plot linear function plt.ylim(0, 1) fig.legend(ncol=3, loc='upper center')
points_X = [1,2,3,4,5,6,7,8,9,10] // your points_X data points_Y = [1,2,3,4,5,6,7,8,9,10] // your points_Y data new_points_X=[] new_points_Y=[] for i in range(len(points_X)): if(points_Y[i] <= points_X[i]): new_points_Y.append(points_Y[i]) new_points_X.append(points_X[i]) plot(new_points_X, new_points_Y)
Changing the linewidth and the color simultaneously in matplotlib
The figure above is a great artwork showing the wind speed, wind direction and temperature simultaneously. detailedly: The X axes represent the date The Y axes shows the wind direction(Southern, western, etc) The variant widths of the line were stand for the wind speed through timeseries The variant colors of the line were stand for the atmospheric temperature This simple figure visualized 3 different attribute without redundancy. So, I really want to reproduce similar plot in matplotlib. My attempt now ## Reference 1 http://stackoverflow.com/questions/19390895/matplotlib-plot-with-variable-line-width ## Reference 2 http://stackoverflow.com/questions/17240694/python-how-to-plot-one-line-in-different-colors def plot_colourline(x,y,c): c = plt.cm.jet((c-np.min(c))/(np.max(c)-np.min(c))) lwidths=1+x[:-1] ax = plt.gca() for i in np.arange(len(x)-1): ax.plot([x[i],x[i+1]], [y[i],y[i+1]], c=c[i],linewidth = lwidths[i])# = lwidths[i]) return x=np.linspace(0,4*math.pi,100) y=np.cos(x) lwidths=1+x[:-1] fig = plt.figure(1, figsize=(5,5)) ax = fig.add_subplot(111) plot_colourline(x,y,prop) ax.set_xlim(0,4*math.pi) ax.set_ylim(-1.1,1.1) Does someone has a more interested way to achieve this? Any advice would be appreciate!
Using as inspiration another question. One option would be to use fill_between. But perhaps not in the way it was intended. Instead of using it to create your line, use it to mask everything that is not the line. Under it you can have a pcolormesh or contourf (for example) to map color any way you want. Look, for instance, at this example: import matplotlib.pyplot as plt import numpy as np from scipy.interpolate import interp1d def windline(x,y,deviation,color): y1 = y-deviation/2 y2 = y+deviation/2 tol = (y2.max()-y1.min())*0.05 X, Y = np.meshgrid(np.linspace(x.min(), x.max(), 100), np.linspace(y1.min()-tol, y2.max()+tol, 100)) Z = X.copy() for i in range(Z.shape[0]): Z[i,:] = c #plt.pcolormesh(X, Y, Z) plt.contourf(X, Y, Z, cmap='seismic') plt.fill_between(x, y2, y2=np.ones(x.shape)*(y2.max()+tol), color='w') plt.fill_between(x, np.ones(x.shape) * (y1.min() - tol), y2=y1, color='w') plt.xlim(x.min(), x.max()) plt.ylim(y1.min()-tol, y2.max()+tol) plt.show() x = np.arange(100) yo = np.random.randint(20, 60, 21) y = interp1d(np.arange(0, 101, 5), yo, kind='cubic')(x) dv = np.random.randint(2, 10, 21) d = interp1d(np.arange(0, 101, 5), dv, kind='cubic')(x) co = np.random.randint(20, 60, 21) c = interp1d(np.arange(0, 101, 5), co, kind='cubic')(x) windline(x, y, d, c) , which results in this: The function windline accepts as arguments numpy arrays with x, y , a deviation (like a thickness value per x value), and color array for color mapping. I think it can be greatly improved by messing around with other details but the principle, although not perfect, should be solid.
import numpy as np import matplotlib.pyplot as plt from matplotlib.collections import LineCollection x = np.linspace(0,4*np.pi,10000) # x data y = np.cos(x) # y data r = np.piecewise(x, [x < 2*np.pi, x >= 2*np.pi], [lambda x: 1-x/(2*np.pi), 0]) # red g = np.piecewise(x, [x < 2*np.pi, x >= 2*np.pi], [lambda x: x/(2*np.pi), lambda x: -x/(2*np.pi)+2]) # green b = np.piecewise(x, [x < 2*np.pi, x >= 2*np.pi], [0, lambda x: x/(2*np.pi)-1]) # blue a = np.ones(10000) # alpha w = x # width fig, ax = plt.subplots(2) ax[0].plot(x, r, color='r') ax[0].plot(x, g, color='g') ax[0].plot(x, b, color='b') # mysterious parts points = np.array([x, y]).T.reshape(-1, 1, 2) segments = np.concatenate([points[:-1], points[1:]], axis=1) # mysterious parts rgba = list(zip(r,g,b,a)) lc = LineCollection(segments, linewidths=w, colors=rgba) ax[1].add_collection(lc) ax[1].set_xlim(0,4*np.pi) ax[1].set_ylim(-1.1,1.1) fig.show() I notice this is what I suffered.
Obtain the surfaces curves in a figure with python
I have a set of data for that I need identify patterns, so I tried to use plt.contours and plt.contourf for that task and it works well, now I can plot contours and show graphically the overdensity among the data. In this step, I tried to get the information of the surface contours (I mean, save the values that define the contour in a variable to use it later.) without success: Is there a way to do this? Also, I have doubts of what does the values in the color bar means, I know that is the level of overdensity of the data, but if someone could tell me more details, would be great. I attach the code that I'm using so far (I generate the data in this case), and a plot of the code. import scipy.interpolate import numpy as np import scipy.stats as st import matplotlib.pyplot as plt np.random.seed(20) data = np.random.rand(400,2) x = data[:,0] y = data[:,1] plt.figure(figsize=(12,7)) # Set up a regular grid of points xi, yi = np.linspace(x.min(), x.max(), 100), np.linspace(y.min(), y.max(), 100) xi, yi = np.meshgrid(xi, yi) #contours: n_contours = 6 positions = np.vstack([xi.ravel(), yi.ravel()]) values = np.vstack([x, y]) kernel = st.gaussian_kde(values) f = np.reshape(kernel(positions).T, xi.shape) cfset = plt.contourf(xi, yi, f,n_contours, cmap='Greens') cset = plt.contour(xi, yi, f,n_contours, colors='k') #For the points data: positions = np.vstack([x.ravel(), y.ravel()]) values = np.vstack([x, y]) kernel = st.gaussian_kde(values) z = np.reshape(kernel(positions).T, x.shape) #plot: plt.scatter(x, y, c=z) plt.colorbar(cfset) plt.show() thanks! EDIT: I founded a way to do this, using the get_paths() feature, so basically, you need to choose the contour, and then the number of the segment that you need to get the values (x,y), for example: #contour 3, section 0 p = cset.collections[3].get_paths()[0] v = p.vertices x0 = v[:,0] y0 = v[:,1] #contour 3, section 1 p = cset.collections[3].get_paths()[1] v = p.vertices x1 = v[:,0] y1 = v[:,1] #contour 3, section 2 p = cset.collections[3].get_paths()[2] v = p.vertices x2 = v[:,0] y2 = v[:,1] plt.plot(x0,y0,'-',x1,y1,'-',x2,y2,'-') With this, you get:
How do you create a 3D surface plot with missing values matplotlib?
I am trying to create a 3D surface energy diagram where an x,y position on a grid contains an associated z level. The issue is that the grid is not uniform (ie, there is not a z component for every x,y position). Is there a way to refrain from plotting those values by calling them NaN in the corresponding position in the array? Here is what I have tried so far: import numpy as np from matplotlib import pyplot as plt from mpl_toolkits.mplot3d import Axes3D import pylab from matplotlib import cm #Z levels energ = np.array([0,3.5,1,-0.3,-1.5,-2,-3.4,-4.8]) #function for getting x,y associated z values? def fun(x,y,array): return array[x] #arrays for grid x = np.arange(0,7,0.5) y = np.arange(0,7,0.5) #create grid X, Y = np.meshgrid(x,y) zs = np.array([fun(x,y,energ) for x in zip(np.ravel(X))]) Z = zs.reshape(X.shape) plt3d = plt.figure().gca(projection='3d') #gradients now with respect to x and y, but ideally with respect to z only Gx, Gz = np.gradient(X * Y) G = (Gx ** 2 + Gz ** 2) ** .5 # gradient magnitude N = G / G.max() # normalize 0..1 plt3d.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=cm.jet(N), edgecolor='k', linewidth=0, antialiased=False, shade=False) plt.show() I cannot post image here of this plot but if you run the code you will see it But I would like to not plot certain x,y pairs, so the figure should triangle downward to the minimum. Can this be accomplished by using nan values? Also would like spacing between each level, to be connected by lines. n = np.NAN #energ represents the z levels, so the overall figure should look like a triangle. energ = np.array([[0,0,0,0,0,0,0,0,0,0,0,0,0],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,2.6,n,2.97,n,2.6,n,2.97,n,2.6,n,3.58,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,1.09,n,1.23,n,1.09,n,1.23,n,1.7,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,-0.65,n,-0.28,n,-0.65,n,0.33,n,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,-2.16,n,-2.02,n,-1.55,n,n,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,n,-3.9,n,-2.92,n,n,n,n,n,],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,n,n,-4.8,n,n,n,n,n,n,]]) plt3d = plt.figure().gca(projection='3d') Gx, Gz = np.gradient(X * energ) # gradients with respect to x and z G = (Gx ** 2 + Gz ** 2) ** .5 # gradient magnitude N = G / G.max() # normalize 0..1 x = np.arange(0,13,1) y = np.arange(0,13,1) X, Y = np.meshgrid(x,y) #but the shapes don't seem to match up plt3d.plot_surface(X, Y, energ, rstride=1, cstride=1, facecolors=cm.jet(N), edgecolor='k', linewidth=0, antialiased=False, shade=False ) Using masked arrays generates the following error: local Python[7155] : void CGPathCloseSubpath(CGMutablePathRef): no current point. n = np.NAN energ = np.array([[0,0,0,0,0,0,0,0,0,0,0,0,0],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,2.6,n,2.97,n,2.6,n,2.97,n,2.6,n,3.58,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,1.09,n,1.23,n,1.09,n,1.23,n,1.7,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,-0.65,n,-0.28,n,-0.65,n,0.33,n,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,-2.16,n,-2.02,n,-1.55,n,n,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,n,-3.9,n,-2.92,n,n,n,n,n,],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,n,n,-4.8,n,n,n,n,n,n,]]) x = np.arange(0,13,1) y = np.arange(0,13,1) X, Y = np.meshgrid(x,y) #create masked arrays mX = ma.masked_array(X, mask=[[0,0,0,0,0,0,0,0,0,0,0,0,0],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,1,0,1,0,1,0,1,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,0,1,0,1,0,1,0,1,0,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,0,1,0,1,0,1,0,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,0,1,0,1,0,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,0,1,0,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,1,1,1,1]]) mY = ma.masked_array(Y, mask=[[0,0,0,0,0,0,0,0,0,0,0,0,0],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,1,0,1,0,1,0,1,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,0,1,0,1,0,1,0,1,0,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,0,1,0,1,0,1,0,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,0,1,0,1,0,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,0,1,0,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,1,1,1,1]]) m_energ = ma.masked_array(energ, mask=[[0,0,0,0,0,0,0,0,0,0,0,0,0],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,1,0,1,0,1,0,1,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,0,1,0,1,0,1,0,1,0,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,0,1,0,1,0,1,0,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,0,1,0,1,0,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,0,1,0,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,1,1,1,1]]) plt3d = plt.figure().gca(projection='3d') plt3d.plot_surface(mX, mY, m_energ, rstride=1, cstride=1, edgecolor='k', linewidth=0, antialiased=False, shade=False) plt.show()
I was playing around with the code from this forum post, and I was able to make the graph have missing values. You can try the code yourself! I got it to work using float("nan") for the missing values. import plotly.graph_objects as go import numpy as np x = np.arange(0.1,1.1,0.1) y = np.linspace(-np.pi,np.pi,10) #print(x) #print(y) X,Y = np.meshgrid(x,y) #print(X) #print(Y) result = [] for i,j in zip(X,Y): result.append(np.log(i)+np.sin(j)) result[0][0] = float("nan") upper_bound = np.array(result)+1 lower_bound = np.array(result)-1 fig = go.Figure(data=[ go.Surface(z=result), go.Surface(z=upper_bound, showscale=False, opacity=0.3,colorscale='purp'), go.Surface(z=lower_bound, showscale=False, opacity=0.3,colorscale='purp')]) fig.show()