Tutorial 09

June 15, 2026 · View on GitHub

PathGennie's discovered path is an ideal seed for Transition Path Sampling (TPS) and Transition Interface Sampling (TIS) — an alternative to Weighted Ensemble for kinetics. This tutorial shows the dependency-free seed preparation (runnable now) and the OpenPathSampling (OPS) run (needs pip install -e .[pathsampling] and an OPS engine).

1. Discover a path and prepare the OPS seed (runnable now)

import numpy as np
from pathgennie.core.driver import PathGennieDriver
from pathgennie.core.parallel import SerialExecutor
from pathgennie.core.progress import EscapeMetric
from pathgennie.core.toy import ToyLangevinEngine
from pathgennie.sampling import build_path_ensemble
from pathgennie.sampling.path_sampling import (
    CVRangeState, extract_transition_path, tis_interfaces, prepare_ops_seed,
)

engine = ToyLangevinEngine(dt=0.005, kT=1.0)
initial = engine.create_state((-1.0, -1.4))
y = lambda c: np.array([c[0, 1]])
progress = EscapeMetric(y, start_cv=np.array([-1.4]), escape_metric="cv0")
driver = PathGennieDriver(engine, progress, lambda c: False,
                          executor=SerialExecutor(), sigma=0.3, seed=0, verbosity=0)
traj, metrics = driver.run(initial, tau1=5, tau2=10, max_trial=6, max_cycle=80, save_freq=1)
ens = build_path_ensemble(traj, metrics)

cv = lambda c: c[0, 1]
A = CVRangeState("A", -2.0, -1.0)
B = CVRangeState("B",  1.0,  2.0)

print("reactive A->B sub-path:", extract_transition_path(ens.frames, cv, A, B))
seed = prepare_ops_seed(ens, cv, A, B, interfaces=tis_interfaces(-1.0, 1.0, 6))
print("reactive:", seed["reactive"], " seed frames:", None if seed["seed_frames"] is None else seed["seed_frames"].shape)
print("TIS interfaces:", np.round(seed["interfaces"], 2))

(If the run didn't reach basin B, increase max_cycle or widen the state ranges.)

2. Run TPS / TIS with OpenPathSampling

import openpathsampling as paths
from openpathsampling.engines.openmm import Engine as OPSEngine
from pathgennie.sampling import make_stage

ops_engine = OPSEngine(...)        # build per OPS docs (topology/system/integrator)

# TPS — sample the transition path ensemble
tps = make_stage("tps", cv_fn=cv, state_a=(-2, -1), state_b=(1, 2),
                 ops_engine=ops_engine, n_steps=2000, storage_path="tps.nc")
tps.run(ens, engine=None)

# TIS — rate constant
tis = make_stage("tis", cv_fn=cv, state_a=(-2, -1), state_b=(1, 2),
                 interfaces=list(tis_interfaces(-1.0, 1.0, 6)),
                 ops_engine=ops_engine, n_steps=5000)
result = tis.run(ens, engine=None)
print(result.rate_constants)

OPS propagates with its own engine (ops_engine), not PathGennie's swarm engine. Without openpathsampling installed the stage raises an informative ImportError.

See path-sampling.md for the full reference and the WE-vs-TPS/TIS comparison.