docs: def reference_axis_from_chains(chains):
      """Average coordinates from a set of primitives calculated from Chains.
  
      Parameters
      ----------
      chains : list(Chain)
  
      Returns
      -------
      reference_axis : numpy.array
          The averaged (x, y, z) coordinates of the primitives for
          the list of Chains. In the case of a coiled coil barrel,
          this would give the central axis for calculating e.g. Crick
          angles.
  
      Raises
      ------
      ValueError :
          If the Chains are not all of the same length.
      """
      if not len(set([len(x) for x in chains])) == 1:
          raise ValueError("All chains must be of the same length")
  
      # First array in coords is the primitive coordinates of the first chain.
      # The orientation of the first chain orients the reference_axis.
      coords = [numpy.array(chains[0].primitive.coordinates)]
      orient_vector = polypeptide_vector(chains[0])
      # Append the coordinates for the remaining chains, reversing the
      # direction in antiparallel arrangements.
      for i, c in enumerate(chains[1:]):
          if is_acute(polypeptide_vector(c), orient_vector):
              coords.append(numpy.array(c.primitive.coordinates))
          else:
              coords.append(numpy.flipud(numpy.array(c.primitive.coordinates)))
  
      # Average across the x, y and z coordinates to get the reference_axis
      # coordinates
      reference_axis = numpy.mean(numpy.array(coords), axis=0)
      return Primitive.from_coordinates(reference_axis)