def test_from_rdkit(): """ Make sure we can create a molecule directly from an rdkit object. """ # load a molecule with openff offmol = OFFMolecule.from_file(file_path=get_data("bace0.sdf")) # make a ligand from the openff object mol = Ligand.from_rdkit(rdkit_mol=offmol.to_rdkit()) # make sure we have the same molecule mol2 = Ligand.from_file(get_data("bace0.sdf")) for i in range(mol.n_atoms): atom1 = mol.atoms[i] atom2 = mol2.atoms[i] assert atom1.dict() == atom2.dict() for i in range(mol.n_bonds): bond1 = mol.bonds[i] bon2 = mol2.bonds[i] assert bond1.dict() == bon2.dict() assert np.allclose(mol.coordinates, mol2.coordinates)
def create_force(self, system, topology, **kwargs): """over write the force creation to use qubekit""" # Get the OpenMM Nonbonded force or add if missing existing = [system.getForce(i) for i in range(system.getNumForces())] existing = [f for f in existing if type(f) == self._OPENMMTYPE] # if not present make one and add the particles if len(existing) == 0: force = self._OPENMMTYPE() system.addForce(force) # add all atom particles, Vsites are added later for _ in topology.topology_atoms: force.addParticle(0.0, 1.0, 0.0) else: force = existing[0] # If we're using PME, then the only possible openMM Nonbonded type is LJPME if self.method == "PME": # If we're given a nonperiodic box, we always set NoCutoff. Later we'll add support for CutoffNonPeriodic if topology.box_vectors is None: force.setNonbondedMethod(openmm.NonbondedForce.NoCutoff) # if (topology.box_vectors is None): # raise SMIRNOFFSpecError("If vdW method is PME, a periodic Topology " # "must be provided") else: force.setNonbondedMethod(openmm.NonbondedForce.LJPME) force.setCutoffDistance(self.cutoff) force.setEwaldErrorTolerance(1.0e-4) # If method is cutoff, then we currently support openMM's PME for periodic system and NoCutoff for nonperiodic elif self.method == "cutoff": # If we're given a nonperiodic box, we always set NoCutoff. Later we'll add support for CutoffNonPeriodic if topology.box_vectors is None: force.setNonbondedMethod(openmm.NonbondedForce.NoCutoff) else: force.setNonbondedMethod(openmm.NonbondedForce.PME) force.setUseDispersionCorrection(True) force.setCutoffDistance(self.cutoff) lj = LennardJones612( free_parameters={ "H": h_base(r_free=self.hfree.value_in_unit(unit.angstroms)), "C": c_base(r_free=self.cfree.value_in_unit(unit.angstroms)), "X": h_base(r_free=self.xfree.value_in_unit(unit.angstroms)), "O": o_base(r_free=self.ofree.value_in_unit(unit.angstroms)), "N": n_base(r_free=self.nfree.value_in_unit(unit.angstroms)), "Cl": cl_base(r_free=self.clfree.value_in_unit(unit.angstroms)), "S": s_base(r_free=self.sfree.value_in_unit(unit.angstroms)), "F": f_base(r_free=self.ffree.value_in_unit(unit.angstroms)), "Br": br_base(r_free=self.brfree.value_in_unit(unit.angstroms)), "I": i_base(r_free=self.ifree.value_in_unit(unit.angstroms)), "P": p_base(r_free=self.ifree.value_in_unit(unit.angstroms)), "B": b_base(r_free=self.bfree.value_in_unit(unit.angstroms)), "Si": si_base(r_free=self.sifree.value_in_unit(unit.angstroms)), }, alpha=self.alpha, beta=self.beta, ) water = Molecule.from_smiles("O") for ref_mol in topology.reference_molecules: # skip any waters if ref_mol == water: continue # if the molecule has no conformer generate one if ref_mol.n_conformers == 0: ref_mol.generate_conformers(n_conformers=1) qb_mol = Ligand.from_rdkit(ref_mol.to_rdkit()) for parameter in self.parameters: matches = ref_mol.chemical_environment_matches( parameter.smirks, unique=False ) for match in matches: qb_mol.atoms[match[0]].aim.volume = parameter.volume.value_in_unit( unit.angstroms**3 ) # make sure all atoms in the molecule have volumes, assign dummy values for i in range(qb_mol.n_atoms): atom = qb_mol.atoms[i] assert atom.aim.volume is not None qb_mol.NonbondedForce.create_parameter( atoms=(i,), charge=0, sigma=0, epsilon=0 ) # calculate the nonbonded terms lj.run(qb_mol) # assign to all copies in the system for topology_molecule in topology._reference_molecule_to_topology_molecules[ ref_mol ]: for topology_particle in topology_molecule.atoms: if type(topology_particle) is TopologyAtom: ref_mol_particle_index = ( topology_particle.atom.molecule_particle_index ) elif type(topology_particle) is TopologyVirtualSite: ref_mol_particle_index = ( topology_particle.virtual_site.molecule_particle_index ) else: raise ValueError( f"Particles of type {type(topology_particle)} are not supported" ) topology_particle_index = topology_particle.topology_particle_index particle_parameters = qb_mol.NonbondedForce[ (ref_mol_particle_index,) ] # Set the nonbonded force parameters force.setParticleParameters( topology_particle_index, particle_parameters.charge, # this is a dummy charge which needs to be corrected particle_parameters.sigma, particle_parameters.epsilon, )