QC, cleanup & structure#

Quality control utilities for replicate trajectory analysis.

phenoms.qc.parse_mdp(path)[source]#

Parse a GROMACS .mdp file into a normalized key/value dictionary.

Parameters:

path (str | Path)

Return type:

dict[str, str]

phenoms.qc.check_mdp_key_consistency(mdp_files, keys=('integrator', 'dt', 'nsteps', 'tcoupl', 'pcoupl', 'constraints', 'constraint-algorithm', 'coulombtype', 'rcoulomb', 'vdwtype', 'rvdw', 'tc-grps', 'tau-t', 'ref-t', 'tau-p', 'ref-p'))[source]#

Check that selected MDP keys are consistent across all provided files. Returns a report dictionary with per-key mismatches.

Parameters:
Return type:

dict

phenoms.qc.assess_series_convergence(series, *, last_fraction=0.2, mean_tolerance=0.05, slope_tolerance=0.0001)[source]#

Simple convergence check: - compare mean of penultimate vs final window - fit slope on final window

Parameters:
Return type:

dict

phenoms.qc.rmsd_convergence_report(traj, *, atom_selection='protein and backbone', last_fraction=0.2, mean_tolerance=0.05, slope_tolerance=0.0001)[source]#

Compute RMSD-to-first-frame series and run a simple convergence check.

Parameters:
  • traj (Trajectory)

  • atom_selection (str)

  • last_fraction (float)

  • mean_tolerance (float)

  • slope_tolerance (float)

Return type:

dict

Optional preprocessing: renumber a mobile PDB trajectory to match a reference PDB’s residue numbers via sequence alignment (handles indels, e.g. Δ747–749 vs WT).

PHENOMS bond labels use PDB residue sequence numbers. Pick which structure defines the target scheme (e.g. renumber WT to mut, or mut to WT). With fill_unmapped_mobile=True, mobile residues that align to gaps in the reference (longer WT vs deletion in mut, or N/C overhangs) get consecutive numbers so every mapped standard residue can be rewritten.

No extra dependencies: global alignment is Needleman–Wunsch (pure Python).

class phenoms.cleanup.ResidueKey(chain, resseq, icode=' ')[source]#

Bases: object

Identifies one residue in a PDB (chain + sequence + insertion code).

Parameters:
chain: str#
resseq: int#
icode: str = ' '#
class phenoms.cleanup.RenumberReport(n_reference_residues, n_mobile_residues, n_mapped, n_mismatch_at_aligned_positions, n_mobile_only_gaps_in_reference, n_filled_unmapped_mobile, aligned_reference_sequence, aligned_mobile_sequence)[source]#

Bases: object

Summary of an align-and-renumber operation.

Parameters:
  • n_reference_residues (int)

  • n_mobile_residues (int)

  • n_mapped (int)

  • n_mismatch_at_aligned_positions (int)

  • n_mobile_only_gaps_in_reference (int)

  • n_filled_unmapped_mobile (int)

  • aligned_reference_sequence (str)

  • aligned_mobile_sequence (str)

n_reference_residues: int#
n_mobile_residues: int#
n_mapped: int#
n_mismatch_at_aligned_positions: int#
n_mobile_only_gaps_in_reference: int#
n_filled_unmapped_mobile: int#
aligned_reference_sequence: str#
aligned_mobile_sequence: str#
phenoms.cleanup.ordered_residue_run(pdb_path, *, chain_id=None)[source]#

First occurrence order of protein residues in the PDB (file order), optional chain filter.

Returns:

  • keys (list of ResidueKey)

  • sequence (str) – One-letter amino acid sequence in the same order.

Parameters:
Return type:

Tuple[List[ResidueKey], str]

phenoms.cleanup.needleman_wunsch(s1, s2, *, match=2, mismatch=-1, gap=-2)[source]#

Global alignment of two strings. Returns (aligned_s1, aligned_s2) with ‘-’ gaps.

Parameters:
Return type:

Tuple[str, str]

phenoms.cleanup.build_mobile_to_reference_map(ref_keys, ref_seq, mob_keys, mob_seq, *, match=2, mismatch=-1, gap=-2, fill_unmapped_mobile=False)[source]#

Align mobile sequence to reference; map each mobile residue key -> reference resseq.

Matched columns (both non-gap) assign mobile residue the reference residue number at that column.

