Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some questions about make_propagator in solver.py #4

Open
longzw001116 opened this issue May 26, 2023 · 4 comments
Open

Some questions about make_propagator in solver.py #4

longzw001116 opened this issue May 26, 2023 · 4 comments

Comments

@longzw001116
Copy link

I'm new to the field of Fourier Optics. I couldn't understand this function since I can't match it to any kind of diffraction. Can anyone have some formulas here to explain it ?

def make_propagator(params):
  
  batchSize = params['batchSize']
  pixelsX = params['pixelsX']
  pixelsY = params['pixelsY']
  upsample = params['upsample']

  # Propagator definition.
  k = 2 * np.pi / params['lam0'][:, 0, 0]
  k = k[:, np.newaxis, np.newaxis]
  samp = params['upsample'] * pixelsX
  k = tf.tile(k, multiples = (1, 2 * samp - 1, 2 * samp - 1))
  k = tf.cast(k, dtype = tf.complex64)  
  k_xlist_pos = 2 * np.pi * np.linspace(0, 1 / (2 *  params['Lx'] / params['upsample']), samp)  
  front = k_xlist_pos[-(samp - 1):]
  front = -front[::-1]
  k_xlist = np.hstack((front, k_xlist_pos))
  k_x = np.kron(k_xlist, np.ones((2 * samp - 1, 1)))
  k_x = k_x[np.newaxis, :, :]
  k_y = np.transpose(k_x, axes = [0, 2, 1])
  k_x = tf.convert_to_tensor(k_x, dtype = tf.complex64)
  k_x = tf.tile(k_x, multiples = (batchSize, 1, 1))
  k_y = tf.convert_to_tensor(k_y, dtype = tf.complex64)
  k_y = tf.tile(k_y, multiples = (batchSize, 1, 1))
  k_z_arg = tf.square(k) - (tf.square(k_x) + tf.square(k_y))
  k_z = tf.sqrt(k_z_arg)

  # Find shift amount
  theta = params['theta'][:, 0, 0]
  theta = theta[:, np.newaxis, np.newaxis]
  y0 = np.tan(theta) * params['f']
  y0 = tf.tile(y0, multiples = (1, 2 * samp - 1, 2 * samp - 1))
  y0 = tf.cast(y0, dtype = tf.complex64)

  phi = params['phi'][:, 0, 0]
  phi = phi[:, np.newaxis, np.newaxis]
  x0 = np.tan(phi) * params['f']
  x0 = tf.tile(x0, multiples = (1, 2 * samp - 1, 2 * samp - 1))
  x0 = tf.cast(x0, dtype = tf.complex64)

  propagator_arg = 1j * (k_z * params['f'] + k_x * x0 + k_y * y0)
  propagator = tf.exp(propagator_arg)

  return propagator
@Ethan-Tseng
Copy link
Owner

Welcome to Fourier Optics! This function implements the Angular Spectrum Method (ASM). It is one of many different wave propagation simulation methods. This function specifically generates the ASM transfer function which is used later in the code to simulate the optical response of the metasurface.

For more information on different types of propagation functions please refer to our other works. Specifically, refer to Section 3 of Learned Hardware-in-the-loop Phase Retrieval for Holographic Near-Eye Displays and our SIGGRAPH course notes.

Let us know if you have any further questions!

@longzw001116
Copy link
Author

longzw001116 commented Jun 5, 2023

Thank you for answering my question.

I have new questions as follows:

In this make_propagator function:
propagator_arg = 1j * (k_z * params['f'] + k_x * x0 + k_y * y0)
while x0 = np.tan(phi) * params['f'] and y0 = np.tan(theta) * params['f'].

  1. k_z * params['f'] represents the ASM, so what does k_x * x0 + k_y * y0 mean? Does it account for the shift of image in the focal plane due to the oblique incident light?
  2. Since θ and φ are field angles alone x- and y-axis, I think there is a mistake in x0 and y0.
    In other words: x0 = np.tan(theta) * params['f'] and y0 = np.tan(phi) * params['f']

@longzw001116
Copy link
Author

Welcome to Fourier Optics! This function implements the Angular Spectrum Method (ASM). It is one of many different wave propagation simulation methods. This function specifically generates the ASM transfer function which is used later in the code to simulate the optical response of the metasurface.

For more information on different types of propagation functions please refer to our other works. Specifically, refer to Section 3 of Learned Hardware-in-the-loop Phase Retrieval for Holographic Near-Eye Displays and our SIGGRAPH course notes.

Let us know if you have any further questions!

@Ethan-Tseng
Copy link
Owner

Thank you for answering my question.

I have new questions as follows:

In this make_propagator function: propagator_arg = 1j * (k_z * params['f'] + k_x * x0 + k_y * y0) while x0 = np.tan(phi) * params['f'] and y0 = np.tan(theta) * params['f'].

  1. k_z * params['f'] represents the ASM, so what does k_x * x0 + k_y * y0 mean? Does it account for the shift of image in the focal plane due to the oblique incident light?
  2. Since θ and φ are field angles alone x- and y-axis, I think there is a mistake in x0 and y0.
    In other words: x0 = np.tan(theta) * params['f'] and y0 = np.tan(phi) * params['f']
  1. You are correct. The extra terms describe lateral shifts on the sensor plane as a result of the tilted wavefront.
  2. Thanks for debugging our code! We assumed rotational symmetry of the metalens and so we ended up only using theta and hence this mistake did not affect the final results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants