中文 | English
Python implementation of NP-Cloud (Nearest Paired Cloud) for fast and robust drift correction in single-molecule localization microscopy (SMLM).
This package is a complete Python port of the original MATLAB implementation from:
"Fast and robust drift correction for single-molecule localization microscopy"
The Python implementation produces numerically identical results to the MATLAB version, verified through comprehensive comparison tests.
- 2D Drift Correction: NP-Cloud and RR-NP-Cloud algorithms
- 3D Drift Correction: NP-Cloud-3D and RR-NP-Cloud-3D algorithms
- MATLAB Comparison Tests: Verify Python output matches MATLAB exactly
- Visualization Tools: Compare drift curves and rendered SMLM images
The Python implementation has been validated against the original MATLAB code:
| Metric | 2D (High Density) | 3D (High Density) |
|---|---|---|
| Max X Drift Diff | ~1e-2 pixels | ~1e-2 pixels |
| Max Y Drift Diff | ~1e-2 pixels | ~1e-2 pixels |
| Max Z Drift Diff | - | ~1e-1 nm |
2D drift curves: Python vs MATLAB
2D drift correction comparison: Original vs Python vs MATLAB corrected images
2D high density data drift curves comparison
2D corrected images difference (Python - MATLAB)
3D drift curves: Python vs MATLAB (X, Y, Z dimensions)
3D drift correction comparison: Original vs Python vs MATLAB corrected images (XY projection)
3D high density data drift curves comparison
cd npcloud_python
pip install -r requirements.txt- Python 3.6+
- NumPy >= 1.19.0
- SciPy >= 1.5.0
- Matplotlib >= 3.3.0
- pytest >= 6.0.0 (for testing)
from npcloud.npc_rrnpc_2d import npc_rrnpc_call_function
from npcloud.utils import load_smlm_data
# Load data (columns: Frame, X, Y)
smlm_data = load_smlm_data('your_data.mat')
array_frames = smlm_data[:, 0].astype('int32')
array_x = smlm_data[:, 1].astype('float32')
array_y = smlm_data[:, 2].astype('float32')
# Run drift correction
xc, yc, xd1, yd1, xd2, yd2, npc_time, total_time = npc_rrnpc_call_function(
array_x, array_y, array_frames,
dc_segment_size=70, # Frames per segment
max_search_radius_pix1=0.3, # Pass 1 search radius (pixels)
max_search_radius_pix2=0.225, # Pass 2 search radius (pixels)
resample_fold=12 # Resampling factor
)
# xc, yc: corrected positions
# xd2, yd2: final drift curves (RR-NPC)from npcloud.npc_rrnpc_3d import npc_rrnpc_3d_call_function
# Load 3D data (columns: Frame, X, Y, Z)
# X, Y in pixels; Z in nm
result = npc_rrnpc_3d_call_function(
array_x, array_y, array_z, array_frames,
dc_segment_size=100, # Frames per segment
max_search_radius_pix1=0.35, # Pass 1 XY search radius
max_search_radius_pix2=0.28, # Pass 2 XY search radius
tol_z_nm=110, # Pass 1 Z tolerance (nm)
tol_z_nm2=90, # Pass 2 Z tolerance (nm)
resample_fold=12
)
xc, yc, zc, xd1, yd1, zd1, xd2, yd2, zd2, npc_time, total_time = result# 2D drift correction
python scripts/run_npc_rrnpc.py --data your_data.mat --name output_folder
# 3D drift correction
python scripts/run_npc_rrnpc_3d.py --data your_3d_data.mat --name output_folder
# Compare Python vs MATLAB (requires MATLAB engine)
python scripts/compare_matlab_python.py| Parameter | 2D Default | 3D Default | Description |
|---|---|---|---|
| dc_segment_size | 70 | 100 | Frames per segment |
| max_search_radius_pix1 | 0.3 | 0.35 | XY search radius Pass 1 (pixels) |
| max_search_radius_pix2 | 0.225 | 0.28 | XY search radius Pass 2 (pixels) |
| tol_z_nm | - | 110 | Z tolerance Pass 1 (nm) |
| tol_z_nm2 | - | 90 | Z tolerance Pass 2 (nm) |
| resample_fold | 12 | 12 | Resampling factor for RR-NPC |
- 2D: 3 columns
[Frame, X, Y]- X,Y in pixels - 3D: 4 columns
[Frame, X, Y, Z]- X,Y in pixels, Z in nm - Frame numbers must be increasing (sorted by frame)
npcloud_python/
├── npcloud/
│ ├── core/
│ │ ├── np_cloud_2d.py # 2D NP-Cloud algorithm
│ │ ├── np_cloud_3d_pass1.py # 3D Pass 1 (Z by averaging)
│ │ └── np_cloud_3d_pass2.py # 3D Pass 2 (Z iterative)
│ ├── npc_rrnpc_2d.py # 2D two-pass drift correction
│ ├── npc_rrnpc_3d.py # 3D two-pass drift correction
│ └── utils.py # Utility functions
├── scripts/
│ ├── run_npc_rrnpc.py # 2D command line script
│ ├── run_npc_rrnpc_3d.py # 3D command line script
│ └── compare_matlab_python.py # Visualization comparison
├── tests/ # MATLAB comparison tests
├── requirements.txt
└── README.md
| MATLAB File | Python File |
|---|---|
| NP_Cloud_NoSort.m | npcloud/core/np_cloud_2d.py |
| NP_Cloud_NoSort_3D_Pass1.m | npcloud/core/np_cloud_3d_pass1.py |
| NP_Cloud_NoSort_3D_Pass2.m | npcloud/core/np_cloud_3d_pass2.py |
| NPC_RRNPC_CallFunction.m | npcloud/npc_rrnpc_2d.py |
| NPC_RRNPC_3D_CallFunction.m | npcloud/npc_rrnpc_3d.py |
| Run_NPC_RRNPC.m | scripts/run_npc_rrnpc.py |
| Run_NPC_RRNPC_3D.m | scripts/run_npc_rrnpc_3d.py |
Run tests comparing Python vs MATLAB (requires MATLAB engine for Python):
# Activate matlab environment
conda activate matlab_py36
# Run all tests
pytest tests/ -v
# Run specific test
pytest tests/test_np_cloud_2d.py -v-
Build Displacement Cloud: For each molecule in the comparing segment, find all molecules in the reference segment within a search radius and record displacement vectors.
-
Iterative Convergence: Shift the cloud center iteratively until convergence to find the true drift.
-
Nearest Neighbor Filtering: Keep only the nearest neighbor pair for each molecule to improve accuracy.
A two-pass approach:
- Pass 1 (NPC): Use the first segment as reference
- Pass 2 (RR-NPC): Resample from the entire drift-corrected dataset as reference for refinement
If you use this code, please cite the original paper:
@article{NPCloud,
title={Fast and robust drift correction for single-molecule localization microscopy},
author={...},
journal={...},
year={...}
}
See original MATLAB code license.
This Python implementation is based on the original MATLAB code from the NPCloud project.