def test_fix_stereo(smiles, fragment_smiles):

    parent_stereo = Fragmenter._find_stereo(smiles_to_molecule(smiles, True))

    fragment = smiles_to_molecule(fragment_smiles, add_atom_map=True)
    fixed = Fragmenter._fix_stereo(fragment, parent_stereo)

    assert Fragmenter._check_stereo(fixed, parent_stereo) is True
def test_check_stereo(smiles, fragment_smiles, output, warning, caplog):

    parent = smiles_to_molecule(smiles, add_atom_map=True)
    fragment = smiles_to_molecule(fragment_smiles, add_atom_map=True)

    parent_stereo = Fragmenter._find_stereo(parent)

    with caplog.at_level(logging.WARNING):
        assert Fragmenter._check_stereo(fragment, parent_stereo) == output

    if warning is None:
        assert len(caplog.records) == 0
    else:
        assert len(caplog.records) == 1
        assert caplog.records[0].message.startswith(warning)
def test_cap_open_valance():

    molecule, _, functional_groups, ring_systems = Fragmenter._prepare_molecule(
        smiles_to_molecule("CNCCc1ccccc1", True), default_functional_groups(),
        False)

    expected_atom = get_map_index(
        molecule,
        molecule.chemical_environment_matches("[#7]-[#6H3:1]")[0][0],
    )

    # noinspection PyTypeChecker
    atoms, bonds = Fragmenter._get_torsion_quartet(
        molecule,
        tuple(
            get_map_index(molecule, i) for i in
            molecule.chemical_environment_matches("[#6a:1]-[#6H2:2]")[0]),
    )
    atoms, bonds = Fragmenter._get_ring_and_fgroups(molecule,
                                                    functional_groups,
                                                    ring_systems, atoms, bonds)

    # Remove the cap atom from the current list to make sure it gets included during
    # capping.
    atoms -= {expected_atom}

    atoms, _ = Fragmenter._cap_open_valence(molecule, functional_groups, atoms,
                                            bonds)

    # Check that carbon bonded to N was added
    assert expected_atom in atoms
def test_get_ring_and_fgroup_ortho(input_smiles, bond_smarts,
                                   expected_pattern):
    """Ensure that FGs and rings attached to ortho groups are correctly
    detected.

    The expected values were generated using fragmenter=0.0.7
    """

    molecule, _, functional_groups, ring_systems = Fragmenter._prepare_molecule(
        smiles_to_molecule(input_smiles, True), default_functional_groups(),
        False)

    bond = tuple(
        get_map_index(molecule, i)
        for i in molecule.chemical_environment_matches(bond_smarts)[0])

    # noinspection PyTypeChecker
    atoms, bonds = Fragmenter._get_torsion_quartet(molecule, bond)
    atoms, bonds = Fragmenter._get_ring_and_fgroups(molecule,
                                                    functional_groups,
                                                    ring_systems, atoms, bonds)

    actual_atoms = {
        map_index
        for map_index in atoms if
        molecule.atoms[get_atom_index(molecule, map_index)].atomic_number != 1
    }
    expected_atoms = {
        get_map_index(molecule, atom_index)
        for match in molecule.chemical_environment_matches(expected_pattern)
        for atom_index in match
    }

    assert actual_atoms == expected_atoms
def test_atom_bond_set_to_mol(abemaciclib):

    molecule = smiles_to_molecule(abemaciclib.to_smiles(mapped=False), True)

    atoms = {
        get_map_index(molecule, atom_index)
        for match in molecule.chemical_environment_matches(
            "[C:1][C:2][N:3]1[C:4][C:5][N:6][C:7][C:8]1")
        for atom_index in match
    }

    bonds = {(
        get_map_index(molecule, bond.atom1_index),
        get_map_index(molecule, bond.atom2_index),
    )
             for bond in molecule.bonds
             if get_map_index(molecule, bond.atom1_index) in atoms
             and get_map_index(molecule, bond.atom2_index) in atoms}

    fragment, _ = Fragmenter._atom_bond_set_to_mol(molecule, {},
                                                   atoms=atoms,
                                                   bonds=bonds)

    for bond in fragment.bonds:

        if bond.atom1.atomic_number == 1 or bond.atom2.atomic_number == 1:
            continue

        map_index_1 = get_map_index(fragment, bond.atom1_index)
        map_index_2 = get_map_index(fragment, bond.atom2_index)

        assert tuple(sorted((map_index_1, map_index_2))) in bonds
def test_find_stereo(smiles, output):

    molecule = smiles_to_molecule(smiles, add_atom_map=True)

    actual_stereo = Fragmenter._find_stereo(molecule)
    expected_stereo = key_smarts_to_map_indices(output, molecule)

    assert actual_stereo == expected_stereo
def test_ring_fgroups(input_smiles, n_output):

    parent = smiles_to_molecule(input_smiles, True)
    parent_groups = Fragmenter._find_functional_groups(
        parent, default_functional_groups())

    parent_rings = Fragmenter._find_ring_systems(parent, parent_groups)

    assert len(parent_rings[1][0]) == n_output
