You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
new feature: pestifer make-ligand-mol2 subcommand that, given a 4-letter RCSB PDB code or a path to a local .pdb file, generates a CGenFF-ready Tripos mol2 file for every HETATM ligand whose resname is not already defined in the loaded CHARMM topologies; for each unknown ligand it fetches the SMILES from the RCSB Chemical Component Dictionary (preferring the OpenEye canonical-stereo descriptor), builds an RDKit Mol whose heavy atoms are in PDB order and carry the original PDB atom names, protonates at the target pH (default 7.4) via Dimorphite-DL, places explicit Hs in 3D, and writes the mol2 via Open Babel with --title <RESNAME> so the CGenFF binary/web tool registers the resulting RESI under the correct residue name (rather than the leaked tempfile path); per-ligand failures are surfaced in a summary table without aborting the run, and --smiles RESNAME=... overrides the RCSB lookup when a custom tautomer or charge state is needed
new feature: new pestifer.charmmff.ligand_paramgen subpackage exposes the building blocks reused by make-ligand-mol2 as a library: fetch_ligand_smiles(comp_id) (RCSB lookup with LRU caching and HTTP-error → RCSBLookupError mapping), protonate_ligand(residue, smiles, ph) (RDKit + Dimorphite-DL pipeline that preserves PDB heavy-atom order and stamps each heavy atom with the original PDB name on the _pdb_name property), write_mol2(mol, resname, outpath) (PDB-block-via-obabel writer that propagates _pdb_name and assigns sequential H1, H2, ... names to hydrogens), and generate_ligand_mol2s(parsed, charmmff_content, outdir, ph, smiles_overrides) (the orchestrator the subcommand calls, which the build workflow will also call for unknown ligands)
new feature: well-known per-user toppar cache at ~/.pestifer/toppar/; when this directory exists, pestifer automatically prepends it to charmmff.user_custom.searchpath so .str files dropped there are picked up by every build without requiring a user_custom block in YAML; any project-local searchpath entry is loaded after the cache and overrides it (last-loaded wins) with a warning naming both files; designed as the default destination for .str files produced by running make-ligand-mol2 output through the CGenFF binary or web tool
enhancement: charmmff.user_custom.searchpath entries now expand ~/ (the user's home directory) and shell environment-variable references like $HOME/foo or ${SCRATCH}/charmm before the directory check; previously those were taken literally and silently failed
behavior change: CHARMMFFContent.add_custom_directory no longer asserts on duplicate-basename clashes between searchpath entries; instead, the later-loaded file wins and a warning is emitted naming both paths (the assertion previously crashed pestifer when, e.g., the user's project happened to contain a .str file with the same basename as one in the cache); same-resname clashes across differently-named files in the searchpath also emit a warning and follow last-loaded-wins semantics, so a project-local override of a cached parameterization is surfaced without silently merging
new optional dep: [project.optional-dependencies] table in pyproject.toml declares an ligand-paramgen extra (pip install 'pestifer[ligand-paramgen]') that pulls in rdkit and dimorphite_dl; the obabel binary remains a runtime-PATH dependency, documented alongside the new subcommand
test: tests/unit/test_charmmff/test_charmmffcontent.py::TestCharmmffContent.setUpClass was picking the CHARMMFF version directory by mtime rather than by parsed month-year (the production ResourceManager.charmmff_version_dirs() orders semantically); when the feb26 and jul24 directories were extracted out of release order, mtime selected jul24 and the test's hard-coded counts (calibrated against feb26) failed by ~1400 residues; setUpClass now delegates to ResourceManager.charmmff_version_dirs() so the test always exercises the same CHARMMFF release that production code uses
test: new tests/unit/test_charmmff/ligand_paramgen/ package covers the ligand-paramgen building blocks (29 tests): protonation invariants on five SMILES across a pH=7.4 charge range, RCSB descriptor-priority selection under unittest.mock of requests.get, mol2 title/atom-name round-trip via the real obabel binary, and orchestrator-level altloc dedup and known-resname filtering using real Hetatm objects; test_charmmffcontent.py gains three TestAddCustomDirectory cases (tilde expansion, duplicate-basename warning + last-wins, duplicate-RESI warning + last-wins) that build a stub CHARMMFFContent via __new__ to avoid paying the full tarball-load cost
doc: new docs/source/subs/make-ligand-mol2.rst covers the subcommand with examples (PDB code, local file, SMILES override, pH override) and outlines the CGenFF round-trip workflow (web tool → ~/.pestifer/toppar/); linked from the subcommand toctree in usage.rst; the charmmff.user_custom schema docstring gains "Per-user toppar cache" and tilde-expansion sections