Minor ticklines in Y axis is not showing in matplotlib - python

I have a log-log plot where minor ticklines shows only in x axis not in y axis. Because my y-axis major ticks are not spaced like x-axis.
plot
Here is my code,
import numpy as np
import matplotlib.pyplot as plt
z = np.loadtxt("msd_profile2.out",delimiter=' ',skiprows=200005)[:, 5]
y= np.loadtxt("msd_profile2.out",delimiter=' ',skiprows=200005)[:, 4]
x=np.loadtxt("msd_profile2.out",delimiter=' ',skiprows=200005)[:, 3]
time =np.loadtxt("msd_profile2.out",delimiter=' ',skiprows=200005)[:, 2]
xy= (np.sqrt(x**2+y**2))
plt.rc('font', size=18,family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig, ax = plt.subplots()
ax.plot(time, z,label="Z")
ax.plot(time, xy,label="XY")
ax.set_xscale('log')
ax.set_yscale('log')
ax.set_xlabel('Time')
ax.set_ylabel('MSD')
ax.legend()
plt.savefig('H:/figure/msd_ar12.png', dpi=600)
plt.show()
How can I add customize tick spacing in yaxis? I think it suppose to be done by default.

read the matplotlib documentation. It appear minor ticks are turned off by default.
You may need to import from matplotlib.ticker to get the MultipleLocator to specify the frequency of your ticks.

Related

how to display axis on binary while having log scale and adding custom grid lines

I gathered different pieces of code from here. My code looks as follows:
fig, ax = plt.subplots()
ax.set_yscale('log', base=2)
ax.yaxis.set_major_formatter(lambda x, pos: f"{int(x):12b}")
data = np.arange(100)
ticks = [2, 3, 4, 13]
plt.plot(data,data)
ax.set_yticks(ticks, minor=True)
ax.yaxis.grid(True, which='minor')
plt.show()
So, the goal is to plot in logarithmic scale, displaying the y axis in binary and adding custom ticks. The code works perfectly, except that the ticks are displayed in decimal. As shown in the picture below. I'd like them to be also in binary. I tried to fix it, but I really have no idea how. I tried setting ax.set_ticks([lambda x: f"{int(x):12b}"], minor=True) but that didn't work. I'd appreciate if someone can help me.
For the minor ticks you need ax.yaxis.set_minor_formatter(...). You'll notice that the major and minor ticks aren't aligned equally. This is due to the tick lengths, which can be forced equal via ax.tick_params(..., length=...).
from matplotlib import pyplot as plt
import numpy as np
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(15, 4))
for ax in (ax1, ax2):
ax.set_yscale('log', base=2)
ax.yaxis.set_major_formatter(lambda x, pos: f"{int(x):12b}")
ax.yaxis.set_minor_formatter(lambda x, pos: f"{int(x):12b}")
data = np.arange(100)
ticks = [2, 3, 4, 13]
ax.plot(data,data)
ax.set_yticks(ticks, minor=True)
ax.yaxis.grid(True, which='minor')
ax1.set_title('default tick lengths')
ax2.set_title('equal tick lengths')
ax2.tick_params(axis='y', which='both', length=2)
plt.show()
PS: Note that minor ticks are suppressed when their position is very close to the major ticks. Therefore, no grid lines are visible for 2 and 4. You can work around that by shifting them a bit. E.g.
ticks = [2.001, 3.001, 4.001, 13.001]
Or you could change the role of major and minor ticks, using the LogLocator for the minor ticks:
from matplotlib.ticker import LogLocator
ax.yaxis.set_minor_locator(LogLocator(base=2))
ax.set_yticks(ticks)
ax.yaxis.grid(True, which='major')

How to make axes ticks in between grid lines in matplotlib?

In my simple example below, how to make x-axis tick values to appear between grids?
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)
x = range(10)
y = np.random.random(10)
plt.plot(x,y)
plt.xticks(x)
plt.grid(True)
plt.show()
The following make ticks to be where I want but the grid lines also moves.
np.random.seed(1)
x = range(10)
y = np.random.random(10)
plt.plot(x,y)
plt.xticks(x)
plt.grid(True)
plt.xticks(np.arange(10)+0.5, x)
plt.show()
I would like the result to be:
You can set the minor ticks so that only 1 minor tick appears inbetween your major ticks. This is done using matplotlib.ticker.AutoMinorLocator. Then, set the gridlines to only appear at the minor ticks. You also need to shift your xtick positions by 0.5:
from matplotlib.ticker import AutoMinorLocator
np.random.seed(10)
x = range(10)
y = np.random.random(10)
plt.plot(x,y)
plt.xticks(np.arange(0.5,10.5,1), x)
plt.xlim(0,9.5)
plt.ylim(0,1)
minor_locator = AutoMinorLocator(2)
plt.gca().xaxis.set_minor_locator(minor_locator)
plt.grid(which='minor')
plt.show()
Edit: I'm having trouble getting two AutoMinorLocators to work on the same axis. When trying to add in another one for the y axis, the minor ticks get messed up. A work around I have found is to manually set the locations of the minor ticks using a matplotlib.ticker.FixedLocator and passing in the locations of the minor ticks.
from matplotlib.ticker import AutoMinorLocator
from matplotlib.ticker import FixedLocator
np.random.seed(10)
x = range(10)
y = np.random.random(10)
plt.plot(x,y)
plt.xticks(np.arange(0.5,10.5,1), x)
plt.yticks([0.05,0.15,0.25,0.35,0.45,0.55,0.65,0.75,0.85,0.95,1.05], [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1])
plt.xlim(0,9.5)
plt.ylim(0,1.05)
minor_locator1 = AutoMinorLocator(2)
minor_locator2 = FixedLocator([0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1])
plt.gca().xaxis.set_minor_locator(minor_locator1)
plt.gca().yaxis.set_minor_locator(minor_locator2)
plt.grid(which='minor')
plt.show()
If you use plt.subplots for figure creation, you get an axes object, too:
f, ax = plt.subplots(1)
This one has a better Interface for adjusting grid/ticks. Then you can give explicitly x-values for your data shifted 0.5 to the left. The same do with the minor ticks and let the grid be shown at the minor ticks:
f, ax = plt.subplots(1)
ax.set_xticks(range(10))
x_values = np.arange(10) - .5
ax.plot(x_values, np.random.random(10))
ax.set_xticks(x_values, minor=True)
ax.grid(which='minor')

