How to calculate the number of hydrogen atoms from SMILES string?
SMILES String: C1=CC(=C(C=C1C(CN)O)O)O
The known result is C8H11NO3
Other answers have done a good job of providing a description of the concepts and algorithms needed to answer the question. Here I'll demonstrate the opposite: a black-box empirical approach.
In Python using
from rdkit import Chem from rdkit.Chem import rdMolDescriptors my_smiles_string = 'C1=CC(=C(C=C1C(CN)O)O)O' my_mol = Chem.MolFromSmiles(my_smiles_string) print(rdMolDescriptors.CalcMolFormula(my_mol))
This shows the result
C8H11NO3. You could parse that further to get only the number of hydrogens, if you need to do so. Alternately:
my_mol_with_explicit_h = Chem.AddHs(my_mol) print(my_mol_with_explicit_h.GetNumAtoms() - my_mol_with_explicit_h.GetNumHeavyAtoms())
11. Slightly more cumbersome but it has the output you want. If you take the latter approach you don't even need to import
Information on the system can be found here: https://en.wikipedia.org/wiki/Simplified_molecular-input_line-entry_system http://www.daylight.com/dayhtml/doc/theory/theory.smiles.html
The correct number of hydrogen atoms to fulfill the bond count around the other elements is assumed unless placed in square brackets. The bonds can be read from left to right and assumed to be a chain, unless placed in braces which represent a branch.
So there would be 1H around the first C (going from left to right) this is because it is c1 indicating it's one half of a ring closure so will have an extra bond attached, there is one H on the second C. The third C has a branch and an O (the chain continues after the braces close) which would have a single H attached, the third carbon has no H as the branch is attached via a double bond. (so far we have 3H)
The first C in the branch has no H and attaches to another branch and another O with an H. The first C in the second branch has a single H. The second C in the second branch is important because it has 1 after it like the first C. This indicates that they should have a bond between them forming a ring closure. It continues down the branch which now looks like a substituent on the ring. So it has no H. The third carbon in this branch has an O (with an H) and a new branch, so it has a single H. (So we have 7H so far) The third (and final 'branch' has a C attached to a N and two H, the N has two H attached. which adds 4H making 11H.
The labels in the diagram apply to the carbons in the SMILE string from left to right
You have to convert the SMILES to a graph model. Most everything you want to do with SMILES requires you construct the graph model, i.e., nodes (atoms) and arcs (bonds). Once you have that, you can go through all nodes, and see how many of their sites are occupied by explicit bonds, the rest you protonize.
If you do chemical informatics, you really need to learn these principles and learn to program them yourself.
But taking this obvious solution aside for a moment, with SMILES the question is always: can you simplify the solution so as to work purely text string based? Might you be able to use regular expression replace pattern matching to come up with your solution? And the answer is categorically no! Because regex patterns do not work for nested parenthesis as you use in SMILES to write out branches.
Could you use a parser to do it? May be. But if you go through this effort, you might just as well reconstruct your nodes and arc model, which then you can use to do so much more than to just protonize.