Quickstart¶
Pack 100 water molecules into a 40 Å cube. This walkthrough uses the Python package — the shortest path from a loaded frame to a packed result. The same model is available as a CLI script or the Rust builder.
1. Install¶
This installs the packing engine and pulls in molcrafts-molrs for the frame
type plus PDB/XYZ I/O.
2. Load or build a template¶
A template is one copy of the molecule you want many of — its atom
positions and element symbols, in any orientation. molpack takes the template
as a molrs.core.Frame, the shared MolCrafts container for atomic data, so any
loader molrs supports will do. Read one from a Protein Data Bank (PDB) file:
Or build one in memory, with no file involved — here a water molecule with the oxygen at the origin:
import molrs
import numpy as np
frame = molrs.core.Frame({
"atoms": {
"x": np.array([0.00, 0.96, -0.24]),
"y": np.array([0.00, 0.00, 0.93]),
"z": np.zeros(3),
"element": ["O", "H", "H"],
}
})
Coordinates are in ångström (Å) throughout molpack.
3. Define the target¶
A Target is one molecule species plus the number of copies to place. Every
mobile target needs a spatial restraint:
import molrs
from molpack import Target
box = molrs.core.Cuboid([0.0, 0.0, 0.0], [40.0, 40.0, 40.0]) # a molrs region
water = (
Target(frame, count=100)
.with_name("water")
.with_restraint(box)
)
Missing restraints
Without a spatial restraint (or a global PBC box), initial placement has to invent a huge free-space region and the run can become impractical.
4. Pack¶
from molpack import GencanPack
result = (
GencanPack()
.with_tolerance(2.0)
.with_seed(42)
.run([water], max_loops=200)
)
print(result.converged, result.natoms, result.fdist, result.frest)
packed = result.frame
| Field | Meaning |
|---|---|
converged |
Both objectives fell below the packer precision threshold |
fdist |
Pair-distance (overlap) violations |
frest |
Restraint violations |
frame |
Topology-complete packed molrs.core.Frame |
GencanPack is the rigid-body engine; CbmcGrow grows chains instead. Each
engine runs once — run() consumes it, so build a new one per pack. If you
only want the frame, take result.frame.
5. Save¶
import molrs
molrs.io.write_pdb("water_box.pdb", packed)
# or: molrs.io.write_xyz("water_box.xyz", packed)