use super::*;
use crate::prelude::*;
use molframe_chem::{HeteroPolicy, MetalFallback, TableRequest};
const CRAMBIN: &[u8] = include_bytes!("../../../molframe-bench/data/1crn.pdb");
const HEMOGLOBIN: &[u8] = include_bytes!("../../../molframe-bench/data/4hhb.pdb");
fn bondi() -> SasaOptions {
SasaOptions::resolve(&TableRequest::profile(), molframe_bench::table_store())
.expect("bench profile resolves")
}
fn read(bytes: &[u8]) -> crate::Structure {
match crate::read_bytes(bytes.to_vec(), Some("e.pdb"), &ReadOptions::new()) {
Ok((structure, _)) => structure,
Err(findings) => panic!("fixture read failed: {findings:?}"),
}
}
fn total(structure: &crate::Structure, options: &SasaOptions) -> f64 {
let areas = structure
.sasa_with(options, &ExecutionContext::default())
.expect("sasa");
areas.iter().filter(|area| area.is_finite()).sum()
}
fn within(value: f64, reference: f64, relative: f64) -> bool {
(value - reference).abs() <= reference * relative
}
fn lee_richards() -> SasaOptions {
SasaOptions {
method: SasaMethod::LeeRichards { slices: 20 },
..bondi()
}
}
#[test]
fn crambin_matches_freesasa_for_both_methods() {
let structure = read(CRAMBIN);
let sr = total(&structure, &bondi());
let lr = total(&structure, &lee_richards());
assert!(within(sr, 2970.152, 0.005), "SR {sr}");
assert!(within(lr, 2969.918, 0.005), "LR {lr}");
}
#[test]
fn haemoglobin_default_measures_the_polymer_like_freesasa() {
let structure = read(HEMOGLOBIN);
let sr = total(&structure, &bondi());
let lr = total(&structure, &lee_richards());
assert!(within(sr, 26097.315, 0.005), "SR {sr}");
assert!(within(lr, 26119.71, 0.005), "LR {lr}");
}
#[test]
fn excluded_heteroatoms_have_nan_area_and_do_not_occlude() {
let structure = read(HEMOGLOBIN);
let areas = structure.sasa(molframe_bench::table_store()).expect("sasa");
let finite = areas.iter().filter(|area| area.is_finite()).count();
assert_eq!(finite, 4384);
assert_eq!(areas.len() - finite, structure.atom_count() as usize - 4384);
}
#[test]
fn including_every_heteroatom_matches_freesasa_with_haem_iron_at_alvarez_radius() {
let structure = read(HEMOGLOBIN);
let everything = |method| SasaOptions {
method,
hetero: HeteroPolicy::ALL,
..bondi()
};
let sr = total(
&structure,
&everything(SasaMethod::ShrakeRupley { points: 960 }),
);
let lr = total(
&structure,
&everything(SasaMethod::LeeRichards { slices: 20 }),
);
assert!(within(sr, 24073.036, 0.005), "SR {sr}");
assert!(within(lr, 24094.362, 0.005), "LR {lr}");
}
#[test]
fn a_metal_without_a_bondi_radius_is_measured_only_when_asked() {
let structure = read(HEMOGLOBIN);
let iron = structure
.atoms()
.into_iter()
.find(|atom| atom.element() == Some(molframe_core::Element::IRON))
.map(|atom| atom.index().as_usize())
.expect("haem iron");
let options = |metals| SasaOptions {
hetero: HeteroPolicy::SOLUTE,
metals,
..bondi()
};
let ask = |metals| {
structure
.sasa_with(&options(metals), &ExecutionContext::default())
.expect("sasa")[iron]
};
assert!(ask(MetalFallback::None).is_nan());
assert!(ask(MetalFallback::Vdw).is_finite());
}