plotting with pcolormesh, changing axis

Supppose I am plotting a assymetric matrix with pcolormesh:
import prettyplotlib as ppl
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
fig, ax = plt.subplots(1)
ppl.pcolormesh(fig, ax, np.random.randn(10,80))
plt.show()
Now I want to change the x-axis such that its extents are for example -500 to 500 without changing the plot, only the labels of the x-axis, the same for y-axis. How can I accomplish that?
After the ppl.pcolormesh command you can define the ticklables directly using
ax.set_xticks(xticks)
ax.set_xticklabels(xticklabels)
where xticklabels is an array of your desired labels and xticks are the values at which the labels should apply.

Add an x-axis at 0 to a pyplot histogram with negative bars

In the histogram produced with the following code, there's no x axis at the zero level
import matplotlib.pyplot as plt
plt.bar(left=[0,4,5],height=[-100,10,110],color=['red','green','green'],width=0.1)
plt.show()
How to put it there?
I tend to use spines to get the x-axis centered:
import matplotlib.pyplot as plt
fig = plt.figure(facecolor='white')
ax = fig.add_subplot(1,1,1)
ax.bar(left=[0,4,5],height=[-100,10,110],color=['red','green','green'],width=0.1)
ax.grid(b=True)
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
plt.show()
Which will produce the next plot:
By default matplotlib does not consider the y=0 line important. You can turn on the grid by a call such as plt.grid().
An alternative used often in the matplotlib.pylab docs is to set a horizontal line at 0. This is done by
plt.axhline(0, color='black', lw=2)

how to turn on minor ticks only on y axis matplotlib

How can I turn the minor ticks only on y axis on a linear vs linear plot?
When I use the function minor_ticks_on to turn minor ticks on, they appear on both x and y axis.
Nevermind, I figured it out.
ax.tick_params(axis='x', which='minor', bottom=False)
Here's another way I found in the matplotlib documentation:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import MultipleLocator
a = np.arange(100)
ml = MultipleLocator(5)
plt.plot(a)
plt.axes().yaxis.set_minor_locator(ml)
plt.show()
This will place minor ticks on only the y-axis, since minor ticks are off by default.
To clarify the procedure of #emad's answer, the steps to show minor ticks at default locations are:
Turn on minor ticks for an axes object, so locations are initialized as Matplotlib sees fit.
Turn off minor ticks that are not desired.
A minimal example:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
plt.plot([1,2])
# Currently, there are no minor ticks,
# so trying to make them visible would have no effect
ax.yaxis.get_ticklocs(minor=True) # []
# Initialize minor ticks
ax.minorticks_on()
# Now minor ticks exist and are turned on for both axes
# Turn off x-axis minor ticks
ax.xaxis.set_tick_params(which='minor', bottom=False)
Alternative Method
Alternatively, we can get minor ticks at default locations using AutoMinorLocator:
import matplotlib.pyplot as plt
import matplotlib.ticker as tck
fig, ax = plt.subplots()
plt.plot([1,2])
ax.yaxis.set_minor_locator(tck.AutoMinorLocator())
Result
Either way, the resulting plot has minor ticks on the y-axis only.
To set minor ticks at custom locations:
ax.set_xticks([0, 10, 20, 30], minor=True)
Also, if you only want minor ticks on the actual y-axis, rather than on both the left and right-hand sides of the graph, you can follow the plt.axes().yaxis.set_minor_locator(ml) with plt.axes().yaxis.set_tick_params(which='minor', right = 'off'), like so:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import MultipleLocator
a = np.arange(100)
ml = MultipleLocator(5)
plt.plot(a)
plt.axes().yaxis.set_minor_locator(ml)
plt.axes().yaxis.set_tick_params(which='minor', right = 'off')
plt.show()
The following snippets should help:
from matplotlib.ticker import MultipleLocator
ax.xaxis.set_minor_locator(MultipleLocator(#))
ax.yaxis.set_minor_locator(MultipleLocator(#))
# refers to the desired interval between minor ticks.

Categories