docs: def de_shift_kernel(kernel, shift_x, shift_y, iterations=20):
      """
      de-shifts a shifted kernel to the center of a pixel. This is performed iteratively.
  
      The input kernel is the solution of a linear interpolated shift of a sharper kernel centered in the middle of the
       pixel. To find the de-shifted kernel, we perform an iterative correction of proposed de-shifted kernels and compare
       its shifted version with the input kernel.
  
      :param kernel: (shifted) kernel, e.g. a star in an image that is not centered in the pixel grid
      :param shift_x: x-offset relative to the center of the pixel (sub-pixel shift)
      :param shift_y: y-offset relative to the center of the pixel (sub-pixel shift)
      :return: de-shifted kernel such that the interpolated shift boy (shift_x, shift_y) results in the input kernel
      """
      nx, ny = np.shape(kernel)
      kernel_new = np.zeros((nx+2, ny+2)) + (kernel[0, 0] + kernel[0, -1] + kernel[-1, 0] + kernel[-1, -1]) / 4.
      kernel_new[1:-1, 1:-1] = kernel
      int_shift_x = int(round(shift_x))
      frac_x_shift = shift_x - int_shift_x
      int_shift_y = int(round(shift_y))
      frac_y_shift = shift_y - int_shift_y
      kernel_init = copy.deepcopy(kernel_new)
      kernel_init_shifted = copy.deepcopy(interp.shift(kernel_init, [int_shift_y, int_shift_x], order=1))
      kernel_new = interp.shift(kernel_new, [int_shift_y, int_shift_x], order=1)
      norm = np.sum(kernel_init_shifted)
      for i in range(iterations):
          kernel_shifted_inv = interp.shift(kernel_new, [-frac_y_shift, -frac_x_shift], order=1)
          delta = kernel_init_shifted - kernel_norm(kernel_shifted_inv) * norm
          kernel_new += delta * 1.
          kernel_new = kernel_norm(kernel_new) * norm
      return kernel_new[1:-1, 1:-1]