How do I add cartesian axes to a polar plot in matplotlib? - python

I have a polar contour plot, and I want to add cartesian axes to it. How can I do this? There seems to be no documentation for this.
import numpy as np
import matplotlib.pyplot as plt
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 8, 50)
y = np.linspace(0, 8, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig, ax = plt.subplots(subplot_kw = dict(projection = 'polar'))
plt.axis('off')
ax.contourf(X, Y, Z)

To add cartesian axes to a polar plot, all you have to do is add a second pair of axes at the same position like so:
import numpy as np
import matplotlib.pyplot as plt
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 8, 50)
y = np.linspace(0, 8, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig, ax = plt.subplots(subplot_kw = dict(projection = 'polar'))
plt.axis('off')
ax.contourf(X, Y, Z)
new_axis = fig.add_axes(ax.get_position(), frameon = False)
new_axis.plot()
plt.show()

Related

How to add a legend entry for a curve in 'plt.contour'?

Based on this question, How to plot a function ax^2+bxy+cy^2+d=0 in Python?. I cite code from #Michael Szczesny's answer:
import matplotlib.pyplot as plt
def f(x,y):
return 0.01*x**2+0.008*x*y-0.013*y**2+0.15*x+0.003*y+1.0097
x = np.arange(-10.0,10.0,0.1)
y = np.arange(-10.0,10.0,0.1)
X, Y = np.meshgrid(x,y)
plt.contour(x, y, f(X, Y), [0]);
If I try to add a label for curve f(X,Y):
import matplotlib.pyplot as plt
def f(x,y):
return 0.01*x**2+0.008*x*y-0.013*y**2+0.15*x+0.003*y+1.0097
x = np.arange(-10.0,10.0,0.1)
y = np.arange(-10.0,10.0,0.1)
X, Y = np.meshgrid(x,y)
plt.contour(x, y, f(X, Y), [0], label='class 1')
plt.legend()
plt.show()
Error: UserWarning: The following kwargs were not used by contour:
The answer from 2021 no longer works on Matplotlib 3.5.2. It will not render correctly:
Instead, we should use legend_elements with custom labels:
import matplotlib.pyplot as plt
import numpy as np
def f(x, y):
return 0.01 * x ** 2 + 0.008 * x * y - 0.013 * y ** 2 + 0.15 * x + 0.003 * y + 1.0097
x = np.arange(-10.0, 10.0, 0.1)
y = np.arange(-10.0, 10.0, 0.1)
X, Y = np.meshgrid(x, y)
cnt = plt.contour(x, y, f(X, Y), [0])
artists, labels = cnt.legend_elements()
plt.legend(artists, ['class 1'])
plt.show()
# multiple levels
levels = [0, 1, 2, 3]
cnt = plt.contour(x, y, f(X, Y), levels)
artists, labels = cnt.legend_elements()
custom_labels = []
for level, contour in zip(levels, cnt.collections):
custom_labels.append(f'level {level}')
plt.legend(artists, custom_labels, bbox_to_anchor=[1.01, 1], loc='upper left')
plt.tight_layout()
plt.show()
It will produce the correct result:
Matplotlib's contour seems to be designed with the idea of drawing a colorbar instead of a legend. However, in this case, with only one level, a legend can be forced assigning a label to individual contours:
import matplotlib.pyplot as plt
import numpy as np
def f(x, y):
return 0.01 * x ** 2 + 0.008 * x * y - 0.013 * y ** 2 + 0.15 * x + 0.003 * y + 1.0097
x = np.arange(-10.0, 10.0, 0.1)
y = np.arange(-10.0, 10.0, 0.1)
X, Y = np.meshgrid(x, y)
cnt = plt.contour(x, y, f(X, Y), [0])
cnt.collections[0].set_label('class 1')
plt.legend()
plt.show()
Here is an example of the same approach with multiple levels:
levels = [0, 1, 2, 3]
cnt = plt.contour(x, y, f(X, Y), levels)
for level, contour in zip(levels, cnt.collections):
contour.set_label('level {level}')
plt.legend(bbox_to_anchor=[1.01, 1], loc='upper left')
plt.tight_layout()
plt.show()

Output matplotlib plots from saving

I found a tutorial online for this matplotlib and numpy graph. The code runs smoothly, but there is no output. I have tried to save the graph as a file, but that does not seem to work.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
fig = plt.figure()
ax = plt.axes(projection="3d")
zline = np.linspace(0, 15, 1000)
xline = np.sin(zline)
yline = np.cos(zline)
ax.plot3D(xline, yline, zline, "gray") # Data for three-dimensional scattered points
zdata = 15 * np.random.random(100)
xdata = np.sin(zdata) + 0.1 * np.random.randn(100)
ydata = np.cos(zdata) + 0.1 * np.random.randn(100)
ax.scatter3D(xdata, ydata, zdata, c=zdata, cmap="Greens");
def f(x, y):
return np.sin(np.sqrt(x ** 2 + y ** 2))
x = np.linspace(-6, 6, 30)
y = np.linspace(-6, 6, 30)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.contour3D(X, Y, Z, 50, cmap='binary')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z');
theta = 2 * np.pi * np.random.random(1000)
r = 6 * np.random.random(1000)
x = np.ravel(r * np.sin(theta))
y = np.ravel(r * np.cos(theta))
z = f(x, y)
ax = plt.axes(projection="3d")
ax.plot_trisurf(x, y, z,cmap="viridis", edgecolor="none");
The link to the website is https://www.edureka.co/blog/python-projects/. Surely there is some way to access the graphical user interface to display the plots?
Adding plt.show() at the end will display both of the graphs.

Clip a contourf() plot in 3D plot

I'm making multiple density plots in 3D with a circle shape, using contourf.
What I want to do is similar to a clip_path for a pcolormesh plot.
How can I clip the plot in 3D in particular for a contourf plot?
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, x)
levels = np.linspace(-0.1, 0.4, 100) #(z_min,z_max,number of contour),
a=0
b=1
c=2
Z1 = a+.1*np.sin(2*X)*np.sin(4*Y)
Z2 = b+.1*np.sin(3*X)*np.sin(4*Y)
Z3 = c+.1*np.sin(4*X)*np.sin(5*Y)
plt.contourf(X, Y,Z1, levels=a+levels,cmap=plt.get_cmap('rainbow'))
plt.contourf(X, Y,Z2, levels=b+levels,cmap=plt.get_cmap('rainbow'))
plt.contourf(X, Y,Z3, levels=c+levels,cmap=plt.get_cmap('rainbow'))
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 2)
plt.show()
Are you sure your code generated that output image with the given parameters? I only got some blue squares. Tweaking a bit, it starts looking like yours.
To clip the contours, consider masking the Z arrays. As in:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
import numpy.ma as ma
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, x)
levels = np.linspace(-0.1, 0.4, 100) #(z_min,z_max,number of contour),
a = 0
b = 1
c = 2
Z1 = a + .3 * np.sin(2 * X) * np.sin(4 * Y)
Z2 = b + .3 * np.sin(3 * X) * np.sin(4 * Y)
Z3 = c + .3 * np.sin(4 * X) * np.sin(5 * Y)
mask_cond = (X - .5) ** 2 + (Y - .5) ** 2 > .25
Z1 = ma.masked_where(mask_cond, Z1)
Z2 = ma.masked_where(mask_cond, Z2)
Z3 = ma.masked_where(mask_cond, Z3)
plt.contourf(X, Y, Z1, levels=a + levels, cmap='rainbow')
plt.contourf(X, Y, Z2, levels=b + levels, cmap='rainbow')
plt.contourf(X, Y, Z3, levels=c + levels, cmap='rainbow')
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 3)
plt.show()

