def test_get_all_bespoke_smirks():
    """
    Generate bespoke smirks for all parameters in a molecule, make sure they all hit the intended atoms, and every term is now bespoke.
    """
    gen = SmirksGenerator()
    gen.target_smirks = [
        SmirksType.Vdw, SmirksType.Bonds, SmirksType.Angles,
        SmirksType.ProperTorsions
    ]

    mol = Molecule.from_smiles("CO")

    all_bespoke_smirks = gen._get_all_bespoke_smirks(
        molecule=mol,
        forcefield_editor=ForceFieldEditor(
            "openff_unconstrained-1.3.0.offxml"))
    # this is a list of all bespoke smirks with real initial values
    all_matches = []
    for smirk in all_bespoke_smirks:
        atoms = condense_matches(mol.chemical_environment_matches(
            smirk.smirks))
        assert compare_matches(atoms, smirk.atoms) is True
        all_matches.extend(atoms)

    assert all_covered(all_matches, mol) is True
def test_no_smirks_requested():
    """
    Make sure an error is raised if we try and generate smirks but do not request any smirks types.
    """
    gen = SmirksGenerator()
    gen.target_smirks = []

    mol = Molecule.from_smiles("CC")

    with pytest.raises(SMIRKSTypeError):
        gen.generate_smirks(molecule=mol)
def test_generate_smirks(bespoke_smirks):
    """
    Test the main worker method to gather bespoke and non bespoke terms.
    """
    gen = SmirksGenerator()
    gen.target_smirks = [
        SmirksType.Vdw,
    ]
    gen.generate_bespoke_terms = bespoke_smirks

    mol = Molecule.from_smiles("CC")
    smirks_list = gen.generate_smirks(molecule=mol)

    # we only request one parameter type
    types = set([smirk.type for smirk in smirks_list])
    assert len(types) == 1
def test_bespoke_target_torsion_smirks():
    """
    Generate bespoke torsion smirks only for the target torsions and make sure the intended atoms are covered.
    """
    gen = SmirksGenerator()
    mol = Molecule.from_file(get_data("OCCO.sdf"))

    torsion_smirks = gen._get_bespoke_torsion_smirks(molecule=mol,
                                                     central_bonds=[(1, 2)])
    # there should be 3 unique smirks for this molecule
    # H-C-C-H, H-C-C-O, O-C-C-O
    assert len(torsion_smirks) == 3
    for smirk in torsion_smirks:
        atoms = condense_matches(mol.chemical_environment_matches(
            smirk.smirks))
        assert compare_matches(atoms, smirk.atoms) is True
Example #5
0
    def _generate_bespoke_torsions(
        self,
        forcefield: "ForceFieldEditor",
        parent_molecule: off.Molecule,
        task_data: TorsionTask,
    ) -> List[TorsionSmirks]:
        """
        For the given task generate set of bespoke torsion terms for the parent molecule using all layers. Here we have to type the fragment and use the fragment parent mapping
        to transfer the parameters.
        """
        from openff.bespokefit.smirks import SmirksGenerator

        smirks_gen = SmirksGenerator(
            target_smirks=[SmirksType.ProperTorsions],
            layers="all",
            expand_torsion_terms=False,
        )

        fragment = task_data.graph_molecule
        fragment_parent_mapping = task_data.fragment_parent_mapping
        # label the fitting molecule
        labels = forcefield.label_molecule(molecule=fragment)["ProperTorsions"]

        bespoke_torsions = []
        for bond in task_data.central_bonds:
            fragment_dihedrals = smirks_gen.get_all_torsions(bond=bond,
                                                             molecule=fragment)
            for dihedral in fragment_dihedrals:
                # get the smirk that hit this torsion
                off_smirk = labels[dihedral]
                # work out the parent torsion
                parent_torsion = tuple(
                    [fragment_parent_mapping[i] for i in dihedral])
                # make the bespoke smirks
                smirks = smirks_gen._get_new_single_graph_smirks(
                    atoms=parent_torsion, molecule=parent_molecule)
                # make the new Torsion Smirks
                bespoke_smirk = TorsionSmirks(smirks=smirks)
                bespoke_smirk.update_parameters(off_smirk=off_smirk)
                if bespoke_smirk not in bespoke_torsions:
                    bespoke_torsions.append(bespoke_smirk)

        return bespoke_torsions
def test_bespoke_bond_smirks():
    """
    Make sure we can generate a bespoke bond smirks for each bond in a molecule and that every bond is covered.
    """
    gen = SmirksGenerator()
    mol = Molecule.from_smiles("CC")

    bond_smirks = gen._get_bespoke_bond_smirks(molecule=mol)
    # there should be 2 unique bond smirks
    assert len(bond_smirks) == 2
    all_bonds = []
    for smirk in bond_smirks:
        atoms = condense_matches(mol.chemical_environment_matches(
            smirk.smirks))
        all_bonds.extend(atoms)
        assert set(atoms) == smirk.atoms
    # make sure all bonds are covered
    for bond in mol.bonds:
        assert (bond.atom1_index, bond.atom2_index) in all_bonds
