quality — Publication Visualization & Structure Quality
The synth_pdb.quality sub-package provides two complementary capabilities:
- Publication-ready plots — journal-standard figures for chemical shift correlations, Ramachandran analysis, and SAXS profiles.
- Structure quality classification — GNN-based and feature-based classifiers for scoring structural plausibility.
Optional Dependencies
The plotting functions require matplotlib. The correlation plot additionally requires scipy. If either is absent the functions return None and log an error — they do not raise, so scripts can run in headless environments.
pip install synth-pdb[viz] # installs matplotlib + scipy
Plotting Functions
Import directly from the sub-package:
from synth_pdb.quality import (
apply_publication_style,
save_publication_figure,
plot_chemical_shift_correlation,
plot_ramachandran_publication,
plot_saxs_publication,
)
Or from the full module path:
from synth_pdb.quality.plots import plot_ramachandran_publication
apply_publication_style()
Sets journal-standard matplotlib rcParams globally: sans-serif fonts (Arial/Helvetica), 300 DPI save default, cleaned tick sizes.
!!! note "Side-effect scope"
This modifies global rcParams. It intentionally does not set savefig.format — the format is always passed explicitly via save_publication_figure to avoid silently changing the output format of other figures in the same process.
save_publication_figure(fig, path, transparent=False)
Saves a figure at 300 DPI with bbox_inches="tight". The format is derived from the file extension (defaults to PDF when no extension is given).
save_publication_figure(fig, "output/ca_correlation.pdf")
save_publication_figure(fig, "output/figure1") # → saves as .pdf
save_publication_figure(fig, "output/thumbnail.png") # → saves as .png
plot_chemical_shift_correlation
fig = plot_chemical_shift_correlation(
exp_data, # dict[int, dict[str, float]] residue → {atom: ppm}
syn_data, # dict[int, dict[str, float]] (same structure)
atom_type="CA", # which nucleus to plot
title=None, # optional override; auto-generates R value in title
output_path=None, # if set, saves the figure
)
Generates a scatter plot of experimental vs synthetic shifts with a diagonal reference line. Annotates Pearson R and RMSD automatically.
plot_ramachandran_publication
fig = plot_ramachandran_publication(
phi, # np.ndarray of φ angles in degrees
psi, # np.ndarray of ψ angles in degrees
title="Ramachandran Plot",
output_path=None,
)
!!! warning "Approximate region shading" The α-helical (blue) and β-strand (red) shaded regions are simplified rectangular approximations. They are not the probability-density contours from MolProbity or the Richardson Top8000 dataset. Use them for quick visual reference only — do not cite them as quantitative Ramachandran statistics.
plot_saxs_publication
fig = plot_saxs_publication(
q, # np.ndarray — scattering vector (Å⁻¹)
intensity, # np.ndarray — I(q)
rg=None, # float | None — annotates Rg on the plot when provided
output_path=None,
)
Plots I(q) on a log-linear scale (standard for SAXS publications).
Full API Reference
::: synth_pdb.quality.plots handler: python options: members: - apply_publication_style - save_publication_figure - plot_chemical_shift_correlation - plot_ramachandran_publication - plot_saxs_publication
Complete Workflow Example
import numpy as np
import biotite.structure.io.pdb as pdb_io
from synth_pdb.bmrb_api import BMRBAPI
from synth_pdb.chemical_shifts import predict_chemical_shifts
from synth_pdb.saxs import calculate_saxs_profile, calculate_radius_of_gyration
from synth_pdb.quality import (
plot_chemical_shift_correlation,
plot_ramachandran_publication,
plot_saxs_publication,
)
import biotite.structure as struc
# Load structure
structure = pdb_io.PDBFile.read("examples/1D3Z.pdb").get_structure(model=1)
# Chemical shift correlation
exp_shifts = BMRBAPI.fetch_chemical_shifts("6457")
syn_shifts_full = predict_chemical_shifts(structure)
syn_shifts = list(syn_shifts_full.values())[0] # first chain
fig = plot_chemical_shift_correlation(
exp_shifts, syn_shifts, atom_type="CA",
output_path="figures/ca_correlation.pdf",
)
# Ramachandran plot
phi, psi, _ = struc.dihedral_backbone(structure)
mask = ~np.isnan(phi) & ~np.isnan(psi)
plot_ramachandran_publication(
np.degrees(phi[mask]), np.degrees(psi[mask]),
output_path="figures/ramachandran.pdf",
)
# SAXS profile
q, intensity = calculate_saxs_profile(structure, q_max=0.3)
rg = calculate_radius_of_gyration(structure)
plot_saxs_publication(q, intensity, rg=rg, output_path="figures/saxs.pdf")