Repository navigation
dmax Flexibility Metric
dmax is a per-residue flexibility metric. It measures the outlier-trimmed maximum spread of an ensemble in (curvature, torsion) space.
A high dmax value marks a residue whose local backbone geometry spans a wide region across the ensemble. This can highlight flexible residues, residues involved in conformational change, or local regions where models disagree.
dmax is computed from trimmed extrema rather than raw extrema so that sparse extreme observations have less influence on the final value.
geometry/residues.csv includes dmax for every residue, and overview.png plots it along the sequence. The output folder's README.md lists the most flexible residues.
The trimmed bounds used in the calculation are in result.residue_summary_df when using FleXgeo2 from Python:
-
curvature_dmax_min,curvature_dmax_max: trimmed curvature bounds -
torsion_dmax_min,torsion_dmax_max: trimmed torsion bounds -
curvature_dmax_bin_width,torsion_dmax_bin_width: histogram bin widths used for trimming
The default outlier fraction is 0.01.
flexgeo2 path/to/ensemble.pdb --dmax-outlier-fraction 0.01Increase the value to trim more sparse extreme bins:
flexgeo2 path/to/ensemble.pdb --dmax-outlier-fraction 0.05The fraction must be in [0, 1).
After a Python run:
from flexgeo2 import AnalysisConfig, FlexGeo2App
result = FlexGeo2App().run(AnalysisConfig(pdb_file="path/to/ensemble.pdb"))
top_dmax = result.residue_summary_df.sort_values("dmax", ascending=False).head(10)
top_dmax[["chain", "order", "residue_label", "models", "dmax"]]These rows identify residues with the widest trimmed curvature/torsion spread.
Once raw_df exists, you can recompute residue summaries with different dmax_outlier_fraction values without loading the PDB again.
from flexgeo2.geometry import GeometryService
geometry = GeometryService()
summary_1pct = geometry.summarize(result.raw_df, dmax_outlier_fraction=0.01)
summary_5pct = geometry.summarize(result.raw_df, dmax_outlier_fraction=0.05)
comparison = summary_1pct[["chain", "order", "residue_label", "dmax"]].merge(
summary_5pct[["chain", "order", "residue_label", "dmax"]],
on=["chain", "order", "residue_label"],
suffixes=("_1pct", "_5pct"),
)
comparison["delta"] = comparison["dmax_5pct"] - comparison["dmax_1pct"]
comparison.reindex(comparison["delta"].abs().sort_values(ascending=False).index).head(10)Large absolute delta values mark residues whose dmax is sensitive to the trimming threshold.
For a runnable version of this workflow, see notebooks/06_dmax_library_api.ipynb.