import math


def rotate_point_around_axis(
      axis_point_1,
      axis_point_2,
      point,
      angle,
      deg=False):
  """
  Rotate a 3D coordinate about a given arbitrary axis by the specified angle.

  :param axis_point_1: tuple representing 3D coordinate at one end of the axis
  :param axis_point_2: tuple representing 3D coordinate at other end of the axis
  :param point: tuple representing 3D coordinate of starting point to rotate
  :param angle: rotation angle (defaults to radians)
  :param deg: Python boolean (default=False), specifies whether the angle is
    in degrees
  :returns: Python tuple (len=3) of rotated point
  """
  if (deg): angle *= math.pi/180.
  xa,ya,za = axis_point_1
  xb,yb,zb = axis_point_2
  x,y,z = point
  xl,yl,zl = xb-xa,yb-ya,zb-za
  xlsq = xl**2
  ylsq = yl**2
  zlsq = zl**2
  dlsq = xlsq + ylsq + zlsq
  dl = dlsq**0.5
  ca = math.cos(angle)
  dsa = math.sin(angle)/dl
  oca = (1-ca)/dlsq
  xlylo = xl*yl*oca
  xlzlo = xl*zl*oca
  ylzlo = yl*zl*oca
  xma,yma,zma = x-xa,y-ya,z-za
  m1 = xlsq*oca+ca
  m2 = xlylo-zl*dsa
  m3 = xlzlo+yl*dsa
  m4 = xlylo+zl*dsa
  m5 = ylsq*oca+ca
  m6 = ylzlo-xl*dsa
  m7 = xlzlo-yl*dsa
  m8 = ylzlo+xl*dsa
  m9 = zlsq*oca+ca
  x_new = xma*m1 + yma*m2 + zma*m3 + xa
  y_new = xma*m4 + yma*m5 + zma*m6 + ya
  z_new = xma*m7 + yma*m8 + zma*m9 + za
  return (x_new,y_new,z_new)