diff --git a/doc/api/axis_api.rst b/doc/api/axis_api.rst index ad5f75d57c82..3889b86498cb 100644 --- a/doc/api/axis_api.rst +++ b/doc/api/axis_api.rst @@ -103,7 +103,6 @@ Ticks, tick labels and Offset text Axis.get_gridlines Axis.grid - Axis.iter_ticks Axis.set_tick_params Axis.axis_date @@ -365,7 +364,6 @@ YAxis YAxis.get_units YAxis.get_view_interval YAxis.grid - YAxis.iter_ticks YAxis.limit_range_for_scale YAxis.pan YAxis.reset_ticks @@ -432,7 +430,6 @@ XAxis XAxis.get_units XAxis.get_view_interval XAxis.grid - XAxis.iter_ticks XAxis.limit_range_for_scale XAxis.pan XAxis.reset_ticks diff --git a/doc/api/next_api_changes/2018-02-05-AL.rst b/doc/api/next_api_changes/2018-02-05-AL.rst new file mode 100644 index 000000000000..48c7ced597ff --- /dev/null +++ b/doc/api/next_api_changes/2018-02-05-AL.rst @@ -0,0 +1,8 @@ +Changes to the internal tick handling API +````````````````````````````````````````` + +``Axis.iter_ticks`` (which only served as a helper to the private +``Axis._update_ticks``) is deprecated. + +The signature of the (private) ``Axis._update_ticks`` has been changed to not +take the renderer as argument anymore (that argument is unused). diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index da85450ba86e..1a903733de86 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -1016,6 +1016,7 @@ def _set_artist_props(self, a): return a.set_figure(self.figure) + @cbook.deprecated("3.1") def iter_ticks(self): """ Yield ``(Tick, location, label)`` tuples for major and minor ticks. @@ -1035,7 +1036,7 @@ def get_ticklabel_extents(self, renderer): of the axes. """ - ticks_to_draw = self._update_ticks(renderer) + ticks_to_draw = self._update_ticks() ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes(ticks_to_draw, renderer) @@ -1058,20 +1059,38 @@ def get_smart_bounds(self): """get whether the axis has smart bounds""" return self._smart_bounds - def _update_ticks(self, renderer): + def _update_ticks(self): """ - Update ticks (position and labels) using the current data - interval of the axes. Returns a list of ticks that will be - drawn. + Update ticks (position and labels) using the current data interval of + the axes. Return the list of ticks that will be drawn. """ - interval = self.get_view_interval() - tick_tups = list(self.iter_ticks()) # iter_ticks calls the locator - if self._smart_bounds and tick_tups: + major_locs = self.major.locator() + major_ticks = self.get_major_ticks(len(major_locs)) + self.major.formatter.set_locs(major_locs) + major_labels = self.major.formatter.format_ticks(major_locs) + for tick, loc, label in zip(major_ticks, major_locs, major_labels): + tick.update_position(loc) + tick.set_label1(label) + tick.set_label2(label) + minor_locs = self.minor.locator() + minor_ticks = self.get_minor_ticks(len(minor_locs)) + self.minor.formatter.set_locs(minor_locs) + minor_labels = self.minor.formatter.format_ticks(minor_locs) + for tick, loc, label in zip(minor_ticks, minor_locs, minor_labels): + tick.update_position(loc) + tick.set_label1(label) + tick.set_label2(label) + ticks = [*major_ticks, *minor_ticks] + + view_low, view_high = self.get_view_interval() + if view_low > view_high: + view_low, view_high = view_high, view_low + + if self._smart_bounds and ticks: # handle inverted limits - view_low, view_high = sorted(interval) data_low, data_high = sorted(self.get_data_interval()) - locs = np.sort([ti[1] for ti in tick_tups]) + locs = np.sort([tick.get_loc() for tick in ticks]) if data_low <= view_low: # data extends beyond view, take view as limit ilow = view_low @@ -1096,33 +1115,21 @@ def _update_ticks(self, renderer): else: # No ticks (why not?), take last tick ihigh = locs[-1] - tick_tups = [ti for ti in tick_tups if ilow <= ti[1] <= ihigh] + ticks = [tick for tick in ticks if ilow <= tick.get_loc() <= ihigh] - if interval[1] <= interval[0]: - interval = interval[1], interval[0] - inter = self.get_transform().transform(interval) + interval_t = self.get_transform().transform([view_low, view_high]) ticks_to_draw = [] - for tick, loc, label in tick_tups: - # draw each tick if it is in interval. Note the transform - # to pixel space to take care of log transforms etc. - # interval_contains has a floating point tolerance. - if tick is None: - continue - # NB: always update labels and position to avoid issues like #9397 - tick.update_position(loc) - tick.set_label1(label) - tick.set_label2(label) + for tick in ticks: try: - loct = self.get_transform().transform(loc) + loc_t = self.get_transform().transform(tick.get_loc()) except AssertionError: # transforms.transform doesn't allow masked values but # some scales might make them, so we need this try/except. - loct = None - continue - if not mtransforms._interval_contains_close(inter, loct): - continue - ticks_to_draw.append(tick) + pass + else: + if mtransforms._interval_contains_close(interval_t, loc_t): + ticks_to_draw.append(tick) return ticks_to_draw @@ -1141,7 +1148,7 @@ def get_tightbbox(self, renderer): if not self.get_visible(): return - ticks_to_draw = self._update_ticks(renderer) + ticks_to_draw = self._update_ticks() self._update_label_position(renderer) @@ -1182,7 +1189,7 @@ def draw(self, renderer, *args, **kwargs): return renderer.open_group(__name__) - ticks_to_draw = self._update_ticks(renderer) + ticks_to_draw = self._update_ticks() ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes(ticks_to_draw, renderer) @@ -1948,7 +1955,7 @@ def _get_tick_boxes_siblings(self, renderer): grp = self.figure._align_xlabel_grp # if we want to align labels from other axes: for nn, axx in enumerate(grp.get_siblings(self.axes)): - ticks_to_draw = axx.xaxis._update_ticks(renderer) + ticks_to_draw = axx.xaxis._update_ticks() tlb, tlb2 = axx.xaxis._get_tick_bboxes(ticks_to_draw, renderer) bboxes.extend(tlb) bboxes2.extend(tlb2) @@ -2262,7 +2269,7 @@ def _get_tick_boxes_siblings(self, renderer): grp = self.figure._align_ylabel_grp # if we want to align labels from other axes: for axx in grp.get_siblings(self.axes): - ticks_to_draw = axx.yaxis._update_ticks(renderer) + ticks_to_draw = axx.yaxis._update_ticks() tlb, tlb2 = axx.yaxis._get_tick_bboxes(ticks_to_draw, renderer) bboxes.extend(tlb) bboxes2.extend(tlb2) diff --git a/lib/matplotlib/tests/baseline_images/test_axes/minorticks_on_rcParams_both.png b/lib/matplotlib/tests/baseline_images/test_axes/minorticks_on_rcParams_both.png deleted file mode 100644 index f8b929e34907..000000000000 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/minorticks_on_rcParams_both.png and /dev/null differ diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 09cd9ecbabfc..39e22f756eb4 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -266,15 +266,15 @@ def test_inverted_cla(): plt.close(fig) -@image_comparison(baseline_images=["minorticks_on_rcParams_both"], - extensions=['png']) -def test_minorticks_on_rcParams_both(): - fig = plt.figure() - matplotlib.rcParams['xtick.minor.visible'] = True - matplotlib.rcParams['ytick.minor.visible'] = True - - plt.plot([0, 1], [0, 1]) - plt.axis([0, 1, 0, 1]) +@check_figures_equal(extensions=["png"]) +def test_minorticks_on_rcParams_both(fig_test, fig_ref): + with matplotlib.rc_context({"xtick.minor.visible": True, + "ytick.minor.visible": True}): + ax_test = fig_test.subplots() + ax_test.plot([0, 1], [0, 1]) + ax_ref = fig_ref.subplots() + ax_ref.plot([0, 1], [0, 1]) + ax_ref.minorticks_on() @image_comparison(baseline_images=["autoscale_tiny_range"], remove_text=True) diff --git a/lib/matplotlib/tests/test_ticker.py b/lib/matplotlib/tests/test_ticker.py index 7d4ed3b1f616..b35a7fd45df8 100644 --- a/lib/matplotlib/tests/test_ticker.py +++ b/lib/matplotlib/tests/test_ticker.py @@ -346,8 +346,7 @@ def test_offset_value(self, left, right, offset): UserWarning) ax.set_xlim(left, right) assert len(w) == (1 if left == right else 0) - # Update ticks. - next(ax.get_xaxis().iter_ticks()) + ax.get_xaxis()._update_ticks() assert formatter.offset == offset with warnings.catch_warnings(record=True) as w: @@ -355,8 +354,7 @@ def test_offset_value(self, left, right, offset): UserWarning) ax.set_xlim(right, left) assert len(w) == (1 if left == right else 0) - # Update ticks. - next(ax.get_xaxis().iter_ticks()) + ax.get_xaxis()._update_ticks() assert formatter.offset == offset @pytest.mark.parametrize('use_offset', use_offset_data) diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index 8550a4407062..6f33d83c1849 100644 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -223,22 +223,11 @@ def draw(self, renderer): self.label._transform = self.axes.transData renderer.open_group('axis3d') - # code from XAxis - majorTicks = self.get_major_ticks() - majorLocs = self.major.locator() + ticks = self._update_ticks() info = self._axinfo index = info['i'] - # filter locations here so that no extra grid lines are drawn - locmin, locmax = self.get_view_interval() - if locmin > locmax: - locmin, locmax = locmax, locmin - - # Rudimentary clipping - majorLocs = [loc for loc in majorLocs if locmin <= loc <= locmax] - majorLabels = self.major.formatter.format_ticks(majorLocs) - mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) # Determine grid lines @@ -259,9 +248,9 @@ def draw(self, renderer): # Grid points where the planes meet xyz0 = [] - for val in majorLocs: + for tick in ticks: coord = minmax.copy() - coord[index] = val + coord[index] = tick.get_loc() xyz0.append(coord) # Draw labels @@ -373,14 +362,14 @@ def draw(self, renderer): xyz1 = copy.deepcopy(xyz0) newindex = (index + 1) % 3 newval = get_flip_min_max(xyz1[0], newindex, mins, maxs) - for i in range(len(majorLocs)): + for i in range(len(ticks)): xyz1[i][newindex] = newval # Grid points at end of the other plane xyz2 = copy.deepcopy(xyz0) newindex = (index + 2) % 3 newval = get_flip_min_max(xyz2[0], newindex, mins, maxs) - for i in range(len(majorLocs)): + for i in range(len(ticks)): xyz2[i][newindex] = newval lines = list(zip(xyz1, xyz0, xyz2)) @@ -401,13 +390,11 @@ def draw(self, renderer): else: ticksign = -1 - for tick, loc, label in zip(majorTicks, majorLocs, majorLabels): - if tick is None: - continue + for tick in ticks: # Get tick line positions pos = copy.copy(edgep1) - pos[index] = loc + pos[index] = tick.get_loc() pos[tickdir] = ( edgep1[tickdir] + info['tick']['outward_factor'] * ticksign * tickdelta) @@ -434,8 +421,6 @@ def draw(self, renderer): tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly)) tick.tick1line.set_linewidth(info['tick']['linewidth']) tick.tick1line.set_color(info['tick']['color']) - tick.set_label1(label) - tick.set_label2(label) tick.draw(renderer) renderer.close_group('axis3d')