def stereogenic_atom_keys(gra, assigned=False): """ Find stereogenic atoms in this graph. If the `assigned` flag is set to `False`, only unassigned stereogenic atoms will be detected. :param gra: the graph :param assigned: Include atoms that already have stereo assignments? :param assigned: bool :returns: the stereogenic atom keys :rtype: frozenset """ gra = without_bond_orders(gra) gra = explicit(gra) # for simplicity, add the explicit hydrogens back in atm_keys = dict_.keys_by_value(atom_bond_valences(gra), lambda x: x == 4) if not assigned: # Remove assigned stereo keys atm_keys -= atom_stereo_keys(gra) atm_ngb_keys_dct = atoms_neighbor_atom_keys(gra) def _is_stereogenic(atm_key): atm_ngb_keys = list(atm_ngb_keys_dct[atm_key]) pri_vecs = [ stereo_priority_vector(gra, atm_key, atm_ngb_key) for atm_ngb_key in atm_ngb_keys ] ret = not any(pv1 == pv2 for pv1, pv2 in itertools.combinations(pri_vecs, r=2)) return ret ste_gen_atm_keys = frozenset(filter(_is_stereogenic, atm_keys)) return ste_gen_atm_keys
def stereogenic_bond_keys(gra, assigned=False): """ Find stereogenic bonds in this graph. If the `assigned` flag is set to `False`, only unassigned stereogenic bonds will be detected. :param gra: the graph :param assigned: Include bonds that already have stereo assignments? :param assigned: bool :returns: the stereogenic bond keys :rtype: frozenset """ gra = without_bond_orders(gra) gra = explicit(gra) # for simplicity, add the explicit hydrogens back in # get candidates: planar bonds bnd_keys = sp2_bond_keys(gra) if not assigned: # remove bonds that already have stereo assignments bnd_keys -= bond_stereo_keys(gra) bnd_keys -= functools.reduce( # remove double bonds in small rings frozenset.union, filter(lambda x: len(x) < 8, rings_bond_keys(gra)), frozenset()) atm_ngb_keys_dct = atoms_neighbor_atom_keys(gra) def _is_stereogenic(bnd_key): atm1_key, atm2_key = bnd_key def _is_symmetric_on_bond(atm_key, atm_ngb_key): atm_ngb_keys = list(atm_ngb_keys_dct[atm_key] - {atm_ngb_key}) if not atm_ngb_keys: # C=:O: ret = True elif len(atm_ngb_keys) == 1: # C=N:-X ret = False else: assert len(atm_ngb_keys) == 2 # C=C(-X)-Y ret = (stereo_priority_vector( gra, atm_key, atm_ngb_keys[0]) == stereo_priority_vector( gra, atm_key, atm_ngb_keys[1])) return ret return not (_is_symmetric_on_bond(atm1_key, atm2_key) or _is_symmetric_on_bond(atm2_key, atm1_key)) ste_gen_bnd_keys = frozenset(filter(_is_stereogenic, bnd_keys)) return ste_gen_bnd_keys
def sp2_bond_keys(gra): """ determine the sp2 bonds in this graph """ gra = without_bond_orders(gra) bnd_keys = dict_.keys_by_value(resonance_dominant_bond_orders(gra), lambda x: 2 in x) # make sure both ends are sp^2 (excludes cumulenes) atm_hyb_dct = resonance_dominant_atom_hybridizations(gra) sp2_atm_keys = dict_.keys_by_value(atm_hyb_dct, lambda x: x == 2) bnd_keys = frozenset( {bnd_key for bnd_key in bnd_keys if bnd_key <= sp2_atm_keys}) return bnd_keys
def resonances(rgr): """ all resonance graphs with this connectivity """ return subresonances(without_bond_orders(rgr))