code: def calc_noise(
      volume,
      mask,
      template,
      noise_dict=None,
  ):
      """Calculates the noise properties of the volume supplied.
      This estimates what noise properties the volume has. For instance it
      determines the spatial smoothness, the autoregressive noise, system
      noise etc. Read the doc string for generate_noise to understand how
      these different types of noise interact.
  
      Parameters
      ----------
  
      volume : 4d numpy array, float
          Take in a functional volume (either the file name or the numpy
          array) to be used to estimate the noise properties of this
  
      mask : 3d numpy array, binary
          A binary mask of the brain, the same size as the volume
      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.
  
      noise_dict : dict
          The initialized dictionary of the calculated noise parameters of the
          provided dataset (usually it is only the voxel size)
      Returns
      -------
  
      noise_dict : dict
          Return a dictionary of the calculated noise parameters of the provided
          dataset
  
      """
  
      # Check the inputs
      if template.max() > 1.1:
          raise ValueError("Template out of range")
  
      # Create the mask if not supplied and set the mask size
      if mask is None:
          raise ValueError("Mask not supplied")
  
      # Update noise dict if it is not yet created
      if noise_dict is None:
          noise_dict = {"voxel_size": [1.0, 1.0, 1.0]}
      elif "voxel_size" not in noise_dict:
          noise_dict["voxel_size"] = [1.0, 1.0, 1.0]
  
      # What is the max activation of the mean of this voxel (allows you to
      # convert between the mask and the mean of the brain volume)
      noise_dict["max_activity"] = np.nanmax(np.mean(volume, 3))
  
      # Calculate the temporal variability of the volume
      (
          noise_dict["auto_reg_rho"],
          noise_dict["ma_rho"],
      ) = _calc_ARMA_noise(volume, mask)
  
      # Set it such that all of the temporal variability will be accounted for
      #  by the AR component
      noise_dict["auto_reg_sigma"] = 1
  
      # Preset these values to be zero, as in you are not attempting to
      # simulate them
      noise_dict["physiological_sigma"] = 0
      noise_dict["task_sigma"] = 0
      noise_dict["drift_sigma"] = 0
  
      # Calculate the sfnr
      noise_dict["sfnr"] = _calc_sfnr(
          volume,
          mask,
      )
  
      # Calculate the fwhm on a subset of volumes
      if volume.shape[3] > 100:
          # Take only 100 shuffled TRs
          trs = np.random.choice(
              volume.shape[3], size=100, replace=False
          )
      else:
          trs = list(range(0, volume.shape[3]))
  
      # Go through the trs and pull out the fwhm
      fwhm = [0] * len(trs)
      for tr in range(len(trs)):
          fwhm[tr] = _calc_fwhm(
              volume[:, :, :, trs[tr]],
              mask,
              noise_dict["voxel_size"],
          )
  
      # Keep only the mean
      noise_dict["fwhm"] = np.mean(fwhm)
      noise_dict["snr"] = _calc_snr(
          volume,
          mask,
      )
  
      # Return the noise dictionary
      return noise_dict
  
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 14 for calling a global function with example usage: calc_noise(volume, mask, template, noise_dict) and returns: noise_dict