3

I want some space before and after the last tick location on an axis. I would just use axis.set_xlim() for example but this interferes with my (custom) locator and reruns the tick generation. I found and overwritten the view_limits() method of the locator-classes but they don't seem to be called automatically and when called manually they don't have any impact on the resulting plot. I searched the docs and the source but haven't come up with a solution. Am I missing something?

For the greater picture I want to have a locator which gives me some space before and after the ticks and chooses tick points which are a multiple of 'base' like the MultipleLocator but scale the base automatically if the number of ticks exceeds a specified value. If there is another way to achieve this without subclassing a locator I am all ears :).

Here is my example code for the subclassed locator with overwritten view_limits-method:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import MaxNLocator

class MyLocator(MaxNLocator):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def view_limits(self, dmin, dmax):
        bins = self.bin_boundaries(dmin, dmax)
        step = bins[1] - bins[0]
        result = np.array([bins[0] - step, bins[-1] + step])
        print(result)
        return result

a = 10.0
b = 99.0

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

loc = MyLocator(9)

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

ax.xaxis.set_major_locator(loc)
loc.autoscale()  # results in [   0.  110.] but doesnt change the plot
plt.show()

2 Answers 2

1

Not sure, if I understood completely what your problem is, but if you only want to add extra space, you can still use MaxNLocator and add that space manually like here:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import MaxNLocator

a = 10.0
b = 99.0

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

loc = MaxNLocator(9)

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

ax.xaxis.set_major_locator(loc)
ticks = ax.get_xticks()
newticks = np.zeros(len(ticks)+2)
newticks[0] = ticks[0]- (ticks[1]-ticks[0])
newticks[-1] = ticks[-1]+ (ticks[1]-ticks[0])
newticks[1:-1] = ticks
ax.set_xticks(newticks)

plt.show()
Sign up to request clarification or add additional context in comments.

1 Comment

thanks for that trick! I can work with that. I would still rather know why the whole view_limits-method doesn't work as expected.
0

One slightly hacky solution to avoid ticks close to the plot's edges is the following:

class PaddedMaxNLocator(mp.ticker.MaxNLocator):
    def __init__(self, *args, protected_width=0.25, **kwargs):
        # `prune` edge ticks that might now become visible
        super().__init__(*args, **kwargs, prune='both')
        # Clamp to some reasonable range
        self.protected_width = min(0.5, protected_width)

    def tick_values(self, vmin, vmax):
        diff = (vmax - vmin) * self.protected_width / 2
        return super().tick_values(vmin + diff, vmax - diff)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.