Skip to content

Release v3.15.0

Choose a tag to compare

@github-actions github-actions released this 07 Aug 19:29
· 380 commits to main since this release
  • feat: import a foreign PSF and edit it — continuation verifies its force field, psfgen edits it.
    A pre-built system (CHARMM-GUI, a prior pestifer build, another tool) now enters the pipeline through
    continuation and flows into downstream MD / membrane / packaging, and a following psfgen can edit
    it. continuation gains verify_parameters (default true): it parses the incoming PSF once to
    report a per-segid composition inventory, warn on residues unknown to the segtype table, and
    hard-error up front if the build's CHARMM release cannot resolve every atom type and
    bond/angle/dihedral/improper term — turning a cryptic mid-NAMD DIDN'T FIND vdW PARAMETER abort into an
    actionable message (new NAMD-free, unit-tested charmmff/psf_param_check.py; internal continuations opt
    out to keep the zero-parse fast path). psfgen infers its mode from the pipeline (the task contract
    is now pipeline-aware): after a fetched source it builds as before; after a STATE with no source it
    edits the incoming topology. Additive edits are layered by readpsf-preserve (topology kept
    verbatim): patches, ssbonds, irotations/crotations, links (glycan-linkage patch resolved from
    geometry), and additive grafts (extend a glycan at a terminal residue). Re-segmenting edits —
    mutations/deletions/insertions — route to a full rebuild that reconstructs the molecule from
    the PSF+coords and re-segments (re-deriving standard links/ssbonds, carrying the box forward), guarded
    by an up-front check that every residue has a CHARMM RESI. Design: docs/design/incoming-psf.md.

  • feat: per-leaflet phase (Lo/Ld) as a build-time input for raft membranes. A cholesterol-rich
    saturated leaflet undergoes a liquid-ordered (Lo) transition that membrane_equilibrate can't converge
    (a phase change, not equilibration); since MD can't cross Ld↔Lo on build timescales, the phase is now
    declared up front and packed with the matching conformer ensemble. New schema
    composition.upper/lower_leaflet_phase (Ld default = prior behavior, or Lo) routes the packer's
    conformer lookup through a per-species conf_key. Lo ordering is a tunable trans-bias in the
    athermal-MC generator — a torsional Metropolis term auto-tuned to a chain-order (Scd) target, with
    bias=0 reproducing the fluid Ld ensemble bit-for-bit — and whether a lipid actually reaches Lo is
    decided by measured order, not structure (so a sphingomyelin's trans double bond doesn't
    misclassify it). 47 curated <resname>__Lo conformer ensembles ship in the lipid repository. Validated
    on ex17's asymmetric HIV-MPER bilayer (saturated raft leaflet calibrates dense ~APL 46.8, unsaturated
    leaflet stays fluid ~56). See docs/design/lipid-conformer-generation.md.

  • change: membrane water chambers are filled with VMD solvate instead of a cubic lattice. The grid
    packer now writes lipid-only PDBs; the water is tiled at true liquid density by a solvate step after
    the lipid psfgen, replacing the old cubic water lattice whose voids the barostat closed early —
    distorting the bilayer. Post-embed equilibration starts near density-equilibrium and converges markedly
    faster (ex16 post-embed dropped ~3h → ~1h49m), and this sidesteps the >9999-residue water resid-wrap.

  • fix: the orthohexagonal grid search now weights box aspect ratio, giving near-square quilts. The
    vacancy-first grid scoring could pick severely elongated boxes (Lx/Ly ~0.67); the score now weights
    |log(aspect)| against vacancy so the quilt comes out ~square (ex17 → 0.98).

  • fix: the membrane grid→psfgen split no longer strands atoms at the origin. The split
    (environ.tcl::write_psfgen, driven by bilayer_patch.tcl) grouped atoms into residues by VMD's
    connectivity-derived residue attribute -- so a single spurious inter-lipid distance bond (common in a
    densely packed leaflet) merged two lipids into one VMD residue, wrote their atoms into one segment
    with duplicate names, and coordpdb then left the unmatched RTF-template atoms at psfgen's default
    (0,0,0). Those origin atoms made box-sized bonds and NaN'd the downstream minimize. The split now keys
    on the PDB's own per-molecule resid (the grid packer assigns each placed molecule a unique resid), so
    the grouping never depends on perceived bonds; psfgen still builds all bonds from the RTF. Validated
    end-to-end on ex17's dense cholesterol/SOPE leaflet: origin atoms 262 (square lattice) -> 131 (hex,
    old split) -> 0, and the patch minimize now completes instead of exploding.

  • feat: membrane_equilibrate gains a constant_ratio spec (default true). The tensionless area
    stage runs useConstantRatio to lock Lx:Ly -- correct for an embedded membrane whose lateral aspect
    must stay stable. Setting constant_ratio: false lets the fully flexible cell relax x and y
    independently, which is what a calibration patch wants: on a non-square (e.g. orthohexagonal) box a
    locked skewed ratio drives the tensionless relaxation to over-condense the area along the short axis
    instead of settling (observed: the calibration APL descended past its plateau and never converged).
    With the flexible cell the calibration converges cleanly. membrane_equilibrate.py + schema.

  • change: the grid packer now lays lipids on an orthohexagonal lattice instead of a square one.
    Rows are offset by half a column pitch with the row pitch at sqrt(3)/2 of the column pitch, so every
    lipid has six equidistant neighbors at one uniform spacing (~7.5% larger nearest-neighbor gap than a
    square lattice at the same APL). This spreads the tight diagonal/jitter contacts that made VMD
    mis-perceive inter-lipid bonds on the topology-free grid PDB (after which psfgen guessed the merged
    atoms to the origin and the minimize exploded). The box dimensions now follow from the integer nx x ny
    cell grid (ny even so the offset tiles the periodic box; patch_area = n*SAPL preserved), so the box
    is no longer square. bilayer.py; test_bilayer_spec_out updated for the hex box geometry.

  • fix: Linkcell scalar cell-index encoding was wrong for non-cubic cell grids. The cy stride was
    nc[1] where a correct row-major index needs nc[0]; the two coincide only when the lateral cell
    counts are equal, so the encode/decode round-trip silently broke for any box whose nc[0] != nc[1],
    tripping assert i in searchlist in ldx_searchlist_of_ldx. This never surfaced while lateral boxes
    were square; a non-square lateral box (e.g. the orthohexagonal membrane grid) hits it immediately.
    Fixed in linkcell.py and the mirrored inline encoding in psfring._scan.

  • fix: build-output basenames now use a 3-digit chunk index ({controller:02d}-{index:02d}-{subtask:03d}).
    A chunked equilibration (membrane_equilibrate) can run well past 100 chunks; the old 2-wide field
    rendered chunk 100 as 100, which sorts lexically before 99 and corrupts the glob/restart
    ordering that keys off these names. Width is the only change (basetask.py).

  • fix: PDB-repository tarball collections no longer register phantom entries from advisory lock
    files.
    The per-entry .<resname>.lock files created by the on-demand build lock ride along inside
    the shipped collection tarballs (e.g. lipid.tgz), and PDBCollection.build_from_resources was
    treating every top-level non-directory member as a solo PDB entry — so a .PSM.lock registered a
    phantom resname .PSM, doubling the lipid collection to 438 entries (219 real + 219 phantom). The
    tarball branch now requires the .pdb extension for solo entries, matching the directory branch that
    already filtered them. Note: the PDBRepository cache is keyed by pestifer version, so an existing
    cache is rebuilt on the next version bump (or clear ~/.cache/pestifer/cacheobj-pdbrepository-*).

  • fix: minimal/truncated SSBOND and LINK records now load instead of raising. A real PDB may
    stop before its optional trailing columns — an SSBOND with no sym1/sym2/length, or one that even
    omits the serial number — and pidibble 1.9.0 hands such blank numeric columns back as an empty value
    (its EmptyField, a str equal to ''). BaseObj._validate_schema now drops an empty-string value
    bound for a field whose declared type cannot hold a string (int, float, …), so pydantic applies
    the field default (length=0.0, serial_number=0, link_distance=None) rather than failing to parse
    '' as a number. Previously these records raised a ValidationError in SSBondList.from_pdb /
    LinkList.from_pdb, aborting the build. Full records are unchanged, and String fields that
    legitimately carry '' (e.g. sym1, altloc) are untouched. Pins pidibble>=1.9.0.

  • feat: new membrane_equilibrate task — self-terminating NPgT membrane equilibration on density +
    lateral area (M1 + M2).
    The anisotropic sibling of density_equilibrate: it runs NPgT
    (useFlexibleCell + useConstantRatio, tensionless by default) in the same stability-bounded chunks
    and stops when both the box density and the membrane lateral area (A = a_x·b_y) have
    converged — density + area fully pin the anisotropic cell since V = A·c_z. Built on new NAMD-free
    primitives in util/density_convergence.py: xst_cell_areas (lateral area |a×b| from the .xst)
    and JointConvergence (track several named observables, each with its own autocorrelation-corrected
    monitor/tolerances/τ, and converge only when all are jointly stationary for n_consecutive checks).
    The chunk loop, patch-grid crash-and-retry, and shrink-rate sizing were extracted from
    density_equilibrate into a shared base ChunkedEquilibrateTask (equilibrate_base.py), of which
    both tasks are now thin subclasses — density_equilibrate's behavior is unchanged (verified by an
    end-to-end bpti1 build). Area tolerances default to the density tolerances — a fine-sampling
    (xstfreq=1) NPgT probe on a real DMPC membrane measured area's integrated autocorrelation time at
    ≈921 steps vs. the membrane density's ≈822 (same order of magnitude), so area is simply the binding
    observable rather than a different regime; optional area_* specs override per-observable — and
    lipids_per_leaflet enables area-per-lipid (APL) in the report/plot. Writes a
    two-observable .dat report and a two-panel density+area (+APL) plot. Registered and schema-validated;
    36 unit tests. Now wired into make_membrane_system's pre-embed quilt relaxation and examples
    16/17 (M3–M5)
    , with per-leaflet protein-corrected APL, a soft-mode area criterion (area_min_steps
    floor), the 100/50 NPgT barostat, and whole-box embed solvation; validated end-to-end on ex16.
    See docs/design/membrane-equilibrate.md.

  • feat: fluid-bilayer-like lipid conformers for grid packing (opt-in). The grid packer stamped one
    extended vacuum conformer onto every lipid, so gridded membranes started over-packed / gel-trapped
    (DMPC settling to APL ~50 vs. fluid ~60). Now: Lever 1 draws a conformer per lipid across the whole
    cached ensemble (and fixed a latent lipid_conformers key mismatch that had been ignoring the pin
    knob); Lever 2a adds a cylinder-confined athermal-MC conformer generator (charmmff/ athermal_mc.py — dihedral-pivot moves that preserve bonds/angles exactly, hard-sphere excluded volume,
    cylinder cross-section = cylinder_inflation × APL), wired as opt-in sampler='mc' through
    do_psfgen/do_resi/ensure_lipid_conformer (default stays 'md' pending multi-lipid validation);
    sterols are forced to a single rigid conformer. Packer hardened for the denser fluid conformers: a
    protein-free bare-membrane build is now reachable (the contract detects a meaningful embed), and a
    re-spin guard (best-of-40 + escalating jitter + ensemble redraw + loud warnings + hard-abort below a
    true-coincidence floor) prevents the VMD-bond-merge → psfgen-guess → NaN and the overlap segfault.
    Acceptance test on a pristine DMPC bilayer: old rods gel-trap at APL 50.3, MC conformers reach fluid
    APL ~67 with 0.5% area drift. See docs/design/lipid-conformer-generation.md.