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
Pixel Brush Processing Unit

Pixel Brush Processing Unit The Pixel Brush Processing Unit (PBPU for short) is a simple 4-Bit CPU I designed in Logisim while I was still in school a

Pixel Brush 2 Nov 03, 2022
Gbs-image-colorizer - A tool to convert colorful pictures to GB Studio-compatible colorized backgrounds.

GB Studio Image Colorizer A tool to convert colorful pictures to GB Studio-compatible colorized backgrounds. Made by NalaFala/Yousurname/Y0UR-U5ERNAME

Yousurname 8 Dec 08, 2022
💯 Watermark your images with one line of command

Watermarker 💯 Watermark your images with one line of command 🧐 $ pip3 install

Orhan Emre Dikicigil 3 May 01, 2022
Me cleaner - Tool for partial deblobbing of Intel ME/TXE firmware images

me_cleaner me_cleaner is a Python script able to modify an Intel ME firmware image with the final purpose of reducing its ability to interact with the

Nicola Corna 4.1k Jan 08, 2023
sK1 2.0 cross-platform vector graphics editor

sK1 2.0 sK1 2.0 is a cross-platform open source vector graphics editor similar to CorelDRAW, Adobe Illustrator, or Freehand. sK1 is oriented for prepr

sK1 Project 238 Dec 04, 2022
Find target hash collisions for Apple's NeuralHash perceptual hash function.💣

neural-hash-collider Find target hash collisions for Apple's NeuralHash perceptual hash function. For example, starting from a picture of this cat, we

Anish Athalye 630 Jan 01, 2023
🎨 Generate and change color-schemes on the fly.

Generate and change color-schemes on the fly. Pywal is a tool that generates a color palette from the dominant colors in an image. It then applies the

dylan 6.9k Jan 03, 2023
Combinatorial image generator for generative NFT art.

ImageGen Stitches multiple image layers together into one image. Run usage: stitch.py [-h] backgrounds_dir dinos_dir traits_dir texture_file

Dinosols NFT 19 Sep 16, 2022
Next-generation of the non-destructive, node-based 2D image graphics editor

Non-destructive, node-based 2D image graphics editor written in Python, focused on simplicity, speed, elegance, and usability

Gimel Studio 238 Dec 30, 2022
A sketch like(?) effect for images

lineArt A sketch like(?) effect for images How to run main.py [filename] [option {1,2}] option 1 retains colour option 2 gives gray image #results ori

1 Oct 28, 2021
Optimize/Compress images using python

Image Optimization Using Python steps to run the script run the command to install the required libraries pip install -r requirements.txt create a dir

Shekhar Gupta 1 Oct 15, 2021
Png-to-stl - Converts PNG and text to SVG, and then extrudes that based on parameters

have ansible installed locally run ansible-playbook setup_application.yml this sets up directories, installs system packages, and sets up python envir

1 Jan 03, 2022
Generative Art Synthesizer - a python program that generates python programs that generates generative art

GAS - Generative Art Synthesizer Generative Art Synthesizer - a python program that generates python programs that generates generative art. Examples

Alexey Borsky 43 Dec 03, 2022
An executor that wraps 3D mesh models and encodes 3D content documents to d-dimension vector.

3D Mesh Encoder An Executor that receives Documents containing point sets data in its blob attribute, with shape (N, 3) and encodes it to embeddings o

Jina AI 11 Dec 14, 2022
Tool made for the FWA Yearbook Team to resize multiple images quickly.

ImageResize Tool Tool made for the FWA Yearbook Team to resize multiple images quickly. Make sure to check this repo for future updates How to Use The

LGobin 1 Jan 07, 2022
HTML2Image is a lightweight Python package that acts as a wrapper around the headless mode of existing web browsers to generate images from URLs and from HTML+CSS strings or files.

A package acting as a wrapper around the headless mode of existing web browsers to generate images from URLs and from HTML+CSS strings or files.

176 Jan 01, 2023
A QR Code encode and decode python module

A QR Code encode and decode python module

Fayas Noushad 4 Feb 10, 2022
Command line utility for converting images to seamless tiles

img2texture Command line utility for converting images to seamless tiles. The resulting tiles can be used as textures in games, compositing and 3D mod

Artёm IG 24 Dec 26, 2022
Simple Python package to convert an image into a quantized image using a customizable palette

Simple Python package to convert an image into a quantized image using a customizable palette. Resulting image can be displayed by ePaper displays such as Waveshare displays.

Luis Obis 3 Apr 13, 2022
HyperBlend is a new type of hyperspectral image simulator based on Blender.

HyperBlend version 0.1.0 This is the HyperBlend leaf spectra simulator developed in Spectral Laboratory of University of Jyväskylä. You can use and mo

SILMAE 2 Jun 20, 2022