Skip to content

Core

Foundational data structures for molecular systems. All available via import molpy as mp. mp.core mirrors molrs's core, molrs.core, by identity, in one module (mp.core.Cuboid is molrs.core.Cuboid). The data classes you handle directly are promoted to the root as the same objects (mp.Frame is mp.core.Frame is molrs.core.Frame, mp.Box, mp.Atomistic, …); everything else is mp.core.<Name>. molpy's additions here are the column selectors and the trajectory splitters, both in mp.core beside the Block and Trajectory they act on. Perception (SmartsPattern, perceive_rings, add_hydrogens, …) is mp.perceive.

Quick reference

Symbol Summary Preferred for Avoid when
Atomistic Editable molecular graph (atoms + bonds) Building, editing, reacting on chemistry Array-backed analysis or export
Block Columnar table: column names → NumPy arrays Tabular data, vectorized computation Graph-level chemical editing
Frame Named Blocks + box + dict-like meta System snapshots, file I/O Editing individual atoms
Box Periodic simulation cell (3×3 matrix + PBC) Wrapping, minimum-image distances Non-periodic systems
Trajectory Ordered in-memory sequence of Frames with step / time labels (slicing, map); lazy readers are mp.io.read_*_trajectory Time-series analysis Single-snapshot work
CoarseGrain CG molecular graph (beads + CG bonds) Coarse-grained modelling; mirrors Atomistic All-atom work (use Atomistic)
mp.ff.forcefield.ForceField Force field container (styles → types → potentials) Defining parameters before execution Direct numerical computation
NodeRef / RelationRef / Refs Live handles onto graph nodes / relations and collections of them (an Atom is a node view, a Bond a relation view) Code generic over node / relation kinds Everyday atom / bond editing
Cuboid / Sphere / HalfSpace / … / Region Geometric regions (mask(block), region(block), & / \| / ~ into a Region) Spatial selection, packing constraints Non-geometric masks (use a Selector)
UnitRegistry / UnitPreset Unit registry (with k_B and reduced LJ units) and named presets (real, metal, openmm, …) Unit conversions and custom presets Unit-agnostic array math

Canonical examples

import numpy as np
import molpy as mp

# Atomistic: editable molecular graph (core APIs mutate in place)
mol = mp.Atomistic(name="water")
o = mol.add_atom(atomic_number=8, x=0.0, y=0.0, z=0.0)
h = mol.add_atom(atomic_number=1, x=0.957, y=0.0, z=0.0)
mol.add_bond(o, h)
mol.generate_topology(gen_angle=True) # writes angles on mol; returns counts added
# bulk reads: mol.atoms["x"] / mol.xyz — no full view materialization

# Block + Frame: tabular snapshot. `meta` is a dict of Python scalars.
frame = mp.Frame(
 blocks={"atoms": {"element": ["O", "H"], "x": [0.0, 0.957]}},
 meta={"timestep": 0},
)

# Box: periodic cell
box = mp.Box(mp.core.Cell.lengths([20.0] * 3))
wrapped = box.wrap(np.array([[21.0, 0.0, 0.0]]))
d = box.distances(np.array([[0.0, 0.0, 0.0]]), np.array([[19.5, 0.0, 0.0]])) # minimum-image distance

# ForceField: parameter data
ff = mp.ff.forcefield.ForceField(name="demo", units="real")
style = ff.def_style("atom", "full")
ct = style.def_type("CT", mass=12.011) # returns the AtomType handle
cc = ff.def_style("bond", "harmonic").def_type("CT-CT", ct, ct, k=536.0, r0=1.529)

Full API

Atomistic

Atomistic

All-atom molecular graph.

Atomistic(**props) — the keywords are :attr:props. Every atom, bond, angle, dihedral, improper, port and term is a live view (an :class:Atom, a :class:Bond, …); a view's mapping is the one door to its fields (atom["x"] = 1.0, del bond["k"]). Every atom carries a valid atomic_number (0..=118, 0 = wildcard): an add, a write or an unpickle that would break that raises. Copy with copy.copy / copy.deepcopy (handles preserved). Subclassable.

props property

props

Whole-graph annotations; carried by copies, pickles and every graph derived from this one.

add_bond

add_bond(a, b, /, **props)

Add a bond; with no bond_type in props it is a single bond.

add_port

add_port(anchor, handle_atom, /, kind, label='', order=1)

Record a descriptor ("$", "<", ">", "!") on the (anchor, handle_atom) valence.

Raises

ValueError an endpoint of another graph, an unknown glyph, handle_atom not bonded to anchor, an indefinite order, or a valence that already carries a port.

