How to achieve the Zernike polynomials combination with different j_terms?
I have a series of Zernike polynomials coefficients (j_terms form 1 ~36). However, I don't know how to achieve their combination by LightPipes.
Field2 = lp.Begin(10*lp.um,lamda,410)
for Noll in range(1, 36):
(nz, mz) = lp.noll_to_zern(Noll)
e_m = 2 if mz == 0 else 1
A = 1
#A = math.sqrt((2 * nz + 2) / e_m / math.pi)
#print(e_m)
Field2 = lp.Zernike(nz, mz, 10*lp.um, zernike_poly[Noll] * A, Field2)
phase2 = lp.PhaseUnwrap(phase2)

I achieve it like this. But the phase is not as I imagined. It's very strange. Do you have any suggestions that how I can achieve this goal correctly?
(ldoyle edited code formatting)
Dear Vicky,
I think you just got the units wrong. In LightPipes the default units for Zernike polynomials is optical path length, i.e. [m]. This follows from the definition of the Zernike polynomials as a phase factor exp(1j*2*pi/lambda*Z).
You have two options to solve this:
- scale the amplitude as desired, e.g.
A=1*lamdafor a 1 lambda = 2 Pi phase shift - in the most recent LightPipes, you can specify alternative units in the Zernike function. Then, e.g.
A=1andunits='lam'will also create a 2 Pi phase shift. Check my example below.
import numpy as np
import matplotlib.pyplot as plt
import LightPipes as lp
lamda = 800*lp.nm
zernike_poly = {i:1 for i in range(1,36)} #amplitude 1 for all indices
Field2 = lp.Begin(10*lp.um,lamda,410)
for Noll in range(1, 36):
(nz, mz) = lp.noll_to_zern(Noll)
e_m = 2 if mz == 0 else 1
A = 1
#A = math.sqrt((2 * nz + 2) / e_m / math.pi)
#print(e_m)
if lp.__version__ == '2.0.5': #or greater actually
#latest LightPipes has inverted argument order for usability
# and adds the optional "units" kwarg
Field2 = lp.Zernike(Field2, nz, mz, 10*lp.um, zernike_poly[Noll] * A, units='lam')
else:
A = 1*lamda
Field2 = lp.Zernike(nz, mz, 10*lp.um, zernike_poly[Noll] * A, Field2)
phase2 = lp.Phase(Field2)
phase2 = lp.PhaseUnwrap(phase2)
plt.imshow(phase2)

Some addition comments:
- The weird diagonal pattern you are seeing comes from the internal workings of
PhaseUnwrapand happens when the phase jump from 1 data point to the next is too large (~1Pi) in which case there is no definite direction of unwrapping. Try increasingA=1toA=100orA=1000lambdas to see the effect in action. If the jumps are really too large for your case, you need to increase the sampling (more datapoints in same dimension). - You may already know this: The keyword
lambdais reserved in Python. You may use it as a variable, but it's a very bad idea. Yourlamdaor alternatives likelamorlabdaare the safe ways to go. - When you post code, make sure to format it as code using 3 ticks before and after to help readability.
- Your code was not a minimum working example since some variables and imports were undefined. I added them accordingly. In the future, best make sure the minimal script you post actually runs and produces the image you posted. In this case, I could not reconstruct the meaning of
zernike_poly[Noll], therefore I assume it's1for all entries.
Let us know if this solves your problem. Best, Lenny