Show entire minor gridline in matplotlib figure - python

I would like to show the topmost minor gridline (at 2.25) in its full width without adjusting the limits manually. How can I achieve this?
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
fig, ax = plt.subplots(constrained_layout=True)
ax.yaxis.set_tick_params(which='minor', width=5)
ax.plot(t, s)
ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.50))
ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.25))
ax.grid(linewidth=5, axis='y', which='both')
ax.set_ylim(0, 2.25)
plt.show()

Adjusting edge gridline visibility in matplotlib
There are a couple ways to accomplish what you're looking for. I think the best method would be to hide the top and right spines. Alternatively, ax.grid takes Line2D args which includes clip_on. Setting clip_on=False has the intended effect of making the ax box not clip the line - but it does result in the top spine going through the grid line (which is not very attractive in my opinion). Lastly, as you mention, you could make a minor increase in y lim (to 2.26 or 2.27) and that would also make the top grid line more visible.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(15,12))
axes = axes.flatten()
ax = axes[0]
ax.yaxis.set_tick_params(which='minor', width=5)
ax.plot(t, s)
ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.50))
ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.25))
ax.grid(linewidth=5, axis='y', which='both', clip_on=False)
[ax.spines[s].set_visible(False) for s in ['top', 'right']]
ax.set_ylim(0, 2.25)
ax.set_title('Hide top/right spines', fontsize=16, fontweight='bold')
ax = axes[1]
ax.yaxis.set_tick_params(which='minor', width=5)
ax.plot(t, s)
ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.50))
ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.25))
ax.grid(linewidth=5, axis='y', which='both', zorder=3, clip_on=False)
ax.set_ylim(0, 2.25)
ax.set_title('Make clip_on=False', fontsize=16, fontweight='bold')
ax = axes[2]
ax.yaxis.set_tick_params(which='minor', width=5)
ax.plot(t, s)
ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.50))
ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.25))
ax.grid(linewidth=5, axis='y', which='both')
ax.set_ylim(0, 2.265)
ax.set_title('Increase ylim to 2.265', fontsize=16, fontweight='bold')
axes[3].axis('off')

Related

Add Empty Subplot With No Axis Ticks/Labels for Text as Subplot in Matplotlib

My goal is to create plot with four subplots, where the bottom two are really just empty boxes where I will display some text. Unfortunately, all of my efforts to remove the y and x axis tick marks and labels have failed. I'm still new to matplotlib so I'm sure there's something simple that I'm missing. Here's what I'm trying and what I get:
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 2, sharex=False, sharey=True, figsize=(6,6))
fig.add_subplot(111, frameon=False)
plt.tick_params(labelcolor='none', top=False, bottom=False, left=False, right=False)
plt.title('Neuron Length')
plt.xlabel('Strain')
plt.ylabel('Neuron Length (um)')
aIP = fig.add_subplot(223, frameon=False)
aIP.annotate('Big Axes \nGridSpec[1:, -1]', (0.1, 0.5),
xycoords='axes fraction', va='center')
# First approach
aIP.axes.xaxis.set_ticks([])
aIP.axes.yaxis.set_ticks([])
# Second approach
ax = plt.gca()
ax.axes.yaxis.set_visible(False)
plt.show()
This is achieved by using plt.subplots() to draw four of them and remove the bottom left frame.
import matplotlib.pyplot as plt
import numpy as np
t = np.linspace(-np.pi, np.pi, 1000)
x1 = np.sin(2*t)
x2 = np.cos(2*t)
x3 = x1 + x2
fig,axes = plt.subplots(nrows=2,ncols=2,figsize=(6,6), sharex=True, sharey=True)
axes[0,0].plot(t, x1, linewidth=2)
axes[0,1].plot(t, x2, linewidth=2)
axes[1,1].plot(t, x3, linewidth=2)
axes[1,0].axis('off') # off
axes[1,0].annotate('Big Axes \nGridSpec[1:, -1]', (0.1, 0.5), xycoords='axes fraction', va='center')
fig.suptitle('Neuron Length')
for ax in axes.flat:
ax.set(xlabel='Strain', ylabel='Neuron Length (um)')
plt.show()

