Git Product home page Git Product logo

laserbeamsize's Introduction

laserbeamsize

by Scott Prahl

pypi github conda zenodo

License testing docs Downloads

Simple and fast calculation of beam sizes from a single monochrome image based on the ISO 11146 method of variances. Some effort has been made to make the algorithm less sensitive to background offset and noise.

This module also supports M² calculations based on a series of images collected at various distances from the focused beam.

Extensive documentation can be found at <https://laserbeamsize.readthedocs.io>

Installation

Use pip:

pip install --user laserbeamsize

or conda:

conda install -c conda-forge laserbeamsize

or use immediately by clicking the Google Colaboratory button below

Colab

Determining the beam size in an image

Finding the center and dimensions of a good beam image:

import imageio.v3 as iio
import laserbeamsize as lbs

file = "https://github.com/scottprahl/laserbeamsize/raw/main/docs/t-hene.pgm"
image = iio.imread(file)

x, y, dx, dy, phi = lbs.beam_size(image)
print("The center of the beam ellipse is at (%.0f, %.0f)" % (x, y))
print("The ellipse diameter (closest to horizontal) is %.0f pixels" % dx)
print("The ellipse diameter (closest to   vertical) is %.0f pixels" % dy)
print("The ellipse is rotated %.0f° ccw from the horizontal" % (phi * 180/3.1416))

to produce:

The center of the beam ellipse is at (651, 492)
The ellipse diameter (closest to horizontal) is 369 pixels
The ellipse diameter (closest to   vertical) is 347 pixels
The ellipse is rotated -12° ccw from the horizontal

A visual report can be done with one function call:

lbs.plot_image_analysis(beam)
plt.show()

produces something like

HeNe report

or:

lbs.plot_image_analysis(beam, r"Original Image $\lambda$=4µm beam", pixel_size = 12, units='µm')
plt.show()

produces something like

astigmatic report

Non-gaussian beams work too:

# 12-bit pixel image stored as high-order bits in 16-bit integers
tem02 = imageio.imread("TEM02_100mm.pgm") >> 4
lbs.plot_image_analysis(tem02, title = r"TEM$_{02}$ at z=100mm", pixel_size=3.75)
plt.show()

produces

TEM02

Determining M²

Determining M² for a laser beam is also straightforward. Just collect beam diameters from five beam locations within one Rayleigh distance of the focus and from five locations more than two Rayleigh distances:

lambda1=308e-9 # meters
z1_all=np.array([-200,-180,-160,-140,-120,-100,-80,-60,-40,-20,0,20,40,60,80,99,120,140,160,180,200])*1e-3
d1_all=2*np.array([416,384,366,311,279,245,216,176,151,120,101,93,102,120,147,177,217,256,291,316,348])*1e-6
lbs.M2_radius_plot(z1_all, d1_all, lambda1, strict=True)
plt.show()

produces

fit for M2

Here is an analysis of a set of images that do not meet the ISO 11146 requirements for determining M² (because the image locations are not taken in right locations relative to the focus). These beam images are from a HeNe laser with slightly misaligned mirrors to primarily lase in a TEM₀₁ transverse mode. The laser resonator had a fixed rotation of 38.7° from the plane of the optical table.:

lambda0 = 632.8e-9 # meters
z10 = np.array([247,251,259,266,281,292])*1e-3 # meters
filenames = ["sb_%.0fmm_10.pgm" % (number*1e3) for number in z10]

# the 12-bit pixel images are stored in high-order bits in 16-bit values
tem10 = [imageio.imread(name)>>4 for name in filenames]

# remove top to eliminate artifact 
for i in range(len(z10)):
    tem10[i] = tem10[i][200:,:]

# find beam rotated by 38.7° in all images
fixed_rotation = np.radians(38.7)
options = {'pixel_size': 3.75, 'units': "µm", 'crop': [1400,1400], 'z':z10, 'phi':fixed_rotation}
dy, dx= lbs.beam_size_montage(tem10, **options)  # dy and dx in microns
plt.show()

produces

montage of laser images

Here is one way to plot the fit using the above diameters:

lbs.M2_diameter_plot(z10, dx*1e-6, lambda0, dy=dy*1e-6)
plt.show()

In the graph on the below right, the dashed line shows the expected divergence of a pure gaussian beam. Since real beams should diverge faster than this (not slower) there is some problem with the measurements (too few!). On the other hand, the M² value the semi-major axis 2.6±0.7 is consistent with the expected value of 3 for the TEM₁₀ mode.

fit

License

laserbeamsize is licensed under the terms of the MIT license.

laserbeamsize's People

Contributors

actions-user avatar scottbreitenstein avatar scottprahl avatar sreich-emi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

laserbeamsize's Issues

Beam diameter estimation

Hello!

I'm getting wrong beam diameter estimation. Here is the result of lbs.beam_size_plot(beam, pixel_size=5.2, units='µm') :

image

Original image: image.zip

subtract_image / subtract_threshold implementation iso conform?

A colleague of mine brought up that the clipping to zero done in these functions is not mentioned in the iso standard. Therefore this wouldn't be completely iso conform. Instead, negative numbers should be used for the next steps. Would you be interested in changing this?

Gaussian fit problem for asymmetric (astigmatic) beams

Dear Scott,

Thank you for this amazingly useful library.
I have just discovered that Gaussian fit seems to be invalid for heavily astigmatic beams, and therefore, the function returns the incorrect beam diameters. Please refer to the image below.
Picture1

Is there any parameter to overcome the problem?

UPD
It seems (from the values) that dx and dy are just mixed up here

Regards

definition of fitting function in m2.py

