def string(gra, one_indexed=True): """ write the graph to a string """ if one_indexed: # shift to one-indexing when we print atm_key_dct = {atm_key: atm_key+1 for atm_key in atom_keys(gra)} gra = relabel(gra, atm_key_dct) yaml_atm_dct = atoms(gra) yaml_bnd_dct = bonds(gra) # prepare the atom dictionary yaml_atm_dct = dict(sorted(yaml_atm_dct.items())) yaml_atm_dct = dict_.transform_values( yaml_atm_dct, lambda x: dict(zip(ATM_PROP_NAMES, x))) # perpare the bond dictionary yaml_bnd_dct = dict_.transform_keys( yaml_bnd_dct, lambda x: tuple(sorted(x))) yaml_bnd_dct = dict(sorted(yaml_bnd_dct.items())) yaml_bnd_dct = dict_.transform_keys( yaml_bnd_dct, lambda x: '-'.join(map(str, x))) yaml_bnd_dct = dict_.transform_values( yaml_bnd_dct, lambda x: dict(zip(BND_PROP_NAMES, x))) yaml_gra_dct = {'atoms': yaml_atm_dct, 'bonds': yaml_bnd_dct} gra_str = yaml.dump(yaml_gra_dct, default_flow_style=None, sort_keys=False) return gra_str
def from_atoms_and_bonds(atoms, bonds): """ construct a molecular graph from atom and bond dictionaries format: gra = (atm_dct, bnd_dct) :param atoms: atom dictionary :type atoms: dict :param bonds: bond dictionary :type bonds: dict """ atm_dct = dict(atoms) # print ('bonds test:', bonds) bnd_dct = dict(bonds) atm_sym_dct = dict_.transform_values(atm_dct, lambda x: x[0]) atm_imp_hyd_vlc_dct = dict_.transform_values(atm_dct, lambda x: x[1]) atm_ste_par_dct = dict_.transform_values(atm_dct, lambda x: x[2]) # print('bnd_dct test:', bnd_dct) bnd_ord_dct = dict_.transform_values(bnd_dct, lambda x: x[0]) bnd_ste_par_dct = dict_.transform_values(bnd_dct, lambda x: x[1]) return from_data(atm_sym_dct, bnd_dct.keys(), atom_implicit_hydrogen_valences=atm_imp_hyd_vlc_dct, atom_stereo_parities=atm_ste_par_dct, bond_orders=bnd_ord_dct, bond_stereo_parities=bnd_ste_par_dct)
def atom_element_valences(xgr): """ element valences (# possible single bonds), by atom """ atm_sym_dct = atom_symbols(xgr) 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 atom_lone_pair_counts(xgr): """ lone pair counts, by atom """ atm_sym_dct = atom_symbols(xgr) 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 atom_bond_valences(xgr, bond_order=True): """ bond count (bond valence), by atom """ atm_keys = list(atom_keys(xgr)) xgr = explicit(xgr) if not bond_order: xgr = without_bond_orders(xgr) atm_nbhs = dict_.values_by_key(atom_neighborhoods(xgr), atm_keys) atm_bnd_vlcs = [sum(bond_orders(nbh).values()) for nbh in atm_nbhs] atm_bnd_vlc_dct = dict_.transform_values(dict(zip(atm_keys, atm_bnd_vlcs)), int) return atm_bnd_vlc_dct
def add_atom_implicit_hydrogen_valences(xgr, inc_atm_imp_hyd_vlc_dct): """ add atom imlicit hydrogen valences (increments can be positive or negative) """ atm_keys = list(inc_atm_imp_hyd_vlc_dct.keys()) atm_imp_hyd_vlcs = numpy.add( dict_.values_by_key(atom_implicit_hydrogen_valences(xgr), atm_keys), dict_.values_by_key(inc_atm_imp_hyd_vlc_dct, atm_keys)) assert all(atm_imp_hyd_vlc >= 0 for atm_imp_hyd_vlc in atm_imp_hyd_vlcs) atm_imp_hyd_vlc_dct = dict_.transform_values( dict(zip(atm_keys, atm_imp_hyd_vlcs)), int) return set_atom_implicit_hydrogen_valences(xgr, atm_imp_hyd_vlc_dct)
def implicit(xgr, atm_keys=None): """ make the hydrogens at these atoms implicit """ atm_keys = backbone_keys(xgr) if atm_keys is None else atm_keys atm_exp_hyd_keys_dct = dict_.by_key(atom_explicit_hydrogen_keys(xgr), atm_keys) inc_imp_hyd_keys_dct = dict_.transform_values(atm_exp_hyd_keys_dct, len) xgr = add_atom_implicit_hydrogen_valences(xgr, inc_imp_hyd_keys_dct) exp_hyd_keys = set(itertools.chain(*atm_exp_hyd_keys_dct.values())) xgr = remove_atoms(xgr, exp_hyd_keys) return xgr
def atom_hybridizations(rgr): """ atom hybridizations, by atom """ atm_keys = list(_atom_keys(rgr)) atm_unsat_vlc_dct = _atom_unsaturated_valences(rgr, bond_order=True) atm_bnd_vlc_dct = _atom_bond_valences(rgr, bond_order=False) # note!! atm_unsat_vlcs = numpy.array( dict_.values_by_key(atm_unsat_vlc_dct, atm_keys)) atm_bnd_vlcs = numpy.array(dict_.values_by_key(atm_bnd_vlc_dct, atm_keys)) atm_lpcs = numpy.array( dict_.values_by_key(_atom_lone_pair_counts(rgr), atm_keys)) atm_hybs = atm_unsat_vlcs + atm_bnd_vlcs + atm_lpcs - 1 atm_hyb_dct = dict_.transform_values( dict(zip(atm_keys, atm_hybs)), int) return atm_hyb_dct
def atom_unsaturated_valences(xgr, bond_order=True): """ unsaturated valences, by atom (element valences minus bonding valences -- pi sites and radical electrons) """ atm_keys = list(atom_keys(xgr)) if not bond_order: xgr = without_bond_orders(xgr) atm_bnd_vlcs = dict_.values_by_key(atom_bond_valences(xgr), atm_keys) atm_tot_vlcs = dict_.values_by_key(atom_element_valences(xgr), atm_keys) atm_rad_vlcs = numpy.subtract(atm_tot_vlcs, atm_bnd_vlcs) atm_unsat_vlc_dct = dict_.transform_values( dict(zip(atm_keys, atm_rad_vlcs)), int) return atm_unsat_vlc_dct
def from_string(gra_str): """ read the graph from a string """ yaml_gra_dct = yaml.load(gra_str, Loader=yaml.FullLoader) atm_dct = yaml_gra_dct['atoms'] bnd_dct = yaml_gra_dct['bonds'] atm_dct = dict_.transform_values( atm_dct, lambda x: tuple(map(x.__getitem__, ATM_PROP_NAMES))) bnd_dct = dict_.transform_keys( bnd_dct, lambda x: frozenset(map(int, x.split('-')))) bnd_dct = dict_.transform_values( bnd_dct, lambda x: tuple(map(x.__getitem__, BND_PROP_NAMES))) gra = _create.from_atoms_and_bonds(atm_dct, bnd_dct) # shift back to zero-indexing when we read it in atm_key_dct = {atm_key: atm_key-1 for atm_key in atom_keys(gra)} gra = relabel(gra, atm_key_dct) return gra
def heuristic_geometry(gra): """ stereo-specific coordinates for a molecular geometry (need not be connected) """ assert gra == explicit(gra) gra_iter = iter(connected_components(gra)) gra_ = next(gra_iter) geo_, geo_idx_dct_ = _connected_heuristic_geometry(gra_) geo = geo_ geo_idx_dct = geo_idx_dct_ for gra_ in gra_iter: geo_, geo_idx_dct_ = _connected_heuristic_geometry(gra_) natms = automol.geom.count(geo) geo_idx_dct_ = dict_.transform_values(geo_idx_dct_, (natms).__add__) geo_idx_dct.update(geo_idx_dct_) geo = automol.geom.join(geo, geo_) return geo, geo_idx_dct
def atom_explicit_hydrogen_valences(xgr): """ explicit hydrogen valences, by atom """ return dict_.transform_values(atom_explicit_hydrogen_keys(xgr), len)
def atom_bond_keys(xgr): """ bond keys, by atom """ return dict_.transform_values(atom_neighborhoods(xgr), bond_keys)