R.01 University research / Structural biology / 2025—2026

PROTEINFLEXIBILITY

DSA — Distance Structure Analysis. Given one UniProt ID, it gathers every solved structure of that protein and measures how much each pair of residues moves between them, without ever superposing the structures.

2025—2026
Gakushuin University / Okada Lab
SECTOR
Research software
ROLE
Analysis design, engine implementation, API and interface
YEAR
2025—2026
CONTEXT
Gakushuin University / Okada Lab
SOURCE
github.com/bbbyk105/protein-flexibility-platform

01 / PROJECT

WHAT THE
PROBLEM IS.

The question is which parts of a protein are rigid and which are flexible. The usual way to answer it is to superpose structures on one another, but superposition needs a reference frame, and the answer changes with the frame you pick.

Distances between Cα atoms do not have that problem: the distance between two residues is the same however the structure is rotated or translated. So the analysis works entirely in distance space. For every pair of residues it collects the Cα–Cα distance across all the structures, then takes the mean and the standard deviation of that distance. A pair whose distance barely changes across dozens of structures is rigid; one whose distance scatters is flexible.

The hard part is not the arithmetic — it is getting comparable data. The same protein appears in the PDB as dozens of entries with different chains, different constructs, engineered mutations, chimeras, expression tags, missing residues and inconsistent numbering. Most of the code exists to reconcile all of that against one UniProt sequence before a single distance is computed.

02 / HOW IT WORKS

STEP BY STEP,
END TO END.

INPUT → OUTPUT PER STAGE

01
Resolve the protein

Fetch the UniProt entry as XML and read out the accession list, the canonical sequence and every cross-referenced PDB entry with its method and resolution.

accessions, FASTA, PDB table
02
Select structures

Keep only the determination methods asked for — X-ray and cryo-EM by default, NMR off, since an NMR ensemble would skew the spread. Explicitly excluded PDB IDs are dropped here, and the run stops early if too few entries survive.

PDB ID list
03
Download and parse

Pull each structure as mmCIF through Biopython's PDBList and read it with MMCIF2Dict. Atom records are filtered to ATOM only, alternate locations are resolved to one per residue, and the coordinates are cached per PDB ID so a re-run does not re-download.

atom_coord/{pdbid}.csv
04
Judge each entry

Compare the structure's sequence references against UniProt and classify the entry as normal, substitution, chimera or delins. Differences annotated as expression tag, linker, conflict or microheterogeneity are ignored — they are artefacts of crystallography, not real sequence changes.

normal / substitution / chimera / delins
05
Align to one sequence

Lay every chain against the UniProt sequence, padding each to the same length from its alignment range. Chains where too few residues actually have coordinates are dropped by a ratio threshold, duplicate residue numbers are collapsed, and chains that will not align after a bounded shift search are discarded with a note.

aligned residue × chain table
06
Take the Cα coordinates

From the cached atom tables, keep only Cα atoms and assemble one matrix of coordinates: every surviving residue position down the rows, every surviving chain across the columns. Rows with any gap are removed, so every pair is measured on exactly the same set of structures.

residue × chain Cα matrix
07
Measure every pair

For each of the N(N−1)/2 residue pairs, compute the Cα–Cα distance in every chain. The inner distance function is JIT-compiled with numba and rounds coordinates to a fixed precision first, so the same input always gives bit-identical output across runs.

pair × chain distance matrix
08
Score the flexibility

Per pair, take the mean and the population standard deviation of that distance across chains, then divide: score = mean / std. A pair that holds the same distance in every structure gets a high score; one that scatters gets a low one. Averaging the score over all pairs gives the protein a single number, UMF.

score, UMF
09
Detect cis bonds

Any residue pair whose Cα–Cα distance falls under the threshold — about 3.3 Å against the roughly 3.8 Å of a normal trans peptide bond — is a cis peptide bond. These are counted and scored separately, since a cis bond sitting in a flexible region means something different from one in a rigid core.

cis count, cis score
10
Report

Emit a heatmap of the pair scores laid out as a residue × residue matrix, a per-residue score for colouring a 3D model, the full pair table as CSV, and a one-row summary — entries, chains, length, mean resolution, UMF, cis statistics — appended to a running CSV so results accumulate across proteins.

heatmap.png, CSV, summary row

03 / ARCHITECTURE

THREE TIERS,
ONE PIPELINE.

01
Interface

Takes UniProt IDs and parameters, creates the job, polls it to completion, then renders the result: the structure in a 3D viewer coloured by per-residue score, the score plots, and the heatmap.

  • Next.js
  • React
  • TypeScript
  • Mol*
  • Recharts
  • TanStack Query
  • Zustand
02
Job API

Splits a batch of UniProt IDs into one job each, assigns an ID, runs the analysis engine as a subprocess under a timeout, persists status and progress, and serves the finished artefacts. Long analyses survive a page reload because the job, not the request, holds the state.

  • Go
  • Gin
  • UUID
03
Analysis engine

The pipeline above, packaged as an installable library with a CLI. It runs on its own from a terminal, which is what makes it usable in the lab without the rest of the platform.

  • Python
  • NumPy
  • pandas
  • Biopython
  • numba
  • Pydantic
  • Click

04 / THE CORE

THE WHOLE IDEA,
IN ONE DIVISION.

score.pyPython
# One row per residue pair, one column per chain.
dis   = distance.iloc[:, 2:]
means = dis.mean(axis='columns')
stds  = dis.std(axis='columns', ddof=0)

# Hold the same distance everywhere -> high score.
score = means / stds
Python7 LINES

05 / OUTPUT

WHAT IT
PRODUCES.

  1. 01

    UMF — one number per protein, the mean of mean/std over all residue pairs

  2. 02

    Pair scores — every residue pair with its mean distance, standard deviation and score

  3. 03

    Per-residue scores, used to colour the structure in the 3D viewer

  4. 04

    A residue × residue heatmap of the pair scores

  5. 05

    Cis peptide bonds: count, mean distance, spread and score

  6. 06

    A summary row per run — entries, chains, length covered, mean resolution — appended to a cumulative CSV

06 / TECHNOLOGY

THE STACK
BEHIND IT.

  • Python
  • NumPy
  • pandas
  • Biopython
  • numba
  • FastAPI
  • Go
  • Gin
  • Next.js
  • Mol*
ALL WORKSWORKSGET IN TOUCH