code: def test_cluster_permutation_with_adjacency(
      numba_conditional, monkeypatch
  ):
      """Test cluster level permutations with adjacency matrix."""
      pytest.importorskip("sklearn")
      from sklearn.feature_extraction.image import grid_to_graph
  
      (
          condition1_1d,
          condition2_1d,
          condition1_2d,
          condition2_2d,
      ) = _get_conditions()
  
      n_pts = condition1_1d.shape[1]
      # we don't care about p-values in any of these, so do fewer permutations
      args = dict(
          seed=None,
          max_step=1,
          exclude=None,
          out_type="mask",
          step_down_p=0,
          t_power=1,
          threshold=1.67,
          check_disjoint=False,
          n_permutations=50,
      )
  
      did_warn = False
      for X1d, X2d, func, spatio_temporal_func in [
          (
              condition1_1d,
              condition1_2d,
              permutation_cluster_1samp_test,
              spatio_temporal_cluster_1samp_test,
          ),
          (
              [condition1_1d, condition2_1d],
              [condition1_2d, condition2_2d],
              permutation_cluster_test,
              spatio_temporal_cluster_test,
          ),
      ]:
          out = func(X1d, **args)
          adjacency = grid_to_graph(1, n_pts)
          out_adjacency = func(X1d, adjacency=adjacency, **args)
          assert_array_equal(out[0], out_adjacency[0])
          for a, b in zip(out_adjacency[1], out[1]):
              assert_array_equal(out[0][a], out[0][b])
              assert np.all(a[b])
  
          # test spatio-temporal w/o time adjacency (repeat spatial pattern)
          adjacency_2 = sparse.coo_matrix(
              linalg.block_diag(
                  adjacency.asfptype().todense(),
                  adjacency.asfptype().todense(),
              )
          )
          # nesting here is time then space:
          adjacency_2a = combine_adjacency(np.eye(2), adjacency)
          assert_array_equal(
              adjacency_2.toarray().astype(bool),
              adjacency_2a.toarray().astype(bool),
          )
  
          if isinstance(X1d, list):
              X1d_2 = [np.concatenate((x, x), axis=1) for x in X1d]
          else:
              X1d_2 = np.concatenate((X1d, X1d), axis=1)
  
          out_adjacency_2 = func(X1d_2, adjacency=adjacency_2, **args)
          # make sure we were operating on the same values
          split = len(out[0])
          assert_array_equal(out[0], out_adjacency_2[0][:split])
          assert_array_equal(out[0], out_adjacency_2[0][split:])
  
          # make sure we really got 2x the number of original clusters
          n_clust_orig = len(out[1])
          assert len(out_adjacency_2[1]) == 2 * n_clust_orig
  
          # Make sure that we got the old ones back
          data_1 = {np.sum(out[0][b[:n_pts]]) for b in out[1]}
          data_2 = {
              np.sum(out_adjacency_2[0][a])
              for a in out_adjacency_2[1][:]
          }
          assert len(data_1.intersection(data_2)) == len(data_1)
  
          # now use the other algorithm
          if isinstance(X1d, list):
              X1d_3 = [np.reshape(x, (-1, 2, n_space)) for x in X1d_2]
          else:
              X1d_3 = np.reshape(X1d_2, (-1, 2, n_space))
  
          out_adjacency_3 = spatio_temporal_func(
              X1d_3,
              n_permutations=50,
              adjacency=adjacency,
              max_step=0,
              threshold=1.67,
              check_disjoint=True,
          )
          # make sure we were operating on the same values
          split = len(out[0])
          assert_array_equal(out[0], out_adjacency_3[0][0])
          assert_array_equal(out[0], out_adjacency_3[0][1])
  
          # make sure we really got 2x the number of original clusters
          assert len(out_adjacency_3[1]) == 2 * n_clust_orig
  
          # Make sure that we got the old ones back
          data_1 = {np.sum(out[0][b[:n_pts]]) for b in out[1]}
          data_2 = {
              np.sum(out_adjacency_3[0][a[0], a[1]])
              for a in out_adjacency_3[1]
          }
          assert len(data_1.intersection(data_2)) == len(data_1)
  
          # test new versus old method
          out_adjacency_4 = spatio_temporal_func(
              X1d_3,
              n_permutations=50,
              adjacency=adjacency,
              max_step=2,
              threshold=1.67,
          )
          out_adjacency_5 = spatio_temporal_func(
              X1d_3,
              n_permutations=50,
              adjacency=adjacency,
              max_step=1,
              threshold=1.67,
          )
  
          # clusters could be in a different order
          sums_4 = [
              np.sum(out_adjacency_4[0][a]) for a in out_adjacency_4[1]
          ]
          sums_5 = [
              np.sum(out_adjacency_4[0][a]) for a in out_adjacency_5[1]
          ]
          sums_4 = np.sort(sums_4)
          sums_5 = np.sort(sums_5)
          assert_array_almost_equal(sums_4, sums_5)
  
          monkeypatch.delenv("MNE_FORCE_SERIAL", raising=False)
          with pytest.raises(ValueError, match="must not be less"):
              spatio_temporal_func(
                  X1d_3,
                  n_permutations=1,
                  adjacency=adjacency,
                  max_step=1,
                  threshold=1.67,
                  n_jobs=-1000,
              )
  
          # not enough TFCE params
          with pytest.raises(
              KeyError, match="threshold, if dict, must have"
          ):
              spatio_temporal_func(
                  X1d_3, adjacency=adjacency, threshold=dict(me="hello")
              )
  
          # too extreme a start threshold
          with _record_warnings() as w:
              spatio_temporal_func(
                  X1d_3,
                  adjacency=adjacency,
                  threshold=dict(start=10, step=1),
              )
          if not did_warn:
              messages = [str(ww.message) for ww in w]
              assert any(
                  "is more extreme" in message for message in messages
              ), messages
              did_warn = True
  
          with pytest.raises(
              ValueError, match="threshold.*<= 0 for tail == -1"
          ):
              spatio_temporal_func(
                  X1d_3,
                  adjacency=adjacency,
                  tail=-1,
                  threshold=dict(start=1, step=-1),
              )
          with pytest.warns(
              RuntimeWarning, match="threshold.* is more extreme"
          ):
              spatio_temporal_func(
                  X1d_3,
                  adjacency=adjacency,
                  tail=1,
                  threshold=dict(start=100, step=1),
              )
          bad_con = adjacency.todense()
          with pytest.raises(
              ValueError, match="must be a SciPy sparse matrix"
          ):
              spatio_temporal_func(
                  X1d_3,
                  n_permutations=50,
                  adjacency=bad_con,
                  max_step=1,
                  threshold=1.67,
              )
          bad_con = adjacency.tocsr()[:-1, :-1].tocoo()
          with pytest.raises(
              ValueError, match="adjacency.*the correct size"
          ):
              spatio_temporal_func(
                  X1d_3,
                  n_permutations=50,
                  adjacency=bad_con,
                  max_step=1,
                  threshold=1.67,
              )
          with pytest.raises(TypeError, match="must be a"):
              spatio_temporal_func(
                  X1d_3, adjacency=adjacency, threshold=[]
              )
          with pytest.raises(
              ValueError, match="Invalid value for the 'tail'"
          ):
              # sometimes ignoring tail
              with _record_warnings():
                  spatio_temporal_func(
                      X1d_3, adjacency=adjacency, tail=2
                  )
  
          # make sure it actually found a significant point
          out_adjacency_6 = spatio_temporal_func(
              X1d_3,
              n_permutations=50,
              adjacency=adjacency,
              max_step=1,
              threshold=dict(start=1, step=1),
          )
          assert np.min(out_adjacency_6[2]) < 0.05
  
          with pytest.raises(ValueError, match="not compatible"):
              with pytest.warns(RuntimeWarning, match="No clusters"):
                  spatio_temporal_func(
                      X1d_3,
                      n_permutations=50,
                      adjacency=adjacency,
                      threshold=1e-3,
                      stat_fun=lambda *x: f_oneway(*x)[:-1],
                      buffer_size=None,
                  )
  
imports: import os
  from functools import partial
  import numpy
  import pytest
  from numpy.testing import assert_allclose, assert_array_almost_equal, assert_array_equal, assert_equal
  from scipy import linalg, sparse, stats
  from mne import MixedSourceEstimate, SourceEstimate, SourceSpaces, VolSourceEstimate
  from mne.stats import combine_adjacency, ttest_ind_no_p
  from mne.stats.cluster_level import f_oneway, permutation_cluster_1samp_test, permutation_cluster_test, spatio_temporal_cluster_1samp_test, spatio_temporal_cluster_test, summarize_clusters_stc, ttest_1samp_no_p
  from mne.utils import _record_warnings, catch_logging
label_desc: Use image node_id 8 for calling a global function with example usage: test_cluster_permutation_with_adjacency(numba_conditional, monkeypatch) without return types