add_term

add_term(block, atoms, /, **props)

Add a row to the term block block (cmaps, exclusions, …) over atoms; a block with typed methods is refused.

center

center(nodes)

Mass-weighted centre (Å) of nodes, a float64 (3,) array.

declare_term

declare_term(block, arity)

Declare a term block the Frame schema does not define.

del_atom

del_atom(atom)

Delete atom and every relation touching it.

del_atoms

del_atoms(atoms)

Delete every atom of atoms and every relation touching one; atomic.

del_terms

del_terms(terms)

Delete terms of ONE block; atomic.

link(a, b)

Join port a to port b: delete both leaving groups, fold their charge (e) onto the anchors, bond the anchors with the port order; returns the new bond. The graph is unchanged on a refusal (ValueError).

merge

merge(other)

Merge other in (emptying it); returns its atoms, now here.

replicate

replicate(template, rotations, translations, frag_ids)

Grow this graph by one rigid copy of template per transform; returns the new atoms, copy-major. Atomic.

set_bond_class

set_bond_class(bond, bond_type, bond_number)

Set a bond's chemical class and its localized bond number together — the one door that writes bond_type / bond_number.

Box

Box

Simulation box with periodic boundary conditions: it holds a :class:Cell, an origin and per-axis periodicity.

approx_eq

approx_eq(other, tol)

Same cell within absolute tol: every matrix entry and origin component within tol, identical pbc and is_cell_defined.

bounding staticmethod

bounding(points, padding, pbc)

The orthorhombic box enclosing points (N, 3), grown by padding[d] >= 0 on each side of axis d. Raises ValueError for no points, a negative padding or an axis of zero extent.

cube staticmethod

cube(a, origin=..., pbc=...)

A cubic box of edge a (Å). Raises ValueError for a non-positive or non-finite a.

delta

delta(xyzu1, xyzu2, minimum_image=False)

Displacement xyzu2 - xyzu1.

Both arguments must be shape (N, 3) (returns (N, 3)) or both shape (3,) (returns (3,)). Mixed ranks raise ValueError. minimum_image defaults to False.

from_lengths_angles staticmethod

from_lengths_angles(lengths, angles, origin=..., pbc=...)

A restricted-triclinic box from [a, b, c] (Å) and [alpha, beta, gamma] (degrees). Raises ValueError for angles that describe no cell.

from_lengths_tilts staticmethod

from_lengths_tilts(lengths, tilts, origin=..., pbc=...)

A restricted-triclinic box from [lx, ly, lz] and tilts [xy, xz, yz] (Å), the LAMMPS form.

ortho staticmethod

ortho(lengths, origin=..., pbc=...)

An orthorhombic box with edge lengths [a, b, c] (Å). Raises ValueError for a non-positive or non-finite length.

wrap

wrap(xyz)

(wrapped, shifts): coordinates wrapped on the periodic axes and the int32 lattice shift applied to each point (image flags).

Forcefield

ForceField

A force field: styles and their types. Subclassable; pickles by content. Styles and types are read and written through their handles.

canonical

canonical()

Every style of a form family in its canonical style's category mapped onto that style, exactly (dihedral opls/charmm/rb … → dihedral periodic; bond class2 → bond harmonic; pair lj/class2 → pair lj/cut). Impropers stay. Idempotent.

Raises

molrs.ff.ir.OutOfImageError A row the canonical style cannot hold (charmm w ≠ 0, class2 k3 ≠ 0), naming the type and the condition. molrs.ff.ir.FormConflictError A form family without exactly one canonical style.

def_style

def_style(category, name, params=None)

Define (or return the identical) category style name: an AtomStyle … CmapStyle for the seven categories, a RelationStyle for any other the force-field IR registry declares or this force field already holds.

fit_form

fit_form(
    category, style, q, w=None, *, kt=None, offset=False
)

Every other style of category fitted to style by least squares over the points q of the coordinate (r; θ, φ in radians), weights w, Boltzmann factors at kt, a free constant offset. Returns (forcefield, residual); residual has sum_sq, rms, max_abs and types (per row: style, type, exact, sum_sq, rms, max_abs, offset). sum_sq is monotone in the metric.

get_styles

get_styles(category)

The styles of a category (a name or a style class; Style selects every category), in definition order.

materialize_one_four

materialize_one_four(frame)

Write the 1-4 pairs of frame as per-pair override cells on its pairs block (epsilon/sigma from the 1-4 parameters when lj/charmm declares one_four="epsilon14", the scales from special_bonds); return the number of rows filled.

materialize_params

materialize_params(frame, *, prefix)

