Skip to main content

Comparison with Other Tools

How zsasa compares to other modern SASA calculation tools.

This page focuses on factual, verifiable differences with source code references. For performance numbers, see Benchmarks.

Overview

FeaturezsasaFreeSASARustSASALahuta
LanguageZigCRustC++
AlgorithmsSR + LRSR + LRSR onlySR only
Input formatsmmCIF, PDB, JSONPDB, mmCIFPDB (via pdbtbx)AF2 model (CIF/PDB)
MD trajectoryNative (XTC, DCD)△ (mdsasa-bolt)
Python API✅ (multi-threaded)✅ (single-threaded)△ (separate package)
Bitmask range1–102464/128/256
External depsNoneNonepdbtbx, pulp, mimalloc13+ (Boost, Eigen, gemmi, Highway, RDKit, lmdb, ...)
Batch processing✅ Native
Multi-chain❌ (chain "A" hardcoded)
Precisionf64/f32 (selectable)f64f32 onlyf64
Build systemzig buildautotools/CMakeCargoCMake + vcpkg

Algorithms

zsasa and FreeSASA support both Shrake-Rupley (SR) and Lee-Richards (LR) algorithms. RustSASA and Lahuta support SR only.

  • RustSASA: lib.rs — "Shrake-Rupley algorithm"
  • Lahuta: sasa.hpp — SR computation only

Input & Parsing

zsasa: Native parser, zero external dependencies

zsasa includes a native mmCIF/PDB parser written in Zig. It extracts only the fields needed for SASA calculation (coordinates, element, residue name, atom name), avoiding errors from irrelevant data fields. JSON input is also supported for maximum flexibility.

RustSASA: pdbtbx dependency causes parse errors

RustSASA uses pdbtbx for PDB parsing. This external parser attempts to validate the entire PDB structure, causing failures on:

  • Multi-character chain IDs (common in large complexes from mmCIF → PDB conversion)
  • Hybrid-36 residue/serial numbers (structures with >9999 residues or >99999 atoms)
  • Missing CRYST1 Z values (common in EM/NMR structures)

Our benchmarking required a dedicated preprocessing script to work around these pdbtbx limitations — reassigning chain IDs, wrapping serial/residue numbers, and fixing CRYST1 records.

Lahuta: AlphaFold2 model input required

Lahuta's sasa-sr command requires AlphaFold2 model inputs. File-based sources must pass the --is_af2_model flag, otherwise an error is thrown:

"sasa-sr expects AlphaFold2 model inputs. For file-based sources, pass --is_af2_model"

Source: sasa_sr_spec.cpp L211–214

Chain Support

Lahuta's SASA kernel hardcodes chain_id = "A":

constexpr std::string_view chain_id = "A";

Source: kernel.hpp L164, L192

This means multi-chain structures are treated as single-chain. zsasa, FreeSASA, and RustSASA all support multi-chain structures natively.

MD Trajectory Support

ToolXTCDCDIntegration
zsasa✅ Native CLI + Python✅ Native CLI + PythonMDTraj, MDAnalysis
FreeSASA
RustSASA△ via mdsasa-boltMDAnalysis (Python bridge)
Lahuta

Lahuta's sasa-sr has no trajectory options — grep for "trajectory", "xtc", or "dcd" in sasa_sr_spec.cpp returns no matches.

mdsasa-bolt (RustSASA) memory issues

RustSASA's trajectory support is via mdsasa-bolt, a separate Python package that bridges MDAnalysis to RustSASA. It has significant memory overhead:

Datasetmdsasa-bolt RSSzsasa CLI RSSRatio
5vz0 (1K frames, 28K atoms)1.4 GB17 MB82x
5wvo (1K frames, 97K atoms)10.9 GB113 MB96x

On 10K-frame datasets, mdsasa-bolt timed out (>2 hours) where zsasa completed in 38 seconds.

See MD Trajectory Benchmarks for full results.

Bitmask LUT Optimization

ToolBitmask supportSupported n_pointsRange
zsasa1–1024 (any value)Continuous
Lahuta64, 128, 2563 discrete values
RustSASA
FreeSASA

zsasa's bitmask supports any n_points from 1 to 1024 (bitmask_lut.zig), while Lahuta is limited to 64/128/256 (sasa_sr_spec.cpp L172–173).

See Bitmask LUT Algorithm for how it works.

Python Bindings

ToolPython SASA APIHow
zsasafrom zsasa import calculate_sasaNative C extension via Zig, multi-threaded
FreeSASAimport freesasaNative C extension, single-threaded only
RustSASArust-sasa-python (separate package)PyO3 bridge
Lahutapybind11 bindings exist but expose pipeline framework only — no SASA API

Lahuta has pybind11 bindings, but they expose the pipeline framework — not SASA calculation. The Python code contains no reference to "sasa" at all.

Source: interop/python/

Precision

ToolPrecisionSelectable
zsasaf64 or f32--precision=f32/f64
FreeSASAf64
RustSASAf32
Lahutaf64

