@verbose
def _tf_mixed_norm_solver_bcd_active_set(
        M, G, alpha_space, alpha_time, lipschitz_constant, phi, phiT,
        Z_init=None, wsize=64, tstep=4, n_orient=1, maxit=200, tol=1e-8,
        log_objective=True, perc=None, verbose=None):
    """Solves TF L21+L1 inverse solver with BCD and active set approach

    Algorithm is detailed in:

    Strohmeier D., Gramfort A., and Haueisen J.:
    MEG/EEG source imaging with a non-convex penalty in the time-
    frequency domain,
    5th International Workshop on Pattern Recognition in Neuroimaging,
    Stanford University, 2015

    Parameters
    ----------
    M : array
        The data.
    G : array
        The forward operator.
    alpha_space : float in [0, 100]
        Regularization parameter for spatial sparsity. If larger than 100,
        then no source will be active.
    alpha_time : float in [0, 100]
        Regularization parameter for temporal sparsity. It set to 0,
        no temporal regularization is applied. It this case, TF-MxNE is
        equivalent to MxNE with L21 norm.
    lipschitz_constant : float
        The lipschitz constant of the spatio temporal linear operator.
    phi : instance of _Phi
        The TF operator.
    phiT : instance of _PhiT
        The transpose of the TF operator.
    Z_init : None | array
        The initialization of the TF coefficient matrix. If None, zeros
        will be used for all coefficients.
    wsize: int
        length of the STFT window in samples (must be a multiple of 4).
    tstep: int
        step between successive windows in samples (must be a multiple of 2,
        a divider of wsize and smaller than wsize/2) (default: wsize/2).
    n_orient : int
        The number of orientation (1 : fixed or 3 : free or loose).
    maxit : int
        The number of iterations.
    tol : float
        If absolute difference between estimates at 2 successive iterations
        is lower than tol, the convergence is reached.
    log_objective : bool
        If True, the value of the minimized objective function is computed
        and stored at every iteration.
    perc : None | float in [0, 1]
        The early stopping parameter used for BCD with active set approach.
        If the active set size is smaller than perc * n_sources, the
        subproblem limited to the active set is stopped. If None, full
        convergence will be achieved.
    verbose : bool, str, int, or None
        If not None, override default verbose level (see mne.verbose).

    Returns
    -------
    X : array
        The source estimates.
    active_set : array
        The mask of active sources.
    E : list
        The value of the objective function at each iteration. If log_objective
        is False, it will be empty.
    """
    n_sources = G.shape[1]
    n_positions = n_sources // n_orient

    if Z_init is None:
        Z = dict.fromkeys(range(n_positions), 0.0)
        active_set = np.zeros(n_sources, dtype=np.bool)
    else:
        active_set = np.zeros(n_sources, dtype=np.bool)
        active = list()
        for i in range(n_positions):
            if np.any(Z_init[i * n_orient:(i + 1) * n_orient]):
                active_set[i * n_orient:(i + 1) * n_orient] = True
                active.append(i)
        Z = dict.fromkeys(range(n_positions), 0.0)
        if len(active):
            Z.update(dict(zip(active, np.vsplit(Z_init[active_set],
                     len(active)))))

    Z, active_set, E, _ = _tf_mixed_norm_solver_bcd_(
        M, G, Z, active_set, alpha_space, alpha_time, lipschitz_constant,
        phi, phiT, wsize=wsize, tstep=tstep, n_orient=n_orient, maxit=1,
        tol=tol, log_objective=log_objective, perc=None, verbose=verbose)

    while active_set.sum():
        active = np.where(active_set)[0][::n_orient] // n_orient
        Z_init = dict(zip(range(len(active)), [Z[idx] for idx in active]))
        Z, as_, E_tmp, converged = _tf_mixed_norm_solver_bcd_(
            M, G[:, active_set], Z_init,
            np.ones(len(active) * n_orient, dtype=np.bool),
            alpha_space, alpha_time,
            lipschitz_constant[active_set[::n_orient]],
            phi, phiT, wsize=wsize, tstep=tstep, n_orient=n_orient,
            maxit=maxit, tol=tol, log_objective=log_objective,
            perc=0.5, verbose=verbose)
        E += E_tmp
        active = np.where(active_set)[0][::n_orient] // n_orient
        Z_init = dict.fromkeys(range(n_positions), 0.0)
        Z_init.update(dict(zip(active, Z.values())))
        active_set[active_set] = as_
        active_set_0 = active_set.copy()
        Z, active_set, E_tmp, _ = _tf_mixed_norm_solver_bcd_(
            M, G, Z_init, active_set, alpha_space, alpha_time,
            lipschitz_constant, phi, phiT, wsize=wsize, tstep=tstep,
            n_orient=n_orient, maxit=1, tol=tol, log_objective=log_objective,
            perc=None, verbose=verbose)
        E += E_tmp
        if converged:
            if np.array_equal(active_set_0, active_set):
                break

    if active_set.sum():
        Z = np.vstack([Z_ for Z_ in list(Z.values()) if np.any(Z_)])
        X = phiT(Z)
    else:
        n_sensors, n_times = M.shape
        n_step = int(ceil(n_times / float(tstep)))
        n_freq = wsize // 2 + 1
        Z = np.zeros((0, n_step * n_freq), dtype=np.complex)
        X = np.zeros((0, n_times))

    return X, Z, active_set, E
dataset/ETHPy150Open mne-tools/mne-python/mne/inverse_sparse/mxne_optim.py/_tf_mixed_norm_solver_bcd_active_set/original