Beginner-Make a frame based video in python from figures

I plot figures in a for loop which is a loop for my time, basically at each time step I plot a surf out of my data as below:
for time_step in range(0,nt):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = np.arange(xmin, xmax+dx, dx)
z = np.arange(zmin, zmax+dz, dz)
X, Z = np.meshgrid(x, z)
ax.plot_surface(X, Z, w1[time_step])
plt.show()
Suppose that w1[time_step] changes in the loop and is sth different at each time step, all other assumptions you can have. I plot but don't know only how to make them into a video.
I have done it matlab, but I want to do sth similar in Python
Matplotlib as some animation features you might want to use. Check the following recipe (that I collected from here):
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
import time
def generate(X, Y, phi):
R = 1 - np.sqrt(X**2 + Y**2)
return np.cos(2 * np.pi * X + phi) * R
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
xs = np.linspace(-1, 1, 50)
ys = np.linspace(-1, 1, 50)
X, Y = np.meshgrid(xs, ys)
Z = generate(X, Y, 0.0)
wframe = None
tstart = time.time()
for phi in np.linspace(0, 360 / 2 / np.pi, 100):
oldcol = wframe
Z = generate(X, Y, phi)
wframe = ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2)
# Remove old line collection before drawing
if oldcol is not None:
ax.collections.remove(oldcol)
plt.pause(.001)
print('FPS: %f' % (100 / (time.time() - tstart)))
Just replace the wireframe plot for whatever you want (and also use your data obviously) and you should have what you are looking for.

matplotlib: add circle to plot

How do I add a small filled circle or point to a countour plot in matplotlib?
Here is an example, using pylab.Circle:
import numpy as np
import matplotlib.pyplot as plt
e = np.e
X, Y = np.meshgrid(np.linspace(0, 5, 100), np.linspace(0, 5, 100))
F = X ** Y
G = Y ** X
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
circ = plt.Circle((e, e), radius=0.07, color='g')
plt.contour(X, Y, (F - G), [0])
ax.add_patch(circ)
plt.show()
And here is another example (though not a contour plot) from the docs.
Or, you could just use plot:
import numpy as np
import matplotlib.pyplot as plt
e = np.e
X, Y = np.meshgrid(np.linspace(0, 5, 100), np.linspace(0, 5, 100))
F = X ** Y
G = Y ** X
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
plt.contour(X, Y, (F - G), [0])
plt.plot([e], [e], 'g.', markersize=20.0)
plt.show()

Categories

Resources