plot_embedding(coordinates, partition=None, add_sphere=False, point_size=8,
    colours=None, labels=None, legend=True, outfile=False, **kwargs):
    
    Plot a 2D / 3D scatterplot of coordinates, optionally
    coloured by group membership.

    Args:
        coordinates: numpy array or treeCl.CoordinateMatrix -
            The coordinates of the points to plot. The number
            of columns determines the number of dimensions in
            the plot.
        add_sphere: bool -
            Add a wireframe sphere to a 3D plot. Spectral clustering
            places points on the surface of a unit sphere.
        colours: list of rgb hexes, or 'auto', or None -
            Colours to use to colour the points, as a list of
            RGB hex values. If None, defaults
            (colorbrewer set3). If 'auto', generates a set
            of colours equally spaced from the colour wheel.
        labels: Tuple(xlab, ylab, title, zlab) -
            Plot labels. Must be given in the above order.
            Missing options will be replaced by None. E.g.
            to set the title: (None, None, "Some points")
        outfile: str -
            Save figure to this filename

def plot_embedding(coordinates, partition=None, add_sphere=False, point_size=8,
        colours=None, labels=None, legend=True, outfile=False, **kwargs):
    """ plot_embedding(coordinates, partition=None, add_sphere=False, point_size=8,
    colours=None, labels=None, legend=True, outfile=False, **kwargs):
    
    Plot a 2D / 3D scatterplot of coordinates, optionally
    coloured by group membership.

    Args:
        coordinates: numpy array or treeCl.CoordinateMatrix -
            The coordinates of the points to plot. The number
            of columns determines the number of dimensions in
            the plot.
        add_sphere: bool -
            Add a wireframe sphere to a 3D plot. Spectral clustering
            places points on the surface of a unit sphere.
        colours: list of rgb hexes, or 'auto', or None -
            Colours to use to colour the points, as a list of
            RGB hex values. If None, defaults
            (colorbrewer set3). If 'auto', generates a set
            of colours equally spaced from the colour wheel.
        labels: Tuple(xlab, ylab, title, zlab) -
            Plot labels. Must be given in the above order.
            Missing options will be replaced by None. E.g.
            to set the title: (None, None, "Some points")
        outfile: str -
            Save figure to this filename
    """
    if isinstance(coordinates, CoordinateMatrix):
        coordinates = coordinates.values
    dimensions = min(3, coordinates.shape[1])
    partition = (partition or
                 Partition(tuple([0] * len(coordinates))))
    ngrp = partition.num_groups()

    if colours is None:
        colours = SET2
    elif colours == 'auto':
        colours = ggColorSlice(ngrp)

    colour_cycle = itertools.cycle(colours)
    colours = np.array([hex2color(c) for c in itertools.islice(colour_cycle, ngrp)])

    if labels is None:
        xlab, ylab, zlab, title = None, None, None, None
    else:
        if isinstance(labels, (tuple, list)):
            labels = list(labels[:4])
            labels.extend([None]*(4-len(labels)))
            xlab, ylab, title, zlab = labels

    fig = plt.figure()

    if dimensions == 3:
        ax = fig.add_subplot(111, projection='3d')
        if add_sphere:
            ax = _add_sphere(ax)
    else:
        ax = fig.add_subplot(111)
    
    members = partition.get_membership()
    for grp in range(ngrp):
        index = np.array(members[grp])
        points = coordinates[index,:dimensions].T
        ax.scatter(*points, s=point_size, c=colours[grp], edgecolor=None, label='Group {}'.format(grp+1), **kwargs)

    if xlab:
        ax.set_xlabel(xlab)
    if ylab:
        ax.set_ylabel(ylab)
    if zlab:
        ax.set_zlabel(zlab)
    if title:
        ax.set_title(title)
    if legend:
        plt.legend()
    if outfile:
        fig.savefig('{0}.pdf'.format(outfile))

    return fig