Research data management and analysis for large-scale polymer molecular-dynamics simulations, built around the study of bacterial chromosome organization under macromolecular crowding.
A single parameter sweep in a coarse-grained LAMMPS study produces tens of thousands of files. The physics of each run — chain length, confinement geometry, crowder size and count, timestep, dump frequency — is encoded in its filename, and each physical state point is repeated across independent replicates that must eventually collapse into one number with an honest error bar.
That leaves two recurring problems, and PolyPhys is built around them:
- The filesystem is the database, but nothing can query it. Filenames carry the physics, yet they are opaque strings.
- Replicates must be reduced correctly. Averaging correlated molecular-dynamics frames with a naive standard error understates the uncertainty.
Every simulation artifact sits at one of five levels of a hierarchy, and each level is a well-defined aggregation of the one before it:
segment → whole → ensemble_long → ensemble → space
a chunk a full one state replicates the whole
of a run trajectory point, verbose collapsed parameter sweep
polyphys.manage.parser decodes a filename into typed physical attributes and
derives that artifact's ancestry, so a file knows which state point and which sweep
it belongs to. Once artifacts know their lineage, polyphys.manage.organizer can
walk the hierarchy and reduce it level by level.
PolyPhys is distributed from source and archived on Zenodo; it is not on PyPI.
python -m pip install "git+https://github.com/amirhs1/poly-phys.git"For a development checkout:
git clone https://github.com/amirhs1/poly-phys.git
cd poly-phys
python -m pip install -e ".[dev]"Requires Python 3.11+. The runtime dependencies are NumPy and pandas.
Decode a simulation filename into physics, and read off where it sits in the hierarchy:
>>> from polyphys.manage.parser import SumRuleCyl
>>> artifact = SumRuleCyl(
... 'N200epsilon5.0r10.5lz25.0sig2.0nc1000dt0.005bdump2000adump5000ens1.j03',
... lineage='segment',
... group='all',
... )
>>> artifact.nmon # monomers in the chain
200
>>> artifact.ncrowd # crowder particles
1000
>>> float(artifact.dcrowd) # crowder diameter
2.0Geometry is derived, not just read. The cylindrical wall is built from particles of
size 1.0, so the usable confinement diameter is D = 2r - 1.0, and the bulk crowder
volume fraction follows from the confining volume:
>>> float(artifact.dcyl) # from 'r10.5': 2 * 10.5 - 1.0
20.0
>>> round(float(artifact.phi_bulk_c), 4)
0.3292Each artifact also knows its ancestors, so a segment can be grouped with its replicates and its sweep without touching the filesystem:
>>> artifact.lineage_genealogy
['segment', 'whole', 'ensemble_long', 'ensemble', 'space']
>>> artifact.whole
'N200epsilon5.0r20.0lz50.0sig2.0nc1000dt0.005bdump2000adump5000ens1'
>>> artifact.ensemble
'N200D20.0ac2.0nc1000'
>>> artifact.space
'N200D20.0ac2.0'polyphys.analyze.measurer provides the structural observables computed per frame:
>>> import numpy as np
>>> from polyphys.analyze import measurer
>>> positions = np.array([[0.0, 0.0, 0.0], [3.0, 4.0, 0.0], [3.0, 4.0, 12.0]])
>>> float(measurer.end_to_end(positions))
13.0
>>> float(measurer.fsd(positions, 2)) # farthest-site distance along z
12.0| Module | Purpose |
|---|---|
manage.parser |
Filename → typed physical attributes and lineage. One ParserBase subclass per project, declaring its own geometry, topology, and attribute schema. |
manage.organizer |
Walks the lineage, combining segments into wholes and reducing replicate ensembles to averaged measurements. |
manage.utils |
Filename sorting, safe IO, and number-density / volume-fraction conversions for cubic and cylindrical geometries. |
manage.types |
Domain type aliases (LineageT, GeometryT, PhaseT, …) that keep the vocabulary explicit and checkable. |
analyze.measurer |
Per-frame structural observables — end-to-end distance, farthest-site distance, transverse size, maximum extent — plus fixed-size binning and radial, axial, azimuthal, and planar histograms. |
Eight parser subclasses ship with the package, covering cylindrical and cubic confinement with linear, ring, and bidisperse chain topologies.
PolyPhys is under active development toward a stable 1.0 API. It is used to produce published research results, and the parsing and measurement layers are covered by tests that run against Python 3.11, 3.12, and 3.13 on every push.
The examples above are executed as part of the test suite, so anything shown in this README is guaranteed to run against the current code.
Current focus, in order:
- Broaden test coverage and executable examples for
manage.organizer, including autocorrelation-aware error estimation for correlated MD frames. - Expand
analyzewith the polymer- and crowding-specific observables that general MD toolkits do not provide. - Reduce the per-project coupling in the
managelayer so a new study can use PolyPhys from outside the package rather than extend it.
If you use PolyPhys in published work, please cite the archived release. The DOI
above resolves to the latest version; see CITATION.cff for
machine-readable metadata, or use GitHub's Cite this repository button.
Bug reports and questions are welcome via
issues. Please see
SECURITY.md for reporting suspected vulnerabilities privately.
MIT — see LICENSE.