code: def test_ica_additional(method, tmp_path, short_raw_epochs):
      """Test additional ICA functionality."""
      _skip_check_picard(method)
      raw, epochs, epochs_eog = short_raw_epochs
      few_picks = np.arange(5)
  
      # test if n_components=None works
      ica = ICA(n_components=None, method=method, max_iter=1)
      with pytest.warns(UserWarning, match="did not converge"):
          ica.fit(epochs)
      _assert_ica_attributes(
          ica, epochs.get_data("data"), limits=(0.05, 20)
      )
  
      test_cov = read_cov(test_cov_name)
      ica = ICA(noise_cov=test_cov, n_components=3, method=method)
      assert ica.info is None
      with pytest.warns(RuntimeWarning, match="normalize_proj"):
          ica.fit(raw, picks=few_picks)
      _assert_ica_attributes(
          ica, raw.get_data(np.arange(5)), limits=(1, 90)
      )
      assert isinstance(ica.info, Info)
      assert ica.n_components_ < 5
  
      ica = ICA(n_components=3, method=method, max_iter=1)
      with pytest.raises(RuntimeError, match="No fit"):
          ica.save("")
  
      with pytest.warns(Warning, match="converge"):
          ica.fit(raw, np.arange(1, 6))
      _assert_ica_attributes(ica, raw.get_data(np.arange(1, 6)))
  
      # check Kuiper index threshold
      assert_allclose(ica._get_ctps_threshold(), 0.5)
      with pytest.raises(TypeError, match="str or numeric"):
          ica.find_bads_ecg(raw, threshold=None)
      with pytest.warns(
          RuntimeWarning, match="is longer than the signal"
      ):
          ica.find_bads_ecg(raw, threshold=0.25)
      # check invalid measure argument
      with pytest.raises(ValueError, match="Invalid value"):
          ica.find_bads_ecg(
              raw,
              method="correlation",
              measure="unknown",
              threshold="auto",
          )
      # check passing a ch_name to find_bads_ecg
      with pytest.warns(RuntimeWarning, match="longer"):
          _, scores_1 = ica.find_bads_ecg(raw, threshold="auto")
      with pytest.warns(RuntimeWarning, match="longer"):
          _, scores_2 = ica.find_bads_ecg(
              raw, raw.ch_names[1], threshold="auto"
          )
      assert scores_1[0] != scores_2[0]
  
      # test corrmap
      ica2 = ica.copy()
      ica3 = ica.copy()
      corrmap(
          [ica, ica2],
          (0, 0),
          threshold="auto",
          label="blinks",
          plot=True,
          ch_type="mag",
      )
      with pytest.raises(RuntimeError, match="No component detected"):
          corrmap(
              [ica, ica2],
              (0, 0),
              threshold=2,
              plot=False,
              show=False,
          )
      with catch_logging(True) as log:
          corrmap(
              [ica, ica2], (0, 0), threshold=0.5, plot=False, show=False
          )
      log = log.getvalue()
      assert "Median correlation with constructed map: 1.0" in log
      assert ica.labels_["blinks"] == ica2.labels_["blinks"]
      assert 0 in ica.labels_["blinks"]
      # test retrieval of component maps as arrays
      components = ica.get_components()
      template = components[:, 0]
      EvokedArray(components, ica.info, tmin=0.0).plot_topomap(
          [0], time_unit="s"
      )
  
      corrmap(
          [ica, ica3],
          template,
          threshold="auto",
          label="blinks",
          plot=True,
          ch_type="mag",
      )
      assert ica2.labels_["blinks"] == ica3.labels_["blinks"]
  
      plt.close("all")
  
      # No match
      bad_ica = ica2.copy()
      bad_ica.mixing_matrix_[:] = 0.0
      with pytest.warns(RuntimeWarning, match="divide"):
          with catch_logging() as log:
              corrmap(
                  [ica, bad_ica],
                  (0, 0),
                  threshold=0.5,
                  plot=False,
                  show=False,
                  verbose=True,
              )
      log = log.getvalue()
      assert "No maps selected" in log
  
      # make sure a single threshold in a list works
      corrmap(
          [ica, ica3],
          template,
          threshold=[0.5],
          label="blinks",
          plot=False,
          ch_type="mag",
      )
  
      ica_different_channels = ICA(n_components=2, max_iter=1)
      with pytest.warns(Warning, match="converge"):
          ica_different_channels.fit(raw, picks=[2, 3, 4, 5])
      with pytest.raises(
          ValueError, match="Not all ICA instances have the"
      ):
          corrmap([ica_different_channels, ica], (0, 0))
  
      # test warnings on bad filenames
      ica_badname = tmp_path / "test-bad-name.fif.gz"
      with pytest.warns(RuntimeWarning, match="-ica.fif"):
          ica.save(ica_badname)
      with pytest.warns(RuntimeWarning, match="-ica.fif"):
          read_ica(ica_badname)
  
      # test decim
      ica = ICA(n_components=3, method=method, max_iter=1)
      raw_ = raw.copy()
      for _ in range(3):
          raw_.append(raw_)
      n_samples = raw_._data.shape[1]
      with pytest.warns(UserWarning, match="did not converge"):
          ica.fit(raw, picks=few_picks)
      _assert_ica_attributes(ica)
      assert raw_._data.shape[1] == n_samples
  
      # test expl var
      with pytest.raises(ValueError, match=r".*1.0 \(exclusive\).*"):
          ICA(n_components=1.0, method=method)
      with pytest.raises(ValueError, match="Selecting one component"):
          ICA(n_components=1, method=method)
      ica = ICA(n_components=4, method=method, max_iter=1)
      with pytest.warns(UserWarning, match="did not converge"):
          ica.fit(raw)
      _assert_ica_attributes(ica)
      assert ica.n_components_ == 4
      ica_var = _ica_explained_variance(ica, raw, normalize=True)
      assert np.all(ica_var[:-1] >= ica_var[1:])
  
      # test ica sorting
      ica.exclude = [0]
      ica.labels_ = dict(blink=[0], think=[1])
      ica_sorted = _sort_components(ica, [3, 2, 1, 0], copy=True)
      assert_equal(ica_sorted.exclude, [3])
      assert_equal(ica_sorted.labels_, dict(blink=[3], think=[2]))
  
      # epochs extraction from raw fit
      with pytest.raises(ValueError, match="not present in the info"):
          ica.get_sources(epochs)
  
      # test filtering
      ica_raw = ica.get_sources(raw)
      d1 = ica_raw._data[0].copy()
      ica_raw.filter(4, 20, fir_design="firwin2")
      assert_equal(ica_raw.info["lowpass"], 20.0)
      assert_equal(ica_raw.info["highpass"], 4.0)
      assert (d1 != ica_raw._data[0]).any()
      d1 = ica_raw._data[0].copy()
      ica_raw.notch_filter(
          [10], trans_bandwidth=10, fir_design="firwin"
      )
      assert (d1 != ica_raw._data[0]).any()
  
      test_ica_fname = tmp_path / "test-ica.fif"
      ica.n_pca_components = 2
      ica.method = "fake"
      ica.save(test_ica_fname)
      ica_read = read_ica(test_ica_fname)
      assert ica.n_pca_components == ica_read.n_pca_components
      assert_equal(ica.method, ica_read.method)
      assert_equal(ica.labels_, ica_read.labels_)
  
      # check type consistency
      attrs = (
          "mixing_matrix_ unmixing_matrix_ pca_components_ "
          "pca_explained_variance_ pre_whitener_"
      )
  
      def f(x, y):
          return getattr(x, y).dtype
  
      for attr in attrs.split():
          assert_equal(f(ica_read, attr), f(ica, attr))
  
      ica.n_pca_components = 4
      ica_read.n_pca_components = 4
  
      ica.exclude = []
      ica.save(test_ica_fname, overwrite=True)  # also testing overwrite
      ica_read = read_ica(test_ica_fname)
      for attr in [
          "mixing_matrix_",
          "unmixing_matrix_",
          "pca_components_",
          "pca_mean_",
          "pca_explained_variance_",
          "pre_whitener_",
      ]:
          assert_array_almost_equal(
              getattr(ica, attr), getattr(ica_read, attr)
          )
  
      assert ica.ch_names == ica_read.ch_names
      assert isinstance(ica_read.info, Info)
  
      sources = ica.get_sources(raw)[:, :][0]
      sources2 = ica_read.get_sources(raw)[:, :][0]
      assert_array_almost_equal(sources, sources2)
  
      _raw1 = ica.apply(raw.copy(), exclude=[1])
      _raw2 = ica_read.apply(raw.copy(), exclude=[1])
      assert_array_almost_equal(_raw1[:, :][0], _raw2[:, :][0])
  
      ica = ICA(n_components=2, method=method, max_iter=1)
      with _record_warnings():  # ICA does not converge
          ica.fit(raw, picks=few_picks)
  
      # check score funcs
      for name, func in get_score_funcs().items():
          if name in score_funcs_unsuited:
              continue
          scores = ica.score_sources(
              raw, target="EOG 061", score_func=func, start=0, stop=10
          )
          assert ica.n_components_ == len(scores)
  
      # check univariate stats
      scores = ica.score_sources(
          raw, start=0, stop=50, score_func=stats.skew
      )
      # check exception handling
      with pytest.raises(
          ValueError, match="Sources and target do not have"
      ):
          ica.score_sources(raw, target=np.arange(1))
  
      evoked = epochs.average()
      evoked_data = evoked.data.copy()
      raw_data = raw[:][0].copy()
      epochs_data = epochs.get_data(copy=True)
  
      with pytest.warns(RuntimeWarning, match="longer"):
          idx, scores = ica.find_bads_ecg(
              raw,
              method="ctps",
              threshold="auto",
              start=0,
              stop=raw.times.size,
          )
      assert_equal(len(scores), ica.n_components_)
      with pytest.warns(RuntimeWarning, match="longer"):
          idx, scores = ica.find_bads_ecg(
              raw, method="correlation", threshold="auto"
          )
      assert_equal(len(scores), ica.n_components_)
  
      with pytest.warns(RuntimeWarning, match="longer"):
          idx, scores = ica.find_bads_eog(raw)
      assert_equal(len(scores), ica.n_components_)
  
      with pytest.raises(ValueError, match="integer .* start and stop"):
          idx, scores = ica.find_bads_ecg(epochs, start=0, stop=1000)
  
      idx, scores = ica.find_bads_ecg(
          epochs,
          method="ctps",
          threshold="auto",
          start=epochs.times[0],
          stop=epochs.times[-1],
      )
  
      assert_equal(len(scores), ica.n_components_)
      with pytest.raises(ValueError, match="only Raw and Epochs input"):
          ica.find_bads_ecg(
              epochs.average(), method="ctps", threshold="auto"
          )
      with pytest.raises(ValueError, match="Invalid value"):
          ica.find_bads_ecg(raw, method="crazy-coupling")
  
      with pytest.warns(RuntimeWarning, match="longer"):
          idx, scores = ica.find_bads_eog(raw)
      assert_equal(len(scores), ica.n_components_)
  
      raw.info["chs"][raw.ch_names.index("EOG 061") - 1]["kind"] = 202
      with pytest.warns(RuntimeWarning, match="longer"):
          idx, scores = ica.find_bads_eog(raw)
      assert isinstance(scores, list)
      assert_equal(len(scores[0]), ica.n_components_)
  
      idx, scores = ica.find_bads_eog(evoked, ch_name="MEG 1441")
      assert_equal(len(scores), ica.n_components_)
  
      with pytest.raises(ValueError, match="integer .* start and stop"):
          idx, scores = ica.find_bads_ecg(evoked, start=0, stop=1000)
  
      idx, scores = ica.find_bads_ecg(
          evoked, method="correlation", threshold="auto"
      )
      assert_equal(len(scores), ica.n_components_)
  
      assert_array_equal(raw_data, raw[:][0])
      assert_array_equal(epochs_data, epochs.get_data(copy=False))
      assert_array_equal(evoked_data, evoked.data)
  
      # check score funcs
      for name, func in get_score_funcs().items():
          if name in score_funcs_unsuited:
              continue
          scores = ica.score_sources(
              epochs_eog, target="EOG 061", score_func=func
          )
          assert ica.n_components_ == len(scores)
  
      # check univariate stats
      scores = ica.score_sources(epochs, score_func=stats.skew)
  
      # check exception handling
      with pytest.raises(
          ValueError, match="Sources and target do not have"
      ):
          ica.score_sources(epochs, target=np.arange(1))
  
      # ecg functionality
      ecg_scores = ica.score_sources(
          raw, target="MEG 1531", score_func="pearsonr"
      )
  
      with pytest.warns(RuntimeWarning, match="longer"):
          ecg_events = ica_find_ecg_events(
              raw, sources[np.abs(ecg_scores).argmax()]
          )
      assert ecg_events.ndim == 2
  
      # eog functionality
      eog_scores = ica.score_sources(
          raw, target="EOG 061", score_func="pearsonr"
      )
      with pytest.warns(RuntimeWarning, match="longer"):
          eog_events = ica_find_eog_events(
              raw, sources[np.abs(eog_scores).argmax()]
          )
      assert eog_events.ndim == 2
  
      # Test ica fiff export
      assert raw.last_samp - raw.first_samp + 1 == raw.n_times
      assert raw.n_times > 100
      ica_raw = ica.get_sources(raw, start=100, stop=200)
      assert ica_raw.first_samp == raw.first_samp + 100
      assert ica_raw.n_times == 100
      assert ica_raw.last_samp - ica_raw.first_samp + 1 == 100
      assert ica_raw._data.shape[1] == 100
      assert_equal(len(ica_raw._filenames), 1)  # API consistency
      ica_chans = [ch for ch in ica_raw.ch_names if "ICA" in ch]
      assert ica.n_components_ == len(ica_chans)
      test_ica_fname = Path.cwd() / "test-ica_raw.fif"
      ica.n_components = np.int32(ica.n_components)
      ica_raw.save(test_ica_fname, overwrite=True)
      ica_raw2 = read_raw_fif(test_ica_fname, preload=True)
      assert_allclose(
          ica_raw._data, ica_raw2._data, rtol=1e-5, atol=1e-4
      )
      ica_raw2.close()
      os.remove(test_ica_fname)
  
      # Test ica epochs export
      ica_epochs = ica.get_sources(epochs)
      assert ica_epochs.events.shape == epochs.events.shape
      ica_chans = [ch for ch in ica_epochs.ch_names if "ICA" in ch]
      assert ica.n_components_ == len(ica_chans)
      assert (
          ica.n_components_ == ica_epochs.get_data(copy=False).shape[1]
      )
      assert ica_epochs._raw is None
      assert ica_epochs.preload is True
  
      # test float n pca components
      ica.pca_explained_variance_ = np.array([0.2] * 5)
      ica.n_components_ = 0
      for ncomps, expected in [[0.3, 2], [0.9, 5], [1, 1]]:
          ncomps_ = ica._check_n_pca_components(ncomps)
          assert ncomps_ == expected
  
      ica = ICA(method=method)
      with _record_warnings():  # sometimes does not converge
          ica.fit(raw, picks=few_picks)
      _assert_ica_attributes(ica, raw.get_data(few_picks))
      with pytest.warns(RuntimeWarning, match="longer"):
          ica.find_bads_ecg(raw, threshold="auto")
      ica.find_bads_eog(epochs, ch_name="MEG 0121")
      assert_array_equal(raw_data, raw[:][0])
  
      raw.drop_channels(raw.ch_names[:2])
      with pytest.raises(ValueError, match="not present in the info"):
          ica.find_bads_eog(raw)
      with pytest.raises(ValueError, match="not present in the info"):
          with pytest.warns(RuntimeWarning, match="longer"):
              ica.find_bads_ecg(raw, threshold="auto")
  
      # test passing picks including the marked bad channels
      raw_ = raw.copy()
      raw_.pick("eeg")
      raw_.info["bads"] = [raw_.ch_names[0]]
      picks = pick_types(raw_.info, eeg=True, exclude=[])
      ica = ICA(n_components=0.99, max_iter="auto")
      ica.fit(raw_, picks=picks, reject_by_annotation=True)
  
