I want to plot a data, which is polar in nature (i.e. has theta and r). But I also want cartesian axes for it, which should be correct (i.e. r cos(theta) must be x and r sin(theta) must be y)
I have tried something, but it isn't working
The origin of the polar plot is not coinciding with the origin of cartesian, and the radius is also mismatching.
Attaching the code
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax4 = fig.add_subplot(1,1,1)
ax4_polar = fig.add_axes(ax4.get_position(), projection='polar', frameon=False)
ax4.set_facecolor('white')
ax4.set_xlim([-10,10])
ax4.set_ylim([-10,10])
ax4.set_xlabel("Distance along lateral axis (meters)")
ax4.set_ylabel("Distance along longitudinal axis (meters)")
ax4.set_title("X-Y scatter plot", color='black')
ax4_polar.set_thetamin(30)
ax4_polar.set_thetamax(150)
# ax4.grid(True)
ax4.xaxis.label.set_color('black')
ax4.yaxis.label.set_color('black')
ax4.tick_params(axis='x', colors='black')
ax4.tick_params(axis='y', colors='black')
theta = [0, np.pi/6, np.pi/3, np.pi/2, 3*np.pi/4]
r = [0, 2, 3 ,4 ,6]
a4, = ax4_polar.plot(theta, r, c='red', marker=".", ls="", alpha=1, label="X-Y scatter")
plt.show()
Please help!
I think the ideal solution to your problem will depend a bit more on what you are trying to accomplish beyond this toy example.
But consider the following:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot()
axp = fig.add_axes(ax.get_position().bounds, polar=True, frameon=False)
theta = np.array([0, np.pi/6, np.pi/3, np.pi/2, 3*np.pi/4])
r = np.array([0, 2, 3 ,4 ,6])
axp.plot(theta, r, 'r.')
# the following 4 commands align the two axes
ax.set_aspect('equal')
ax.set_xlim(-10,10)
ax.set_ylim(-10,10)
axp.set_rlim(0,10)
# to plot on the cartesian axes, one must convert to polar
x = np.cos(theta)*r
y = np.sin(theta)*r
ax.plot(x,y, 'bs', ms=10, mfc='none')
# display the data
plt.draw()
plt.pause(0.1)
In the above image, one can see the two axes are aligned.
Note however, if you call the following commands to set theta limits, the alignment between the Cartesian and the polar axes is broken:
axp.set_thetamin(30)
axp.set_thetamax(150)
plt.draw()
plt.pause(0.1)
This is because the calls to set_thetamin
and set_thetamax
introduced new transformation rules for the polar axes axp
. One can see this by exploring the axp.trans
matrices, e.g. axp.transWedge.get_matrix()
both before and after the adjustment to theta limits.
One can actually use these updated transformations when plotting Cartesian data to maintain alignment:
# remove the original Cartesian axes plot with bad alignment
ax.lines.pop()
# grab the transformation introduced to the theta limits
# note, I explored the transformations tutorial and experimented here to find the proper rules, as transWedge doesn't seem well documented
trans = axp.transProjectionAffine + axp.transWedge + axp.transAxes
# use the transform keyword argument
ax.plot(x,y, 'bs', ms=10, mfc='none', transform=trans)
plt.title("Oh no, the Cartesian axes labels broke!")
plt.draw()
plt.pause(0.1)
In the above, one can see alignment once again, however, now the Cartesian axes labels are incorrect. You can set them manually, again the ideal solution will depend on what you wish to accomplish.
ax.set_title("Manually set axis labels")
mn,mx = ax.get_ylim() # equiv to ax.get_xlim()
# see https://stackoverflow.com/a/40475221/2077270
ax_to_dat = axp.transAxes + axp.transData.inverted()
xlabs = []
ylabs = []
for t in ax.get_yticks():
tfrac = (t-mn)/(mx-mn)
th,rad = ax_to_dat.transform( [0,tfrac])
ylab = "%.1f" % (rad*np.sin(th))
ylabs.append(ylab)
th,rad = ax_to_dat.transform( [tfrac,0])
xlab = "%.1f" % (rad*np.cos(th))
xlabs.append(xlab)
ax.set_yticklabels(ylabs)
ax.set_xticklabels(xlabs)
# add some test lines
ax.hlines([10,0], -10, 10, color='lightgreen', ls='--', transform=trans)
plt.draw()
plt.pause(0.1)
Hope this helps somewhat, and maybe someone with more experience using matplotlib transformations can help further!