removing shades from surface plot in python - python

When I run the attached python code (some of it is junk that is left over from the figure I try to generate), I get a surface with two shades. (dark and light red), is there a way to turn this into a single shade?
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import sys
from math import sqrt,exp,log, sin
from pylab import rcParams
rcParams['figure.figsize'] = 30,26
fig = plt.figure()
ax = fig.add_subplot(211, projection='3d')
l = 7
sigma = 1.0/277.450924284104 #You are stupid so have found the charge density for surface potentail of exactly 62mV
pi = 3.14159
b = 1.0/(2*pi*sigma*l)
lambdaD = 9.5
X0, Y0 = np.mgrid[0:1:100j, 0:1:100j]
Z0 = np.zeros_like(X0)
for i in range(0,len(X0)):
for j in range (0, len(X0[i])):
Z0[i][j] = 10*sin(X0[i][j]*2*pi)
ax.plot_surface(X0,Y0,Z0,color='red', linewidth=0, rstride=10, cstride=10, antialiased=False)
ax.set_axis_off()

Sure, just specify shade=False to ax.plot_surface.
Also, there's absolutely no need to use nested for loops or to specify the figure size through rcParams.
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(30, 26))
ax = fig.add_subplot(111, projection='3d')
X0, Y0 = np.mgrid[0:1:100j, 0:1:100j]
Z0 = 10 * np.sin(X0 * 2 * np.pi)
ax.plot_surface(X0,Y0,Z0,color='red', linewidth=0, rstride=10, cstride=10,
antialiased=False, shade=False)
ax.set_axis_off()
plt.show()

Related

matplotlib 3d: moving tick's label

Is there a way to move tick labels in Matplot3dlib like this?
from mpl_toolkits import mplot3d
import numpy as np
import matplotlib.pyplot as plt
x = np.outer(np.linspace(-2, 2, 30), np.ones(30))
y = x.copy().T # transpose
z = np.cos(x ** 2 + y ** 2)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot_surface(x, y, z,cmap='viridis', edgecolor='none')
ax.set_title('Surface plot')
plt.show()
There are some ways using pad parameters.
However, I want to move more precisely like figure in the link above.
Any help appreciated.
-- Addition --
When I changing PAD parameter like the code below, the tick's label is more closer to the axis. However, I want to move it a little bit more to -x direction.
tick's label position changing
from mpl_toolkits import mplot3d
import numpy as np
import matplotlib.pyplot as plt
x = np.outer(np.linspace(-2, 2, 30), np.ones(30))
y = x.copy().T # transpose
z = np.cos(x ** 2 + y ** 2)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot_surface(x, y, z,cmap='viridis', edgecolor='none')
ax.set_title('Surface plot')
ax.tick_params(axis='x', which='major', pad=-5)
plt.show()

Matplotlib 3d Plot Colorbar Scale

I have a 3d plot with a colorbar and I would like the colorbar's size to scale with the size of the projection, no matter the orientation I select with ax.view_init.
It would also be great if I could get the aspect ratio of the 3d plot to be equal at the same time as well.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.colors
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.view_init(elev=90, azim=0)
x = np.arange(3)
X,Y = np.meshgrid(x,x)
Z = np.ones_like(X)
V = np.array([[3,2,2],[1,0,3],[2,1,0]])
norm = matplotlib.colors.Normalize(vmin=0, vmax=3)
ax.plot_surface(X, Y, Z, facecolors=plt.cm.jet(norm(V)), shade=False)
m = cm.ScalarMappable(cmap=plt.cm.jet, norm=norm)
m.set_array([])
plt.colorbar(m)
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
Example code stolen shamelessly from this question

Matplotlib colored sphere

