code: def test_dgapl21l1():
      """Test duality gap for L21 + L1 regularization."""
      n_orient = 2
      M, G, active_set = _generate_tf_data()
      n_times = M.shape[1]
      n_sources = G.shape[1]
      tstep, wsize = np.array([4, 2]), np.array([64, 16])
      n_steps = np.ceil(n_times / tstep.astype(float)).astype(int)
      n_freqs = wsize // 2 + 1
      n_coefs = n_steps * n_freqs
      phi = _Phi(wsize, tstep, n_coefs, n_times)
      phiT = _PhiT(tstep, n_freqs, n_steps, n_times)
  
      for l1_ratio in [0.05, 0.1]:
          alpha_max = norm_epsilon_inf(G, M, phi, l1_ratio, n_orient)
          alpha_space = (1.0 - l1_ratio) * alpha_max
          alpha_time = l1_ratio * alpha_max
  
          Z = np.zeros([n_sources, phi.n_coefs.sum()])
          # for alpha = alpha_max, Z = 0 is the solution so the dgap is 0
          gap = dgap_l21l1(
              M,
              G,
              Z,
              np.ones(n_sources, dtype=bool),
              alpha_space,
              alpha_time,
              phi,
              phiT,
              n_orient,
              -np.inf,
          )[0]
  
          assert_allclose(0.0, gap)
          # check that solution for alpha smaller than alpha_max is non 0:
          X_hat_tf, active_set_hat_tf, E, gap = tf_mixed_norm_solver(
              M,
              G,
              alpha_space / 1.01,
              alpha_time / 1.01,
              maxit=200,
              tol=1e-8,
              verbose=True,
              debias=False,
              n_orient=n_orient,
              tstep=tstep,
              wsize=wsize,
              return_gap=True,
          )
          # allow possible small numerical errors (negative gap)
          assert_array_less(-1e-10, gap)
          assert_array_less(gap, 1e-8)
          assert_array_less(1, len(active_set_hat_tf))
  
          X_hat_tf, active_set_hat_tf, E, gap = tf_mixed_norm_solver(
              M,
              G,
              alpha_space / 5.0,
              alpha_time / 5.0,
              maxit=200,
              tol=1e-8,
              verbose=True,
              debias=False,
              n_orient=n_orient,
              tstep=tstep,
              wsize=wsize,
              return_gap=True,
          )
          assert_array_less(-1e-10, gap)
          assert_array_less(gap, 1e-8)
          assert_array_less(1, len(active_set_hat_tf))
  
file_path: mne-python/mne/inverse_sparse/tests/test_mxne_optim.py
imports: import numpy
  import pytest
  from numpy.testing import assert_allclose, assert_array_almost_equal, assert_array_equal, assert_array_less
  from mne.inverse_sparse.mxne_optim import _Phi, _PhiT, dgap_l21l1, iterative_mixed_norm_solver, iterative_tf_mixed_norm_solver, mixed_norm_solver, norm_epsilon, norm_epsilon_inf, tf_mixed_norm_solver
  from mne.time_frequency._stft import stft_norm2
  from mne.utils import _record_warnings, catch_logging
label_desc: Use image node_id 6 for calling a global function with example usage: test_dgapl21l1() without return types