docs: def offset(
          self,
          points,
          offsets,
          along,
          offset_axis,
          units="same",
          offset_units="same",
          mode="valid",
          method="linear",
          verbose=True,
      ):
          """Offset one axis based on another axis' values.
  
          Useful for correcting instrumental artifacts such as zerotune.
  
          Parameters
          ----------
          points : 1D array-like
              Points.
          offsets : 1D array-like
              Offsets.
          along : str or int
              Axis that points array lies along.
          offset_axis : str or int
              Axis to offset using offsets.
          units : str (optional)
              Units of points array.
          offset_units : str (optional)
              Units of offsets aray.
          mode : {'valid', 'full', 'old'} (optional)
              Define how far the new axis will extend. Points outside of valid
              interpolation range will be written nan.
          method : {'linear', 'nearest', 'cubic'} (optional)
              The interpolation method. Note that cubic interpolation is only
              possible for 1D and 2D data. See `griddata`__ for more information.
              Default is linear.
          verbose : bool (optional)
              Toggle talkback. Default is True.
  
  
          __ http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
  
              >>> points  # an array of w1 points
              >>> offsets  # an array of d1 corrections
              >>> data.offset(points, offsets, 'w1', 'd1')
  
          """
          raise NotImplementedError
          # axis ------------------------------------------------------------------------------------
          if isinstance(along, int):
              axis_index = along
          elif isinstance(along, str):
              axis_index = self.axis_names.index(along)
          else:
              raise TypeError("along: expected {int, str}, got %s" % type(along))
          axis = self._axes[axis_index]
          # values & points -------------------------------------------------------------------------
          # get values, points, units
          if units == "same":
              input_units = axis.units
          else:
              input_units = units
          # check offsets is 1D or 0D
          if len(offsets.shape) == 1:
              pass
          else:
              raise RuntimeError("values must be 1D or 0D in offset!")
          # check if units is compatible, convert
          dictionary = getattr(wt_units, axis.units_kind)
          if input_units in dictionary.keys():
              pass
          else:
              raise RuntimeError("units incompatible in offset!")
          points = wt_units.converter(points, input_units, axis.units)
          # create correction array
          function = interp1d(points, offsets, bounds_error=False)
          corrections = function(axis[:])
          # remove nans
          finite_indicies = np.where(np.isfinite(corrections))[0]
          left_pad_width = finite_indicies[0]
          right_pad_width = len(corrections) - finite_indicies[-1] - 1
          corrections = np.pad(
              corrections[np.isfinite(corrections)],
              (int(left_pad_width), int(right_pad_width)),
              mode="edge",
          )
          # do correction ---------------------------------------------------------------------------
          # transpose so axis is last
          transpose_order = np.arange(len(self._axes))
          transpose_order[axis_index] = len(self._axes) - 1
          transpose_order[-1] = axis_index
          self.transpose(transpose_order, verbose=False)
          # get offset axis index
          if isinstance(offset_axis, int):
              offset_axis_index = offset_axis
          elif isinstance(offset_axis, str):
              offset_axis_index = self.axis_names.index(offset_axis)
          else:
              raise TypeError("offset_axis: expected {int, str}, got %s" % type(offset_axis))
          # new points
          new_points = [a[:] for a in self._axes]
          old_offset_axis_points = self._axes[offset_axis_index][:]
          spacing = abs(
              (old_offset_axis_points.max() - old_offset_axis_points.min())
              / float(len(old_offset_axis_points))
          )
          if mode == "old":
              new_offset_axis_points = old_offset_axis_points
          elif mode == "valid":
              _max = old_offset_axis_points.max() + corrections.min()
              _min = old_offset_axis_points.min() + corrections.max()
              n = int(abs(np.ceil((_max - _min) / spacing)))
              new_offset_axis_points = np.linspace(_min, _max, n)
          elif mode == "full":
              _max = old_offset_axis_points.max() + corrections.max()
              _min = old_offset_axis_points.min() + corrections.min()
              n = np.ceil((_max - _min) / spacing)
              new_offset_axis_points = np.linspace(_min, _max, n)
          new_points[offset_axis_index] = new_offset_axis_points
          new_xi = tuple(np.meshgrid(*new_points, indexing="ij"))
          xi = tuple(np.meshgrid(*[a[:] for a in self._axes], indexing="ij"))
          for channel in self.channels:
              # 'undo' gridding
              arr = np.zeros((len(self._axes) + 1, channel[:].size))
              for i in range(len(self._axes)):
                  arr[i] = xi[i].flatten()
              arr[-1] = channel[:].flatten()
              # do corrections
              corrections = list(corrections)
              corrections = corrections * int((len(arr[0]) / len(corrections)))
              arr[offset_axis_index] += corrections
              # grid data
              tup = tuple([arr[i] for i in range(len(arr) - 1)])
              # note that rescale is crucial in this operation
              out = griddata(tup, arr[-1], new_xi, method=method, fill_value=np.nan, rescale=True)
              channel[:] = out
          self._axes[offset_axis_index][:] = new_offset_axis_points
          # transpose out
          self.transpose(transpose_order, verbose=False)