code: 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()
  
      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]
      self.major.formatter.set_locs(majorLocs)
      majorLabels = [
          self.major.formatter(val, i)
          for i, val in enumerate(majorLocs)
      ]
  
      mins, maxs, centers, deltas, tc, highs = self._get_coord_info(
          renderer
      )
  
      # Determine grid lines
      minmax = np.where(highs, maxs, mins)
  
      # Draw main axis line
      juggled = info["juggled"]
      edgep1 = minmax.copy()
      edgep1[juggled[0]] = get_flip_min_max(
          edgep1, juggled[0], mins, maxs
      )
  
      edgep2 = edgep1.copy()
      edgep2[juggled[1]] = get_flip_min_max(
          edgep2, juggled[1], mins, maxs
      )
      pep = proj3d.proj_trans_points([edgep1, edgep2], renderer.M)
      centpt = proj3d.proj_transform(
          centers[0], centers[1], centers[2], renderer.M
      )
      self.line.set_data((pep[0][0], pep[0][1]), (pep[1][0], pep[1][1]))
      self.line.draw(renderer)
  
      # Grid points where the planes meet
      xyz0 = []
      for val in majorLocs:
          coord = minmax.copy()
          coord[index] = val
          xyz0.append(coord)
  
      # Draw labels
      peparray = np.asanyarray(pep)
      # 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([peparray[0:2, 1]])
          - self.axes.transAxes.transform([peparray[0:2, 0]])
      )[0]
  
      lxyz = 0.5 * (edgep1 + edgep2)
  
      # A rough estimate; points are ambiguous since 3D plots rotate
      ax_scale = self.axes.bbox.size / self.figure.bbox.size
      ax_inches = np.multiply(ax_scale, self.figure.get_size_inches())
      ax_points_estimate = sum(72.0 * ax_inches)
      deltas_per_point = 48.0 / ax_points_estimate
      default_offset = 21.0
      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[0], lxyz[1], lxyz[2], renderer.M
      )
      self.label.set_position((tlx, tly))
      if self.get_rotate_label(self.label.get_text()):
          angle = art3d.norm_text_angle(
              math.degrees(math.atan2(dy, dx))
          )
          self.label.set_rotation(angle)
      self.label.set_va(info["label"]["va"])
      self.label.set_ha(info["label"]["ha"])
      self.label.draw(renderer)
  
      # Draw Offset text
  
      # Which of the two edge points do we want to
      # use for locating the offset text?
      if juggled[2] == 2:
          outeredgep = edgep1
          outerindex = 0
      else:
          outeredgep = edgep2
          outerindex = 1
  
      pos = copy.copy(outeredgep)
      pos = move_from_center(pos, centers, labeldeltas, axmask)
      olx, oly, olz = proj3d.proj_transform(
          pos[0], pos[1], pos[2], renderer.M
      )
      self.offsetText.set_text(self.major.formatter.get_offset())
      self.offsetText.set_position((olx, oly))
      angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
      self.offsetText.set_rotation(angle)
      # Must set rotation mode to "anchor" so that
      # the alignment point is used as the "fulcrum" for rotation.
      self.offsetText.set_rotation_mode("anchor")
  
      # ----------------------------------------------------------------------
      # Note: the following statement for determining the proper alignment of
      # the offset text. This was determined entirely by trial-and-error
      # and should not be in any way considered as "the way".  There are
      # still some edge cases where alignment is not quite right, but this
      # seems to be more of a geometry issue (in other words, I might be
      # using the wrong reference points).
      #
      # (TT, FF, TF, FT) are the shorthand for the tuple of
      #   (centpt[info['tickdir']] <= peparray[info['tickdir'], outerindex],
      #    centpt[index] <= peparray[index, outerindex])
      #
      # Three-letters (e.g., TFT, FTT) are short-hand for the array of bools
      # from the variable 'highs'.
      # ---------------------------------------------------------------------
      if (
          centpt[info["tickdir"]]
          > peparray[info["tickdir"], outerindex]
      ):
          # if FT and if highs has an even number of Trues
          if centpt[index] <= peparray[index, outerindex] and (
              (len(highs.nonzero()[0]) % 2) == 0
          ):
              # Usually, this means align right, except for the FTT case,
              # in which offset for axis 1 and 2 are aligned left.
              if highs.tolist() == [False, True, True] and index in (
                  1,
                  2,
              ):
                  align = "left"
              else:
                  align = "right"
          else:
              # The FF case
              align = "left"
      else:
          # if TF and if highs has an even number of Trues
          if centpt[index] > peparray[index, outerindex] and (
              (len(highs.nonzero()[0]) % 2) == 0
          ):
              # Usually mean align left, except if it is axis 2
              if index == 2:
                  align = "right"
              else:
                  align = "left"
          else:
              # The TT case
              align = "right"
  
      self.offsetText.set_va("center")
      self.offsetText.set_ha(align)
      self.offsetText.draw(renderer)
  
      # Draw grid lines
      if len(xyz0) > 0:
          # Grid points at end of one plane
          xyz1 = copy.deepcopy(xyz0)
          newindex = (index + 1) % 3
          newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
          for i in range(len(majorLocs)):
              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)):
              xyz2[i][newindex] = newval
  
          lines = list(zip(xyz1, xyz0, xyz2))
          if self.axes._draw_grid:
              self.gridlines.set_segments(lines)
              self.gridlines.set_color(
                  [info["grid"]["color"]] * len(lines)
              )
              self.gridlines.set_linewidth(
                  [info["grid"]["linewidth"]] * len(lines)
              )
              self.gridlines.set_linestyle(
                  [info["grid"]["linestyle"]] * len(lines)
              )
              self.gridlines.draw(renderer, project=True)
  
      # Draw ticks
      tickdir = info["tickdir"]
      tickdelta = deltas[tickdir]
      if highs[tickdir]:
          ticksign = 1
      else:
          ticksign = -1
  
      for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
          if tick is None:
              continue
  
          # Get tick line positions
          pos = copy.copy(edgep1)
          pos[index] = loc
          pos[tickdir] = (
              edgep1[tickdir]
              + info["tick"]["outward_factor"] * ticksign * tickdelta
          )
          x1, y1, z1 = proj3d.proj_transform(
              pos[0], pos[1], pos[2], renderer.M
          )
          pos[tickdir] = (
              edgep1[tickdir]
              - info["tick"]["inward_factor"] * ticksign * tickdelta
          )
          x2, y2, z2 = proj3d.proj_transform(
              pos[0], pos[1], pos[2], renderer.M
          )
  
          # Get position of label
          default_offset = 8.0  # A rough estimate
          labeldeltas = (
              (tick.get_pad() + default_offset)
              * deltas_per_point
              * deltas
          )
  
          axmask = [True, True, True]
          axmask[index] = False
          pos[tickdir] = edgep1[tickdir]
          pos = move_from_center(pos, centers, labeldeltas, axmask)
          lx, ly, lz = proj3d.proj_transform(
              pos[0], pos[1], pos[2], renderer.M
          )
  
          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")
      self.stale = False
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import six
  import math
  import copy
  from matplotlib import lines, axis, patches
  from matplotlib import rcParams
  from .None import art3d
  from .None import proj3d
  import numpy
label_desc: Use image node_id 11 for calling the Axis obj's underlying member method code with example usage: obj.draw(renderer) without return types