imports: import os
  import shutil
  from contextlib import nullcontext
  from pathlib import Path
  import matplotlib.pyplot
  import numpy
  import pytest
  from numpy.testing import assert_allclose, assert_array_almost_equal, assert_array_equal, assert_equal
  from scipy import linalg, stats
  from scipy.io import loadmat, savemat
  from mne import Annotations, Epochs, EpochsArray, EvokedArray, Info, create_info, make_ad_hoc_cov, pick_channels_regexp, pick_types, read_events
  from mne._fiff.pick import _DATA_CH_TYPES_SPLIT, get_channel_type_constants
  from mne.cov import read_cov
  from mne.datasets import testing
  from mne.event import make_fixed_length_events
  from mne.io import RawArray, read_raw_ctf, read_raw_eeglab, read_raw_fif
  from mne.io.eeglab.eeglab import _check_load_mat
  from mne.preprocessing import ICA
  from mne.preprocessing import ica_find_ecg_events, ica_find_eog_events, read_ica
  from mne.preprocessing.ica import _ica_explained_variance, _sort_components, corrmap, get_score_funcs, read_ica_eeglab
  from mne.rank import _compute_rank_int
  from mne.utils import _record_warnings, catch_logging, check_version
label_desc: Use image node_id 14 for calling a global function with example usage: test_ica_additional(method, tmp_path, short_raw_epochs) and returns: getattr