Tutorial: Measure particle size distribution via SEM
This tutorial explains how to collect particle-size statistics with
AutoEMX using the script:
autoemx/scripts/Particle size Statistics measurements/Collect_Particle_Statistics.py
It also explains how to post-process results and, for advanced users, how to add a separate particle-segmentation model.
What this script does
Collect_Particle_Statistics.py:
Acquires SEM frames across the selected sample region.
Segments particles in each frame.
Filters particles by size.
Continues until the requested number of particles is reached (or frames are exhausted).
Saves per-particle measurements and summary statistics.
Saves a particle-size histogram.
Step 1 - Open script to edit
Open:
autoemx/scripts/Particle size Statistics measurements/Collect_Particle_Statistics.py
When you run it, a GUI appears to collect the main inputs.
Step 2 - Define required inputs in the GUI
Fill in the following fields:
Sample IDName used to create the output folder and output files.
Sample Center X, YStage coordinates (mm) of the center of the sample.
Number of Particles to AnalyseTarget number of particles to analyse.
Min & Max Particle Diameter (um)Accepted particle-diameter range (used to compute area filters). It is recommended to split measurements into multiple runs, each covering at most one order of magnitude (for example, 1 um to 10 um). This is because frame dimensions are chosen based on the largest accepted particle diameter; if the range is too large, the pixel size can become comparable to the smallest particles, which can invalidate their area measurements.
Carbon Tape Diameter (mm)Used to estimate the effective sample area to scan over the carbon tape.
Working Distance (mm)Nominal working distance used by autofocus to prevent catastrophic focus drift.
Segmentation ModelParticle segmentation model. Default is
threshold_bright. This default model works best when there is clear contrast between carbon tape and particles. For this reason, electron backscatter detector mode is recommended to maximize Z-contrast. Particles should also be well separated; touching/overlapping particles can be segmented as a single particle. For more complex samples, machine-learning segmentation models are recommended (for exampleRettenberger2024). You can also add your own segmentation model (see the advanced section below).
Manual NavigationIf enabled, you manually navigate to regions/particles and determine the frame size.
Auto Detect Carbon TapeEnables automatic substrate detection for carbon tape workflows.
Auto Adjust Brightness and ContrastIf set to
No, you must also provide:BrightnessContrast
After submitting, choose results_dir (save directory) in the folder picker.
Step 3 - Run the script
Note that the measurement runs using the microscope’s current settings, including detector type, beam current, and acceleration voltage.
Run from your AutoEMX environment, for example:
python "autoemx/scripts/Particle size Statistics measurements/Collect_Particle_Statistics.py"
Output
In the sample output directory, the workflow writes:
<SampleID>_Par_sizes.csvPer-particle table with particle ID, frame ID, area, and equivalent diameter.
<SampleID>_Par_size_stats.csvSummary statistics (mean, stdev, median, min, max, D10, D25, D75, D90).
<SampleID>_Par_size_distribution_hist.pngHistogram plot of equivalent particle diameters.
SEM images collected during the scan (depending on script options).
Optional: Reprocess particle statistics after filtering
If some particles or full frames were incorrectly segmented and you want to exclude them before recomputing the size distribution, use:
autoemx/scripts/Particle size Statistics measurements/Process_Particle_Stats_Files.py
Main editable fields in that script are:
sample_ID: sample folder to processinput_dir: parent path where sample folder is storedparticles_IDs_to_filter: list of particle IDs to ignoreframe_IDs_to_filter: list of frame IDs to ignore (if a full frame is bad, all its particles are ignored)
The script generates processed outputs with suffix _processed.
Optional (Advanced): Add a separate segmentation model
Most users do not need this section. Use it only if the built-in segmentation models are not suitable for your images.
AutoEMX automatically discovers custom segmentation models from:
autoemx/core/em_runtime/particle_segmentation_models/
To add a new model:
- Create a new Python file in that folder, for example:
my_segmentation_model.py
- Use
autoemx/core/em_runtime/particle_segmentation_models/segmentation_model_template.pyas the template.
Implement a function with this signature:
def segment_particles(frame_image, powder_meas_config=None, save_image=False, EM=None):
...
return par_mask
Return either:
a binary mask (background 0, particles > 0), or
a labeled image (background 0, each particle with a unique positive label).
- Restart the particle-statistics script. Your model name should appear in the
Segmentation Modeldropdown automatically.
- Select it in the GUI (or set
par_segmentation_modeldirectly in powder_meas_cfg_kwargs).
- Select it in the GUI (or set
Notes:
- If your model requires external files (for example ONNX weights), keep paths
stable and preferably relative to the model file location.
If a model name is invalid, AutoEMX falls back to
threshold_bright.