Asked 1 month ago by InterstellarWayfarer151
How can I zoom in on sub-degree theta variations in a Matplotlib polar plot?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by InterstellarWayfarer151
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I have RA and DEC pointing data that I convert to polar coordinates (rho and theta) for plotting with Matplotlib. However, the theta variations are extremely small (around 0.01°), making them nearly invisible on a full polar plot.
When I adjust the theta limits using ax.set_thetamin() and ax.set_thetamax(), I end up with a very thin wedge that loses useful information. I would like to display a wedge that spans at least one degree while still emphasizing the tiny shifts between data points.
Below is the code I am currently using:
PYTHONimport numpy as np import matplotlib.pyplot as plt import matplotlib import pandas as pd print('matplotlib version : ', matplotlib.__version__) fig = plt.figure() ra = np.asarray([1.67484,1.67485,1.67485,1.67486,1.67486,1.67488,1.67487,1.67488,1.67487, 1.67487]) #radians dec = np.asarray([-0.92147,-0.92147,-0.92147,-0.92147,-0.92147,-0.92147,-0.92147, -0.92147,-0.92147, -0.92147]) #radians rho = np.sqrt(ra**2 + dec**2) # get rho from ra and dec theta = np.tan(dec / ra) # get theta from ra and dec fig = plt.figure() ax = fig.add_subplot(1,1,1,polar=True) ax.plot(theta, rho,'*-',color='y') ax.set_ylim(1.9114,1.9117) # limits of rho ax.set_thetamin(310) ax.set_thetamax(340) plt.show()
I have reviewed the Matplotlib polar plot documentation and online examples, but none address how to magnify very small theta differences while keeping a meaningful wedge shape. Any suggestions on how to rescale or otherwise adjust the theta values to make such sub-degree changes visible?
Comments 0
•Answers 3
•Views 78
Answer by TychoAI Agent • 1 month ago
Below is one suggested approach. By default the polar projection always draws a full circle (or a full wedge defined by your thetamin/thetamax), so “zooming in” on a very small change in theta isn’t supported directly. In other words, setting very narrow theta limits can make the drawn wedge too thin to be useful.
A common workaround is to explicitly rescale (or “exaggerate”) the theta values so that the relative change is larger while still drawing a wedge of a desired width. For example, you may choose a center angle and then apply an offset and a zoom factor to the differences from that center. In this way your plotted data will be transformed so that small variations are amplified. You then set the wedge limits to a comfortable range (say one or two degrees) so the resulting plot remains readable.
Here’s an illustrative example:
PYTHONimport numpy as np import matplotlib.pyplot as plt # Original RA/DEC data (in radians). # Replace these with your actual data. ra = np.asarray([1.67484, 1.67485, 1.67485, 1.67486, 1.67486, 1.67488, 1.67487, 1.67488, 1.67487, 1.67487]) dec = np.asarray([-0.92147, -0.92147, -0.92147, -0.92147, -0.92147, -0.92147, -0.92147, -0.92147, -0.92147, -0.92147]) # Compute rho from ra and dec. rho = np.sqrt(ra**2 + dec**2) # Compute theta from ra and dec. (Note: double-check your conversion.) theta = np.tan(dec / ra) # Determine a center for theta; for instance, choose the midpoint of your desired wedge. # Here we choose 325° (converted to radians) as an example. theta_center = np.deg2rad(325) # Compute the offset from the center. theta_offset = theta - theta_center # Define a zoom factor to exaggerate small variations in theta. zoom_factor = 100 # Adjust this factor as needed. # Create modified theta values that exaggerate the small differences. theta_zoomed = theta_center + theta_offset * zoom_factor fig = plt.figure() ax = fig.add_subplot(1, 1, 1, polar=True) ax.plot(theta_zoomed, rho, '*-', color='y') ax.set_ylim(1.9114, 1.9117) # your rho limits # Set a wedge that spans at least one degree. # For example, from 324° to 326°. ax.set_thetamin(324) ax.set_thetamax(326) plt.show()
Rescaling Theta Data:
By subtracting a chosen center (here 325°) and multiplying the small differences by a zoom factor, you “magnify” the shifts in theta. This way, even if the true change is 0.01° the shifted value is 0.01° × (zoom factor) and becomes easier to see.
Defining the Wedge:
You then choose wedge limits (with set_thetamin/set_thetamax) that suit your display requirements—for example, ensuring that you always show at least a one‑degree span.
Caveats:
Note that this manual transform means the axis tick labels and the plotted theta values should be interpreted with the transformation in mind. If you need the ticks to show the original (unzoomed) values, you may need to add custom tick labeling.
This approach lets you emphasize small changes in the theta coordinate while still showing a wedge-shaped polar plot that is wide enough to be useful.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by CelestialDiscoverer868 • 1 month ago
First of all, you still have some potential concerning narrowing down the plotted radial range, e.g., to ax.set_ylim(1.91159, 1.91164)
. Please also note, that when I was searching for a solution (which I couldn't fin on the internet either), I found that using np.arctan2()
is the appropriate approach for polar coordinates, that is the reason why I changed this part in your code.
Otherwise, I had no better idea than applying a scaling approach to your plot. Now the wedge in question is scaled up by an arbitrary scaling factor (i.e., theta for the upscaled plot in degrees), as in:
PYTHONimport numpy as np import matplotlib.pyplot as plt ra = np.asarray([1.67484, 1.67485, 1.67485, 1.67486, 1.67486, 1.67488, 1.67487, 1.67488, 1.67487, 1.67487]) dec = np.asarray([-0.92147, -0.92147, -0.92147, -0.92147, -0.92147, -0.92147, -0.92147, -0.92147, -0.92147, -0.92147]) rho = np.sqrt(ra**2 + dec**2) theta = np.arctan2(dec, ra) # instead of np.tan(dec / ra), see the other answer. # set scaling factor scalingfactor = 40 # scaling up by arbitrary scaling factor theta_scaled = (theta - np.min(theta)) / (np.max(theta) - np.min(theta)) * np.radians(scalingfactor) fig, ax = plt.subplots(figsize=(6, 6), subplot_kw={'projection': 'polar'}) ax.plot(theta_scaled, rho, '*-', color='y', label=f"Scaled 1:{1/scalingfactor}") ax.set_ylim(1.91159, 1.91164) #check theta limits print(np.degrees(min(theta)), np.degrees(max(theta))) #creating theta ticks ticks = np.radians(np.linspace(0, scalingfactor, 5)) ax.set_xticks(ticks) # setting theta labels explicitly scaled_labels = np.round(np.linspace(360+np.degrees(min(theta)), 360+np.degrees(max(theta)), len(ticks)), 4) ax.set_xticklabels(scaled_labels) ax.set_thetamin(-3) ax.set_thetamax(scalingfactor+1) ax.grid(True, linestyle="--", alpha=0.5) ax.legend() plt.show()
I am sure you can still make it look prettier, otherwise, it looks to be a solid solution to me, resulting in for example this version of the plot:
No comments yet.
Answer by LunarRanger417 • 1 month ago
Mine is uglier :
PYTHONimport numpy as np import matplotlib.pyplot as plt import matplotlib import pandas as pd print('matplotlib version : ', matplotlib.__version__) fig = plt.figure() ra = np.asarray([1.67484,1.67485,1.67485,1.67486,1.67486,1.67488,1.67487,1.67488,1.67487, 1.67487]) #radians dec = np.asarray([-0.92147,-0.92147,-0.92147,-0.92147,-0.92147,-0.92147,-0.92147, -0.92147,-0.92147, -0.92147]) #radians rho = np.sqrt(ra**2 + dec**2) # get rho from ra and dec #theta_or = np.tan(dec / ra) #get theta from ra and dec to keep original theta_or = np.arctan2(dec , ra) ## changed as per comments , theta expressed correctly #theta = np.tan(dec / ra) as in the original question #theta expressed correctly: theta = np.arctan2(dec, ra) print('\ntheta : ', theta) print(theta*180/np.pi) print(360+theta*180/np.pi) # theta = 360+theta*180/np.pi idx = None print(enumerate(theta)) for i, value in enumerate(theta): #print(i,value) #print(theta[i] ) theta[i] = value + i*0.1 #print(i*0.1) idx = i print('theta[idx] : ', theta[idx], idx) print('rho : ', rho) print('\ntheta : ', theta) fig = plt.figure() ax = fig.add_subplot(1,1,1,polar=True) ax.plot(theta, rho,'*-',color='y') ax.set_ylim(1.9114,1.9117) srt = [-10+theta[0]*180/np.pi , 10+theta[idx]*180/np.pi] print('\nsrt : ', srt) ax.set_thetamin(srt[0]) ax.set_thetamax(srt[1]) ticks = np.linspace(theta[0], theta[-1], len(theta)) ax.set_xticks(ticks) #ax.set_xticklabels([i*180/np.pi+360 for i in theta]) ax.set_xticklabels([360 + i*180/np.pi for i in theta_or]) plt.show()
but the pics has x_labels more similar to the original:
Guess as per other answer
The conversion in the question was incorrect:
See
No comments yet.
No comments yet.