docs: def animate(zdata, xdata, ydata,
              conversionFactorArray, timedata,
              BoxSize,
              timeSteps=100, filename="particle"):
      """
      Animates the particle's motion given the z, x and y signal (in Volts)
      and the conversion factor (to convert between V and nm).
  
      Parameters
      ----------
      zdata : ndarray
          Array containing the z signal in volts with time.
      xdata : ndarray
          Array containing the x signal in volts with time.
      ydata : ndarray
          Array containing the y signal in volts with time.
      conversionFactorArray : ndarray
          Array of 3 values of conversion factors for z, x and y (in units of Volts/Metre)
      timedata : ndarray
          Array containing the time data in seconds.
      BoxSize : float
          The size of the box in which to animate the particle - in nm
      timeSteps : int, optional
          Number of time steps to animate
      filename : string, optional
          filename to create the mp4 under (<filename>.mp4)
  
      """
      timePerFrame = 0.203
      print("This will take ~ {} minutes".format(timePerFrame * timeSteps / 60))
  
      convZ = conversionFactorArray[0] * 1e-9
      convX = conversionFactorArray[1] * 1e-9
      convY = conversionFactorArray[2] * 1e-9
      
      ZBoxStart = -BoxSize  # 1/conv*(_np.mean(zdata)-0.06)
      ZBoxEnd = BoxSize  # 1/conv*(_np.mean(zdata)+0.06)
      XBoxStart = -BoxSize  # 1/conv*(_np.mean(xdata)-0.06)
      XBoxEnd = BoxSize  # 1/conv*(_np.mean(xdata)+0.06)
      YBoxStart = -BoxSize  # 1/conv*(_np.mean(ydata)-0.06)
      YBoxEnd = BoxSize  # 1/conv*(_np.mean(ydata)+0.06)
  
      FrameInterval = 1  # how many timesteps = 1 frame in animation
  
      a = 20
      b = 0.6 * a
      myFPS = 7
      myBitrate = 1000000
  
      fig = _plt.figure(figsize=(a, b))
      ax = fig.add_subplot(111, projection='3d')
      ax.set_title("{} us".format(timedata[0] * 1000000))
      ax.set_xlabel('X (nm)')
      ax.set_xlim([XBoxStart, XBoxEnd])
      ax.set_ylabel('Y (nm)')
      ax.set_ylim([YBoxStart, YBoxEnd])
      ax.set_zlabel('Z (nm)')
      ax.set_zlim([ZBoxStart, ZBoxEnd])
      ax.view_init(20, -30)
  
      #ax.view_init(0, 0)
  
      def setup_plot():
          XArray = 1 / convX * xdata[0]
          YArray = 1 / convY * ydata[0]
          ZArray = 1 / convZ * zdata[0]
          scatter = ax.scatter(XArray, YArray, ZArray)
          return scatter,
  
      def animate(i):
          # print "\r {}".format(i),
          print("Frame: {}".format(i), end="\r")
          ax.clear()
          ax.view_init(20, -30)
          ax.set_title("{} us".format(int(timedata[i] * 1000000)))
          ax.set_xlabel('X (nm)')
          ax.set_xlim([XBoxStart, XBoxEnd])
          ax.set_ylabel('Y (nm)')
          ax.set_ylim([YBoxStart, YBoxEnd])
          ax.set_zlabel('Z (nm)')
          ax.set_zlim([ZBoxStart, ZBoxEnd])
          XArray = 1 / convX * xdata[i]
          YArray = 1 / convY * ydata[i]
          ZArray = 1 / convZ * zdata[i]
          scatter = ax.scatter(XArray, YArray, ZArray)
          ax.scatter([XArray], [0], [-ZBoxEnd], c='k', alpha=0.9)
          ax.scatter([-XBoxEnd], [YArray], [0], c='k', alpha=0.9)
          ax.scatter([0], [YBoxEnd], [ZArray], c='k', alpha=0.9)
  
          Xx, Yx, Zx, Xy, Yy, Zy, Xz, Yz, Zz = [], [], [], [], [], [], [], [], []
  
          for j in range(0, 30):
  
              Xlast = 1 / convX * xdata[i - j]
              Ylast = 1 / convY * ydata[i - j]
              Zlast = 1 / convZ * zdata[i - j]
  
              Alpha = 0.5 - 0.05 * j
              if Alpha > 0:
                  ax.scatter([Xlast], [0 + j * 10],
                             [-ZBoxEnd], c='grey', alpha=Alpha)
                  ax.scatter([-XBoxEnd], [Ylast], [0 - j * 10],
                             c='grey', alpha=Alpha)
                  ax.scatter([0 - j * 2], [YBoxEnd],
                             [Zlast], c='grey', alpha=Alpha)
  
                  Xx.append(Xlast)
                  Yx.append(0 + j * 10)
                  Zx.append(-ZBoxEnd)
  
                  Xy.append(-XBoxEnd)
                  Yy.append(Ylast)
                  Zy.append(0 - j * 10)
  
                  Xz.append(0 - j * 2)
                  Yz.append(YBoxEnd)
                  Zz.append(Zlast)
  
              if j < 15:
                  XCur = 1 / convX * xdata[i - j + 1]
                  YCur = 1 / convY * ydata[i - j + 1]
                  ZCur = 1 / convZ * zdata[i - j + 1]
                  ax.plot([Xlast, XCur], [Ylast, YCur], [Zlast, ZCur], alpha=0.4)
  
          ax.plot_wireframe(Xx, Yx, Zx, color='grey')
          ax.plot_wireframe(Xy, Yy, Zy, color='grey')
          ax.plot_wireframe(Xz, Yz, Zz, color='grey')
  
          return scatter,
  
      anim = _animation.FuncAnimation(fig, animate, int(
          timeSteps / FrameInterval), init_func=setup_plot, blit=True)
  
      _plt.rcParams['animation.ffmpeg_path'] = '/usr/bin/ffmpeg'
      mywriter = _animation.FFMpegWriter(fps=myFPS, bitrate=myBitrate)
      # , fps = myFPS, bitrate = myBitrate)
      anim.save('{}.mp4'.format(filename), writer=mywriter)
      return None