Structure analysis
BiochemicalAlgorithms.AbstractMolecularSurfaceBiochemicalAlgorithms.Circle3BiochemicalAlgorithms.NumericalSASResultBiochemicalAlgorithms.ReducedSurfaceBiochemicalAlgorithms.SolventAccessibleSurfaceBiochemicalAlgorithms.SolventExcludedSurfaceBiochemicalAlgorithms.assign_ball_radii!BiochemicalAlgorithms.assign_radii!BiochemicalAlgorithms.check_rsBiochemicalAlgorithms.check_sesBiochemicalAlgorithms.clean_ses!BiochemicalAlgorithms.compute_bounding_boxBiochemicalAlgorithms.compute_numerical_sasBiochemicalAlgorithms.compute_reduced_surfaceBiochemicalAlgorithms.compute_sasBiochemicalAlgorithms.compute_sesBiochemicalAlgorithms.icosphereBiochemicalAlgorithms.load_ball_radii_tableBiochemicalAlgorithms.read_msmsBiochemicalAlgorithms.sas_areaBiochemicalAlgorithms.sas_volumeBiochemicalAlgorithms.ses_areaBiochemicalAlgorithms.surface_areaBiochemicalAlgorithms.triangulateBiochemicalAlgorithms.triangulate_sasBiochemicalAlgorithms.triangulate_sesBiochemicalAlgorithms.vdw_radius
Bounding box computation
BiochemicalAlgorithms.compute_bounding_box — Function
compute_bounding_box(
ac::AbstractAtomContainer{T}
) -> BoundingBox
Computes the axis-aligned bounding box of the given AbstractAtomContainer.
Molecular surfaces
Types
BiochemicalAlgorithms.AbstractMolecularSurface — Type
AbstractMolecularSurface{T<:Real}Common supertype for analytical molecular surfaces (reduced surface, SAS, SES).
BiochemicalAlgorithms.Circle3 — Type
Circle3{T<:Real}Oriented circle in 3D: center p, unit normal n (the circle's axis), radius r.
GeometryBasics.Circle is 2D only; Circle3 is used throughout the analytical surface algorithms (Connolly) where probe-atom contact circles must carry an orientation.
Radii and mesh helpers
BiochemicalAlgorithms.vdw_radius — Function
vdw_radius(
_::Type{T<:Real},
e::BiochemicalAlgorithms.Elements.T
) -> Any
van-der-Waals radius (in Å) for the given element, as type T.
Values are taken from Mendeleev's element data (Bondi-style). For elements without a published value (e.g., very heavy synthetic atoms) or for Elements.Unknown, a fallback of 1.5 Å is returned.
BiochemicalAlgorithms.assign_radii! — Function
assign_radii!(
ac::AbstractAtomContainer{T};
overwrite
) -> AbstractAtomContainer
Assign van-der-Waals radii to the atoms of ac. Atoms whose radius field is already non-zero are left untouched unless overwrite=true. Returns ac.
BiochemicalAlgorithms.assign_ball_radii! — Function
assign_ball_radii!(ac, rules::Dict{Tuple{String,String}, Float64};
fallback_element_radii::Bool = false)Assign atom radii from a BALL .siz-style table loaded by load_ball_radii_table. Each atom is looked up by (residue.name, atom.name); if no match, falls back to wildcard ("*", atom_name).
When fallback_element_radii=false (the default), atoms that match neither the explicit residue rule nor the wildcard are LEFT WITH THEIR EXISTING RADIUS (which is 0 for atoms that have never been assigned). BALL's radiusRuleProcessor follows this convention — atoms with radius == 0 are excluded from molecular-surface computations (see compute_reduced_surface).
Set fallback_element_radii=true to fall back to element-based vdW defaults (Bondi via Mendeleev) for unmatched atoms. This INCLUDES heteroatoms (heme Fe, exotic ions, etc.) in the surface — useful when you want a full molecular surface, but breaks bit-for-bit parity with BALL on PDBs containing HETATM records.
BiochemicalAlgorithms.load_ball_radii_table — Function
load_ball_radii_table(path::AbstractString) -> Dict{Tuple{String,String}, Float64}Load BALL's .siz radii table format (e.g., PARSE.siz, amber94.siz). Each entry is RESIDUE:ATOM_NAME RADIUS. Wildcard * matches any residue. Returns a dictionary keyed by (residue, atom_name).
BiochemicalAlgorithms.icosphere — Function
icosphere(
::Type{T<:Real}
) -> GeometryBasics.Mesh{_A, _B, GeometryBasics.TriangleFace{Int64}, _C, _D, Vector{GeometryBasics.TriangleFace{Int64}}} where {_A, _B<:Real, _C, _D<:(Tuple{var"#s13", Vararg{Union{AbstractVector{T}, GeometryBasics.FaceView{T, AVT} where AVT<:AbstractVector{T}} where T}} where var"#s13"<:AbstractArray{GeometryBasics.Point{_A, _B}, 1})}
icosphere(
::Type{T<:Real},
subdivisions::Int64
) -> GeometryBasics.Mesh{_A, _B, GeometryBasics.TriangleFace{Int64}, _C, _D, Vector{GeometryBasics.TriangleFace{Int64}}} where {_A, _B<:Real, _C, _D<:(Tuple{var"#s13", Vararg{Union{AbstractVector{T}, GeometryBasics.FaceView{T, AVT} where AVT<:AbstractVector{T}} where T}} where var"#s13"<:AbstractArray{GeometryBasics.Point{_A, _B}, 1})}
Generate a geodesic unit sphere by subdivisions rounds of icosahedral midpoint refinement.
Starts from a regular icosahedron (12 vertices, 20 faces), subdivides each triangle into four by splitting at edge midpoints, and projects every new vertex back onto the unit sphere. The resulting mesh has 10·4^subdivisions + 2 vertices.
Returns a GeometryBasics.Mesh with Point3{T} positions, per-vertex unit Vec3{T} outward normals (equal to the position on the unit sphere), and TriangleFace{Int} faces.
BiochemicalAlgorithms.surface_area — Function
surface_area(m::GeometryBasics.Mesh) -> Any
Total surface area of a triangulated mesh, computed as ½ Σ ‖(b-a) × (c-a)‖ over all triangles.
BiochemicalAlgorithms.read_msms — Function
read_msms(
_::Type{T<:Real},
vert_path::AbstractString,
face_path::AbstractString
) -> GeometryBasics.Mesh{_A, _B, GeometryBasics.TriangleFace{Int64}, _C, _D, Vector{GeometryBasics.TriangleFace{Int64}}} where {_A, _B<:Real, _C, _D<:(Tuple{var"#s13", Vararg{Union{AbstractVector{T}, GeometryBasics.FaceView{T, AVT} where AVT<:AbstractVector{T}} where T}} where var"#s13"<:AbstractArray{GeometryBasics.Point{_A, _B}, 1})}
Read a triangulated surface from a pair of MSMS files (Sanner et al.).
vert_path provides per-vertex coordinates and outward normals; face_path provides 1-based triangle vertex indices. Both files use a three-line header followed by whitespace-separated data lines. Returns a GeometryBasics.Mesh.
Numerical SAS (Eisenhaber/Argos)
BiochemicalAlgorithms.NumericalSASResult — Type
NumericalSASResult{T<:Real}Result of a numerical SAS computation. Vector fields are indexed by atom position in the source AbstractAtomContainer (i.e., at.r[i]-aligned), so atoms with radius == 0 keep zero contributions in atom_areas / atom_volumes.
Fields
total_area::T— total solvent-accessible surface area (Ų)total_volume::T— total volume enclosed by the SAS (ų)atom_areas::Vector{T}— per-atom area contribution (Ų)atom_volumes::Vector{T}— per-atom volume contribution (ų)surface_vertices— non-occluded sample points (only ifcompute_surface=true)surface_normals— area-weighted outward normals at each point (sum of‖normal‖equalstotal_area)atom_surface_vertices— per-atom sample points (only ifcompute_surface_per_atom=true)atom_surface_normals— per-atom area-weighted normals
BiochemicalAlgorithms.compute_numerical_sas — Function
compute_numerical_sas(
ac::AbstractAtomContainer{T<:Real};
probe_radius,
number_of_points,
compute_area,
compute_volume,
compute_surface,
compute_surface_per_atom
) -> NumericalSASResult
Compute the solvent-accessible surface (SAS) of ac numerically via the Eisenhaber/Argos double-cubic-lattice method (Eisenhaber, Lijnzaad, Argos, Sander & Scharf, J. Comput. Chem. 1995, 15, 273-284; Eisenhaber & Argos, J. Comput. Chem. 1993, 14, 1272-1280).
Every atom whose radius > 0.001 Å is inflated by probe_radius and sampled with number_of_points points distributed via icosahedral subdivision (the returned tessellation has the smallest 10·4ⁿ + 2 ≥ number_of_points vertices). For each sample, occlusion against neighboring inflated atoms is tested; non-occluded samples contribute to area, volume, and (optionally) surface point clouds.
Keyword arguments
probe_radius::T = 1.5— radius of the spherical probe (Å)number_of_points::Int = 400— lower bound on sample points per atomcompute_area::Bool = true— populatetotal_area/atom_areascompute_volume::Bool = true— populatetotal_volume/atom_volumescompute_surface::Bool = false— populate aggregatesurface_*fieldscompute_surface_per_atom::Bool = false— populateatom_surface_*fields
The volume is integrated via the divergence theorem V = ⅓ ∮ r·n dA, using the geometric center of the radius-bearing atoms as the origin (per BALL's convention).
BiochemicalAlgorithms.sas_area — Function
sas_area(ac::AbstractAtomContainer{T};
probe_radius = 1.5,
number_of_points = 1600) -> TTotal solvent-accessible surface area (Ų). Uses the Eisenhaber/Argos icosphere-sampling algorithm (see compute_numerical_sas); the result converges to the analytical SAS area as number_of_points grows.
sas_area(sas::SolventAccessibleSurface{T}; number_of_points = 1600) -> TTotal area of an already-constructed SAS. Re-evaluates the underlying atom geometry numerically; the topology stored in sas is not used.
BiochemicalAlgorithms.sas_volume — Function
sas_volume(ac::AbstractAtomContainer{T};
probe_radius = 1.5,
number_of_points = 1600) -> TTotal volume enclosed by the SAS (ų).
Reduced surface
BiochemicalAlgorithms.ReducedSurface — Type
ReducedSurface{T}Connolly's reduced surface for a set of atom spheres and a probe radius.
The RS is a graph of vertices (per-atom), edges (per atom pair where the probe can roll between two adjacent faces), and faces (per atom triple where the probe rests on three atoms simultaneously).
Build it from an atom container via compute_reduced_surface; atoms must have radius > 0 (use assign_radii! first).
Fields
atoms::Vector{Sphere{T}}— input atom spheres (radius does not include the probe)probe_radius::Tvertices::Vector{RSVertex},edges::Vector{RSEdge{T}},faces::Vector{RSFace{T}}bounding_box::BoundingBox{T}— over atom centersr_max::T— maximum atom radius
BiochemicalAlgorithms.compute_reduced_surface — Function
compute_reduced_surface(
ac::AbstractAtomContainer{T};
probe_radius
) -> ReducedSurface
Compute Connolly's reduced surface for an atom container.
The reduced surface (RS) is the topological skeleton produced by a spherical probe of radius probe_radius rolling over the inflated atom spheres: its vertices sit on individual atoms, its edges on pairs of atoms (where the probe rolls between two adjacent faces), and its faces on triples of atoms (where the probe rests tangent to all three).
Atoms with radius == 0 are skipped; call assign_radii! first to populate van-der-Waals radii.
Precision
The rolling-probe algorithm has many ULP-sensitive geometric tests (3-sphere intersection, probe-collision checks, oriented angles). BALL hardcodes double precision throughout its surface stack — all its TSphere3, TVector3, TCircle3 are <double> regardless of atom storage. We follow that convention: when called with a Float32 atom container the RS is built internally in Float64, then converted to ReducedSurface{Float32} for return. This keeps the user-facing type stable while avoiding the ~50 hole defects that Float32-internal arithmetic produces on BPTI.
Keyword arguments
probe_radius::T = 1.5— probe sphere radius (Å)
Analytical solvent-accessible surface
BiochemicalAlgorithms.SolventAccessibleSurface — Type
SolventAccessibleSurface{T}Analytical solvent-accessible surface (SAS) built as the dual of a ReducedSurface. Each atom contributes one or more spherical-cap faces; arcs and points on the surface come from the rolling-probe topology.
BiochemicalAlgorithms.compute_sas — Function
compute_sas(
rs::ReducedSurface{T<:Real}
) -> SolventAccessibleSurface
Compute the analytical solvent-accessible surface (SAS) from a precomputed ReducedSurface. The SAS shares its T parameter with the source RS and reuses its topology rather than recomputing it.
compute_sas(
ac::AbstractAtomContainer{T};
probe_radius
) -> SolventAccessibleSurface
Compute the analytical solvent-accessible surface (SAS) directly from an atom container. Equivalent to compute_sas(compute_reduced_surface(ac; probe_radius)).
Analytical solvent-excluded surface
BiochemicalAlgorithms.SolventExcludedSurface — Type
SolventExcludedSurface{T}Analytical solvent-excluded surface (SES) built from a ReducedSurface. The SES has three distinct face types — contact (atom patches), toric (saddle regions), and spheric (inverted-probe lobes) — connected by convex and concave arcs.
This implementation builds the topological skeleton but does not split singular toric faces (probe touching 4+ atoms). Such faces are recorded with type ToricSingular and left intact, which is sufficient for triangulation of typical molecular structures.
BiochemicalAlgorithms.compute_ses — Function
compute_ses(
rs::ReducedSurface{T<:Real};
density
) -> SolventExcludedSurface
Build the analytical solvent-excluded surface (SES) from a precomputed ReducedSurface.
Mirrors BALL SESComputer::run (solventExcludedSurface.C:1045-1058): build the SES once, run the singularity cleaner, and if the cleaner called deleteSimilarFaces on the underlying RS (returning false), discard the SES and rebuild it from the now-modified RS. Loops until the cleaner reports no further modifications.
compute_ses(
ac::AbstractAtomContainer{T};
probe_radius,
density
) -> SolventExcludedSurface
Compute the analytical solvent-excluded surface directly from an atom container. Equivalent to compute_ses(compute_reduced_surface(ac; probe_radius)).
BiochemicalAlgorithms.ses_area — Function
ses_area(ses::SolventExcludedSurface{T}; number_of_points = 1600) -> TTotal solvent-excluded surface area (Ų) summed over the three face types:
- contact (atom-sphere patches): Eisenhaber-style numerical integration using the SES-specific tangent-probe occlusion test;
- toric: closed-form surface-of-revolution between the two probe contact angles, swept by the rolling angle;
- spheric: spherical triangle area on the probe sphere.
number_of_points controls only the contact-face sampling; toric and spheric contributions are computed in closed form. Singular toric faces (probe touching ≥4 atoms) are included with their non-singular formula. Spindle-torus regions (probe radius exceeding the torus major radius) are clipped to the physically valid band by _ses_toric_face_area; the analytical sum may still differ slightly from mesh integration in densely packed structures due to the closed-form / numerical mixture. Where exact agreement with mesh integration matters, use surface_area(triangulate_ses(ses; density)) instead.
ses_area(ac::AbstractAtomContainer; probe_radius = 1.5, number_of_points = 1600)Convenience overload that builds the analytical SES first.
Triangulation
BiochemicalAlgorithms.triangulate — Function
triangulate(surface; density=1.0)Dispatch entry point for surface triangulation. Routes to triangulate_sas for a SolventAccessibleSurface and to triangulate_ses for a SolventExcludedSurface.
BiochemicalAlgorithms.triangulate_sas — Function
triangulate_sas(sas::SolventAccessibleSurface{T}; density = 1.0)Triangulate the analytical SAS produced by compute_sas.
Per-atom icosphere mesh of each inflated atom, with template vertices that fall behind any neighbour's intersection plane removed (BALL's removeInsideTriangles). The resulting mesh is patchwise — adjacent atoms produce separate triangulated caps with no boundary stitching between them, matching BALL's TriangulatedSAS semantics exactly.
density controls the icosphere refinement level via the same numberOfRefinements formula used for the SES (see triangulate_ses).
triangulate_sas(ac::AbstractAtomContainer{T}; probe_radius, density)Convenience overload that builds the analytical SAS first.
BiochemicalAlgorithms.triangulate_ses — Function
triangulate_ses(ses::SolventExcludedSurface{T}; density = 1.0)Build a triangulated mesh approximating the SES. Boundary curves (atom- contact circles and probe-sphere concave arcs) are sampled into a shared vertex pool so that adjacent spheric / toric / contact faces meet at exactly the same vertices — eliminating the per-patch cracks that an independent- sampler approach would produce.
density controls subdivision via BALL's adaptive formulas (see _segments_for_edge and _num_refinements):
- Per-RS-edge segment count:
max(1, round(angle · radius · √density)), matching BALL'spartitionNonFreeSingularEdge. - Per-atom contact icosphere refinement level:
numberOfRefinements(BALLtriangulatedSES.C:1350) — the smallestnwith(2·5·4^n + 2) ≥ 4·density·π·r².
Higher density therefore produces both finer arcs and finer interior icosphere patches; the relationship is monotonic but not linear in density.
triangulate_ses(ac::AbstractAtomContainer{T}; probe_radius, density)Convenience overload that builds the analytical SES first.
Mesh cleanup and validation
BiochemicalAlgorithms.clean_ses! — Function
clean_ses!(ses; min_torus_radius = 0, min_angle = 0, density = 0.0)Drop toric faces whose radius_of_torus or angle is below the supplied threshold. With density > 0, additionally drop toric faces whose triangulation would have fewer than 0.1 segments (BALL's cleanToricFace criterion: angle * radius * sqrt(density) < 0.1). Then prune any spheric/contact face whose rs_index references a no-longer-present element. Mirrors BALL's deleteSmallToricFace + cleanSphericFaces + cleanContactFaces cascade (solventExcludedSurface.C:249-303).
density defaults to 0.0, which disables the segment-count criterion (only min_torus_radius / min_angle apply). Pass the density you'll triangulate with to enable the BALL-style sliver removal — sub-segment sliver toric faces are the dominant source of T-junctions in the triangulator, so enabling it directly improves mesh manifoldness.
Returns the number of toric faces removed.
BiochemicalAlgorithms.check_rs — Function
check_rs(rs::ReducedSurface) -> Vector{String}Topology integrity check for a ReducedSurface. Returns a list of human-readable issues (empty vector = healthy). Validates:
- every face's vertex/edge slot is within bounds and non-zero;
- every edge's vertex slot is within bounds;
- faces sit on three distinct atoms;
- the cached
vertex.edges/vertex.facessets agree with the canonical face/edge tables.
BiochemicalAlgorithms.check_ses — Function
check_ses(ses::SolventExcludedSurface) -> Vector{String}Topology integrity check for a SolventExcludedSurface. Returns a list of issues (empty vector = healthy). Validates that:
- every SES edge references valid SES vertex indices;
- every face's vertex / edge list refers to in-range indices;
- every face is one of the four
SESFaceTypeenums; - the underlying reduced surface itself passes
check_rs.