<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def Spring( startPoint=(0, 0, 0), endPoint=(1, 0, 0), coils=20, r=0.1, r2=None, thickness=None, c="grey", alpha=1, ):
 """ Build a spring of specified nr of `coils` between `startPoint` and `endPoint`. :param int coils: number of coils :param float r: radius at start point :param float r2: radius at end point :param float thickness: thickness of the coil section .. hint:: |aspring| |aspring.py|_ """

    diff = endPoint - np.array(startPoint)
    length = np.linalg.norm(diff)
    if not length:
        return None
    if not r:
        r = length / 20
    trange = np.linspace(0, length, num=50 * coils)
    om = 6.283 * (coils - 0.5) / length
    if not r2:
        r2 = r
    pts = []
    for t in trange:
        f = (length - t) / length
        rd = r * f + r2 * (1 - f)
        pts.append([rd * np.cos(om * t), rd * np.sin(om * t), t])

    pts = [[0, 0, 0]] + pts + [[0, 0, length]]
    diff = diff / length
    theta = np.arccos(diff[2])
    phi = np.arctan2(diff[1], diff[0])
    sp = Line(pts).polydata(False)
    t = vtk.vtkTransform()
    t.RotateZ(phi * 57.3)
    t.RotateY(theta * 57.3)
    tf = vtk.vtkTransformPolyDataFilter()
    tf.SetInputData(sp)
    tf.SetTransform(t)
    tf.Update()
    tuf = vtk.vtkTubeFilter()
    tuf.SetNumberOfSides(12)
    tuf.CappingOn()
    tuf.SetInputData(tf.GetOutput())
    if not thickness:
        thickness = r / 10
    tuf.SetRadius(thickness)
    tuf.Update()
    poly = tuf.GetOutput()
    actor = Actor(poly, c, alpha)
    actor.GetProperty().SetInterpolationToPhong()
    actor.SetPosition(startPoint)
    actor.base = np.array(startPoint)
    actor.top = np.array(endPoint)
    settings.collectable_actors.append(actor)
    return actor