I have a data set which maps a tuple of phi and theta to
a value which represents the strength of the signal.
I want to plot these on a sphere. I simply followed
a demo from matplotlib and adjusted the code to my
use case.
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
u = phi
v = theta
vals =vals/vals.max()
Map = cm.coolwarm
facecolors = Map(vals[:])
x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))
ax.plot_surface(x, y, z, rstride=1, cstride=1, cmap=cm.coolwarm,
linewidth=0, antialiased=False, facecolors=facecolors)
plt.show()
This generates an error message IndexError: index 4 is out of bounds for axis 0 with size 4. I also looked into the source code, which seems
to indicate to me that facecolors isn't formatted correctly, but I'm
struggling to figure out, what formatting is needed exactly.
Any help or other ways to achieve this goal would be greatly
appreciated.
Greetings
If your question is: "How to get rid of this IndexError?", I modified your code and now it works. plot_surface takes X,Y,Z and facecolors as 2D arrays of corresponding values on a 2D grid. Facecolors in your case weren't and this was the source of your error.
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm, colors
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
u, v = np.mgrid[0:np.pi:50j, 0:2*np.pi:50j]
strength = u
norm=colors.Normalize(vmin = np.min(strength),
vmax = np.max(strength), clip = False)
x = 10 * np.sin(u) * np.cos(v)
y = 10 * np.sin(u) * np.sin(v)
z = 10 * np.cos(u)
ax.plot_surface(x, y, z, rstride=1, cstride=1, cmap=cm.coolwarm,
linewidth=0, antialiased=False,
facecolors=cm.coolwarm(norm(strength)))
plt.show()
Result is this image of a sphere.
However, if your data is not on a 2D grid you are in trouble. Additionally if your grid is not regular the sphere you plot will look irregular as well. So if your question is: "How to plot a heatmap on a sphere?", there is already such a question and solution here using Basemap package produces this result:

Matplotlib line plot: coloring regions of high curvature

I want to plot a line in 3D Space and color regions of high curvature. Right now I have a workaround using a discrete scatter plot:
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cmx
mpl.rcParams['legend.fontsize'] = 10
data = np.loadtxt('data',usecols=range(0,4))
x = data[:,0]
y = data[:,1]
z = data[:,2]
cs = data[:,3]
colorsMap='jet'
cm = plt.get_cmap(colorsMap)
cNorm = mpl.colors.Normalize(vmin=min(cs), vmax=max(cs))
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
fig = plt.figure()
scalarMap.set_array(cs)
fig.colorbar(scalarMap)
ax = fig.gca(projection='3d')
ax.scatter(x, y, z, c=scalarMap.to_rgba(cs), label='scatter curve')
ax.legend()
plt.show()
But I would rather have a continuous line plot.Is there a way to do that?
Depending on how many data points you have you might be able to get your way around this. For instance, consider the generated 3D spiral data below in substitution to your data.txt
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cmx
mpl.rcParams['legend.fontsize'] = 10
theta = np.linspace(-4 * np.pi, 4 * np.pi, 1000)
z = np.linspace(-2, 2, 1000)
r = z**2 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)
cs = 1/r
colorsMap='jet'
cm = plt.get_cmap(colorsMap)
cNorm = mpl.colors.Normalize(vmin=min(cs), vmax=max(cs))
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
fig = plt.figure()
scalarMap.set_array(cs)
ax = fig.gca(projection='3d')
ax.scatter(x, y, z, c=scalarMap.to_rgba(cs), marker='_', s=1)
plt.colorbar(scalarMap)
plt.show()
If the sampling frequency of your data points is not as "tight", then this won't look as nice. However, you could use this accepted answer to improve upon this.

Python 2D plots as 3D (Matplotlib)

Python plot in Matplotlib: I have a number of samples taken daily at the same time which shows a change in measurement (of something). This may be shown as a 2D plot (below left), but as the sample number increases I'd like to display this data as a 3D plot which is stacked (below right image) - this image is for illustration only.
For a starting point my code is below, how may I achieve this?
import numpy as np
import pylab as plt
t = np.arange(1024)*1e-6
y1 = np.sin(t*2e3*np.pi)
y2 = 0.5*y1
y3 = 0.25*y1
plt.plot(t,y1,'k-', label='12/03/14')
plt.plot(t,y2,'r-', label='13/03/14')
plt.plot(t,y3,'b-', label='14/03/14')
plt.xlabel('Time/sample no.')
plt.ylabel('Pk-pk level (arbitrary units)')
plt.legend()
plt.grid()
plt.show()
Would it be something like this?
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import PolyCollection
from matplotlib.colors import colorConverter
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
zs = [0.0, 1.0, 2.0]
t = np.arange(1024)*1e-6
ones = np.ones(1024)
y1 = np.sin(t*2e3*np.pi)
y2 = 0.5*y1
y3 = 0.25*y1
verts=[list(zip(t, y1)), list(zip(t, y2)), list(zip(t, y3))]
poly = PolyCollection(verts, facecolors = ['r','g','b'])
poly.set_alpha(0.7)
ax.add_collection3d(poly, zs=zs, zdir='y')
ax.set_xlabel('X')
ax.set_xlim3d(0, 1024e-6)
ax.set_ylabel('Y')
ax.set_ylim3d(-1, 3)
ax.set_zlabel('Z')
ax.set_zlim3d(-1, 1)
plt.show()

Categories