def set_miller_indices(x, y, z=nil)
      raise "Vectors must be orthogonal" unless 0 == dot(x,y)
      if z
        raise "Vectors must be orthogonal" unless 0 == dot(x,z)
      else
        z = cross(x, y)
      end
      self.cart_to_miller = Matrix[[x[0], y[0], z[0]], 
                               [x[1], y[1], z[1]],
                               [x[2], y[2], z[2]]]
      self.miller_to_cart = cart_to_miller.inverse
      return nil
    end
def set_miller_indices(x, y, z=nil)
      raise "Vectors must be orthogonal" unless 0 == dot(x,y)
      if z
        raise "Vectors must be orthogonal" unless 0 == dot(x,z)
      else
        z = cross(x, y)
      end
      self.cart_to_miller = Matrix[[x[0], y[0], z[0]], 
                               [x[1], y[1], z[1]],
                               [x[2], y[2], z[2]]]
      self.miller_to_cart = cart_to_miller.inverse
      return nil
    end
Define the [h, k, l] vectors for each cartesian direction x, y, and z
 There must be at least two vectors provided, and they must be orthogonal
 The z vector, if provided, must also be orthogonal.  If it is not
 provided it will be calculated as the cross product of x and y

 These vectors will populate a matrix that for calculation of the
 miller indices for any arbitrary vector in cartesian space, and
 the calculation of the cartesian space vector for any arbitrary miller index
 See miller_from_cartesion and cartesian_from_miller for more details.

 The default miller indices are parallel to the cartesian indices.  That is
 the default x-axes points in (100), y points along (010) and z points along (001)