Beispiel #1
0
def make_mol(struct, verbose=False):
    mol = openbabel.OBMol()
    mol.BeginModify()

    atoms = []
    for xyz, t in zip(struct.xyz, struct.c):
        x, y, z = map(float, xyz)
        ch = struct.channels[t]
        atom = mol.NewAtom()
        atom.SetAtomicNum(ch.atomic_num)
        atom.SetVector(x, y, z)
        atoms.append(atom)

    fixup(atoms, mol, struct)
    connect_the_dots(mol, atoms, struct)
    fixup(atoms, mol, struct)

    mol.PerceiveBondOrders()
    fixup(atoms, mol, struct)

    for (i, a) in enumerate(atoms):
        openbabel.OBAtomAssignTypicalImplicitHydrogens(a)

    fixup(atoms, mol, struct)

    mol.EndModify()

    mol.AddHydrogens()
    fixup(atoms, mol, struct)

    mismatches = 0
    for (a, t) in zip(atoms, struct.c):
        ch = struct.channels[t]
        if 'Donor' in ch.name and not a.IsHbondDonor():
            mismatches += 1
            if verbose:
                print("Not Donor", ch.name, a.GetX(), a.GetY(), a.GetZ())
        if ch.name != 'NitrogenXSDonorAcceptor' and 'Acceptor' in ch.name and not a.IsHbondAcceptorSimple(
        ):
            #there are issues with nitrogens and openbabel protonation..
            mismatches += 1
            if verbose:
                print("Not Acceptor", ch.name, a.GetX(), a.GetY(), a.GetZ())

        if 'Aromatic' in ch.name and not a.IsAromatic():
            mismatches += 1
            if verbose:
                print("Not Aromatic", ch.name, a.GetX(), a.GetY(), a.GetZ())

    mol.DeleteHydrogens()
    return mol, mismatches
Beispiel #2
0
def make_obmol(struct, verbose=False):
    '''Create an OBMol from AtomStruct that attempts to maintain
    correct atom typing'''
    mol = ob.OBMol()
    mol.BeginModify()
    visited_mols = []

    atoms = []
    for xyz, t in zip(struct.xyz, struct.c):
        x, y, z = map(float, xyz)
        ch = struct.channels[t]
        atom = mol.NewAtom()
        atom.SetAtomicNum(ch.atomic_num)
        atom.SetVector(x, y, z)
        atoms.append(atom)

    fixup(atoms, mol, struct)
    visited_mols.append(ob.OBMol(mol))

    connect_the_dots(mol, atoms, struct)
    fixup(atoms, mol, struct)
    visited_mols.append(ob.OBMol(mol))

    mol.EndModify()

    mol.AddPolarHydrogens()  #make implicits explicit
    visited_mols.append(ob.OBMol(mol))

    mol.PerceiveBondOrders()
    fixup(atoms, mol, struct)
    visited_mols.append(ob.OBMol(mol))

    for (i, a) in enumerate(atoms):
        ob.OBAtomAssignTypicalImplicitHydrogens(a)

    fixup(atoms, mol, struct)
    visited_mols.append(ob.OBMol(mol))

    mol.AddHydrogens()
    fixup(atoms, mol, struct)
    visited_mols.append(ob.OBMol(mol))

    #make rings all aromatic if majority of carbons are aromatic
    for ring in ob.OBMolRingIter(mol):
        if 5 <= ring.Size() <= 6:
            carbon_cnt = 0
            aromatic_ccnt = 0
            for ai in ring._path:
                a = mol.GetAtom(ai)
                if a.GetAtomicNum() == 6:
                    carbon_cnt += 1
                    if a.IsAromatic():
                        aromatic_ccnt += 1
            if aromatic_ccnt / carbon_cnt >= .5 and aromatic_ccnt != ring.Size(
            ):
                #set all ring atoms to be aromatic
                for ai in ring._path:
                    a = mol.GetAtom(ai)
                    a.SetAromatic(True)

    #bonds must be marked aromatic for smiles to match
    for bond in ob.OBMolBondIter(mol):
        a1 = bond.GetBeginAtom()
        a2 = bond.GetEndAtom()
        if a1.IsAromatic() and a2.IsAromatic():
            bond.SetAromatic(True)

    visited_mols.append(ob.OBMol(mol))

    mismatches = 0
    for (a, t) in zip(atoms, struct.c):
        ch = struct.channels[t]
        if 'Donor' in ch.name and not a.IsHbondDonor():
            mismatches += 1
            if verbose:
                print("Not Donor", ch.name, a.GetX(), a.GetY(), a.GetZ())
        if ch.name != 'NitrogenXSDonorAcceptor' and 'Acceptor' in ch.name and a.GetExplicitDegree(
        ) != a.GetTotalDegree():
            #there are issues with nitrogens and openbabel protonation..
            mismatches += 1
            if verbose:
                print("Not Acceptor", ch.name, a.GetX(), a.GetY(), a.GetZ())

        if 'Aromatic' in ch.name and not a.IsAromatic():
            mismatches += 1
            if verbose:
                print("Not Aromatic", ch.name, a.GetX(), a.GetY(), a.GetZ())

    return pybel.Molecule(mol), mismatches, visited_mols
