From 99659543d7d9fae5bd7bec3351ef8e0534ab05b0 Mon Sep 17 00:00:00 2001 From: Scott Shambaugh Date: Sun, 30 Apr 2023 20:02:53 -0600 Subject: [PATCH 1/6] Break axis3d drawing into subfunctions --- lib/mpl_toolkits/mplot3d/axis3d.py | 189 +++++++++++++++++------------ 1 file changed, 109 insertions(+), 80 deletions(-) diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index 30f56c70f9f5..d0a711c69d03 100644 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -322,69 +322,63 @@ def draw_pane(self, renderer): self.pane.draw(renderer) renderer.close_group('pane3d') - @artist.allow_rasterization - def draw(self, renderer): - self.label._transform = self.axes.transData - self.offsetText._transform = self.axes.transData - renderer.open_group("axis3d", gid=self.get_gid()) - ticks = self._update_ticks() - - # Get general axis information: + def _axmask(self): info = self._axinfo index = info["i"] - juggled = info["juggled"] + axmask = [True, True, True] + axmask[index] = False + return axmask + + def _draw_ticks(self, renderer, edgep1, deltas_per_point): mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) + ticks = self._update_ticks() + info = self._axinfo + index = info["i"] - minmax = np.where(highs, maxs, mins) - maxmin = np.where(~highs, maxs, mins) + # Draw ticks: + tickdir = self._get_tickdir() + tickdelta = deltas[tickdir] if highs[tickdir] else -deltas[tickdir] - # Create edge points for the black bolded axis line: - edgep1, edgep2 = self._get_axis_line_edge_points(minmax, maxmin) + tick_info = info['tick'] + tick_out = tick_info['outward_factor'] * tickdelta + tick_in = tick_info['inward_factor'] * tickdelta + tick_lw = tick_info['linewidth'] + edgep1_tickdir = edgep1[tickdir] + out_tickdir = edgep1_tickdir + tick_out + in_tickdir = edgep1_tickdir - tick_in - # Project the edge points along the current position and - # create the line: - pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M) - pep = np.asarray(pep) - self.line.set_data(pep[0], pep[1]) - self.line.draw(renderer) + default_label_offset = 8. # A rough estimate + points = deltas_per_point * deltas + for tick in ticks: + # Get tick line positions + pos = edgep1.copy() + pos[index] = tick.get_loc() + pos[tickdir] = out_tickdir + x1, y1, z1 = proj3d.proj_transform(*pos, self.axes.M) + pos[tickdir] = in_tickdir + x2, y2, z2 = proj3d.proj_transform(*pos, self.axes.M) - # Draw labels - # The transAxes transform is used because the Text object - # rotates the text relative to the display coordinate system. - # Therefore, if we want the labels to remain parallel to the - # axis regardless of the aspect ratio, we need to convert the - # edge points of the plane to display coordinates and calculate - # an angle from that. - # TODO: Maybe Text objects should handle this themselves? - dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) - - self.axes.transAxes.transform([pep[0:2, 0]]))[0] + # Get position of label + labeldeltas = (tick.get_pad() + default_label_offset) * points - lxyz = 0.5 * (edgep1 + edgep2) + pos[tickdir] = edgep1_tickdir + pos = _move_from_center(pos, centers, labeldeltas, self._axmask()) + lx, ly, lz = proj3d.proj_transform(*pos, self.axes.M) - # A rough estimate; points are ambiguous since 3D plots rotate - reltoinches = self.figure.dpi_scale_trans.inverted() - ax_inches = reltoinches.transform(self.axes.bbox.size) - ax_points_estimate = sum(72. * ax_inches) - deltas_per_point = 48 / ax_points_estimate - default_offset = 21. - labeldeltas = ( - (self.labelpad + default_offset) * deltas_per_point * deltas) - axmask = [True, True, True] - axmask[index] = False - lxyz = _move_from_center(lxyz, centers, labeldeltas, axmask) - tlx, tly, tlz = proj3d.proj_transform(*lxyz, self.axes.M) - self.label.set_position((tlx, tly)) - if self.get_rotate_label(self.label.get_text()): - angle = art3d._norm_text_angle(np.rad2deg(np.arctan2(dy, dx))) - self.label.set_rotation(angle) - self.label.set_va(info['label']['va']) - self.label.set_ha(info['label']['ha']) - self.label.set_rotation_mode(info['label']['rotation_mode']) - self.label.draw(renderer) + _tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly)) + tick.tick1line.set_linewidth(tick_lw[tick._major]) + tick.draw(renderer) - # Draw Offset text + + def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, pep, dx, dy): + mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) + + # Get general axis information: + info = self._axinfo + index = info["i"] + juggled = info["juggled"] # Which of the two edge points do we want to # use for locating the offset text? @@ -395,7 +389,7 @@ def draw(self, renderer): outeredgep = edgep2 outerindex = 1 - pos = _move_from_center(outeredgep, centers, labeldeltas, axmask) + pos = _move_from_center(outeredgep, centers, labeldeltas, self._axmask()) olx, oly, olz = proj3d.proj_transform(*pos, self.axes.M) self.offsetText.set_text(self.major.formatter.get_offset()) self.offsetText.set_position((olx, oly)) @@ -448,39 +442,74 @@ def draw(self, renderer): self.offsetText.set_ha(align) self.offsetText.draw(renderer) - # Draw ticks: - tickdir = self._get_tickdir() - tickdelta = deltas[tickdir] if highs[tickdir] else -deltas[tickdir] - tick_info = info['tick'] - tick_out = tick_info['outward_factor'] * tickdelta - tick_in = tick_info['inward_factor'] * tickdelta - tick_lw = tick_info['linewidth'] - edgep1_tickdir = edgep1[tickdir] - out_tickdir = edgep1_tickdir + tick_out - in_tickdir = edgep1_tickdir - tick_in + def _draw_labels(self, renderer, edgep1, edgep2, labeldeltas, dx, dy): + info = self._axinfo + mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) - default_label_offset = 8. # A rough estimate - points = deltas_per_point * deltas - for tick in ticks: - # Get tick line positions - pos = edgep1.copy() - pos[index] = tick.get_loc() - pos[tickdir] = out_tickdir - x1, y1, z1 = proj3d.proj_transform(*pos, self.axes.M) - pos[tickdir] = in_tickdir - x2, y2, z2 = proj3d.proj_transform(*pos, self.axes.M) + # Draw labels + lxyz = 0.5 * (edgep1 + edgep2) + lxyz = _move_from_center(lxyz, centers, labeldeltas, self._axmask()) + tlx, tly, tlz = proj3d.proj_transform(*lxyz, self.axes.M) + self.label.set_position((tlx, tly)) + if self.get_rotate_label(self.label.get_text()): + angle = art3d._norm_text_angle(np.rad2deg(np.arctan2(dy, dx))) + self.label.set_rotation(angle) + self.label.set_va(info['label']['va']) + self.label.set_ha(info['label']['ha']) + self.label.set_rotation_mode(info['label']['rotation_mode']) + self.label.draw(renderer) - # Get position of label - labeldeltas = (tick.get_pad() + default_label_offset) * points - pos[tickdir] = edgep1_tickdir - pos = _move_from_center(pos, centers, labeldeltas, axmask) - lx, ly, lz = proj3d.proj_transform(*pos, self.axes.M) + @artist.allow_rasterization + def draw(self, renderer): + self.label._transform = self.axes.transData + self.offsetText._transform = self.axes.transData + renderer.open_group("axis3d", gid=self.get_gid()) - _tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly)) - tick.tick1line.set_linewidth(tick_lw[tick._major]) - tick.draw(renderer) + # Get general axis information: + mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) + + minmax = np.where(highs, maxs, mins) + maxmin = np.where(~highs, maxs, mins) + + # Create edge points for the black bolded axis line: + edgep1, edgep2 = self._get_axis_line_edge_points(minmax, maxmin) + + # Draw the lines + # Project the edge points along the current position + pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M) + pep = np.asarray(pep) + self.line.set_data(pep[0], pep[1]) + self.line.draw(renderer) + + # Calculate offset distances + # A rough estimate; points are ambiguous since 3D plots rotate + reltoinches = self.figure.dpi_scale_trans.inverted() + ax_inches = reltoinches.transform(self.axes.bbox.size) + ax_points_estimate = sum(72. * ax_inches) + deltas_per_point = 48 / ax_points_estimate + default_offset = 21. + labeldeltas = ( + (self.labelpad + default_offset) * deltas_per_point * deltas) + # The transAxes transform is used because the Text object + # rotates the text relative to the display coordinate system. + # Therefore, if we want the labels to remain parallel to the + # axis regardless of the aspect ratio, we need to convert the + # edge points of the plane to display coordinates and calculate + # an angle from that. + # TODO: Maybe Text objects should handle this themselves? + dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) - + self.axes.transAxes.transform([pep[0:2, 0]]))[0] + + # Draw labels + self._draw_labels(renderer, edgep1, edgep2, labeldeltas, dx, dy) + + # Draw Offset text + self._draw_offset_text(renderer, edgep1, edgep2, labeldeltas, pep, dx, dy) + + # Draw ticks + self._draw_ticks(renderer, edgep1, deltas_per_point) renderer.close_group('axis3d') self.stale = False From cc70dcfbf045981ea7529e85c2636819164aee04 Mon Sep 17 00:00:00 2001 From: Scott Shambaugh Date: Sun, 7 May 2023 10:55:24 -0600 Subject: [PATCH 2/6] Implement 3d axis positions --- lib/mpl_toolkits/mplot3d/axis3d.py | 102 ++++++++++++++++++----------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index d0a711c69d03..53dd252b145f 100644 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -76,6 +76,8 @@ def __init__(self, *args, **kwargs): name = self.axis_name + self.position = 'auto' + # This is a temporary member variable. # Do not depend on this existing in future releases! self._axinfo = self._AXINFO[name].copy() @@ -225,8 +227,7 @@ def _get_coord_info(self, renderer): # Get the mean value for each bound: centers = 0.5 * (maxs + mins) - # Add a small offset between min/max point and the edge of the - # plot: + # Add a small offset between min/max point and the edge of the plot: deltas = (maxs - mins) / 12 mins -= 0.25 * deltas maxs += 0.25 * deltas @@ -256,19 +257,26 @@ def _get_coord_info(self, renderer): return mins, maxs, centers, deltas, bounds_proj, highs - def _get_axis_line_edge_points(self, minmax, maxmin): + def _get_axis_line_edge_points(self, minmax, maxmin, position=None): """Get the edge points for the black bolded axis line.""" # When changing vertical axis some of the axes has to be # moved to the other plane so it looks the same as if the z-axis # was the vertical axis. - mb = [minmax, maxmin] + mb = [minmax, maxmin] # line from origin to near invisible corner mb_rev = mb[::-1] mm = [[mb, mb_rev, mb_rev], [mb_rev, mb_rev, mb], [mb, mb, mb]] mm = mm[self.axes._vertical_axis][self._axinfo["i"]] juggled = self._axinfo["juggled"] - edge_point_0 = mm[0].copy() - edge_point_0[juggled[0]] = mm[1][juggled[0]] + edge_point_0 = mm[0].copy() # origin point + + if ( (position == 'lower' + and mm[1][juggled[-1]] < mm[0][juggled[-1]]) + or (position == 'upper' + and mm[1][juggled[-1]] > mm[0][juggled[-1]])): + edge_point_0[juggled[-1]] = mm[1][juggled[-1]] + else: + edge_point_0[juggled[0]] = mm[1][juggled[0]] edge_point_1 = edge_point_0.copy() edge_point_1[juggled[1]] = mm[1][juggled[1]] @@ -372,7 +380,8 @@ def _draw_ticks(self, renderer, edgep1, deltas_per_point): tick.draw(renderer) - def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, pep, dx, dy): + def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, pep, + dx, dy): mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) # Get general axis information: @@ -389,7 +398,8 @@ def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, pep, dx, dy): outeredgep = edgep2 outerindex = 1 - pos = _move_from_center(outeredgep, centers, labeldeltas, self._axmask()) + pos = _move_from_center(outeredgep, centers, labeldeltas, + self._axmask()) olx, oly, olz = proj3d.proj_transform(*pos, self.axes.M) self.offsetText.set_text(self.major.formatter.get_offset()) self.offsetText.set_position((olx, oly)) @@ -470,19 +480,6 @@ def draw(self, renderer): # Get general axis information: mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) - minmax = np.where(highs, maxs, mins) - maxmin = np.where(~highs, maxs, mins) - - # Create edge points for the black bolded axis line: - edgep1, edgep2 = self._get_axis_line_edge_points(minmax, maxmin) - - # Draw the lines - # Project the edge points along the current position - pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M) - pep = np.asarray(pep) - self.line.set_data(pep[0], pep[1]) - self.line.draw(renderer) - # Calculate offset distances # A rough estimate; points are ambiguous since 3D plots rotate reltoinches = self.figure.dpi_scale_trans.inverted() @@ -492,24 +489,53 @@ def draw(self, renderer): default_offset = 21. labeldeltas = ( (self.labelpad + default_offset) * deltas_per_point * deltas) - # The transAxes transform is used because the Text object - # rotates the text relative to the display coordinate system. - # Therefore, if we want the labels to remain parallel to the - # axis regardless of the aspect ratio, we need to convert the - # edge points of the plane to display coordinates and calculate - # an angle from that. - # TODO: Maybe Text objects should handle this themselves? - dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) - - self.axes.transAxes.transform([pep[0:2, 0]]))[0] - - # Draw labels - self._draw_labels(renderer, edgep1, edgep2, labeldeltas, dx, dy) - # Draw Offset text - self._draw_offset_text(renderer, edgep1, edgep2, labeldeltas, pep, dx, dy) - - # Draw ticks - self._draw_ticks(renderer, edgep1, deltas_per_point) + # Determine edge points for the axis lines + edgep1s = [] + edgep2s = [] + minmax = np.where(highs, maxs, mins) # "origin" point + maxmin = np.where(~highs, maxs, mins) # "opposite" corner near camera + if self.position == 'auto': + edgep1, edgep2 = self._get_axis_line_edge_points(minmax, maxmin) + edgep1s = [edgep1] + edgep2s = [edgep2] + else: + edgep1_l, edgep2_l = self._get_axis_line_edge_points(minmax, maxmin, position='lower') + edgep1_u, edgep2_u = self._get_axis_line_edge_points(minmax, maxmin, position='upper') + if self.position in ('lower', 'both'): + edgep1s.append(edgep1_l) + edgep2s.append(edgep2_l) + if self.position in ('upper', 'both'): + edgep1s.append(edgep1_u) + edgep2s.append(edgep2_u) + + for edgep1, edgep2 in zip(edgep1s, edgep2s): + # Draw the lines + # Project the edge points along the current position + pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M) + pep = np.asarray(pep) + self.line.set_data(pep[0], pep[1]) + self.line.draw(renderer) + + # The transAxes transform is used because the Text object + # rotates the text relative to the display coordinate system. + # Therefore, if we want the labels to remain parallel to the + # axis regardless of the aspect ratio, we need to convert the + # edge points of the plane to display coordinates and calculate + # an angle from that. + # TODO: Maybe Text objects should handle this themselves? + dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) - + self.axes.transAxes.transform([pep[0:2, 0]]))[0] + + # Draw labels + self._draw_labels(renderer, edgep1, edgep2, labeldeltas, dx, dy) + + # Draw Offset text + self._draw_offset_text(renderer, edgep1, edgep2, labeldeltas, pep, + dx, dy) + + # Draw ticks + self._draw_ticks(renderer, edgep1, deltas_per_point) renderer.close_group('axis3d') self.stale = False From aab4211fa1caf3f8be02cb5177fcb92cf32f79bf Mon Sep 17 00:00:00 2001 From: Scott Shambaugh Date: Sun, 7 May 2023 11:37:13 -0600 Subject: [PATCH 3/6] Separate out 3D axis label and ticks positions --- lib/mpl_toolkits/mplot3d/axis3d.py | 133 +++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 35 deletions(-) diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index 53dd252b145f..1d739ef78e3f 100644 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -76,7 +76,8 @@ def __init__(self, *args, **kwargs): name = self.axis_name - self.position = 'auto' + self._label_position = 'default' + self._tick_position = 'default' # This is a temporary member variable. # Do not depend on this existing in future releases! @@ -185,6 +186,54 @@ def get_minor_ticks(self, numticks=None): obj.set_transform(self.axes.transData) return ticks + def set_ticks_position(self, position): + """ + Set the ticks position. + + Parameters + ---------- + position : {'lower', 'upper', 'both', 'default', 'none'} + The position of the bolded axis lines, ticks, and tick labels. + """ + _api.check_in_list(['lower', 'upper', 'both', 'default', 'none'], + position=position) + self._tick_position = position + + def get_ticks_position(self): + """ + Get the ticks position. + + Returns + ------- + position : {'lower', 'upper', 'both', 'default', 'none'} + The position of the bolded axis lines, ticks, and tick labels. + """ + return self._tick_position + + def set_label_position(self, position): + """ + Set the label position. + + Parameters + ---------- + position : {'lower', 'upper', 'both', 'default', 'none'} + The position of the axis label. + """ + _api.check_in_list(['lower', 'upper', 'both', 'default', 'none'], + position=position) + self._label_position = position + + def get_label_position(self): + """ + Get the label position. + + Returns + ------- + position : {'lower', 'upper', 'both', 'default', 'none'} + The position of the axis label. + """ + return self._label_position + def set_pane_color(self, color, alpha=None): """ Set pane color. @@ -262,7 +311,7 @@ def _get_axis_line_edge_points(self, minmax, maxmin, position=None): # When changing vertical axis some of the axes has to be # moved to the other plane so it looks the same as if the z-axis # was the vertical axis. - mb = [minmax, maxmin] # line from origin to near invisible corner + mb = [minmax, maxmin] # line from origin to nearest corner to camera mb_rev = mb[::-1] mm = [[mb, mb_rev, mb_rev], [mb_rev, mb_rev, mb], [mb, mb, mb]] mm = mm[self.axes._vertical_axis][self._axinfo["i"]] @@ -283,6 +332,25 @@ def _get_axis_line_edge_points(self, minmax, maxmin, position=None): return edge_point_0, edge_point_1 + def _get_all_axis_line_edge_points(self, minmax, maxmin, position=None): + # Determine edge points for the axis lines + edgep1s = [] + edgep2s = [] + if position in (None, 'default'): + edgep1, edgep2 = self._get_axis_line_edge_points(minmax, maxmin) + edgep1s = [edgep1] + edgep2s = [edgep2] + else: + edgep1_l, edgep2_l = self._get_axis_line_edge_points(minmax, maxmin, position='lower') + edgep1_u, edgep2_u = self._get_axis_line_edge_points(minmax, maxmin, position='upper') + if position in ('lower', 'both'): + edgep1s.append(edgep1_l) + edgep2s.append(edgep2_l) + if position in ('upper', 'both'): + edgep1s.append(edgep1_u) + edgep2s.append(edgep2_u) + return edgep1s, edgep2s + def _get_tickdir(self): """ Get the direction of the tick. @@ -339,8 +407,8 @@ def _axmask(self): return axmask - def _draw_ticks(self, renderer, edgep1, deltas_per_point): - mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) + def _draw_ticks(self, renderer, edgep1, centers, deltas, highs, + deltas_per_point): ticks = self._update_ticks() info = self._axinfo index = info["i"] @@ -380,10 +448,8 @@ def _draw_ticks(self, renderer, edgep1, deltas_per_point): tick.draw(renderer) - def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, pep, - dx, dy): - mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) - + def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, centers, + highs, pep, dx, dy): # Get general axis information: info = self._axinfo index = info["i"] @@ -453,9 +519,9 @@ def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, pep, self.offsetText.draw(renderer) - def _draw_labels(self, renderer, edgep1, edgep2, labeldeltas, dx, dy): + def _draw_labels(self, renderer, edgep1, edgep2, labeldeltas, centers, + dx, dy): info = self._axinfo - mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) # Draw labels lxyz = 0.5 * (edgep1 + edgep2) @@ -491,31 +557,14 @@ def draw(self, renderer): (self.labelpad + default_offset) * deltas_per_point * deltas) # Determine edge points for the axis lines - edgep1s = [] - edgep2s = [] minmax = np.where(highs, maxs, mins) # "origin" point maxmin = np.where(~highs, maxs, mins) # "opposite" corner near camera - if self.position == 'auto': - edgep1, edgep2 = self._get_axis_line_edge_points(minmax, maxmin) - edgep1s = [edgep1] - edgep2s = [edgep2] - else: - edgep1_l, edgep2_l = self._get_axis_line_edge_points(minmax, maxmin, position='lower') - edgep1_u, edgep2_u = self._get_axis_line_edge_points(minmax, maxmin, position='upper') - if self.position in ('lower', 'both'): - edgep1s.append(edgep1_l) - edgep2s.append(edgep2_l) - if self.position in ('upper', 'both'): - edgep1s.append(edgep1_u) - edgep2s.append(edgep2_u) - for edgep1, edgep2 in zip(edgep1s, edgep2s): - # Draw the lines + for edgep1, edgep2 in zip(*self._get_all_axis_line_edge_points( + minmax, maxmin, self._tick_position)): # Project the edge points along the current position pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M) pep = np.asarray(pep) - self.line.set_data(pep[0], pep[1]) - self.line.draw(renderer) # The transAxes transform is used because the Text object # rotates the text relative to the display coordinate system. @@ -527,15 +576,29 @@ def draw(self, renderer): dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) - self.axes.transAxes.transform([pep[0:2, 0]]))[0] - # Draw labels - self._draw_labels(renderer, edgep1, edgep2, labeldeltas, dx, dy) + # Draw the lines + self.line.set_data(pep[0], pep[1]) + self.line.draw(renderer) + + # Draw ticks + self._draw_ticks(renderer, edgep1, centers, deltas, highs, + deltas_per_point) # Draw Offset text - self._draw_offset_text(renderer, edgep1, edgep2, labeldeltas, pep, - dx, dy) + self._draw_offset_text(renderer, edgep1, edgep2, labeldeltas, + centers, highs, pep, dx, dy) - # Draw ticks - self._draw_ticks(renderer, edgep1, deltas_per_point) + for edgep1, edgep2 in zip(*self._get_all_axis_line_edge_points( + minmax, maxmin, self._label_position)): + # See comments above + pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M) + pep = np.asarray(pep) + dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) - + self.axes.transAxes.transform([pep[0:2, 0]]))[0] + + # Draw labels + self._draw_labels(renderer, edgep1, edgep2, labeldeltas, centers, + dx, dy) renderer.close_group('axis3d') self.stale = False From 6af369af43e6a707b54286a78b692168654ccfa0 Mon Sep 17 00:00:00 2001 From: Scott Shambaugh Date: Sun, 7 May 2023 11:59:10 -0600 Subject: [PATCH 4/6] Whats new for 3d axis positions --- doc/users/next_whats_new/3d_axis_positions.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 doc/users/next_whats_new/3d_axis_positions.rst diff --git a/doc/users/next_whats_new/3d_axis_positions.rst b/doc/users/next_whats_new/3d_axis_positions.rst new file mode 100644 index 000000000000..370860cd1349 --- /dev/null +++ b/doc/users/next_whats_new/3d_axis_positions.rst @@ -0,0 +1,17 @@ +Specify ticks and axis label positions for 3D plots +--------------------------------------------------- + +You can now specify the positions of ticks and axis labels for 3D plots. + +.. plot:: + :include-source: + + import matplotlib.pyplot as plt + + positions = ['default', 'upper', 'lower', 'both', 'none'] + fig, axs = plt.subplots(1, 5, subplot_kw={'projection': '3d'}) + for ax, pos in zip(axs, positions): + for axis in ax.xaxis, ax.yaxis, ax.zaxis: + axis._label_position = pos + axis._tick_position = pos + ax.set(xlabel='x', ylabel='y', zlabel='z', title=pos) From b62eb9bc135c807f5f4b6dcc5e4c5810558a3134 Mon Sep 17 00:00:00 2001 From: Scott Shambaugh Date: Sun, 7 May 2023 12:06:33 -0600 Subject: [PATCH 5/6] Cleanup Fix tick directions Make tickdirs work all the time More tickdir tweaks Code review comments Apply suggestions from code review Co-authored-by: Elliott Sales de Andrade Code review suggestions linting --- lib/mpl_toolkits/mplot3d/axis3d.py | 111 ++++++++++-------- lib/mpl_toolkits/mplot3d/tests/test_axes3d.py | 2 +- 2 files changed, 66 insertions(+), 47 deletions(-) diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index 1d739ef78e3f..ace7f0a81ebc 100644 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -192,7 +192,7 @@ def set_ticks_position(self, position): Parameters ---------- - position : {'lower', 'upper', 'both', 'default', 'none'} + str : {'lower', 'upper', 'both', 'default', 'none'} The position of the bolded axis lines, ticks, and tick labels. """ _api.check_in_list(['lower', 'upper', 'both', 'default', 'none'], @@ -205,7 +205,7 @@ def get_ticks_position(self): Returns ------- - position : {'lower', 'upper', 'both', 'default', 'none'} + str : {'lower', 'upper', 'both', 'default', 'none'} The position of the bolded axis lines, ticks, and tick labels. """ return self._tick_position @@ -216,7 +216,7 @@ def set_label_position(self, position): Parameters ---------- - position : {'lower', 'upper', 'both', 'default', 'none'} + str : {'lower', 'upper', 'both', 'default', 'none'} The position of the axis label. """ _api.check_in_list(['lower', 'upper', 'both', 'default', 'none'], @@ -229,7 +229,7 @@ def get_label_position(self): Returns ------- - position : {'lower', 'upper', 'both', 'default', 'none'} + str : {'lower', 'upper', 'both', 'default', 'none'} The position of the axis label. """ return self._label_position @@ -319,10 +319,8 @@ def _get_axis_line_edge_points(self, minmax, maxmin, position=None): juggled = self._axinfo["juggled"] edge_point_0 = mm[0].copy() # origin point - if ( (position == 'lower' - and mm[1][juggled[-1]] < mm[0][juggled[-1]]) - or (position == 'upper' - and mm[1][juggled[-1]] > mm[0][juggled[-1]])): + if ((position == 'lower' and mm[1][juggled[-1]] < mm[0][juggled[-1]]) or + (position == 'upper' and mm[1][juggled[-1]] > mm[0][juggled[-1]])): edge_point_0[juggled[-1]] = mm[1][juggled[-1]] else: edge_point_0[juggled[0]] = mm[1][juggled[0]] @@ -332,42 +330,72 @@ def _get_axis_line_edge_points(self, minmax, maxmin, position=None): return edge_point_0, edge_point_1 - def _get_all_axis_line_edge_points(self, minmax, maxmin, position=None): + def _get_all_axis_line_edge_points(self, minmax, maxmin, axis_position=None): # Determine edge points for the axis lines edgep1s = [] edgep2s = [] - if position in (None, 'default'): + position = [] + if axis_position in (None, 'default'): edgep1, edgep2 = self._get_axis_line_edge_points(minmax, maxmin) edgep1s = [edgep1] edgep2s = [edgep2] + position = ['default'] else: - edgep1_l, edgep2_l = self._get_axis_line_edge_points(minmax, maxmin, position='lower') - edgep1_u, edgep2_u = self._get_axis_line_edge_points(minmax, maxmin, position='upper') + edgep1_l, edgep2_l = self._get_axis_line_edge_points(minmax, maxmin, + position='lower') + edgep1_u, edgep2_u = self._get_axis_line_edge_points(minmax, maxmin, + position='upper') if position in ('lower', 'both'): edgep1s.append(edgep1_l) edgep2s.append(edgep2_l) - if position in ('upper', 'both'): + position.append('lower') + if axis_position in ('upper', 'both'): edgep1s.append(edgep1_u) edgep2s.append(edgep2_u) - return edgep1s, edgep2s + position.append('upper') + return edgep1s, edgep2s, position - def _get_tickdir(self): + def _get_tickdir(self, position): """ Get the direction of the tick. + Parameters + ---------- + position : str, optional : {'upper', 'lower', 'default'} + The position of the axis. + Returns ------- tickdir : int Index which indicates which coordinate the tick line will align with. """ + _api.check_in_list(('upper', 'lower', 'default'), position=position) + # TODO: Move somewhere else where it's triggered less: - tickdirs_base = [v["tickdir"] for v in self._AXINFO.values()] + tickdirs_base = [v["tickdir"] for v in self._AXINFO.values()] # default + elev_mod = np.mod(self.axes.elev + 180, 360) - 180 + azim_mod = np.mod(self.axes.azim, 360) + if position == 'upper': + if elev_mod >= 0: + tickdirs_base = [2, 2, 0] + else: + tickdirs_base = [1, 0, 0] + if (0 <= azim_mod < 180): + tickdirs_base[2] = 1 + elif position == 'lower': + if elev_mod >= 0: + tickdirs_base = [1, 0, 1] + else: + tickdirs_base = [2, 2, 1] + if (0 <= azim_mod < 180): + tickdirs_base[2] = 0 info_i = [v["i"] for v in self._AXINFO.values()] i = self._axinfo["i"] - j = self.axes._vertical_axis - 2 - # tickdir = [[1, 2, 1], [2, 2, 0], [1, 0, 0]][i] + vert_ax = self.axes._vertical_axis + j = vert_ax - 2 + # default: tickdir = [[1, 2, 1], [2, 2, 0], [1, 0, 0]][vert_ax][i] tickdir = np.roll(info_i, -j)[np.roll(tickdirs_base, j)][i] return tickdir @@ -398,23 +426,19 @@ def draw_pane(self, renderer): self.pane.draw(renderer) renderer.close_group('pane3d') - def _axmask(self): - info = self._axinfo - index = info["i"] axmask = [True, True, True] - axmask[index] = False + axmask[self._axinfo["i"]] = False return axmask - def _draw_ticks(self, renderer, edgep1, centers, deltas, highs, - deltas_per_point): + deltas_per_point, pos): ticks = self._update_ticks() info = self._axinfo index = info["i"] # Draw ticks: - tickdir = self._get_tickdir() + tickdir = self._get_tickdir(pos) tickdelta = deltas[tickdir] if highs[tickdir] else -deltas[tickdir] tick_info = info['tick'] @@ -447,13 +471,13 @@ def _draw_ticks(self, renderer, edgep1, centers, deltas, highs, tick.tick1line.set_linewidth(tick_lw[tick._major]) tick.draw(renderer) - def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, centers, highs, pep, dx, dy): # Get general axis information: info = self._axinfo index = info["i"] juggled = info["juggled"] + tickdir = info["tickdir"] # Which of the two edge points do we want to # use for locating the offset text? @@ -484,14 +508,14 @@ def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, centers, # using the wrong reference points). # # (TT, FF, TF, FT) are the shorthand for the tuple of - # (centpt[info['tickdir']] <= pep[info['tickdir'], outerindex], + # (centpt[tickdir] <= pep[tickdir, outerindex], # centpt[index] <= pep[index, outerindex]) # # Three-letters (e.g., TFT, FTT) are short-hand for the array of bools # from the variable 'highs'. # --------------------------------------------------------------------- centpt = proj3d.proj_transform(*centers, self.axes.M) - if centpt[info['tickdir']] > pep[info['tickdir'], outerindex]: + if centpt[tickdir] > pep[tickdir, outerindex]: # if FT and if highs has an even number of Trues if (centpt[index] <= pep[index, outerindex] and np.count_nonzero(highs) % 2 == 0): @@ -518,10 +542,8 @@ def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, centers, self.offsetText.set_ha(align) self.offsetText.draw(renderer) - - def _draw_labels(self, renderer, edgep1, edgep2, labeldeltas, centers, - dx, dy): - info = self._axinfo + def _draw_labels(self, renderer, edgep1, edgep2, labeldeltas, centers, dx, dy): + label = self._axinfo["label"] # Draw labels lxyz = 0.5 * (edgep1 + edgep2) @@ -531,12 +553,11 @@ def _draw_labels(self, renderer, edgep1, edgep2, labeldeltas, centers, if self.get_rotate_label(self.label.get_text()): angle = art3d._norm_text_angle(np.rad2deg(np.arctan2(dy, dx))) self.label.set_rotation(angle) - self.label.set_va(info['label']['va']) - self.label.set_ha(info['label']['ha']) - self.label.set_rotation_mode(info['label']['rotation_mode']) + self.label.set_va(label['va']) + self.label.set_ha(label['ha']) + self.label.set_rotation_mode(label['rotation_mode']) self.label.draw(renderer) - @artist.allow_rasterization def draw(self, renderer): self.label._transform = self.axes.transData @@ -553,15 +574,14 @@ def draw(self, renderer): ax_points_estimate = sum(72. * ax_inches) deltas_per_point = 48 / ax_points_estimate default_offset = 21. - labeldeltas = ( - (self.labelpad + default_offset) * deltas_per_point * deltas) + labeldeltas = (self.labelpad + default_offset) * deltas_per_point * deltas # Determine edge points for the axis lines minmax = np.where(highs, maxs, mins) # "origin" point maxmin = np.where(~highs, maxs, mins) # "opposite" corner near camera - for edgep1, edgep2 in zip(*self._get_all_axis_line_edge_points( - minmax, maxmin, self._tick_position)): + for edgep1, edgep2, pos in zip(*self._get_all_axis_line_edge_points( + minmax, maxmin, self._tick_position)): # Project the edge points along the current position pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M) pep = np.asarray(pep) @@ -582,14 +602,14 @@ def draw(self, renderer): # Draw ticks self._draw_ticks(renderer, edgep1, centers, deltas, highs, - deltas_per_point) + deltas_per_point, pos) # Draw Offset text self._draw_offset_text(renderer, edgep1, edgep2, labeldeltas, centers, highs, pep, dx, dy) - for edgep1, edgep2 in zip(*self._get_all_axis_line_edge_points( - minmax, maxmin, self._label_position)): + for edgep1, edgep2, pos in zip(*self._get_all_axis_line_edge_points( + minmax, maxmin, self._label_position)): # See comments above pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M) pep = np.asarray(pep) @@ -597,8 +617,7 @@ def draw(self, renderer): self.axes.transAxes.transform([pep[0:2, 0]]))[0] # Draw labels - self._draw_labels(renderer, edgep1, edgep2, labeldeltas, centers, - dx, dy) + self._draw_labels(renderer, edgep1, edgep2, labeldeltas, centers, dx, dy) renderer.close_group('axis3d') self.stale = False @@ -652,7 +671,7 @@ def get_tightbbox(self, renderer=None, *, for_layout_only=False): # (and hope they are up to date) because at draw time we # shift the ticks and their labels around in (x, y) space # based on the projection, the current view port, and their - # position in 3D space. If we extend the transforms framework + # position in 3D space. If we extend the transforms framework # into 3D we would not need to do this different book keeping # than we do in the normal axis major_locs = self.get_majorticklocs() diff --git a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py index 671ce68b1e93..9dfa9804100a 100644 --- a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py +++ b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py @@ -2156,7 +2156,7 @@ def test_view_init_vertical_axis( # Assert ticks are correctly aligned: tickdir_expected = tickdirs_expected[i] - tickdir_actual = axis._get_tickdir() + tickdir_actual = axis._get_tickdir('default') np.testing.assert_array_equal(tickdir_expected, tickdir_actual) From 724e80cf7ad6238b8493cab4788621be58ad4f7c Mon Sep 17 00:00:00 2001 From: Scott Shambaugh Date: Sun, 30 Jul 2023 23:55:58 -0600 Subject: [PATCH 6/6] Tests, fix, and whats new from code review Code review commits Test image for axis positions --- doc/users/next_whats_new/3d_axis_positions.rst | 15 +++++++++------ lib/mpl_toolkits/mplot3d/axis3d.py | 16 +++++++++++++--- .../test_axes3d/axis_positions.png | Bin 0 -> 95870 bytes lib/mpl_toolkits/mplot3d/tests/test_axes3d.py | 12 ++++++++++++ 4 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 lib/mpl_toolkits/mplot3d/tests/baseline_images/test_axes3d/axis_positions.png diff --git a/doc/users/next_whats_new/3d_axis_positions.rst b/doc/users/next_whats_new/3d_axis_positions.rst index 370860cd1349..e4e09eb3afad 100644 --- a/doc/users/next_whats_new/3d_axis_positions.rst +++ b/doc/users/next_whats_new/3d_axis_positions.rst @@ -8,10 +8,13 @@ You can now specify the positions of ticks and axis labels for 3D plots. import matplotlib.pyplot as plt - positions = ['default', 'upper', 'lower', 'both', 'none'] - fig, axs = plt.subplots(1, 5, subplot_kw={'projection': '3d'}) - for ax, pos in zip(axs, positions): + positions = ['lower', 'upper', 'default', 'both', 'none'] + fig, axs = plt.subplots(2, 3, figsize=(12, 8), + subplot_kw={'projection': '3d'}) + for ax, pos in zip(axs.flatten(), positions): for axis in ax.xaxis, ax.yaxis, ax.zaxis: - axis._label_position = pos - axis._tick_position = pos - ax.set(xlabel='x', ylabel='y', zlabel='z', title=pos) + axis.set_label_position(pos) + axis.set_ticks_position(pos) + title = f'position="{pos}"' + ax.set(xlabel='x', ylabel='y', zlabel='z', title=title) + axs[1, 2].axis('off') diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index ace7f0a81ebc..58792deae963 100644 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -195,6 +195,11 @@ def set_ticks_position(self, position): str : {'lower', 'upper', 'both', 'default', 'none'} The position of the bolded axis lines, ticks, and tick labels. """ + if position in ['top', 'bottom']: + _api.warn_deprecated('3.8', name=f'{position=}', + obj_type='argument value', + alternative="'upper' or 'lower'") + return _api.check_in_list(['lower', 'upper', 'both', 'default', 'none'], position=position) self._tick_position = position @@ -219,6 +224,11 @@ def set_label_position(self, position): str : {'lower', 'upper', 'both', 'default', 'none'} The position of the axis label. """ + if position in ['top', 'bottom']: + _api.warn_deprecated('3.8', name=f'{position=}', + obj_type='argument value', + alternative="'upper' or 'lower'") + return _api.check_in_list(['lower', 'upper', 'both', 'default', 'none'], position=position) self._label_position = position @@ -345,7 +355,7 @@ def _get_all_axis_line_edge_points(self, minmax, maxmin, axis_position=None): position='lower') edgep1_u, edgep2_u = self._get_axis_line_edge_points(minmax, maxmin, position='upper') - if position in ('lower', 'both'): + if axis_position in ('lower', 'both'): edgep1s.append(edgep1_l) edgep2s.append(edgep2_l) position.append('lower') @@ -381,14 +391,14 @@ def _get_tickdir(self, position): tickdirs_base = [2, 2, 0] else: tickdirs_base = [1, 0, 0] - if (0 <= azim_mod < 180): + if 0 <= azim_mod < 180: tickdirs_base[2] = 1 elif position == 'lower': if elev_mod >= 0: tickdirs_base = [1, 0, 1] else: tickdirs_base = [2, 2, 1] - if (0 <= azim_mod < 180): + if 0 <= azim_mod < 180: tickdirs_base[2] = 0 info_i = [v["i"] for v in self._AXINFO.values()] diff --git a/lib/mpl_toolkits/mplot3d/tests/baseline_images/test_axes3d/axis_positions.png b/lib/mpl_toolkits/mplot3d/tests/baseline_images/test_axes3d/axis_positions.png new file mode 100644 index 0000000000000000000000000000000000000000..d4155479d213bed69d964d825afaf1f38c5313b4 GIT binary patch literal 95870 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%0AShLK*T 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ͅJWCT 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 E7oS0Ti2wiq literal 0 HcmV?d00001 diff --git a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py index 9dfa9804100a..c00a96b421c7 100644 --- a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py +++ b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py @@ -57,6 +57,18 @@ def test_invisible_ticks_axis(): axis.line.set_visible(False) +@mpl3d_image_comparison(['axis_positions.png'], remove_text=False, style='mpl20') +def test_axis_positions(): + positions = ['upper', 'lower', 'both', 'none'] + fig, axs = plt.subplots(2, 2, subplot_kw={'projection': '3d'}) + for ax, pos in zip(axs.flatten(), positions): + for axis in ax.xaxis, ax.yaxis, ax.zaxis: + axis.set_label_position(pos) + axis.set_ticks_position(pos) + title = f'{pos}' + ax.set(xlabel='x', ylabel='y', zlabel='z', title=title) + + @mpl3d_image_comparison(['aspects.png'], remove_text=False, style='mpl20') def test_aspects(): aspects = ('auto', 'equal', 'equalxy', 'equalyz', 'equalxz', 'equal')