Changelog¶
Changelog¶
All notable changes to this project are documented in this file. The format follows Keep a Changelog.
[Unreleased]¶
[1.8.0] - 2026-07-22¶
Added¶
PDB writing: parsed structures can be serialized back to conformant fixed-column PDB.
PDBParser.write_PDB()assembles a document in canonical section order, reconstructs the coordinate section (ATOMwith interleavedANISOUand chain-terminatingTERcards, thenHETATM), and regenerates theMASTER/ENDbookkeeping records from the emitted content. The record-level engine (pidibble.pdbwrite.PDBWriter) is the inverse of the parser, driven by the same field specs plus optional per-field writer hints ({prec, just}) carried as a third element in the YAML field definitions.Coverage spans all four writable record families: single-line records (types 1/3, plus
TER), continuation records (type 2 —TITLE,COMPND,SOURCE,KEYWDS,AUTHOR, …), and determinant-group records (type 4 —SEQRES,HETNAM,HETSYN,FORMUL,SITE, and the multi-lineREVDAT), re-wrapped/chunked across numbered continuation lines.REMARKandJRNL(type 6) are re-emitted verbatim from the source lines.A full
parse -> write -> re-parseround-trip preserves every parsed record type and all field values on 4ZMJ (60 keys) and 4TVP (64 keys, incl.SITE); the regeneratedMASTERmatches the original entry’s byte-for-byte, and the coordinate/SEQRES/HETNAM/FORMUL/KEYWDS/TITLErecords re-serialize byte-exactly.Hexadecimal serial numbers for structures with more than 99999 atoms (e.g. large solvated systems):
HexSerialEncoderis the exact inverse of the parser’sAtomSerialParser, switching to hex once a serial passes 99999 and staying hex thereafter — including smallCONECTback-references, which the parser reads as hex once tripped. Serials round-trip up to the 5-column hybrid-hex ceiling (0xFFFFF= 1 048 575 atoms).CHARMM read/write dialect (
PDBParser(dialect='charmm'),write_PDB(dialect='charmm')), for coordinate PDBs that must stay column-congruent with a CHARMM/psfgen PSF. It widensresNameto 6 columns for CHARMM/glycan names (e.g.BGLCNA,ANE5AC) and writes the authoritativesegIDcolumn (73-76) that psfgencoordpdbdepends on, while pinning x/y/z at columns 31-54 regardless of resName width — designing out the wide-resName coordinate-column drift that scrambles fixed-column readers. Parser and writer share one column model (charmm_formats/ResidueCharmmin the YAML) so they are exact inverses; the default'standard'dialect remains strict wwPDB. Aparse -> write -> parseround-trip on a glycan structure with a populated segID column is the identity for every coordinate field.
Changed¶
Field specs may now carry an optional third element with writer formatting hints; parsing ignores it (the byte-range unpacking is now width-tolerant), so the change is fully backward-compatible.
Not yet supported¶
Re-serialization of
REMARK/JRNLfrom the parsed model (they are passed through from the source instead, so they are omitted when the input was mmCIF), and multi-model coordinate sections.
[1.7.2] - 2026-07-21¶
Added¶
Continuous-integration workflow (
tests.yaml) running the unit tests on Python 3.10–3.12 and the documentation doctests on every push and pull request. Previously tests ran only on tagged releases.README now documents PDBx/mmCIF parsing (with a worked example) and carries version, Python-versions, license, tests, docs, and downloads badges.
Changed¶
Documentation overhauled from a single quickstart page into a multi-page User Guide — loading structures, the parsed data model, working with records, biological assemblies and symmetry, PDBx/mmCIF, large structures, nonconformant files, and advanced/customization — plus a supported-record-types coverage table. Numerous example corrections; every doctest is now validated (
sphinx -b doctest), withNORMALIZE_WHITESPACEenabled so pretty-printed output validates on content rather than incidental spacing. The docs landing page is retitled from “Welcome to Pidibble’s documentation!” to “pidibble”.
[1.7.1] - 2026-07-15¶
Added¶
mmCIF
REMARK.350(biological assembly) records now exposeheader_label, the raw label asym_id list, alongside the existingheader(author chains, mapped via the chainmap). This preserves the full per-chain (label) detail — including glycan/ligand chains — that the deduplicated author-chain list collapses.
[1.7.0] - 2026-07-14¶
Added¶
Substantially expanded PDBx/mmCIF parsing: coverage grew from 6 to 16 record types (reading 22 of a typical file’s ~73 categories). New mmCIF-mapped records:
HEADER,TITLE,EXPDTA,KEYWDS,CRYST1,SEQRES,HELIX,SHEET(complete — ranges, sense, numStrands, H-bond registration), andCOMPND/SOURCE(as native per-entity records). Metal coordination (metalc) now folds intoLINK. Every mapping is validated against the legacy PDB parse.mmCIF↔PDB correspondence test suite revived and extended (atoms, links, ssbonds, seqadv, missing residues, assembly, metadata, seqres, helix, sheet, entities, metal coordination).
mmCIF coverage summary logged at parse time: how many of a file’s categories pidibble reads, with the unmapped ones listed at DEBUG level.
docs/mmcif_coverage.md: PDB vs PDBx/mmCIF coverage audit and roadmap.Reusable declarative mmCIF mapspec directives:
merge,join(multi-keymatch:conditions with nested residue dicts),groupby/collect/lengths,as_list,value_maps, list-awareallcaps, and multi-valuesignal_value.
Changed¶
mmCIF
gen_dictrefactored onto the py-mmcif higher-level API (selectIndices,getRowAttributeDict) instead of positionalgetValueloops; verified byte-for-byte identical output on existing records.A mapped-but-absent mmCIF category now emits no records (previously produced a spurious empty
{'tables': {}}record).
Removed¶
Dead
MMCIFDictclass andresolve()stub inmmcif_parse.py.
[1.6.0] - 2026-07-14¶
Added¶
NonconformanceRegistry: PDB-format deviations (e.g. achargecolumn that cannot be coerced to its declared type, or a record exceeding 80 bytes) are now aggregated by type — keyed by(record_key, field, kind)— rather than logged per instance. At the end of a parse,PDBParseremits a single INFO summary line per type with a count and one exemplar, replacing what could be tens of thousands of repeated warnings. The registry is available programmatically asPDBParser.nonconformances(.types(),len(),bool()).
Changed¶
Per-instance field/record parse-error messages demoted from WARNING to DEBUG; the INFO type-summary is the default-visible output, with full per-instance detail available by setting the logger to DEBUG.
[1.5.4] - 2026-07-14¶
Fixed¶
ATOM/HETATM/ANISOU
chargefield retyped fromFloattoString. The PDB charge column (79–80) is a formatted string (e.g.1-,2+), never a plain float, so every populated charge previously failedfloat()and emitted a spurious “Could not parse field charge” warning while discarding the value. Charges are now captured correctly (e.g.1-).Off-by-one in
StringParser.report_record_error()highlight: the error display dropped the character at the field’s first column and coloured a window shifted one column to the right of the offending field. The highlight now wraps exactly the columns given by the field’s byte range.
[1.5.3] - 2026-05-03¶
Fixed¶
PDBParser(PDBcode=...)legacy parameter silently swallowed by**kwargs; restored via explicit mapping tosource_id/source_db='rcsb'Eight bare
except:clauses narrowed to specific exception types throughoutBitwise
&=used as logical AND inBaseRecord.empty()replaced withall()str2int_sigraisedIndexErroron empty-string input; added guard before index access!= None/== Nonecomparisons replaced withis not None/is Nonethroughouttype(x) == Tidentity comparisons replaced withisinstance(x, T)throughoutelif type(p) == list:inparse_tokens()was unreachable; corrected toisinstance(p, PDBRecordList)Mutable default arguments
hold={}andhold=[]ingather_tokenandheader_checkreplaced withNone
Changed¶
Global hex-tripped flag in
hex.pyreplaced withAtomSerialParsercallable class; eachPDBParserinstance owns its own state, eliminating thread-safety hazard and cross-parse contaminationmappersdefault argument changed from a mutable dict literal toNone; default built inside__init__Resource YAML files now loaded via
importlib.resources.files()instead ofos.path.dirname(resources.__file__), ensuring correct behavior inside wheels and zip archivesresources/__init__.pyremoved;resources/is now a plain data directory, not a sub-packageMANIFEST.inremoved; hatchling auto-discovers package data from git-tracked filesPEP 8 spacing applied throughout all source files
parse_embedded()refactored:triggered/capturingboolean pair replaced with explicit_EmbedStateenum (SEARCHING,PRE_CAPTURE,CAPTURING); setup phase extracted into_setup_embed_context()
Added¶
CHANGELOG.mdwith full release historyscripts/release.shfor automated version rotation, tagging, and push[test]optional dependency group inpyproject.toml
[1.5.2] - 2025-09-16¶
Added¶
Capability to download structures from OPM and split DUM residues into a separate PDB file
[1.5.1] - 2025-09-15¶
Fixed¶
Minor fixes following 1.5.0
[1.5.0] - 2025-09-15¶
Added¶
Initial OPM support
[1.4.2] - 2025-08-11¶
Changed¶
Updated AlphaFold interface to current API
[1.4.1] - 2025-08-07¶
Fixed¶
Parsing bug in
PDBRecordList
[1.4.0] - 2025-07-29¶
Added¶
PDBRecordListandPDBRecordDictclasses
[1.3.3] - 2025-07-29¶
Fixed¶
Bugs where missing records were incorrectly assumed present during mmCIF parsing
[1.3.2] - 2025-07-25¶
Added¶
filepathparameter inPDBParser()for transparent reading of local files
[1.3.1] - 2025-07-25¶
Fixed¶
Minor fixes following 1.3.0
[1.3.0] - 2025-07-16¶
Changed¶
Streamlined class attribute usage throughout
Full API documentation published
[1.2.3] - 2025-03-06¶
Fixed¶
Negative residue sequence numbers now parsed correctly
[1.2.2] - 2025-03-04¶
Fixed¶
Minor fixes following 1.2.1
[1.2.1] - 2024-10-01¶
Fixed¶
Hexadecimal serial number parsing issues (again)
[1.2.0] - 2024-09-08¶
Fixed¶
Hexadecimal serial number parsing issues
[1.1.9] - 2024-08-08¶
Fixed¶
nanvalues and*filler characters in numeric fields now handled gracefully
[1.1.8] - 2024-07-15¶
Added¶
Unstructured REMARK records (e.g. from PACKMOL output) parsed as
REMARK.-1
[1.1.6] - 2024-07-11¶
Fixed¶
Hexadecimal atom serial detection when no
a-fcharacters are present, based on value exceeding 99999
[1.1.5] - 2024-07-11¶
Fixed¶
Hex-or-integer detection now restricted to atom serial number fields only
[1.1.4] - 2024-07-11¶
Added¶
Hexadecimal atom serial number support for files with more than 99999 atoms
[1.1.3] - 2024-03-21¶
Added¶
Ability to group records into models for multi-model PDB entries
[1.1.2] - 2024-02-28¶
Added¶
Ability to fetch structures from the AlphaFold database
[1.1.1] - 2023-09-19¶
Added¶
Version detection via
importlib.metadata
[1.0.9.1] - 2023-08-28¶
Added¶
Limited mmCIF parsing:
ATOM,HETATM,SSBOND,LINK,SEQADV,REMARK 350, andREMARK 465records
[1.0.8] - 2023-08-23¶
Fixed¶
Variations in how symmetry operation matrices are represented in PDB files
[1.0.7.7] - 2023-08-22¶
Changed¶
Cleaned up logging throughout
[1.0.7.6] - 2023-08-22¶
Fixed¶
Leading whitespace in
resNamefield ofResidue10record sometimes ignored
[1.0.7.5] - 2023-08-18¶
Added¶
Support for four-letter residue names
[1.0.7.4] - 2023-08-04¶
Added¶
Logging functionality
[1.0.7.3] - 2023-08-03¶
Changed¶
Improved parsing of BIOMT transforms
[1.0.7.2] - 2023-08-03¶
Added¶
Documentation stub on ReadTheDocs
[1.0.7.1] - 2023-08-03¶
Added¶
Support for split BIOMT tables and REMARK 280, 375, 650, and 700
[1.0.7] - 2023-08-01¶
Added¶
Pretty-print support for parsed records
[1.0] - 2023-07-01¶
Added¶
Initial release