code: def unscented_transform2(
      sigmas, Wm, Wc, noise_cov=None, mean_fn=np.dot, residual_fn=None
  ):
      """Computes unscented transform of a set of sigma points and weights.
      returns the mean and covariance in a tuple.
  
      Parameters
      ----------
  
      sigmas: ndarray [#sigmas per dimension, dimension]
          2D array of sigma points.
  
      Wm : ndarray [# sigmas per dimension]
          Weights for the mean. Must sum to 1.
  
  
      Wc : ndarray [# sigmas per dimension]
          Weights for the covariance. Must sum to 1.
  
      noise_cov : ndarray, optional
          noise matrix added to the final computed covariance matrix.
  
      mean_fn : callable (sigma_points, weights), optional
          Function that computes the mean of the provided sigma points
          and weights. Use this if your state variable contains nonlinear
          values such as angles which cannot be summed.
  
          .. code-block:: Python
  
              def state_mean(sigmas, Wm):
                  x = np.zeros(3)
                  sum_sin, sum_cos = 0., 0.
  
                  for i in range(len(sigmas)):
                      s = sigmas[i]
                      x[0] += s[0] * Wm[i]
                      x[1] += s[1] * Wm[i]
                      sum_sin += sin(s[2])*Wm[i]
                      sum_cos += cos(s[2])*Wm[i]
                  x[2] = atan2(sum_sin, sum_cos)
                  return x
  
      residual_fn : callable (x, y), optional
  
          Function that computes the residual (difference) between x and y.
          You will have to supply this if your state variable cannot support
          subtraction, such as angles (359-1 degreees is 2, not 358). x and y
          are state vectors, not scalars.
  
          .. code-block:: Python
  
              def residual(a, b):
                  y = a[0] - b[0]
                  if y > np.pi:
                      y -= 2*np.pi
                  if y < -np.pi:
                      y = 2*np.pi
                  return y
  
  
      Returns
      -------
  
      x : ndarray [dimension]
          Mean of the sigma points after passing through the transform.
  
      P : ndarray
          covariance of the sigma points after passing throgh the transform.
      """
  
      n, kmax = sigmas.shape
  
      x = np.dot(sigmas, Wm).reshape(
          (-1, 1)
      )  # dot = \Sigma^n_1 (W[k]*Xi[k])
  
      # new covariance is the sum of the outer product of the residuals
      # times the weights
  
      # this is the fast way to do this - see 'else' for the slow way
      if residual_fn is None:
          y = sigmas - x[np.newaxis, :]
          P = y.T.dot(np.diag(Wc)).dot(y)
      else:
          P = np.zeros((n, n))
          for k in range(kmax):
              y = residual_fn(sigmas[:, k], x[:, 0])
              P += Wc[k] * np.outer(y, y)
  
      if noise_cov is not None:
          P += noise_cov
  
      return (x, P)
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import matplotlib.pyplot
  import numpy.random
  from numpy.random import randn
  from numpy import asarray
  import numpy
  from filterpy.kalman import UnscentedKalmanFilter
  from filterpy.kalman import unscented_transform, MerweScaledSigmaPoints, JulierSigmaPoints, SimplexSigmaPoints
  from filterpy.common import Q_discrete_white_noise
  import filterpy.stats
  from math import cos, sin
  from filterpy.kalman import UnscentedKalmanFilter2
label_desc: Use image node_id 1 for calling a global function with example usage: unscented_transform2(sigmas, Wm, Wc, noise_cov, mean_fn, residual_fn) and returns: x,  P