docstr: Fit fODF and GM/CSF volume fractions globally.
  
  Parameters
  ----------
  data : ndarray (x, y, z, N)
      Signal values for each voxel. Must be 4D.
  mask : ndarray (x, y, z), optional
      Binary mask specifying voxels of interest with 1; results will only
      be fit at these voxels (0 elsewhere). If `None`, fits all voxels.
      Default: None.
  
  Returns
  -------
  model_fit : RumbaFit
      Fit object storing model parameters.
docstr_tok: ["Fit","fODF","and","GM\/CSF","volume","fractions","globally",".","Parameters","--","--","--","--","--","data",":","ndarray","(","x",",","y",",","z",",","N",")","Signal","values","for","each","voxel",".","Must","be","4D",".","mask",":","ndarray","(","x",",","y",",","z",")",",","optional","Binary","mask","specifying","voxels","of","interest","with","1",";","results","will","only","be","fit","at","these","voxels","(","0","elsewhere",")",".","If","`","None","`",",","fits","all","voxels",".","Default",":","None",".","Returns","--","--","--","-","model_fit",":","RumbaFit","Fit","object","storing","model","parameters","."]
code: def _global_fit(self, data, mask=None):
      """
      Fit fODF and GM/CSF volume fractions globally.
  
      Parameters
      ----------
      data : ndarray (x, y, z, N)
          Signal values for each voxel. Must be 4D.
      mask : ndarray (x, y, z), optional
          Binary mask specifying voxels of interest with 1; results will only
          be fit at these voxels (0 elsewhere). If `None`, fits all voxels.
          Default: None.
  
      Returns
      -------
      model_fit : RumbaFit
          Fit object storing model parameters.
  
      """
  
      # Checking data and mask shapes
      if len(data.shape) != 4:
          raise ValueError(
              f"Data should be 4D, received shape f{data.shape}"
          )
  
      if mask is None:  # default mask includes all voxels
          mask = np.ones(data.shape[:3])
  
      if data.shape[:3] != mask.shape:
          raise ValueError(
              "Mask shape should match first 3 dimensions of "
              + f"data, but data dimensions are f{data.shape} "
              + f"while mask dimensions are f{mask.shape}"
          )
  
      # Signal repair, normalization
  
      # Normalize data to mean b0 image
      data = normalize_data(data, self.where_b0s, _EPS)
      # Rearrange data to match corrected gradient table
      data = np.concatenate(
          (np.ones([*data.shape[:3], 1]), data[..., self.where_dwi]),
          axis=3,
      )
      data[data > 1] = 1  # clip values between 0 and 1
  
      # All arrays are converted to float32 to reduce memory load
      data = data.astype(np.float32)
  
      # Generate kernel
      self.kernel = generate_kernel(
          self.gtab,
          self.sphere,
          self.wm_response,
          self.gm_response,
          self.csf_response,
      ).astype(np.float32)
  
      # Fit fODF
      model_params = rumba_deconv_global(
          data,
          self.kernel,
          mask,
          self.n_iter,
          self.recon_type,
          self.n_coils,
          self.R,
          self.use_tv,
          self.verbose,
      )
  
      model_fit = RumbaFit(self, model_params)
      return model_fit
  
imports: import logging
  import warnings
  import numpy
  from dipy.core.geometry import vec2vec_rotmat
  from dipy.core.gradients import gradient_table, unique_bvals_tolerance, get_bval_indices
  from dipy.core.onetime import auto_attr
  from dipy.core.sphere import Sphere
  from dipy.data import get_sphere
  from dipy.reconst.shm import lazy_index, normalize_data
  from dipy.reconst.odf import OdfModel, OdfFit
  from dipy.reconst.csdeconv import AxSymShResponse
  from dipy.segment.mask import bounding_box, crop
  from dipy.sims.voxel import single_tensor, all_tensor_evecs
label_desc: Use image node_id 2 for calling the RumbaSDModel obj's underlying member method code with example usage: obj._global_fit(data, mask) and returns: model_fit