code: def _fit_spatial(
      noise,
      noise_temporal,
      drift_noise,
      mask,
      template,
      spatial_sd,
      temporal_sd,
      noise_dict,
      fit_thresh,
      fit_delta,
      iterations,
  ):
      """
      Fit the noise model to match the SNR of the data
  
      Parameters
      ----------
  
      noise : multidimensional array, float
          Initial estimate of the noise
  
      noise_temporal : multidimensional array, float
          The temporal noise that was generated by _generate_temporal_noise
  
      drift_noise : multidimensional array, float
          The drift noise generated by _generate_noise_temporal_drift
  
      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
  
      spatial_sd : float
          What is the standard deviation in space of the noise volume to be
          generated
  
      temporal_sd : float
          What is the standard deviation in time of the noise volume to be
          generated
  
      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'
  
      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
  
      iterations : 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.
  
      Returns
      -------
  
      noise : multidimensional array, float
          Generates the noise volume given these parameters
  
      """
  
      # Pull out information that is needed
      dim_tr = noise.shape
      base = template * noise_dict["max_activity"]
      base = base.reshape(dim_tr[0], dim_tr[1], dim_tr[2], 1)
      mean_signal = (base[mask > 0]).mean()
      target_snr = noise_dict["snr"]
  
      # Iterate through different parameters to fit SNR and SFNR
      spat_sd_orig = np.copy(spatial_sd)
      iteration = 0
      for iteration in list(range(iterations)):
          # Calculate the new metrics
          new_snr = _calc_snr(noise, mask)
  
          # Calculate the difference between the real and simulated data
          diff_snr = abs(new_snr - target_snr) / target_snr
  
          # If the AR is sufficiently close then break the loop
          if diff_snr < fit_thresh:
              logger.info(
                  "Terminated SNR fit after "
                  + str(iteration)
                  + " iterations."
              )
              break
  
          # Convert the SFNR and SNR
          spat_sd_new = mean_signal / new_snr
  
          # Update the variable
          spatial_sd -= (spat_sd_new - spat_sd_orig) * fit_delta
  
          # Prevent these going out of range
          if spatial_sd < 0 or np.isnan(spatial_sd):
              spatial_sd = 10e-3
  
          # Set up the machine noise
          noise_system = _generate_noise_system(
              dimensions_tr=dim_tr,
              spatial_sd=spatial_sd,
              temporal_sd=temporal_sd,
          )
  
          # 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
  
      # Failed to converge
      if iterations == 0:
          logger.info("No fitting iterations were run")
      elif iteration == iterations:
          logger.warning("SNR failed to converge.")
  
      # Return the updated noise
      return noise, spatial_sd
  
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 24 for calling a global function with example usage: _fit_spatial(noise, noise_temporal, drift_noise, mask, template, spatial_sd, temporal_sd, noise_dict, fit_thresh, fit_delta, iterations) and returns: noise,  spatial_sd