Example #7
0
 def _get_smirks_generator(self) -> SmirksGenerator:
     """
     Build a smirks generator from the set of inputs.
     """
     smirks_gen = SmirksGenerator(
         initial_forcefield=self.initial_forcefield,
         generate_bespoke_terms=self.generate_bespoke_terms,
         expand_torsion_terms=self.expand_torsion_terms,
         target_smirks=self.target_smirks,
     )
     return smirks_gen
def test_bespoke_angle_smirks():
    """
    Make sure we can generate a bespoke angle smirks for each angle, also make sure the intended atoms are covered and that every angle has a bespoke smirks.
    """
    gen = SmirksGenerator()
    mol = Molecule.from_smiles("CC")

    angle_smirks = gen._get_bespoke_angle_smirks(molecule=mol)
    # there should be 2 unique smirks
    assert len(angle_smirks) == 2
    all_angles = []
    for smirk in angle_smirks:
        atoms = condense_matches(mol.chemical_environment_matches(
            smirk.smirks))
        all_angles.extend(atoms)
        assert set(atoms) == smirk.atoms
    # make sure all angles are covered
    for angle in mol.angles:
        assert tuple([atom.molecule_atom_index
                      for atom in angle]) in all_angles
def test_bespoke_atom_smirks():
    """
    Make sure we can generate bespoke atom smirks for a molecule and that they cover the correct atoms, also check all atoms have
    a bespoke smirks.
    """
    gen = SmirksGenerator()
    mol = Molecule.from_smiles("C")

    atom_smirks = gen._get_bespoke_atom_smirks(molecule=mol)
    # there should only be 2 unique smirks
    assert len(atom_smirks) == 2
    # make sure the correct atoms are hit
    all_atoms = []
    for smirk in atom_smirks:
        atoms = condense_matches(mol.chemical_environment_matches(
            smirk.smirks))
        all_atoms.extend(atoms)
        assert set(atoms) == smirk.atoms
    # make sure all atoms have a bespoke smirks
    for i in range(mol.n_atoms):
        assert (i, ) in all_atoms
def test_bespoke_torsion_smirks():
    """
    Generate bespoke smirks for every torsion in the molecule, make sure that the intended atoms are covered and make sure every torsion has a bespoke smirks.
    """
    gen = SmirksGenerator()
    mol = Molecule.from_file(get_data("OCCO.sdf"))

    torsion_smirks = gen._get_bespoke_torsion_smirks(molecule=mol)
    # there should be 5 unique torsions
    assert len(torsion_smirks) == 5

    all_torsions = []
    for smirk in torsion_smirks:
        atoms = condense_matches(mol.chemical_environment_matches(
            smirk.smirks))
        all_torsions.extend(atoms)
        assert compare_matches(atoms, smirk.atoms) is True

    for torsion in mol.propers:
        dihedral = tuple([atom.molecule_atom_index for atom in torsion])
        assert dihedral in all_torsions or tuple(
            reversed(dihedral)) in all_torsions
def test_get_all_smirks():
    """
    Get the full list of smirks which cover this molecule from the forcefield, no new smirks should be generated here.
    """
    gen = SmirksGenerator()
    gen.target_smirks = [
        SmirksType.Vdw, SmirksType.Bonds, SmirksType.Angles,
        SmirksType.ProperTorsions
    ]

    mol = Molecule.from_smiles("CO")

    all_smirks = gen._get_all_smirks(molecule=mol,
                                     forcefield_editor=ForceFieldEditor(
                                         "openff_unconstrained-1.3.0.offxml"))
    # this is a list of all of the smirks from the forcefield
    all_matches = []
    for smirk in all_smirks:
        atoms = condense_matches(mol.chemical_environment_matches(
            smirk.smirks))
        assert compare_matches(atoms, smirk.atoms) is True
        all_matches.extend(atoms)

    assert all_covered(all_matches, mol) is True
Example #12
0
    def target_dihedral(self) -> Tuple[int, int, int, int]:
        """
        Return a target dihedral that could be driven for the target central bond.
        """
        from openff.bespokefit.smirks import SmirksGenerator

        dihedrals = SmirksGenerator.get_all_torsions(
            bond=self.fragment_torsion, molecule=self.molecule)
        molecule = self.molecule
        # now find the first dihedral with no hydrogens,
        # if none can be found return any
        for dihedral in dihedrals:
            atoms = [molecule.atoms[i].atomic_number for i in dihedral]
            if 1 not in atoms:
                return dihedral

        return dihedrals[0]
def test_expand_torsion_terms(bespoke_smirks, expand_torsions):
    """
    Make sure torsion terms are expanded up to 4 when requested for bespoke and standard smirks.
    """
    gen = SmirksGenerator()
    gen.target_smirks = [
        SmirksType.ProperTorsions,
    ]
    gen.generate_bespoke_terms = bespoke_smirks
    gen.expand_torsion_terms = expand_torsions

    mol = Molecule.from_smiles("CC")

    smirks_list = gen.generate_smirks(molecule=mol)
    # make sure there is only one parameter type
    types = set([smirk.type for smirk in smirks_list])
    assert len(types) == 1
    for smirk in smirks_list:
        if expand_torsions:
            assert len(smirk.terms) == 4
        else:
            assert len(smirk.terms) < 4