code: def make_spring(
      num_points=300,
      num_turns=4,
      height=12,
      radius=2.0,
      xnot=None,
      ynot=None,
      znot=None,
  ):
      """
      Generate a list of points corresponding to a spring.
  
      Parameters
      ----------
      num_points : int
          Number of points to map spring over. More points means a rounder
          spring.
      num_turns : int
          Number of coils in the spring
      height : float
          The height of the spring. Keep it in whatever units the rest of the
          spring is in.
      radius : float
          The radius of the coils. The spring will end up being
          2*radius wide.
      xnot : float
          Initial x-coordinate for the spring coordinates to start at.
      ynot : float
          Initial y-coordinate for the spring coordinates to start at.
      znot : float
          Initial z-coordinate for the spring coordinates to start at.
  
      Returns
      -------
      coord_list: list of tuples
          Coordinate list of (x, y, z) positions for the spring
  
      Notes
      -----
      Right now, this assumes the center is at x=0, y=0. Later, it might be
      good to add in stuff to change that.
  
      Right now, the length of the "ends" is 10% of the overall length, as
      well as a small "turn" that is length radius / 2. In the future, maybe
      there could be a kwarg to set the length of the sides of the spring.
      For now, 10% looks good.
  
      """
      coords_list = []
      init_pts = num_points // 10
      znot = 0 if znot is None else znot
      xnot = 0 if xnot is None else xnot
      ynot = 0 if ynot is None else ynot
      coords_list.append((xnot, ynot, znot))
      for _ in range(init_pts):
          znot += height / num_points
          coords_list.append((xnot, ynot, znot))
      hold_z = znot
      for i in range(init_pts // 2):
          small_theta = (i + 1) * np.pi / init_pts
          xnot = radius / 2 * (1 - np.cos(small_theta))
          znot = hold_z + radius / 2 * np.sin(small_theta)
          coords_list.append((xnot, ynot, znot))
      coords_list += make_spiral(
          num_points=num_points - 3 * init_pts,
          num_turns=num_turns,
          height=(height - (91 * height / num_points) - radius / 2),
          radius=radius,
          xnot=xnot,
          ynot=ynot,
          znot=znot,
      )
      hold_z = coords_list[-1][-1]
      for i in range(init_pts // 2):
          small_theta = np.pi / 2 - (i + 1) * np.pi / init_pts
          xnot = radius / 2 * (1 - np.cos(small_theta))
          znot = hold_z + radius / 2 * np.cos(small_theta)
          coords_list.append((xnot, ynot, znot))
      xnot = 0.0
      znot += height / num_points
      for _ in range(init_pts):
          znot += height / num_points
          coords_list.append((xnot, ynot, znot))
      coords_list.append((0, 0, height))
  
      return coords_list
  
imports: from __future__ import division, print_function, absolute_import
  from vispy import app, visuals
  from vispy.visuals import transforms
  from vispy.io import load_data_file
  import sys
  import numpy
  import string
  import logging
  import traceback
  from PyQt5 import QtCore, QtGui, QtWidgets
label_desc: Use image node_id 2 for calling a global function with example usage: make_spring(num_points, num_turns, height, radius, xnot, ynot, znot) and returns: coords_list