Skip to main content

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.XDS format.

Use Cases

  1. Beamline Rastering & Crystal Screening: Rapidly evaluate hundreds of grid-scan frames to identify optimal crystal centering and diffraction hotspots.
  2. Real-Time Data Collection Monitoring: Compute instant quality scores and resolution limits during live rotation data collection.
  3. Automated Ice Contamination Flagging: Detect crystalline water ice rings early and exclude corrupted resolution shells from downstream processing.
  4. Spot Finding & XDS Export: Generate filtered spot lists and SPOT.XDS coordinate 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

mxspots-2026.8.1.tar.gz (259.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

mxspots-2026.8.1-cp314-cp314-manylinux_2_28_x86_64.whl (145.1 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ x86-64

mxspots-2026.8.1-cp313-cp313-manylinux_2_28_x86_64.whl (145.1 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

mxspots-2026.8.1-cp312-cp312-manylinux_2_28_x86_64.whl (145.1 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

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

Hashes for mxspots-2026.8.1.tar.gz
Algorithm Hash digest
SHA256 3c1850e0dfe0a8756bddfd79c1437e49f3801570221d30ee8af7451ae942fb48
MD5 12870ddc82ecdabcbb719be3b39f268e
BLAKE2b-256 316eaa2e15da479248e750a1b6ec58ca826a4b8740f7926173052b326f8d98b6

See more details on using hashes here.

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

Hashes for mxspots-2026.8.1-cp314-cp314-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 37f6fbf1227d56a3856d80cdecc6827ff066cd845d93b6771ff4da1b08c42bf3
MD5 928a1e53421ce3038ee715cabe204133
BLAKE2b-256 ffc187859176a1a0c8e844c6ab16fd8f8344dd623472462f59e7f8404fca91aa

See more details on using hashes here.

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

Hashes for mxspots-2026.8.1-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8b512052440ff24fa3b2a590d4f87df8b55f6482550385660238ff9bb55f359b
MD5 98e9601cee46187e66534344a5c6e5c9
BLAKE2b-256 2beee78cd2b30bca22d0c7e66e1415cdcd0a56b7c37af3d1251d0a71553e4db1

See more details on using hashes here.

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

Hashes for mxspots-2026.8.1-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 70666f4d851e79155f75cde1322c25c6533c752a15317c2975cc1c652b432f1d
MD5 121be05ec7a64bbc5391f14adf456313
BLAKE2b-256 344eabdee2279613991b00fac1ecb62e3d01ee9ab1c35952d1b2e1a189bd05a4

See more details on using hashes here.

Release history Release notifications | RSS feed

2026.8.5

4 files

2026.8.4

4 files

2026.8.3

4 files

2026.8.2

4 files

This release

2026.8.1 This release

4 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page