Embeds the distance matrix in a coordinate space. Implemented methods are:
            cmds: Classical MultiDimensional Scaling
            kpca: Kernel Principal Components Analysis
            mmds: Metric MultiDimensional Scaling
            nmmds: Non-Metric MultiDimensional Scaling
            spectral: Spectral decomposition of Laplacian matrix
            tsne: t-distributed Stochastic Neighbour Embedding

        Valid kwargs:
            kpca: affinity_matrix - a precomputed array of affinities
                  sigma - the value of sigma to use when computing the affinity matrix via
                          the Radial Basis Function
            nmmds: initial_coords - a set of coordinates to refine. NMMDS works very badly
                                    without this
            spectral: affinity_matrix, sigma
                      unit_length - scale the coordinates to unit length, so points sit
                                    on the surface of the unit sphere
        :param dimensions: (int) number of coordinate axes to use
        :param method: (string) one of cmds, kpca, mmds, nmmds, spectral
        :param kwargs: unit_length (bool), affinity_matrix (np.array), sigma (float), initial_coords (np.array)
        :return: coordinate matrix (np.array)

def embedding(self, dimensions, method, **kwargs):
        """
        Embeds the distance matrix in a coordinate space. Implemented methods are:
            cmds: Classical MultiDimensional Scaling
            kpca: Kernel Principal Components Analysis
            mmds: Metric MultiDimensional Scaling
            nmmds: Non-Metric MultiDimensional Scaling
            spectral: Spectral decomposition of Laplacian matrix
            tsne: t-distributed Stochastic Neighbour Embedding

        Valid kwargs:
            kpca: affinity_matrix - a precomputed array of affinities
                  sigma - the value of sigma to use when computing the affinity matrix via
                          the Radial Basis Function
            nmmds: initial_coords - a set of coordinates to refine. NMMDS works very badly
                                    without this
            spectral: affinity_matrix, sigma
                      unit_length - scale the coordinates to unit length, so points sit
                                    on the surface of the unit sphere
        :param dimensions: (int) number of coordinate axes to use
        :param method: (string) one of cmds, kpca, mmds, nmmds, spectral
        :param kwargs: unit_length (bool), affinity_matrix (np.array), sigma (float), initial_coords (np.array)
        :return: coordinate matrix (np.array)
        """
        errors.optioncheck(method, ['cmds', 'kpca', 'mmds', 'nmmds', 'spectral', 'tsne'])
        if method == 'cmds':
            array =  _embedding_classical_mds(self.to_array(), dimensions, **kwargs)
        elif method == 'kpca':
            array = _embedding_kernel_pca(self.to_array(), dimensions, **kwargs)
        elif method == 'mmds':
            array = _embedding_metric_mds(self.to_array(), dimensions)
        elif method == 'nmmds':
            array = _embedding_nonmetric_mds(self.to_array(), dimensions, **kwargs)
        elif method == 'spectral':
            array = _embedding_spectral(self.to_array(), dimensions, **kwargs)
        elif method == 'tsne':
            array = _embedding_tsne(self.to_array(), dimensions, **kwargs)

        return CoordinateMatrix(array, names=self.df.index)