PATTY [Bush et al. J. Inf. Comput. Sci 33 (1993) 756-762]
    TODO: not yet implemented

    1:cation 2:anion 3:donor 4:acceptor
    5:polar 6:hydrophobe 7:others

def assign_type(mol, force_recalc=False):
    """ PATTY [Bush et al. J. Inf. Comput. Sci 33 (1993) 756-762]
    TODO: not yet implemented

    1:cation 2:anion 3:donor 4:acceptor
    5:polar 6:hydrophobe 7:others
    """
    if "PATTY" in mol.descriptors and not force_recalc:
        return
    mol.require("Phys_charge")
    for i, atom in mol.atoms_iter():
        # default is 7 (others)
        nbrcnt = mol.neighbor_count(i)
        if atom.charge > 0 or atom.charge_phys > 0 or \
                atom.charge_conj > 0 and not atom.n_oxide:
            atom.type = 1  # cation
        elif atom.charge < 0 or atom.charge_phys < 0 or \
                atom.charge_conj < 0 and not atom.n_oxide:
            atom.type = 2  # anion
        elif atom.symbol == "N":
            if nbrcnt in (1, 2):
                if atom.pi == 2:
                    atom.type = 3  # donor
                elif atom.pi == 1:
                    atom.type = 4  # acceptor
        elif atom.symbol == "O":
            if nbrcnt == 1 and not atom.pi:
                atom.type = 5  # polar
            else:
                atom.type = 4  # acceptor
        elif atom.symbol in ("C", "Si", "S", "Se", "P", "As"):
            ewg = False
            for n, bond in mol.neighbors(i).items():
                natom = mol.atom(n)
                if natom.symbol in ("N", "O", "S") and atom.pi \
                        and not (natom.pi == 2 and mol.neighbor_count(n) == 3):
                    # the sp2 adjacent to neg (but not conj tert amine) is 7
                    ewg = True
                    break
            if not ewg:
                atom.type = 6  # hydrophobes
        elif atom.symbol in ("F", "Cl", "Br", "I") and nbrcnt == 1:
            atom.type = 6  # typical halogens are hydrophobic
    mol.descriptors.add("PATTY")