Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 7.1.0

### Added
- Use libdx for TRC and file conversion capabilities; conversion to/from SDF, to/from XYZ, and
`perceive_bonds` and `perceive_formal_charges` member functions on TRCS are now available

## 7.0.0

No new changes since 7.0.0rc3.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from pathlib import Path

from rush import RunOpts, exess, prepare
from rush import RunOpts, exess, get_fragments_near_fragment, prepare

# ===== Example 1: Fragment-based interaction energy =====
print("=" * 60)
Expand Down Expand Up @@ -80,7 +80,7 @@

# Step 2: Find ligand fragment index + nearby pocket
lig_idx = trc.residues.seqs.index("MK1")
frag_idcs = trc.topology.get_fragments_near_fragment(lig_idx, 5.0) + [lig_idx]
frag_idcs = get_fragments_near_fragment(trc.topology, lig_idx, 5.0) + [lig_idx]

# Step 3: Run interaction energy

Expand Down
62 changes: 27 additions & 35 deletions examples/exess-qmmm/06_exess_qmmm.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
"""

import json
from itertools import batched
from pathlib import Path

from rush import RunOpts, Topology, exess
import numpy as np

from rush import TRC, RunOpts, Topology, exess
from rush.exess import Trajectory
from rush.mol import Element, Fragment, Residue, Residues
from rush.mol import Element

DATA_DIR = Path(__file__).parent / "data"
OUTPUT_DIR = Path(__file__).parent / "qmmm-outputs"
Expand Down Expand Up @@ -72,7 +73,8 @@
out_traj = res.geometries

# Load topology for atom info
topology = Topology.from_json(topology_path)
with open(topology_path) as f:
topology = Topology.from_dict(json.load(f))
assert topology.fragments, "Topology lost its fragments!"

n_atoms = len(topology.symbols)
Expand Down Expand Up @@ -119,6 +121,10 @@ def geometry_to_xyz(syms, geom, frame_label=""):
return "\n".join(lines)


# NOTE: topology.geometry is an (N,3) numpy array, but out_traj geometries
# from the server are flat lists. geometry_to_xyz handles the flat format.


# Build all frames as XYZ strings
all_frames_xyz = []
for i, geom in enumerate(out_traj):
Expand Down Expand Up @@ -337,38 +343,23 @@ def geometry_to_xyz(syms, geom, frame_label=""):
print("Example 2: Minimal QM/MM (two water molecules)")
print("=" * 60)

topology = Topology(
trc = TRC(
symbols=[Element.O, Element.H, Element.H, Element.O, Element.H, Element.H],
geometry=[
0.0000,
0.0000,
0.0000,
0.7570,
0.5860,
0.0000,
-0.7570,
0.5860,
0.0000,
2.8000,
0.0000,
0.0000,
3.5570,
0.5860,
0.0000,
2.0430,
0.5860,
0.0000,
[0.0000, 0.0000, 0.0000],
[0.7570, 0.5860, 0.0000],
[-0.7570, 0.5860, 0.0000],
[2.8000, 0.0000, 0.0000],
[3.5570, 0.5860, 0.0000],
[2.0430, 0.5860, 0.0000],
],
fragments=[Fragment([0, 1, 2]), Fragment([3, 4, 5])],
)

residues = Residues(
residues=[Residue([0, 1, 2]), Residue([3, 4, 5])],
seqs=["HOH", "HOH"],
fragments=[[0, 1, 2], [3, 4, 5]],
residues=[[0, 1, 2], [3, 4, 5]],
residue_seqs=["HOH", "HOH"],
)

run2 = exess.qmmm(
(topology, residues),
trc,
n_timesteps=100,
trajectory=Trajectory(include_waters=True),
mm_fragments=[],
Expand All @@ -386,10 +377,11 @@ def geometry_to_xyz(syms, geom, frame_label=""):
out_traj = res2.geometries

print("Atoms at First Step")
for atom_x, atom_y, atom_z in batched(topology.geometry, 3):
print(f" x: {atom_x:>7.4f}, y: {atom_y:>7.4f}, z: {atom_z:>7.4f}")
for x, y, z in trc.topology.geometry:
print(f" x: {x:>7.4f}, y: {y:>7.4f}, z: {z:>7.4f}")

topology.geometry = out_traj[-1]
final_geom = np.array(out_traj[-1], dtype=np.float32).reshape(-1, 3)
final_trc = TRC(symbols=list(trc.topology.symbols), geometry=final_geom.tolist())
print("Atoms at Final Step")
for atom_x, atom_y, atom_z in batched(topology.geometry, 3):
print(f" x: {atom_x:>7.4f}, y: {atom_y:>7.4f}, z: {atom_z:>7.4f}")
for x, y, z in final_trc.topology.geometry:
print(f" x: {x:>7.4f}, y: {y:>7.4f}, z: {z:>7.4f}")
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "rush-py"
version = "7.0.0"
version = "7.1.0"
description = "Python client for QDX's Rush platform"
readme = "README.md"
requires-python = ">=3.12"
Expand All @@ -11,6 +11,7 @@ authors = [
dependencies = [
"gql~=4.0",
"h5py~=3.14",
"libqdx~=0.8.0",
"numpy>=1.26,<3",
"rdkit~=2025.9.2",
"matplotlib~=3.10",
Expand Down
40 changes: 19 additions & 21 deletions src/rush/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,24 @@
)
from .mol import (
TRC,
Topology,
Residues,
Chains,
AlphaHelices,
AminoAcidSeq,
AtomRef,
BetaSheets,
Bond,
BondOrder,
Chain,
ChainRef,
Chains,
Element,
FormalCharge,
Fragment,
FragmentRef,
PartialCharge,
Residue,
ResidueId,
HelixClass,
ResidueRef,
Residues,
SchemaVersion,
Topology,
Stereochemistry,
StrandSense,
AtomCheckStrictness,
get_fragments_near_fragment,
)
from .objects import (
ObjectID,
Expand Down Expand Up @@ -87,26 +87,24 @@
"ObjectID",
"TRCPaths",
"TRCRef",
# Core structures
# Core types
"TRC",
"Topology",
"Residues",
"Chains",
# Chemistry types
"Element",
"Bond",
"BondOrder",
"FormalCharge",
"PartialCharge",
"Fragment",
"FragmentRef",
"Stereochemistry",
"HelixClass",
"StrandSense",
"AlphaHelices",
"BetaSheets",
"AtomCheckStrictness",
"AminoAcidSeq",
"SchemaVersion",
# Indices and records
"AtomRef",
"Residue",
"ResidueRef",
"ResidueId",
"Chain",
"ChainRef",
"FragmentRef",
"get_fragments_near_fragment",
]
Loading
Loading