Extract the ISO 11146 beam size from an image file

Overview

laserbeamsize


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>

Using laserbeamsize

  1. Install with pip:

    pip install --user laserbeamsize
    
  2. or run this code in the cloud using Google Collaboratory by selecting the Jupyter notebook that interests you.

  3. use binder which will create a new environment that allows you to run Jupyter notebooks. This takes a bit longer to start, but it automatically installs laserbeamsize.

  4. clone the laserbeamsize github repository and then add the repository to your PYTHONPATH environment variable

Determining the beam size in an image

Finding the center and dimensions of a good beam image:

import imageio
import numpy as np
import matplotlib.pyplot as plt
import laserbeamsize as lbs

beam = imageio.imread("t-hene.pgm")
x, y, dx, dy, phi = lbs.beam_size(beam)

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 horizontal" % (phi*180/3.1416))

to produce:

The center of the beam ellipse is at (651, 491)
The ellipse diameter (closest to horizontal) is 334 pixels
The ellipse diameter (closest to   vertical) is 327 pixels
The ellipse is rotated 29° ccw from the horizontal

A visual report can be done with one function call:

lbs.beam_size_plot(beam)
plt.show()

produces something like

hene-report.png

or:

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

produces something like

astigmatic-report.png

Non-gaussian beams work too:

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

produces

tem02.png

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

m2fit.png

Here is an analysis of a set of images that were insufficient for ISO 11146:

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 in all the images and create arrays of beam diameters
options = {'pixel_size': 3.75, 'units': "µm", 'crop': [1400,1400], 'z':z10}
dy, dx= lbs.beam_size_montage(tem10, **options)  # dy and dx in microns
plt.show()

produces

sbmontage.png

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.

sbfit.png

License

laserbeamsize is licensed under the terms of the MIT license.

Comments
  • Gaussian fit problem for asymmetric (astigmatic) beams

    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

    opened by Werefkin 7
  • Working with the highly astigmatic beams

    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 !!!

    opened by arktrin 6
  • definition of fitting function in m2.py

    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?

    opened by SReich-EMI 3
  • added BPP as output parameter

    added BPP as output parameter

    added the BPP=Theta*d0/4 to the calculations. For us this is always an important value, knowing that it is easily to calculate from M2. I don't know if I have found all poisitions, where to add the BPP, as I could only test one type of analysis with my data.

    opened by SReich-EMI 3
  • Beam diameter estimation

    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

    opened by arktrin 1
  • rotated_rect_mask speedup

    rotated_rect_mask speedup

    I want to use this package on data coming at 10Hz but found that the current version was too slow for this. After some profiling, I found that rotated_rect_mask is slow as it rotates the whole image instead of just drawing a rotated rectangle. I wrote an alternative implementation that does that.

    I also added a test to make sure that the result is the same as for the normal implementation and changed depreciated np.float to float.

    opened by HTuennermann 1
  • Bump jinja2 from 2.11.2 to 2.11.3 in /docs

    Bump jinja2 from 2.11.2 to 2.11.3 in /docs

    Bumps jinja2 from 2.11.2 to 2.11.3.

    Release notes

    Sourced from jinja2's releases.

    2.11.3

    This contains a fix for a speed issue with the urlize filter. urlize is likely to be called on untrusted user input. For certain inputs some of the regular expressions used to parse the text could take a very long time due to backtracking. As part of the fix, the email matching became slightly stricter. The various speedups apply to urlize in general, not just the specific input cases.

    Changelog

    Sourced from jinja2's changelog.

    Version 2.11.3

    Released 2021-01-31

    • Improve the speed of the urlize filter by reducing regex backtracking. Email matching requires a word character at the start of the domain part, and only word characters in the TLD. :pr:1343
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • beam centers as float

    beam centers as float

    As my beams are not always perfeclty located at a pixel, I need the position as float and not int. Is there a reason for this restriction?

    for disc of round beam ISO says abs(2*xy)

    opened by SReich-EMI 0
  • New subtract_tilted_background

    New subtract_tilted_background

    I rewrote subtract_tilted_background so it now samples every point around a perimeter with width equal to the width of the corner boxes. I made a new function, perimeter_mask, to enable this. The new function works just as fast despite fitting many more points, and the result is now consistent from one run to the next because the randomness is removed. I updated the notebook to show the perimeter mask function.

    opened by scottbreitenstein 0
  • subtract_image / subtract_threshold implementation iso conform?

    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?

    opened by HTuennermann 1
