code: def _gibbs_removal_1d(x, axis=0, n_points=3):
      """Suppresses Gibbs ringing along a given axis using fourier sub-shifts.
  
      Parameters
      ----------
      x : 2D ndarray
          Matrix x.
      axis : int (0 or 1)
          Axis in which Gibbs oscillations will be suppressed.
          Default is set to 0.
      n_points : int, optional
          Number of neighbours to access local TV (see note).
          Default is set to 3.
  
      Returns
      -------
      xc : 2D ndarray
          Matrix with suppressed Gibbs oscillations along the given axis.
  
      Notes
      -----
      This function suppresses the effects of Gibbs oscillations based on the
      analysis of local total variation (TV). Although artefact correction is
      done based on two adjacent points for each voxel, total variation should be
      accessed in a larger range of neighbours. The number of neighbours to be
      considered in TV calculation can be adjusted using the parameter n_points.
  
      """
      dtype_float = np.promote_types(x.real.dtype, np.float32)
  
      ssamp = np.linspace(0.02, 0.9, num=45, dtype=dtype_float)
  
      xs = x.copy() if axis else x.T.copy()
  
      # TV for shift zero (baseline)
      tvr, tvl = _image_tv(xs, axis=1, n_points=n_points)
      tvp = np.minimum(tvr, tvl)
      tvn = tvp.copy()
  
      # Find optimal shift for gibbs removal
      isp = xs.copy()
      isn = xs.copy()
      sp = np.zeros(xs.shape, dtype=dtype_float)
      sn = np.zeros(xs.shape, dtype=dtype_float)
      N = xs.shape[1]
      c = _fft.fft(xs, axis=1)
      k = _fft.fftfreq(N, 1 / (2.0j * np.pi))
      k = k.astype(c.dtype, copy=False)
      for s in ssamp:
          ks = k * s
          # Access positive shift for given s
          img_p = abs(_fft.ifft(c * np.exp(ks), axis=1))
  
          tvsr, tvsl = _image_tv(img_p, axis=1, n_points=n_points)
          tvs_p = np.minimum(tvsr, tvsl)
  
          # Access negative shift for given s
          img_n = abs(_fft.ifft(c * np.exp(-ks), axis=1))
          tvsr, tvsl = _image_tv(img_n, axis=1, n_points=n_points)
          tvs_n = np.minimum(tvsr, tvsl)
  
          # Update positive shift params
          isp[tvp > tvs_p] = img_p[tvp > tvs_p]
          sp[tvp > tvs_p] = s
          tvp[tvp > tvs_p] = tvs_p[tvp > tvs_p]
  
          # Update negative shift params
          isn[tvn > tvs_n] = img_n[tvn > tvs_n]
          sn[tvn > tvs_n] = s
          tvn[tvn > tvs_n] = tvs_n[tvn > tvs_n]
  
      # check non-zero sub-voxel shifts
      idx = np.nonzero(sp + sn)
  
      # use positive and negative optimal sub-voxel shifts to interpolate to
      # original grid points
      xs[idx] = (isp[idx] - isn[idx]) / (sp[idx] + sn[idx]) * sn[
          idx
      ] + isn[idx]
  
      return xs if axis else xs.T
  
file_path: dipy/dipy/denoise/gibbs.py
imports: from functools import partial
  from multiprocessing import Pool
  import numpy
  import scipy
  from dipy.utils.multiproc import determine_num_processes
  from dipy.utils.deprecator import deprecated_params
  import scipy.fft
label_desc: Use image node_id 2 for calling a global function with example usage: _gibbs_removal_1d(x, axis, n_points) and returns: unknown