class_docstr: Displays a tube around a piecewise-linear path.
  
  The tube mesh is corrected following its Frenet curvature and
  torsion such that it varies smoothly along the curve, including if
  the tube is closed.
  
  Parameters
  ----------
  points : ndarray
      An array of (x, y, z) points describing the path along which the
      tube will be extruded.
  radius : float | ndarray
      The radius of the tube. Use array of floats as input to set radii of
      points individually. Defaults to 1.0.
  closed : bool
      Whether the tube should be closed, joining the last point to the
      first. Defaults to False.
  color : Color | ColorArray
      The color(s) to use when drawing the tube. The same color is
      applied to each vertex of the mesh surrounding each point of
      the line. If the input is a ColorArray, the argument will be
      cycled; for instance if 'red' is passed then the entire tube
      will be red, or if ['green', 'blue'] is passed then the points
      will alternate between these colours. Defaults to 'purple'.
  tube_points : int
      The number of points in the circle-approximating polygon of the
      tube's cross section. Defaults to 8.
  shading : str | None
      Same as for the `MeshVisual` class. Defaults to 'smooth'.
  vertex_colors: ndarray | None
      Same as for the `MeshVisual` class.
  face_colors: ndarray | None
      Same as for the `MeshVisual` class.
  mode : str
      Same as for the `MeshVisual` class. Defaults to 'triangles'.
code: def __init__(
      self,
      points,
      radius=1.0,
      closed=False,
      color="purple",
      tube_points=8,
      shading="smooth",
      vertex_colors=None,
      face_colors=None,
      mode="triangles",
  ):
      # make sure we are working with floats
      points = np.array(points).astype(float)
  
      tangents, normals, binormals = _frenet_frames(points, closed)
  
      segments = len(points) - 1
  
      # if single radius, convert to list of radii
      if not isinstance(radius, collections.abc.Iterable):
          radius = [radius] * len(points)
      elif len(radius) != len(points):
          raise ValueError("Length of radii list must match points.")
  
      # get the positions of each vertex
      grid = np.zeros((len(points), tube_points, 3))
      for i in range(len(points)):
          pos = points[i]
          normal = normals[i]
          binormal = binormals[i]
          r = radius[i]
  
          # Add a vertex for each point on the circle
          v = (
              np.arange(tube_points, dtype=np.float32)
              / tube_points
              * 2
              * np.pi
          )
          cx = -1.0 * r * np.cos(v)
          cy = r * np.sin(v)
          grid[i] = (
              pos
              + cx[:, np.newaxis] * normal
              + cy[:, np.newaxis] * binormal
          )
  
      # construct the mesh
      indices = []
      for i in range(segments):
          for j in range(tube_points):
              ip = (i + 1) % segments if closed else i + 1
              jp = (j + 1) % tube_points
  
              index_a = i * tube_points + j
              index_b = ip * tube_points + j
              index_c = ip * tube_points + jp
              index_d = i * tube_points + jp
  
              indices.append([index_a, index_b, index_d])
              indices.append([index_b, index_c, index_d])
  
      vertices = grid.reshape(grid.shape[0] * grid.shape[1], 3)
  
      color = ColorArray(color)
      if vertex_colors is None:
          point_colors = np.resize(color.rgba, (len(points), 4))
          vertex_colors = np.repeat(point_colors, tube_points, axis=0)
  
      indices = np.array(indices, dtype=np.uint32)
  
      MeshVisual.__init__(
          self,
          vertices,
          indices,
          vertex_colors=vertex_colors,
          face_colors=face_colors,
          shading=shading,
          mode=mode,
      )
  
file_path: vispy/vispy/visuals/tube.py
imports: from __future__ import division
  from .mesh import MeshVisual
  import numpy
  from numpy.linalg import norm
  from ..util.transforms import rotate
  from ..color import ColorArray
  import collections
label_desc: Use image node_id 1 to create a new TubeVisual object from inherited base classes: MeshVisual with example: obj = TubeVisual(points, radius, closed, color, tube_points, shading, vertex_colors, face_colors, mode)