Releases(v1.9.4)
  • v1.9.4(Mar 19, 2022)

    v1.9.4

    • allow beam angle to be specified during fitting
    • new notebook to illustrate constrained fits
    • improve docstrings and therefore api documentation
    • still better ellipse and rect outlines
    • start adding examples

    v1.9.3

    • use faster version of creating rotated rect mask
    • move tests to their own directory
    • avoid deprecated np.float
    • improve drawing of rect and ellipse outlines
    • improve some docstrings
    Source code(tar.gz)
    Source code(zip)
  • v1.9.3(Mar 15, 2022)

    v1.9.3

    • use faster version of creating rotated rect mask
    • move tests to their own directory
    • avoid deprecated np.float
    • improve drawing of rect and ellipse outlines
    • improve some docstrings

    v1.9.2

    • use both black and white dashed lines
    • fit to d and not d**2
    • add more dunders to init.py
    • fix residual calculation broken in v1.9.1
    Source code(tar.gz)
    Source code(zip)
  • v1.9.2(Mar 13, 2022)

    M² is found by fitting to a hyperbola. Heretofore the hyperbola was fit using d², laserbeamsize now uses d. Both methods give nearly identical results, but I believe fitting to d is more correct.

    v1.9.2

    • use both black and white dashed lines
    • fit to d and not d**2
    • add more dunders to init.py
    • fix residual calculation broken in v1.9.1

    v1.9.1

    • centralize version number to a single place

    v1.9.0

    • add beam_ellipticity()
    • add beam_parameter_product()
    • rotate x-tick labels when more than 10 ticks
    • removed deprecated use of np.matrix()
    • M2_report now includes BPP values
    • improve API docs
    • code linting
    Source code(tar.gz)
    Source code(zip)
  • v1.9.1(Mar 10, 2022)

    No features. This just reduces the number of places version numbers are used from 3 (setup.cfg, docs/conf.py, laserbeamsize/__init__.py) down to just the __init__.py file.

    v1.9.1

    • centralize version number to a single place

    v1.9.0

    • add beam_ellipticity()
    • add beam_parameter_product()
    • rotate x-tick labels when more than 10 ticks
    • removed deprecated use of np.matrix()
    • M2_report now includes BPP values
    • improve API docs
    • code linting
    Source code(tar.gz)
    Source code(zip)
  • v1.9.0(Mar 9, 2022)

    v1.9.0

    • add beam_ellipticity()
    • add beam_parameter_product()
    • rotate x-tick labels when more than 10 ticks
    • removed deprecated use of np.matrix()
    • M2_report now includes BPP values
    • improve API docs
    • code linting

    v1.8.0

    • handle rotated masks properly
    • fix readthedoc configuration
    Source code(tar.gz)
    Source code(zip)
  • v1.8.0(Dec 15, 2021)

    Internally, laserbeamsize masks the laser spot in the image. This involves rotating a binary mask which sometimes creates pixels that are not exactly 1. Guilhem noticed this and suggested a fix.

    Additionally, building of doc files on readthedocs.io has been made more robust.

    Source code(tar.gz)
    Source code(zip)
  • v1.7.3(Aug 7, 2021)

    v1.7.3

    • create pure python packaging
    • include wheel file
    • package as python3 only

    v1.7.2

    • allow non-integer beam centers
    • add badges to docs
    • use sphinx-book-theme for docs

    v1.7.1

    • explicit warning for non-monochrome images in beam_size()
    • improve help() messages

    v1.7.0

    • fix error in identifying major/minor axes in beam_size_plot()
    Source code(tar.gz)
    Source code(zip)
  • v1.7.2(Mar 22, 2021)

    v1.7.2

    • allow non-integer beam centers
    • add badges to docs
    • use sphinx-book-theme for docs

    v1.7.1

    • explicit warning for non-monochrome images in beam_size()
    • improve help() messages

    v1.7.0

    • fix error in identifying major/minor axes in beam_size_plot()
    Source code(tar.gz)
    Source code(zip)
  • v1.7.1(Jan 3, 2021)

  • v1.7.0(Nov 11, 2020)

  • v1.6.1(Sep 30, 2020)

    Minor release.

    • Fix the deprecation warning for register_cmap
    • a sphinx and pydocstyle warnings
    • use all points on background rect for fitting tilted background
    Source code(tar.gz)
    Source code(zip)
  • v1.6.0(Aug 3, 2020)

    A number of small changes and

    • new function subtract_tilted_background()
    • M²=1 line added M2_radius_plot()
    • autoselect line color on images for visibility (still imperfect)
    • documentation tweaks
    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(Jul 28, 2020)

    Support for ISO 11146 measurement of M² now. If you have an array of images, then analysis can be as simple as::

    import imageio
    import matplotlib.pyplot as plt
    import laserbeamsize as lbs
    
    images = [imageio.imread(name) for name in list_of_filenames]
    dy, dx= lbs.beam_size_montage(images, pixel_size=3.75)  # pixel_size in microns
    plt.show()
    lbs.M2_diameter_plot(z10, dx*1e-6, lambda0, dy=dy*1e-6)
    plt.show()
    
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Jun 7, 2020)

    New feature. visual_report() creates four subplots to show the beam analysis. Other updates include::

    • Add routines to plot values along semi axes
    • Fix error when calculating circular radius
    • Add missing scipy requirement
    • Improve README.rst with figure
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jun 3, 2020)

    Previously, laserbeamsize used the standard definitions for the first and second order moments of the WIgner distribution to calculate beam parameters.

    This version now also follows ISO 11146 for

    • integration areas
    • background using corners
    • background subtraction

    The overall result is that beam parameters extraction is much more robust.

    Source code(tar.gz)
    Source code(zip)
  • v1.0.3(May 20, 2020)

