code: def generate_noise(
      dimensions,
      stimfunction_tr,
      tr_duration,
      template,
      mask=None,
      noise_dict=None,
      temporal_proportion=0.5,
      iterations=None,
      fit_thresh=0.05,
      fit_delta=0.5,
  ):
      """Generate the noise to be added to the signal.
      Default noise parameters will create a noise volume with a standard
      deviation of 0.1 (where the signal defaults to a value of 1). This has
      built into estimates of how different types of noise mix. All noise
      values can be set by the user or estimated with calc_noise.
  
      Parameters
      ----------
  
      dimensions : nd array
          What is the shape of the volume to be generated
  
      stimfunction_tr :  Iterable, list
          When do the stimuli events occur. Each element is a TR
  
      tr_duration : float
          What is the duration, in seconds, of each TR?
  
      template : 3d array, float
          A continuous (0 -> 1) volume describing the likelihood a voxel is in
          the brain. This can be used to contrast the brain and non brain.
  
      mask : 3d array, binary
          The mask of the brain volume, distinguishing brain from non-brain
  
      noise_dict : dict
          A dictionary specifying the types of noise in this experiment. The
          noise types interact in important ways. First, autoregressive,
          physiological and task-based noise types are mixed together in
          _generate_temporal_noise. The parameter values for 'auto_reg_sigma',
          'physiological_sigma' and 'task_sigma' describe the proportion of
          mixing of these elements, respectively. However critically, 'SFNR' is
          the parameter that controls how much noise these components contribute
          to the brain. 'auto_reg_rho' and 'ma_rho' set parameters for the
          autoregressive noise being simulated. Second, drift noise is added to
          this, according to the size of 'drift_sigma'. Thirdly, system noise is
          added based on the 'SNR' parameter. Finally, 'fwhm' is used to estimate
          the smoothness of the noise being inserted. If 'matched' is set to
          true, then it will fit the parameters to match the participant as best
          as possible.
  
          Variables defined as follows:
  
          snr [float]: Ratio of MR signal to the spatial noise
          sfnr [float]: Ratio of the MR signal to the temporal noise. This is the
          total variability that the following sigmas 'sum' to:
  
          task_sigma [float]: Size of the variance of task specific noise
          auto_reg_sigma [float]: Size of the variance of autoregressive
          noise. This is an ARMA process where the AR and MA components can be
          separately specified
          physiological_sigma [float]: Size of the variance of physiological
          noise
  
          drift_sigma [float]: Size of the variance of drift noise
  
          auto_reg_rho [list]: The coefficients of the autoregressive
          components you are modeling
          ma_rho [list]:The coefficients of the moving average components you
          are modeling
          max_activity [float]: The max value of the averaged brain in order
          to reference the template
          voxel_size [list]: The mm size of the voxels
          fwhm [float]: The gaussian smoothing kernel size (mm)
          matched [bool]: Specify whether you are fitting the noise parameters
  
          The volumes of brain noise that are generated have smoothness
          specified by 'fwhm'
  
      temporal_proportion, float
          What is the proportion of the temporal variance (as specified by the
          SFNR noise parameter) that is accounted for by the system noise. If
          this number is high then all of the temporal variability is due to
          system noise, if it is low then all of the temporal variability is
          due to brain variability.
  
      iterations : list, int
          The first element is how many steps of fitting the SFNR and SNR values
          will be performed. Usually converges after < 5. The second element
          is the number of iterations for the AR fitting. This is much more
          time consuming (has to make a new timecourse on each iteration) so
          be careful about setting this appropriately.
  
      fit_thresh : float
          What proportion of the target parameter value is sufficient error to
          warrant finishing fit search.
  
      fit_delta : float
          How much are the parameters attenuated during the fitting process,
          in terms of the proportion of difference between the target
          parameter and the actual parameter
  
  
      Returns
      ----------
  
      noise : multidimensional array, float
          Generates the noise volume for these parameters
  
      """
  
      # Check the input data
      if template.max() > 1.1:
          raise ValueError("Template out of range")
  
      # Change to be an empty dictionary if it is None
      if noise_dict is None:
          noise_dict = {}
  
      # Take in the noise dictionary and add any missing information
      noise_dict = _noise_dict_update(noise_dict)
  
      # How many iterations will you perform? If unspecified it will set
      # values based on whether you are trying to match noise specifically to
      # this participant or just get in the ball park
      if iterations is None:
          if noise_dict["matched"] == 1:
              iterations = [20, 20]
          else:
              iterations = [0, 0]
  
      if (
          abs(noise_dict["auto_reg_rho"][0])
          - abs(noise_dict["ma_rho"][0])
          < 0.1
      ):
          logger.warning(
              "ARMA coefs are close, may have trouble fitting"
          )
  
      # What are the dimensions of the volume, including time
      dimensions_tr = (
          dimensions[0],
          dimensions[1],
          dimensions[2],
          len(stimfunction_tr),
      )
  
      # Get the mask of the brain and set it to be 3d
      if mask is None:
          mask = np.ones(dimensions)
  
      # Create the base (this inverts the process to make the template)
      base = template * noise_dict["max_activity"]
  
      # Reshape the base (to be the same size as the volume to be created)
      base = base.reshape(
          dimensions[0], dimensions[1], dimensions[2], 1
      )
      base = np.ones(dimensions_tr) * base
  
      # What is the mean signal of the non masked voxels in this template?
      mean_signal = (base[mask > 0]).mean()
  
      # Generate the temporal noise
      noise_temporal = _generate_noise_temporal(
          stimfunction_tr=stimfunction_tr,
          tr_duration=tr_duration,
          dimensions=dimensions,
          template=template,
          mask=mask,
          noise_dict=noise_dict,
      )
  
      # Generate the drift noise
      if noise_dict["drift_sigma"] != 0:
          # Calculate the drift time course
          noise = _generate_noise_temporal_drift(
              len(stimfunction_tr),
              tr_duration,
          )
          # Create a volume with the drift properties
          volume = np.ones(dimensions[:3])
  
          # Combine the volume and noise
          drift_noise = (
              np.multiply.outer(volume, noise)
              * noise_dict["drift_sigma"]
          )
      else:
          # If there is no drift, then just make this zeros (in 4d)
          drift_noise = np.zeros(dimensions_tr)
  
      # Convert SFNR into the size of the standard deviation of temporal
      # variability
      temporal_sd = mean_signal / noise_dict["sfnr"]
  
      # Calculate the temporal sd of the system noise (as opposed to the noise
      #  attributed to the functional variability).
      temporal_sd_system = np.sqrt(
          (temporal_sd**2) * temporal_proportion
      )
  
      # What is the standard deviation of the background activity
      spat_sd = mean_signal / noise_dict["snr"]
      spatial_sd = np.sqrt((spat_sd**2) * (1 - temporal_proportion))
  
      # Set up the machine noise
      noise_system = _generate_noise_system(
          dimensions_tr=dimensions_tr,
          spatial_sd=spatial_sd,
          temporal_sd=temporal_sd_system,
      )
  
      # Sum up the noise of the brain
      noise = base + drift_noise + noise_system
      noise += (
          noise_temporal * temporal_sd
      )  # Add the brain specific noise
  
      # Reject negative values (only happens outside of the brain)
      noise[noise < 0] = 0
  
      # Fit the SNR
      noise, spatial_sd = _fit_spatial(
          noise,
          noise_temporal,
          drift_noise,
          mask,
          template,
          spatial_sd,
          temporal_sd_system,
          noise_dict,
          fit_thresh,
          fit_delta,
          iterations[0],
      )
  
      # Fit the SFNR and AR noise
      noise = _fit_temporal(
          noise,
          mask,
          template,
          stimfunction_tr,
          tr_duration,
          spatial_sd,
          temporal_proportion,
          temporal_sd,
          drift_noise,
          noise_dict,
          fit_thresh,
          fit_delta,
          iterations[1],
      )
  
      # Return the noise
      return noise
  
imports: import logging
  from itertools import product
  from statsmodels.tsa.arima.model import ARIMA
  import math
  import numpy
  from numpy.linalg import LinAlgError
  from pkg_resources import resource_stream
  from scipy import stats
  from scipy import signal
  import scipy.ndimage
  import copy
  from scipy import optimize
label_desc: Use image node_id 26 for calling a global function with example usage: generate_noise(dimensions, stimfunction_tr, tr_duration, template, mask, noise_dict, temporal_proportion, iterations, fit_thresh, fit_delta) and returns: noise