Pyplot: Circle class: What are the units of the axis arg? - matplotlib

What units does Pyplot use for the radius size of Circle class objects? Playing around with it, it seems that a radius of .6 is already almost off the screen... small example below
import matplotlib as plt
plt.use('TkAgg')
import matplotlib.pyplot as plt
circle = plt.Circle((0.5, 0.5), 0.6, color='white')
fig, ax = plt.subplots()
plt.subplot
plt.axis('off')
ax.add_artist(circle)
fig.set_facecolor("black")

Absolute units are used for the radius. The reason why 0.6 goes out of the axis is that by default, if you just plot a blank figure, its extent is from 0 to 1. For example
fig, ax = plt.subplots()
ax.set_aspect('equal')
results in
Now if you center your circle at (0.5, 0.5) and use radius of 0.6, it will go outside the axis and you will see a truncated patch as you see in your question.
Things become clear when you remove plt.axis('off') and use radius=0.5
circle = plt.Circle((0.5, 0.5), 0.5, color='blue')
fig, ax = plt.subplots(figsize=(3,3))
# plt.axis('off') <--- commented out
ax.add_artist(circle)
fig.set_facecolor("gray")
ax.set_aspect('equal')
plt.plot([0.5], [0.5], 'ro')

Related

How to make the plot's shape round?

I have created a plot, which is working just fine.
But I really want to change its shape to a circle.
This is my current plotting code:
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5,5), dpi=300)
ax = fig.add_axes([0,0,1,1])
ax.plot(30, 80, marker="o", markersize=20, markeredgecolor="#ed6033", markerfacecolor="#ed6033")
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('center')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
ax.set_facecolor('#8cc9e2')
ax.margins(0.1)
plt.setp(ax.get_xticklabels()[4], visible=False)
plt.xlim(10, 90)
plt.ylim(10, 90)
plt.grid(color='white')
plt.show()
and this is the output I get:
eventually, this is my desired output:
You can clip the path of artists including the background patch using the path of another artist.
Add this snippet before the plt.show() call:
clip_path = plt.Circle(
(0.5, 0.5), 0.5, transform=ax.transAxes, # circle coordinates defined in axes fractions
fill=None, linewidth=0 # makes circle invisible
)
ax.add_patch(clip_path)
ax.patch.set_clip_path(clip_path)

matplotlib text in display coordinate

I try to understand how different coordinate systems work in matplotlib. My understanding is that if I add some texts using data coordinates, then I can achieve the same effect if I first transform the data coordinates to the display coordinates and then add the text using these display coordinates. In the following snippet, I expect the 'x' in green are right on top of the 'x' in red. But they are not. What do I miss here? Thank you!
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.set_xlim(0, 10)
ax.set_ylim(-1, 1)
ax.grid()
ax.text(4,0,'x', horizontalalignment='center', verticalalignment='center', color='r')
_x2, _y2 = ax.transData.transform((4.0, 0))
ax.text(_x2,_y2,'x', horizontalalignment='center', verticalalignment='center', transform=None, color='g')
Result:
Once again, we have examined the FIGURE, DATA, and AXIS criteria. We have modified them for clarity from the data range in question. The same is obtained with the figure criterion, divided by the graph size in inches and dpi value. The position of the origin of the axis is also obtained with the figure reference, and when drawn, it overlaps with the origin of the graph. The origin of the graph is shown in black.
import matplotlib.pyplot as plt
fig_x, fig_y = plt.rcParams['figure.figsize']
dpi = plt.rcParams['figure.dpi']
print(fig_x, fig_y, dpi)
fig, ax = plt.subplots()
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.grid()
g = ax.text(0,0,'o', horizontalalignment='center', verticalalignment='center', color='r')
print('get_position', g.get_position())
_x2, _y2 = ax.transData.transform((0.0, 0))
print('ax.transData', _x2, _y2)
_x3, _y3 = ax.transAxes.transform((0.0, 0))
print('ax.transAxes', _x3, _y3)
# From Figure position to ax.transData
ax.text(_x2/fig_x/dpi,_y2/fig_y/dpi,'x', horizontalalignment='center', verticalalignment='center', color='g', transform=fig.transFigure)
# From Figure position to ax.transAxes
ax.text(_x3/fig_x/dpi,_y3/fig_y/dpi,'x', horizontalalignment='center', verticalalignment='center', color='b', transform=fig.transFigure)
# Figure x0, y0
ax.text(0,0,'x', horizontalalignment='center', verticalalignment='center', color='k', transform=fig.transFigure)
plt.show()

