code: def single_tensor(
      gtab, S0=1, evals=None, evecs=None, snr=None, rng=None
  ):
      """Simulate diffusion-weighted signals with a single tensor.
  
      Parameters
      ----------
      gtab : GradientTable
          Table with information of b-values and gradient directions g.
          Note that if gtab has a btens attribute, simulations will be performed
          according to the given b-tensor B information.
      S0 : double, optional
          Strength of signal in the presence of no diffusion gradient (also
          called the ``b=0`` value).
      evals : (3,) ndarray, optional
          Eigenvalues of the diffusion tensor.  By default, values typical for
          prolate white matter are used.
      evecs : (3, 3) ndarray, optional
          Eigenvectors of the tensor.  You can also think of this as a rotation
          matrix that transforms the direction of the tensor. The eigenvectors
          need to be column wise.
      snr : float, optional
          Signal to noise ratio, assuming Rician noise.  None implies no noise.
  
      Returns
      -------
      S : (N,) ndarray
          Simulated signal:
              ``S(b, g) = S_0 e^(-b g^T R D R.T g)``, if gtab.tens=None
              ``S(B) = S_0 e^(-B:D)``, if gtab.tens information is given
  
      References
      ----------
      .. [1] M. Descoteaux, "High Angular Resolution Diffusion MRI: from Local
             Estimation to Segmentation and Tractography", PhD thesis,
             University of Nice-Sophia Antipolis, p. 42, 2008.
      .. [2] E. Stejskal and J. Tanner, "Spin diffusion measurements: spin echos
             in the presence of a time-dependent field gradient", Journal of
             Chemical Physics, nr. 42, pp. 288--292, 1965.
  
      """
      if rng is None:
          rng = np.random.default_rng()
  
      if evals is None:
          evals = diffusion_evals
  
      if evecs is None:
          evecs = np.eye(3)
  
      out_shape = gtab.bvecs.shape[: gtab.bvecs.ndim - 1]
      gradients = gtab.bvecs.reshape(-1, 3)
  
      R = np.asarray(evecs)
      S = np.zeros(len(gradients))
      D = dot(dot(R, np.diag(evals)), R.T)
  
      if gtab.btens is None:
          for i, g in enumerate(gradients):
              S[i] = S0 * np.exp(-gtab.bvals[i] * dot(dot(g.T, D), g))
      else:
          for i, b in enumerate(gtab.btens):
              S[i] = S0 * np.exp(-np.sum(b * D))
  
      S = add_noise(S, snr, S0, rng=rng)
  
      return S.reshape(out_shape)
  
imports: import numpy
  from numpy import dot
  from dipy.core.geometry import sphere2cart
  from dipy.core.geometry import vec2vec_rotmat
  from dipy.core.gradients import GradientTable
  from dipy.reconst.utils import dki_design_matrix
  from scipy.special import jn
label_desc: Use image node_id 10 for calling a global function with example usage: single_tensor(gtab, S0, evals, evecs, snr, rng) and returns: S