def test_keep_non_rotor(keep_non_rotor_ring_substituents, n_output):

    ring_systems = Fragmenter._find_ring_systems(
        smiles_to_molecule("c1ccccc1C", True),
        {},
        keep_non_rotor_ring_substituents=keep_non_rotor_ring_substituents,
    )

    assert len(ring_systems[1][0]) == n_output
def test_compare_wbo():

    parent = assign_elf10_am1_bond_orders(
        smiles_to_molecule("CCCC", add_atom_map=True))
    rotors_wbo = WBOFragmenter._get_rotor_wbo(
        parent, WBOFragmenter.find_rotatable_bonds(parent, None))

    fragment = smiles_to_molecule("CCCC", add_atom_map=True)

    for bond_tuple, value in rotors_wbo.items():

        assert numpy.isclose(
            WBOFragmenter._compare_wbo(fragment, bond_tuple, value),
            0.0,
            atol=1.0e-6,
        )
        assert numpy.isclose(
            WBOFragmenter._compare_wbo(fragment, bond_tuple, value + 1.0),
            1.0,
            atol=1.0e-6,
        )
def test_get_torsion_quartet(input_smiles, expected_n_atoms, expected_n_bonds):

    molecule = smiles_to_molecule(input_smiles, True)

    bond_match = molecule.chemical_environment_matches("C[C:1][C:2]CCCC")[0]

    atoms, bonds = Fragmenter._get_torsion_quartet(
        molecule,
        (
            get_map_index(molecule, bond_match[0]),
            get_map_index(molecule, bond_match[1]),
        ),
    )

    # This also includes explicit hydrogen
    assert len(atoms) == expected_n_atoms
    assert len(bonds) == expected_n_bonds
def test_build_fragment():

    parent = assign_elf10_am1_bond_orders(smiles_to_molecule("CCCCCC", True))
    rotors_wbo = WBOFragmenter._get_rotor_wbo(
        parent, WBOFragmenter.find_rotatable_bonds(parent, None))

    fragments = {
        bond: WBOFragmenter._build_fragment(parent, {}, {}, {},
                                            bond,
                                            parent_wbo,
                                            threshold=0.05)
        for bond, parent_wbo in rotors_wbo.items()
    }

    assert len(fragments) == 3

    assert (fragments[(3, 5)].to_smiles(explicit_hydrogens=False,
                                        mapped=False) == "CCCCC")
    assert (fragments[(4, 6)].to_smiles(explicit_hydrogens=False,
                                        mapped=False) == "CCCCC")
    assert (fragments[(5, 6)].to_smiles(explicit_hydrogens=False,
                                        mapped=False) == "CCCCCC")
def test_get_rotor_wbo():

    molecule = smiles_to_molecule("CCCC", True)

    for bond in molecule.bonds:
        bond.fractional_bond_order = 0.986

    expected_bonds = {
        (
            get_map_index(molecule, match[0]),
            get_map_index(molecule, match[1]),
        )
        for match in molecule.chemical_environment_matches("[#6:1]-[#6:2]")
    }

    rotors_wbo = WBOFragmenter._get_rotor_wbo(
        molecule, WBOFragmenter.find_rotatable_bonds(molecule, None))

    assert len(rotors_wbo) == 1

    rotor_index = next(iter(rotors_wbo))

    assert rotor_index in expected_bonds
    assert numpy.isclose(rotors_wbo[rotor_index], 0.986, atol=0.001)
def test_get_ring_and_fgroup(input_smiles, bond_smarts, expected):

    molecule, _, functional_groups, ring_systems = Fragmenter._prepare_molecule(
        smiles_to_molecule(input_smiles, True), default_functional_groups(),
        False)

    # noinspection PyTypeChecker
    atoms, bonds = Fragmenter._get_torsion_quartet(
        molecule,
        tuple(
            get_map_index(molecule, i)
            for i in molecule.chemical_environment_matches(bond_smarts)[0]),
    )

    bonds = {tuple(sorted(bond)) for bond in bonds}

    l_atoms = len(atoms)
    l_bonds = len(bonds)

    atoms_2, bonds_2 = Fragmenter._get_ring_and_fgroups(
        molecule, functional_groups, ring_systems, atoms, bonds)

    assert (l_atoms == len(atoms_2)) == expected
    assert (l_bonds == len(bonds_2)) == expected
def test_find_ring_systems(input_smiles, n_ring_systems):

    ring_systems = Fragmenter._find_ring_systems(
        smiles_to_molecule(input_smiles, True), {})

    assert len(ring_systems) == n_ring_systems
Exemple #15
0
def test_smiles_to_molecule(add_atom_map):

    molecule = smiles_to_molecule("CCCC", add_atom_map=add_atom_map)

    assert isinstance(molecule, Molecule)
    assert ("atom_map" in molecule.properties) == add_atom_map