Real-time laser beam profiler with Gaussian fitting for GenICam cameras.
- Real-time Gaussian fitting β 1D projections (230+ fps), 2D with rotation (50+ fps), linecut (300+ fps)
- Browser-based GUI β Dash web interface with live heatmap, fits, dark/light theme, 30+ color scales, and camera controls
- Multiple width definitions β Gaussian (1/eΒ²), FWHM, D4Ο (ISO 11146)
- GenICam hardware support β FLIR (Spinnaker) and Basler (Pylon) via Harvesters; auto-discovered features grouped by SFNC category
- Jupyter support β Live streaming with
bp.setting()interactive widgets - Simulated camera β Gaussian beam with noise, no hardware needed
- Auto-configuration β Pixel size detection for 40+ sensor models
pip install pybeamprofiler
# Run the browser GUI with a simulated camera (no hardware needed)
pybeamprofiler --camera simulated
# Or connect to real hardware
pybeamprofiler --camera flir # FLIR / Spinnaker
pybeamprofiler --camera basler # Basler / PylonThe browser opens automatically at http://127.0.0.1:8050. Press Ctrl+C in the terminal to stop the server and exit.
pip install pybeamprofilerFor real hardware (FLIR or Basler), also install the corresponding SDK and set the CTI path:
| Vendor | SDK | GENICAM_GENTL64_PATH |
|---|---|---|
| FLIR | Spinnaker | /usr/local/lib/spinnaker-gentl (macOS/Linux) |
| Basler (macOS) | Pylon | /Library/Frameworks/pylon.framework/Libraries/gentlproducer/gtl |
| Basler (Linux) | Pylon | /opt/pylon/lib64/gentlproducer/gtl |
| Basler (Windows) | Pylon | C:\Program Files\Basler\pylon\Runtime\x64 |
export GENICAM_GENTL64_PATH=/path/to/cti/filesNote: GenICam cameras allow only one application to connect at a time β close Spinnaker GUI / Pylon Viewer first.
pybeamprofiler --camera simulated # simulated camera
pybeamprofiler --camera flir # FLIR / Spinnaker
pybeamprofiler --camera basler # Basler / Pylon
pybeamprofiler --file beam.png # static image
pybeamprofiler --fit 2d --definition fwhm
pybeamprofiler --help # all optionsPress Ctrl+C in the terminal to stop streaming and exit.
from pybeamprofiler import BeamProfiler, print_camera_info
print_camera_info() # list connected cameras
bp = BeamProfiler(camera="simulated")
bp.plot() # open browser GUI
bp.plot(num_img=1) # single shot
print(f"Width X: {bp.width_x:.1f} ΞΌm, Y: {bp.width_y:.1f} ΞΌm")
print(f"Center: ({bp.center_x:.1f}, {bp.center_y:.1f}) px")
# Change settings
bp.setting(exposure_time=0.05, Gain=10.0)
# In Jupyter: open interactive control panel
bp.setting()See the API docs for fitting methods (1d, 2d, linecut), width definitions (gaussian, fwhm, d4s), ROI control, and more.
- Camera not found β verify SDK install,
GENICAM_GENTL64_PATH, and runprint_camera_info(). - Access denied β close other camera software (Spinnaker GUI, Pylon Viewer).
- Jupyter camera stuck β restart the kernel to release the hardware lock.
- Basler USB3 β pass the USB3 CTI explicitly:
BaslerCamera(cti_file="/path/to/ProducerU3V.cti").
git clone https://github.com/acechenx/pybeamprofiler.git
cd pybeamprofiler
uv sync --extra dev
uv run pre-commit installuv run ruff check src tests
uv run ruff format src tests
uv run ty check src testsuv run pytest # all tests + coverage
uv run pytest --cov-report=html # HTML coverage report
uv run pytest tests/test_profiler.py # single fileCurrent suite: 588 tests, 97% coverage.
beamprofiler.pyβBeamProfilerclass, fitting algorithms, CLI entry pointcamera.pyβ abstractCamerabase class + Jupyter widget buildergen_camera.pyβHarvesterCamerafor GenICam devicesflir.py/basler.pyβ vendor-specific subclassessimulated.pyβSimulatedCamera(no hardware)dash_app.pyβ browser GUI with live updates, settings panel, pattern-matching callbacksutils.pyβ camera discovery helpersconstants.pyβ shared constants
- Fork and create a feature branch
- Add tests for new functionality
- Ensure
uv run pytest,uv run ruff check, anduv run ty checkpass - Submit a pull request
- 2D fits use adaptive downsampling + Levenberg-Marquardt warm starts
- Projection profiles are cached between
analyze()and figure rendering - In the current Dash implementation, live updates perform
bp.camera.get_image(timeout=0.1)andbp.analyze(img)synchronously while holding athreading.Lockto reduce segfault risk in the Harvesters C library
Auto-detected pixel sizes (40+ models) β Sony IMX174, IMX183, IMX226, IMX249, IMX250, IMX252, IMX253, IMX255, IMX264, IMX265, IMX273, IMX287, IMX290, IMX291, IMX304, IMX392, IMX412, IMX477, IMX485, IMX530, IMX531, IMX540, IMX541, IMX542, IMX547, and direct Basler model lookups (acA4024-8gm, acA4024-29um, acA1920-155um, acA2440-75um, acA3800-14um).
MIT β see LICENSE.
C.-A. Chen (acechen@cirx.org)
- Built on Harvesters, Plotly/Dash
- Inspired by LaseView (old freeware), ptomato/Beams, jordens/bullseye
- FLIR and Basler cameras loaned from Atom Computing for testing