docs: def subgrid_kernel(kernel, subgrid_res, odd=False, num_iter=100):
      """
      creates a higher resolution kernel with subgrid resolution as an interpolation of the original kernel in an
      iterative approach
  
      :param kernel: initial kernel
      :param subgrid_res: subgrid resolution required
      :return: kernel with higher resolution (larger)
      """
      subgrid_res = int(subgrid_res)
      if subgrid_res == 1:
          return kernel
      nx, ny = np.shape(kernel)
      d_x = 1. / nx
      x_in = np.linspace(d_x/2, 1-d_x/2, nx)
      d_y = 1. / nx
      y_in = np.linspace(d_y/2, 1-d_y/2, ny)
      nx_new = nx * subgrid_res
      ny_new = ny * subgrid_res
      if odd is True:
          if nx_new % 2 == 0:
              nx_new -= 1
          if ny_new % 2 == 0:
              ny_new -= 1
  
      d_x_new = 1. / nx_new
      d_y_new = 1. / ny_new
      x_out = np.linspace(d_x_new/2., 1-d_x_new/2., nx_new)
      y_out = np.linspace(d_y_new/2., 1-d_y_new/2., ny_new)
      kernel_input = copy.deepcopy(kernel)
      kernel_subgrid = image_util.re_size_array(x_in, y_in, kernel_input, x_out, y_out)
      kernel_subgrid = kernel_norm(kernel_subgrid)
      for i in range(max(num_iter, 1)):
          # given a proposition, re-size it to original pixel size
          if subgrid_res % 2 == 0:
              kernel_pixel = averaging_even_kernel(kernel_subgrid, subgrid_res)
          else:
              kernel_pixel = util.averaging(kernel_subgrid, numGrid=nx_new, numPix=nx)
          delta = kernel - kernel_pixel
          #plt.matshow(delta)
          #plt.colorbar()
          #plt.show()
          temp_kernel = kernel_input + delta
          kernel_subgrid = image_util.re_size_array(x_in, y_in, temp_kernel, x_out, y_out)#/norm_subgrid
          kernel_subgrid = kernel_norm(kernel_subgrid)
          kernel_input = temp_kernel
  
      #from scipy.ndimage import zoom
  
      #ratio = subgrid_res
      #kernel_subgrid = zoom(kernel, ratio, order=4) / ratio ** 2
      #print(np.shape(kernel_subgrid))
      # whatever has not been matched is added to zeroth order (in squares of the undersampled PSF)
      if subgrid_res % 2 == 0:
          return kernel_subgrid
      kernel_pixel = util.averaging(kernel_subgrid, numGrid=nx_new, numPix=nx)
      kernel_pixel = kernel_norm(kernel_pixel)
      delta_kernel = kernel_pixel - kernel_norm(kernel)
      id = np.ones((subgrid_res, subgrid_res))
      delta_kernel_sub = np.kron(delta_kernel, id)/subgrid_res**2
      return kernel_norm(kernel_subgrid - delta_kernel_sub)