Repository navigation
Release v3.15.0
-
feat: import a foreign PSF and edit it —
continuationverifies its force field,psfgenedits it.
A pre-built system (CHARMM-GUI, a prior pestifer build, another tool) now enters the pipeline through
continuationand flows into downstream MD / membrane / packaging, and a followingpsfgencan edit
it.continuationgainsverify_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-NAMDDIDN'T FIND vdW PARAMETERabort into an
actionable message (new NAMD-free, unit-testedcharmmff/psf_param_check.py; internal continuations opt
out to keep the zero-parse fast path).psfgeninfers 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 additivegrafts(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 thatmembrane_equilibratecan'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(Lddefault = prior behavior, orLo) routes the packer's
conformer lookup through a per-speciesconf_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=0reproducing 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>__Loconformer 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). Seedocs/design/lipid-conformer-generation.md. -
change: membrane water chambers are filled with VMD
solvateinstead of a cubic lattice. The grid
packer now writes lipid-only PDBs; the water is tiled at true liquid density by asolvatestep 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 bybilayer_patch.tcl) grouped atoms into residues by VMD's
connectivity-derivedresidueattribute -- so a single spurious inter-lipid distance bond (common in a
densely packed leaflet) merged two lipids into one VMDresidue, wrote their atoms into one segment
with duplicate names, andcoordpdbthen 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-moleculeresid(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_equilibrategains aconstant_ratiospec (defaulttrue). The tensionless area
stage runsuseConstantRatioto lockLx:Ly-- correct for an embedded membrane whose lateral aspect
must stay stable. Settingconstant_ratio: falselets 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 atsqrt(3)/2of 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 (nyeven so the offset tiles the periodic box;patch_area = n*SAPLpreserved), so the box
is no longer square.bilayer.py;test_bilayer_spec_outupdated for the hex box geometry. -
fix:
Linkcellscalar cell-index encoding was wrong for non-cubic cell grids. Thecystride was
nc[1]where a correct row-major index needsnc[0]; the two coincide only when the lateral cell
counts are equal, so the encode/decode round-trip silently broke for any box whosenc[0] != nc[1],
trippingassert i in searchlistinldx_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 inlinkcell.pyand the mirrored inline encoding inpsfring._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 as100, which sorts lexically before99and 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>.lockfiles created by the on-demand build lock ride along inside
the shipped collection tarballs (e.g.lipid.tgz), andPDBCollection.build_from_resourceswas
treating every top-level non-directory member as a solo PDB entry — so a.PSM.lockregistered a
phantom resname.PSM, doubling the lipid collection to 438 entries (219 real + 219 phantom). The
tarball branch now requires the.pdbextension for solo entries, matching the directory branch that
already filtered them. Note: thePDBRepositorycache 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
SSBONDandLINKrecords now load instead of raising. A real PDB may
stop before its optional trailing columns — anSSBONDwith nosym1/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
(itsEmptyField, astrequal to'').BaseObj._validate_schemanow 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 aValidationErrorinSSBondList.from_pdb/
LinkList.from_pdb, aborting the build. Full records are unchanged, andStringfields that
legitimately carry''(e.g.sym1,altloc) are untouched. Pinspidibble>=1.9.0. -
feat: new
membrane_equilibratetask — self-terminating NPgT membrane equilibration on density +
lateral area (M1 + M2). The anisotropic sibling ofdensity_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 sinceV = A·c_z. Built on new NAMD-free
primitives inutil/density_convergence.py:xst_cell_areas(lateral area|a×b|from the.xst)
andJointConvergence(track several named observables, each with its own autocorrelation-corrected
monitor/tolerances/τ, and converge only when all are jointly stationary forn_consecutivechecks).
The chunk loop, patch-grid crash-and-retry, and shrink-rate sizing were extracted from
density_equilibrateinto a shared baseChunkedEquilibrateTask(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; optionalarea_*specs override per-observable — and
lipids_per_leafletenables area-per-lipid (APL) in the report/plot. Writes a
two-observable.datreport and a two-panel density+area (+APL) plot. Registered and schema-validated;
36 unit tests. Now wired intomake_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.
Seedocs/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 latentlipid_conformerskey 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-insampler='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. Seedocs/design/lipid-conformer-generation.md.