Owner
Scott Prahl
Scott Prahl
MikuMikuRig是一款集生成控制器,自动导入动画,自动布料为一体的blender插件

Miku_Miku_Rig MikuMikuRig是一款集生成控制器,自动导入动画,自动布料为一体的blender插件。 MikumiKurig is a Blender plugin that can generates rig, automatically imports animations

小威廉伯爵 342 Dec 29, 2022
Convert the SVG code to PNG and replace the line by a call to the image in markdown

Convert the SVG code to PNG and replace the line by a call to the image in markdown

6 Sep 06, 2022
Make GIFs from time-stacked xarray.DataArrays (time, [optional band], y, x), dead-simple.

GeoGIF Make GIFs from time-stacked xarray.DataArrays (time, [optional band], y, x), dead-simple. from geogif import gif, dgif gif(data_array) dgif(das

Gabe Joseph 47 Dec 22, 2022
An open source image editor which can manipulate an image in many ways!

Image Editor - An open source image editor which can manipulate an image in many ways! If you need any more modes in repo or I

TroJanzHEX 44 Nov 17, 2022
A collection of python scripts which help you programatically create PNGs or GIFs

A collection of python scripts which help you programatically create PNGs or GIFs and their Metadata in bulk with custom rarity rates, upload them to OpenSea & list them for sale.

Tom 30 Dec 24, 2022
QR code python application which can read(decode) and generate(encode) QR codes.

QR Code Application This is a basic QR Code application. Using this application you can generate QR code for you text/links. Using this application yo

Atharva Parkhe 1 Aug 09, 2022
Advance Image Steganography

Chaya Advance Image Steganography Using LSB-LPS + AES-256-GCM + FLIF Right To Privacy! United Nations Declaration of Human Rights (UDHR) 1948, Article

XeroHack 113 Dec 02, 2022
missing-pixel-filler is a python package that, given images that may contain missing data regions (like satellite imagery with swath gaps), returns these images with the regions filled.

Missing Pixel Filler This is the official code repository for the Missing Pixel Filler by SpaceML. missing-pixel-filler is a python package that, give

SpaceML 11 Jul 19, 2022
Extracts dominating colors from an image and presents them as a palette.

ColorPalette A simple web app to extract dominant colors from an image. Demo Live View it live at : https://colorpalettedemo.herokuapp.com/ You can de

Mayank Nader 214 Dec 29, 2022
Music Thumbnail Maker

Music Thumbnail Installing pip install TMFrame

krypton 4 Jan 28, 2022
Alternate Python bindings for the Open Asset Import Library (ASSIMP)

Impasse A simple Python wrapper for assimp using cffi to access the library. Requires Python = 3.7. It's a fork of PyAssimp, Assimp's official Python

Salad Dais 3 Sep 26, 2022
thumbor is an open-source photo thumbnail service by globo.com

Survey If you use thumbor, please take 1 minute and answer this survey? It's only 2 questions and one is multiple choice!!! thumbor is a smart imaging

Thumbor (by @globocom) 9.3k Dec 31, 2022
Steganography Image/Data Injector.

Byte Steganography Image/Data Injector. For artists or people to inject their own print/data into their images. TODO Add more file formats to support.

Ori 4 Nov 16, 2022
This tool allows the user to convert a 16 by 16 image into a list with numbers representing an object/character.

Room Formatter This tool allows the user to convert a 16 by 16 image into a list with numbers representing an object/character. There is cur

Thomas Landstra 1 Nov 13, 2021
3D printer / slicing GUI built on top of the Uranium framework

Cura Ultimaker Cura is a state-of-the-art slicer application to prepare your 3D models for printing with a 3D printer. With hundreds of settings and h

Ultimaker 4.4k Jan 02, 2023
Parking management project which generates barcode parking ticket with user-friendly Tkinter program GUI

Parking-management-system Parking management project which generates barcode parking ticket with user-friendly Tkinter program GUI How to run Download

1 Jul 03, 2022
An esoteric visual language that takes image files as input based on a multi-tape turing machine, designed for compatibility with C.

vizh An esoteric visual language that takes image files as input based on a multi-tape turing machine, designed for compatibility with C. Overview Her

Sy Brand 228 Dec 17, 2022
A utility for quickly cropping large collections of images.

Crop Tool A utility for quickly cropping large collections of images. Inspired by Derrick Schultz's dataset-tools. Setup It's suggested that you use A

dusk (they/them) 6 Nov 14, 2021
BeeRef — A Simple Reference Image Viewer

BeeRef — A Simple Reference Image Viewer BeeRef lets you quickly arrange your reference images and view them while you create. Its minimal interface i

Rebecca 245 Dec 25, 2022
Utilities for SteamVR on Linux

This project contains scripts to improve the functionally of SteamVR on Linux:

86 Dec 29, 2022