Kelia
Kelia

Reputation: 1

Curve fitting of the laser beam radius W(z) versus propagation distance z

I am taking 5 measurements of the laser beam radius at various distances between 1-200 cm. Without knowing where the beam waist Wo is, I am trying to use the curve_fit() function to find the opt value of Wo and Zo. The output I am getting seems wrong. The focus it finds is 0.75mm at z=0.1cm. However my measurements show a point where the radius reached 0.595mm (<0.75mm) and that point is at z=160cm. so zo is 160 cm from the laser source. I am uploading the code I've written and the output plot.graph-->

import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt


def BeamRadius(z, Wo, Zo):
    return Wo * np.sqrt(1 + (((4.03225 * 10**-13) / (np.pi**2)) * ((z-Zo) / Wo)**2))


def difdiv(l, Wo):
    return 2*(l/(np.pi*Wo))


def main():
# z : distance from laser, zo: where the waist/ laser focus is
z1 = 10*10
z2= 20*10  # *10 to get mm
z3= 30*10
z4= 50*10
z5= 70*10
z6= 100*10
z7 = 110*10
z8= 140*10
z9= 150*10
z10= 155*10
z11= 160*10
z12= 165*10
z13= 170*10
z14= 180*10
# Beam Radius in mm at z cm from the laser
wz1 = 1.02
wz2= 1.0035  # mm
wz3= 0.9695
wz4= 0.9385
wz5= 0.885
wz6= 0.7465
wz7 = 0.715
wz8= 0.625
wz9= 0.613775
wz10= 0.60936
wz11= 0.595
wz12= 0.605
wz13= 0.61815
wz14= 0.6465
z_array = np.array([z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14])
wz_array = np.array([wz1, wz2, wz3, wz4, wz5, wz6, wz7, wz8, wz9,wz10,wz11,wz12,wz13,wz14])
print(z_array, "and ", wz_array)
p_opt, p_cov = curve_fit(BeamRadius, z_array, wz_array)
BeamFit = BeamRadius(z_array, p_opt[0], p_opt[1])

I am not sure if curve_fit is correct or if I should use fitpredict. I haven't found much on fitpredict and I don't know how to use it. I have thought of trying supervised learning but haven't made any progress. I appreciate any ideas/feedback you can give.

Upvotes: 0

Views: 460

Answers (3)

JJacquelin
JJacquelin

Reputation: 1705

If I well understand your code the model equation is :

enter image description here

With this approach the fitting is reduced to a simple problem of linear regression for three parameters a,b,c.

The hitch is that this three parameters linear regression applied to the given data leads to a value of the parameter (a) extremely different from the value that you set in your code : a=4.0325*10**(-13)/pi**2

This draw to think that there is a typo or a mistake. Maybe a confusion of units used in measumements and units in theoretical equation.

The wrong value of (a) in your formula might be the main cause of trouble that you observed.

If the value of the parameter (a) is considered as a known value a two parameters linear regression leads to b and c then to zo and wo. For example :

enter image description here

Another cause of deviation (but of low importance compared to the preceeding one) is that the equation model is not good enough for low values of z.

For example if we take only half of the points (range 1200<z<2000) the three parameters linear regression for a,b,c gives :

enter image description here

Upvotes: 0

ljelschen
ljelschen

Reputation: 1

Hey the right way to prpagate is fitting a hyperbole-function its defined after the ISO 11146. However im stuck in this Topic myself.

You need to get more then five mesurepoins in the rayleigh range (zr) and outside the rayleigh range

try to fit this and use the p0 Parameter in the curve_fit funktion:

def dz(z, d0, z0, zr):
    return d0 * np.sqrt(1 + ((z-z0)/zr)**2)

#start fit parameters d0, z0, zr
p0 = [0.3, 150, 5]
#curve fit
p_opt, p_cov = curve_fit(dz, z_array, wz_array, p0=p0)

Upvotes: 0

Ugur Yigit
Ugur Yigit

Reputation: 230

Since you have limited data, curve fit may be a good option but if i were you, i would give a chance to linear regression model. Since the data is very limited, dont waste your time for ML algorithms like tree based ones etc.

I'm not familiar to your topic but I assume you have X and Y values to fit therefore:

Sample linear regression code for your case:

import statsmodels.api as sm

z_array = sm.add_constant(z_array, prepend=False)
mod = sm.OLS(wz_array, z_array)
res = mod.fit()
print(res.summary())

Upvotes: 0

Related Questions