I'm trying to label the nodes in my polar coordinates plot. There are 3 "axes" that are split and I have figured out how to use the quadrants to select which nodes to label. However, I can't figure out how to align these on the edge of the plot (i.e. axis_maximum). I have spent several hours trying to figure this out. My best option was to pad with . on the left or right but this was a fixed number and got messy when there were too many points. Also, this method went too far outside the "circular" nature of the plot when there were a lot of points. I did some trigonometry to figure out the lengths for everything but this was difficult to implement using text units such as ..
If anyone can help it would be greatly appreciated. I showed what the plot looks like below and then added in red what I am trying to implement. label in the mock figure corresponds to name_node in the for-loop. Ideally I would like to steer away from using characters like . and would rather use an actual matplotlib Line object so I can specify linestyle like : or -.
In summary, I would like to do the following:
- Add horizontal lines stretching from my "axis" to the outer edge of the plot (either the right or the left depending on the quadrant)
- At the end of the line in (1), I would like to add the
name_nodetext.
EDIT:
- I've added an attempt to overlay a cartesian axis and then plot the lines on this. No success.
import numpy as np
from numpy import array # I don't like this but it's for loading in the pd.DataFrame
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({'node_positions_normalized': {'iris_100': 200.0, 'iris_101': 600.0, 'iris_102': 1000.0, 'iris_0': 200.0, 'iris_1': 600.0, 'iris_2': 1000.0, 'iris_50': 200.0, 'iris_51': 600.0, 'iris_52': 1000.0}, 'theta': {'iris_100': array([5.42070629, 6.09846678]), 'iris_101': array([5.42070629, 6.09846678]), 'iris_102': array([5.42070629, 6.09846678]), 'iris_0': array([1.23191608, 1.90967657]), 'iris_1': array([1.23191608, 1.90967657]), 'iris_2': array([1.23191608, 1.90967657]), 'iris_50': array([3.32631118, 4.00407168]), 'iris_51': array([3.32631118, 4.00407168]), 'iris_52': array([3.32631118, 4.00407168])}})
axis_maximum = df["node_positions_normalized"].max()
thetas = np.unique(np.stack(df["theta"].values).ravel())
def pol2cart(rho, phi):
x = rho * np.cos(phi)
y = rho * np.sin(phi)
return(x, y)
def _get_quadrant_info(theta_representative):
# 0/360
if theta_representative == np.deg2rad(0):
quadrant = 0
# 90
if theta_representative == np.deg2rad(90):
quadrant = 90
# 180
if theta_representative == np.deg2rad(180):
quadrant = 180
# 270
if theta_representative == np.deg2rad(270):
quadrant = 270
# Quadrant 1
if np.deg2rad(0) < theta_representative < np.deg2rad(90):
quadrant = 1
# Quadrant 2
if np.deg2rad(90) < theta_representative < np.deg2rad(180):
quadrant = 2
# Quadrant 3
if np.deg2rad(180) < theta_representative < np.deg2rad(270):
quadrant = 3
# Quadrant 4
if np.deg2rad(270) < theta_representative < np.deg2rad(360):
quadrant = 4
return quadrant
with plt.style.context("seaborn-white"):
fig = plt.figure(figsize=(8,8))
ax = plt.subplot(111, polar=True)
ax_cartesian = fig.add_axes(ax.get_position(), frameon=False, polar=False)
ax_cartesian.set_xlim(-axis_maximum, axis_maximum)
ax_cartesian.set_ylim(-axis_maximum, axis_maximum)
# Draw axes
for theta in thetas:
ax.plot([theta,theta], [0,axis_maximum], color="black")
# Draw nodes
for name_node, data in df.iterrows():
r = data["node_positions_normalized"]
for theta in data["theta"]:
ax.scatter(theta, r, color="teal", s=150, edgecolor="black", linewidth=1, alpha=0.618)
# Draw node labels
quadrant = _get_quadrant_info(np.mean(data["theta"]))
# pad on the right and push label to left
if quadrant in {1,4}:
theta_anchor_padding = min(data["theta"])
# pad on left and push label to the right
if quadrant in {2,3}:
theta_anchor_padding = max(data["theta"])
# Plot
ax.text(
s=name_node,
x=theta_anchor_padding,
y=r,
horizontalalignment="center",
verticalalignment="center",
)
ax.set_rlim((0,axis_maximum))
# Convert polar to cartesian and plot on cartesian overlay?
xf, yf = pol2cart(theta_anchor_padding, r) #fig.transFigure.inverted().transform(ax.transData.transform((theta_anchor_padding, r)))
ax_cartesian.plot([xf, axis_maximum], [yf, yf])

