def add_atoms(gra, sym_dct, imp_hyd_vlc_dct=None, ste_par_dct=None): """ add atoms to this molecular graph, setting their keys """ atm_keys = atom_keys(gra) atm_sym_dct = atom_symbols(gra) atm_imp_hyd_vlc_dct = atom_implicit_hydrogen_valences(gra) atm_ste_par_dct = atom_stereo_parities(gra) keys = set(sym_dct.keys()) imp_hyd_vlc_dct = {} if imp_hyd_vlc_dct is None else imp_hyd_vlc_dct ste_par_dct = {} if ste_par_dct is None else ste_par_dct assert not keys & atm_keys assert set(imp_hyd_vlc_dct.keys()) <= keys assert set(ste_par_dct.keys()) <= keys atm_sym_dct.update(sym_dct) atm_imp_hyd_vlc_dct.update(imp_hyd_vlc_dct) atm_ste_par_dct.update(ste_par_dct) atm_dct = _create.atoms_from_data( atom_symbols=atm_sym_dct, atom_implicit_hydrogen_valences=atm_imp_hyd_vlc_dct, atom_stereo_parities=atm_ste_par_dct) bnd_dct = bonds(gra) gra = _create.from_atoms_and_bonds(atoms=atm_dct, bonds=bnd_dct) return gra
def two_bond_idxs(gra, asymb1='H', cent='C', asymb2='H'): """ Determine triplet of idxs for describing bond idxs = (asymb1_idx, cent_idx, asymb2_idx) """ grps = tuple() neigh_dct = atom_neighbor_keys(gra) idx_symb_dct = atom_symbols(gra) symb_idx_dct = atom_symbol_idxs(gra) cent_idxs = symb_idx_dct.get(cent, tuple()) for cent_idx in cent_idxs: neighs = tuple(neigh_dct[cent_idx]) neigh_symbs = atom_idx_to_symb(neighs, idx_symb_dct) if neigh_symbs == (asymb1, asymb2): grp_idxs = (neighs[0], cent_idx, neighs[1]) elif neigh_symbs == (asymb2, asymb1): grp_idxs = (neighs[1], cent_idx, neighs[0]) else: grp_idxs = () if grp_idxs: grps += ((grp_idxs),) return grps
def isomorphic_radical_graphs(gra): """ Generate a set of graphs that are isomorphic to a graph of a radical species """ # Determine useful keys symbols = atom_symbols(gra) unsat_keys = unsaturated_atom_keys(gra) unsat_key = next(iter(unsat_keys)) h_atm_key = max(symbols.keys()) + 1 iso_gras = [] for aidx, symbol in enumerate(symbols.values()): # Loop over saturated (non-radical) heavy atoms if symbol != 'H' and aidx != unsat_key: # Add hydrogen atom to radical atom new_graph = add_atom_explicit_hydrogen_keys( gra, {unsat_key: [h_atm_key]}) # Remove hydrogen from saturated atom neighbors = atom_neighbor_keys(new_graph) for neigh in neighbors[aidx]: if symbols[neigh] == 'H': aneighbor = neigh break new_graph = remove_atoms(new_graph, [aneighbor]) # Test to see if new radical species is the same as the original inv_atm_key_dct = full_isomorphism(gra, new_graph) if inv_atm_key_dct: iso_gras.append(new_graph) return iso_gras
def atom_element_valences(gra): """ element valences (# possible single bonds), by atom """ atm_sym_dct = atom_symbols(gra) atm_group_idx_dct = dict_.transform_values(atm_sym_dct, pt.to_group) atm_elem_vlc_dct = dict_.transform_values(atm_group_idx_dct, VALENCE_DCT.__getitem__) return atm_elem_vlc_dct
def heavy_atom_count(gra, with_dummy=False): """ the number of heavy atoms """ if not with_dummy: gra = without_dummy_atoms(gra) atm_sym_dct = atom_symbols(gra) nhvy_atms = sum(pt.to_Z(sym) != 1 for sym in atm_sym_dct.values()) return nhvy_atms
def atom_lone_pair_counts(gra): """ lone pair counts, by atom """ atm_sym_dct = atom_symbols(gra) atm_group_idx_dct = dict_.transform_values(atm_sym_dct, pt.to_group) atm_lpc_dct = dict_.transform_values(atm_group_idx_dct, LONE_PAIR_COUNTS_DCT.__getitem__) atm_lpc_dct = dict_.transform_values(atm_lpc_dct, int) return atm_lpc_dct
def explicit_hydrogen_keys(gra): """ explicit hydrogen keys (H types: explicit, implicit, backbone) """ hyd_keys = dict_.keys_by_value(atom_symbols(gra), lambda x: x == 'H') atm_ngb_keys_dct = atom_neighbor_keys(gra) def _is_backbone(hyd_key): return all(ngb_key in hyd_keys and hyd_key < ngb_key for ngb_key in atm_ngb_keys_dct[hyd_key]) exp_hyd_keys = frozenset(fmit.filterfalse(_is_backbone, hyd_keys)) return exp_hyd_keys
def neighbors_of_type(gra, aidx, asymb='H'): """ Get the neighbor indices for a certain type """ idx_symb_dct = atom_symbols(gra) neighs = atom_neighbor_keys(gra)[aidx] neigh_symbs = atom_idx_to_symb(neighs, idx_symb_dct) idxs_of_type = tuple() for nidx, nsymb in zip(neighs, neigh_symbs): if nsymb == asymb: idxs_of_type += (nidx,) return idxs_of_type
def from_graph(gra): """ networkx graph object from a molecular graph """ nxg = networkx.Graph() nxg.add_nodes_from(atom_keys(gra)) nxg.add_edges_from(bond_keys(gra)) networkx.set_node_attributes(nxg, atom_symbols(gra), 'symbol') networkx.set_node_attributes(nxg, atom_implicit_hydrogen_valences(gra), 'implicit_hydrogen_valence') networkx.set_node_attributes(nxg, atom_stereo_parities(gra), 'stereo_parity') networkx.set_edge_attributes(nxg, bond_orders(gra), 'order') networkx.set_edge_attributes(nxg, bond_stereo_parities(gra), 'stereo_parity') return nxg
def bonds_of_type(gra, asymb1='C', asymb2='C', mbond=1): """ Determine the indices of all a specific bond specified by atom type and bond order """ # Get the dict that relates atom indices to symbols idx_symb_dct = atom_symbols(gra) # Loop over all the bonds and build a list of ones that match _bonds_of_type = tuple() _bonds = bonds_of_order(gra, mbond=mbond) for bond in _bonds: idx1, idx2 = bond symb1, symb2 = idx_symb_dct[idx1], idx_symb_dct[idx2] if (symb1, symb2) in ((asymb1, asymb2), (asymb2, asymb1)): _bonds_of_type += ((idx1, idx2),) return _bonds_of_type
def without_dummy_atoms(gra): """ remove dummy atoms from the graph """ atm_sym_dct = atom_symbols(gra) atm_keys = [key for key, sym in atm_sym_dct.items() if pt.to_Z(sym)] return subgraph(gra, atm_keys)
def electron_count(gra, charge=0): """ the number of electrons in the molecule """ atm_sym_dct = atom_symbols(explicit(gra)) nelec = sum(map(pt.to_Z, atm_sym_dct.values())) - charge return nelec