code: def gradient_table_from_bvals_bvecs(
      bvals, bvecs, b0_threshold=50, atol=1e-2, btens=None, **kwargs
  ):
      """Creates a GradientTable from a bvals array and a bvecs array
  
      Parameters
      ----------
      bvals : array_like (N,)
          The b-value, or magnitude, of each gradient direction.
      bvecs : array_like (N, 3)
          The direction, represented as a unit vector, of each gradient.
      b0_threshold : float
          Gradients with b-value less than or equal to `b0_threshold` are
          considered to not have diffusion weighting. If its value is equal to or
          larger than all values in b-vals, then it is assumed that no
          thresholding is requested.
      atol : float
          Each vector in `bvecs` must be a unit vectors up to a tolerance of
          `atol`.
      btens : can be any of three options
          1. a string specifying the shape of the encoding tensor for all volumes
             in data. Options: 'LTE', 'PTE', 'STE', 'CTE' corresponding to
             linear, planar, spherical, and "cigar-shaped" tensor encoding.
             Tensors are rotated so that linear and cigar tensors are aligned
             with the corresponding gradient direction and the planar tensor's
             normal is aligned with the corresponding gradient direction.
             Magnitude is scaled to match the b-value.
          2. an array of strings of shape (N,), (N, 1), or (1, N) specifying
             encoding tensor shape for each volume separately. N corresponds to
             the number volumes in data. Options for elements in array: 'LTE',
             'PTE', 'STE', 'CTE' corresponding to linear, planar, spherical, and
             "cigar-shaped" tensor encoding. Tensors are rotated so that linear
             and cigar tensors are aligned with the corresponding gradient
             direction and the planar tensor's normal is aligned with the
             corresponding gradient direction. Magnitude is scaled to match the
             b-value.
          3. an array of shape (N,3,3) specifying the b-tensor of each volume
             exactly. N corresponds to the number volumes in data. No rotation or
             scaling is performed.
  
      Other Parameters
      ----------------
      **kwargs : dict
          Other keyword inputs are passed to GradientTable.
  
      Returns
      -------
      gradients : GradientTable
          A GradientTable with all the gradient information.
  
      See Also
      --------
      GradientTable, gradient_table
  
      """
      bvals = np.asarray(bvals, float)
      bvecs = np.asarray(bvecs, float)
      dwi_mask = bvals > b0_threshold
  
      # check that bvals is (N,) array and bvecs is (N, 3) unit vectors
      if (
          bvals.ndim != 1
          or bvecs.ndim != 2
          or bvecs.shape[0] != bvals.shape[0]
      ):
          raise ValueError(
              "bvals and bvecs should be (N,) and (N, 3) arrays "
              "respectively, where N is the number of diffusion "
              "gradients"
          )
      # checking for negative bvals
      if b0_threshold < 0:
          raise ValueError(
              "Negative bvals in the data are not feasible"
          )
  
      # Upper bound for the b0_threshold
      if b0_threshold >= 200:
          warn("b0_threshold has a value > 199")
  
      # If all b-values are smaller or equal to the b0 threshold, it is assumed
      # that no thresholding is requested
      if any(mask_non_weighted_bvals(bvals, b0_threshold)):
          # checking for the correctness of bvals
          if b0_threshold < bvals.min():
              warn(
                  "b0_threshold (value: {0}) is too low, increase your "
                  "b0_threshold. It should be higher than the lowest b0 value "
                  "({1}).".format(b0_threshold, bvals.min())
              )
  
      bvecs = np.where(np.isnan(bvecs), 0, bvecs)
      bvecs_close_to_1 = abs(vector_norm(bvecs) - 1) <= atol
      if bvecs.shape[1] != 3:
          raise ValueError("bvecs should be (N, 3)")
      if not np.all(bvecs_close_to_1[dwi_mask]):
          raise ValueError(
              "The vectors in bvecs should be unit (The tolerance "
              "can be modified as an input parameter)"
          )
  
      bvecs = np.where(bvecs_close_to_1[:, None], bvecs, 0)
      bvals = bvals * bvecs_close_to_1
      gradients = bvals[:, None] * bvecs
  
      grad_table = GradientTable(
          gradients, b0_threshold=b0_threshold, btens=btens, **kwargs
      )
      grad_table.bvals = bvals
      grad_table.bvecs = bvecs
      grad_table.b0s_mask = ~dwi_mask
  
      return grad_table
  
imports: import logging
  from warnings import warn
  import numpy
  from scipy.linalg import inv, polar
  from dipy.io import gradients
  from dipy.core.onetime import auto_attr
  from dipy.core.geometry import vector_norm, vec2vec_rotmat
  from dipy.core.sphere import disperse_charges, HemiSphere
  from dipy.utils.deprecator import deprecate_with_version
label_desc: Use image node_id 5 for calling a global function with example usage: gradient_table_from_bvals_bvecs(bvals, bvecs, b0_threshold, atol, btens) and returns: grad_table