def test_packmol_failed(): from openff.toolkit.topology import Molecule molecules = [Molecule.from_smiles("O")] with pytest.raises(PackmolRuntimeException): packmol.pack_box(molecules, [10], box_size=([0.1] * 3) * unit.angstrom)
def test_packmol_bad_input(): from openff.toolkit.topology import Molecule molecules = [Molecule.from_smiles("O")] with pytest.raises(ValueError): packmol.pack_box(molecules, [10, 20], box_size=([20] * 3) * unit.angstrom)
def test_packmol_ions(): from openff.toolkit.topology import Molecule molecules = [ Molecule.from_smiles("[Na+]"), Molecule.from_smiles("[Cl-]"), Molecule.from_smiles("[K+]"), ] trajectory, _ = packmol.pack_box(molecules, [1, 1, 1], box_size=([20] * 3) * unit.angstrom) assert trajectory is not None assert trajectory.n_chains == 3 assert trajectory.n_residues == 3 assert trajectory.n_atoms == 3 assert trajectory.topology.n_bonds == 0 assert trajectory.top.residue(0).name == "Na+" assert trajectory.top.residue(1).name == "Cl-" assert trajectory.top.residue(2).name == "K+" assert trajectory.top.atom(0).name == "Na+" assert trajectory.top.atom(1).name == "Cl-" assert trajectory.top.atom(2).name == "K+"
def _execute(self, directory, available_resources): molecules, number_of_molecules, exception = self._build_molecule_arrays() packmol_directory = path.join(directory, "packmol_files") # Create packed box trajectory, residue_names = packmol.pack_box( molecules=molecules, number_of_copies=number_of_molecules, structure_to_solvate=self.solute_coordinate_file, center_solute=self.center_solute_in_box, mass_density=self.mass_density, box_aspect_ratio=self.box_aspect_ratio, tolerance=self.tolerance, verbose=self.verbose_packmol, working_directory=packmol_directory, retain_working_files=self.retain_packmol_files, ) if trajectory is None: raise RuntimeError("Packmol failed to complete.") self.assigned_residue_names = dict() for component, residue_name in zip(self.substance, residue_names): self.assigned_residue_names[component.identifier] = residue_name self._save_results(directory, trajectory)
def test_packmol_paracetamol(): from openff.toolkit.topology import Molecule # Test something a bit more tricky than water molecules = [Molecule.from_smiles("CC(=O)NC1=CC=C(C=C1)O")] trajectory, _ = packmol.pack_box(molecules, [1], box_size=([20] * 3) * unit.angstrom) assert trajectory is not None assert trajectory.n_chains == 1 assert trajectory.n_residues == 1 assert trajectory.n_atoms == 20 assert trajectory.topology.n_bonds == 20
def test_amino_acids(): amino_residues = { "C[C@H](N)C(=O)O": "ALA", # Undefined stereochemistry error. # "N=C(N)NCCC[C@H](N)C(=O)O": "ARG", "NC(=O)C[C@H](N)C(=O)O": "ASN", "N[C@@H](CC(=O)O)C(=O)O": "ASP", "N[C@@H](CS)C(=O)O": "CYS", "N[C@@H](CCC(=O)O)C(=O)O": "GLU", "NC(=O)CC[C@H](N)C(=O)O": "GLN", "NCC(=O)O": "GLY", "N[C@@H](Cc1c[nH]cn1)C(=O)O": "HIS", "CC[C@H](C)[C@H](N)C(=O)O": "ILE", "CC(C)C[C@H](N)C(=O)O": "LEU", "NCCCC[C@H](N)C(=O)O": "LYS", "CSCC[C@H](N)C(=O)O": "MET", "N[C@@H](Cc1ccccc1)C(=O)O": "PHE", "O=C(O)[C@@H]1CCCN1": "PRO", "N[C@@H](CO)C(=O)O": "SER", "C[C@@H](O)[C@H](N)C(=O)O": "THR", "N[C@@H](Cc1c[nH]c2ccccc12)C(=O)O": "TRP", "N[C@@H](Cc1ccc(O)cc1)C(=O)O": "TYR", "CC(C)[C@H](N)C(=O)O": "VAL", } smiles = [*amino_residues] from openff.toolkit.topology import Molecule molecules = [Molecule.from_smiles(x) for x in smiles] counts = [1] * len(smiles) trajectory, _ = packmol.pack_box(molecules, counts, box_size=([1000] * 3) * unit.angstrom) assert trajectory is not None assert trajectory.n_chains == len(smiles) assert trajectory.n_residues == len(smiles) for index, smiles in enumerate(smiles): assert trajectory.top.residue(index).name == amino_residues[smiles]
def test_packmol_box_size(): from openff.toolkit.topology import Molecule molecules = [Molecule.from_smiles("O")] trajectory, _ = packmol.pack_box(molecules, [10], box_size=([20] * 3) * unit.angstrom) assert trajectory is not None assert trajectory.n_chains == 1 assert trajectory.n_residues == 10 assert trajectory.n_atoms == 30 assert trajectory.topology.n_bonds == 20 assert all(x.name == "HOH" for x in trajectory.top.residues) assert np.allclose(trajectory.unitcell_lengths, 2.2)
def test_packmol_water(): from openff.toolkit.topology import Molecule molecules = [Molecule.from_smiles("O")] trajectory, _ = packmol.pack_box( molecules, [10], mass_density=1.0 * unit.grams / unit.milliliters, ) assert trajectory is not None assert trajectory.n_chains == 1 assert trajectory.n_residues == 10 assert trajectory.n_atoms == 30 assert trajectory.topology.n_bonds == 20 assert all(x.name == "HOH" for x in trajectory.top.residues)
def compare_condensed_systems(mol, force_field): from openff.evaluator import unit as evaluator_unit from openff.evaluator.utils.packmol import pack_box mass_density = 500 * evaluator_unit.kilogram / evaluator_unit.meter ** 3 trj, assigned_residue_names = pack_box( molecules=[mol], number_of_copies=[100], mass_density=mass_density ) try: openff_top = Topology.from_openmm(trj.top.to_openmm(), unique_molecules=[mol]) except ValueError: print(f"Molecule failed! (conversion from OpenMM)\t{mol.to_inchi()}") return box_vectors = trj.unitcell_vectors[0] * simtk_unit.nanometer openff_top.box_vectors = box_vectors try: toolkit_sys = force_field.create_openmm_system( openff_top, charge_from_molecules=[mol], ) except ( UnassignedBondParameterException, UnassignedAngleParameterException, UnassignedProperTorsionParameterException, ): print(f"Molecule failed! (missing valence parameters)\t{mol.to_inchi()}") return positions = trj.xyz[0] * simtk_unit.nanometer toolkit_energy = _get_openmm_energies( toolkit_sys, box_vectors=box_vectors, positions=positions, ) openff_sys = Interchange.from_smirnoff(force_field=force_field, topology=openff_top) openff_sys.box = box_vectors openff_sys.positions = trj.xyz[0] * unit.nanometer new_sys = openff_sys.to_openmm(combine_nonbonded_forces=True) system_energy = _get_openmm_energies( new_sys, box_vectors=box_vectors, positions=positions, ) # Where energies to not precisely match, inspect all parameters in each force try: toolkit_energy.compare( system_energy, custom_tolerances={ "Bond": 1e-6 * kj_mol, "Angle": 1e-6 * kj_mol, "Torsion": 4e-5 * kj_mol, "Nonbonded": 1e-5 * kj_mol, }, ) except EnergyError as e: if "Torsion" in str(e): _compare_torsion_forces( _get_force(toolkit_sys, openmm.PeriodicTorsionForce), _get_force(new_sys, openmm.PeriodicTorsionForce), ) if "Nonbonded" in str(e): _compare_nonbonded_settings( _get_force(toolkit_sys, openmm.NonbondedForce), _get_force(new_sys, openmm.NonbondedForce), ) _compare_nonbonded_parameters( _get_force(toolkit_sys, openmm.NonbondedForce), _get_force(new_sys, openmm.NonbondedForce), ) if "Bond" in str(e): raise e if "Angle" in str(e): raise e