RustSASA uses f32 throughout its entire computation pipeline — coordinates, sphere points, and SASA output are all single-precision.

Source: lib.rsVec<f32> for coordinates, f32 for all SIMD operations

zsasa defaults to f64 for maximum accuracy, with f32 available as an option for trajectory processing or when comparing with f32-based tools.

Validation against FreeSASA reference (E. coli K-12 proteome, 4,370 structures):

  • zsasa f64: mean error <0.001%
  • zsasa f32: mean error <0.05%
  • RustSASA f32: mean error <0.05% (expected, same precision)

See Validation Benchmarks for full convergence analysis.

Batch Processing

ToolDirectory batchParallelism
zsasa✅ Native zsasa batchFile-level multi-threading
FreeSASA❌ Single file onlySingle file at a time
RustSASArust-sasa dir/ out/File-level multi-threading
Lahuta--directory / --filesPipeline-based

FreeSASA processes one file at a time and has no built-in batch/directory mode. Processing a proteome-scale dataset requires external scripting with sequential invocations.

See Batch Benchmarks for performance comparison across proteome-scale datasets.

Build Complexity

ToolBuild commandDependencies
zsasazig build -Doptimize=ReleaseFastNone (Zig only)
FreeSASA./configure && makeNone (C only)
RustSASAcargo build --releasepdbtbx, pulp, mimalloc, rayon
LahutaCMakeBoost, Eigen, gemmi, Google Highway (via distopia), RDKit, lmdb, mimalloc, spdlog, libdivide, simde, ZLIB, ...

zsasa and FreeSASA have zero external dependencies. RustSASA pulls in several crates. Lahuta bundles 13+ external libraries — building from source requires resolving all of them.

SIMD Architecture

ToolSIMD approachArchitecture independence
zsasaZig @Vector✅ Compiler auto-targets native ISA (x86 SSE/AVX, ARM NEON, etc.)
RustSASApulp crate✅ Runtime dispatch via ARCH.dispatch (lib.rs)
LahutaSIMDe (AVX2 API)△ Written against AVX2 intrinsics — SIMDe emulates on non-x86
FreeSASANone

zsasa uses Zig's built-in @Vector primitives — the compiler maps them directly to the target architecture's SIMD instructions without any abstraction layer.

RustSASA uses pulp for runtime SIMD dispatch — it detects available instruction sets at runtime and selects the best implementation.

Lahuta uses SIMDe but with explicit AVX2 API calls (#include <simde/x86/avx2.h>). All SIMD functions are named with _avx2 suffix (e.g., fast_rsqrt_avx2, octa_encode_avx2). SIMDe can emulate AVX2 on non-x86 platforms, but the code is fundamentally written against the x86 AVX2 instruction set.

Source: bitmask_simd.hpp

Performance Summary

Single-file (100 test points, median across 128 structures)

Metriczsasa f64 (t=10)vs FreeSASAvs RustSASA
Median speedup1.88x1.84x
Thread scaling (t=1→10)2.71x1.99x1.39x

RustSASA shows pathological slowdowns on certain structures (up to 280x slower than zsasa).

See Single-file Benchmarks for full results.

Batch (128 test points, E. coli K-12 proteome, 4,370 structures)

ToolTimeRSSvs zsasa
zsasa bitmask (f32)1.42s43 MBbaseline
Lahuta bitmask2.01s291 MB1.4x slower, 6.8x more memory
RustSASA5.24s169 MB3.7x slower, 3.9x more memory

At SwissProt scale (550K structures), zsasa uses 157 MB vs RustSASA 1.1 GB (7.2x less) and Lahuta bitmask 2.2 GB (14x less).

See Batch Benchmarks for full results including memory scaling charts.

Known Limitations of zsasa

Zig language maturity

Zig has not yet reached version 1.0. The language may introduce breaking changes between releases, which could require updates to the zsasa codebase. Unreported compiler bugs are also possible in pre-1.0 software.

Mitigation: The Python package (zsasa) communicates with the Zig core through the C ABI, which is stable and standardized. This means Python users are insulated from Zig-specific changes — even if the Zig internals are updated, the Python API remains unaffected as long as the C ABI interface is maintained.

Early-stage API

zsasa is a young project and its CLI options, Python API, and output formats may change between releases. Established tools like FreeSASA have stable APIs refined over many years of use.

ToolRepository
zsasagithub.com/N283T/zsasa
FreeSASAgithub.com/mittinatten/freesasa
RustSASAgithub.com/maxall41/RustSASA
Lahutagithub.com/bisejdiu/lahuta

Acknowledgments

zsasa builds on ideas and methods from these excellent projects. We are grateful to their authors for advancing open-source SASA calculation:

  • FreeSASA by Simon Mitternacht — the foundational C library that established open-source SASA calculation. zsasa uses FreeSASA as the accuracy reference for validation.
  • RustSASA by Max Campbell — a modern Rust implementation that demonstrated SIMD-accelerated SASA calculation.
  • Lahuta by Besian I. Sejdiu — a C++ toolkit that pioneered bitmask LUT optimization for SASA.