Algorithms
zsasa provides two SASA calculation algorithms.
Recommendation
Use Shrake-Rupley (SR) for most use cases. It is the default algorithm, faster, and produces results within 0.05% of Lee-Richards.
Use Lee-Richards (LR) only when you need to compare results with other LR implementations or require arc-based geometric rigor.
Comparison
| Property | Shrake-Rupley (SR) | Lee-Richards (LR) |
|---|---|---|
| Method | Test point sampling | Slice/arc integration |
| Speed | Fast | ~4x slower |
| Default | Yes (--algorithm=sr) | No (--algorithm=lr) |
| Precision control | --n-points (default: 100) | --n-slices (default: 20) |
| Recommended for | General use | Comparison with LR implementations |
Performance (1A0Q, 3,183 atoms, 4 threads)
| Algorithm | Time | vs FreeSASA C |
|---|---|---|
| SR (100 points) | 2.6ms | 1.7x faster |
| LR (20 slices) | 9.9ms | 1.6x faster |
Accuracy
Both algorithms produce nearly identical results on the same structure:
| Algorithm | SASA (Ų) |
|---|---|
| SR (100 points) | 19,211.19 |
| LR (20 slices) | 19,201.26 |
| Difference | 0.05% |
Usage
- CLI
- Python
# Shrake-Rupley (default)
zsasa calc structure.cif output.json
# Lee-Richards
zsasa calc --algorithm=lr structure.cif output.json
# SR with more test points (higher precision)
zsasa calc --n-points=200 structure.cif output.json
from zsasa import calculate_sasa
# Shrake-Rupley (default)
result = calculate_sasa(coords, radii)
# Lee-Richards
result = calculate_sasa(coords, radii, algorithm="lr")
# SR with more test points
result = calculate_sasa(coords, radii, n_points=200)
Precision vs Speed
Shrake-Rupley: --n-points
| Points | Precision | Relative Time |
|---|---|---|
| 50 | Low | 0.5x |
| 100 | Medium (default) | 1.0x |
| 200 | High | 2.0x |
| 1000 | Very high | 10.0x |
Lee-Richards: --n-slices
| Slices | Precision | Relative Time |
|---|---|---|
| 10 | Low | 0.5x |
| 20 | Medium (default) | 1.0x |
| 50 | High | 2.5x |
| 100 | Very high | 5.0x |
Bitmask LUT Optimization
The Shrake-Rupley algorithm supports an optional bitmask lookup table (LUT) optimization that significantly improves performance, especially for large structures and MD trajectories. This approach is inspired by Lahuta, which demonstrated the effectiveness of bitmask-based neighbor occlusion for SASA calculations.
How It Works
In standard SR, each neighbor's occlusion of test points is computed individually by distance checks. The bitmask LUT approach replaces this with precomputed bitmask patterns:
- Precompute: For each possible neighbor geometry (distance, relative orientation), a bitmask encodes which test points on the sphere are occluded
- Lookup: During calculation, the appropriate bitmask is fetched from the LUT based on neighbor position
- Combine: Neighbor occlusion masks are combined using bitwise OR — a single CPU instruction processes all test points simultaneously
This converts the inner loop from per-point floating-point comparisons to bulk bitwise operations, yielding ~2x speedup on large systems.
Performance
Bitmask mode provides the largest benefit on large structures and long trajectories:
| Use Case | Speedup vs Standard | Details |
|---|---|---|
| Single file (100k+ atoms) | ~1.2x | Single-file benchmarks |
| Batch proteome processing | ~1.5–2x | Batch benchmarks |
| MD trajectory (33k atoms, 1k frames) | ~2.1x | MD benchmarks |
Memory usage is minimal — the LUT adds only ~2 MB overhead for CLI mode.
Accuracy
Bitmask introduces a small systematic offset due to the LUT discretization:
| Metric | Standard SR | Bitmask |
|---|---|---|
| R² vs FreeSASA | 1.000000 | 0.9997 |
| Mean error | < 0.001% | ~0.7% |
| Max error | < 0.02% | ~2.5% |
The offset is constant regardless of n_points (unlike standard SR where error decreases with more points). However, for MD trajectory analysis, the frame-to-frame changes (ΔR²) are nearly identical between standard and bitmask (> 0.99 at 500+ points) — the systematic offset cancels out in differences.
For detailed accuracy analysis, see SASA Validation.
Constraints
- SR algorithm only — not available for Lee-Richards
- Supported n_points: 1–1024
- Lahuta uses n_points=128 fixed; zsasa supports any value in range
When to Use
| Mode | Best For |
|---|---|
| Standard (default) | Maximum accuracy, small structures, single calculations |
| Bitmask | MD trajectories, batch processing, large structures, memory-constrained environments |
Usage
- CLI
- Python
# Bitmask with 128 test points (recommended)
zsasa calc --use-bitmask --n-points=128 structure.cif output.json
# Trajectory with bitmask
zsasa traj --use-bitmask --n-points=128 trajectory.xtc topology.pdb
# Batch with bitmask
zsasa batch --use-bitmask --n-points=128 input_dir/ output_dir/
from zsasa import calculate_sasa
# Single frame
result = calculate_sasa(coords, radii, n_points=128, use_bitmask=True)
# Batch (trajectory)
from zsasa import calculate_sasa_batch
result = calculate_sasa_batch(coords, radii, n_points=128, use_bitmask=True)
References
- Shrake, A.; Rupley, J. A. Environment and Exposure to Solvent of Protein Atoms. J. Mol. Biol. 1973, 79(2), 351-371.
- Lee, B.; Richards, F. M. The Interpretation of Protein Structures: Estimation of Static Accessibility. J. Mol. Biol. 1971, 55(3), 379-400.
- Lahuta — Bitmask LUT approach for SASA neighbor occlusion.