Skip to content

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

pip install molcrafts-molpack

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:

import molrs

frame = molrs.io.read_pdb("water.pdb")

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)

Where next