Write the parameters this force field gives each row of frame (relation blocks by type; atoms by atoms.type under every atom style and every pair style's self row) as columns <prefix><parameter>, in the force-field IR's units; a parameter a row's type lacks is a null cell. Return block → columns written.

to_form

to_form(category, style)

Every style of category in style's form family converted to style, exactly, through the canonical parameters.

Raises

molrs.ff.ir.NoFormError style has no form codec. molrs.ff.ir.OutOfImageError A row is outside its image (sin(2φ) coefficient … ≠ 0, the constant term …).

Style

Handle of one style of a :class:ForceField; equal handles name the same category and style of one force field.

del_type

del_type(name)

Remove the type name (Style::del_type); the count removed, 0 or 1.

ForceFieldType

Handle of one type of a :class:ForceField; equal handles name the same category, style and type of one force field.

PotentialCompiler

Compiles a ForceField into evaluable kernels.

Owns a copy of the force field taken at construction; later edits to that ForceField do not reach it. compile(frame) binds a typed frame now; defer() returns Potentials that bind the frame they are evaluated on; compile_typed(frame) builds the kernels of a neighbour-driven (MD) evaluation. Both doors price a pair only inside its style's cutoff (r < cutoff, as LAMMPS; ∞ when the style states none).

Frame and Block

Re-exported from the native core — mp.Frame is molrs.core.Frame:

Frame

Dictionary of Blocks with optional box and typed meta — the one Frame.

coords property writable

coords

(N, 3) float64 copy of atoms x / y / z. Raises KeyError without an atoms block or one of the columns.

concat staticmethod

concat(frames)

The frames joined end to end, block by block (:meth:replicate for parts that differ). Relation endpoints of part p are offset by the rows the indexed block has in the parts before it; a column one part lacks is null on its rows; every other column is copied verbatim. meta and the box are the first part's. No part is modified.

Raises

ValueError a relation block indexing a block its part lacks or lacking UInt endpoints; one column under two dtypes.

copy

copy()

Deep copy: blocks (new buffers), box and typed meta.

replicate

replicate(count)

count copies of this frame, concatenated block by block (the inverse of :meth:subset). Relation endpoints of copy c are offset by c times the row count of the block they index; every other column — id / mol_id included — is copied verbatim. Validity masks, meta and the box travel. This frame is never modified.

Raises

ValueError a relation block indexing a missing block or lacking UInt endpoints; a members block.

subset

subset(rows, block='atoms')

A new frame holding the selected rows of block: a 1-D bool mask (True rows, in order) or 1-D int rows (-n_rows <= i wraps). Every relation block indexing block keeps only the rows whose endpoints are all selected, renumbered. Other blocks, the box and meta are copied; values keep their units (Å). This frame is never modified.

Raises

KeyError no block block. IndexError a mask of the wrong length, an index below -n_rows, a selector that is not 1-D. TypeError a selector that is neither bool nor integer. ValueError a row past the end or repeated; a relation block without UInt endpoints; a members block.

Block

Heterogeneous column store (dict of typed numpy arrays) — the one Block.

Columns are dense. A per-row component that only some rows carry is stored with a validity mask beside it, read back with :meth:validity. Every column-key argument accepts a str or a molrs.core.keys.Key. A block read from a frame (frame["atoms"]) is a handle on the stored block.

coords property writable

coords

(n_rows, 3) float64 copy of the x / y / z columns. Raises KeyError if one is missing.

copy

copy()

Deep copy: no buffer shared with this block.

dtype

dtype(key)

The dtype name of a column ("float", "int", "i64", "uint", "bool", "u8", "string", …). KeyError for an absent column.

insert

insert(key, values, validity=None)

Store a column at the given width, optionally with a per-row validity mask (the write side of :meth:validity).

Parameters

key : str | Key Column name. values : numpy.ndarray | Sequence[str] Column data. validity : numpy.ndarray | Sequence[bool] | None 1-D bool mask, one entry per row of values; False marks a row that holds no value. An all-True mask states nothing and is dropped.

Raises

TypeError If the array dtype is unsupported, or validity is neither a 1-D bool array nor a sequence of bools. ValueError If the row count does not match existing columns, or validity does not cover exactly the rows of values.

precision

precision(key)

The declared precision of a column, or None.

Raises

KeyError If key names no column.

rename

rename(old_key, new_key)

Rename in place; a canonical new_key adopts its schema dtype.

set_precision

set_precision(key, precision)

Declare (None: withdraw) the precision of a float64 column.

An absolute tolerance in the column's units. A record writer stores the column rounded to the largest power of two not above it (ties to even), within precision / 2 of the values; memory is untouched. The declaration reads back from *.mrec.

Raises

KeyError If key names no column. ValueError If the column is not float64 or precision is not finite and within [2**-1000, 2**1000].

set_target

set_target(key, target)

Declare (None: withdraw) that a uint64 column holds row indices into target ("<block>" or "/<section>/<block>").

Raises

KeyError If key names no column. ValueError If the column is not uint64 or target is malformed or names a trajectory block.

set_validity

set_validity(key, mask)

Attach a validity mask to an existing column of any dtype.

mask[i] is False where row i holds no value; the mask replaces any the column had, and an all-True mask clears it.

Raises

KeyError If key names no column. TypeError If mask is neither a 1-D bool array nor a sequence of bools. ValueError If mask does not have exactly one entry per row.

stack staticmethod

stack(parts)

Row-wise union of parts under the union of their columns (first-seen order). A column a part lacks is filled with the dtype's default for that part's rows and marked null in its validity mask.

Raises

ValueError If two parts carry one column under different dtypes or per-row shapes.

target

target(key)

The declared target of a column, or None. KeyError for an absent column.

targets

targets()

Every declared target, {column: target}.

validity

validity(key)

The validity mask of a column, or None when it has no holes.

Returns

numpy.ndarray | None A 1-D bool array in row order — True where the cell holds a real value, False where it is a hole — or None when the column carries no mask. None means "every cell is a stated value", not "every cell is a hole".

Raises

KeyError If key names no column of this block — the same answer indexing and :meth:dtype give, so a misspelled key cannot read as a dense column.

Trajectory

Trajectory

An in-memory frame sequence with optional per-frame step / time labels; a slice is the sub-trajectory with its labels.

TrajectorySplitter

TrajectorySplitter(trajectory)

Split a trajectory into sub-trajectories using a strategy.

The resulting segments are :class:Trajectory slices of the original, each with its step / time labels.

Parameters:

Name Type Description Default
trajectory Trajectory

The trajectory to split.

required

split

split(strategy)

Split the trajectory using strategy.

Parameters:

Name Type Description Default
strategy SplitStrategy

The splitting strategy to apply.

required

Returns:

Type Description
list[Trajectory]

A list of :class:Trajectory segments, each a contiguous,

list[Trajectory]

non-empty slice of the original frames. An empty trajectory has

list[Trajectory]

no segments.

Raises:

Type Description
ValueError

If the strategy's indices are not integers rising strictly from 0 to the frame count.

SplitStrategy

Bases: ABC

Abstract base class for trajectory splitting strategies.

Subclasses implement different strategies for dividing a trajectory into segments based on various criteria (frame count, time intervals, etc.).

get_split_indices abstractmethod

get_split_indices(trajectory)

Get split-point indices for dividing the trajectory.

Parameters:

Name Type Description Default
trajectory Trajectory

The trajectory to split.

required

Returns:

Type Description
list[int]

Indices where the trajectory should be split, rising strictly from

list[int]

0 to the total number of frames ([0] for an empty trajectory).

FrameIntervalStrategy

FrameIntervalStrategy(interval)

Bases: SplitStrategy

Split a trajectory at regular frame intervals.

Splits the trajectory every interval frames, creating segments of equal size (except possibly the last).

Parameters:

Name Type Description Default
interval int

Number of frames per segment. Must be positive.

required

TimeIntervalStrategy

TimeIntervalStrategy(interval)

Bases: SplitStrategy

Split a trajectory into fixed-width simulation-time bins.

Bin k holds the frames with t0 + k * interval <= t < t0 + (k + 1) * interval, where t0 is the first frame's time; a segment starts at each frame that enters a new bin, and empty bins produce no segment.

The times are the trajectory's native time array (Trajectory(frames, time=...)) or, when it has none, each frame's meta["time"].

Parameters:

Name Type Description Default
interval float

Time interval for splitting (same units as the times). Must be positive and finite.

required

Raises:

Type Description
ValueError

From :meth:get_split_indices, if a frame has no time or the times decrease or contain non-finite values.

CustomStrategy

CustomStrategy(split_func)

Bases: SplitStrategy

Split a trajectory using a user-provided function.

Parameters:

Name Type Description Default
split_func Callable[[Trajectory], list[int]]

A callable taking a :class:Trajectory and returning a list of split indices, rising strictly from 0 to the total frame count. :meth:TrajectorySplitter.split rejects any other list.

required

Coarse-Grain

CoarseGrain

Coarse-grained molecular graph.

CoarseGrain(**props) — the keywords are :attr:props. Every bead carries a string bead_type. A bead's membership (:meth:set_bead_members) names nodes of one source graph, the member world. Copy with copy.copy / copy.deepcopy. Subclassable.

Script

Script dataclass

Script(name, text, path=None)

An input script: a name, its text and the file it came from.

Attributes:

Name Type Description
name str

Logical name; an engine writes an unpathed script to <name><extension>.

text str

The full text, written as is.

path Path | None

The file it was read from, or None; an engine writes it under this file name.

from_path classmethod

from_path(path)

The script in the file at path, named after its stem.

The text is the file's, unchanged.

Raises:

Type Description
FileNotFoundError

If the file does not exist.

from_text classmethod

from_text(name, text, *, path=None)

A script from a string literal.

The block is dedented and ends in exactly one newline, so an indented triple-quoted string in code becomes a flush-left file.

Parameters:

Name Type Description Default
name str

Logical name of the script.

required
text str

The script text.

required
path str | Path | None

The file name an engine writes it under.

None

preview

preview(max_lines=20)

The first max_lines lines, numbered, and how many more there are.

save

save(path=None)

Write the text to path (default: :attr:path); return where.

Parent directories are created. The script itself is unchanged.

Raises:

Type Description
ValueError

If no path is given and the script has none.

Node and relation handles

NodeRef

Live view of one node: its fields as a mapping — the one door to read (view[key]), write (view[key] = value) and clear (del view[key]) them. Made by the graph, never constructed directly; interned while alive. A write that would break the graph's invariant (an atom's atomic_number, a bead's bead_type) raises ValueError; None is no value (TypeError).

RelationRef

Live view of one relation (a bond, an angle, a port, a term, …): interned endpoint views plus its fields as a mapping, the one door to them. Made by the graph, never constructed directly. bond_type / bond_number are written only by :meth:Atomistic.set_bond_class; a port's fields are fixed when it is added.

Refs

Ordered views of one kind of one graph; refs["x"] is a column. Every door that takes several nodes or relations takes a Refs too.

Selector

MaskPredicate

Bases: ABC

Boolean mask producer combinable with &, |, ~.

The other operand of & / | may be another selector or a molrs region (mp.core.Sphere, …): anything with mask(block).

ColumnSelector

ColumnSelector(value, column=keys.ELEMENT)

Bases: MaskPredicate

Select rows whose column equals value.

The column defaults to :data:molrs.core.keys.ELEMENT; pass another keys constant for another column (keys.TYPE for the string type label, keys.TYPE_ID for the numeric one, keys.RES_NAME, …).

The value must have the column's type: ColumnSelector(1, column=keys.TYPE) on a string type column raises TypeError instead of silently selecting nothing. A missing column raises KeyError. A null cell never matches its stored fill value. Masks are ordinary booleans, so negating a selector includes those unmatched rows.

Parameters:

Name Type Description Default
value _Scalar

The value to match (a string, integer, float or bool scalar).

required
column str | Key

The column to compare, a keys constant or its name.

ELEMENT

AtomIndexSelector

AtomIndexSelector(indices)

Bases: MaskPredicate

Select rows by their 0-based row index.

This is the row position in the block, not the id column (molrs's id is a label, never an index). Calling the selector on a block is block.select_rows(indices); mask marks the same rows.

Parameters:

Name Type Description Default
indices list[int] | ndarray

Non-negative row indices. Duplicates collapse and the selected rows keep the block's order.

required

Raises:

Type Description
TypeError

If indices is not a 1-D sequence of integers.

ValueError

If an index is negative, or (on use) past the block's end.

Region

Region

Composed geometric region (result of &, |, ~ operators).

mask

mask(block)

Which rows of block (its x/y/z) lie inside.

Cuboid

Axis-aligned cuboid (box) region.

A point is inside when origin[d] <= p[d] <= origin[d] + lengths[d] on every axis.

mask

mask(block)

Which rows of block (its x/y/z) lie inside.

Sphere

Solid sphere region.

mask

mask(block)

Which rows of block (its x/y/z) lie inside.

Units

UnitRegistry

define_lj_sigma

define_lj_sigma(sigma)

Define the reduced-LJ length unit lj_sigma alone.

Raises

UnitsError sigma is not a finite positive length, or lj_sigma is already defined.

UnitPreset

names staticmethod

names()

Every registered preset name, sorted (the LAMMPS styles, openmm, and any :meth:register added).

register staticmethod

register(
    name, units, *, boltzmann, coulomb, overwrite=False
)

Register a preset (one unit expression per each of the ten dimensions, plus its two constants) process-wide and return it. Raises ValueError for a missing/unknown dimension or a taken name without overwrite.