def _bond_stereo_corrected_geometry(gra, bnd_ste_par_dct, geo, geo_idx_dct): """ correct the bond stereo parities of a geometry, for a subset of bonds """ bnd_keys = list(bnd_ste_par_dct.keys()) for bnd_key in bnd_keys: par = bnd_ste_par_dct[bnd_key] curr_par = _bond_stereo_parity_from_geometry(gra, bnd_key, geo, geo_idx_dct) if curr_par != par: xyzs = automol.geom.coordinates(geo) atm1_key, atm2_key = bnd_key atm1_xyz = xyzs[geo_idx_dct[atm1_key]] atm2_xyz = xyzs[geo_idx_dct[atm2_key]] rot_axis = numpy.subtract(atm2_xyz, atm1_xyz) rot_atm_keys = atom_keys( branch(gra, atm1_key, {atm1_key, atm2_key})) rot_idxs = list(map(geo_idx_dct.__getitem__, rot_atm_keys)) geo = automol.geom.rotate(geo, rot_axis, numpy.pi, orig_xyz=atm1_xyz, idxs=rot_idxs) assert _bond_stereo_parity_from_geometry(gra, bnd_key, geo, geo_idx_dct) == par gra = set_bond_stereo_parities(gra, {bnd_key: par}) return geo, gra
def remove_bond_stereo_parities(gra, bnd_keys): """ Remove stereo parities for certain bonds :param gra: the graph :param bnd_keys: the keys for which to remove stereo parities :param gra: the resulting graph """ return set_bond_stereo_parities(gra, {k: None for k in bnd_keys})
def _set_bond_stereo_from_geometry(gra, bnd_keys, geo, geo_idx_dct): assert gra == explicit(gra) bnd_pars = [ _bond_stereo_parity_from_geometry(gra, bnd_key, geo, geo_idx_dct) for bnd_key in bnd_keys] gra = set_bond_stereo_parities(gra, dict(zip(bnd_keys, bnd_pars))) return gra
def _expand_bond_stereo(sgr): bnd_ste_keys = stereogenic_bond_keys(sgr) nste_bnds = len(bnd_ste_keys) sgrs = [ set_bond_stereo_parities(sgr, dict(zip(bnd_ste_keys, bnd_ste_par_vals))) for bnd_ste_par_vals in itertools.product(bool_vals, repeat=nste_bnds) ] return sgrs
def to_index_based_stereo(sgr): """ Convert a graph to index-based stereo assignments, where parities are defined relative to the ordering of indices rather than the absolute stereo priority. :param sgr: a graph with absolute stereo assignments :returns: a graph with index-based stereo assignments """ assert sgr == explicit(sgr), ("Not an explicit graph:\n{}".format( string(sgr, one_indexed=False))) abs_srt_keys_dct = atoms_stereo_sorted_neighbor_atom_keys(sgr) atm_ste_keys = atom_stereo_keys(sgr) bnd_ste_keys = bond_stereo_keys(sgr) abs_atm_ste_par_dct = atom_stereo_parities(sgr) abs_bnd_ste_par_dct = bond_stereo_parities(sgr) idx_atm_ste_par_dct = {} idx_bnd_ste_par_dct = {} # Determine index-based stereo assignments for atoms for atm_key in atm_ste_keys: abs_srt_keys = abs_srt_keys_dct[atm_key] idx_srt_keys = sorted(abs_srt_keys) if automol.util.is_even_permutation(idx_srt_keys, abs_srt_keys): idx_atm_ste_par_dct[atm_key] = abs_atm_ste_par_dct[atm_key] else: idx_atm_ste_par_dct[atm_key] = not abs_atm_ste_par_dct[atm_key] # Determine index-based stereo assignments for bonds for bnd_key in bnd_ste_keys: atm1_key, atm2_key = sorted(bnd_key) atm1_abs_srt_keys = abs_srt_keys_dct[atm1_key] atm2_abs_srt_keys = abs_srt_keys_dct[atm2_key] atm1_idx_srt_keys = sorted(atm1_abs_srt_keys) atm2_idx_srt_keys = sorted(atm2_abs_srt_keys) if not ((atm1_idx_srt_keys[0] != atm1_abs_srt_keys[0]) ^ (atm2_idx_srt_keys[0] != atm2_abs_srt_keys[0])): idx_bnd_ste_par_dct[bnd_key] = abs_bnd_ste_par_dct[bnd_key] else: idx_bnd_ste_par_dct[bnd_key] = not abs_bnd_ste_par_dct[bnd_key] sgr = set_atom_stereo_parities(sgr, idx_atm_ste_par_dct) sgr = set_bond_stereo_parities(sgr, idx_bnd_ste_par_dct) return sgr
def from_index_based_stereo(sgr): """ Convert a graph from index-based stereo assignments back to absolute stereo assignments, where parities are independent of atom ordering. :param sgr: a graph with index-based stereo assignments :returns: a graph with absolute stereo assignments """ assert sgr == explicit(sgr), ("Not an explicit graph:\n{}".format( string(sgr, one_indexed=False))) gra = without_stereo_parities(sgr) if has_stereo(sgr): atm_keys_pool = atom_stereo_keys(sgr) bnd_keys_pool = bond_stereo_keys(sgr) idx_atm_ste_par_dct = atom_stereo_parities(sgr) idx_bnd_ste_par_dct = bond_stereo_parities(sgr) atm_ngb_keys_dct = atoms_neighbor_atom_keys(sgr) atm_keys = set() bnd_keys = set() last_gra = None # Do the assignments iteratively to handle higher-order stereo while last_gra != gra: last_gra = gra abs_atm_ste_par_dct = {} abs_bnd_ste_par_dct = {} atm_keys.update(stereogenic_atom_keys(gra) & atm_keys_pool) bnd_keys.update(stereogenic_bond_keys(gra) & bnd_keys_pool) # Determine absolute stereo assignments for atoms for atm_key in atm_keys: abs_srt_keys = atom_stereo_sorted_neighbor_atom_keys( gra, atm_key, atm_ngb_keys_dct[atm_key]) idx_srt_keys = sorted(abs_srt_keys) if automol.util.is_even_permutation(idx_srt_keys, abs_srt_keys): abs_atm_ste_par_dct[atm_key] = ( idx_atm_ste_par_dct[atm_key]) else: abs_atm_ste_par_dct[atm_key] = ( not idx_atm_ste_par_dct[atm_key]) # Determine absolute stereo assignments for bonds for bnd_key in bnd_keys: atm1_key, atm2_key = sorted(bnd_key) atm1_abs_srt_keys = atom_stereo_sorted_neighbor_atom_keys( gra, atm1_key, atm_ngb_keys_dct[atm1_key] - bnd_key) atm2_abs_srt_keys = atom_stereo_sorted_neighbor_atom_keys( gra, atm2_key, atm_ngb_keys_dct[atm2_key] - bnd_key) atm1_idx_srt_keys = sorted(atm1_abs_srt_keys) atm2_idx_srt_keys = sorted(atm2_abs_srt_keys) if not ((atm1_idx_srt_keys[0] != atm1_abs_srt_keys[0]) ^ (atm2_idx_srt_keys[0] != atm2_abs_srt_keys[0])): abs_bnd_ste_par_dct[bnd_key] = ( idx_bnd_ste_par_dct[bnd_key]) else: abs_bnd_ste_par_dct[bnd_key] = ( not idx_bnd_ste_par_dct[bnd_key]) gra = set_atom_stereo_parities(gra, abs_atm_ste_par_dct) gra = set_bond_stereo_parities(gra, abs_bnd_ste_par_dct) atm_ste_keys = atom_stereo_keys(gra) bnd_ste_keys = bond_stereo_keys(gra) assert atm_ste_keys == atm_keys_pool, ( "Index-based to absolute stereo conversion failed:\n" "{} != {}".format(str(atm_ste_keys), str(atm_keys_pool))) assert bnd_ste_keys == bnd_keys_pool, ( "Index-based to absolute stereo conversion failed:\n" "{} != {}".format(str(bnd_ste_keys), str(bnd_keys_pool))) return gra