Title: ETH_Sem6 / DC / W02_Cheminformatics

Q: SMILES
A: simplified molecular-input line-entry system

Q: SMARTS
A: SMILES arbitrary target specification

Q: SMIRKS
A: "Perform reactions": Find a group of reactions that undergo the same set of atom and bond changes.

Q: Are SMILES unique representations? If not provide an example!
A: No, they are not unique. For example, CCO, OCC and C(O)C all specify the structure of ethanol.

Q: How do you specify isotopes in SMILES?
A: Use square brackets, eg. [2H] for deuterium.

Q: How do you make a triple bond in SMILES?
A: #: eg. C#N = Hydrogen cyanide

Q: How can you draw cyclic structures with SMILES?
A: Index the atoms that are connected with the same index, eg. C1CCCCC1 = cyclohexane

Q: How do you show disconnected structures in SMILES?
A: With a . (dot) between the atoms, eg. [Na+].[O-]c1ccccc1

Q: Can SMILES specify the stereoisomer?
A: Yes, there is a notation for isomeric SMILES, eg. F/C=C/F for E-1,2-difluoroethene and F/C=C\F for Z-1,2-difluoroethene

Q: Do tautomers have the same SMILES?
A: No they are individual, as the charges locations are specified

Q: Molecular fingerprints?
A: Vector of bits corresponding to structural features and thus encoding the molecule.

Q: Reaction fingerprints?
A: Concatenation, sum or difference of molecular fingerprints. May include agents as well

Q: If two molecular fingerprints [...], then the compounds [...].
A: are similar; should behave similarly

Q: What is a descriptor?
A: - Numerical values representing the properties of a molecule
- Often calculated, but can also be exp.
- Depends on different molecular dimensionality

Q: RDKit descriptors
A: Global molecular descriptors, conveniently calculated and used extensively
from rdkit.Chem import Descriptors
mol = Chem.MolFromSmiles('c1ccccc1')
desc = Descriptors.CalcMolDescriptors(mol)
print(len(desc)) # 210

Q: Descriptor visualization with RDKit
A: from rdkit.Chem.Draw import SimilarityMaps
mol = Chem.MolFromSmiles("Cn1cnc2c1c(=O)n(C)c(=O)n2C")
AllChem.ComputeGasteigerCharges(mol)
contribs = [
  mol.GetAtomWithIdx(i).GetDoubleProp("_GasteigerCharge")
  for i in range(mol.GetNumAtoms())
]
fig = SimilarityMaps.GetSimilarityMapFromWeights(mol, contribs,
size=(500, 500))

Q: Meaning 3D descriptors
A: Depend on the 3D coordinates

Q: Dealing with conformational dependence for descriptors
A: Usually ignore the problem, best (but expensive) approach would be to use Boltzmann averaging

Q: What is a conformer?
A: Stable conformation of a molecule (minimum on PES)

Q: SMILES?
A: C=CCCS

Q: SMILES?
A: structure?
C=CC(S)C

Q: SMILES?
A: structure?
C1CCCCC1

Q: SMILES?
A: structure?
c1ccncc1

Q: SMILES?
A: structure?
c12ccccc1cccn2

Q: How do you visualize a SMILES with rdkit?
A: from rdkit import Chem
smiles = 'CCO'
# Convert the SMILES into an RDKit Mol object
molecule = Chem.MolFromSmiles(smiles)
img = Chem.Draw.MolToImage(molecule)
img.show()

Q: SMARTS for any carboxylic acid
A: *C(=O)O

Q: SMARTS for benzene or pyridine
A: 'c1cc[c,n]cc1'
"," acts as a logical OR

Q: SMARTS for a benzene with one heteroatom substituent
A: 'c1ccccc1[!#6,!#1]'
"!" signals not and #n stands for the atomic number

Q: What do you need to consider when filtering duplicate SMILES?
A: The SMILES are not unique! A way to tackle the problem is to standardize them with rdkit:
from rdkit.Chem.MolStandardize.rdMolStandardize import StandardizeSmiles

Q: How could you quantify the structural similarity between pairs of molecules?
A: We can use the Tanimoto similarity:
from rdkit.Chem import AllChem
from rdkit.DataStructs.cDataStructs import TanimotoSimilarity
df['fingerprint'] = df['molecule'].apply(lambda x: AllChem.GetMorganFingerprintAsBitVect(x, radius=2, nBits=2048))
# Iterate over all pairs of molecules
tanimoto_similarities = []
num_molecules = len(df_filtered)
for i in range(num_molecules):
    for j in range(num_molecules):
        if j > i:
          # Calculate the Tanimoto similarity
          tanimoto_similarity = TanimotoSimilarity(df_filtered.iloc[i]['fingerprint'], df_filtered.iloc[j]['fingerprint'])
          tanimoto_similarities.append(tanimoto_similarity)

Q: What step (computationally intensive) step is necessary to obtain 3D descriptors from SMILES?
A: We need to generate conformers and optimize them to get the 3D representation:
mol = Chem.MolFromSmiles('CHOOCc1ccccc1S')
mol = Chem.AddHs(mol)
# Randomly generate 50 conformers for the molecule
AllChem.EmbedMultipleConfs(mol, numConfs=50)
# Optimise the conformers
AllChem.MMFFOptimizeMoleculeConfs(mol)
# Prune the conformers which are too close from each others (RMSD < 1 Å)
threshold = 1.0
confIds_to_remove = []
# Loop over the conformers two compare them pairwise
for confId_1 in range(mol.GetNumConformers()):
    for confId_2 in range(confId_1 + 1, mol.GetNumConformers()):
        if confId_1 in confIds_to_remove:
            continue
        # Calculate RMSD between the two conformers
        rmsd = AllChem.GetConformerRMS(mol, confId_1, confId_2, prealigned=False)
        if rmsd < threshold:
            confIds_to_remove.append(confId_2)

Q: Steps you could take to ensure that a data point is indeed an outlier (4)
A: - Further data analysis techniques
- Look up database entries and see if the units are the same
- Look up database entries to investigate measurement conditions
- Look up the original papers