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$) using a calibrated factor hierarchy (ADR 0020) combining Bragg spot count, Bragg fraction, average SNR, resolution limit ($d_{98}$), 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

Pre-compiled binary wheels are available for standard Linux systems (manylinux_2_28 and musllinux_1_2 across x86_64 and aarch64 on Python 3.12+):

pip install mxspots

Install from Source

When installing from source or building custom binaries:

  • Prerequisites:
    • Python 3.12 or later
    • C Compiler (GCC, Clang, or MSVC) with OpenMP support
    • CMake 3.18 or later
# Clone the repository
git clone https://github.com/michel4j/mxspots.git
cd mxspots

# Install in editable mode with development dependencies
pip install -e ".[dev]"

Quick Start & CLI

mxspots provides command-line tools for rapid diffraction frame analysis:

1. Finding Spots (mxspots.findspots)

Find Bragg spots in a single frame and optionally export them to SPOT.XDS:

# Basic spot finding
mxspots.findspots /path/to/frame_00001.cbf

# Custom SNR threshold, resolution filtering, and XDS export
mxspots.findspots /path/to/frame_00001.cbf --snr 5.0 --dmin 1.5 --dmax 20.0 --xds

Example Output

Found 342 spots in /path/to/frame_00001.cbf:
Index  X (px)     Y (px)     d (Å)      Intensity    SNR     
------------------------------------------------------------
1      1248.50    1312.20    2.45       5420.0       42.3    
2      1105.10    1480.00    2.12       4980.0       38.7    
3      1380.25    1150.80    2.80       4320.0       35.1    
... and 322 more spots.

2. Quality Scoring (mxspots.score)

Compute composite quality score, Bragg spot metrics, resolution limit, and ice ring diagnostics:

# Output formatted summary
mxspots.score /path/to/frame_00001.cbf

# Output detailed JSON for automated beamline pipelines
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 Å (98th 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=2.5)
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 with a calibrated factor hierarchy (ADR 0020):

$$\text{Score} = \begin{cases} 0.0 & \text{if } N_{\text{bragg}} = 0 \ \text{clamp}\left(\frac{100}{1 + e^{-z}} - P_{\text{ice}},, 0.0,, 100.0\right) & \text{if } N_{\text{bragg}} > 0 \end{cases}$$

where the logit $z$ is computed as:

$$z = -6.50 + 0.75 \ln(1 + N_{\text{bragg}}) + 1.20 \ln(1 + \text{SNR}) + 1.40 (P_{\text{bragg}} / 100) + 0.50 s_{\text{res}}$$

Factor Hierarchy & Dynamic Share

  1. Tier 1 (Major Co-Equal Drivers, ~82% dynamic share):
    • Bragg Spot Count ($N_{\text{bragg}}$): $w_N = 0.75 \ln(1 + N_{\text{bragg}})$ (~44.2% dynamic variance contribution)
    • Signal-to-Noise Ratio ($\text{SNR}$): $w_S = 1.20 \ln(1 + \text{SNR})$ (~38.2% dynamic variance contribution)
  2. Tier 2 (Secondary Driver, ~12% dynamic share):
    • Bragg Percentage ($P_{\text{bragg}}$): $w_P = 1.40 (P_{\text{bragg}} / 100)$ (~11.9% contribution representing crystalline diffraction purity)
  3. Tier 3 (Tertiary Refinement, ~6% dynamic share):
    • Resolution Limit ($s_{\text{res}}$): $w_{\text{res}} = 0.50 s_{\text{res}}$ where $s_{\text{res}} = \text{clamp}\left(\frac{4.0 - d_{98}}{4.0 - 1.2}, 0.0, 1.0\right)$ (~5.6% contribution)
  4. Post-Logistic Ice Penalty ($P_{\text{ice}} \in [0.0, 10.0]$): $$P_{\text{ice}} = \text{clamp}\left(2.0 N_{\text{ice}} + 1.0 \max(0.0, I_{\text{ice}} - 2.0),, 0.0,, 10.0\right)$$ Guarantees that ice contamination penalizes the quality score by at most 10 points (10%).

Testing

Run the test suite with pytest:

pytest

License

This project is licensed under the MIT License.

Metadata

Release files for mxspots 2026.11.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mxspots 2026.11.1
File Size Uploaded Provenance Actions
mxspots-2026.11.1.tar.gz 364.2 kB Without provenance Details for mxspots-2026.11.1.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for mxspots 2026.11.1
File Interpreter ABI Platform Actions
mxspots-2026.11.1-cp314-cp314-manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.28+ x86-64 Details for mxspots-2026.11.1-cp314-cp314-manylinux_2_28_x86_64.whl
mxspots-2026.11.1-cp313-cp313-manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64 Details for mxspots-2026.11.1-cp313-cp313-manylinux_2_28_x86_64.whl
mxspots-2026.11.1-cp312-cp312-manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64 Details for mxspots-2026.11.1-cp312-cp312-manylinux_2_28_x86_64.whl

Total release size: 806.9 kB

Release files / mxspots-2026.11.1.tar.gz

Download URL mxspots-2026.11.1.tar.gz
Size 364.2 kB
Tags Source
SHA-256 checksum
How to use checksums
afc5a7ab20d5c116994cbc75e37b1c83d8250ba1205deb8476157190a2cd21e4
BLAKE2b-256 checksum
How to use checksums
9825b808cfc802c3d9f70a22d151556fafa88b609bae6890c28639e2c775bd49
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.3.4 CPython/3.14.8 Linux/7.2.9-200.fc44.x86_64

Release files / mxspots-2026.11.1-cp314-cp314-manylinux_2_28_x86_64.whl

Download URL mxspots-2026.11.1-cp314-cp314-manylinux_2_28_x86_64.whl
Size 147.6 kB
Tags CPython 3.14 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
a4f72a21208ff98df009ee75cee3b293457afa9eef2fc7fd02b419b65188e98d
BLAKE2b-256 checksum
How to use checksums
3cc69fec1e8e5b518370052b98b96beba2abeb5b0470cada03619ba8b1f5e4df
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.3.4 CPython/3.14.8 Linux/7.2.9-200.fc44.x86_64

Release files / mxspots-2026.11.1-cp313-cp313-manylinux_2_28_x86_64.whl

Download URL mxspots-2026.11.1-cp313-cp313-manylinux_2_28_x86_64.whl
Size 147.6 kB
Tags CPython 3.13 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
b151f1c0ba1ad82c75a2e6f5eee4cef1fa30473042e4d1b02ceb79f1ce88e5b6
BLAKE2b-256 checksum
How to use checksums
be3302b74ea71ebb92549986fb9c4bd81db5fc677d600e31196ba40c94d34934
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.3.4 CPython/3.14.8 Linux/7.2.9-200.fc44.x86_64

Release files / mxspots-2026.11.1-cp312-cp312-manylinux_2_28_x86_64.whl

Download URL mxspots-2026.11.1-cp312-cp312-manylinux_2_28_x86_64.whl
Size 147.6 kB
Tags CPython 3.12 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
d2fc4a5b4abbf5214f50fa17b41ebdda87c3fb24d36a5a84521a96c7ee839fb2
BLAKE2b-256 checksum
How to use checksums
d52ba635c6403afe66f513cdd5157a875014894b7314b01a60d28148c9bf9eb0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.3.4 CPython/3.14.8 Linux/7.2.9-200.fc44.x86_64

Security for mxspots 2026.11.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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