How to Make a secondary vertical axis, with labels on the left, using matplotlib?

I was trying to make a graph with two secondary vertical axis (y-axis), with python matplotlib.
I was using twinx() method, where one of the two new axis is with the default behavior (labels on the right)
and the other with labels on the left, like the example of tan(x) on the figure bellow (created in an specific software).
Is there an easy way to do that? I'm not restricted to use the twinx() method, if there is another way
Here is a way to add two secondary y-axis, one towards the inside:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(.5, 10, 1000)
y1 = np.cos(x)
y2 = np.sin(2 * x)
y3 = np.clip(np.tan(x * .6), -75, 75)
fig, ax1 = plt.subplots()
color = 'dodgerblue'
ax1.set_ylabel('$cos(x)$', color=color)
ax1.plot(x, y1, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx()
color = 'limegreen'
ax2.set_ylabel('$sin(2 x)$', color=color)
ax2.plot(x, y2, color=color)
ax2.tick_params(axis="y", labelcolor=color)
ax3 = ax1.twinx()
color = 'crimson'
ax3.set_ylabel('$tan(.6 x)$', color=color, labelpad=-40)
ax3.plot(x, y3, color=color)
ax3.tick_params(axis="y", labelcolor=color, direction="in", pad=-5)
plt.setp(ax3.get_yticklabels(), ha="right")
ax1.set_xlim(0, 12)
fig.tight_layout()
plt.show()

How to add an encircling axes around a polar plot?

I'm trying to figure out how to append an axes to my polar projection. The newly added axes is supposed to wrap around the original polar axes like a ring.
For that purpose I tried to use append_axes from a divider created via make_axes_locatable on a polar matplotlib projection ax.
However, there's no option for "outer" or anything that would resemble polar projections with the append_axes arguments.
Instead of a ring around the axes, I get a new axes just below the original one (see picture).
Is there any alternative that would allow creating an axes of ring shape around an existing polar axes?
Note, I don't want to add them on the same ax because the scales may be different.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
plt.style.use("seaborn-white")
def synthesize(polar=False):
fig = plt.figure()
ax = fig.add_subplot(111, polar=polar)
t = np.linspace(0,2*np.pi)
r_sin = np.sin(t)
r_cos = np.cos(t)
for r in [r_sin, r_cos]:
ax.scatter(t, r, c=r, s=t*100, edgecolor="white", cmap=plt.cm.magma_r)
ax.scatter(t, -r, c=r, s=t*100, edgecolor="white", cmap=plt.cm.magma_r)
ax.set_title("polar={}".format(polar),fontsize=15)
ax.set_xticklabels([])
return fig, ax, t
# Rectilinear
fig, ax, t = synthesize(polar=False)
# Here are the plot dimensions in response to the answer below
xlim = ax.get_xlim()
ylim = ax.get_ylim()
rlim = (ax.get_rmin(), ax.get_rmax())
print(xlim, ylim, rlim)
(0.0, 6.283185307179586) (0.0, 2.2437621373846617) (0.0, 2.2437621373846617)
# Encircling axis
divider = make_axes_locatable(ax)
ax_below = divider.append_axes("bottom", size="32.8%", pad=0.1)
ax_below.scatter(t, np.tan(t), c="black", edgecolor="white")
# Polar
fig, ax, t = synthesize(polar=True)
divider = make_axes_locatable(ax)
ax_below = divider.append_axes("bottom", size="32.8%", pad=0.1)
ax_below.scatter(t, np.tan(t), c="black", edgecolor="white")
You probably can do something by tunning set_rmax and set_rorigin like this:
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("seaborn-white")
def synthesize(polar=False):
fig = plt.figure()
ax = fig.add_subplot(111, polar=polar)
ax.set_rmax(30)
t = np.linspace(0,2*np.pi)
r_sin = np.sin(t)
r_cos = np.cos(t)
for r in [r_sin, r_cos]:
ax.scatter(t, r, c=r, s=t*100, edgecolor="white", cmap=plt.cm.magma_r)
ax.scatter(t, -r, c=r, s=t*100, edgecolor="white", cmap=plt.cm.magma_r)
ax.set_title("polar={}".format(polar),fontsize=15)
ax.set_xticklabels([])
return fig, ax, t
# Polar
fig, ax, t = synthesize(polar=True)
ax_below = fig.add_subplot(111, polar=True, frameon=True)
# ax_below = divider.append_axes("bottom", size="32.8%", pad=0.1)
ax_below.scatter(t, np.tan(t), c="black", edgecolor="white")
ax_below.set_rorigin(-75)
ax_below.set_rmin(-25)
plt.show()

Circle with matplotlib with border out of the figure

I am trying to draw a circle with matplotlib, with a diameter, say, of 2 inches and a border of 10 pixels, and I want to save it in a file. This is my code:
import matplotlib.pyplot as plt
from matplotlib import patches
path = 'test.png'
fig1 = plt.figure()
fig1.dpi = 100
fig1.set_size_inches(2, 2)
ax1 = fig1.add_subplot(111, aspect='equal')
ax1.axes.get_xaxis().set_visible(False)
ax1.axes.get_yaxis().set_visible(False)
ax1.add_patch(patches.Circle((0.5, 0.5),
radius=0.5,
color='k', linewidth=10, fill=False))
fig1.tight_layout()
fig1.savefig(path, bbox_inches='tight', pad_inches=0)
and this is what I get:
As you can see, part of the border is out of the picture.
In fact, even doing something much simpler, I get similar results:
import matplotlib.pyplot as plt
from matplotlib import patches
fig1 = plt.figure()
ax1 = fig1.add_subplot(111, aspect='equal')
ax1.add_patch(patches.Circle((0.5, 0.5),
radius=0.5,
color='k', linewidth=10, fill=False))
plt.show()
so, I can't understand where is the problem.
What am I doing wrong?
Adding a patch won't automatically adjust the axes limits. You have to call ax1.autoscale_view() to adjust the limits to the content.
fig1 = plt.figure()
ax1 = fig1.add_subplot(111, aspect='equal')
ax1.add_patch(patches.Circle((0.5, 0.5),
radius=0.5,
color='k', linewidth=10, fill=False))
ax1.autoscale_view()
The limits are small, by default take the minimum position and maximum of all points without considering the thickness, I recommend that you set the limits a little bigger. You must be {axes}.set_xlim() and {axes}.set_ylim()
import matplotlib.pyplot as plt
from matplotlib import patches
path = 'test.png'
fig1 = plt.figure()
fig1.dpi = 100
fig1.set_size_inches(2, 2)
ax1 = fig1.add_subplot(111, aspect='equal')
ax1.axes.get_xaxis().set_visible(False)
ax1.axes.get_yaxis().set_visible(False)
ax1.add_patch(patches.Circle((0.5, 0.5),
radius=0.5,
color='k', linewidth=10, fill=False))
ax1.set_xlim([-0.1, 1.1])
ax1.set_ylim([-0.1, 1.1])
fig1.tight_layout()
fig1.savefig(path, bbox_inches='tight', pad_inches=0)

How to display yaxis on both side using matplotlib 0.99?

I want to display yaxis on both side. In matplotlib 1.2, I can use following code:
ax.tick_params(labelright = True)
However, there is no method tick_params for Axes in matplotlib 0.99. Is there any simple way to do this in 0.99?
Tks
EDIT
I got this solution followed by #Brian Cain's
ax2 = ax1.twinx()
ax2.set_yticks(ax1.get_yticks())
ax2.set_yticklabels([t.get_text() for t in ax1.get_yticklabels()])
Here is an example from matplotlib docs with differing scales on each Y axis. You could use the same scale if you preferred.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
t = np.arange(0.01, 10.0, 0.01)
s1 = np.exp(t)
ax1.plot(t, s1, 'b-')
ax1.set_xlabel('time (s)')
# Make the y-axis label and tick labels match the line color.
ax1.set_ylabel('exp', color='b')
for tl in ax1.get_yticklabels():
tl.set_color('b')
ax2 = ax1.twinx()
s2 = np.sin(2*np.pi*t)
ax2.plot(t, s2, 'r.')
ax2.set_ylabel('sin', color='r')
for tl in ax2.get_yticklabels():
tl.set_color('r')
plt.show()

Categories