Source decomposition with ICA.

    Apply ICA to the data x, with optional PCA dimensionality reduction.

    Parameters
    ----------
    x : array, shape (n_trials, n_channels, n_samples) or (n_channels, n_samples)
        data set
    reducedim : {int, float, 'no_pca'}, optional
        A number of less than 1 in interpreted as the fraction of variance that should remain in the data. All
        components that describe in total less than `1-reducedim` of the variance are removed by the PCA step.
        An integer numer of 1 or greater is interpreted as the number of components to keep after applying the PCA.
        If set to 'no_pca' the PCA step is skipped.
    backend : dict-like, optional
        Specify backend to use. When set to None the backend configured in config.backend is used.

    Returns
    -------
    result : ResultICA
        Source decomposition

def plainica(x, reducedim=0.99, backend=None, random_state=None):
    """ Source decomposition with ICA.

    Apply ICA to the data x, with optional PCA dimensionality reduction.

    Parameters
    ----------
    x : array, shape (n_trials, n_channels, n_samples) or (n_channels, n_samples)
        data set
    reducedim : {int, float, 'no_pca'}, optional
        A number of less than 1 in interpreted as the fraction of variance that should remain in the data. All
        components that describe in total less than `1-reducedim` of the variance are removed by the PCA step.
        An integer numer of 1 or greater is interpreted as the number of components to keep after applying the PCA.
        If set to 'no_pca' the PCA step is skipped.
    backend : dict-like, optional
        Specify backend to use. When set to None the backend configured in config.backend is used.

    Returns
    -------
    result : ResultICA
        Source decomposition
    """

    x = atleast_3d(x)
    t, m, l = np.shape(x)

    if backend is None:
        backend = scotbackend

    # pre-transform the data with PCA
    if reducedim == 'no pca':
        c = np.eye(m)
        d = np.eye(m)
        xpca = x
    else:
        c, d, xpca = backend['pca'](x, reducedim)

    # run on residuals ICA to estimate volume conduction
    mx, ux = backend['ica'](cat_trials(xpca), random_state=random_state)

    # correct (un)mixing matrix estimatees
    mx = mx.dot(d)
    ux = c.dot(ux)

    class Result:
        unmixing = ux
        mixing = mx

    return Result