Changelog¶
0.5.1 - 2026-07-01¶
Requires molcrafts-molrs == 0.5.1 (molpy and molrs now share one version).
Added¶
- TRAVIS-parity compute operators in
molpy.compute: angular/dihedral/ distance and combined distribution functions, the spatial distribution function, the Van Hove correlationG(r, t), Legendre reorientational correlations, hydrogen-bond detection, radical Voronoi tessellation with domain/void/charge analysis, and vibrational spectra (VDOS, IR, Raman, VCD, ROA, resonance Raman). molpy.version.check_molrs_version()— run onimport molpy, warns when the installedmolcrafts-molrsdoes not match.
Changed¶
- Documentation now builds with Zensical; user-guide notebooks are pre-rendered to Markdown. The compute section documents every operator with textbook-style guides and a full API reference.
0.4.1 - 2026-06-14¶
Maintenance release on top of 0.4.0. Requires molcrafts-molrs == 0.1.2.
Removed¶
molpy.legacyis gone. The pure-NumPyMSD/DisplacementCorrelationoperators (and themolpy.legacysubmodule) were removed. Use the molrs-backed trunk inmolpy.computeinstead —molpy.compute.MSDandmolpy.compute.MCDCompute.
Fixed¶
- AMBER prmtop reader. Atom-connectivity index columns
(
atomi/atomj/atomk/atoml/idon bonds/angles/dihedrals and the atomid) are now emitted as unsigneduint32to match molrs'sUIntindex columns (get_uint); mask/sentinel columns that use-1stay signed.
Internal¶
- Pinned
molcrafts-molrs == 0.1.2(was0.1.1); kept the CI install comment in sync. - Collapsed the three near-identical PDB-writer required-field tests into a single parametrized test.
0.4.0 - 2026-06-11¶
This release lands the molrs Rust backend as the foundation of Frame /
Block / Box / compute, and a five-stage builder/reacter overhaul
(dead-code consolidation, fix bond/react serialization moved into the io layer,
REACTER template scientific-correctness fixes, a consolidated public API with
executable docs, and a behavior-preserving build-loop performance pass).
A follow-up consolidation wave completes the molrs sink: topology perception,
trajectory storage, the force-field/potential model, and box/region geometry
now all execute in the Rust backend, a fail-fast sweep removes every known
silent-failure path, and a new CL&P ionic-liquid force field plus the
foundations of the CL&Pol polarizable stack land in the typifier/builder
layer.
Requires molcrafts-molrs == 0.1.0.
Builder / Reacter¶
BondReactTemplate.write()/write_map()were removed.BondReactTemplateis now a pure data object; all fix bond/react serialization lives in the io layer. Write a complete reactive system (data + ff + templates, with type IDs unified across all files) withmp.io.write_lammps_bond_react_system(workdir, frame, ff, templates=...); write just the.mapfile withmp.io.write_bond_react_map(template, stem). The single-templatewrite()path produced template-local type IDs that were inconsistent with the system data file and has no replacement.- Importing a molpy subpackage no longer eagerly loads the rest.
Top-level submodules (
molpy.io,molpy.engine,molpy.adapter, …) are now lazy (PEP 562):import molpy.reacterinitializes onlycore(andpotential).mp.io.…attribute access andimport molpy.iobehave as before.molpy.builder/reacter/pack/computeare reachable as lazy top-level attributes (mp.builder.…). - Builder/reacter terminology and API consolidation.
polymer()/polymer_system()are the documented one-call entry points;PolymerBuilder+Connectorremain the step-by-step API. Agent-only Tool classes moved tomolpy.builder.polymer.tools(out of the user__all__);ReactionPresets/ReactionPresetSpecare now public extension points.ReactionPresetSpec.site_selector_*→anchor_selector_*;molpy.reacter.find_port_atom→find_port. No deprecation shims (experimental stage); see the repo-rootCHANGELOG.md. - REACTER template correctness.
BondReactReacterpost templates now carry impropers (sp2 planarity terms survivefix bond/react),InitiatorIDsare deterministic and validated (exactly 2, never on the template boundary), edge atoms are checked for identical pre/post type and charge, total charge is checked for conservation (CHARGE_CONSERVATION_TOL = 1e-6e), andrun()no longer mutates caller-ownedleft/rightstructures. - molrs is now a required dependency.
molcrafts-molrsmoved from an optional extra into the coredependencies. Themolpy[molrs]extra key was removed — installing molpy always installs molrs.Frame,Block, andBoxare backed by (and inherit from) molrs types, and thecomputeoperators forward directly into the Rust kernel. There is no pure-Python fallback. - The RDKit-backed compute node was removed.
molpy.compute.rdkit(Generate3D/OptimizeGeometryoverRDKitAdapter) is gone.molpy.compute.Generate3Dis now the molrs-backed trunk operator, taking anAtomisticgraph and returning a fresh 3D structure. The RDKit adapter (molpy.adapter.rdkit) is retained as an optional external backend;rdkitremains an optional extra, not a required dependency. Frame/Blockare the canonical molrs types, not molpy subclasses.molpy.core.frame.Frame is molrs.FrameandBlock is molrs.Block(thin re-exports). The Python-side object-column overflow (_objects) is gone: columns are numpy-only (float / int / bool / str). Assigning an object /None/ ragged column now raisesmolrs.BlockDtypeErrorat write time instead of being silently stored on the Python side.frame.boxreturns amolrs.Box(carryingis_free/style/volume()); molpy's richer box geometry stays available asmolpy.Box, upgradable viaBox.from_box(frame.box).
Typifiers & Force Fields¶
- One public typifier class per force field. The dual atom-only/atomistic
hierarchy collapsed into a single full-pipeline class per force field:
OplsTypifierandGaffTypifier(atom → pair → bond → angle → dihedral). The orchestrator base was renamedForceFieldAtomisticTypifier→ForceFieldTypifier; per-FF atom typifiers are now private (_OplsAtomTypifier/_GaffAtomTypifier); theOpls{Bond,Angle,Dihedral}Typifierclasses and theGaffTypifier = GaffAtomisticTypifieralias were removed. Behavior is unchanged. - New CL&P ionic-liquid force field.
ClpTypifier(OplsTypifier)types ionic liquids through the full pipeline from a new built-inclp.xml(imidazolium cation + BF4 / PF6 / NTf2 / dca anions), generated from the authoritative paduagroup CL&Pil.ffwith exact charges/LJ and hand-authored SMARTS for ring-position discrimination (CR/CW/NA). It is read through the existing OPLS reader;oplsaa.xmlis untouched.[C4C1im]+sums to +1, each anion to −1. - CL&Pol polarizable-force-field foundations.
VirtualSite/DrudeParticle/MasslessSiteare new data-onlyAtomsubclasses carrying a persistentvsitemarker (identity lives in the field, so it survives the molrs store;Atom.is_virtualreads it). TheVirtualSiteBuilderABC (copy → select → build sites → redistribute, no input mutation) ships withDrudeBuilder(the CL&Pol polarizer, driven by the bundledalpha.ffpolarizability data) andTip4pBuilder(rigid M-site). - CL&Pol scaleLJ SAPT epsilon scaling.
molpy.core.ops.scale_ljscales cross-fragment LJ epsilon by the SAPT-derived factor k_ij (matching paduagroup/clandpol scaleLJ), deep-copying theForceFieldand touching only inter-fragment pair epsilon — sigma and charges are unchanged. Fragment data ships asclpol_fragments.ff;FragmentScaling,compute_k_ij, andload_fragment_scaling_dataare public. - Interim pure-Python Thole and Tang–Toennies damping evaluators were
developed and validated against paduagroup/clandpol and LAMMPS
pair_thole/pair_coul_ttduring this cycle, but were superseded by the force-field collapse onto molrs before release — they are not part of the 0.4.0 surface and will return as molrs-native kernels.
molrs Consolidation¶
- The force-field model now lives entirely in molrs;
molpy.potentialis a facade.molpy.core.forcefieldis a thin re-export of the native molrsForceField/ Style / Type hierarchy (plus theAtomisticForcefieldalias and named specialized Style classes). The parallel Python kernels and energy math underpotential/were deleted;molpy.potential[.bond|.angle|…]re-exports the molrs-backed Style classes andPotentialsso users never import molrs. Energy/forces are evaluated viaff.to_potentials(frame).calc_energy(frame)/.calc_forces(frame);optimize.ForceFieldPotentialwraps this (the per-kernelpotential_wrappersare gone). I/O formatters now dispatch by style/kernel name (no per-kernelTypeclasses), anddef_typeparameters are keyword-only. - Topology perception runs on the molrs graph kernel; the parallel igraph
engine is deleted.
get_topoangle/dihedral perception delegates tomolrs.Atomistic.generate_topology;get_topo_neighbors/get_topo_distancesandextract_subgraphuse the molrs BFS (topo_distances) and adjacency kernels.core/topology.pyand the publicmolpy.Topology/molpy.core.Topologyexports were removed —get_toponow always returns anAtomistic(no flags = plain copy), fixing a latent bug where the no-flags path could leak a raw graph object. igraph remains only inside the SMARTS typifier. Relation enumeration uses the authoritative molrsrelation_ids()— the Python-side_rel_handlesshadow and its handle-range probing heuristic are gone. Trajectoryis now amolrs.Trajectorysubclass. The eager container, lazy reading, and LAMMPS/XYZ trajectory parsing all live in molrs (read_lammps_trajectory/read_xyz_trajectory); molpy's duplicate readers and the mmap-index infrastructure were deleted. molpy keeps the split extensions (SplitStrategy/TrajectorySplitter), topology/slice/map conveniences, the XYZ writer, and the HDF5 path.TimeIntervalStrategyreads the native.timearray (Pythonframe.metadatadoes not round-trip the molrs store).Computeis a plain class.__init__takes configuration,__call__takes inputs,dump()persists. The single-input_computehook, the molexpexecute()/input_key/output_keyshim, and theCompute[InT, OutT]generic were removed, along with 17 dead_computestubs across the molrs-backed operator wrappers.- Box and region geometry delegate to the Rust kernels.
Box.make_fractional/make_absolute/isinforward to the inherited molrsto_frac/to_cart/isin;volume, lengths/tilts, wrapping, and minimum-image differences use the molrs properties andBox.wrap/Box.delta.SphereRegionandBoxRegion/Cubepoint-membership tests run onmolrs.Sphere.contains/molrs.Cuboid.contains— molpy keeps only the boolean-algebra /MaskPredicatelayer. The Python-side_is_freeflag is gone: free-box state derives from molrscell_defined, so a non-periodic bounding box (from_bounds) now correctly reports a real cell with volume/lengths.Atomistic.scaleandalignusemolrs.scale/molrs.rotate(the per-atom Rodrigues loop is gone). Ortho + triclinic parity with the previous NumPy paths was verified before each sink. - Canonical field registry comes from
molrs.fields.molpy.core.fieldsno longer defines a parallelFieldSpec/FieldFormatterset — it re-exports the single canonical registry (molpy.core.fields.CHARGEismolrs.fields.CHARGE), keeping only the FF-specificForceFieldFormatteron top. This resolves the drifted triple-duplicated registry.
Fail-Fast¶
- Selectors raise on missing columns.
AtomIndexSelector/ElementSelector/CoordinateRangeSelector/DistanceSelectornow raiseKeyErrornaming the missing column instead of silently matching zero atoms on a typo'd field. ForceField.to_potentials()no longer silently drops styles. Legitimately-empty styles (no types) are skipped explicitly; any real failure (unknown kernel, a type missing required params) propagates.- Typifier inputs are validated. A SMARTS pattern that fails to parse now
raises instead of being warned and dropped (which silently un-typed that atom
type); an invalid element symbol or atomic number raises
ValueErrorinstead of degrading to a match-anything wildcard (*stays reserved for the explicit no-element/no-number case). - The LAMMPS data reader keeps force-field coefficients.
Pair/Bond/Angle/Dihedral/Improper Coeffs sections are now stored on the
metadata
ForceField(positionally-keyed, style-arity aware) so read → write round-trips them; previously they were parsed and discarded. Malformed (non-numeric) coeff lines raiseValueErrorinstead of being swallowed. - The dead
molpy.oppackage (unused geometry helpers) was deleted.
Added¶
molpy.compute.NeighborList— linked-cell neighbor search (molrs backend).molpy.compute.RDF— radial distribution function over one or more frames.molpy.Boxinheritsmolrs.Box, so a molpy box is accepted by any molrs API with no conversion.- molrs analyses exposed as molpy operators:
MSD,Cluster,ClusterCenters,CenterOfMass,GyrationTensor,InertiaTensor,RadiusOfGyration,Pca,KMeans. molpy.typifier.ClpTypifier+ built-inclp.xml— CL&P ionic-liquid force field (imidazolium + BF4/PF6/NTf2/dca) on top of the OPLS pipeline.VirtualSite/DrudeParticle/MasslessSiteatoms,Atom.is_virtual, andVirtualSiteBuilder/DrudeBuilder/Tip4pBuilder(CL&Pol Drude polarizer + TIP4P M-site), with bundledalpha.ffpolarizability data.molpy.core.ops.scale_lj(+FragmentScaling,compute_k_ij,load_fragment_scaling_data,clpol_fragments.ff) — CL&Pol SAPT cross-fragment LJ epsilon scaling.UnitSystem.register_preset(name, base_units, *, overwrite=False)— register custom LAMMPS-style unit presets usable viapreset(); the preset table is no longer a closed dict.
Changed¶
compute.mcdandcompute.pmsdnow compute minimum-image displacements via molrsBox.delta(minimum_image=True); public signatures are unchanged.
Migration¶
- Replace
pip install "molcrafts-molpy[molrs]"withpip install molcrafts-molpy. - If you imported
from molpy.compute.rdkit import Generate3D, switch tofrom molpy.compute import Generate3D(molrs-backed,Atomistic -> Atomistic) or, for the RDKit adapter flow,from molpy.adapter import Generate3D. - Build
Blockcolumns from numpy-representable data: replacenp.array([...], dtype=object)string columns with nativenp.array([...])(numpy infers aUdtype). Sparse per-entity attributes can no longer beNone-filled into a column — use a typed default or omit the column.Atomistic.to_frame()/CoarseGrain.to_frame()now drop columns that cannot be numpy-represented (e.g. a CG bead's raggedatomsmapping) rather than emitting object arrays. molpy.Topology/molpy.core.Topologyno longer exist;get_topo()always returns anAtomistic. For k-hop graph queries useget_topo_neighbors/get_topo_distances(molrs BFS backed).- Typifiers: replace
OplsAtomTypifier/GaffAtomTypifier/Opls{Bond,Angle,Dihedral}Typifier/GaffAtomisticTypifierwithOplsTypifier/GaffTypifier; a custom orchestrator should subclassForceFieldTypifier(renamed fromForceFieldAtomisticTypifier). - Potentials: the Python kernel classes under
molpy.potentialare gone — import the molrs-backed Style classes from the same paths and evaluate viaff.to_potentials(frame).calc_energy(frame). Parameter names follow molrs (k, notk0); look up styles withff.get_style(category, name);def_typeparameters are keyword-only. Computesubclasses: configuration goes to__init__, data to__call__. Theexecute()/input_key/output_keymolexp shim and the_computehook were removed.- Code that relied on selectors returning an empty mask for a missing column,
on unparseable SMARTS being skipped, or on
to_potentials()ignoring broken styles must now handle the raisedKeyError/ValueError(or fix the input — these were silent-failure bugs).
See the molrs backend developer guide for details.