If fill_unmapped_mobile is False, mobile residues aligned to a gap in the reference are left unmapped.

If True, those residues get consecutive numbers: N/C overhangs extend from the first/last mapped reference number; internal gaps (e.g. WT residues where mut has a deletion) are numbered L+1, L+2, ... from the last mapped reference residue L before the gap (and fit below the next reference R when integers are available).

Parameters:
Return type:

Tuple[Dict[ResidueKey, int], RenumberReport]

phenoms.cleanup.renumber_pdb_atom_lines(lines, mob_to_ref_resseq)[source]#

Return new lines with residue sequence numbers rewritten where mapping applies.

Parameters:
Return type:

List[str]

phenoms.cleanup.iter_pdb_models(lines)[source]#

Yield (start_idx, end_idx_inclusive) for each MODEL … ENDMDL block. If no MODEL records, yield (0, len-1) for whole file.

Parameters:

lines (Sequence[str])

Return type:

Iterator[Tuple[int, int]]

phenoms.cleanup.renumber_pdb_file(mobile_pdb, output_pdb, mob_to_ref_resseq)[source]#

Rewrite mobile_pdb to output_pdb applying residue number mapping (all MODELs).

Parameters:
Return type:

None

phenoms.cleanup.align_and_renumber_pdb(reference_pdb, mobile_pdb, output_pdb, *, chain_id=None, match=2, mismatch=-1, gap=-2, fill_unmapped_mobile=False)[source]#

Align mobile chain sequence to reference chain sequence and write a new PDB where mobile residue numbers match the reference numbering for aligned positions.

Parameters:
  • reference_pdb (str | Path) – PDB whose residue numbers define the target scheme (e.g. mut, or WT).

  • mobile_pdb (str | Path) – Trajectory or structure to renumber (e.g. WT when reference is mut).

  • output_pdb (str | Path) – Path for the renumbered copy (atoms unchanged; only resSeq fields updated where mapped).

  • chain_id (str | None) – PDB chain to use on both files. If None and the file has exactly one non-empty chain, that chain is used; otherwise this must be set (e.g. 'A').

  • fill_unmapped_mobile (bool) – If True, assign consecutive resSeq to mobile residues in alignment columns where the reference has a gap (WT-only segment vs mut deletion, or N/C overhang on mobile).

  • match (int)

  • mismatch (int)

  • gap (int)

Returns:

Alignment statistics (check n_mismatch_at_aligned_positions and unmapped counts).

Return type:

RenumberReport

Notes

  • If fill_unmapped_mobile is False, mobile residues opposite a reference gap keep their original resSeq.

  • Non-standard residues (not in THREE_TO_ONE) are not mapped and are copied unchanged.

phenoms.cleanup.renumber_many_to_reference(reference_pdb, mobile_pdbs, output_dir, *, chain_id=None, suffix='_renumbered_to_ref.pdb', match=2, mismatch=-1, gap=-2, fill_unmapped_mobile=False)[source]#

Renumber multiple mobile PDBs to the same reference; write under output_dir.

Output names: {stem}{suffix} for each input stem. Returns mapping stem -> RenumberReport.

Parameters:
Return type:

Dict[str, RenumberReport]

Write PDB with B-factors set from per-residue values (e.g. difference, variance) for visualization.

phenoms.structure.write_pdb_bfactors(pdb_path, residue_to_value, output_path, value_column=None, model_index=0)[source]#

Write a PDB file with B-factors set to the given per-residue values (e.g. difference). Use for PyMOL/Chimera visualization of differential protection or fluctuation.

Parameters:
  • pdb_path (str) – Reference PDB file path.

  • residue_to_value (dict or pd.DataFrame) – If dict: mapping residue_number (int) -> value (float). If DataFrame: must have ‘Residue Number’ and a value column (or ‘Difference’).

  • output_path (str) – Output PDB path.

  • value_column (str or None) – If residue_to_value is a DataFrame, column to use for B-factor. If None, uses Difference_clipped when present, else Difference.

  • model_index (int) – Only modify a single static model/frame (0-based). Useful for multi-model PDBs.

phenoms.structure.residue_value_map_from_comparison(comparison_df, value_column='Difference_clipped')[source]#

Build dict residue_number -> value from comparison DataFrame for write_pdb_bfactors.