opticspy / lightpipes

LightPipes for Python, "Pure Python version"
https://opticspy.github.io/lightpipes/
BSD 3-Clause "New" or "Revised" License
227 stars 52 forks source link

Calculate the power( ratio) in the bucket and times the diffraction limit #80

Open tianjiaoshanzai opened 9 months ago

tianjiaoshanzai commented 9 months ago

Hello, @FredvanGoor

I am simulating the calculation of a circular aperture beam passing through a lens and converging at the focal plane. I want to calculate what is the radius of the spot when the energy in the barrel at the focal plane is 83.9%. And calculate its times of the diffraction limit.

If the diameter of the center of the first dark ring (Airy disk) of a Fraunhofer diffraction pattern is taken as the diffraction limit diameter.Theoretically, When focused through an ideal lens to the focal plane, the measured ideal diffraction limit diameter should be $d{difflimit} =\theta {difflimit} f$ = $2.44 λ * f / D$, where λ is the wavelength, f is the focal length, and D is the diameter of the circular aperture.[1]

$$u{\mathrm{~ref}}=\frac{\int{0}^{2\pi}\int{0}^{d{u,\mathrm{ref}}/2 }I\left(r\right)\mathrm{d}r\mathrm{d}\theta}{\iint I\left(r\right)\mathrm{d}r\mathrm{d}\theta}$$

Formula 1

According to Formula 1, it can be calculated that $u{ref}$ =0.839,when $d{u,\mathrm{ref}}$ is taken as diffraction limit diameter metioned above

There are some details for $u_{ref}$ According to Fraunhofer diffraction theory, the far-field intensity distribution of the reference beam with radius $r$ is calculated in paraximal approximation see A.1 $$I\left(r\right)=I_0\left\lbrace\frac{2J_{1}\left[\pi d_{u,near}r/\left(f\lambda\right)\right]}{\pi d_{u,near}r/\left(f\lambda\right)}-\varepsilon^2\frac{2J_{1}\left[\pi\varepsilon d_{u,near}r/\left(f\lambda\right)\right]}{\pi\varepsilon d_{u,near}r/\left(f\lambda\right)}\right\rbrace^2\cdots\cdots\cdots\cdots(\text{ A.}1)$$ $I_{0}$ -- the reference beam far-field peak intensity; $J_{1}$ -- first-order Bessel function; $d_\mathrm{u.near}$ -- reference beam near-field beam diameter; $f$ -- device equivalent focal length; $\lambda$ -- actual beam laser wavelength; $\varepsilon$ - center blocking ratio. (center circle area as a proportion of total area) Let $I(r)=0$, the positional equation to be satisfied by the zero radius of the circular beam intensity is given in Eq. (A.2). $J_1[\pi d_\text{u.near}r/(f\lambda)]-\varepsilon J_1[\pi\varepsilon d_\text{u,near}r/(f\lambda)]=0\quad........................( A.2 )$ According to Formula 1, when $\varepsilon$ = 0, it can be calculated that c=2.44, $u_{ref}$ =0.839

So the calculation result we would expect should be $\beta = d{simulate}/d{therory} =1 $,where $d{simulate}$ is the circular diameter of the region that accounts for 83.9% of the total energy in the simulation results,and $d{therory}$ = $2.44 F.lam f / w$

But in practice, the code didn't work as I thought it would.

Code Parts

At first, I tried combining the Lens() and Propagate() functions. Then ,I tried LensFarfield() Fuction And now,I am trying use Spherical coordinates

calRediuswithPow.py is the base function I used to calculate it, there are some things wrong with its algorithm, such as the center of mass calculating itself, and the energy calculating itself, but I don't think it's going to be particularly wrong for the same field and it's propagation, and during debugging, the energy percentage was not more than 0.3% wrong

They all produce beta results that are way off compared to one, generally speaking aspherical coordinate calculations will be about 30% off, and will change greatly with focal length, and diameter of the circular hole,even if I use "ideal sampling": $dx=\frac{\lambda *z}{L}$ [2]73-74. Spherical coordinates in my example are calculated to be 0.3-0.4, which is off by 60-70%.