I like this module, as is makes analysis very easy. However, I wonder about the fitting for M2. Especially I refer to

def _beam_fit_fn_(z, d0, z0, Theta): """Fitting function for d0, z0, and Theta.""" return d0**2 + (Theta*(z-z0))**2

I understand the idea of fitting d(z)^2 = ... wwithout the sqrt. But if I change the input from d**2 to d and also the function from d0**2 + (Theta*(z-z0))**2 to np.sqrt(d0**2 + (Theta*(z-z0))**2), I get different results.

Has anyone an idea, where this change comes from and how to get the proper output? Which of the two versions is right?

focused_diameter question

I noticed that you have a focused_diameter function for the diffraction limited spot size. In the function, the size is not proportional to the $M^2$, but $(M^2)^2$.

This is different to what I would expect and other treatments of this. Nevertheless, I was able to dig up the equation in the referenced text and it is indeed $M^4$. Although interestingly that seems inconsistent with their own definition in their figure 12.30 which is immediately above the equation, $d_0 = M^2 d_{00}$. And also as a sanity check, consider when defined by divergence angle, $M^2$ is inversely proportional to wavelength. Then wavelengths would not cancel and you would have the situation where the focused spot size decreases as wavelength increases.

Just wondering if the equation is right or I have some confusion here.

Thank you for contributing this library and the documentation, I have found it very useful and works great so far. I shall now be able to retire my personal, much less complete beam profiling code.

Data printed differs from data in plot

Hi Scott Prahl,
Thanks for code. I've just used your code in data processing.
But i find data printed differs from data in plot with my experiment data.
And i cannot find what happened to this. Please help~

Here is the detailed information.

Data Printed

         laserbeamsize
M2x      1.29 ± 0.03   
M2y      1.07 ± 0.11   

d0x       152 ± 3 µm   
d0y       135 ± 14 µm  

Thetax    5.28 ± 0 mrad
Thetay    4.95 ± 0 mrad

z0x       -276 ± 1 mm  
z0y       -277 ± 3 mm  

zRx       29 ± 1 mm    
zRy       27 ± 6 mm

PLOT
图片

Experiment data

lambda4 = 488e-9
d_scan_head = 0
f = 150
z = np.array([210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320,
              760, 770, 780, 790, 800, 810, 820, 830, 840, 850]) * 1e-3
dx = np.array([397.4, 330.2, 284.4, 242.8, 192.6, 167.1, 142.1, 148.5, 180.7, 206.1, 242.3,
               287.5, 2570.9, 2622.5, 2675.6, 2726.5, 2780.2, 2832.2, 2886.8, 2939.3, 2992.1, 3024.3]) * 1e-6
dy = np.array([382.3, 329.4, 277.9, 226.1, 182.1, 149.1, 128.5, 126.3, 145.8, 178.2, 220.7,
               263.7, 2465.3, 2503.9, 2540.6, 2574.7, 2608.4, 2641.9, 2677.1, 2712.5, 2739.9, 2768.1]) * 1e-6

Cannot specify the tilt angle as zero

When specifying the phi argument of lbs.beam_size, a zero value (0.0) is not accepted.
It is, however, useful to do so, e.g., for measuring the m2 of an astigmatic beam.

Looking into the code, I'm pretty sure the reason is in line 205 of laserbeamsize/analysis.py:

phi_ = phi or phi_

There is a workaround I used, that is specifying phi as a really small but nonzero value or 180degrees, however I don't think this is elegant and yields unexpected results.

I think a robust fix would be a change to

phi_ = phi if phi is not None else phi_

in lines 205 and 223 of laserbeamsize/analysis.py.

This would require no further changes.
Would you be interested in considering this?

Thanks for this great module, I use it all the time!

Small MWE

>>> phi = 0.0
>>> phi_ =  1.0
>>> phi or phi_ # Gives phi_, even though phi is defined
1.0
>>> phi if phi is not None else phi_ # Works as expected
0.0

Working with the highly astigmatic beams

Hello!

I have a highly astigmatic laser diode. At some point after a lens I getting this with lbs.beam_size_montage():

image
image

No problems with estimating the center of the beam, but axes are rotated by 45 degrees. Laser modes are aligned along x and y axes, no need to rotate them (almost).

Is there any type of workaround for this problem?

Here is the original image from Thorlabs DCC1545M: astigmatic_beam.zip

P.S. Thanks a lot for this project !!!

AttributeError: module 'laserbeamsize' has no attribute 'beam_size_plot”

When I use your code:

import imageio.v3 as iio
import laserbeamsize as lbs

file = "https://github.com/scottprahl/laserbeamsize/raw/master/docs/t-hene.pgm"
image = iio.imread(file)

x, y, dx, dy, phi = lbs.beam_size(image)
print("The center of the beam ellipse is at (%.0f, %.0f)" % (x, y))
print("The ellipse diameter (closest to horizontal) is %.0f pixels" % dx)
print("The ellipse diameter (closest to vertical) is %.0f pixels" % dy)
print("The ellipse is rotated %.0f° ccw from the horizontal" % (phi * 180/3.1416))

I can get the expected results.

But then I follow your instructions from the screenshot1.png:

"A visual report can be done with one function call:

lbs.beam_size_plot(beam)
plt.show() "

The code would return error: AttributeError: module 'laserbeamsize' has no attribute 'beam_size_plot',pls see the screenshot2.png.

I wonder whether there is some trouble with my understanding on your code? And I also search the "beam_size_plot" in all the API from your link "https://laserbeamsize.readthedocs.io/en/latest/index.html",
and cannot find the "beam_size_plot" attribute.
screenshot1
screenshot2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.