def test_map_order_geometry(permute, toolkit, toolkit_name): """Test map ordered geometry""" hooh = { 'symbols': ['H', 'O', 'O', 'H'], 'geometry': [ 1.84719633, 1.47046223, 0.80987166, 1.3126021, -0.13023157, -0.0513322, -1.31320906, 0.13130216, -0.05020593, -1.83756335, -1.48745318, 0.80161212 ], 'name': 'HOOH', 'connectivity': [[0, 1, 1], [1, 2, 1], [2, 3, 1]], } mol = utils.load_molecule(hooh, toolkit=toolkit_name, permute_xyz=permute) mapped_smiles = utils.mol_to_smiles(mol, isomeric=True, explicit_hydrogen=True, mapped=True) atom_map = utils.get_atom_map(mol, mapped_smiles) symbols, geometry = toolkit.get_map_ordered_geometry(mol, atom_map) json_geom = np.asarray(hooh['geometry']).reshape(int(len(geometry) / 3), 3) geometry_array = np.asarray(geometry).reshape(int(len(geometry) / 3), 3) for m in atom_map: for i in range(3): assert json_geom[atom_map[m]][i] == pytest.approx( geometry_array[m - 1][i], 0.0000001) if not permute: assert hooh['geometry'] == pytest.approx(geometry, 0.0000001)
def test_atom_map(smiles): """Test that atom map orders geometry the same way every time no matter the SMILES used to create the molecule""" import cmiles mapped_smiles = '[H:5][C:1]([H:6])([C:2]([H:7])([H:8])[O:4][H:10])[O:3][H:9]' mol_id_oe = cmiles.get_molecule_ids(mapped_smiles, toolkit='openeye') oemol = utils.load_molecule(mapped_smiles, toolkit='openeye') mapped_symbols = ['C', 'C', 'O', 'O', 'H', 'H', 'H', 'H', 'H', 'H'] mapped_geometry = [ -1.6887193912042044, 0.8515190939276903, 0.8344587822904272, -4.05544806361675, -0.3658269566455062, -0.22848169646448416, -1.6111611950422127, 0.4463128276938808, 3.490617694146934, -3.97756355964586, -3.0080934853087373, 0.25948499322223956, -1.6821252026076652, 2.891135395246369, 0.4936556190978574, 0.0, 0.0, 0.0, -4.180315034973438, -0.09210893239246959, -2.2748227320305525, -5.740516456782416, 0.4115539217904015, 0.6823267491485907, -0.07872657410528058, 1.2476492272884379, 4.101615944163073, -5.514569080545831, -3.7195945404657222, -0.4441653010509862 ] mol = cmiles.utils.load_molecule(smiles, toolkit='openeye') if not utils.has_explicit_hydrogen(mol): mol = utils.add_explicit_hydrogen(mol) atom_map = utils.get_atom_map(mol, mapped_smiles=mapped_smiles) # use the atom map to add coordinates to molecule. First reorder mapped geometry to order in molecule mapped_coords = np.array(mapped_geometry, dtype=float).reshape( int(len(mapped_geometry) / 3), 3) coords = np.zeros((mapped_coords.shape)) for m in atom_map: coords[atom_map[m]] = mapped_coords[m - 1] # flatten coords = coords.flatten() # convert to Angstroms coords = coords * utils.BOHR_2_ANGSTROM # set coordinates in oemol mol.SetCoords(coords) mol.SetDimension(3) # Get new atom map atom_map = utils.get_atom_map(mol, mapped_smiles) symbols, geometry = _cmiles_oe.get_map_ordered_geometry(mol, atom_map) assert geometry == mapped_geometry assert symbols == mapped_symbols
def test_atom_map_order(self): """Test atom map""" from openeye import oechem tagged_smiles = '[H:5][C:1]#[N+:4][C:3]([H:9])([H:10])[C:2]([H:6])([H:7])[H:8]' mol_from_tagged_smiles = chemi.smiles_to_oemol(tagged_smiles) atom_map = get_atom_map(mol_from_tagged_smiles, tagged_smiles) # Compare atom map to tag for i in range(1, len(atom_map) + 1): atom_1 = mol_from_tagged_smiles.GetAtom( oechem.OEHasAtomIdx(atom_map[i])) self.assertEqual(i, atom_1.GetMapIdx())
def test_connectivity(mapped_smiles, expected_table, toolkit): """Test connectivity table""" molecule = utils.load_molecule(mapped_smiles, toolkit) atom_map = utils.get_atom_map(molecule, mapped_smiles) connectivity_table = utils.get_connectivity_table(molecule, atom_map) for bond in connectivity_table: xi = np.isin(expected_table, bond[:2]) match = np.where(np.array([i[:2].sum() for i in xi]) == 2)[0] # assert that a match was found and only one was found assert len(match) == 1 # assert that bond order is the same assert expected_table[match][0][-1] == bond[-1]
def test_atom_map(self): """Test get atom map""" from openeye import oechem tagged_smiles = '[H:5][C:1]#[N+:4][C:3]([H:9])([H:10])[C:2]([H:6])([H:7])[H:8]' mol_1 = chemi.smiles_to_oemol('CC[N+]#C') inf = get_fn('ethylmethylidyneamonium.mol2') ifs = oechem.oemolistream(inf) mol_2 = oechem.OEMol() oechem.OEReadMolecule(ifs, mol_2) atom_map = get_atom_map(mol_1, tagged_smiles) for i, mapping in enumerate(atom_map): atom_1 = mol_1.GetAtom(oechem.OEHasAtomIdx(atom_map[mapping])) atom_1.SetAtomicNum(i + 1) atom_2 = mol_2.GetAtom(oechem.OEHasAtomIdx(mapping - 1)) atom_2.SetAtomicNum(i + 1) self.assertEqual(oechem.OECreateCanSmiString(mol_1), oechem.OECreateCanSmiString(mol_2)) # Test aromatic molecule tagged_smiles = '[H:10][c:4]1[c:3]([c:2]([c:1]([c:6]([c:5]1[H:11])[H:12])[C:7]([H:13])([H:14])[H:15])[H:8])[H:9]' mol_1 = chemi.smiles_to_oemol('Cc1ccccc1') inf = get_fn('toluene.mol2') ifs = oechem.oemolistream(inf) mol_2 = oechem.OEMol() oechem.OEReadMolecule(ifs, mol_2) atom_map = get_atom_map(mol_1, tagged_smiles) for i, mapping in enumerate(atom_map): atom_1 = mol_1.GetAtom(oechem.OEHasAtomIdx(atom_map[mapping])) atom_1.SetAtomicNum(i + 1) atom_2 = mol_2.GetAtom(oechem.OEHasAtomIdx(mapping - 1)) atom_2.SetAtomicNum(i + 1) self.assertEqual(oechem.OECreateCanSmiString(mol_1), oechem.OECreateCanSmiString(mol_2))
def test_permute_json(toolkit): """Test permute json xyz, symbols and connectivity to match mapped smiles""" molecule_ids = { 'canonical_smiles': 'OO', 'canonical_isomeric_smiles': 'OO', 'canonical_isomeric_explicit_hydrogen_smiles': '[H]OO[H]', 'canonical_explicit_hydrogen_smiles': '[H]OO[H]', 'canonical_isomeric_explicit_hydrogen_mapped_smiles': '[H:3][O:1][O:2][H:4]', 'unique_protomer_representation': 'OO', 'unique_tautomer_representation': 'OO', 'provenance': 'cmiles_v0.1.1+59.g0b7a12d.dirty_openeye_2018.Oct.b7', 'standard_inchi': 'InChI=1S/H2O2/c1-2/h1-2H', 'inchi_key': 'MHAJPDPJQMAIIY-UHFFFAOYSA-N', 'molecular_formula': 'H2O2' } hooh = { 'symbols': ['H', 'O', 'O', 'H'], 'geometry': [ 1.84719633, 1.47046223, 0.80987166, 1.3126021, -0.13023157, -0.0513322, -1.31320906, 0.13130216, -0.05020593, -1.83756335, -1.48745318, 0.80161212 ], 'name': 'HOOH', 'connectivity': [[0, 1, 1], [1, 2, 1], [2, 3, 1]], 'molecular_multiplicity': 1 } mapped_smiles = molecule_ids[ 'canonical_isomeric_explicit_hydrogen_mapped_smiles'] mol = utils.mol_from_json(hooh, toolkit=toolkit) atom_map = utils.get_atom_map(mol, '[H:3][O:1][O:2][H:4]') permuted_hooh = utils.permute_qcschema(hooh, mapped_smiles, toolkit=toolkit) json_geom = np.asarray(hooh['geometry']).reshape( int(len(hooh['geometry']) / 3), 3) permuted_geom = np.asarray(permuted_hooh['geometry']).reshape( int(len(hooh['geometry']) / 3), 3) assert hooh['geometry'] != permuted_hooh['geometry'] for m in atom_map: for i in range(3): assert json_geom[atom_map[m]][i] == pytest.approx( permuted_geom[m - 1][i], 0.0000001)
def test_mapped_xyz(self): """Test writing out mapped xyz""" from openeye import oechem, oeomega tagged_smiles = '[H:10][c:4]1[c:3]([c:2]([c:1]([c:6]([c:5]1[H:11])[H:12])[C:7]([H:13])([H:14])[H:15])[H:8])[H:9]' mol_1 = chemi.smiles_to_oemol('Cc1ccccc1') inf = get_fn('toluene.mol2') ifs = oechem.oemolistream(inf) mol_2 = oechem.OEMol() oechem.OEReadMolecule(ifs, mol_2) mol_1 = chemi.generate_conformers(mol_1, max_confs=1) atom_map = get_atom_map(mol_1, tagged_smiles) for i, mapping in enumerate(atom_map): atom_1 = mol_1.GetAtom(oechem.OEHasAtomIdx(atom_map[mapping])) atom_1.SetAtomicNum(i + 1) atom_2 = mol_2.GetAtom(oechem.OEHasAtomIdx(mapping - 1)) atom_2.SetAtomicNum(i + 1) xyz_1 = chemi.to_mapped_xyz(mol_1, atom_map, xyz_format=False) # molecule generated from mol2 should be in the right order. atom_map_mol2 = { 1: 0, 2: 1, 3: 2, 4: 3, 5: 4, 6: 5, 7: 6, 8: 7, 9: 8, 10: 9, 11: 10, 12: 11, 13: 12, 14: 13, 15: 14 } xyz_2 = chemi.to_mapped_xyz(mol_2, atom_map_mol2, xyz_format=False) for ele1, ele2 in zip(xyz_1.split('\n')[:-1], xyz_2.split('\n')[:-1]): self.assertEqual(ele1.split(' ')[2], ele2.split(' ')[2])
def test_get_atom_map(toolkit, toolkit_name): smiles = 'C[C@@H](c1c(ccc(c1Cl)F)Cl)OC' mol = utils.load_molecule(smiles, toolkit_name) if toolkit_name == 'openeye': from openeye import oechem oechem.OEAddExplicitHydrogens(mol) for a in mol.GetAtoms(): a.SetMapIdx(a.GetIdx() + 1) mapped_smiles = oechem.OEMolToSmiles(mol) if toolkit_name == 'rdkit': from rdkit import Chem mol = Chem.AddHs(mol) for a in mol.GetAtoms(): a.SetAtomMapNum(a.GetIdx() + 1) mapped_smiles = Chem.MolToSmiles(mol) atom_map = utils.get_atom_map(mol, mapped_smiles) for m in atom_map: assert m == (atom_map[m] + 1)
def generate_constraint_opt_input(qc_molecule, dihedrals, maximum_rotation=30, interval=5, filename=None): """ Parameters ---------- qc_molecule dihedrals Returns ------- QCFractal optimization jobs input """ from openeye import oechem optimization_jobs = {} tagged_smiles = qc_molecule['identifiers']['canonical_isomeric_explicit_hydrogen_mapped_smiles'] mol = oechem.OEMol() oechem.OESmilesToMol(mol, tagged_smiles) atom_map = get_atom_map(mol, tagged_smiles) coords = chemi.from_mapped_xyz_to_mol_idx_order(qc_molecule['geometry'], atom_map) # convert coord to Angstrom coords = coords * utils.BOHR_2_ANGSTROM conf = mol.GetConfs().next() conf.SetCoords(oechem.OEFloatArray(coords)) # new molecule for setting dihedral angles mol_2 = oechem.OEMol(mol) conf_2 = mol_2.GetConfs().next() coords_2 = oechem.OEFloatArray(conf_2.GetMaxAtomIdx()*3) conf.GetCoords(coords_2) mol_2.DeleteConfs() interval = radians(interval) max_rot = radians(maximum_rotation) for dihedral in dihedrals: #j = 0 dih_idx = dihedrals[dihedral] tor = [] for i in dih_idx: a = mol.GetAtom(oechem.OEHasMapIdx(i+1)) tor.append(a) dih_angle = oechem.OEGetTorsion(conf, tor[0], tor[1], tor[2], tor[3]) for i, angle in enumerate(np.arange(dih_angle-max_rot, dih_angle+max_rot, interval)): newconf = mol.NewConf(coords_2) oechem.OESetTorsion(newconf, tor[0], tor[1], tor[2], tor[3], angle) #new_angle = oechem.OEGetTorsion(newconf, tor[0], tor[1], tor[2], tor[3]) # if new_angle == dih_angle: # j += 1 # if j > 1: # # One equivalent angle should be generated. # logger().warning("Openeye did not generate a new conformer for torsion and angle {} {}. Will not generate" # "qcfractal optimizaiton input".format(dih_idx, angle)) # break if filename: pdb = oechem.oemolostream("{}_{}.pdb".format(filename, i)) oechem.OEWritePDBFile(pdb, newconf) symbols, geometry = chemi.to_mapped_geometry(newconf, atom_map) qc_molecule = copy.deepcopy(qc_molecule) qc_molecule['geometry'] = geometry qc_molecule['symbols'] = symbols degree = degrees(angle) optimization_jobs['{}_{}'.format(dih_idx, int(round(degree)))] = { 'type': 'optimization_input', 'initial_molecule': qc_molecule, 'dihedral': dih_idx, 'constraints': { "set": [{ "type": "dihedral", "indices": dih_idx, "value": degree }] } } return optimization_jobs