Analyze images of microspheres for characterizing light microscopy systems. Measures FWHM, PSF shape, SNR, and symmetry from fluorescent beads in entire 3D image stacks or lateral regions within them. Supports manual bead selection, classical blob/trackpy detection, StarDist automatic detection, and Cellpose with custom-trained models.
Choose the method that best fits your workflow:
To prevent conflicts with other imaging tools, we highly recommend using a fresh environment:
# Create and activate a clean environment
conda create -n bead-env python=3.10
conda activate bead-env
# Install the analyzer
pip install .For optional detection backends:
pip install ".[stardist]" # StarDist support
pip install ".[cellpose]" # Cellpose supportIf you do not use Git, follow these steps to get running in minutes:
- Download: Click the green "<> Code" button above and select "Download ZIP".
- Extract: Unzip the folder to your analysis directory (e.g.,
D:\Analysis\bead-analyzer). - Verify & Install: Open a terminal (PowerShell or Terminal.app), navigate to that folder, and run:
python install_check.py # Run the built-in environment checker
pip install .# Launch the Graphical Interface
bead-analyzer-gui
# Use the Command Line (default mode = blob)
bead-analyzer image.tif --scale_xy 0.26 --scale_z 2.0The command-line interface supports five detection modes. Required arguments: input file, --scale_xy, and --scale_z.
# Show all options
bead-analyzer --help
# Blob: classical detector (recommended default for most bead slides)
bead-analyzer beads.tif --mode blob --scale_xy 0.26 --scale_z 2 --fit_gaussian
# Trackpy: robust under intensity gradients / low-NA backgrounds
bead-analyzer beads.tif --mode trackpy --scale_xy 0.26 --scale_z 2 --fit_gaussian
# StarDist: neural network (best when beads are ~15+ px diameter)
bead-analyzer beads.tif --mode stardist --scale_xy 0.26 --scale_z 2 --fit_gaussian --max_z_fwhm 15
# Cellpose: custom model (best when beads are ~15+ px diameter)
bead-analyzer beads.tif --mode cellpose --scale_xy 0.26 --scale_z 2 --cellpose_model path/to/model --fit_gaussianAdd --na 1.4 --fluorophore "FITC" to record experimental metadata in the summary. Use --output_dir ./results to write outputs to a different folder. See docs/CLI.md for full reference.
| Mode | Description | Dependencies |
|---|---|---|
| Manual | Right-click on beads in MIP | Base only |
| Blob | Classical Gaussian smooth + local maxima | Base only |
| Trackpy | Bandpass filter + sub-pixel centroid detection | trackpy |
| StarDist | Automatic detection (pretrained neural network) | stardist, csbdeep |
| Cellpose | Custom model, requires training | cellpose, torch |
- Blob path: recommended default for most bead slides, especially tiny beads.
- Trackpy path: preferred when backgrounds have gradients or low-NA blur.
- StarDist/Cellpose path: best when beads span roughly 15+ pixels in diameter.
- Cellpose 3D: for anisotropic z-stacks, use
--cellpose_do_3d --anisotropy (z_spacing/xy_spacing).
- StarDist on native Windows: often CPU-heavy in practical setups because StarDist depends on TensorFlow. This can increase runtime and RAM usage compared with classical detectors. TensorFlow GPU workflows are generally smoother on Linux/WSL2 than native Windows.
- Cellpose in this pipeline: intended for bead-specific custom models. Generic biological pretrained models (for cells/nuclei) often underperform on tiny PSF beads.
- Practical default for beads: start with Blob or Trackpy for most datasets, then use StarDist/Cellpose for dense, overlapping, or otherwise difficult fields where classical detectors struggle.
For bead-center localization, some labs report strong results with keypoint/heatmap spot detectors (2D) and heatmap-regression or U-Net-style models (3D). These are not currently integrated in this repository; current AI options are StarDist and Cellpose.
*_FWHM_data.csv-- per-bead FWHM measurements (all modes)*_FWHM_summary.txt-- mean +/- std report*_bead_quality.csv-- QA metrics (SNR, symmetry)*_average_bead_stack.tif-- upsampled average bead (all modes)*_average_bead_plot.png-- XY/XZ/YZ projections of average bead*_summary_figure.png-- publication-quality figure: average bead projections with scale bars + mean profiles with Gaussian fit overlay*_detection_overview.png-- MIP with bead locations (green=accepted, red=rejected)*_FWHM_heatmap.png-- 3x3 spatial FWHM variation across the field (all modes)*_rejected_beads.csv-- beads filtered by QA (if--qa_auto_reject)bead_diagnostics/-- per-bead diagnostic plots with fit overlays on all axes (if--save_diagnostics)- (Cellpose)
*_every_bead_log.csv
Understanding the pipeline helps you choose the right options.
A 2D maximum-intensity projection (MIP) is computed from the Z-stack. Beads are located on the MIP by one of the five methods listed above.
StarDist still has a blob fallback (--use_blob_fallback) when you want to keep StarDist as the primary detector but recover from sparse/failed detections.
Each detected bead center is refined to sub-pixel precision using parabolic interpolation around the 3D intensity peak. This prevents snapping errors that can shift the center by up to 0.5 px.
Three 1D intensity profiles (Z, X, and Y) are drawn through the refined center using bilinear interpolation (scipy.ndimage.map_coordinates, order=1) for lateral axes.
The line length (--line_length, default 5 um) should be at least 3x the expected FWHM so the profile tails reach background. The box size (--box_size, default 15 px) controls how many XY pixels are averaged for the Z profile -- larger boxes improve Z-profile SNR but blur if beads are close together.
Bead Analyzer supports three baseline correction strategies:
| Strategy | Flag | What it does | When to use |
|---|---|---|---|
| Global minimum | (default) | profile - min(profile) |
Clean samples, uniform background |
| Detrend | --detrend |
scipy.signal.detrend (removes linear slope) |
Profiles with a tilted baseline |
| Local annulus | --local_background |
Subtracts the median intensity in a ring around the bead | Light-sheet data with spatially varying out-of-focus haze |
Note: The Gaussian fit model (A*exp(...) + C) independently estimates a constant background C, so the fitted FWHM is somewhat tolerant of baseline errors regardless of which strategy you choose. The prominence method also measures half-maximum relative to the peak base, not absolute zero.
Both Prominence (robust to background offsets) and Gaussian Fit (parametric sub-pixel precision) methods are computed for analysis.
| Method | What it does | Strengths |
|---|---|---|
| Prominence | Finds the peak, measures width at half the peak prominence | Fast, no assumptions about shape, works on noisy profiles |
| Gaussian fit | Fits A * exp(-0.5*((x-mu)/sigma)^2) + C, computes FWHM = 2*sqrt(2 ln 2) * sigma |
Sub-pixel precision, gives a parametric model, reports fit quality |
Enable Gaussian fitting with --fit_gaussian.
| Option | Flag | What it does |
|---|---|---|
| 1D Gaussian | --fit_gaussian |
Fits 1D Gaussians to each axis profile independently |
| 3D Gaussian | --fit_3d |
Fits a single 3D Gaussian to the entire bead volume -- more accurate for asymmetric PSFs because it uses all voxels simultaneously |
| Robust fit | --robust_fit |
Switches the optimizer to use soft-L1 loss (a smooth Huber-like function) instead of least-squares. This downweights outlier pixels in the profile tails -- useful when beads are clipped by the edge of a segmentation mask, when a neighboring bead contaminates the tail, or when the PSF is slightly asymmetric. |
All Gaussian fits (1D and 3D) enforce parameter bounds: amplitude > 0, sigma >= 0.3 px, center within the data window. This prevents degenerate fits (negative width, negative amplitude) that could silently corrupt results.
After fitting, each bead receives two QA scores:
- SNR: peak intensity above noise (estimated from the Z-profile baseline). Default threshold: 3.0.
- Symmetry: how symmetric the Z-profile is around its peak (1.0 = perfect). Default threshold: 0.6.
With --qa_auto_reject, beads below these thresholds are automatically removed from the summary statistics and written to a separate *_rejected_beads.csv.
Use --save_diagnostics to write a PNG per bead to bead_diagnostics/ showing:
- Z/X/Y profiles with FWHM markers
- XY/XZ/YZ projections through the bead center
- All numeric results (FWHM, QA scores, fit residuals)
This is invaluable for verifying that the pipeline is measuring what you expect.
bead-analyzer beads.tif --mode blob --scale_xy 0.26 --scale_z 2 \
--fit_gaussian --fit_3d --qa_auto_rejectbead-analyzer beads.tif --mode trackpy --scale_xy 0.51 --scale_z 1.0 \
--fit_gaussian --fit_3d --robust_fit --local_background \
--qa_auto_reject --save_diagnosticsbead-analyzer beads.tif --mode stardist --scale_xy 0.51 --scale_z 1.0 \
--use_blob_fallback --fit_gaussianbead-analyzer beads.tif --mode cellpose --scale_xy 0.26 --scale_z 2 \
--cellpose_model path/to/model --fit_gaussian --reject_outliers 3- CLI usage
- GUI usage
- Example commands
- Building & installing
- Contributing
- Changelog
- CI workflow -- automatic testing on Python 3.9-3.11 for Windows and Ubuntu
File types: TIFF, BigTIFF, and OME-TIFF image stacks (.tif, .tiff, .ome.tif). Proprietary formats (.nd2, .czi, .lif, etc.) should be exported to TIFF from your acquisition software before analysis.
Large files: For multi-gigabyte stacks, crop your data before analysis or ensure your system has sufficient RAM, as the entire stack is loaded into memory.
The tool expects a single-channel or multi-channel stack with dimensions (Z, Y, X) or (C, Z, Y, X). Use --channel to select a channel from multi-channel data.
Use any 3D TIFF stack of fluorescent beads (e.g. from your confocal or light-sheet microscope).
- Annotate:
python scripts/annotate_beads.py image.tif-> creates*_raw.tif,*_masks.tif - Train:
python scripts/train_cellpose.py path/to/folder - Set model:
set FWHM_CELLPOSE_MODEL=path/to/cellpose_bead_model(Windows) orexport FWHM_CELLPOSE_MODEL=...(Unix) - Analyze:
bead-analyzer image.tif --mode cellpose --scale_xy 0.26 --scale_z 2 --cellpose_model path/to/model
pip install -e ".[dev]"
pytest tests/ -vContinuous Integration (CI) runs automatically on every push to main via GitHub Actions, testing across Python 3.9-3.11 on both Ubuntu and Windows.
If you are on an older or unfamiliar system, run the install checker first:
python install_check.pyThis verifies your Python version (>=3.9), pip version, and dry-runs dependency resolution to catch conflicts before they happen.
- Python: >=3.9 (tested on 3.9, 3.10, 3.11)
- Current tested minimums in this repo:
cellpose>=4.0.8stardist>=0.9.2csbdeep>=0.7.4
This project is developed and maintained by Nathan O'Connor, PhD, MS at Arnas Technologies, LLC. I offer professional services for labs and companies requiring tailored, end-to-end solutions, specializing in bridging the gap from sample to reports and figures.
- Custom Image Analysis: Development of bespoke pipelines for complex datasets, including deconvolution, destriping, and 3D registration (e.g., Allen Brain Atlas mapping).
- End-to-End Workflow Design: Automation of your entire data lifecycle, from microscope-specific acquisition to publication-ready figures and statistical reports.
- Grant Inclusion: I am available for inclusion in NIH/NSF and private foundation grants as a Key Personnel or Consultant to lead neuroinformatics and imaging core initiatives.
- Hardware Integration: Custom software interfaces for specialized optical setups (e.g., multi-camera light-sheet systems, optical rectification).
If you are interested in discussing a collaboration or professional engagement, please reach out via:
- Email: nate@arnastechnologies.com
- Website: www.arnastechnologies.com
This tool optionally integrates the following packages. If you use one of these detection modes in published work, please cite the original authors:
- Trackpy -- Allan, D. B., Caswell, T., Keim, N. C., van der Wel, C. M., & Verweij, R. W. soft-matter/trackpy. Zenodo. DOI: 10.5281/zenodo.4682814
- StarDist -- Schmidt, U., Weigert, M., Broaddus, C., & Myers, G. Cell Detection with Star-Convex Polygons. MICCAI 2018. DOI: 10.1007/978-3-030-00934-2_30
- Cellpose -- Stringer, C., Wang, T., Michaelos, M., & Pachitariu, M. Cellpose: a generalist algorithm for cellular segmentation. Nature Methods 18, 100-106 (2021). DOI: 10.1038/s41592-020-01018-x
MIT