code: def generate_fake_fmri(
      shape=(10, 11, 12),
      length=17,
      kind="noise",
      affine=np.eye(4),
      n_blocks=None,
      block_size=None,
      block_type="classification",
      random_state=0,
  ):
      """Generate a signal which can be used for testing.
  
      The return value is a 4D image, representing 3D volumes along time.
      Only the voxels in the center are non-zero, to mimic the presence of
      brain voxels in real signals. Setting n_blocks to an integer generates
      condition blocks, the remaining of the timeseries corresponding
      to 'rest' or 'baseline' condition.
  
      Parameters
      ----------
      shape : :obj:`tuple`, default=(10, 11, 12)
          Shape of 3D volume.
  
      length : :obj:`int`, default=17
          Number of time instants.
  
      kind : :obj:`str`, default='noise'
          Kind of signal used as timeseries.
          "noise": uniformly sampled values in [0..255]
          "step": 0.5 for the first half then 1.
  
      affine : :obj:`numpy.ndarray`, default=np.eye(4)
          Affine of returned images.
  
      n_blocks : :obj:`int` or None, default=None
          Number of condition blocks.
  
      block_size : :obj:`int` or None, default=None
          Number of timepoints in a block.
          Used only if n_blocks is not None.
          Defaults to 3 if n_blocks is None.
  
      block_type : :obj:`str`, default='classification'
          Defines if the returned target should be used for
          'classification' or 'regression'.
  
      random_state : :obj:`int` or :obj:`numpy.random.RandomState` instance, \
                     default=0
          Random number generator, or seed.
  
      Returns
      -------
      Niimg-like object
          Fake fmri signal.
          shape: shape + (length,)
  
      Niimg-like object
          Mask giving non-zero voxels.
  
      target : :obj:`numpy.ndarray`
          Classification or regression target.
          A 1D array with one element for each time point.
          Returned only if ``n_blocks`` is not None.
  
      """
      full_shape = shape + (length,)
      fmri = np.zeros(full_shape)
      # Fill central voxels timeseries with random signals
      width = [s // 2 for s in shape]
      shift = [s // 4 for s in shape]
  
      rand_gen = np.random.default_rng(random_state)
      if kind == "noise":
          signals = rand_gen.integers(256, size=(width + [length]))
      elif kind == "step":
          signals = np.ones(width + [length])
          signals[..., : length // 2] = 0.5
      else:
          raise ValueError("Unhandled value for parameter 'kind'")
  
      fmri[
          shift[0] : shift[0] + width[0],
          shift[1] : shift[1] + width[1],
          shift[2] : shift[2] + width[2],
          :,
      ] = signals
  
      mask = np.zeros(shape)
      mask[
          shift[0] : shift[0] + width[0],
          shift[1] : shift[1] + width[1],
          shift[2] : shift[2] + width[2],
      ] = 1
  
      if n_blocks is None:
          return (Nifti1Image(fmri, affine), Nifti1Image(mask, affine))
  
      block_size = 3 if block_size is None else block_size
      flat_fmri = fmri[mask.astype(bool)]
      flat_fmri /= np.abs(flat_fmri).max()
      target = np.zeros(length, dtype=int)
      rest_max_size = (length - (n_blocks * block_size)) // n_blocks
      if rest_max_size < 0:
          raise ValueError(
              f"{length} is too small "
              f"to put {n_blocks} blocks of size {block_size}"
          )
      t_start = 0
      if rest_max_size > 0:
          t_start = rand_gen.integers(0, rest_max_size, 1)[0]
      for block in range(n_blocks):
          if block_type == "classification":
              # Select a random voxel and add some signal to the background
              voxel_idx = rand_gen.integers(0, flat_fmri.shape[0], 1)[0]
              trials_effect = (rand_gen.random(block_size) + 1) * 3.0
          else:
              # Select the voxel in the image center and add some signal
              # that increases with each block
              voxel_idx = flat_fmri.shape[0] // 2
              trials_effect = (rand_gen.random(block_size) + 1) * block
          t_rest = 0
          if rest_max_size > 0:
              t_rest = rand_gen.integers(0, rest_max_size, 1)[0]
          flat_fmri[
              voxel_idx, t_start : t_start + block_size
          ] += trials_effect
          target[t_start : t_start + block_size] = block + 1
          t_start += t_rest + block_size
      target = (
          target
          if block_type == "classification"
          else target.astype(np.float64)
      )
      fmri = np.zeros(fmri.shape)
      fmri[mask.astype(bool)] = flat_fmri
      return (
          Nifti1Image(fmri, affine),
          Nifti1Image(mask, affine),
          target,
      )
  
imports: from __future__ import annotations
  import itertools
  import json
  import string
  from pathlib import Path
  import numpy
  import pandas
  import scipy.linalg
  import scipy.signal
  from nibabel import Nifti1Image
  from scipy.ndimage import binary_dilation
  from nilearn import datasets, image, maskers, masking
  from nilearn._utils import as_ndarray, logger
  from nilearn.interfaces.bids.utils import bids_entities, check_bids_label, create_bids_filename
  from nilearn.interfaces.fmriprep.tests._testing import get_legal_confound
label_desc: Use image node_id 6 for calling a global function with example usage: generate_fake_fmri(shape, length, kind, affine, n_blocks, block_size, block_type, random_state) and returns: Nifti1Image,  Nifti1Image,  target, Nifti1Image,  Nifti1Image