-
Notifications
You must be signed in to change notification settings - Fork 100
Description
Describe the bug
When adding a molecule converted from RDKit using OpenFF Toolkit to an OpenMM Modeller, the following error is raised:
AttributeError: 'numpy.ndarray' object has no attribute 'x'
This occurs due to a mismatch in coordinate format returned by t.get_positions()—a NumPy array— instead Vec3
Minimal example
This helper function causes the issue:
def add_molecule_to_modeller(modeller: Modeller, molecule: rdkit.Chem.Mol, resname: str = "FRA") -> None:
resid = modeller.topology.getNumResidues() + 1
mol = Molecule.from_rdkit(molecule)
t = mol.to_topology()
for atom in t.atoms:
atom.metadata["residue_name"] = resname
atom.metadata["residue_number"] = str(resid)
modeller.add(t.to_openmm(), t.get_positions().to_openmm()) # <-- Causes errorDownstream, this triggers an exception when trying to compute bounding box coordinates after using modeller.addSolvent()
for pos in water_positions:
min_coords = Vec3(min(min_coords.x, pos.x), min(min_coords.y, pos.y), min(min_coords.z, pos.z))
max_coords = Vec3(max(max_coords.x, pos.x), max(max_coords.y, pos.y), max(max_coords.z, pos.z))Expected behavior
The to_openmm() call should produce a list of Vec3 positions compatible with Modeller.addSolvent().
Actual behavior
The t.get_positions().to_openmm() call returns a NumPy array, not a list of Vec3, leading to the AttributeError.
Workaround
Manually convert coordinates to Vec3:
from openmm.unit import nanometer, Vec3
def add_molecule_to_modeller(modeller: Modeller, molecule: rdkit.Chem.Mol, resname: str = "FRA") -> None:
"""Converts RDKit molecule to topology and adds it to the modeller."""
resid = modeller.topology.getNumResidues() + 1
mol = Molecule.from_rdkit(molecule)
t = mol.to_topology()
for atom in t.atoms:
atom.metadata["residue_name"] = resname
atom.metadata["residue_number"] = str(resid)
positions = []
for x, y, z in t.get_positions():
x = x.to('nanometer').magnitude
y = y.to('nanometer').magnitude
z = z.to('nanometer').magnitude
positions.append(Vec3(x, y, z) * nanometer)
modeller.add(t.to_openmm(), positions)Computing environment:
openff-toolkit 0.16.9 pyhd8ed1ab_0 conda-forge
openmm 8.2.0 py312haeaa2e4_2 conda-forge