Is it possible to hatch PolyCollection instance?
I want to hath a PolyCollection returned from fill_betweenx.
import matplotlib.mlab as mlab
from matplotlib.pyplot import figure, show
import numpy as np
x = np.arange(0.0, 2, 0.01)
y1 = np.sin(2*np.pi*x)
y2 = 1.2*np.sin(4*np.pi*x)
fig = figure()
ax1 = fig.add_subplot(111)
PC = ax1.fill_betweenx(x, 0, y1)
# I want to do something like this
# PC.set_hatch('\')
# but there is no such method
show()
It's a bit of a hack, but you should be able to do something like this:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import PathPatch
x = np.arange(0.0, 2, 0.01)
y1 = np.sin(2*np.pi*x)
y2 = 1.2*np.sin(4*np.pi*x)
fig, ax = plt.subplots()
pc = ax.fill_betweenx(x, 0, y1, color='blue')
# Now we'll add the hatches...
for path in pc.get_paths():
patch = PathPatch(path, hatch='/', facecolor='none')
ax.add_patch(patch)
plt.show()
Related
I have tried using gridspec, everything looks fine but mi main plot doesn't fill all the space.
[1]: https://i.stack.imgur.com/frHEN.png
[2]: https://i.stack.imgur.com/MA1Sg.png
This is my code:
import h5py
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import transforms
from matplotlib.transforms import Affine2D
import matplotlib.gridspec as gridspec
from FUNCION import *
from FUNCIONAVG import *
f = h5py.File('Datos1', 'r')
list(f.keys())
print(f.keys());
data=f['default'];
data=np.array(data)
fig = plt.figure(1, figsize=(5, 5))
gs = gridspec.GridSpec(8, 8)
gs.update(wspace=0, hspace=0)
xtr_subplot = fig.add_subplot(gs[0:6, 0:2])
base = plt.gca().transData
rot = transforms.Affine2D().rotate_deg(90)
line = plt.plot(sum, transform=rot + base)
plt.ylabel("Y Label")
ax = plt.gca()
ax.axes.xaxis.set_ticklabels([])
xtr_subplot = fig.add_subplot(gs[0:6, 2:6])
plt.imshow(data, aspect=(6/4))
ax = plt.gca()
ax.axes.yaxis.set_ticklabels([])
xtr_subplot = fig.add_subplot(gs[6:8, 2:6])
plt.plot(avg)
plt.savefig("multipanel.png")
plt.show()
Set the aspect argument of plt.imshow.
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import gridspec
from matplotlib import transforms
data = np.random.randn(100).reshape(10, 10)
avg = np.random.randn(10)
total = np.random.randn(10)
fig = plt.figure(1, figsize=(5, 5))
gs = gridspec.GridSpec(8, 8)
gs.update(wspace=0, hspace=0)
xtr_subplot = fig.add_subplot(gs[0:6, 0:2])
base = plt.gca().transData
rot = transforms.Affine2D().rotate_deg(90)
line = plt.plot(total, transform=rot + base)
plt.ylabel("Y Label")
ax = plt.gca()
ax.axes.xaxis.set_ticklabels([])
xtr_subplot = fig.add_subplot(gs[0:6, 2:6])
plt.imshow(data, aspect=(6 / 4))
ax = plt.gca()
ax.axes.yaxis.set_ticklabels([])
xtr_subplot = fig.add_subplot(gs[6:8, 2:6])
plt.plot(avg)
plt.savefig("multipanel.png")
I want to add a colormap to this interpolated line, such that the colour of the line-segment changes with the value in the y-axis.
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import CubicHermiteSpline
fig, ax = plt.subplots()
x = [1,2,3,4,5,6,7,8,9,10]
y = [8,2,1,7,5,5,8,1,9,5]
cs = CubicHermiteSpline(x, y, np.zeros(len(x)))
xs = np.linspace(min(x), max(x), num=100)
ax.plot(xs, cs(xs))
Further updates:
I took the suggestion of playing around with this tutorial. I've been able to create a LineCollection and apply the colormap. However, the multicoloured line will only show up behind the plotted line. Removing the plot command removes all lines from plot.
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import CubicHermiteSpline
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap, BoundaryNorm
fig, ax = plt.subplots()
x = [1,2,3,4,5,6,7,8,9,10]
y = [8,2,1,7,5,5,8,1,9,5]
cs = CubicHermiteSpline(x, y, np.zeros(len(x)))
xs = np.linspace(min(x), max(x), num=400)
points = np.array([xs, cs(xs)]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
norm = plt.Normalize(cs(xs).min(), cs(xs).max())
lc = LineCollection(segments, cmap='rainbow', norm=norm)
lc.set_array(cs(xs))
lc.set_linewidth(2)
line = ax.add_collection(lc)
fig.colorbar(line, ax=ax)
ax.plot(xs, cs(xs))
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 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()
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()