mxspots
High-Performance Spot Finding, Bragg Lattice Analysis, and Quality Scoring for Macromolecular Crystallography (MX)
mxspots is a fast, multithreaded library and command-line toolkit designed for real-time diffraction frame quality assessment and spot analysis in Macromolecular Crystallography. It combines an optimized C core engine with a Python API, integrating with mxio to process detector images (.cbf, .h5, Eiger/Pilatus, etc.) at beamline acquisition rates.
Key Features
- Fast Multithreaded Spot Finding: Employs 2D Integral Images (Summed-Area Tables) and OpenMP parallelization for constant-time local background and dispersion estimation, followed by single-pass streaming Connected Component Labeling (CCL).
- Automated Ice Ring Detection & Masking: Performs 1D azimuthal radial integration to detect characteristic powder ice rings (e.g., at 3.90 Å, 3.67 Å, 2.25 Å, 2.07 Å, 1.92 Å) and masks candidate spots falling within contaminated resolution shells.
- Reciprocal Difference-Vector Lattice Analysis: Uses difference-vector recurrence clustering in reciprocal space to classify regular Bragg spots from amorphous scatter or noise without requiring reciprocal lattice FFT indexing.
- Hybrid Gated-Logistic Quality Scoring: Generates a unified, normalized quality score ($0 - 100$) combining Bragg spot count, Bragg fraction, average Bragg intensity, average SNR, resolution limit ($d_{95}$), and ice contamination penalties.
- Zero-Allocation Batch Processing: Pre-allocates reusable execution contexts (
MxSpotsContext) for scratch buffers during batch grid scans and mesh screening. - XDS Compatibility: Supports exporting spots directly to
SPOT.XDSformat.
Use Cases
- Beamline Rastering & Crystal Screening: Rapidly evaluate hundreds of grid-scan frames to identify optimal crystal centering and diffraction hotspots.
- Real-Time Data Collection Monitoring: Compute instant quality scores and resolution limits during live rotation data collection.
- Automated Ice Contamination Flagging: Detect crystalline water ice rings early and exclude corrupted resolution shells from downstream processing.
- Spot Finding & XDS Export: Generate filtered spot lists and
SPOT.XDScoordinate files for downstream data processing pipelines.
Installation
Prerequisites
- Python: Version 3.12 or later
- C Compiler: GCC, Clang, or MSVC with OpenMP support
- CMake: Version 3.18 or later
Install from Source
# Clone the repository
git clone https://github.com/michel4j/mxspots.git
cd mxspots
# Install package with pip
pip install .
# For development (including test dependencies)
pip install -e ".[dev]"
Command-Line Usage
mxspots provides two primary CLI entry points:
1. mxspots.findspots
Finds diffraction spots on an image frame, with optional ice ring detection and SPOT.XDS export.
# Basic spot finding
mxspots.findspots /path/to/frame_00001.cbf
# Export spots formatted as JSON
mxspots.findspots /path/to/frame_00001.cbf --json
# Export spot coordinates to SPOT.XDS
mxspots.findspots /path/to/frame_00001.cbf --xds --xds-file SPOT.XDS
# Filter by resolution shells and SNR threshold
mxspots.findspots /path/to/frame_00001.cbf --snr 6.0 --dmin 1.8 --dmax 20.0
CLI Options
image: Path to diffraction image (.cbf,.h5,.yaml, etc.).--snr: Signal-to-noise ratio threshold (default:6.0).--dmin: High-resolution cutoff in Å (default:0.0, unbounded).--dmax: Low-resolution cutoff in Å (default:20.0).--min-area,--max-area: Minimum and maximum spot pixel areas (default:2,500).--max-spots: Maximum number of spots to return (default:5000).--no-ice-mask: Disable automated ice ring detection and masking.--ice-sensitivity: Ice ring detection threshold (default:1.0).--xds,--xds-file: Export spots to XDS format.--json: Output results formatted as JSON.
2. mxspots.score
Computes composite quality scores, Bragg metrics, lattice counts, and resolution limits.
# Assess diffraction frame quality
mxspots.score /path/to/frame_00001.cbf
# Output score metrics as JSON
mxspots.score /path/to/frame_00001.cbf --json
Example Output
Quality Score for /path/to/frame_00001.cbf:
Score: 88.4 / 100
Spot Count: 342
Bragg Spots: 318
Bragg %: 93.0%
Avg Intensity: 1420.5
Lattices Detected: 1
Average SNR: 14.22
Resolution Limit: 1.75 Å (95th percentile)
Ice Score: 0.00
Python API
Finding Spots
from mxspots import findspots, SpotParams
# Configure spot finding parameters
params = SpotParams(
snr_threshold=6.0,
d_min=1.5,
d_max=20.0,
ice_mask=True,
)
# Find spots from an image file or NumPy array
spot_list = findspots("frame_00001.cbf", params=params)
print(f"Detected {spot_list.count} spots:")
for spot in spot_list.spots[:10]:
print(f"Spot at ({spot.x:.1f}, {spot.y:.1f}), d = {spot.d_spacing:.2f} Å, I = {spot.intensity:.1f}")
# Export to SPOT.XDS
spot_list.to_xds("SPOT.XDS", frame_index=1)
Scoring Diffraction Frames
from mxspots import score, SpotParams
# Compute quality metrics for an image frame
result = score("frame_00001.cbf")
print(f"Composite Score: {result.score:.1f} / 100")
print(f"Bragg Spots: {result.bragg_spots} / {result.spot_count} ({result.bragg_percent:.1f}%)")
print(f"Resolution Limit: {result.d_min:.2f} Å")
print(f"Lattices Detected: {result.num_lattices}")
print(f"Ice Score: {result.ice_score:.2f}")
Ice Ring Detection
from mxspots import detect_ice_rings, SpotParams
params = SpotParams(ice_sensitivity=1.0)
ice_result = detect_ice_rings("frame_00001.cbf", params=params)
if ice_result.num_rings > 0:
print(f"Ice contamination detected (score: {ice_result.ice_score:.2f})")
for ring in ice_result.rings:
print(f" Ring at {ring.d_spacing:.2f} Å (SNR: {ring.score:.1f})")
High-Throughput Batch Scoring (score_data)
For in-memory batch screening of raw NumPy arrays:
import numpy as np
from mxspots import score_data, SpotParams
# Frame 2D float32 array with detector geometry
params = SpotParams(
beam_x=1500.0,
beam_y=1500.0,
distance=200.0,
wavelength=1.0,
pixel_size_x=0.075,
pixel_size_y=0.075,
)
data = np.load("frame_data.npy").astype(np.float32)
res = score_data(data, params=params)
print(f"Score: {res.score:.1f}")
Scoring Model
The Composite Quality Score ($S \in [0, 100]$) uses a Hybrid Gated-Logistic model:
$$\text{Score} = \begin{cases} 0.0 & \text{if } N_{\text{bragg}} = 0 \ \text{clamp}\left(\frac{100}{1 + e^{-z}}, 0, 100\right) & \text{if } N_{\text{bragg}} > 0 \end{cases}$$
where the logit $z$ is computed from:
- Bragg Spot Count ($N_{\text{bragg}}$): Logarithmic scaling $\ln(1 + N_{\text{bragg}})$
- Bragg Spot Fraction ($P_{\text{bragg}}$): Linear weighting of lattice conformity
- Average Bragg Intensity ($I_{\text{bragg}}$): Logarithmic intensity scaling $\ln(1 + I_{\text{bragg}} / 50)$
- Signal-to-Noise Ratio ($\text{SNR}$): Logarithmic peak quality $\ln(1 + \text{SNR})$
- Bragg Resolution Limit ($d_{95}$): Linear scaling between $4.0,\text{Å}$ and $1.2,\text{Å}$
- Ice Penalties ($P_{\text{ice}}$): Penalty based on number of ice rings and contamination significance
Testing
Run the test suite with pytest:
pytest
License
This project is licensed under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mxspots-2026.8.1.tar.gz.
File metadata
- Download URL: mxspots-2026.8.1.tar.gz
- Upload date:
- Size: 259.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
poetry/2.1.1 CPython/3.13.15 Linux/7.1.8-200.fc44.x86_64
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c1850e0dfe0a8756bddfd79c1437e49f3801570221d30ee8af7451ae942fb48
|
|
| MD5 |
12870ddc82ecdabcbb719be3b39f268e
|
|
| BLAKE2b-256 |
316eaa2e15da479248e750a1b6ec58ca826a4b8740f7926173052b326f8d98b6
|
File details
Details for the file mxspots-2026.8.1-cp314-cp314-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: mxspots-2026.8.1-cp314-cp314-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 145.1 kB
- Tags: CPython 3.14, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
poetry/2.1.1 CPython/3.13.15 Linux/7.1.8-200.fc44.x86_64
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37f6fbf1227d56a3856d80cdecc6827ff066cd845d93b6771ff4da1b08c42bf3
|
|
| MD5 |
928a1e53421ce3038ee715cabe204133
|
|
| BLAKE2b-256 |
ffc187859176a1a0c8e844c6ab16fd8f8344dd623472462f59e7f8404fca91aa
|
File details
Details for the file mxspots-2026.8.1-cp313-cp313-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: mxspots-2026.8.1-cp313-cp313-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 145.1 kB
- Tags: CPython 3.13, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
poetry/2.1.1 CPython/3.13.15 Linux/7.1.8-200.fc44.x86_64
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b512052440ff24fa3b2a590d4f87df8b55f6482550385660238ff9bb55f359b
|
|
| MD5 |
98e9601cee46187e66534344a5c6e5c9
|
|
| BLAKE2b-256 |
2beee78cd2b30bca22d0c7e66e1415cdcd0a56b7c37af3d1251d0a71553e4db1
|
File details
Details for the file mxspots-2026.8.1-cp312-cp312-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: mxspots-2026.8.1-cp312-cp312-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 145.1 kB
- Tags: CPython 3.12, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
poetry/2.1.1 CPython/3.13.15 Linux/7.1.8-200.fc44.x86_64
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70666f4d851e79155f75cde1322c25c6533c752a15317c2975cc1c652b432f1d
|
|
| MD5 |
121be05ec7a64bbc5391f14adf456313
|
|
| BLAKE2b-256 |
344eabdee2279613991b00fac1ecb62e3d01ee9ab1c35952d1b2e1a189bd05a4
|