Skip to content

Getting Started

A minimal end-to-end pack: 100 water molecules inside a 40 Å cube.

1. Load a molecule

Use molrs.read_pdb to load a template PDB file — the returned Frame can be passed directly to Target:

import molrs

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

No PDB file? Build a molrs.Frame from arrays with Frame.from_dict:

import molrs
import numpy as np

frame = molrs.Frame.from_dict({
    "blocks": {
        "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"],
        }
    }
})

2. Create a Target

A Target bundles a molecule template with the number of copies to pack. VdW radii are looked up automatically from element symbols (Bondi 1964).

from molpack import Target

water = Target(frame, count=100).with_name("water")

Arguments:

  • frame — a molrs.Frame or molpy.Frame with columns "x", "y", "z", and "element" (or "symbol" for molrs PDB frames).
  • count — number of copies to produce.

A display label is optional — attach one via .with_name("...").

All builder methods are immutable — they return a new Target.

3. Attach a restraint

Every target needs at least one restraint — the geometric region it should be packed into.

from molpack import InsideBoxRestraint

water = water.with_restraint(
    InsideBoxRestraint([0.0, 0.0, 0.0], [40.0, 40.0, 40.0])
)

Five geometric built-in restraints: InsideBoxRestraint, InsideSphereRestraint, OutsideSphereRestraint, AbovePlaneRestraint, BelowPlaneRestraint — plus a family of collective distribution-matching restraints. Stack multiple restraints with repeated .with_restraint() calls — see Restraints.

4. Pack

from molpack import Molpack

packer = Molpack().with_tolerance(2.0).with_seed(42)
frame = packer.pack([water], max_loops=200)

print(frame["atoms"].nrows)

pack() returns a ready-to-use molrs.Frame. If you need structured diagnostics, call pack_with_report() instead; it returns a PackResult with .converged, .fdist, .frest, .positions, and .frame.

5. Save

molpack does not write files directly — Frame is the canonical output. Hand the returned frame to a writer:

import molrs

molrs.write_xyz("packed.xyz", frame)

Or use pack_with_report() and write result.frame if you also need the diagnostic fields.

Full script

import molrs
from molpack import InsideBoxRestraint, Molpack, Target

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

water = (
    Target(frame, count=100)
    .with_name("water")
    .with_restraint(InsideBoxRestraint([0.0, 0.0, 0.0], [40.0, 40.0, 40.0]))
)

frame = (
    Molpack().with_tolerance(2.0).with_seed(42).pack([water], max_loops=200)
)

print(f"packed {frame['atoms'].nrows} atoms")

Next steps

  • Targets — orientation, centering, fixed placement.
  • Restraints — per-atom scoping, stacking.
  • Packer — all builder options.
  • Examples — five complete Packmol workloads.