def isomorphism(gra1, gra2, backbone_only=False, stereo=True, dummy=True): """ Obtain an isomorphism between two graphs This should eventually replace the other isomorphism functions. :param backbone_only: Compare backbone atoms only? :type backbone_only: bool :param stereo: Consider stereo? :type stereo: bool :param dummy: Consider dummy atoms? :type dummy: bool :returns: The isomorphism mapping `gra1` onto `gra2` :rtype: dict """ if backbone_only: gra1 = implicit(gra1) gra2 = implicit(gra2) if not stereo: gra1 = without_stereo_parities(gra1) gra2 = without_stereo_parities(gra2) if not dummy: gra1 = without_dummy_atoms(gra1) gra2 = without_dummy_atoms(gra2) return _isomorphism(gra1, gra2)
def linear_segments_atom_keys(gra, lin_keys=None): """ atom keys for linear segments in the graph """ ngb_keys_dct = atoms_neighbor_atom_keys(without_dummy_atoms(gra)) lin_keys = (linear_atom_keys(gra, dummy=True) if lin_keys is None else lin_keys) lin_keys = [k for k in lin_keys if len(ngb_keys_dct[k]) <= 2] lin_segs = connected_components(subgraph(gra, lin_keys)) lin_keys_lst = [] for lin_seg in lin_segs: lin_seg_keys = atom_keys(lin_seg) if len(lin_seg_keys) == 1: key, = lin_seg_keys lin_keys_lst.append([key]) else: end_key1, end_key2 = sorted([ key for key, ngb_keys in atoms_neighbor_atom_keys(lin_seg).items() if len(ngb_keys) == 1 ]) ngb_keys_dct = atoms_neighbor_atom_keys(lin_seg) key = None keys = [end_key1] while key != end_key2: key, = ngb_keys_dct[keys[-1]] - set(keys) keys.append(key) lin_keys_lst.append(keys) lin_keys_lst = tuple(map(tuple, lin_keys_lst)) return lin_keys_lst
def rotational_symmetry_number(gra, key1, key2, lin_keys=None): """ get the rotational symmetry number along a given rotational axis :param gra: the graph :param key1: the first atom key :param key2: the second atom key """ ngb_keys_dct = atoms_neighbor_atom_keys(without_dummy_atoms(gra)) imp_hyd_vlc_dct = atom_implicit_hydrogen_valences(implicit(gra)) axis_keys = {key1, key2} # If the keys are part of a linear chain, use the ends of that for the # symmetry number calculation lin_keys_lst = linear_segments_atom_keys(gra, lin_keys=lin_keys) for keys in lin_keys_lst: if key1 in keys or key2 in keys: if len(keys) == 1: key1, key2 = sorted(ngb_keys_dct[keys[0]]) else: key1, = ngb_keys_dct[keys[0]] - {keys[1]} key2, = ngb_keys_dct[keys[-1]] - {keys[-2]} axis_keys |= set(keys) break sym_num = 1 for key in (key1, key2): if key in imp_hyd_vlc_dct: ngb_keys = ngb_keys_dct[key] - axis_keys if len(ngb_keys) == imp_hyd_vlc_dct[key] == 3: sym_num = 3 break return sym_num
def reverse(tsg, dummies=True): """ reverse a transition state graph """ if not dummies: tsg = without_dummy_atoms(tsg) return graph(gra=tsg, frm_bnd_keys=breaking_bond_keys(tsg), brk_bnd_keys=forming_bond_keys(tsg))
def rotational_groups(gra, key1, key2, dummy=False): """ get the rotational groups for a given rotational axis :param gra: the graph :param key1: the first atom key :param key2: the second atom key """ if not dummy: gra = without_dummy_atoms(gra) bnd_key = frozenset({key1, key2}) assert bnd_key in bond_keys(gra) grp1 = branch_atom_keys(gra, key2, bnd_key) - {key1} grp2 = branch_atom_keys(gra, key1, bnd_key) - {key2} grp1 = tuple(sorted(grp1)) grp2 = tuple(sorted(grp2)) return grp1, grp2