Logarithmic y-axis tick color in matplotlib subplots doesn't work

I am plotting a function in matplotlib using subplots (I have to use subplots because of other reasons) and like to set the y-scale to logarithmic while having the y-ticks in the color red.
I used this code:
import matplotlib.pyplot as plt
x_data = np.arange(500.0, 900.0, 1.0)
def func(x):
return a*(x/500.0)**(-b)
fig, ax = plt.subplots()
ax.plot(x_data, 10*func(x_data))
ax.set_yscale('log')
ax.tick_params('y', colors='r')
plt.show()
image using code above
The tickcolor is black although I specificly set it to red.
However, when I choose a linear scale, the tickcolor is red:
import matplotlib.pyplot as plt
x_data = np.arange(500.0, 900.0, 1.0)
def func(x):
return a*(x/500.0)**(-b)
fig, ax = plt.subplots()
ax.plot(x_data, 10*func(x_data))
ax.set_yscale('linear')
ax.tick_params('y', colors='r')
plt.show()
image using code above
Also, when a manually select the y-axis range, the first tick is red:
import matplotlib.pyplot as plt
x_data = np.arange(500.0, 900.0, 1.0)
def func(x):
return a*(x/500.0)**(-b)
fig, ax = plt.subplots()
ax.plot(x_data, 10*func(x_data))
ax.set_yscale('linear')
ax.tick_params('y', colors='r')
plt.show()
image using code above
It has something to do with the logarithmic scale but I don't know how to solve it. Can someone help me with this?
The ticks you see in the first graph are minor ticks, and ax.tick_params applies to major ticks by default.
You can specify which ticks ax.tick_params applies to using the which= argument:
ax.tick_params('y', which="both", colors='r')

Manipulation on vertical space in matplotlib subplots

I want to reduce the verticalspacing between subplot. Surfing along the web I just have found how to reduce the horizontal spacing, something like
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=4, ncols=4)
fig.tight_layout() # Or equivalently, "plt.tight_layout()"
fig.subplots_adjust(hspace=0.5)
plt.show()
The hspace thing is the one that manipulates such behaviour, but apparently there's no vspace.
EDIT:
This does not reduce the space between the y-axis, that is what I want to manipulate.
As you said in your question hspace reduces the vertical spacing between subplots. The equivalent for horizontal spacing between subplots is wspace. Below is an example:
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
fig, ((ax1,ax2),(ax3,ax4)) = plt.subplots(nrows=2, ncols=2)
fig.tight_layout()
ax1.plot(x, y)
ax2.scatter(x, y)
ax3.scatter(x, y)
ax4.scatter(x, y)
fig.subplots_adjust(wspace=0.2)
plt.show()
Using a value for 1 for wspace gives
Using 0.2 as the value of wspace gives
An alternative approach is to pass the gridspec_kw argument a dict with keys wspace / hspace:
Example
fig, axes = plt.subplots(nrows=2, ncols=2, gridspec_kw={'hspace': 0.2, 'wspace': 0.9})
plt.tight_layout()
for ax, color in zip(axes.ravel(), list('rgbk')):
ax.scatter(np.arange(100), np.random.randn(100), color=color)
If I understood your question correctly, you want to reduce the vertical spacing, which is not what I have seen in all of the answers above.
If I am correct, you should reduce the hspace from 0.5 to 0.2, for instance. That's because hspace does not stand for horizontal spacing, it stands for height spacing, which is what you need.

How to remove padding/border in a matplotlib subplot

The second subplot is just the first image with an overlay ploted. In the second plot there appears to have white padding/boarder. How do I remove this padding/whitespace?
For completness, here is the fragment of code that performs the plotting:
fig, ax = plt.subplots(1, 2)
fig.set_size_inches(16, 6, forward=True)
plt.subplots_adjust(0.05, 0.05, 0.95, 0.95, 0.05, 0.05)
ax[0].set_title("Region Labels")
ax[0].imshow(image_labels)
ax[1].set_title("Region Connectivity Graph")
ax[1].imshow(image_labels)
for edge in edges:
ax[1].plot([centers[edge[0]][0],centers[edge[1]][0]],
[centers[edge[0]][1],centers[edge[1]][1]])
for a in ax:
a.set_xticks(())
a.set_yticks(())
plt.show()
By default, Matplotlib adds some margin to plotted data. I cant test it because it dont have your image_labels and centers, but this should normally work:
ax[1].autoscale_view('tight')
An alternative would be to manually set the xlim and ylim of the axes:
ax[1].set_xlim(0,image_labels.shape[1])
ax[1].set_ylim(0,image_labels.shape[0])