Beispiel #3
0
    def fill_rem_valences(self, ob_mol, atoms, struct):
        '''
        Fill empty valences with hydrogens up to the
        amount expected by the atom type, or a typical
        amount according to openbabel, and then fill
        remaining empty valences with higher bond orders.
        '''
        max_vals = get_max_valences(atoms)

        for ob_atom, atom_type in zip(atoms, struct.atom_types):

            if struct.typer.explicit_h:
                # all Hs should already be present
                continue

            max_val = max_vals.get(ob_atom.GetIdx(), 1)

            if Atom.h_count in struct.typer:
                # this should have already been set
                #   by set_min_h_counts, but whatever
                h_count = Atom.h_count(ob_atom)
                if h_count < atom_type.h_count:
                    n = ob_atom.GetImplicitHCount()
                    ob_atom.SetImplicitHCount(n + atom_type.h_count - h_count)

            elif ob_atom.GetExplicitValence() < max_val:
                # this uses explicit valence and formal charge,
                #   and only ever INCREASES hydrogens, since it
                #   never sets implicit H to a negative value
                # but it does overwrite the existing value, so
                #   we need to save it beforehand and then add
                n = ob_atom.GetImplicitHCount()
                ob.OBAtomAssignTypicalImplicitHydrogens(ob_atom)
                n += ob_atom.GetImplicitHCount()
                ob_atom.SetImplicitHCount(n)

        # these have possibly changed
        max_vals = get_max_valences(atoms)

        # now increment bond orders to fill remaining valences
        atom_info = sort_atoms_by_valence(atoms, max_vals)
        for max_val, rem_val, atom in reversed(atom_info):

            if atom.GetExplicitValence() >= max_val:
                continue
            # else, the atom could have an empty valence
            #   so check whether we can augment a bond,
            #   prioritizing bonds that are too short

            bond_info = sort_bonds_by_stretch(ob.OBAtomBondIter(atom))
            for bond_stretch, bond_len, bond in reversed(bond_info):

                if bond.GetBondOrder() >= 3:
                    continue  # don't go above triple

                # do the atoms involved in this bond have empty valences?
                #   since we are modifying the valences in the loop, this
                #   could have changed since calling sort_atoms_by_valence

                a1, a2 = bond.GetBeginAtom(), bond.GetEndAtom()
                min_val_diff = min(  # by how much are the valences under?
                    max_vals.get(a1.GetIdx(), 1) - a1.GetExplicitValence(),
                    max_vals.get(a2.GetIdx(), 1) - a2.GetExplicitValence())
                if min_val_diff > 0:  # increase bond order

                    bond_order = bond.GetBondOrder()  # don't go above triple
                    bond.SetBondOrder(min(bond_order + min_val_diff, 3))

                    # if the current atom now has its preferred valence,
                    #   break and let other atoms choose next bonds to augment
                    if atom.GetExplicitValence() == max_vals[atom.GetIdx()]:
                        break