def fake_stereo_geometry(gra, ntries=5, max_dist_err=0.5): """ generate a fake stereo geometry """ # determine stereo "groups" with geometrically interdependent chirality atm_ngbs_dct = atom_neighborhoods(gra) bnd_ngbs_dct = bond_neighborhoods(gra) atm_ste_keys = atom_stereo_keys(gra) bnd_ste_keys = bond_stereo_keys(gra) atm_ste_groups = list( map(atom_keys, map(atm_ngbs_dct.__getitem__, atm_ste_keys))) bnd_ste_groups = list( map(atom_keys, map(bnd_ngbs_dct.__getitem__, bnd_ste_keys))) ste_groups = _aggregate_connected_groups(atm_ste_groups + bnd_ste_groups) ste_groups = list(map(sorted, ste_groups)) natms = 0 geo_idx_dct = {} geo = () for group in ste_groups: group_geo = geometry( gra, keys=group, ntries=ntries, max_dist_err=max_dist_err) group_natms = len(group) idxs = list(range(natms, natms+group_natms)) geo_idx_dct.update(dict(zip(group, idxs))) natms += group_natms geo = geometry_join(geo, group_geo) return geo, geo_idx_dct
def bonds_neighbor_atom_keys(gra): """ keys of neighboring atoms, by bond """ def _neighbor_keys(bnd_key, bnd_nbh): return frozenset(atom_keys(bnd_nbh) - bnd_key) bnd_ngb_keys_dct = dict_.transform_items_to_values(bond_neighborhoods(gra), _neighbor_keys) return bnd_ngb_keys_dct
def bonds_neighbor_bond_keys(gra): """ keys of neighboring bonds, by bond """ def _neighbor_keys(bnd_key, bnd_nbh): bnd_keys = bond_keys(bnd_nbh) bnd_keys -= {bnd_key} bnd_keys = frozenset(key for key in bnd_keys if key & bnd_key) return bnd_keys bnd_ngb_keys_dct = dict_.transform_items_to_values(bond_neighborhoods(gra), _neighbor_keys) return bnd_ngb_keys_dct
def planarity_constraint_bounds(gra, keys): """ bounds for enforcing planarity restrictions """ ngb_key_dct = atoms_neighbor_atom_keys(gra) ngb_dct = bond_neighborhoods(gra) bnd_keys = [bnd_key for bnd_key in sp2_bond_keys(gra) if atom_keys(ngb_dct[bnd_key]) <= set(keys)] def _planarity_constraints(bnd_key): key1, key2 = sorted(bnd_key) key1ab = sorted(ngb_key_dct[key1] - {key2}) key2ab = sorted(ngb_key_dct[key2] - {key1}) lst = [] # I don't think the order of the keys matters, but I tried to be # roughly consistent with Figure 8 in the Blaney Dixon paper if len(key1ab) == 2 and len(key2ab) == 2: lst.append(tuple(map(keys.index, key1ab + key2ab))) if len(key1ab) == 2: lst.append(tuple(map(keys.index, [key1, key2] + key1ab))) if len(key2ab) == 2: lst.append(tuple(map(keys.index, [key1, key2] + key2ab))) if (len(key1ab) == 2 and len(key2ab) == 1) or ( len(key1ab) == 1 and len(key2ab) == 2): lst.append(tuple(map(keys.index, [key1] + key1ab + key2ab))) lst.append(tuple(map(keys.index, [key2] + key1ab + key2ab))) if len(key1ab) == 1 and len(key2ab) == 1: lst.append(tuple(map(keys.index, [key1, key2] + key1ab + key2ab))) return tuple(lst) const_dct = { idxs: (-0.5, +0.5) for idxs in itertools.chain(*map(_planarity_constraints, bnd_keys))} return const_dct