Setting multiple sets of minor ticks with Matplotlib

Viewed 1091

I am trying to customize my x-axis with minor ticks but I want to bolden or lengthen the middle minor tick. So basically I want a major, middle, and minor tick for my subplot. I tried using tick_params but that overwrites the previous modifications to the ticks. Is there another way to achieve this?

The end result should have 4 minor ticks and 2 semi-minor ticks between the labeled numbers.

Bonus points if there is a way to label the semi-minor ticks.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,
                               AutoMinorLocator)

t = np.arange(0.0, 100.0, 0.1)
s = np.sin(0.1 * np.pi * t) * np.exp(-t * 0.01)

fig, ax = plt.subplots()
ax.plot(t, s)

#Try to set 4 minor ticks
ax.xaxis.set_minor_locator(AutoMinorLocator(4))
ax.tick_params(which='minor', length=2, color='k')

#Set 2 minor ticks that are larger
ax.xaxis.set_minor_locator(AutoMinorLocator(2))
ax.tick_params(which='minor', length=6, color='k')

#Make major ticks even larger
ax.tick_params(which='major', length=12, color='k')

plt.show()

enter image description here

1 Answers

Two ways. The first one is messy and it's probably better to avoid it, but it doesn't hurt to include it here. The second one, as suggested by ImportanceOfBeingErnest and is based on How to add third level of ticks in python matplotlib

fig, ax = plt.subplots()
ax.plot(t, s)

ax.xaxis.set_minor_locator(AutoMinorLocator(9))
ax.tick_params(which='major', length=12, color='k')
minor_labels = list()
i = 0
l = -2
sum_l = 1.125
for line in ax.xaxis.get_ticklines(minor=True):

    if i == 0:
        line.set_markersize(4)
        minor_labels.append('')
        i += 1
        l += sum_l
    elif i == 2:
        line.set_markersize(4)
        minor_labels.append('')
        i += 1
        l += sum_l
    elif i == 4 or i == 6 or i == 10 or i == 12 or i == 16:
        line.set_markersize(4)
        minor_labels.append('')
        i += 1
        l += sum_l
    elif i == 18:
        line.set_markersize(4)
        minor_labels.append('')
        i -= 15
        l += sum_l
    elif i == 8 or i == 14:
        line.set_markersize(8)
        minor_labels.append(l)
        i += 1
        l += sum_l
    else:
        i += 1
        l += sum_l
print(minor_labels)
ax.set_xticklabels(minor_labels,minor=True)
plt.setp(ax.xaxis.get_minorticklabels(), rotation=45)
plt.setp(ax.xaxis.get_ticklabels(), rotation=45)
plt.show()

plot 1

ImportanceOfBeingErnest's solution seems to follow this logic — maybe he had something else in mind —It looks nicer, but I haven't been able to reproduce the minor / semi-minor tick combination. Perhaps with some more time you will be able to do what you intend by tweaking it.

t = np.arange(0.0, 100.0, 0.1)
s = np.sin(0.1 * np.pi * t) * np.exp(-t * 0.01)

fig, ax = plt.subplots()
plt.plot(t, s)
ax2 = ax.twiny()
ax2.plot(t, s)
ax2.xaxis.set_ticks_position('bottom')

ax.xaxis.set_minor_locator(ticker.FixedLocator(np.arange(5, 100.01, 5)))
ax.tick_params(which='minor', length=8, color='k')

ax2.xaxis.set_major_locator(ticker.FixedLocator([]))
ax2.xaxis.set_minor_locator(ticker.FixedLocator(np.arange(1.25, 100.01,1.25)))
ax2.tick_params(which='minor', length=4, color='k')

ax.tick_params(which='major', length=12, color='k')
ax.set_xticklabels(np.arange(5, 100.01, 5),minor=True)
plt.setp(ax.xaxis.get_minorticklabels(), rotation=45)
plt.setp(ax.xaxis.get_ticklabels(), rotation=45)
plt.show()

plot 2

Related