I'm not sure what went wrong, the radius calculations should not logically produce such a large deviation. Is there something I am not taking into account in my simulation method.

calRediuswithPow.py ### use calRediuswithPow() function to calculate the radius corresponding to energy in specify bucket ```python from LightPipes import * import matplotlib as mpl import numpy as np import copy as _copy def calRediuswithPow(fieldIn,energyPercent=0.839): ''' Calculate the radius corresponding to the ring energy Parameters ---------- energyPercent : double fieldIn : lp.Field The input field. Returns ------- The Redius correspend to the energyPercent power. """ ---------- ''' fieldIn=_copy.copy(fieldIn) I=Intensity(fieldIn) sumEnergy=0 # sumEnergy=sum(I) sumEnergy1=0 sumEnergy1=0 F_row=np.size(fieldIn.field,0) F_col=np.size(fieldIn.field,1) for i in range(F_row): for j in range(F_col): sumEnergy+=I[i][j] #sumEnergy2=Power(fieldIn) targetEnergy=energyPercent*sumEnergy # Y, X = fieldIn.mgrid_cartesian #Determine spot center of mass Coordinate system with array indexed x,y coordinates x_power_sum=0 y_power_sum=0 for i in range(F_row): for j in range(F_col): x_power_sum+=I[i][j]*i for i in range(F_row): for j in range(F_col): y_power_sum+=I[i][j]*j x_center=x_power_sum/sumEnergy y_center=y_power_sum/sumEnergy #Calculate the approximation of the true radius using the Bisection method. # First set the maximum value of the radius to the diagonal of the matrix r_max=np.sqrt(F_row**2+F_col**2) r_min=0 girdR=binarySearchR(I,r_max,r_min,targetEnergy,x_center,y_center,F_row,F_col) Rres=girdR*fieldIn.dx return Rres def binarySearchR(intensityIn,r_max,r_min,targetEnergy,x_center,y_center,F_row,F_col): ''' Bisection method to approximate the real radius (the fitting effect is a bit poor, later can be changed to a point by point cascade outward expansion) The error is close to 0.3% ''' while r_min <= r_max: r_mid=(r_min+(r_max-r_min)/2) midEnergy=calPowerWithRadius(intensityIn,F_row,F_col,x_center,y_center,r_mid) if midEnergy == targetEnergy: return r_mid elif midEnergy>targetEnergy: r_max=r_mid-1 else: r_min=r_mid+1 #close return r_mid #TODO:Sort, compute distance from center of mass for all cells, put into set sort, set map def calPowerWithRadius(intensityIn,F_row,F_col,x_center,y_center,radius): ''' Calculate the power within a specified radius ''' powerRes=0 for i in range(F_row): for j in range(F_col): if ((i-x_center)**2+(j-y_center)**2)<=radius**2: powerRes+=intensityIn[i][j] return powerRes ```
LensAndLensFarfieldTry.py ### try combine Lens() and Propagate() And try LensFarfield() ```python from LightPipes import * import matplotlib as mpl import numpy as np import calRediuswithPow mpl.use('TkAgg') import matplotlib.pyplot as plt #import Utils # wavelength = 500*nm # size = 7*mm # N = 100 # w0 = 1*mm # f = 1*m # z = 1*m wavelength = 1000 * nm N = 3000 #2840 size = 125 * mm f = 5.5*m z = f w0 = 1*mm # dx = wavelength*z/size # N = int(size/dx) F = Begin(size, wavelength, N) F= CircAperture(R=50*mm,Fin=F) F = Lens(F, f) # F = Fresnel(F, z) # F = Forvard(F, z) F = Propagate(F, f) # F2=LensFresnel(f2,f,F2); # F=LensFarField(F,f) # F=Forward(F) #############################Beita calculate start############################################### d = 100*mm FToCalB=F Dpow=calRediuswithPow.calRediuswithPow(FToCalB,0.839)*2 DTherory=2.44*FToCalB.lam*f/d beita=Dpow/DTherory print('The Beita is :',beita) #############################Beita calculate end############################################### ```
TrySphericalCoordinates.py ### Try use Spherical Coordinatesto calculate ```python from LightPipes import * import matplotlib.pyplot as plt #import Utils import calRediuswithPow def TheExample(N): fig = plt.figure(figsize=(15, 9.5)) ax1 = fig.add_subplot(221) ax2 = fig.add_subplot(222) ax3 = fig.add_subplot(223) ax4 = fig.add_subplot(224) labda = 1000 * nm size = 10 * mm f = 100 * cm f1 = 10 * m f2 = f1 * f / (f1 - f) frac = f / f1 newsize = frac * size w = 10 * mm w=w/5 #something wrong######################################### # wavelength = 1000 * nm # # N = 500 # size = 125 * mm # f = 500 * mm # z = 500 * mm # w0 = 1 * mm ############################################ F = Begin(size, labda, N) F = CircAperture(F, R=w) # 1) Using Lens and Fresnel: F1 = Lens(f, 0, 0, F) # F1 = Fresnel(f, F1) F1 = Propagate(F1,f) phi1 = Phase(F1) phi1 = PhaseUnwrap(phi1) I1 = Intensity(0, F1) x1 = [] for i in range(N): x1.append((-size / 2 + i * size / N) / mm) # 2) Using Lens + LensFresnel and Convert: F2 = Lens(f1, 0, 0, F) F2 = LensFresnel(f2, f, F2) F2 = Convert(F2) phi2 = Phase(F2) phi2 = PhaseUnwrap(phi2) I2 = Intensity(0, F2) #Utils.show(F2,"F2 Inten") x2 = [] for i in range(N): x2.append((-newsize / 2 + i * newsize / N) / mm) ax1.plot(x1, phi1[int(N / 2)], 'k--', label='Without spherical coordinates') ax1.plot(x2, phi2[int(N / 2)], 'k', label='With spherical coordinates') ax1.set_xlim(-newsize / 2 / mm, newsize / 2 / mm) ax1.set_ylim(-2, 4) ax1.set_xlabel('x [mm]') ax1.set_ylabel('phase [rad]') ax1.set_title('phase, N = %d' % N) legend = ax1.legend(loc='upper center', shadow=True) ax2.plot(x1, I1[int(N / 2)], 'k--', label='Without spherical coordinates') ax2.plot(x2, I2[int(N / 2)], 'k', label='With spherical coordinates') ax2.set_xlim(-newsize / 2 / mm, newsize / 2 / mm) ax2.set_ylim(0, 1000) ax2.set_xlabel('x [mm]') ax2.set_ylabel('Intensity [a.u.]') ax2.set_title('intensity, N = %d' % N) legend = ax2.legend(loc='upper center', shadow=True) ax3.imshow(I1) ax3.axis('off') ax3.set_title('Without spherical coordinates') ax3.set_xlim(int(N / 2) - N * frac / 2, int(N / 2) + N * frac / 2) ax3.set_ylim(int(N / 2) - N * frac / 2, int(N / 2) + N * frac / 2) ax4.imshow(I2) ax4.axis('off') ax4.set_title('With spherical coordinates') plt.figtext(0.3, 0.95, 'Spherical Coordinates, f = 100cm lens\nGrid dimension is: %d x %d pixels' % (N, N), fontsize=18, color='red') #############################Beita calculate start############################################### d = w FToCalB=F2 Dpow=calRediuswithPow.calRediuswithPow(FToCalB,0.839)*2 DTherory=2.44*FToCalB.lam*f/d beita=Dpow/DTherory print('The Beita is :',beita) #############################Beita calculate end############################################### # TheExample(100) # 100 x 100 grid TheExample(1000) # 1000 x 1000 grid plt.show() ```

Others

Spherical coordinates is a little hard to understand, for example I don't know how to set f1 and z. @ldoyle 's xplanation confused me even more

End

Thanks for your reading! I've been puzzling over these calculations for a long time, so if you have time please help me!

References

[1] Hecht E. Optics[M]. 5.Boston: Pearson Education, Inc.,2017: vi, 480-484. [2] Voelz D G.Computational fourier optics: a MATLAB tutorial[J],2011.