code: def _permuted_ols_on_chunk(
      scores_original_data,
      tested_vars,
      target_vars,
      thread_id,
      threshold=None,
      confounding_vars=None,
      masker=None,
      n_perm=10000,
      n_perm_chunk=10000,
      intercept_test=True,
      two_sided_test=True,
      tfce=False,
      tfce_original_data=None,
      random_state=None,
      verbose=0,
  ):
      """Perform massively univariate analysis with permuted OLS on a data chunk.
  
      To be used in a parallel computing context.
  
      Parameters
      ----------
      scores_original_data : array-like, shape=(n_descriptors, n_regressors)
          t-scores obtained for the original (non-permuted) data.
  
      tested_vars : array-like, shape=(n_samples, n_regressors)
          Explanatory variates.
  
      target_vars : array-like, shape=(n_samples, n_targets)
          fMRI data. F-ordered for efficient computations.
  
      thread_id : int
          process id, used for display.
  
      threshold : :obj:`float`
          Cluster-forming threshold in t-scale.
          This is only used for cluster-level inference.
          If ``threshold`` is not None, but ``masker`` is, an exception will be
          raised.
  
          .. versionadded:: 0.9.2
  
      confounding_vars : array-like, shape=(n_samples, n_covars), optional
          Clinical data (covariates).
  
      masker : None or :class:`~nilearn.maskers.NiftiMasker` or \
              :class:`~nilearn.maskers.MultiNiftiMasker`, optional
          A mask to be used on the data.
          This is used for cluster-level inference and :term:`TFCE`-based
          inference, if either is enabled.
          If ``threshold`` is not None, but ``masker`` is, an exception will be
          raised.
  
          .. versionadded:: 0.9.2
  
      n_perm : int, default=10000
          Total number of permutations to perform, only used for
          display in this function.
  
      n_perm_chunk : int, default=10000
          Number of permutations to be performed.
  
      intercept_test : boolean, default=True
          Change the permutation scheme (swap signs for intercept,
          switch labels otherwise). See :footcite:t:`Fisher1935`.
  
      two_sided_test : boolean, default=True
          If True, performs an unsigned t-test. Both positive and negative
          effects are considered; the null hypothesis is that the effect is zero.
          If False, only positive effects are considered as relevant. The null
          hypothesis is that the effect is zero or negative.
  
      tfce : :obj:`bool`, default=False
          Whether to perform :term:`TFCE`-based multiple comparisons correction
          or not.
          Calculating TFCE values in each permutation can be time-consuming, so
          this option is disabled by default.
          The TFCE calculation is implemented as described in
          :footcite:t:`Smith2009a`.
  
          .. versionadded:: 0.9.2
  
      tfce_original_data : None or array-like, \
              shape=(n_descriptors, n_regressors), optional
          TFCE values obtained for the original (non-permuted) data.
  
          .. versionadded:: 0.9.2
  
      random_state : int or None, optional
          Seed for random number generator, to have the same permutations
          in each computing units.
  
      verbose : int, default=0
          Defines the verbosity level.
  
      Returns
      -------
      scores_as_ranks_part : array-like, shape=(n_regressors, n_descriptors)
          The ranks of the original scores in ``h0_fmax_part``.
          When ``n_descriptors`` or ``n_perm`` are large, it can be quite long to
          find the rank of the original scores into the whole H0 distribution.
          Here, it is performed in parallel by the workers involved in the
          permutation computation.
  
      h0_fmax_part : array-like, shape=(n_perm_chunk, n_regressors)
          Distribution of the (max) t-statistic under the null hypothesis
          (limited to this permutation chunk).
  
      h0_csfwe_part, h0_cmfwe_part : array-like, \
              shape=(n_perm_chunk, n_regressors)
          Distribution of max cluster sizes/masses under the null hypothesis.
          Only calculated if ``masker`` is not None.
          Otherwise, these will both be None.
  
          .. versionadded:: 0.9.2
  
      tfce_scores_as_ranks_part : array-like, shape=(n_regressors, n_descriptors)
          The ranks of the original TFCE values in ``h0_tfce_part``.
          When ``n_descriptors`` or ``n_perm`` are large, it can be quite long to
          find the rank of the original scores into the whole H0 distribution.
          Here, it is performed in parallel by the workers involved in the
          permutation computation.
  
          .. versionadded:: 0.9.2
  
      h0_tfce_part : array-like, shape=(n_perm_chunk, n_regressors)
          Distribution of the (max) TFCE value under the null hypothesis
          (limited to this permutation chunk).
  
          .. versionadded:: 0.9.2
  
      References
      ----------
      .. footbibliography::
  
      """
      # initialize the seed of the random generator
      rng = check_random_state(random_state)
  
      n_samples, n_regressors = tested_vars.shape
      n_descriptors = target_vars.shape[1]
  
      # run the permutations
      t0 = time.time()
      h0_fmax_part = np.empty((n_regressors, n_perm_chunk))
      scores_as_ranks_part = np.zeros((n_regressors, n_descriptors))
  
      # Preallocate null arrays for optional outputs
      # Any unselected outputs will just return a None
      if tfce:
          h0_tfce_part = np.empty((n_regressors, n_perm_chunk))
          tfce_scores_as_ranks_part = np.zeros(
              (n_regressors, n_descriptors)
          )
      else:
          h0_tfce_part, tfce_scores_as_ranks_part = None, None
  
      if threshold is not None:
          h0_csfwe_part = np.empty((n_regressors, n_perm_chunk))
          h0_cmfwe_part = np.empty((n_regressors, n_perm_chunk))
      else:
          h0_csfwe_part, h0_cmfwe_part = None, None
  
      for i_perm in range(n_perm_chunk):
          if intercept_test:
              # sign swap (random multiplication by 1 or -1)
              target_vars = target_vars * (
                  rng.randint(2, size=(n_samples, 1)) * 2 - 1
              )
  
          else:
              # shuffle data
              # Regarding computation costs, we choose to shuffle testvars
              # and covars rather than fmri_signal.
              # Also, it is important to shuffle tested_vars and covars
              # jointly to simplify t-scores computation (null dot product).
              shuffle_idx = rng.permutation(n_samples)
              tested_vars = tested_vars[shuffle_idx]
              if confounding_vars is not None:
                  confounding_vars = confounding_vars[shuffle_idx]
  
          # OLS regression on randomized data
          perm_scores = np.asfortranarray(
              t_score_with_covars_and_normalized_design(
                  tested_vars, target_vars, confounding_vars
              )
          )
  
          # find the rank of the original scores in h0_fmax_part
          # (when n_descriptors or n_perm are large, it can be quite long to
          #  find the rank of the original scores into the whole H0 distribution.
          #  Here, it is performed in parallel by the workers involved in the
          #  permutation computation)
          # NOTE: This is not done for the cluster-level methods.
          if two_sided_test:
              # Get maximum absolute value for voxel-level FWE
              h0_fmax_part[:, i_perm] = np.nanmax(
                  np.fabs(perm_scores), axis=0
              )
              scores_as_ranks_part += (
                  h0_fmax_part[:, i_perm].reshape((-1, 1))
                  < np.fabs(scores_original_data).T
              )
          else:
              # Get maximum value for voxel-level FWE
              h0_fmax_part[:, i_perm] = np.nanmax(perm_scores, axis=0)
              scores_as_ranks_part += (
                  h0_fmax_part[:, i_perm].reshape((-1, 1))
                  < scores_original_data.T
              )
  
          # Prepare data for cluster thresholding
          if tfce or (threshold is not None):
              arr4d = masker.inverse_transform(
                  perm_scores.T
              ).get_fdata()
              bin_struct = generate_binary_structure(3, 1)
  
          if tfce:
              # The TFCE map will contain positive and negative values if
              # two_sided_test is True, or positive only if it's False.
              # In either case, the maximum absolute value is the one we want.
              h0_tfce_part[:, i_perm] = np.nanmax(
                  np.fabs(
                      calculate_tfce(
                          arr4d,
                          bin_struct=bin_struct,
                          two_sided_test=two_sided_test,
                      )
                  ),
                  axis=(0, 1, 2),
              )
              tfce_scores_as_ranks_part += h0_tfce_part[
                  :, i_perm
              ].reshape((-1, 1)) < np.fabs(tfce_original_data.T)
  
          if threshold is not None:
              (
                  h0_csfwe_part[:, i_perm],
                  h0_cmfwe_part[:, i_perm],
              ) = calculate_cluster_measures(
                  arr4d,
                  threshold,
                  bin_struct,
                  two_sided_test=two_sided_test,
              )
  
          if verbose > 0:
              step = 11 - min(verbose, 10)
              if i_perm % step == 0:
                  # If there is only one job, progress information is fixed
                  crlf = "\n"
                  if n_perm == n_perm_chunk:
                      crlf = "\r"
  
                  percent = float(i_perm) / n_perm_chunk
                  percent = round(percent * 100, 2)
                  dt = time.time() - t0
                  remaining = (
                      (100.0 - percent) / max(0.01, percent) * dt
                  )
                  sys.stderr.write(
                      f"Job #{thread_id}, processed {i_perm}/{n_perm_chunk} "
                      f"permutations ({percent:0.2f}%, {remaining} seconds "
                      f"remaining){crlf}"
                  )
  
      return (
          scores_as_ranks_part,
          h0_fmax_part,
          h0_csfwe_part,
          h0_cmfwe_part,
          tfce_scores_as_ranks_part,
          h0_tfce_part,
      )
  
file_path: nilearn/nilearn/mass_univariate/permuted_least_squares.py
imports: import sys
  import time
  import warnings
  import joblib
  import nibabel
  import numpy
  from scipy import stats
  from scipy.ndimage import generate_binary_structure, label
  from sklearn.utils import check_random_state
  from nilearn import image
  from nilearn.masking import apply_mask
  from nilearn.mass_univariate._utils import calculate_cluster_measures, calculate_tfce, normalize_matrix_on_axis, null_to_p, orthonormalize_matrix, t_score_with_covars_and_normalized_design
label_desc: Use image node_id 1 for calling a global function with example usage: _permuted_ols_on_chunk(scores_original_data, tested_vars, target_vars, thread_id, threshold, confounding_vars, masker, n_perm, n_perm_chunk, intercept_test, two_sided_test, tfce, tfce_original_data, random_state, verbose) and returns: scores_as_ranks_part,  h0_fmax_part,  h0_csfwe_part,  h0_cmfwe_part,  tfce_scores_as_ranks_part,  h0_tfce_part