MaxNLocator的源码:matplotlib.org/api/ticker_…
本来想整理一下Locator的子类,但是因为对MaxNLocator类里面的steps参数不了解,因而在这里写下这边文章,记录在阅读源码过程中遇到的问题:
1、
"""Find nice tick locations with no more than N being within the view limits.
Locations beyond the limits are added to support autoscaling."""
在视野之外的Locations会被加起来来适应autoscaling。
可能是这个意思,就是当设置后这个类的参数之后,可能有一些Locator因为不适应参数的要求,比如设置好了间隔数目,坐标轴的显示范围等参数之后,有一些Locator就会被舍弃。
比如:
from matplotlib.ticker import MaxNLocator
import matplotlib.pyplot as plt
loc=MaxNLocator(5,steps=[3])
fig,ax=plt.subplots(1)
ax.xaxis.set_major_locator(loc)
ax.axis(xmax=10,xmin=0)
plt.show()
这里我设置好了steps参数和x轴的显示范围,那么本来应该是有五个间隔,为了适应我设置的xmax和xmin参数,只显示了四个locator。这个是我的理解。
2、
min_n_ticks参数的优先级比任何一个参数的优先级都高,如果其他参数跟min_n_ticks参数有冲突,这个类会强制隐式改变其他的参数。比如:
from matplotlib.ticker import MaxNLocator
import matplotlib.pyplot as plt
loc=MaxNLocator(5,steps=[3],integer=True,min_n_ticks=5)
fig,ax=plt.subplots(1)
ax.xaxis.set_major_locator(loc)
print(loc._nbins)
plt.show()
5
这个时候的nbins参数会隐式被改变,并且integer参数也无效,从而保证至少有min_n_ticks个ticks出现在坐标轴上。
3、
以后版本的可能不再支持现在的nbins同时作为位置和关键字参数:
if args:
if 'nbins' in kwargs:
cbook.deprecated("3.1",
message='Calling MaxNLocator with positional '
'and keyword parameter *nbins* is '
'considered an error and will fail '
'in future versions of matplotlib.')
其中的cbook.deprecated类是matplotlib用来提示用户的类,提示关键字参数。
4、
如果要用位置参数来实例化这个类,只能有一个位置参数,并且无论如何这个位置参数都会对应nbins,那么当你的编译器出现了这个错误,不妨看看你是否用了过多的位置参数。
if len(args) > 1:
raise ValueError(
"Keywords are required for all arguments except 'nbins'")
5、对steps参数的要求:
def _validate_steps(steps):
if not np.iterable(steps):
raise ValueError('steps argument must be an increasing sequence '
'of numbers between 1 and 10 inclusive')
steps = np.asarray(steps)
if np.any(np.diff(steps) <= 0) or steps[-1] > 10 or steps[0] < 1:
raise ValueError('steps argument must be an increasing sequence '
'of numbers between 1 and 10 inclusive')
if steps[0] != 1:
steps = np.hstack((1, steps))
if steps[-1] != 10:
steps = np.hstack((steps, 10))
return steps
总结几点:
steps必须是一个可迭代对象,具体到这里,就要求是一个数组,并且数组的元素不能小于1或者大于10,还得是一个递增的序列,即前向差分不能小于0。而且在赋值steps参数的时候,不需要刻意把1或者10加进去,最后这个_validate_steps方法都会把1和10加进去。
6、_staircase方法
我没看懂有什么用。
def _staircase(steps):
# Make an extended staircase within which the needed
# step will be found. This is probably much larger
# than necessary.
flights = (0.1 * steps[:-1], steps, 10 * steps[1])
return np.hstack(flights)
在steps的前面和后面加上1和第二个元素的十倍,再往后再看看有什么具体作用。
7、_raw_ticks方法
(1)如果nbins设置是auto且坐标轴还没有创建的话,nbins就默认设置为9,也就是设置auto的话会有9个间隔,如果坐标轴已经存在的话,就把这个已经存在的坐标轴的刻度的数目限制在9之内,也就是说已经存在的坐标轴的刻度数目可以小于9个,但是不能大于9个
if self._nbins == 'auto':
if self.axis is not None:
nbins = np.clip(self.axis.get_tick_space(),
max(1, self._min_n_ticks - 1), 9)
else:
nbins = 9
(2)对上限和下限的微小调节,对一般的画图没有很大影响,写源码的太严谨,一个变量,比如steps,变来变去的看得头都晕了,本来想弄清楚steps参数的作用,最后不了了之。
scale, offset = scale_range(vmin, vmax, nbins)
_vmin = vmin - offset
_vmax = vmax - offset
raw_step = (_vmax - _vmin) / nbins
steps = self._extended_steps * scale
if self._integer:
# For steps > 1, keep only integer values.
igood = (steps < 1) | (np.abs(steps - np.round(steps)) < 0.001)
steps = steps[igood]
istep = np.nonzero(steps >= raw_step)[0][0]
# Classic round_numbers mode may require a larger step.
if mpl.rcParams['axes.autolimit_mode'] == 'round_numbers':
for istep in range(istep, len(steps)):
step = steps[istep]
best_vmin = (_vmin // step) * step
best_vmax = best_vmin + step * nbins
if best_vmax >= _vmax:
break
# This is an upper limit; move to smaller steps if necessary.
for istep in reversed(range(istep + 1)):
step = steps[istep]
if (self._integer and
np.floor(_vmax) - np.ceil(_vmin) >= self._min_n_ticks - 1):
step = max(1, step)
best_vmin = (_vmin // step) * step
# Find tick locations spanning the vmin-vmax range, taking into
# account degradation of precision when there is a large offset.
# The edge ticks beyond vm
# # # # # in and/or vmax are needed for the # "round_numbers" autolimit mode.
edge = _Edge_integer(step, offset)
low = edge.le(_vmin - best_vmin)
high = edge.ge(_vmax - best_vmin)
ticks = np.arange(low, high + 1) * step + best_vmin
# Count only the ticks that will be displayed.
nticks = ((ticks <= _vmax) & (ticks >= _vmin)).sum()
if nticks >= self._min_n_ticks:
break
return ticks + offset
8、tick_values方法
用当前实例的steps和nbins参数来进行生成locators,但是这个时候的上下限可以自己设置。在实例化MaxNLocator对象的时候,会自动调用tick_values方法,而且坐标轴的上下限会自动使用get_view_interval方法获取当前坐标轴的坐标轴上下限。
9、view_limits方法
没弄懂,主要是这个语句:
mpl.rcParams['axes.autolimit_mode'] == 'round_numbers'